Skip to content

feat: 包装载支持多 App 与包内 Service——第三方应用可自带多个窗口与服务 - #6

Merged
ShiningRay merged 1 commit into
mainfrom
feat/pkg-multi-app-services
Sep 16, 2026
Merged

ShiningRay merged 1 commit into
mainfrom
feat/pkg-multi-app-services

Conversation

@ShiningRay

Copy link
Copy Markdown
Owner

动机

第三方 .emz 包此前只能承载一个 App(AppHost 要求 entry 定义的类 app_id 必须等于包 id),且包内 Service 无人接管、ctx 里没有正式的开窗入口。因此一个真实应用(如 AgentOS 桌面:1 个轮询 Service + 4 个窗口 App)无法独立分发。

本 PR 补齐这三项宿主能力,不含任何具体应用代码。

改动

能力 实现
多 App 包 AppHost#evaluate! 注册 entry 定义的全部 Emerald::App 子类(去掉 app_id == 包 id 硬断言,保留「至少一个新 App 子类」);scan_one 逐个注册,已注册的同 app_id 跳过。reopen/reload 场景经 @package_apps(包 id → 类列表)回查——重开类不触发 inherited
包内 Service Emerald::Service 加子类追踪(inherited + service_subclasses,与 App 同款);AppHost#defined_services 暴露本轮新定义的 Service(含 reopen 回查 @package_services);DesktopShell#register_package_services 注册进 ServiceHub 并幂等 activate_startup,在启动扫描 / install_and_register / on_app_source_saved 三处调用
开窗能力面 ctx[:launch_app] = ->(id, argv = {}) { launch_app(id, **argv) }。包内 App 拉起兄弟窗口的正规入口(此前 ctx[:launcher] 是裸 AppRegistry,launch 只建实例不开窗,宿主只能替换服务对象这种非常规注入——这也是 emerald 侧示例里那个 ShellLauncherBridge 存在的原因)
贡献命令指向窗口 contributes.commands[] 新增可选 app 字段,取值链 cmd[:app] → 该包首个已注册 App → 包 id;包内无可用 App 时跳过并 notify 告警(原先硬接 launch_app(包id),多 App 包会抛「未注册的应用」)
顺带 卸载时 invalidate_cache(清 /System/Cache/<id>.js);.gitignore 补 examples/*.emz

ctx[:launcher] / [:apps] 语义未变(shell_test / about_test 的断言仍成立)。

docs/SPEC-package-format.md §4.1 同步:包 entry 可定义一个或多个 App 子类、可定义 Service 子类、命令可声明 app。

验证

  • 本仓 bundle exec rake test:405 runs, 0 failures;rake compile 通过
  • 新增测试:pkg_apphost_test(多 App 注册、defined_services、扫描重置、失败包不贡献 Service、reopen 回查)、shell_e7_test(多 App .emz 安装、启动期 Service 注册+激活、幂等、launch_app argv 透传、卸载清缓存)
  • 变异检验:逐一回退 invalidate_cache / register_package_services 调用 / reopen 回查 / defined_services 重置,各自触发对应测试失败(非空断言)
  • 真实包端到端:把 AgentOS 包(1 Service + 4 App,包 id ≠ 任何 app_id)打成 .emz 装入 DesktopShell → 四 App 注册、LinkService 进 hub 且 activated?、launch_app(:agentos_agent, endpoint: 'agent-1') 开窗、卸载清缓存 —— 全通过

配套

应用侧独立仓库:agentos-desk(源码、打包器、测试、CI)。本 PR 与它配套;本仓不再持有该包源码。

让第三方 .emz 包能成为一个完整应用(而非只能一个 App),这是 AgentOS 桌面
包独立分发的前置能力:

- AppHost#evaluate! 放宽为注册 entry 定义的**全部** Emerald::App 子类(去掉
  app_id 必须等于包 id 的硬断言,保留「至少一个新 App 子类」);reopen/reload
  场景经包 id → 类列表的内存映射回查(重开类不触发 inherited)
- Emerald::Service 加子类追踪(inherited + service_subclasses,照 App 写法);
  AppHost 暴露 defined_services(本轮 scan/reload 新定义的 Service 子类,
  含 reopen 回查),DesktopShell 新增 register_package_services:注册进
  ServiceHub 并幂等 activate_startup;启动扫描与 install_and_register、
  on_app_source_saved 三处调用
- 新增能力面 ctx[:launch_app](->(id, argv = {}) { launch_app(id, **argv) }):
  包内 App 拉起兄弟窗口的正规入口(此前 ctx 里只有裸 AppRegistry,
  launch 只建实例不开窗)
- 贡献命令可指向包内窗口:contributes.commands[] 新增可选 app 字段,
  取值链 cmd[:app] → 该包首个已注册 App → 包 id;无可用 App 时跳过并告警
- 卸载时清编译缓存(invalidate_cache),examples/*.emz 进 .gitignore
- SPEC §4.1 同步:多 App / 包内 Service / 命令 app 字段
@ShiningRay
ShiningRay merged commit acf9640 into main Sep 16, 2026
5 checks passed
@ShiningRay
ShiningRay deleted the feat/pkg-multi-app-services branch September 16, 2026 16:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant