OpenProgram Docs

从新标签页打开应用#

侧栏 Applications(应用) 页面支持从本地目录安装软件、查看来源和版本、打开、启停、隐藏启动按钮、从原来源更新,以及保留数据卸载。安装 Python 后端需要明确勾选信任。更新会填写安装表单,请审查来源后再提交。Tools、Workflows 和 harness 程序包仍在 能力 页面管理。

顶层 openprogram apps 命令管理软件;原 openprogram programs apps 命令继续兼容。软件注册保存到 ~/.openprogram/applications/catalog.json,不再与 Program 来源混存。已有记录在首次访问时迁移,保留版本、启停与隐藏设置、卸载记录和实例数据;发生冲突时停止迁移,不覆盖任何一份记录。

安装后的应用会与文件、新建对话、浏览器、终端一起出现在新标签页。点击名称打开应用自己的界面,再次打开会选中同一个实例。关闭标签页不会取消后台操作。

应用界面使用标准 HTML、CSS 和 JavaScript,也可以提供 Python 业务操作。界面不必使用 OpenProgram 组件。前端依赖需要打包到本地,资源和 JavaScript 模块导入使用相对路径。应用运行在独立 opaque origin 的 sandbox iframe 中,不能读取宿主页面、直接调用宿主 API、加载远程脚本、嵌套其他页面或提交导航表单。资源 URL 只授权读取该应用版本的 UI 目录,不是宿主凭据。

安装与打开#

在本地 OpenProgram worker 运行时执行:

openprogram apps install /absolute/path/to/application
openprogram apps list

Python 后端以当前操作系统用户执行受信代码。检查源码和依赖后,使用 --trust 授权运行:

openprogram apps install /absolute/path/to/application --trust

新标签页获得焦点时和每十秒刷新应用列表。项目级应用在打开时绑定当前选中的项目,之后切换对话项目不会改变已经打开的实例。没有当前项目时会复用唯一的已有绑定;首次使用或有多个绑定时提供项目选择,也可以选择新文件夹。全局应用使用当前 owner 的同一个实例;不同项目的实例独立保存业务数据。

仓库包含计算器、论文阅读器和文件分析样例。阅读器只在点击生成摘要时调用配置的模型,保存笔记不需要模型。

应用定义与接口#

包根目录中的 application.json 定义稳定 id、title、version、scope(global 或 project)、dataSchema、ui、可选 backend 和 operations。完整 JSON 示例见英文版。ui.root 相对包根目录,ui.entry 相对 UI 目录。Python 和私有配置应放在 UI 目录之外。

Python 后端的 module:object 入口导出操作字典。操作接收 (input, context),同步或异步返回 JSON 值;输入输出使用 JSON Schema 校验。声明 agent: true 的操作可以由 Program 客户端调用。backend.dependencies 使用精确固定版本,例如 package-name==1.2.3。每个内容版本有自己的 Python 环境,同时使用已安装宿主框架及其依赖。安装时在独立进程中检查后端;列出应用不会导入代码。

支持的宿主能力是 storage.app、model.invoke、files.project.read。这些声明限制宿主 bridge,不限制受信 Python 代码的操作系统权限。

页面使用 window.openprogramApp:

  • load() 返回 {value, version},save(value, version) 只在版本仍匹配时保存,并发写入冲突后需要重新读取。
  • run(operation, input, requestKey) 返回持久任务记录。重试相同请求时复用 request key,不同输入复用同一个 key 会被拒绝。
  • runs() 列出最近任务;status(id, after) 返回状态、结果、错误、待回答问题和指定序号之后的事件。
  • cancel(id) 取消任务;answer(id, requestId, answer) 回答当前问题。bridge 不能操作其他实例的任务。

Python 操作使用 context.load()、context.save(value, expected_version=...)、context.progress(value)、context.ask(question) 和 context.read_file(relative_path)。读取项目文件需要声明能力并绑定项目。声明模型能力的操作可直接使用现有 llm()、agent() 和 ambient Runtime,模型凭据留在后端。应用提问使用 context.ask();要求预声明持久等待点的 Runtime 工作流交互仍保留原有要求。

Program 调用同一套操作:

from openprogram.programs.application_client import run, status
job = run("local.notes", "summarize", {"text": "..."}, request_key="summary-1")
print(status(job["id"]))

CLI 对应 programs apps run APP OPERATION --input JSON,项目级应用增加 --project ID;查看和取消使用 programs apps status RUN_ID、programs apps cancel RUN_ID。

数据与生命周期#

安装会复制代码并固定内容版本。修改源目录不改变已安装版本,使用 install --replace 更新;Python 应用还需要 --trust。已有任务继续使用旧代码,新版本激活后需要重新打开旧页面才能提交新操作。

业务数据与代码、对话分开保存,每个实例使用自己的 SQLite 状态,JSON 值上限为 4 MiB,单个事件上限为 1 MiB。执行状态使用现有 execution store;模型调用记录通过现有 session-node writer 保存到应用运行目录。

worker 停止会中断未完成的 Python 函数,重启后显示中断状态,不会自动恢复任意 Python 调用栈。应用应逐步保存进度,用户查看中断情况后明确启动另一次操作。当前版本拒绝改变数据 schema 或 scope 的升级,不提供自动迁移。

openprogram apps uninstall APP 移除菜单入口并取消活动操作,保留业务数据、旧代码及 schema/scope 兼容身份。重新安装兼容包可以恢复数据,不兼容的重新安装会在激活前被拒绝。owner API 的 PATCH /api/applications/{id} 支持 enabled、hidden、display_title;隐藏不取消任务,停用会取消。

独立部署、非 Python 后端、MCP Apps 兼容以及原生操作系统 GUI 窗口嵌入尚未实现。

项目应用在启动操作和读取项目文件前,根据绑定的项目 ID 重新确认当前位置。移动项目不改变应用实例和已保存数据;位置缺失、被其他目录替代或尚未确认时,拒绝启动新操作,已保存的应用数据仍可读取。

将应用作为资源使用#

已启用应用自动出现在 resource(action="describe") 中,名称为 application.<id>。安装、禁用、更新和卸载无需重启 worker 即生效。项目级应用的 open 接受 project_id,并将实例关联调用会话。observe 返回实例数据与最近执行;act 接受清单中 Agent 可见的操作及稳定的 request_key。使用 open 返回的 instance_id 与 digest,更新应用后旧 digest 会被拒绝。

status、cancel、answer 只处理属于该实例的执行。声明 storage.app 后,save 要求预期的数据版本。release 只移除会话关联,保留实例、数据和正在执行的操作;隐藏视图也不停止操作。Resources 和顶部标签复用同一实例及现有 sandbox 应用 frame,无需另外编写前端适配器。

通过 framework 工具 调用 POST /api/applications/scaffold,传入 path、app_id、title 可生成可运行的示例包。父目录必须存在,目标目录不能已存在。包中分别放置 backend/operations.py、ui/index.html 和 application.json,界面与 Agent 都调用声明的 read/save 操作。审查源码后,通过 /api/applications/install 传入源路径及 trust: true 安装。增加功能时同步扩展后端和操作清单,不要仅在前端事件中实现业务修改。

Last updated · 2026-10-10