create-windy 0.3.19 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/README.md +28 -13
  2. package/dist/cli.js +783 -280
  3. package/package.json +1 -1
  4. package/template/.agents/skills/windy-business-module/SKILL.md +34 -10
  5. package/template/.windy-template.json +2 -2
  6. package/template/AGENTS.md +18 -8
  7. package/template/README.md +32 -22
  8. package/template/apps/server/Dockerfile +1 -0
  9. package/template/apps/server/package.json +1 -0
  10. package/template/apps/server/scripts/validate-module-composition-once.ts +4 -0
  11. package/template/apps/server/scripts/validate-module-composition.ts +28 -0
  12. package/template/apps/server/src/agent/data-scope-routes.test.ts +20 -5
  13. package/template/apps/server/src/agent/routes.test.ts +20 -7
  14. package/template/apps/server/src/agent/routes.ts +14 -0
  15. package/template/apps/server/src/agent/runtime-bootstrap.ts +22 -6
  16. package/template/apps/server/src/agent/sandbox-worker.ts +2 -2
  17. package/template/apps/server/src/agent/unavailable-routes.ts +33 -0
  18. package/template/apps/server/src/app/server-composition.ts +56 -0
  19. package/template/apps/server/src/application-services.ts +2 -0
  20. package/template/apps/server/src/bulk-data/service.ts +14 -0
  21. package/template/apps/server/src/data-governance/export/authorization-port.ts +1 -1
  22. package/template/apps/server/src/data-governance/export/postgres-api-fixture.ts +18 -2
  23. package/template/apps/server/src/data-governance/export/postgres-recovery.integration.test.ts +10 -9
  24. package/template/apps/server/src/data-governance/export/routes-test-fixture.ts +6 -8
  25. package/template/apps/server/src/data-governance/user-plaintext-routes.test.ts +4 -2
  26. package/template/apps/server/src/feature/routes.authorization.test.ts +26 -1
  27. package/template/apps/server/src/feature/routes.ts +33 -15
  28. package/template/apps/server/src/foundation-activation.test.ts +60 -0
  29. package/template/apps/server/src/foundation.ts +64 -5
  30. package/template/apps/server/src/guards.test.ts +23 -0
  31. package/template/apps/server/src/guards.ts +12 -0
  32. package/template/apps/server/src/index.ts +28 -34
  33. package/template/apps/server/src/installed-business-modules.ts +13 -24
  34. package/template/apps/server/src/jobs/legacy-adapter.integration.test.ts +1 -0
  35. package/template/apps/server/src/jobs/legacy-adapter.test.ts +106 -0
  36. package/template/apps/server/src/jobs/legacy-service-runtime.ts +40 -0
  37. package/template/apps/server/src/license/activation.test.ts +30 -0
  38. package/template/apps/server/src/license/activation.ts +26 -0
  39. package/template/apps/server/src/license/restriction.test.ts +16 -0
  40. package/template/apps/server/src/license/routes-offline-code.test.ts +6 -2
  41. package/template/apps/server/src/license/routes.ts +20 -4
  42. package/template/apps/server/src/license/runtime-service.test.ts +10 -2
  43. package/template/apps/server/src/module-bootstrap.ts +14 -23
  44. package/template/apps/server/src/module-composition.test.ts +43 -2
  45. package/template/apps/server/src/module-composition.ts +29 -0
  46. package/template/apps/server/src/module-host/durable-context-guard.test.ts +172 -0
  47. package/template/apps/server/src/module-host/durable-context-unavailable.test.ts +50 -1
  48. package/template/apps/server/src/module-host/durable-context.test.ts +42 -25
  49. package/template/apps/server/src/module-host/durable-context.ts +42 -2
  50. package/template/apps/server/src/module-host/durable-handler-registration.ts +96 -5
  51. package/template/apps/server/src/module-host/implementation-completeness.test.ts +185 -0
  52. package/template/apps/server/src/module-host/implementation-completeness.ts +132 -0
  53. package/template/apps/server/src/module-host/initialize-contracts.ts +14 -0
  54. package/template/apps/server/src/module-host/initialize.test.ts +78 -2
  55. package/template/apps/server/src/module-host/initialize.ts +15 -4
  56. package/template/apps/server/src/module-host/project-attachments.test.ts +92 -0
  57. package/template/apps/server/src/module-host/project-attachments.ts +58 -0
  58. package/template/apps/server/src/module-host/project-composition-package.test.ts +186 -0
  59. package/template/apps/server/src/module-host/project-composition.test.ts +260 -0
  60. package/template/apps/server/src/module-host/project-composition.ts +311 -0
  61. package/template/apps/server/src/module-host/request-context.ts +3 -0
  62. package/template/apps/server/src/module-host/route-declaration.ts +15 -6
  63. package/template/apps/server/src/module-host/route-installer.test.ts +15 -2
  64. package/template/apps/server/src/module-host/route-installer.ts +12 -2
  65. package/template/apps/server/src/module-host/route-registration.test.ts +13 -4
  66. package/template/apps/server/src/module-host/runtime-composition-compatibility.test.ts +63 -0
  67. package/template/apps/server/src/module-host/runtime-composition-compatibility.ts +46 -0
  68. package/template/apps/server/src/module-host/runtime-composition.ts +34 -0
  69. package/template/apps/server/src/module-host/search-provider-registration.test.ts +64 -0
  70. package/template/apps/server/src/module-host/search-provider-registration.ts +35 -0
  71. package/template/apps/server/src/module-host/static-route-authorization.test.ts +99 -0
  72. package/template/apps/server/src/module-host/static-route-authorization.ts +90 -0
  73. package/template/apps/server/src/module-host/task-definitions.ts +1 -0
  74. package/template/apps/server/src/module-host/user-directory-composition.test.ts +4 -1
  75. package/template/apps/server/src/module-host.test.ts +2 -0
  76. package/template/apps/server/src/module-preflight.test.ts +289 -0
  77. package/template/apps/server/src/module-preflight.ts +96 -0
  78. package/template/apps/server/src/module-runtime-validation.ts +1 -0
  79. package/template/apps/server/src/platform-app-bootstrap.ts +50 -0
  80. package/template/apps/server/src/platform-http-runtime.ts +32 -7
  81. package/template/apps/server/src/route-guards.test.ts +22 -0
  82. package/template/apps/server/src/route-guards.ts +10 -3
  83. package/template/apps/server/src/runtime-audit-query.ts +50 -0
  84. package/template/apps/server/src/runtime-feature.test.ts +46 -0
  85. package/template/apps/server/src/runtime-feature.ts +5 -0
  86. package/template/apps/server/src/runtime.ts +10 -49
  87. package/template/apps/server/src/scheduler/audit-action.test.ts +49 -0
  88. package/template/apps/server/src/scheduler/audit.ts +1 -1
  89. package/template/apps/server/src/scheduler/execution-recorder.ts +10 -5
  90. package/template/apps/server/src/scheduler/recovery-service.test.ts +4 -3
  91. package/template/apps/server/src/scheduler/service-idle.test.ts +4 -3
  92. package/template/apps/server/src/scheduler/service.test.ts +1 -0
  93. package/template/apps/server/src/scheduler/service.ts +18 -21
  94. package/template/apps/server/src/scheduler/types.ts +5 -1
  95. package/template/apps/server/src/startup-composition-validation.test.ts +35 -0
  96. package/template/apps/server/src/startup-composition-validation.ts +54 -0
  97. package/template/apps/server/src/startup-preflight.test.ts +36 -0
  98. package/template/apps/server/src/startup-preflight.ts +37 -0
  99. package/template/apps/server/src/system/audit-routes.test.ts +9 -3
  100. package/template/apps/server/src/system/department-routes.test.ts +5 -3
  101. package/template/apps/server/src/system/feature-routes.test.ts +4 -3
  102. package/template/apps/server/src/system/interface-catalog.test.ts +5 -3
  103. package/template/apps/server/src/system/interface-catalog.ts +3 -0
  104. package/template/apps/server/src/system/menu-routes.test.ts +5 -3
  105. package/template/apps/server/src/system/route-test-runtime.ts +24 -0
  106. package/template/apps/server/src/system/routes-validation.test.ts +7 -3
  107. package/template/apps/server/src/system/routes.test.ts +21 -11
  108. package/template/apps/server/src/system/routes.ts +11 -2
  109. package/template/apps/server/src/work-order/foundation-modules.test.ts +6 -4
  110. package/template/apps/server/src/work-order/routes.test.ts +8 -0
  111. package/template/apps/server/src/work-order/task.test.ts +6 -1
  112. package/template/apps/web/Dockerfile +5 -0
  113. package/template/apps/web/package.json +1 -0
  114. package/template/apps/web/scripts/validate-admin-ui-composition.ts +106 -0
  115. package/template/apps/web/src/app/web-composition.ts +24 -0
  116. package/template/apps/web/src/app/web-composition.webtest.ts +15 -0
  117. package/template/apps/web/src/layout/AppSidebar.vue +8 -1
  118. package/template/apps/web/src/layout/NavigationSearchDialog.vue +8 -1
  119. package/template/apps/web/src/layout/navigation.ts +29 -4
  120. package/template/apps/web/src/layout/navigation.webtest.ts +51 -0
  121. package/template/apps/web/src/pages/dashboard/dashboard-presenter.ts +6 -1
  122. package/template/apps/web/src/pages/work-orders/WorkOrderListPage.vue +202 -0
  123. package/template/apps/web/src/pages/work-orders/WorkOrderListPage.webtest.ts +51 -0
  124. package/template/apps/web/src/router/admin-extension-loader.ts +44 -0
  125. package/template/apps/web/src/router/admin-extension-loader.webtest.ts +49 -0
  126. package/template/apps/web/src/router/admin-ui-composition-plugin.ts +33 -0
  127. package/template/apps/web/src/router/admin-ui-composition-plugin.webtest.ts +20 -0
  128. package/template/apps/web/src/router/admin-ui-composition.ts +313 -0
  129. package/template/apps/web/src/router/admin-ui-composition.webtest.ts +225 -0
  130. package/template/apps/web/src/router/admin-ui-module-registry-plugin.ts +55 -0
  131. package/template/apps/web/src/router/admin-ui-module-registry-plugin.webtest.ts +46 -0
  132. package/template/apps/web/src/router/business-routes.ts +32 -45
  133. package/template/apps/web/src/router/business-routes.webtest.ts +40 -44
  134. package/template/apps/web/src/router/index.ts +64 -54
  135. package/template/apps/web/src/router/manifest-routes.ts +27 -7
  136. package/template/apps/web/src/router/manifest-routes.webtest.ts +10 -2
  137. package/template/apps/web/src/router/platform-admin-route-bindings.ts +58 -0
  138. package/template/apps/web/src/router/reserved-route-paths.ts +14 -0
  139. package/template/apps/web/src/router/shared-scaffold-neutrality.webtest.ts +10 -4
  140. package/template/apps/web/src/router/web-composition-host.ts +20 -0
  141. package/template/apps/web/src/services/work-order-api.ts +16 -0
  142. package/template/apps/web/src/services/work-order-api.webtest.ts +21 -0
  143. package/template/apps/web/src/virtual-admin-ui-modules.d.ts +5 -0
  144. package/template/apps/web/vite.config.ts +22 -1
  145. package/template/docs/architecture/migration-bundle.md +10 -7
  146. package/template/docs/architecture/module-manifest-composition.md +85 -3
  147. package/template/docs/architecture/search-provider-protocol.md +6 -1
  148. package/template/docs/architecture/server-module-interface.md +70 -7
  149. package/template/docs/development/business-web-routes.md +53 -50
  150. package/template/docs/development/module-lifecycle.md +48 -54
  151. package/template/docs/platform/navigation-registry.md +5 -4
  152. package/template/package.json +1 -1
  153. package/template/packages/config/package.json +1 -1
  154. package/template/packages/database/package.json +1 -1
  155. package/template/packages/example-work-order/package.json +6 -0
  156. package/template/packages/example-work-order/src/admin-page.ts +78 -0
  157. package/template/packages/example-work-order/src/admin.ts +35 -0
  158. package/template/packages/example-work-order/src/manifest.test.ts +62 -5
  159. package/template/packages/example-work-order/src/manifest.ts +54 -7
  160. package/template/packages/example-work-order/src/migration-bundle.ts +8 -0
  161. package/template/packages/example-work-order/src/server-module.ts +2 -2
  162. package/template/packages/jobs/package.json +1 -1
  163. package/template/packages/modules/index.ts +4 -0
  164. package/template/packages/modules/package.json +3 -2
  165. package/template/packages/modules/src/admin-ui-entry.ts +8 -0
  166. package/template/packages/modules/src/admin-ui-manifest.test.ts +52 -0
  167. package/template/packages/modules/src/admin-ui-manifest.ts +53 -0
  168. package/template/packages/modules/src/capability-audit-validation.test.ts +127 -0
  169. package/template/packages/modules/src/capability-audit-validation.ts +38 -0
  170. package/template/packages/modules/src/capability-guard-validation.ts +148 -0
  171. package/template/packages/modules/src/capability-key-validation.test.ts +150 -0
  172. package/template/packages/modules/src/composition-fixtures.test-support.ts +7 -5
  173. package/template/packages/modules/src/composition.test.ts +74 -9
  174. package/template/packages/modules/src/composition.ts +8 -0
  175. package/template/packages/modules/src/manifest.ts +1 -0
  176. package/template/packages/modules/src/migration-bundle-validation.test.ts +23 -0
  177. package/template/packages/modules/src/module-host-range.test.ts +57 -0
  178. package/template/packages/modules/src/module-host-range.ts +125 -0
  179. package/template/packages/modules/src/project-module-assembly.test.ts +133 -0
  180. package/template/packages/modules/src/project-module-assembly.ts +126 -0
  181. package/template/packages/modules/src/system-admin-routes.ts +6 -5
  182. package/template/packages/modules/src/system-admin-ui-catalog.ts +72 -0
  183. package/template/packages/modules/src/system-agent-tools.ts +2 -2
  184. package/template/packages/modules/src/system-api-binding.ts +43 -9
  185. package/template/packages/modules/src/system-api-control-plane.ts +202 -0
  186. package/template/packages/modules/src/system-api-data-governance.ts +4 -2
  187. package/template/packages/modules/src/system-api-operational.ts +57 -8
  188. package/template/packages/modules/src/system-api-permissions.ts +115 -21
  189. package/template/packages/modules/src/system-api-watermark.ts +3 -0
  190. package/template/packages/modules/src/system-audit-actions.ts +7 -0
  191. package/template/packages/modules/src/system-data-governance.ts +5 -2
  192. package/template/packages/modules/src/system-features.ts +31 -0
  193. package/template/packages/modules/src/system-governed-export-bindings.ts +8 -4
  194. package/template/packages/modules/src/system-module-catalog.test.ts +39 -4
  195. package/template/packages/modules/src/system-module-catalog.ts +68 -7
  196. package/template/packages/modules/src/system-module-tasks.ts +8 -1
  197. package/template/packages/modules/src/system-modules-access.test.ts +4 -0
  198. package/template/packages/modules/src/system-modules.test.ts +10 -2
  199. package/template/packages/modules/src/system-modules.ts +6 -5
  200. package/template/packages/modules/src/system-permissions.ts +4 -0
  201. package/template/packages/modules/user/module.ts +19 -2
  202. package/template/packages/server-sdk/index.ts +8 -0
  203. package/template/packages/server-sdk/package.json +2 -1
  204. package/template/packages/server-sdk/src/durable-handler.ts +16 -1
  205. package/template/packages/server-sdk/src/module-adapter.test.ts +44 -0
  206. package/template/packages/server-sdk/src/module-adapter.ts +59 -0
  207. package/template/packages/server-sdk/src/route-definition.ts +3 -2
  208. package/template/packages/shared/package.json +1 -1
  209. package/template/packages/shared/src/audit.test.ts +7 -0
  210. package/template/packages/shared/src/audit.ts +16 -0
  211. package/template/packages/shared/src/migration-bundle-validation.ts +9 -11
  212. package/template/packages/shared/src/rbac.ts +2 -0
  213. package/template/apps/web/src/app/business-routes.ts +0 -22
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-windy",
3
- "version": "0.3.19",
3
+ "version": "0.4.0",
4
4
  "description": "创建单组织、单租户、私有部署优先的 Windy 企业 Dashboard Starter",
5
5
  "type": "module",
6
6
  "bin": {
@@ -10,51 +10,75 @@ description: "Windy 业务模块、Manifest、Repository、Service、Agent Tool
10
10
 
11
11
  ## 工作流
12
12
 
13
- 1. 选择一个稳定的能力基础 Key 和模块命名空间。先定义业务边界、Actor、数据归属与
13
+ 1. 先运行 `windy module list` 读取项目实际装配;安装、启用、停用、升级或移除模块时,
14
+ 先执行对应命令的 `--dry-run`,再处理兼容范围、依赖、配置、权限与 Migration 提示。
15
+ 不直接修改 `node_modules`、`.windy` 升级元数据,也不为新增入口改写客户 Admin
16
+ layout。当前 CLI 对无法安全自动改变的 source/template 模块会 fail closed;按报告
17
+ 修改 project-owned Composition,不能伪造安装成功。
18
+ 2. 选择一个稳定的能力基础 Key 和模块命名空间。先定义业务边界、Actor、数据归属与
14
19
  失败语义,再改代码。
15
- 2. 在业务 package 的 Module Manifest 一次性注册 Feature、Permission、API、
20
+ 3. 在业务 package 的 Module Manifest 一次性注册 Feature、Permission、API、
16
21
  菜单/入口、审计动作,以及需要的 Task、Provider、JSON Schema 和 Tool。
17
- 3. 数据层使用 Drizzle Schema、前向 Migration 和 Repository;Service 持有业务规则,
22
+ Feature 直接使用能力基础 Key,Permission 在同一 Key 后追加动作;Route、Task、
23
+ Tool、Provider 与 Durable Handler 只能绑定这里已注册且基础 Key 一致的能力。
24
+ 4. 数据层使用 Drizzle Schema、前向 Migration 和 Repository;Service 持有业务规则,
18
25
  其它模块只能通过 Service、公开 Port 或模块注册机制协作。
19
- 4. Server 通过 `InstallableServerModule` 和 `ModuleHost` 注册 Guarded Route、Task、
26
+ 5. Server 通过 `InstallableServerModule` 和 `ModuleHost` 注册 Guarded Route、Task、
20
27
  Provider 或 Tool Handler。Handler 调用 Service,不直接访问其它模块 Repository。
21
28
  需要选择启用用户时使用 `ModuleRequestContext.userDirectory`;不要导入用户 Admin
22
29
  Repository。业务 RolePreset 不能注册平台 Permission,部署管理员须显式向业务角色
23
30
  授予 `system.user-directory.read` 并配置数据范围。
24
- 5. Tool 输入输出只使用 Manifest 已注册的顶层 object JSON Schema。Actor、Permission、
31
+ 6. Tool 输入输出只使用 Manifest 已注册的顶层 object JSON Schema。Actor、Permission、
25
32
  Feature、License 和 Data Scope 只来自 `ModuleToolContext` 与平台 Runtime。
26
33
  Tool 或 Route 需要读取同业务范围内其他用户上传的文件时,在 Host 注册精确
27
34
  `purpose + resourceType` 的 `registerResourceFileAccessPolicies()`;Resolver 必须用
28
35
  project-owned Repository 回查资源与 fileId 绑定及对象级授权,只返回布尔判定,
29
36
  再通过 `context.storage.openResourceFile()` 取得最小元数据与流。禁止注入
30
37
  UploadRepository、BlobStore 或申请平台 manage Repository。
31
- 6. 业务资源包含敏感字段时,在 Manifest 一次声明 Data Policy、standard read、
38
+ 7. 业务资源包含敏感字段时,在 Manifest 一次声明 Data Policy、standard read、
32
39
  sensitive-disclosure reveal、governed-export Permission 与 masked/reveal API 绑定,
33
40
  再用 `registerGovernedResources()` 分别注册对象授权 Resolver 和去除治理字段的投影。
34
41
  需要导出时再登记四个 Manifest API 绑定、受控查询校验和 cursor 分页 Source;审批、
35
42
  Durable Job、水印、TTL、下载与取消由宿主负责。业务不自行签发明文 Grant、校验密码,
36
43
  也不接触 Workflow、BlobStore 或平台 Repository。
37
- 7. 若项目包含 `system.agent`,`operation=query` 的 Tool 会由同一 Registry 自动进入
44
+ 8. 若项目包含 `system.agent`,`operation=query` 的 Tool 会由同一 Registry 自动进入
38
45
  MCP;不要编辑 MCP Adapter 或复制 Tool 定义。写操作在幂等、审批和结果追踪闭环前
39
46
  不通过 MCP 暴露。
40
47
  对无需 Actor、Repository、Secret、文件系统或外网的纯计算 Tool,可改用
41
48
  `setupSandbox()` 注册;此入口必须同步且无副作用,Handler 只能使用输入、
42
49
  `idempotencyKey` 与 `AbortSignal`。需要业务数据或外部服务的 Tool 必须保留在普通
43
50
  `setup()`,不能为了使用 Sandbox 绕过依赖边界。
44
- 8. 补 Manifest/Composition、Repository/Service、Guard 拒绝和 Handler 契约测试。
51
+ 9. 补 Manifest/Composition、Repository/Service、Guard 拒绝和 Handler 契约测试。
52
+ 涉及 Durable Handler 时覆盖 Feature/Permission/Audit 绑定,并证明首次执行、重试和
53
+ 恢复都会按当前 License、Feature 与 RBAC 状态重新授权。
45
54
  涉及 Tool 时还要覆盖 Schema 拒绝、数据范围与未授权发现/调用;涉及可选模块时覆盖
46
55
  Starter 的文件、依赖和数据库裁剪。涉及资源文件时还要覆盖跨上传者成功、资源绑定/
47
56
  purpose/Feature/Permission/Scope 任一拒绝、最小元数据与成功/拒绝审计。
48
57
  涉及 Sandbox Tool 时还要覆盖无网络、无平台 Secret、无宿主数据挂载、Worker
49
58
  重启恢复,以及策略拒绝与业务失败审计分类。
50
- 9. 更新长期文档,运行受影响测试、`bun run typecheck` 和 `bun run lint`,按一个完整
51
- 小切片提交。
59
+ 10. 更新长期文档,运行受影响测试、`bun run typecheck` 和 `bun run lint`,按一个完整
60
+ 小切片提交。
61
+
62
+ ## 项目所有权与自动装配
63
+
64
+ - `apps/web/src`、`apps/server/src/app`、业务模块源码和
65
+ `windy.modules.json` 都是 project-owned;客户可以修改或替换。日常模块命令只更新
66
+ package/锁文件与装配声明,不覆盖 Admin、Router、layout 或 Server Composition。
67
+ - Admin Host 从启用模块的 `./admin` 与 Manifest 贡献投影页面、入口和可见性。客户可
68
+ 隐藏、排序或替换展示;模块不得直接写侧边栏源码。
69
+ - Server Host 只接受 canonical `./manifest`、声明兼容范围的 Adapter 和显式
70
+ attachment。动态 package 不获得数据库或平台 Repository;需要项目 Repository 的
71
+ 模块在 project-owned Composition 中装配。
72
+ - 每次安装、构建和 Server 监听前都必须执行同一套 Manifest/实现双向校验。未知、
73
+ 重复、缺失声明以及 setup 后替换或变异 canonical Manifest 都应 fail closed。
52
74
 
53
75
  ## 代码事实源
54
76
 
55
77
  - Manifest 与 Tool 类型:`packages/modules/src/manifest.ts`
56
78
  - Tool 组合校验:`packages/modules/src/tool-composition.ts`
57
79
  - 模块 Host 契约:`packages/server-sdk/src/module-host.ts`
80
+ - Durable Handler 契约:`packages/server-sdk/src/durable-handler.ts`
81
+ - 项目模块生命周期:`packages/create-windy/src/module-lifecycle-resolver.ts`
58
82
  - Tool Handler 契约:`packages/server-sdk/src/tool-registration.ts`
59
83
  - Sandbox Tool 契约:`packages/server-sdk/src/sandbox-tool.ts`
60
84
  - 可移除业务示例:`packages/example-work-order/`、`apps/server/src/work-order/`
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "templateCommit": "45fdbe8e2a55dff118933af58a60976e9bfe318c",
4
- "generatorVersion": "0.3.19",
3
+ "templateCommit": "50d32b9470dbf55110aba320338f5e54ed896c77",
4
+ "generatorVersion": "0.4.0",
5
5
  "modules": [
6
6
  {
7
7
  "name": "system",
@@ -40,20 +40,30 @@
40
40
  共享脚手架或根工具链同样受支持,但通常会增加后续三方合并成本。
41
41
  - 修改前可查看 ownership 评估升级风险;优先扩展 `project-owned` 路径,对
42
42
  `windy-managed` 路径建议保持改动小而清晰。
43
+ - `windy.modules.json` 是 project-owned 模块装配选择:可调整启用、顺序、Admin
44
+ 可见性与模块配置;package 只写无版本入口,实际版本以 `package.json` 和
45
+ `bun.lock` 为准。日常模块命令不得为了装配入口改写客户 Router、layout 或 Host。
46
+ - 整个 `apps/web/src` 与整个 `apps/server/src/app` 都是 project-owned。普通
47
+ `windy update` 不覆盖或三方合并客户的 Admin、Router、layout、页面、Host 或
48
+ Server 组合。
49
+ - 当前没有 H3 模块,也不支持任意 npm package 名称安装。日常只使用
50
+ `module list/enable/disable`;内置模块的 add/update/remove 实际集合变化会在写入前
51
+ fail closed。`system.settings`、`system.storage` 与
52
+ `system.data-governance` 不能只靠 registry 安全停用。
43
53
  - 直接修改 Windy 基线代码时,使用独立小提交记录原因和影响;升级前先运行
44
54
  `bun run windy update --dry-run`,根据三方合并计划处理冲突。
45
- - 完整定制登录页时,在 project-owned 的
46
- `apps/web/src/app/auth/login-page.ts` 注册业务组件可获得最低升级成本。若直接修改
47
- `apps/web/src/pages/auth/LoginPage.vue` 或 Router,升级器会尝试三方合并。业务页面复用
55
+ - 完整定制登录页时,可在 `apps/web/src/app/auth/login-page.ts` 注册业务组件,也可
56
+ 直接修改 `apps/web/src/pages/auth/LoginPage.vue` 或 Router;这些文件均由项目拥有。
57
+ 业务页面复用
48
58
  `useLoginFlow`、`DevelopmentAuthWarning` 和平台品牌设置,保留安全
49
59
  `returnTo`、真实认证与开发认证提示。
50
- - 定制 404、500、维护中或网络异常页时,优先修改 project-owned 的
60
+ - 定制 404、500、维护中或网络异常页时,可以修改
51
61
  `apps/web/src/app/error-pages.ts`,并把业务 SFC 放在 `apps/web/src/app/`;
52
- 直接修改 Router、HTTP 核心或平台默认错误页时会增加三方合并成本。
62
+ 也可以直接修改项目拥有的 Router 或平台默认错误页。
53
63
  - 新增业务管理页面时,在业务 Module Manifest 注册 Feature、Permission、菜单和
54
- Admin Route,再把 Vue 页面绑定到 project-owned 的
55
- `apps/web/src/app/business-routes.ts` 是推荐接入方式。直接修改 Router 或 AppSidebar
56
- 时同样按 Base/Ours/Theirs 合并。导航来自服务端 Manifest 快照,接入见
64
+ Admin Route,并由 package 的 `./admin` 提供默认页面;项目需要替换页面时在
65
+ `apps/web/src/app/web-composition.ts` 按 route key 覆盖 loader。业务工作台路由可在
66
+ 项目拥有的 Router 中直接实现。导航来自服务端 Manifest 快照,接入见
57
67
  `docs/development/business-web-routes.md`。
58
68
  - 业务 Agent Operation 开启 Provider 出网时,必须在 Manifest 同时声明最小
59
69
  `providerDataPolicy.inputFields` JSON Pointer allowlist 与
@@ -62,9 +62,10 @@ Skill 完成该能力”。Skill 只指导开发流程;Feature、Permission、
62
62
  运行时事实仍以 Module Manifest 与平台 Registry 为准。
63
63
 
64
64
  当前组合未包含 `system.agent`,MCP Server、Agent Tool Host 和相关文档已被
65
- 物理裁剪。创建时可增加 `--module system.agent` 或使用 `--all-modules`;已部署
66
- 项目使用 `bun run windy module add system.agent`,不要手工复制 MCP Adapter 或
67
- 另建授权链。仓库 Skill 仍可用于普通业务模块开发。
65
+ 物理裁剪。创建时可增加 `--module system.agent` 或使用 `--all-modules`。当前没有
66
+ self-contained H3 模块,已部署项目当前不能通过模块命令补装 `system.agent`;
67
+ `module add` 会在写入前 fail closed。不要手工复制 MCP Adapter 或另建授权链。仓库
68
+ Skill 仍可用于普通业务模块开发。
68
69
 
69
70
 
70
71
 
@@ -101,8 +102,8 @@ create-windy 在本机 `.env` 中随机生成的 `WINDY_BOOTSTRAP_ADMIN_PASSWORD
101
102
  | 法律许可 | `UNLICENSED` |
102
103
 
103
104
  平台当前注册的全部模块如下。H0 表示 profile 锁定核心;H2 表示创建时可以物理包含或
104
- 排除;H3 还具备部署期安装、更新、数据保留卸载和重装证据。通用生命周期命令会保守
105
- 处理所有目录模块,但只有通过完整 H3 回归的模块才标记为 H3。
105
+ 排除;H3 还具备部署期安装、更新、数据保留卸载和重装证据。当前没有 H3 模块,也不
106
+ 支持任意 npm package 名称安装。
106
107
 
107
108
  | Module Key | 当前项目 | 热插拔可靠度 | 说明 |
108
109
  | ---------- | -------- | ------------ | ---- |
@@ -121,17 +122,24 @@ create-windy 在本机 `.env` 中随机生成的 `WINDY_BOOTSTRAP_ADMIN_PASSWORD
121
122
  | `system.bulk-data` | 未包含 | H2 | 批量导入导出与结果留存。 |
122
123
  | `system.search` | 未包含 | H2 | 权限感知搜索与 Provider 聚合。 |
123
124
  | `system.data-governance` | 未包含 | H2 | 敏感字段、明文访问和治理导出。 |
124
- | `work-order` | 未包含 | H3 | 可替换的业务模块接入示例。 |
125
-
126
- 项目自有业务模块以 `apps/server/src/installed-business-modules.ts` 装配的 Module Manifest
127
- 为准;对应 Vue 页面在 project-owned 的
128
- `apps/web/src/app/business-routes.ts` 注册,侧栏继续从服务端 Manifest 快照生成。
129
- 不要为增加业务页面修改 shared-scaffold Router 或 AppSidebar。shared-scaffold README
130
- 不复制项目业务 Key,避免平台升级固化产品命名。
131
-
132
- 精确生成来源和选择记录在 `.windy/generation.json`。当前版本已提供可回滚的
133
- `windy update` 与 `windy module list/add/update/remove`。Feature Flag 关闭仍不
134
- 等于模块卸载。
125
+ | `work-order` | 未包含 | H2 | 可替换的业务模块接入示例。 |
126
+
127
+ 项目装配选择记录在 project-owned 的 `windy.modules.json`,可提交 Git 并结构化编辑;
128
+ 它只保存无版本 package 入口、启用状态、顺序、Admin 可见性与模块配置。依赖版本事实
129
+ 仍只来自 `package.json` 与 `bun.lock`。Server 默认从
130
+ `apps/server/src/app/server-composition.ts` 装配 Adapter;Web 通过 package 的
131
+ browser-safe `./admin` 与 project-owned 的
132
+ `apps/web/src/app/web-composition.ts` 装配页面,不复制第二份 Feature、Permission
133
+ 或路由清单。整个 `apps/web/src` 与整个 `apps/server/src/app` 都是
134
+ project-owned,客户可以修改 Router、layout、页面、Host 和 Server 组合;普通
135
+ `windy update` 不会覆盖或三方合并这些文件。
136
+
137
+ 精确生成来源保留在 `.windy/generation.json`。当前版本已提供可回滚的
138
+ `windy update` 与 `windy module list/enable/disable`。当前内置模块仍依赖
139
+ source/template 或 project-owned Composition;当前内置模块的 add/update/remove
140
+ 实际集合变化会在写入前 fail closed。Feature Flag 关闭、module disable 与物理卸载是
141
+ 三个不同动作;`system.settings`、`system.storage` 和
142
+ `system.data-governance` 只能在创建期物理排除,部署后不能只改 registry 安全停用。
135
143
 
136
144
  ## 常用命令
137
145
 
@@ -148,8 +156,7 @@ bun run windy doctor
148
156
  bun run windy update --check
149
157
  bun run windy update --dry-run
150
158
  bun run windy module list
151
- bun run windy module add work-order --dry-run
152
- bun run windy module remove work-order --dry-run
159
+ # 当前组合没有可安全 runtime disable 的已安装可选模块
153
160
  bun run lint
154
161
  bun run format
155
162
  ```
@@ -158,7 +165,9 @@ bun run format
158
165
 
159
166
  更新前无需提交、暂存或清理业务改动。`--dry-run` 只生成计划,不写项目;无关 WIP
160
167
  保持原样,命中同一路径时按冻结快照与三方合并 fail closed。正式更新先备份,再做
161
- package 字段级合并、共享脚手架三方合并与完整验证。任何冲突都会在写入前中止,
168
+ package 字段级合并、共享脚手架三方合并与完整验证。整个 `apps/web/src` 和
169
+ `apps/server/src/app` 保持项目版本。任何冲突都会在写入前中止,模块启停在交互
170
+ 终端确认;CI、Agent 或其它非 TTY 环境必须显式传入 `--yes`。
162
171
  无并发变化的验证失败会自动回滚;中断恢复使用
163
172
  `bun run windy doctor --repair`。该命令在提交点前保留并发编辑并回滚其余路径,
164
173
  在 committed 提交点后只完成事务状态与备份清理,不回滚项目文件。
@@ -181,9 +190,10 @@ create-windy 默认建立 `main` 分支并创建 `chore: initialize project` 首
181
190
  没有配置 Git 用户身份,文件会保留在暂存区;配置身份后手动提交即可。
182
191
 
183
192
  当前已交付的 Windy 更新器会根据 Project Lock 和文件所有权,从 Project Lock 指向的
184
- 精确 npm artifact 重建 Base 并执行三方合并;它不连接私有源仓库,也不会静默覆盖项目代码。模块
185
- 生命周期命令复用同一计划、事务、验证与恢复边界;卸载默认保留数据库数据,并要求
186
- 显式确认数据处置计划。
193
+ 精确 npm artifact 重建 Base 并执行三方合并;它不连接私有源仓库。
194
+ 更新器不会静默覆盖项目代码。`module enable/disable` 只以 CAS 事务更新
195
+ `windy.modules.json`;当前内置模块的 add/update/remove 实际集合变化在生成更新
196
+ 计划前即被拒绝。
187
197
 
188
198
  ## License
189
199
 
@@ -4,6 +4,7 @@ FROM oven/bun:1.3.14-alpine AS deps
4
4
  WORKDIR /app
5
5
 
6
6
  COPY package.json bun.lock ./
7
+ COPY windy.modules.json windy.modules.json
7
8
  # windy-copy:deps begin
8
9
  COPY apps/license/package.json apps/license/package.json
9
10
  COPY apps/server/package.json apps/server/package.json
@@ -4,6 +4,7 @@
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "scripts": {
7
+ "build": "bun run scripts/validate-module-composition.ts",
7
8
  "dev": "bun --watch run src/index.ts",
8
9
  "start": "bun run src/index.ts",
9
10
  "typecheck": "tsc --noEmit --project tsconfig.json"
@@ -0,0 +1,4 @@
1
+ process.argv.push("--validate-module-composition");
2
+ delete process.env.DATABASE_URL;
3
+
4
+ await import("../src/index.js");
@@ -0,0 +1,28 @@
1
+ import { spawnSync } from "node:child_process";
2
+
3
+ const variants = [
4
+ { name: "default", env: { PLATFORM_ENABLE_AI: "false" } },
5
+ {
6
+ name: "ai-enabled",
7
+ env: {
8
+ PLATFORM_ENABLE_AI: "true",
9
+ AGENT_SERVER_INTERNAL_TOKEN: "0123456789abcdef0123456789abcdef",
10
+ AI_ARTIFACT_ENCRYPTION_SECRET: "abcdef0123456789abcdef0123456789",
11
+ },
12
+ },
13
+ ] as const;
14
+
15
+ for (const variant of variants) {
16
+ const result = spawnSync(
17
+ process.execPath,
18
+ ["run", "scripts/validate-module-composition-once.ts"],
19
+ {
20
+ cwd: process.cwd(),
21
+ env: { ...process.env, ...variant.env, DATABASE_URL: "" },
22
+ stdio: "inherit",
23
+ },
24
+ );
25
+ if (result.status !== 0) {
26
+ throw new Error(`${variant.name} Module Composition 验证失败`);
27
+ }
28
+ }
@@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test";
2
2
  import { buildScopeContext } from "../data-access/context.js";
3
3
  import { createFoundationSnapshot, loadSystemModules } from "../foundation.js";
4
4
  import { createServerRuntime } from "../runtime.js";
5
+ import { createStaticRouteAuthorizer } from "../module-host/static-route-authorization.js";
5
6
  import { FakeRouteApp } from "../system/route-test-app.js";
6
7
  import { createSystemRepositories } from "../system/seed.js";
7
8
  import {
@@ -13,7 +14,11 @@ import { GovernedToolRegistry } from "./tool-registry.js";
13
14
 
14
15
  describe("Agent Tool data scope", () => {
15
16
  test("启动时拒绝 Manifest 与 Handler 不一致", () => {
16
- const runtime = createServerRuntime({ WINDY_DEV_ADMIN_TOKEN: "token_1" });
17
+ const snapshot = createFoundationSnapshot();
18
+ const runtime = createServerRuntime(
19
+ { WINDY_DEV_ADMIN_TOKEN: "token_1" },
20
+ { featureCatalog: snapshot.features },
21
+ );
17
22
  const handlers = createSystemToolHandlers(
18
23
  createSystemRepositories(createFoundationSnapshot()),
19
24
  runtime,
@@ -41,8 +46,12 @@ describe("Agent Tool data scope", () => {
41
46
  test("用户 Tool 忽略客户端 ownership 参数并使用 Server self scope", async () => {
42
47
  const snapshot = createFoundationSnapshot();
43
48
  const repositories = createSystemRepositories(snapshot);
44
- const runtime = createServerRuntime({ WINDY_DEV_ADMIN_TOKEN: "token_1" });
49
+ const runtime = createServerRuntime(
50
+ { WINDY_DEV_ADMIN_TOKEN: "token_1" },
51
+ { featureCatalog: snapshot.features },
52
+ );
45
53
  const app = new FakeRouteApp();
54
+ const modules = loadSystemModules();
46
55
  const guardContext = await runtime.createGuardContext(
47
56
  authenticatedRequest(),
48
57
  );
@@ -64,10 +73,11 @@ describe("Agent Tool data scope", () => {
64
73
  registerAgentRoutes(
65
74
  app,
66
75
  new GovernedToolRegistry(
67
- loadSystemModules(),
76
+ modules,
68
77
  createSystemToolHandlers(repositories, runtime),
69
78
  runtime,
70
79
  ),
80
+ createStaticRouteAuthorizer(runtime, modules),
71
81
  );
72
82
  guardContext.actor = {
73
83
  ...guardContext.actor,
@@ -94,15 +104,20 @@ describe("Agent Tool data scope", () => {
94
104
 
95
105
  test("请求级 Tool 缺少 Server ScopeContext 时 fail closed", async () => {
96
106
  const snapshot = createFoundationSnapshot();
97
- const runtime = createServerRuntime({ WINDY_DEV_ADMIN_TOKEN: "token_1" });
107
+ const runtime = createServerRuntime(
108
+ { WINDY_DEV_ADMIN_TOKEN: "token_1" },
109
+ { featureCatalog: snapshot.features },
110
+ );
98
111
  const app = new FakeRouteApp();
112
+ const modules = loadSystemModules();
99
113
  registerAgentRoutes(
100
114
  app,
101
115
  new GovernedToolRegistry(
102
- loadSystemModules(),
116
+ modules,
103
117
  createSystemToolHandlers(createSystemRepositories(snapshot), runtime),
104
118
  runtime,
105
119
  ),
120
+ createStaticRouteAuthorizer(runtime, modules),
106
121
  );
107
122
  const guardContext = await runtime.createGuardContext(
108
123
  authenticatedRequest(),
@@ -5,6 +5,7 @@ import {
5
5
  } from "@southwind-ai/shared";
6
6
  import { createFoundationSnapshot, loadSystemModules } from "../foundation.js";
7
7
  import { createServerRuntime } from "../runtime.js";
8
+ import { createStaticRouteAuthorizer } from "../module-host/static-route-authorization.js";
8
9
  import type { RouteApp } from "../system/routes.js";
9
10
  import { createSystemRepositories } from "../system/seed.js";
10
11
  import { createSystemToolHandlers, registerAgentRoutes } from "./routes.js";
@@ -37,12 +38,18 @@ class FakeRouteApp implements RouteApp {
37
38
  }
38
39
 
39
40
  function routeFixture(features?: FeatureFlagDefinition[]) {
40
- const runtime = createServerRuntime({ WINDY_DEV_ADMIN_TOKEN: "token_1" });
41
41
  const app = new FakeRouteApp();
42
- const modules = loadSystemModules();
43
- if (features) {
44
- modules[0] = { ...modules[0]!, features };
45
- }
42
+ const overrides = new Map(features?.map((feature) => [feature.key, feature]));
43
+ const modules = loadSystemModules().map((module) => ({
44
+ ...module,
45
+ features: module.features.map(
46
+ (feature) => overrides?.get(feature.key) ?? feature,
47
+ ),
48
+ }));
49
+ const runtime = createServerRuntime(
50
+ { WINDY_DEV_ADMIN_TOKEN: "token_1" },
51
+ { featureCatalog: modules.flatMap((module) => module.features) },
52
+ );
46
53
  registerAgentRoutes(
47
54
  app,
48
55
  new GovernedToolRegistry(
@@ -53,6 +60,7 @@ function routeFixture(features?: FeatureFlagDefinition[]) {
53
60
  ),
54
61
  runtime,
55
62
  ),
63
+ createStaticRouteAuthorizer(runtime, modules),
56
64
  );
57
65
  return { app, runtime };
58
66
  }
@@ -189,16 +197,21 @@ describe("agent routes", () => {
189
197
  await repositories.features.syncManifest(snapshot.features);
190
198
  const runtime = createServerRuntime(
191
199
  { WINDY_DEV_ADMIN_TOKEN: "token_1" },
192
- { featureResolver: repositories.features },
200
+ {
201
+ featureCatalog: snapshot.features,
202
+ featureResolver: repositories.features,
203
+ },
193
204
  );
194
205
  const app = new FakeRouteApp();
206
+ const modules = loadSystemModules();
195
207
  registerAgentRoutes(
196
208
  app,
197
209
  new GovernedToolRegistry(
198
- loadSystemModules(),
210
+ modules,
199
211
  createSystemToolHandlers(repositories, runtime),
200
212
  runtime,
201
213
  ),
214
+ createStaticRouteAuthorizer(runtime, modules),
202
215
  );
203
216
  const request = () =>
204
217
  new Request(
@@ -14,6 +14,7 @@ import {
14
14
  type ModuleToolHandlers,
15
15
  type PlatformToolExecutionContext,
16
16
  } from "./tool-registry.js";
17
+ import type { StaticRouteAuthorizer } from "../module-host/static-route-authorization.js";
17
18
 
18
19
  type ServerRuntime = ReturnType<typeof createServerRuntime>;
19
20
 
@@ -85,9 +86,16 @@ export function createSystemToolHandlers(
85
86
  export function registerAgentRoutes(
86
87
  app: RouteApp,
87
88
  registry: GovernedToolRegistry,
89
+ authorizer: StaticRouteAuthorizer,
88
90
  ) {
89
91
  app.get("/agent/tools", async (rawContext) => {
90
92
  const { guardContext } = rawContext as RouteContext;
93
+ const denied = await authorizer.authorize(
94
+ guardContext,
95
+ "GET",
96
+ "/api/agent/tools",
97
+ );
98
+ if (denied) return denied;
91
99
  return Promise.all(
92
100
  registry.definitions().map(async (tool) => ({
93
101
  key: tool.key,
@@ -103,6 +111,12 @@ export function registerAgentRoutes(
103
111
 
104
112
  app.post("/agent/tools/:key/execute", async (rawContext) => {
105
113
  const context = rawContext as RouteContext;
114
+ const denied = await authorizer.authorize(
115
+ context.guardContext,
116
+ "POST",
117
+ "/api/agent/tools/:key/execute",
118
+ );
119
+ if (denied) return denied;
106
120
  try {
107
121
  return await registry.execute(
108
122
  context.params.key ?? "",
@@ -46,6 +46,11 @@ import { AgentBackgroundOperationExecutor } from "./background-operation.js";
46
46
  import type { DeferredAgentBackgroundOperationPortFactory } from "./background-operation-port.js";
47
47
  import { UnixSandboxToolClient } from "./sandbox-client.js";
48
48
  import { createModuleAiOperationPort } from "../module-host/ai-operation-port.js";
49
+ import {
50
+ createManifestAuthorizedRouteApp,
51
+ createStaticRouteAuthorizer,
52
+ } from "../module-host/static-route-authorization.js";
53
+ import { registerUnavailableAiRoutes } from "./unavailable-routes.js";
49
54
 
50
55
  export function registerAgentPlatformRuntime(input: {
51
56
  app: RouteApp;
@@ -79,18 +84,29 @@ export function registerAgentPlatformRuntime(input: {
79
84
  toolHandlers,
80
85
  input.runtime,
81
86
  );
82
- registerAgentRoutes(input.app, toolRegistry);
87
+ const routeAuthorizer = createStaticRouteAuthorizer(
88
+ input.runtime,
89
+ input.modules,
90
+ );
91
+ registerAgentRoutes(input.app, toolRegistry, routeAuthorizer);
83
92
  registerMcpRoutes(
84
93
  input.app,
85
94
  new PlatformMcpAdapter(toolRegistry, input.runtime, features),
86
95
  );
87
96
  if (!input.platformConfig.enableAI) {
97
+ registerUnavailableAiRoutes(
98
+ createManifestAuthorizedRouteApp(input.app, routeAuthorizer),
99
+ );
88
100
  return {
89
101
  toolHandlers,
90
102
  aiArtifacts: undefined,
91
103
  aiOperations: undefined,
92
104
  };
93
105
  }
106
+ const aiRouteApp = createManifestAuthorizedRouteApp(
107
+ input.app,
108
+ routeAuthorizer,
109
+ );
94
110
  const internalToken = requiredEnvironment("AGENT_SERVER_INTERNAL_TOKEN");
95
111
  const aiArtifacts = new AiArtifactRuntime(
96
112
  new AiArtifactCodec(requiredEnvironment("AI_ARTIFACT_ENCRYPTION_SECRET")),
@@ -100,7 +116,7 @@ export function registerAgentPlatformRuntime(input: {
100
116
  input.storage,
101
117
  resolveAgentActor,
102
118
  );
103
- registerAiArtifactRoutes(input.app, aiArtifacts, internalToken);
119
+ registerAiArtifactRoutes(aiRouteApp, aiArtifacts, internalToken);
104
120
  const remote = new RemoteAgentRuntime({
105
121
  baseUrl: process.env.AGENT_SERVER_URL || "http://agent-server:8080",
106
122
  internalToken,
@@ -127,7 +143,7 @@ export function registerAgentPlatformRuntime(input: {
127
143
  aiArtifacts,
128
144
  grants,
129
145
  );
130
- registerDocumentRunRoutes(input.app, documentFacade, documentRemote);
146
+ registerDocumentRunRoutes(aiRouteApp, documentFacade, documentRemote);
131
147
  const speechRemote = process.env.SPEECH_SERVER_URL?.trim()
132
148
  ? new RemoteSpeechRuntime({
133
149
  baseUrl: process.env.SPEECH_SERVER_URL,
@@ -142,7 +158,7 @@ export function registerAgentPlatformRuntime(input: {
142
158
  aiArtifacts,
143
159
  grants,
144
160
  );
145
- registerSpeechRunRoutes(input.app, speechFacade, speechRemote);
161
+ registerSpeechRunRoutes(aiRouteApp, speechFacade, speechRemote);
146
162
  const embeddingRemote = process.env.EMBEDDING_SERVER_URL?.trim()
147
163
  ? new RemoteEmbeddingRuntime({
148
164
  baseUrl: process.env.EMBEDDING_SERVER_URL,
@@ -156,7 +172,7 @@ export function registerAgentPlatformRuntime(input: {
156
172
  embeddingRemote,
157
173
  aiArtifacts,
158
174
  );
159
- registerEmbeddingRoutes(input.app, embeddingFacade);
175
+ registerEmbeddingRoutes(aiRouteApp, embeddingFacade);
160
176
  const agentFacade = new AgentRunFacade(
161
177
  input.modules,
162
178
  input.hosts,
@@ -166,7 +182,7 @@ export function registerAgentPlatformRuntime(input: {
166
182
  aiArtifacts,
167
183
  );
168
184
  registerAgentRunRoutes(
169
- input.app,
185
+ aiRouteApp,
170
186
  agentFacade,
171
187
  remote,
172
188
  new RestrictedAgentToolHost(
@@ -1,6 +1,6 @@
1
- import { installedBusinessModules } from "../installed-business-modules.js";
2
1
  import { SandboxToolRegistry } from "./sandbox-registry.js";
3
2
  import { runSandboxWorkerUntilSignal } from "./sandbox-worker-server.js";
3
+ import { runtimeBusinessModules } from "../module-host/runtime-composition.js";
4
4
 
5
5
  const socketPath =
6
6
  process.env.TOOL_SANDBOX_SOCKET?.trim() ||
@@ -8,5 +8,5 @@ const socketPath =
8
8
 
9
9
  await runSandboxWorkerUntilSignal(
10
10
  socketPath,
11
- new SandboxToolRegistry(installedBusinessModules),
11
+ new SandboxToolRegistry(runtimeBusinessModules),
12
12
  );
@@ -0,0 +1,33 @@
1
+ import type { RouteApp } from "../system/route-types.js";
2
+
3
+ const unavailableRoutes = [
4
+ ["GET", "/internal/ai/artifacts"],
5
+ ["POST", "/document/runs"],
6
+ ["GET", "/document/runs/:runId/events"],
7
+ ["GET", "/document/runs/:runId/result"],
8
+ ["POST", "/document/runs/:runId/cancel"],
9
+ ["POST", "/speech/runs"],
10
+ ["GET", "/speech/runs/:runId/events"],
11
+ ["GET", "/speech/runs/:runId/result"],
12
+ ["GET", "/speech/runs/:runId/artifact"],
13
+ ["POST", "/speech/runs/:runId/cancel"],
14
+ ["POST", "/embeddings"],
15
+ ["POST", "/agent/runs"],
16
+ ["GET", "/agent/runs/:runId/events"],
17
+ ["GET", "/agent/runs/:runId/result"],
18
+ ["POST", "/agent/runs/:runId/cancel"],
19
+ ["POST", "/agent/runs/:runId/attach"],
20
+ ["POST", "/internal/agent/tools/execute"],
21
+ ] as const;
22
+
23
+ export function registerUnavailableAiRoutes(app: RouteApp): void {
24
+ const unavailable = () =>
25
+ Response.json(
26
+ { code: "RUNTIME_UNAVAILABLE", message: "AI Runtime 未启用" },
27
+ { status: 503 },
28
+ );
29
+ for (const [method, path] of unavailableRoutes) {
30
+ if (method === "GET") app.get(path, unavailable);
31
+ else app.post(path, unavailable);
32
+ }
33
+ }