@ai-agent-forge/agent-forge 0.86.7 → 0.87.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 (665) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +8 -9
  3. package/dist/artifacts/artifact-store.d.ts.map +1 -1
  4. package/dist/artifacts/artifact-store.js +9 -5
  5. package/dist/artifacts/artifact-store.js.map +1 -1
  6. package/dist/bundle/.build-manifest.json +410 -371
  7. package/dist/bundle/chunks/{chunk-A7GUOX2H.js → chunk-6ZKDNZHA.js} +5 -1
  8. package/dist/bundle/chunks/chunk-BFC2BDVJ.js +13 -0
  9. package/dist/bundle/chunks/chunk-MOHOLL3F.js +1456 -0
  10. package/dist/bundle/chunks/image-resize-worker.js +12 -1
  11. package/dist/bundle/chunks/{virtual-modules-3IZ4MYSQ.js → virtual-modules-KZ5DRH7Q.js} +1 -1
  12. package/dist/bundle/cli.js +1 -1
  13. package/dist/bundle/client.js +1 -1
  14. package/dist/bundle/index.js +2 -2
  15. package/dist/bundle/rpc-entry.js +1 -1
  16. package/dist/cli/args.d.ts.map +1 -1
  17. package/dist/cli/args.js +231 -185
  18. package/dist/cli/args.js.map +1 -1
  19. package/dist/cli/auth-check.d.ts.map +1 -1
  20. package/dist/cli/auth-check.js +3 -2
  21. package/dist/cli/auth-check.js.map +1 -1
  22. package/dist/cli/auth-command.d.ts.map +1 -1
  23. package/dist/cli/auth-command.js +15 -9
  24. package/dist/cli/auth-command.js.map +1 -1
  25. package/dist/cli/credential-print.d.ts.map +1 -1
  26. package/dist/cli/credential-print.js +14 -7
  27. package/dist/cli/credential-print.js.map +1 -1
  28. package/dist/cli/experimental/command.d.ts.map +1 -1
  29. package/dist/cli/experimental/command.js +6 -5
  30. package/dist/cli/experimental/command.js.map +1 -1
  31. package/dist/cli/list-models.d.ts.map +1 -1
  32. package/dist/cli/list-models.js +9 -8
  33. package/dist/cli/list-models.js.map +1 -1
  34. package/dist/cli/plugin-manager-controller.d.ts.map +1 -1
  35. package/dist/cli/plugin-manager-controller.js +2 -1
  36. package/dist/cli/plugin-manager-controller.js.map +1 -1
  37. package/dist/cli/serve.d.ts.map +1 -1
  38. package/dist/cli/serve.js +8 -5
  39. package/dist/cli/serve.js.map +1 -1
  40. package/dist/client/remote-session.d.ts.map +1 -1
  41. package/dist/client/remote-session.js +16 -9
  42. package/dist/client/remote-session.js.map +1 -1
  43. package/dist/config.d.ts.map +1 -1
  44. package/dist/config.js +2 -1
  45. package/dist/config.js.map +1 -1
  46. package/dist/core/agent-capability-contract.d.ts +0 -7
  47. package/dist/core/agent-capability-contract.d.ts.map +1 -1
  48. package/dist/core/agent-capability-contract.js +72 -68
  49. package/dist/core/agent-capability-contract.js.map +1 -1
  50. package/dist/core/agent-session-bash.d.ts.map +1 -1
  51. package/dist/core/agent-session-bash.js +5 -4
  52. package/dist/core/agent-session-bash.js.map +1 -1
  53. package/dist/core/agent-session-compaction.d.ts.map +1 -1
  54. package/dist/core/agent-session-compaction.js +28 -22
  55. package/dist/core/agent-session-compaction.js.map +1 -1
  56. package/dist/core/agent-session-context.d.ts.map +1 -1
  57. package/dist/core/agent-session-context.js +18 -13
  58. package/dist/core/agent-session-context.js.map +1 -1
  59. package/dist/core/agent-session-model.d.ts.map +1 -1
  60. package/dist/core/agent-session-model.js +2 -1
  61. package/dist/core/agent-session-model.js.map +1 -1
  62. package/dist/core/agent-session-retry.d.ts.map +1 -1
  63. package/dist/core/agent-session-retry.js +3 -2
  64. package/dist/core/agent-session-retry.js.map +1 -1
  65. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  66. package/dist/core/agent-session-runtime.js +7 -6
  67. package/dist/core/agent-session-runtime.js.map +1 -1
  68. package/dist/core/agent-session-services.d.ts +1 -1
  69. package/dist/core/agent-session-services.d.ts.map +1 -1
  70. package/dist/core/agent-session-services.js.map +1 -1
  71. package/dist/core/agent-session-tools.d.ts.map +1 -1
  72. package/dist/core/agent-session-tools.js +3 -2
  73. package/dist/core/agent-session-tools.js.map +1 -1
  74. package/dist/core/agent-session.d.ts +40 -2
  75. package/dist/core/agent-session.d.ts.map +1 -1
  76. package/dist/core/agent-session.js +142 -34
  77. package/dist/core/agent-session.js.map +1 -1
  78. package/dist/core/auth-guidance.d.ts.map +1 -1
  79. package/dist/core/auth-guidance.js +11 -5
  80. package/dist/core/auth-guidance.js.map +1 -1
  81. package/dist/core/auth-storage.d.ts.map +1 -1
  82. package/dist/core/auth-storage.js +9 -6
  83. package/dist/core/auth-storage.js.map +1 -1
  84. package/dist/core/compaction/compaction.d.ts.map +1 -1
  85. package/dist/core/compaction/compaction.js +2 -1
  86. package/dist/core/compaction/compaction.js.map +1 -1
  87. package/dist/core/embedded-sdk.d.ts.map +1 -1
  88. package/dist/core/embedded-sdk.js +10 -6
  89. package/dist/core/embedded-sdk.js.map +1 -1
  90. package/dist/core/export-html/index.d.ts.map +1 -1
  91. package/dist/core/export-html/index.js +9 -4
  92. package/dist/core/export-html/index.js.map +1 -1
  93. package/dist/core/extensions/agent-composition.d.ts.map +1 -1
  94. package/dist/core/extensions/agent-composition.js +26 -19
  95. package/dist/core/extensions/agent-composition.js.map +1 -1
  96. package/dist/core/extensions/bootstrap-agent-loop.d.ts.map +1 -1
  97. package/dist/core/extensions/bootstrap-agent-loop.js +3 -2
  98. package/dist/core/extensions/bootstrap-agent-loop.js.map +1 -1
  99. package/dist/core/extensions/bootstrap-lifecycle.d.ts.map +1 -1
  100. package/dist/core/extensions/bootstrap-lifecycle.js +20 -17
  101. package/dist/core/extensions/bootstrap-lifecycle.js.map +1 -1
  102. package/dist/core/extensions/bootstrap-overflow-policy.d.ts.map +1 -1
  103. package/dist/core/extensions/bootstrap-overflow-policy.js +2 -1
  104. package/dist/core/extensions/bootstrap-overflow-policy.js.map +1 -1
  105. package/dist/core/extensions/bootstrap-retry-policy.d.ts.map +1 -1
  106. package/dist/core/extensions/bootstrap-retry-policy.js +2 -1
  107. package/dist/core/extensions/bootstrap-retry-policy.js.map +1 -1
  108. package/dist/core/extensions/bootstrap-skills.d.ts.map +1 -1
  109. package/dist/core/extensions/bootstrap-skills.js +7 -6
  110. package/dist/core/extensions/bootstrap-skills.js.map +1 -1
  111. package/dist/core/extensions/bootstrap-tools.d.ts.map +1 -1
  112. package/dist/core/extensions/bootstrap-tools.js +2 -1
  113. package/dist/core/extensions/bootstrap-tools.js.map +1 -1
  114. package/dist/core/extensions/capability-plugin.d.ts.map +1 -1
  115. package/dist/core/extensions/capability-plugin.js +37 -13
  116. package/dist/core/extensions/capability-plugin.js.map +1 -1
  117. package/dist/core/extensions/capability-runtime-events.d.ts.map +1 -1
  118. package/dist/core/extensions/capability-runtime-events.js +17 -13
  119. package/dist/core/extensions/capability-runtime-events.js.map +1 -1
  120. package/dist/core/extensions/capability-runtime-guards.d.ts.map +1 -1
  121. package/dist/core/extensions/capability-runtime-guards.js +16 -15
  122. package/dist/core/extensions/capability-runtime-guards.js.map +1 -1
  123. package/dist/core/extensions/capability-runtime-manifest.d.ts.map +1 -1
  124. package/dist/core/extensions/capability-runtime-manifest.js +52 -30
  125. package/dist/core/extensions/capability-runtime-manifest.js.map +1 -1
  126. package/dist/core/extensions/capability-runtime-validation.d.ts.map +1 -1
  127. package/dist/core/extensions/capability-runtime-validation.js +66 -65
  128. package/dist/core/extensions/capability-runtime-validation.js.map +1 -1
  129. package/dist/core/extensions/capability-runtime.d.ts.map +1 -1
  130. package/dist/core/extensions/capability-runtime.js +147 -127
  131. package/dist/core/extensions/capability-runtime.js.map +1 -1
  132. package/dist/core/extensions/compaction-memory-failure-mode.d.ts.map +1 -1
  133. package/dist/core/extensions/compaction-memory-failure-mode.js +3 -2
  134. package/dist/core/extensions/compaction-memory-failure-mode.js.map +1 -1
  135. package/dist/core/extensions/context-strategy-binding.d.ts.map +1 -1
  136. package/dist/core/extensions/context-strategy-binding.js +7 -4
  137. package/dist/core/extensions/context-strategy-binding.js.map +1 -1
  138. package/dist/core/extensions/lifecycle-catalog.d.ts.map +1 -1
  139. package/dist/core/extensions/lifecycle-catalog.js +290 -279
  140. package/dist/core/extensions/lifecycle-catalog.js.map +1 -1
  141. package/dist/core/extensions/lifecycle-delivery-queue.d.ts.map +1 -1
  142. package/dist/core/extensions/lifecycle-delivery-queue.js +3 -2
  143. package/dist/core/extensions/lifecycle-delivery-queue.js.map +1 -1
  144. package/dist/core/facade/coding-agent-facade.d.ts +6 -0
  145. package/dist/core/facade/coding-agent-facade.d.ts.map +1 -1
  146. package/dist/core/facade/coding-agent-facade.js +2 -0
  147. package/dist/core/facade/coding-agent-facade.js.map +1 -1
  148. package/dist/core/http-dispatcher.d.ts.map +1 -1
  149. package/dist/core/http-dispatcher.js +2 -1
  150. package/dist/core/http-dispatcher.js.map +1 -1
  151. package/dist/core/i18n/index.d.ts +14 -0
  152. package/dist/core/i18n/index.d.ts.map +1 -0
  153. package/dist/core/i18n/index.js +67 -0
  154. package/dist/core/i18n/index.js.map +1 -0
  155. package/dist/core/i18n/locales/en/example.d.ts +7 -0
  156. package/dist/core/i18n/locales/en/example.d.ts.map +1 -0
  157. package/dist/core/i18n/locales/en/example.js +7 -0
  158. package/dist/core/i18n/locales/en/example.js.map +1 -0
  159. package/dist/core/i18n/locales/zh-cn/cli.d.ts +8 -0
  160. package/dist/core/i18n/locales/zh-cn/cli.d.ts.map +1 -0
  161. package/dist/core/i18n/locales/zh-cn/cli.js +227 -0
  162. package/dist/core/i18n/locales/zh-cn/cli.js.map +1 -0
  163. package/dist/core/i18n/locales/zh-cn/common.d.ts +6 -0
  164. package/dist/core/i18n/locales/zh-cn/common.d.ts.map +1 -0
  165. package/dist/core/i18n/locales/zh-cn/common.js +6 -0
  166. package/dist/core/i18n/locales/zh-cn/common.js.map +1 -0
  167. package/dist/core/i18n/locales/zh-cn/core-contract-core.d.ts +13 -0
  168. package/dist/core/i18n/locales/zh-cn/core-contract-core.d.ts.map +1 -0
  169. package/dist/core/i18n/locales/zh-cn/core-contract-core.js +173 -0
  170. package/dist/core/i18n/locales/zh-cn/core-contract-core.js.map +1 -0
  171. package/dist/core/i18n/locales/zh-cn/core-contract-extensions.d.ts +12 -0
  172. package/dist/core/i18n/locales/zh-cn/core-contract-extensions.d.ts.map +1 -0
  173. package/dist/core/i18n/locales/zh-cn/core-contract-extensions.js +582 -0
  174. package/dist/core/i18n/locales/zh-cn/core-contract-extensions.js.map +1 -0
  175. package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts +9 -0
  176. package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts.map +1 -0
  177. package/dist/core/i18n/locales/zh-cn/core-contract-final.js +55 -0
  178. package/dist/core/i18n/locales/zh-cn/core-contract-final.js.map +1 -0
  179. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.d.ts +11 -0
  180. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.d.ts.map +1 -0
  181. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js +455 -0
  182. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js.map +1 -0
  183. package/dist/core/i18n/locales/zh-cn/core-errors.d.ts +9 -0
  184. package/dist/core/i18n/locales/zh-cn/core-errors.d.ts.map +1 -0
  185. package/dist/core/i18n/locales/zh-cn/core-errors.js +191 -0
  186. package/dist/core/i18n/locales/zh-cn/core-errors.js.map +1 -0
  187. package/dist/core/i18n/locales/zh-cn/example.d.ts +7 -0
  188. package/dist/core/i18n/locales/zh-cn/example.d.ts.map +1 -0
  189. package/dist/core/i18n/locales/zh-cn/example.js +10 -0
  190. package/dist/core/i18n/locales/zh-cn/example.js.map +1 -0
  191. package/dist/core/i18n/locales/zh-cn/index.d.ts +2 -0
  192. package/dist/core/i18n/locales/zh-cn/index.d.ts.map +1 -0
  193. package/dist/core/i18n/locales/zh-cn/index.js +41 -0
  194. package/dist/core/i18n/locales/zh-cn/index.js.map +1 -0
  195. package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts +10 -0
  196. package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts.map +1 -0
  197. package/dist/core/i18n/locales/zh-cn/interactive-mode.js +265 -0
  198. package/dist/core/i18n/locales/zh-cn/interactive-mode.js.map +1 -0
  199. package/dist/core/i18n/locales/zh-cn/keybindings.d.ts +11 -0
  200. package/dist/core/i18n/locales/zh-cn/keybindings.d.ts.map +1 -0
  201. package/dist/core/i18n/locales/zh-cn/keybindings.js +67 -0
  202. package/dist/core/i18n/locales/zh-cn/keybindings.js.map +1 -0
  203. package/dist/core/i18n/locales/zh-cn/slash-commands.d.ts +7 -0
  204. package/dist/core/i18n/locales/zh-cn/slash-commands.d.ts.map +1 -0
  205. package/dist/core/i18n/locales/zh-cn/slash-commands.js +39 -0
  206. package/dist/core/i18n/locales/zh-cn/slash-commands.js.map +1 -0
  207. package/dist/core/i18n/locales/zh-cn/tui-builtin.d.ts +10 -0
  208. package/dist/core/i18n/locales/zh-cn/tui-builtin.d.ts.map +1 -0
  209. package/dist/core/i18n/locales/zh-cn/tui-builtin.js +15 -0
  210. package/dist/core/i18n/locales/zh-cn/tui-builtin.js.map +1 -0
  211. package/dist/core/i18n/locales/zh-cn/tui-components-misc.d.ts +13 -0
  212. package/dist/core/i18n/locales/zh-cn/tui-components-misc.d.ts.map +1 -0
  213. package/dist/core/i18n/locales/zh-cn/tui-components-misc.js +102 -0
  214. package/dist/core/i18n/locales/zh-cn/tui-components-misc.js.map +1 -0
  215. package/dist/core/i18n/locales/zh-cn/tui-components-selectors.d.ts +12 -0
  216. package/dist/core/i18n/locales/zh-cn/tui-components-selectors.d.ts.map +1 -0
  217. package/dist/core/i18n/locales/zh-cn/tui-components-selectors.js +288 -0
  218. package/dist/core/i18n/locales/zh-cn/tui-components-selectors.js.map +1 -0
  219. package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.d.ts +9 -0
  220. package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.d.ts.map +1 -0
  221. package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.js +79 -0
  222. package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.js.map +1 -0
  223. package/dist/core/i18n/locales/zh-cn/tui-self-owned.d.ts +8 -0
  224. package/dist/core/i18n/locales/zh-cn/tui-self-owned.d.ts.map +1 -0
  225. package/dist/core/i18n/locales/zh-cn/tui-self-owned.js +72 -0
  226. package/dist/core/i18n/locales/zh-cn/tui-self-owned.js.map +1 -0
  227. package/dist/core/keybindings.d.ts +15 -0
  228. package/dist/core/keybindings.d.ts.map +1 -1
  229. package/dist/core/keybindings.js +18 -0
  230. package/dist/core/keybindings.js.map +1 -1
  231. package/dist/core/logger.d.ts.map +1 -1
  232. package/dist/core/logger.js +5 -1
  233. package/dist/core/logger.js.map +1 -1
  234. package/dist/core/model-registry.d.ts.map +1 -1
  235. package/dist/core/model-registry.js +2 -1
  236. package/dist/core/model-registry.js.map +1 -1
  237. package/dist/core/model-runtime.d.ts.map +1 -1
  238. package/dist/core/model-runtime.js +8 -4
  239. package/dist/core/model-runtime.js.map +1 -1
  240. package/dist/core/package-install-host.d.ts.map +1 -1
  241. package/dist/core/package-install-host.js +4 -3
  242. package/dist/core/package-install-host.js.map +1 -1
  243. package/dist/core/package-manager.d.ts.map +1 -1
  244. package/dist/core/package-manager.js +15 -10
  245. package/dist/core/package-manager.js.map +1 -1
  246. package/dist/core/package-resource-collection.d.ts.map +1 -1
  247. package/dist/core/package-resource-collection.js +2 -1
  248. package/dist/core/package-resource-collection.js.map +1 -1
  249. package/dist/core/package-source.d.ts.map +1 -1
  250. package/dist/core/package-source.js +3 -2
  251. package/dist/core/package-source.js.map +1 -1
  252. package/dist/core/provider-composer.d.ts.map +1 -1
  253. package/dist/core/provider-composer.js +22 -13
  254. package/dist/core/provider-composer.js.map +1 -1
  255. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  256. package/dist/core/remote-catalog-provider.js +6 -2
  257. package/dist/core/remote-catalog-provider.js.map +1 -1
  258. package/dist/core/resolve-config-value.d.ts.map +1 -1
  259. package/dist/core/resolve-config-value.js +15 -5
  260. package/dist/core/resolve-config-value.js.map +1 -1
  261. package/dist/core/sdk.d.ts +19 -5
  262. package/dist/core/sdk.d.ts.map +1 -1
  263. package/dist/core/sdk.js +74 -54
  264. package/dist/core/sdk.js.map +1 -1
  265. package/dist/core/session-cwd.d.ts.map +1 -1
  266. package/dist/core/session-cwd.js +5 -2
  267. package/dist/core/session-cwd.js.map +1 -1
  268. package/dist/core/session-export.d.ts.map +1 -1
  269. package/dist/core/session-export.js +2 -1
  270. package/dist/core/session-export.js.map +1 -1
  271. package/dist/core/session-manager.d.ts.map +1 -1
  272. package/dist/core/session-manager.js +39 -29
  273. package/dist/core/session-manager.js.map +1 -1
  274. package/dist/core/session-storage.d.ts.map +1 -1
  275. package/dist/core/session-storage.js +3 -3
  276. package/dist/core/session-storage.js.map +1 -1
  277. package/dist/core/settings-manager.d.ts +11 -0
  278. package/dist/core/settings-manager.d.ts.map +1 -1
  279. package/dist/core/settings-manager.js +27 -5
  280. package/dist/core/settings-manager.js.map +1 -1
  281. package/dist/core/slash-commands.d.ts.map +1 -1
  282. package/dist/core/slash-commands.js +53 -32
  283. package/dist/core/slash-commands.js.map +1 -1
  284. package/dist/core/system-prompt.d.ts.map +1 -1
  285. package/dist/core/system-prompt.js +25 -2
  286. package/dist/core/system-prompt.js.map +1 -1
  287. package/dist/core/tools/bash.d.ts.map +1 -1
  288. package/dist/core/tools/bash.js +11 -7
  289. package/dist/core/tools/bash.js.map +1 -1
  290. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  291. package/dist/core/tools/edit-diff.js +9 -4
  292. package/dist/core/tools/edit-diff.js.map +1 -1
  293. package/dist/core/tools/edit.d.ts.map +1 -1
  294. package/dist/core/tools/edit.js +4 -3
  295. package/dist/core/tools/edit.js.map +1 -1
  296. package/dist/core/tools/index.d.ts.map +1 -1
  297. package/dist/core/tools/index.js +3 -2
  298. package/dist/core/tools/index.js.map +1 -1
  299. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  300. package/dist/core/tools/output-accumulator.js +2 -1
  301. package/dist/core/tools/output-accumulator.js.map +1 -1
  302. package/dist/core/tools/read.d.ts.map +1 -1
  303. package/dist/core/tools/read.js +6 -2
  304. package/dist/core/tools/read.js.map +1 -1
  305. package/dist/core/tools/write.d.ts.map +1 -1
  306. package/dist/core/tools/write.js +2 -1
  307. package/dist/core/tools/write.js.map +1 -1
  308. package/dist/durable/durable-service.d.ts.map +1 -1
  309. package/dist/durable/durable-service.js +25 -18
  310. package/dist/durable/durable-service.js.map +1 -1
  311. package/dist/host/checkpoint-commit.d.ts.map +1 -1
  312. package/dist/host/checkpoint-commit.js +2 -1
  313. package/dist/host/checkpoint-commit.js.map +1 -1
  314. package/dist/host/manual-compaction.d.ts.map +1 -1
  315. package/dist/host/manual-compaction.js +2 -1
  316. package/dist/host/manual-compaction.js.map +1 -1
  317. package/dist/host/output-projection.d.ts +0 -13
  318. package/dist/host/output-projection.d.ts.map +1 -1
  319. package/dist/host/output-projection.js +16 -2
  320. package/dist/host/output-projection.js.map +1 -1
  321. package/dist/host/summary-retry.d.ts.map +1 -1
  322. package/dist/host/summary-retry.js +3 -2
  323. package/dist/host/summary-retry.js.map +1 -1
  324. package/dist/main.d.ts.map +1 -1
  325. package/dist/main.js +94 -58
  326. package/dist/main.js.map +1 -1
  327. package/dist/modes/interactive/components/agents-view.d.ts.map +1 -1
  328. package/dist/modes/interactive/components/agents-view.js +18 -15
  329. package/dist/modes/interactive/components/agents-view.js.map +1 -1
  330. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  331. package/dist/modes/interactive/components/assistant-message.js +6 -5
  332. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  333. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  334. package/dist/modes/interactive/components/bash-execution.js +12 -7
  335. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  336. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  337. package/dist/modes/interactive/components/bordered-loader.js +2 -1
  338. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  339. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  340. package/dist/modes/interactive/components/branch-summary-message.js +6 -5
  341. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  342. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  343. package/dist/modes/interactive/components/compaction-summary-message.js +9 -5
  344. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  345. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  346. package/dist/modes/interactive/components/config-selector.js +18 -15
  347. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  348. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
  349. package/dist/modes/interactive/components/custom-entry.js +2 -1
  350. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  351. package/dist/modes/interactive/components/dialog-editor.d.ts.map +1 -1
  352. package/dist/modes/interactive/components/dialog-editor.js +5 -4
  353. package/dist/modes/interactive/components/dialog-editor.js.map +1 -1
  354. package/dist/modes/interactive/components/dialog-input.d.ts.map +1 -1
  355. package/dist/modes/interactive/components/dialog-input.js +2 -1
  356. package/dist/modes/interactive/components/dialog-input.js.map +1 -1
  357. package/dist/modes/interactive/components/dialog-selector.d.ts.map +1 -1
  358. package/dist/modes/interactive/components/dialog-selector.js +4 -3
  359. package/dist/modes/interactive/components/dialog-selector.js.map +1 -1
  360. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  361. package/dist/modes/interactive/components/first-time-setup.js +11 -10
  362. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  363. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  364. package/dist/modes/interactive/components/footer.js +7 -4
  365. package/dist/modes/interactive/components/footer.js.map +1 -1
  366. package/dist/modes/interactive/components/index.d.ts +1 -0
  367. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  368. package/dist/modes/interactive/components/index.js +1 -0
  369. package/dist/modes/interactive/components/index.js.map +1 -1
  370. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  371. package/dist/modes/interactive/components/keybinding-hints.js +3 -2
  372. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  373. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  374. package/dist/modes/interactive/components/login-dialog.js +12 -11
  375. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  376. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
  377. package/dist/modes/interactive/components/mermaid.js +6 -2
  378. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  379. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  380. package/dist/modes/interactive/components/model-selector.js +28 -16
  381. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  382. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  383. package/dist/modes/interactive/components/oauth-selector.js +10 -9
  384. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  385. package/dist/modes/interactive/components/plugin-manager-entry.d.ts.map +1 -1
  386. package/dist/modes/interactive/components/plugin-manager-entry.js +22 -13
  387. package/dist/modes/interactive/components/plugin-manager-entry.js.map +1 -1
  388. package/dist/modes/interactive/components/plugin-selection-entry.d.ts.map +1 -1
  389. package/dist/modes/interactive/components/plugin-selection-entry.js +27 -12
  390. package/dist/modes/interactive/components/plugin-selection-entry.js.map +1 -1
  391. package/dist/modes/interactive/components/queue-manager-selector.d.ts +60 -0
  392. package/dist/modes/interactive/components/queue-manager-selector.d.ts.map +1 -0
  393. package/dist/modes/interactive/components/queue-manager-selector.js +166 -0
  394. package/dist/modes/interactive/components/queue-manager-selector.js.map +1 -0
  395. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  396. package/dist/modes/interactive/components/scoped-models-selector.js +16 -14
  397. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  398. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  399. package/dist/modes/interactive/components/session-selector.js +43 -31
  400. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  401. package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  402. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  403. package/dist/modes/interactive/components/settings-selector.js +113 -96
  404. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  405. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -1
  406. package/dist/modes/interactive/components/settings-submenu.js +5 -4
  407. package/dist/modes/interactive/components/settings-submenu.js.map +1 -1
  408. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  409. package/dist/modes/interactive/components/show-images-selector.js +3 -2
  410. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  411. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  412. package/dist/modes/interactive/components/skill-invocation-message.js +4 -3
  413. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  414. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  415. package/dist/modes/interactive/components/status-indicator.js +14 -5
  416. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  417. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  418. package/dist/modes/interactive/components/theme-selector.js +2 -1
  419. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  420. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  421. package/dist/modes/interactive/components/thinking-selector.js +11 -4
  422. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  423. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  424. package/dist/modes/interactive/components/tool-execution.js +8 -3
  425. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  426. package/dist/modes/interactive/components/tree-list.d.ts.map +1 -1
  427. package/dist/modes/interactive/components/tree-list.js +7 -6
  428. package/dist/modes/interactive/components/tree-list.js.map +1 -1
  429. package/dist/modes/interactive/components/tree-render.d.ts.map +1 -1
  430. package/dist/modes/interactive/components/tree-render.js +28 -23
  431. package/dist/modes/interactive/components/tree-render.js.map +1 -1
  432. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  433. package/dist/modes/interactive/components/tree-selector.js +9 -7
  434. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  435. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  436. package/dist/modes/interactive/components/user-message-selector.js +5 -4
  437. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  438. package/dist/modes/interactive/components/workflow-view.d.ts.map +1 -1
  439. package/dist/modes/interactive/components/workflow-view.js +36 -21
  440. package/dist/modes/interactive/components/workflow-view.js.map +1 -1
  441. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  442. package/dist/modes/interactive/external-editor.js +2 -1
  443. package/dist/modes/interactive/external-editor.js.map +1 -1
  444. package/dist/modes/interactive/interactive-auth.d.ts.map +1 -1
  445. package/dist/modes/interactive/interactive-auth.js +71 -40
  446. package/dist/modes/interactive/interactive-auth.js.map +1 -1
  447. package/dist/modes/interactive/interactive-commands.d.ts +1 -0
  448. package/dist/modes/interactive/interactive-commands.d.ts.map +1 -1
  449. package/dist/modes/interactive/interactive-commands.js +3 -0
  450. package/dist/modes/interactive/interactive-commands.js.map +1 -1
  451. package/dist/modes/interactive/interactive-dialog-ui.d.ts.map +1 -1
  452. package/dist/modes/interactive/interactive-dialog-ui.js +5 -5
  453. package/dist/modes/interactive/interactive-dialog-ui.js.map +1 -1
  454. package/dist/modes/interactive/interactive-format.d.ts.map +1 -1
  455. package/dist/modes/interactive/interactive-format.js +34 -18
  456. package/dist/modes/interactive/interactive-format.js.map +1 -1
  457. package/dist/modes/interactive/interactive-helpers.d.ts.map +1 -1
  458. package/dist/modes/interactive/interactive-helpers.js +7 -2
  459. package/dist/modes/interactive/interactive-helpers.js.map +1 -1
  460. package/dist/modes/interactive/interactive-mode.d.ts +4 -1
  461. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  462. package/dist/modes/interactive/interactive-mode.js +327 -243
  463. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  464. package/dist/modes/interactive/interactive-selectors.d.ts +9 -0
  465. package/dist/modes/interactive/interactive-selectors.d.ts.map +1 -1
  466. package/dist/modes/interactive/interactive-selectors.js +79 -25
  467. package/dist/modes/interactive/interactive-selectors.js.map +1 -1
  468. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  469. package/dist/modes/interactive/theme/theme-controller.js +5 -1
  470. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  471. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  472. package/dist/modes/interactive/theme/theme.js +26 -23
  473. package/dist/modes/interactive/theme/theme.js.map +1 -1
  474. package/dist/modes/json-event.d.ts.map +1 -1
  475. package/dist/modes/json-event.js +3 -2
  476. package/dist/modes/json-event.js.map +1 -1
  477. package/dist/modes/print-mode.d.ts.map +1 -1
  478. package/dist/modes/print-mode.js +3 -2
  479. package/dist/modes/print-mode.js.map +1 -1
  480. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  481. package/dist/modes/rpc/rpc-client.js +3 -2
  482. package/dist/modes/rpc/rpc-client.js.map +1 -1
  483. package/dist/package-manager-cli.d.ts.map +1 -1
  484. package/dist/package-manager-cli.js +28 -13
  485. package/dist/package-manager-cli.js.map +1 -1
  486. package/dist/plugins/ecosystem/catalog.d.ts.map +1 -1
  487. package/dist/plugins/ecosystem/catalog.js +3 -2
  488. package/dist/plugins/ecosystem/catalog.js.map +1 -1
  489. package/dist/plugins/ecosystem/cli.d.ts.map +1 -1
  490. package/dist/plugins/ecosystem/cli.js +2 -1
  491. package/dist/plugins/ecosystem/cli.js.map +1 -1
  492. package/dist/plugins/ecosystem/default-plugin-market.d.ts.map +1 -1
  493. package/dist/plugins/ecosystem/default-plugin-market.js +3 -2
  494. package/dist/plugins/ecosystem/default-plugin-market.js.map +1 -1
  495. package/dist/plugins/ecosystem/distribution.d.ts.map +1 -1
  496. package/dist/plugins/ecosystem/distribution.js +2 -1
  497. package/dist/plugins/ecosystem/distribution.js.map +1 -1
  498. package/dist/plugins/ecosystem/installer.d.ts.map +1 -1
  499. package/dist/plugins/ecosystem/installer.js +3 -2
  500. package/dist/plugins/ecosystem/installer.js.map +1 -1
  501. package/dist/plugins/ecosystem/node-disk-registry-source.d.ts.map +1 -1
  502. package/dist/plugins/ecosystem/node-disk-registry-source.js +20 -17
  503. package/dist/plugins/ecosystem/node-disk-registry-source.js.map +1 -1
  504. package/dist/plugins/ecosystem/node-distribution-host.d.ts.map +1 -1
  505. package/dist/plugins/ecosystem/node-distribution-host.js +35 -34
  506. package/dist/plugins/ecosystem/node-distribution-host.js.map +1 -1
  507. package/dist/plugins/ecosystem/node-npm-registry-source.d.ts.map +1 -1
  508. package/dist/plugins/ecosystem/node-npm-registry-source.js +35 -34
  509. package/dist/plugins/ecosystem/node-npm-registry-source.js.map +1 -1
  510. package/dist/plugins/ecosystem/node-package-install-host.d.ts.map +1 -1
  511. package/dist/plugins/ecosystem/node-package-install-host.js +9 -8
  512. package/dist/plugins/ecosystem/node-package-install-host.js.map +1 -1
  513. package/dist/plugins/ecosystem/node-package-install-persistence.d.ts.map +1 -1
  514. package/dist/plugins/ecosystem/node-package-install-persistence.js +4 -3
  515. package/dist/plugins/ecosystem/node-package-install-persistence.js.map +1 -1
  516. package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts.map +1 -1
  517. package/dist/plugins/ecosystem/node-plugin-bootstrap.js +21 -5
  518. package/dist/plugins/ecosystem/node-plugin-bootstrap.js.map +1 -1
  519. package/dist/plugins/ecosystem/node-plugin-trust-root.d.ts.map +1 -1
  520. package/dist/plugins/ecosystem/node-plugin-trust-root.js +10 -9
  521. package/dist/plugins/ecosystem/node-plugin-trust-root.js.map +1 -1
  522. package/dist/plugins/ecosystem/node-registry-source.d.ts.map +1 -1
  523. package/dist/plugins/ecosystem/node-registry-source.js +31 -30
  524. package/dist/plugins/ecosystem/node-registry-source.js.map +1 -1
  525. package/dist/plugins/ecosystem/node-release-package-source.d.ts.map +1 -1
  526. package/dist/plugins/ecosystem/node-release-package-source.js +30 -29
  527. package/dist/plugins/ecosystem/node-release-package-source.js.map +1 -1
  528. package/dist/plugins/ecosystem/node-tar-writer.d.ts.map +1 -1
  529. package/dist/plugins/ecosystem/node-tar-writer.js +11 -10
  530. package/dist/plugins/ecosystem/node-tar-writer.js.map +1 -1
  531. package/dist/plugins/ecosystem/node-url-package-source.d.ts.map +1 -1
  532. package/dist/plugins/ecosystem/node-url-package-source.js +21 -20
  533. package/dist/plugins/ecosystem/node-url-package-source.js.map +1 -1
  534. package/dist/plugins/ecosystem/plugin-acquisition.d.ts.map +1 -1
  535. package/dist/plugins/ecosystem/plugin-acquisition.js +3 -2
  536. package/dist/plugins/ecosystem/plugin-acquisition.js.map +1 -1
  537. package/dist/plugins/ecosystem/registry-cli-adapter.d.ts.map +1 -1
  538. package/dist/plugins/ecosystem/registry-cli-adapter.js +2 -1
  539. package/dist/plugins/ecosystem/registry-cli-adapter.js.map +1 -1
  540. package/dist/plugins/ecosystem/registry.d.ts.map +1 -1
  541. package/dist/plugins/ecosystem/registry.js +35 -32
  542. package/dist/plugins/ecosystem/registry.js.map +1 -1
  543. package/dist/plugins/ecosystem/resolver.d.ts.map +1 -1
  544. package/dist/plugins/ecosystem/resolver.js +3 -2
  545. package/dist/plugins/ecosystem/resolver.js.map +1 -1
  546. package/dist/plugins/ecosystem/selection-store.d.ts.map +1 -1
  547. package/dist/plugins/ecosystem/selection-store.js +11 -10
  548. package/dist/plugins/ecosystem/selection-store.js.map +1 -1
  549. package/dist/plugins/ecosystem/selection.d.ts.map +1 -1
  550. package/dist/plugins/ecosystem/selection.js +8 -7
  551. package/dist/plugins/ecosystem/selection.js.map +1 -1
  552. package/dist/plugins/ecosystem/state.d.ts.map +1 -1
  553. package/dist/plugins/ecosystem/state.js +24 -23
  554. package/dist/plugins/ecosystem/state.js.map +1 -1
  555. package/dist/plugins/ecosystem/updates.d.ts.map +1 -1
  556. package/dist/plugins/ecosystem/updates.js +5 -4
  557. package/dist/plugins/ecosystem/updates.js.map +1 -1
  558. package/dist/plugins/mcp-http.d.ts +0 -17
  559. package/dist/plugins/mcp-http.d.ts.map +1 -1
  560. package/dist/plugins/mcp-http.js +30 -7
  561. package/dist/plugins/mcp-http.js.map +1 -1
  562. package/dist/plugins/plugin-supervisor.d.ts.map +1 -1
  563. package/dist/plugins/plugin-supervisor.js +19 -1
  564. package/dist/plugins/plugin-supervisor.js.map +1 -1
  565. package/dist/profile/first-roles.d.ts.map +1 -1
  566. package/dist/profile/first-roles.js +10 -1
  567. package/dist/profile/first-roles.js.map +1 -1
  568. package/dist/profile/goal-plugin.d.ts.map +1 -1
  569. package/dist/profile/goal-plugin.js +24 -5
  570. package/dist/profile/goal-plugin.js.map +1 -1
  571. package/dist/profile/identity.d.ts.map +1 -1
  572. package/dist/profile/identity.js +7 -6
  573. package/dist/profile/identity.js.map +1 -1
  574. package/dist/profile/lock.d.ts.map +1 -1
  575. package/dist/profile/lock.js +15 -1
  576. package/dist/profile/lock.js.map +1 -1
  577. package/dist/profile/plan-plugin.d.ts.map +1 -1
  578. package/dist/profile/plan-plugin.js +26 -13
  579. package/dist/profile/plan-plugin.js.map +1 -1
  580. package/dist/profile/plugin-profiles.d.ts.map +1 -1
  581. package/dist/profile/plugin-profiles.js +2 -1
  582. package/dist/profile/plugin-profiles.js.map +1 -1
  583. package/dist/profile/policy-manifest.d.ts.map +1 -1
  584. package/dist/profile/policy-manifest.js +5 -4
  585. package/dist/profile/policy-manifest.js.map +1 -1
  586. package/dist/profile/profile-registry.d.ts +0 -12
  587. package/dist/profile/profile-registry.d.ts.map +1 -1
  588. package/dist/profile/profile-registry.js +14 -1
  589. package/dist/profile/profile-registry.js.map +1 -1
  590. package/dist/profile/role-catalog.d.ts +0 -1
  591. package/dist/profile/role-catalog.d.ts.map +1 -1
  592. package/dist/profile/role-catalog.js +17 -15
  593. package/dist/profile/role-catalog.js.map +1 -1
  594. package/dist/profile/role-orchestrator.d.ts.map +1 -1
  595. package/dist/profile/role-orchestrator.js +8 -7
  596. package/dist/profile/role-orchestrator.js.map +1 -1
  597. package/dist/profile/role-runner.d.ts.map +1 -1
  598. package/dist/profile/role-runner.js +3 -2
  599. package/dist/profile/role-runner.js.map +1 -1
  600. package/dist/profile/root-facade.d.ts.map +1 -1
  601. package/dist/profile/root-facade.js +2 -1
  602. package/dist/profile/root-facade.js.map +1 -1
  603. package/dist/profile/skill-discovery-wiring.d.ts.map +1 -1
  604. package/dist/profile/skill-discovery-wiring.js +7 -2
  605. package/dist/profile/skill-discovery-wiring.js.map +1 -1
  606. package/dist/profile/state-store.d.ts.map +1 -1
  607. package/dist/profile/state-store.js +13 -9
  608. package/dist/profile/state-store.js.map +1 -1
  609. package/dist/profile/todo-plugin.d.ts.map +1 -1
  610. package/dist/profile/todo-plugin.js +9 -4
  611. package/dist/profile/todo-plugin.js.map +1 -1
  612. package/dist/profiles/builtin-suites.d.ts +13 -6
  613. package/dist/profiles/builtin-suites.d.ts.map +1 -1
  614. package/dist/profiles/builtin-suites.js +15 -6
  615. package/dist/profiles/builtin-suites.js.map +1 -1
  616. package/dist/profiles/suite-loader.d.ts +25 -1
  617. package/dist/profiles/suite-loader.d.ts.map +1 -1
  618. package/dist/profiles/suite-loader.js +34 -9
  619. package/dist/profiles/suite-loader.js.map +1 -1
  620. package/dist/remote/server-entry.d.ts.map +1 -1
  621. package/dist/remote/server-entry.js +3 -2
  622. package/dist/remote/server-entry.js.map +1 -1
  623. package/dist/remote/session-source.d.ts.map +1 -1
  624. package/dist/remote/session-source.js +8 -4
  625. package/dist/remote/session-source.js.map +1 -1
  626. package/dist/share/session-share.d.ts.map +1 -1
  627. package/dist/share/session-share.js +14 -2
  628. package/dist/share/session-share.js.map +1 -1
  629. package/dist/testing/plugin-testkit.d.ts.map +1 -1
  630. package/dist/testing/plugin-testkit.js +4 -3
  631. package/dist/testing/plugin-testkit.js.map +1 -1
  632. package/dist/testing/runtime-delivery-queue.d.ts.map +1 -1
  633. package/dist/testing/runtime-delivery-queue.js +2 -1
  634. package/dist/testing/runtime-delivery-queue.js.map +1 -1
  635. package/dist/testing/session-plugin-testkit.d.ts.map +1 -1
  636. package/dist/testing/session-plugin-testkit.js +10 -7
  637. package/dist/testing/session-plugin-testkit.js.map +1 -1
  638. package/dist/utils/ansi.d.ts.map +1 -1
  639. package/dist/utils/ansi.js +2 -1
  640. package/dist/utils/ansi.js.map +1 -1
  641. package/dist/utils/clipboard.d.ts.map +1 -1
  642. package/dist/utils/clipboard.js +7 -6
  643. package/dist/utils/clipboard.js.map +1 -1
  644. package/dist/utils/image-resize-worker.d.ts.map +1 -1
  645. package/dist/utils/image-resize-worker.js +3 -2
  646. package/dist/utils/image-resize-worker.js.map +1 -1
  647. package/dist/utils/shell.d.ts.map +1 -1
  648. package/dist/utils/shell.js +9 -8
  649. package/dist/utils/shell.js.map +1 -1
  650. package/dist/utils/tools-manager.d.ts.map +1 -1
  651. package/dist/utils/tools-manager.js +23 -13
  652. package/dist/utils/tools-manager.js.map +1 -1
  653. package/dist/utils/version-check.d.ts.map +1 -1
  654. package/dist/utils/version-check.js +5 -1
  655. package/dist/utils/version-check.js.map +1 -1
  656. package/docs/keybindings.md +3 -0
  657. package/docs/quickstart.md +1 -1
  658. package/docs/settings.md +1 -0
  659. package/docs/terminal-setup.md +2 -3
  660. package/docs/usage.md +6 -5
  661. package/examples/extensions/with-deps/package-lock.json +2 -2
  662. package/examples/extensions/with-deps/package.json +1 -1
  663. package/examples/extensions/with-deps/plugin.json +1 -1
  664. package/package.json +1 -1
  665. package/dist/bundle/chunks/chunk-EALJ5DDX.js +0 -1452
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-profiles.d.ts","sourceRoot":"","sources":["../../src/profile/plugin-profiles.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACX,WAAW,EACX,gBAAgB,EAEhB,mBAAmB,EACnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAmB,KAAK,uBAAuB,EAAE,KAAK,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAEjH,MAAM,MAAM,wBAAwB,GACjC,aAAa,GACb,YAAY,GACZ,iBAAiB,GACjB,iBAAiB,GACjB,iBAAiB,GACjB,kBAAkB,GAClB,cAAc,GACd,aAAa,GACb,iBAAiB,GACjB,uBAAuB,GACvB,kBAAkB,GAClB,gBAAgB,CAAC;AAEpB,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,EAAE,EAAE,wBAAwB,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,gCAAgC,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAE1F,MAAM,MAAM,gCAAgC,GACzC;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACtE;IACA,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9C,GACD;IACA,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CAAC;IACzC,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;IACzC,QAAQ,CAAC,QAAQ,CAAC,EAAE,uBAAuB,CAAC;CAC3C,CAAC;AAuCL,wBAAgB,2BAA2B,IAAI,SAAS,sBAAsB,EAAE,CAE/E;AAED,sFAAsF;AACtF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,wBAAwB,CAE3F;AAED,gFAAgF;AAChF,wBAAgB,4BAA4B,IAAI,SAAS,gBAAgB,EAAE,CAO1E;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,oBAAoB,EAAE,CAOlG;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACpD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,iEAAiE;IACjE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC3D,yEAAyE;IACzE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,gCAAgC,CAAC;CAC9D,GAAG,gCAAgC,CA2FnC","sourcesContent":["import { VERSION } from \"../config.ts\";\nimport { comparePluginVersionsV1 } from \"../plugins/ecosystem/catalog.ts\";\nimport { resolvePluginProfileV1 } from \"../plugins/ecosystem/resolver.ts\";\nimport type {\n\tHostFactsV1,\n\tPluginManifestV1,\n\tPluginResolutionV1,\n\tProfileResolutionV1,\n} from \"../plugins/ecosystem/types.ts\";\nimport { assembleProfile, type ProfileAssemblyResultV1, type VerifiedToolPluginV1 } from \"./profile-assembly.ts\";\n\nexport type BuiltinPluginProfileIdV1 =\n\t| \"coding-core\"\n\t| \"desktop-qa\"\n\t| \"desktop-observe\"\n\t| \"desktop-control\"\n\t| \"lsp-diagnostics\"\n\t| \"image-generation\"\n\t| \"process-exec\"\n\t| \"test-runner\"\n\t| \"workspace-files\"\n\t| \"workspace-files-write\"\n\t| \"formatter-linter\"\n\t| \"git-repository\";\n\nexport interface BuiltinPluginProfileV1 {\n\treadonly id: BuiltinPluginProfileIdV1;\n\treadonly version: string;\n\treadonly pluginIds: readonly string[];\n}\n\n/**\n * Host-owned manifest replacements for installed, verified package versions.\n *\n * Builtin manifests remain the default. A host may explicitly provide one\n * replacement per builtin plugin ID when a staged/verified/active install is\n * selected for a new Profile. The resolver never discovers files or chooses a\n * version implicitly; the replacement is part of the resulting Profile\n * identity and must still pass normal compatibility and verification checks.\n */\nexport type BuiltinPluginManifestOverridesV1 = Readonly<Record<string, PluginManifestV1>>;\n\nexport type BuiltinPluginProfileResolutionV1 =\n\t| { readonly status: \"not_found\"; readonly profileId: string }\n\t| { readonly status: \"host_facts_required\"; readonly profileId: string }\n\t| {\n\t\t\treadonly status: \"invalid_selection\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly unknownPluginIds: readonly string[];\n\t\t\treadonly duplicatePluginIds: readonly string[];\n\t }\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profile: BuiltinPluginProfileV1;\n\t\t\treadonly resolution: ProfileResolutionV1;\n\t\t\treadonly assembly?: ProfileAssemblyResultV1;\n\t };\n\n// D-075 S3: every first-party category-A plugin now ships as an independent\n// package under `plugins/` with the `agent-forge.plugin.<name>` id domain\n// (design §4.1). No embedded manifests remain; profiles resolve through the\n// install store (host-provided `manifestOverrides` from active bindings).\nconst manifests: Readonly<Record<string, PluginManifestV1>> = Object.freeze({});\n\nconst profiles: readonly BuiltinPluginProfileV1[] = Object.freeze([\n\t{ id: \"coding-core\", version: \"1\", pluginIds: [] },\n\t{\n\t\tid: \"desktop-qa\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"desktop-observe\", version: \"1\", pluginIds: [\"agent-forge.plugin.desktop-windows-observe\"] },\n\t{\n\t\tid: \"desktop-control\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"lsp-diagnostics\", version: \"1\", pluginIds: [\"agent-forge.plugin.lsp-diagnostics\"] },\n\t{ id: \"image-generation\", version: \"1\", pluginIds: [\"agent-forge.plugin.image-generation\"] },\n\t{ id: \"process-exec\", version: \"1\", pluginIds: [\"agent-forge.plugin.process-exec\"] },\n\t{ id: \"test-runner\", version: \"1\", pluginIds: [\"agent-forge.plugin.test-runner\"] },\n\t{ id: \"workspace-files\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files\"] },\n\t{ id: \"workspace-files-write\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files-write\"] },\n\t{\n\t\t// D-075 S2: the plugin code ships as the independent package\n\t\t// `agent-forge.plugin.formatter-linter` (design §4.1 id domain); this\n\t\t// Profile stays the stable user entry (`--plugin-profile formatter-linter`)\n\t\t// and resolves through the install store, not an embedded manifest.\n\t\tid: \"formatter-linter\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.formatter-linter\"],\n\t},\n\t{ id: \"git-repository\", version: \"1\", pluginIds: [\"agent-forge.plugin.git-repository\"] },\n]);\n\nexport function listBuiltinPluginProfilesV1(): readonly BuiltinPluginProfileV1[] {\n\treturn profiles;\n}\n\n/** True when the id names a builtin plugin profile (the CLI selection vocabulary). */\nexport function isBuiltinPluginProfileIdV1(value: string): value is BuiltinPluginProfileIdV1 {\n\treturn profiles.some((profile) => profile.id === value);\n}\n\n/** Return the first-party manifest projection for catalog and selection UIs. */\nexport function listBuiltinPluginManifestsV1(): readonly PluginManifestV1[] {\n\treturn Object.freeze(\n\t\tObject.values(manifests).sort((left, right) => {\n\t\t\tconst idOrder = `${left.id}@${left.pluginVersion}`.localeCompare(`${right.id}@${right.pluginVersion}`);\n\t\t\treturn idOrder === 0 ? comparePluginVersionsV1(left.pluginVersion, right.pluginVersion) : idOrder;\n\t\t}),\n\t);\n}\n\n/**\n * First-party plugins of an explicitly selected Profile are trusted by\n * default: builtins ship with the product and the user chose the Profile\n * explicitly. Installed third-party versions are still verified through the\n * active-binding resolver; host-injected verifiedPlugins always win.\n */\nexport function defaultBuiltinVerifiedPluginsV1(profileId: string): readonly VerifiedToolPluginV1[] {\n\tconst profile = profiles.find((candidate) => candidate.id === profileId);\n\tif (profile === undefined) return [];\n\treturn profile.pluginIds.flatMap((pluginId) => {\n\t\tconst manifest = manifests[pluginId];\n\t\treturn manifest === undefined ? [] : [{ pluginId: manifest.id, version: manifest.pluginVersion }];\n\t});\n}\n\nexport function resolveBuiltinPluginProfileV1(input: {\n\treadonly profileId: string;\n\treadonly host: HostFactsV1;\n\t/** Optional subset of the selected builtin Profile's plugins. */\n\treadonly selectedPluginIds?: readonly string[];\n\treadonly disabledPluginIds?: readonly string[];\n\treadonly verifiedPlugins?: readonly VerifiedToolPluginV1[];\n\t/** Explicit host-selected active manifests; never inferred from disk. */\n\treadonly manifestOverrides?: BuiltinPluginManifestOverridesV1;\n}): BuiltinPluginProfileResolutionV1 {\n\tconst profile = profiles.find((candidate) => candidate.id === input.profileId);\n\tif (profile === undefined) return { status: \"not_found\", profileId: input.profileId };\n\tconst requestedPluginIds = input.selectedPluginIds;\n\tconst requestedDisabledPluginIds = input.disabledPluginIds;\n\tif (requestedPluginIds !== undefined || requestedDisabledPluginIds !== undefined) {\n\t\tconst availablePluginIds = new Set(profile.pluginIds);\n\t\tconst duplicatePluginIds: string[] = [];\n\t\tconst unknownPluginIds: string[] = [];\n\t\tfor (const requestedIds of [requestedPluginIds ?? [], requestedDisabledPluginIds ?? []]) {\n\t\t\tconst seen = new Set<string>();\n\t\t\tfor (const pluginId of requestedIds) {\n\t\t\t\tif (!availablePluginIds.has(pluginId) && !unknownPluginIds.includes(pluginId))\n\t\t\t\t\tunknownPluginIds.push(pluginId);\n\t\t\t\tif (seen.has(pluginId) && !duplicatePluginIds.includes(pluginId)) duplicatePluginIds.push(pluginId);\n\t\t\t\tseen.add(pluginId);\n\t\t\t}\n\t\t}\n\t\tif (unknownPluginIds.length > 0 || duplicatePluginIds.length > 0) {\n\t\t\treturn {\n\t\t\t\tstatus: \"invalid_selection\",\n\t\t\t\tprofileId: input.profileId,\n\t\t\t\tunknownPluginIds: Object.freeze([...new Set(unknownPluginIds)]),\n\t\t\t\tduplicatePluginIds: Object.freeze(duplicatePluginIds),\n\t\t\t};\n\t\t}\n\t}\n\tconst selected =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile.pluginIds\n\t\t\t: profile.pluginIds.filter((pluginId) => requestedPluginIds.includes(pluginId));\n\tconst selectedProfile =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile\n\t\t\t: Object.freeze({ ...profile, pluginIds: Object.freeze([...selected]) });\n\tconst disabled = new Set(input.disabledPluginIds ?? []);\n\t// D-075 S2: a Profile plugin without a builtin manifest and without a\n\t// host-installed override is a structured miss, not a startup failure. The\n\t// plugin is omitted from the resolved manifest and runtime bindings; the\n\t// remaining Profile plugins resolve normally (soft degradation).\n\tconst manifestByPluginId = new Map(\n\t\tselectedProfile.pluginIds.map((pluginId) => [pluginId, manifestFor(pluginId, input.manifestOverrides)] as const),\n\t);\n\tconst missingPluginIds = selectedProfile.pluginIds.filter(\n\t\t(pluginId) => manifestByPluginId.get(pluginId) === undefined,\n\t);\n\tconst resolution = resolvePluginProfileV1({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tplugins: selectedProfile.pluginIds.flatMap((pluginId) => {\n\t\t\tconst manifest = manifestByPluginId.get(pluginId);\n\t\t\treturn manifest === undefined\n\t\t\t\t? []\n\t\t\t\t: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmanifest,\n\t\t\t\t\t\t\t// A user-disabled plugin must not block the remaining profile. It is\n\t\t\t\t\t\t\t// still represented in the resolution diagnostics, but is omitted from\n\t\t\t\t\t\t\t// the active resolved manifest and runtime bindings.\n\t\t\t\t\t\t\trequired: !disabled.has(pluginId),\n\t\t\t\t\t\t\tdisabled: disabled.has(pluginId),\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t}),\n\t\thost: input.host,\n\t\t// The host's own version enforces each manifest's minHostVersion floor\n\t\t// at the single builtin profile resolution funnel used by production\n\t\t// loading paths.\n\t\thostVersion: VERSION,\n\t});\n\tconst merged = mergeMissingPluginResolutionsV1(resolution, missingPluginIds, disabled);\n\tif (merged.status !== \"ready\") return { status: \"resolved\", profile: selectedProfile, resolution: merged };\n\tconst resolvedPlugins = merged.resolvedManifest.plugins.map((plugin) => ({\n\t\tpluginId: plugin.pluginId,\n\t\tpluginVersion: plugin.pluginVersion,\n\t\tcapabilityRefs: plugin.capabilityRefs,\n\t\t...(plugin.selectedAdapter === undefined ? {} : { selectedAdapter: plugin.selectedAdapter }),\n\t}));\n\tconst verifiedPlugins = input.verifiedPlugins ?? [];\n\tconst assembly = assembleProfile({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tresolvedPlugins,\n\t\tverifiedPlugins,\n\t});\n\treturn {\n\t\tstatus: \"resolved\",\n\t\tprofile: selectedProfile,\n\t\tresolution: merged,\n\t\tassembly,\n\t};\n}\n\nfunction manifestFor(\n\tpluginId: string,\n\toverrides: BuiltinPluginManifestOverridesV1 | undefined,\n): PluginManifestV1 | undefined {\n\tconst manifest = overrides?.[pluginId] ?? manifests[pluginId];\n\t// A mismatched override stays a hard host error: the host selected it\n\t// explicitly, so silence would hide an identity bug. A plain absent\n\t// manifest (no builtin, no installed override) is the structured miss.\n\tif (manifest !== undefined && manifest.id !== pluginId)\n\t\tthrow new Error(`builtin manifest override does not match plugin ${pluginId}`);\n\treturn manifest;\n}\n\n/**\n * Merge structured `manifest_missing` resolutions for Profile plugins that\n * have no builtin manifest and no installed override into the resolver\n * result. Missing plugins never block the Profile (soft degradation): the\n * remaining diagnostics and the resolved manifest stay exactly what the\n * resolver produced, and the merged plugin list keeps the resolver's\n * deterministic id sort.\n */\nfunction mergeMissingPluginResolutionsV1(\n\tresolution: ProfileResolutionV1,\n\tmissingPluginIds: readonly string[],\n\tdisabled: ReadonlySet<string>,\n): ProfileResolutionV1 {\n\tif (missingPluginIds.length === 0) return resolution;\n\tconst missing: PluginResolutionV1[] = missingPluginIds.map((pluginId) => ({\n\t\tpluginId,\n\t\tpluginVersion: \"\",\n\t\trequired: !disabled.has(pluginId),\n\t\tstatus: \"manifest-missing\",\n\t\tdiagnostics: [\n\t\t\t{\n\t\t\t\tcode: \"manifest_missing\",\n\t\t\t\tmessage: `Plugin ${pluginId} has no builtin manifest and no installed active override; the plugin is omitted from this profile (install it with agent-forge plugin install)`,\n\t\t\t},\n\t\t],\n\t}));\n\tconst plugins = [...resolution.plugins, ...missing].sort((left, right) =>\n\t\tleft.pluginId.localeCompare(right.pluginId),\n\t);\n\treturn Object.freeze({\n\t\t...resolution,\n\t\tplugins: Object.freeze(plugins),\n\t\tdiagnostics: Object.freeze(plugins.flatMap((plugin) => plugin.diagnostics)),\n\t});\n}\n"]}
1
+ {"version":3,"file":"plugin-profiles.d.ts","sourceRoot":"","sources":["../../src/profile/plugin-profiles.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACX,WAAW,EACX,gBAAgB,EAEhB,mBAAmB,EACnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAmB,KAAK,uBAAuB,EAAE,KAAK,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAEjH,MAAM,MAAM,wBAAwB,GACjC,aAAa,GACb,YAAY,GACZ,iBAAiB,GACjB,iBAAiB,GACjB,iBAAiB,GACjB,kBAAkB,GAClB,cAAc,GACd,aAAa,GACb,iBAAiB,GACjB,uBAAuB,GACvB,kBAAkB,GAClB,gBAAgB,CAAC;AAEpB,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,EAAE,EAAE,wBAAwB,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,gCAAgC,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAE1F,MAAM,MAAM,gCAAgC,GACzC;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACtE;IACA,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9C,GACD;IACA,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CAAC;IACzC,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;IACzC,QAAQ,CAAC,QAAQ,CAAC,EAAE,uBAAuB,CAAC;CAC3C,CAAC;AAuCL,wBAAgB,2BAA2B,IAAI,SAAS,sBAAsB,EAAE,CAE/E;AAED,sFAAsF;AACtF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,wBAAwB,CAE3F;AAED,gFAAgF;AAChF,wBAAgB,4BAA4B,IAAI,SAAS,gBAAgB,EAAE,CAO1E;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,oBAAoB,EAAE,CAOlG;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACpD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,iEAAiE;IACjE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC3D,yEAAyE;IACzE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,gCAAgC,CAAC;CAC9D,GAAG,gCAAgC,CA2FnC","sourcesContent":["import { VERSION } from \"../config.ts\";\nimport { t } from \"../core/i18n/index.ts\";\nimport { comparePluginVersionsV1 } from \"../plugins/ecosystem/catalog.ts\";\nimport { resolvePluginProfileV1 } from \"../plugins/ecosystem/resolver.ts\";\nimport type {\n\tHostFactsV1,\n\tPluginManifestV1,\n\tPluginResolutionV1,\n\tProfileResolutionV1,\n} from \"../plugins/ecosystem/types.ts\";\nimport { assembleProfile, type ProfileAssemblyResultV1, type VerifiedToolPluginV1 } from \"./profile-assembly.ts\";\n\nexport type BuiltinPluginProfileIdV1 =\n\t| \"coding-core\"\n\t| \"desktop-qa\"\n\t| \"desktop-observe\"\n\t| \"desktop-control\"\n\t| \"lsp-diagnostics\"\n\t| \"image-generation\"\n\t| \"process-exec\"\n\t| \"test-runner\"\n\t| \"workspace-files\"\n\t| \"workspace-files-write\"\n\t| \"formatter-linter\"\n\t| \"git-repository\";\n\nexport interface BuiltinPluginProfileV1 {\n\treadonly id: BuiltinPluginProfileIdV1;\n\treadonly version: string;\n\treadonly pluginIds: readonly string[];\n}\n\n/**\n * Host-owned manifest replacements for installed, verified package versions.\n *\n * Builtin manifests remain the default. A host may explicitly provide one\n * replacement per builtin plugin ID when a staged/verified/active install is\n * selected for a new Profile. The resolver never discovers files or chooses a\n * version implicitly; the replacement is part of the resulting Profile\n * identity and must still pass normal compatibility and verification checks.\n */\nexport type BuiltinPluginManifestOverridesV1 = Readonly<Record<string, PluginManifestV1>>;\n\nexport type BuiltinPluginProfileResolutionV1 =\n\t| { readonly status: \"not_found\"; readonly profileId: string }\n\t| { readonly status: \"host_facts_required\"; readonly profileId: string }\n\t| {\n\t\t\treadonly status: \"invalid_selection\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly unknownPluginIds: readonly string[];\n\t\t\treadonly duplicatePluginIds: readonly string[];\n\t }\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profile: BuiltinPluginProfileV1;\n\t\t\treadonly resolution: ProfileResolutionV1;\n\t\t\treadonly assembly?: ProfileAssemblyResultV1;\n\t };\n\n// D-075 S3: every first-party category-A plugin now ships as an independent\n// package under `plugins/` with the `agent-forge.plugin.<name>` id domain\n// (design §4.1). No embedded manifests remain; profiles resolve through the\n// install store (host-provided `manifestOverrides` from active bindings).\nconst manifests: Readonly<Record<string, PluginManifestV1>> = Object.freeze({});\n\nconst profiles: readonly BuiltinPluginProfileV1[] = Object.freeze([\n\t{ id: \"coding-core\", version: \"1\", pluginIds: [] },\n\t{\n\t\tid: \"desktop-qa\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"desktop-observe\", version: \"1\", pluginIds: [\"agent-forge.plugin.desktop-windows-observe\"] },\n\t{\n\t\tid: \"desktop-control\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"lsp-diagnostics\", version: \"1\", pluginIds: [\"agent-forge.plugin.lsp-diagnostics\"] },\n\t{ id: \"image-generation\", version: \"1\", pluginIds: [\"agent-forge.plugin.image-generation\"] },\n\t{ id: \"process-exec\", version: \"1\", pluginIds: [\"agent-forge.plugin.process-exec\"] },\n\t{ id: \"test-runner\", version: \"1\", pluginIds: [\"agent-forge.plugin.test-runner\"] },\n\t{ id: \"workspace-files\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files\"] },\n\t{ id: \"workspace-files-write\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files-write\"] },\n\t{\n\t\t// D-075 S2: the plugin code ships as the independent package\n\t\t// `agent-forge.plugin.formatter-linter` (design §4.1 id domain); this\n\t\t// Profile stays the stable user entry (`--plugin-profile formatter-linter`)\n\t\t// and resolves through the install store, not an embedded manifest.\n\t\tid: \"formatter-linter\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.formatter-linter\"],\n\t},\n\t{ id: \"git-repository\", version: \"1\", pluginIds: [\"agent-forge.plugin.git-repository\"] },\n]);\n\nexport function listBuiltinPluginProfilesV1(): readonly BuiltinPluginProfileV1[] {\n\treturn profiles;\n}\n\n/** True when the id names a builtin plugin profile (the CLI selection vocabulary). */\nexport function isBuiltinPluginProfileIdV1(value: string): value is BuiltinPluginProfileIdV1 {\n\treturn profiles.some((profile) => profile.id === value);\n}\n\n/** Return the first-party manifest projection for catalog and selection UIs. */\nexport function listBuiltinPluginManifestsV1(): readonly PluginManifestV1[] {\n\treturn Object.freeze(\n\t\tObject.values(manifests).sort((left, right) => {\n\t\t\tconst idOrder = `${left.id}@${left.pluginVersion}`.localeCompare(`${right.id}@${right.pluginVersion}`);\n\t\t\treturn idOrder === 0 ? comparePluginVersionsV1(left.pluginVersion, right.pluginVersion) : idOrder;\n\t\t}),\n\t);\n}\n\n/**\n * First-party plugins of an explicitly selected Profile are trusted by\n * default: builtins ship with the product and the user chose the Profile\n * explicitly. Installed third-party versions are still verified through the\n * active-binding resolver; host-injected verifiedPlugins always win.\n */\nexport function defaultBuiltinVerifiedPluginsV1(profileId: string): readonly VerifiedToolPluginV1[] {\n\tconst profile = profiles.find((candidate) => candidate.id === profileId);\n\tif (profile === undefined) return [];\n\treturn profile.pluginIds.flatMap((pluginId) => {\n\t\tconst manifest = manifests[pluginId];\n\t\treturn manifest === undefined ? [] : [{ pluginId: manifest.id, version: manifest.pluginVersion }];\n\t});\n}\n\nexport function resolveBuiltinPluginProfileV1(input: {\n\treadonly profileId: string;\n\treadonly host: HostFactsV1;\n\t/** Optional subset of the selected builtin Profile's plugins. */\n\treadonly selectedPluginIds?: readonly string[];\n\treadonly disabledPluginIds?: readonly string[];\n\treadonly verifiedPlugins?: readonly VerifiedToolPluginV1[];\n\t/** Explicit host-selected active manifests; never inferred from disk. */\n\treadonly manifestOverrides?: BuiltinPluginManifestOverridesV1;\n}): BuiltinPluginProfileResolutionV1 {\n\tconst profile = profiles.find((candidate) => candidate.id === input.profileId);\n\tif (profile === undefined) return { status: \"not_found\", profileId: input.profileId };\n\tconst requestedPluginIds = input.selectedPluginIds;\n\tconst requestedDisabledPluginIds = input.disabledPluginIds;\n\tif (requestedPluginIds !== undefined || requestedDisabledPluginIds !== undefined) {\n\t\tconst availablePluginIds = new Set(profile.pluginIds);\n\t\tconst duplicatePluginIds: string[] = [];\n\t\tconst unknownPluginIds: string[] = [];\n\t\tfor (const requestedIds of [requestedPluginIds ?? [], requestedDisabledPluginIds ?? []]) {\n\t\t\tconst seen = new Set<string>();\n\t\t\tfor (const pluginId of requestedIds) {\n\t\t\t\tif (!availablePluginIds.has(pluginId) && !unknownPluginIds.includes(pluginId))\n\t\t\t\t\tunknownPluginIds.push(pluginId);\n\t\t\t\tif (seen.has(pluginId) && !duplicatePluginIds.includes(pluginId)) duplicatePluginIds.push(pluginId);\n\t\t\t\tseen.add(pluginId);\n\t\t\t}\n\t\t}\n\t\tif (unknownPluginIds.length > 0 || duplicatePluginIds.length > 0) {\n\t\t\treturn {\n\t\t\t\tstatus: \"invalid_selection\",\n\t\t\t\tprofileId: input.profileId,\n\t\t\t\tunknownPluginIds: Object.freeze([...new Set(unknownPluginIds)]),\n\t\t\t\tduplicatePluginIds: Object.freeze(duplicatePluginIds),\n\t\t\t};\n\t\t}\n\t}\n\tconst selected =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile.pluginIds\n\t\t\t: profile.pluginIds.filter((pluginId) => requestedPluginIds.includes(pluginId));\n\tconst selectedProfile =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile\n\t\t\t: Object.freeze({ ...profile, pluginIds: Object.freeze([...selected]) });\n\tconst disabled = new Set(input.disabledPluginIds ?? []);\n\t// D-075 S2: a Profile plugin without a builtin manifest and without a\n\t// host-installed override is a structured miss, not a startup failure. The\n\t// plugin is omitted from the resolved manifest and runtime bindings; the\n\t// remaining Profile plugins resolve normally (soft degradation).\n\tconst manifestByPluginId = new Map(\n\t\tselectedProfile.pluginIds.map((pluginId) => [pluginId, manifestFor(pluginId, input.manifestOverrides)] as const),\n\t);\n\tconst missingPluginIds = selectedProfile.pluginIds.filter(\n\t\t(pluginId) => manifestByPluginId.get(pluginId) === undefined,\n\t);\n\tconst resolution = resolvePluginProfileV1({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tplugins: selectedProfile.pluginIds.flatMap((pluginId) => {\n\t\t\tconst manifest = manifestByPluginId.get(pluginId);\n\t\t\treturn manifest === undefined\n\t\t\t\t? []\n\t\t\t\t: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmanifest,\n\t\t\t\t\t\t\t// A user-disabled plugin must not block the remaining profile. It is\n\t\t\t\t\t\t\t// still represented in the resolution diagnostics, but is omitted from\n\t\t\t\t\t\t\t// the active resolved manifest and runtime bindings.\n\t\t\t\t\t\t\trequired: !disabled.has(pluginId),\n\t\t\t\t\t\t\tdisabled: disabled.has(pluginId),\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t}),\n\t\thost: input.host,\n\t\t// The host's own version enforces each manifest's minHostVersion floor\n\t\t// at the single builtin profile resolution funnel used by production\n\t\t// loading paths.\n\t\thostVersion: VERSION,\n\t});\n\tconst merged = mergeMissingPluginResolutionsV1(resolution, missingPluginIds, disabled);\n\tif (merged.status !== \"ready\") return { status: \"resolved\", profile: selectedProfile, resolution: merged };\n\tconst resolvedPlugins = merged.resolvedManifest.plugins.map((plugin) => ({\n\t\tpluginId: plugin.pluginId,\n\t\tpluginVersion: plugin.pluginVersion,\n\t\tcapabilityRefs: plugin.capabilityRefs,\n\t\t...(plugin.selectedAdapter === undefined ? {} : { selectedAdapter: plugin.selectedAdapter }),\n\t}));\n\tconst verifiedPlugins = input.verifiedPlugins ?? [];\n\tconst assembly = assembleProfile({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tresolvedPlugins,\n\t\tverifiedPlugins,\n\t});\n\treturn {\n\t\tstatus: \"resolved\",\n\t\tprofile: selectedProfile,\n\t\tresolution: merged,\n\t\tassembly,\n\t};\n}\n\nfunction manifestFor(\n\tpluginId: string,\n\toverrides: BuiltinPluginManifestOverridesV1 | undefined,\n): PluginManifestV1 | undefined {\n\tconst manifest = overrides?.[pluginId] ?? manifests[pluginId];\n\t// A mismatched override stays a hard host error: the host selected it\n\t// explicitly, so silence would hide an identity bug. A plain absent\n\t// manifest (no builtin, no installed override) is the structured miss.\n\tif (manifest !== undefined && manifest.id !== pluginId)\n\t\tthrow new Error(t(\"builtin manifest override does not match plugin {pluginId}\", { pluginId }));\n\treturn manifest;\n}\n\n/**\n * Merge structured `manifest_missing` resolutions for Profile plugins that\n * have no builtin manifest and no installed override into the resolver\n * result. Missing plugins never block the Profile (soft degradation): the\n * remaining diagnostics and the resolved manifest stay exactly what the\n * resolver produced, and the merged plugin list keeps the resolver's\n * deterministic id sort.\n */\nfunction mergeMissingPluginResolutionsV1(\n\tresolution: ProfileResolutionV1,\n\tmissingPluginIds: readonly string[],\n\tdisabled: ReadonlySet<string>,\n): ProfileResolutionV1 {\n\tif (missingPluginIds.length === 0) return resolution;\n\tconst missing: PluginResolutionV1[] = missingPluginIds.map((pluginId) => ({\n\t\tpluginId,\n\t\tpluginVersion: \"\",\n\t\trequired: !disabled.has(pluginId),\n\t\tstatus: \"manifest-missing\",\n\t\tdiagnostics: [\n\t\t\t{\n\t\t\t\tcode: \"manifest_missing\",\n\t\t\t\tmessage: `Plugin ${pluginId} has no builtin manifest and no installed active override; the plugin is omitted from this profile (install it with agent-forge plugin install)`,\n\t\t\t},\n\t\t],\n\t}));\n\tconst plugins = [...resolution.plugins, ...missing].sort((left, right) =>\n\t\tleft.pluginId.localeCompare(right.pluginId),\n\t);\n\treturn Object.freeze({\n\t\t...resolution,\n\t\tplugins: Object.freeze(plugins),\n\t\tdiagnostics: Object.freeze(plugins.flatMap((plugin) => plugin.diagnostics)),\n\t});\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { VERSION } from "../config.js";
2
+ import { t } from "../core/i18n/index.js";
2
3
  import { comparePluginVersionsV1 } from "../plugins/ecosystem/catalog.js";
3
4
  import { resolvePluginProfileV1 } from "../plugins/ecosystem/resolver.js";
4
5
  import { assembleProfile } from "./profile-assembly.js";
@@ -161,7 +162,7 @@ function manifestFor(pluginId, overrides) {
161
162
  // explicitly, so silence would hide an identity bug. A plain absent
162
163
  // manifest (no builtin, no installed override) is the structured miss.
163
164
  if (manifest !== undefined && manifest.id !== pluginId)
164
- throw new Error(`builtin manifest override does not match plugin ${pluginId}`);
165
+ throw new Error(t("builtin manifest override does not match plugin {pluginId}", { pluginId }));
165
166
  return manifest;
166
167
  }
167
168
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-profiles.js","sourceRoot":"","sources":["../../src/profile/plugin-profiles.ts"],"names":[],"mappings":"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","sourcesContent":["import { VERSION } from \"../config.ts\";\nimport { comparePluginVersionsV1 } from \"../plugins/ecosystem/catalog.ts\";\nimport { resolvePluginProfileV1 } from \"../plugins/ecosystem/resolver.ts\";\nimport type {\n\tHostFactsV1,\n\tPluginManifestV1,\n\tPluginResolutionV1,\n\tProfileResolutionV1,\n} from \"../plugins/ecosystem/types.ts\";\nimport { assembleProfile, type ProfileAssemblyResultV1, type VerifiedToolPluginV1 } from \"./profile-assembly.ts\";\n\nexport type BuiltinPluginProfileIdV1 =\n\t| \"coding-core\"\n\t| \"desktop-qa\"\n\t| \"desktop-observe\"\n\t| \"desktop-control\"\n\t| \"lsp-diagnostics\"\n\t| \"image-generation\"\n\t| \"process-exec\"\n\t| \"test-runner\"\n\t| \"workspace-files\"\n\t| \"workspace-files-write\"\n\t| \"formatter-linter\"\n\t| \"git-repository\";\n\nexport interface BuiltinPluginProfileV1 {\n\treadonly id: BuiltinPluginProfileIdV1;\n\treadonly version: string;\n\treadonly pluginIds: readonly string[];\n}\n\n/**\n * Host-owned manifest replacements for installed, verified package versions.\n *\n * Builtin manifests remain the default. A host may explicitly provide one\n * replacement per builtin plugin ID when a staged/verified/active install is\n * selected for a new Profile. The resolver never discovers files or chooses a\n * version implicitly; the replacement is part of the resulting Profile\n * identity and must still pass normal compatibility and verification checks.\n */\nexport type BuiltinPluginManifestOverridesV1 = Readonly<Record<string, PluginManifestV1>>;\n\nexport type BuiltinPluginProfileResolutionV1 =\n\t| { readonly status: \"not_found\"; readonly profileId: string }\n\t| { readonly status: \"host_facts_required\"; readonly profileId: string }\n\t| {\n\t\t\treadonly status: \"invalid_selection\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly unknownPluginIds: readonly string[];\n\t\t\treadonly duplicatePluginIds: readonly string[];\n\t }\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profile: BuiltinPluginProfileV1;\n\t\t\treadonly resolution: ProfileResolutionV1;\n\t\t\treadonly assembly?: ProfileAssemblyResultV1;\n\t };\n\n// D-075 S3: every first-party category-A plugin now ships as an independent\n// package under `plugins/` with the `agent-forge.plugin.<name>` id domain\n// (design §4.1). No embedded manifests remain; profiles resolve through the\n// install store (host-provided `manifestOverrides` from active bindings).\nconst manifests: Readonly<Record<string, PluginManifestV1>> = Object.freeze({});\n\nconst profiles: readonly BuiltinPluginProfileV1[] = Object.freeze([\n\t{ id: \"coding-core\", version: \"1\", pluginIds: [] },\n\t{\n\t\tid: \"desktop-qa\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"desktop-observe\", version: \"1\", pluginIds: [\"agent-forge.plugin.desktop-windows-observe\"] },\n\t{\n\t\tid: \"desktop-control\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"lsp-diagnostics\", version: \"1\", pluginIds: [\"agent-forge.plugin.lsp-diagnostics\"] },\n\t{ id: \"image-generation\", version: \"1\", pluginIds: [\"agent-forge.plugin.image-generation\"] },\n\t{ id: \"process-exec\", version: \"1\", pluginIds: [\"agent-forge.plugin.process-exec\"] },\n\t{ id: \"test-runner\", version: \"1\", pluginIds: [\"agent-forge.plugin.test-runner\"] },\n\t{ id: \"workspace-files\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files\"] },\n\t{ id: \"workspace-files-write\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files-write\"] },\n\t{\n\t\t// D-075 S2: the plugin code ships as the independent package\n\t\t// `agent-forge.plugin.formatter-linter` (design §4.1 id domain); this\n\t\t// Profile stays the stable user entry (`--plugin-profile formatter-linter`)\n\t\t// and resolves through the install store, not an embedded manifest.\n\t\tid: \"formatter-linter\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.formatter-linter\"],\n\t},\n\t{ id: \"git-repository\", version: \"1\", pluginIds: [\"agent-forge.plugin.git-repository\"] },\n]);\n\nexport function listBuiltinPluginProfilesV1(): readonly BuiltinPluginProfileV1[] {\n\treturn profiles;\n}\n\n/** True when the id names a builtin plugin profile (the CLI selection vocabulary). */\nexport function isBuiltinPluginProfileIdV1(value: string): value is BuiltinPluginProfileIdV1 {\n\treturn profiles.some((profile) => profile.id === value);\n}\n\n/** Return the first-party manifest projection for catalog and selection UIs. */\nexport function listBuiltinPluginManifestsV1(): readonly PluginManifestV1[] {\n\treturn Object.freeze(\n\t\tObject.values(manifests).sort((left, right) => {\n\t\t\tconst idOrder = `${left.id}@${left.pluginVersion}`.localeCompare(`${right.id}@${right.pluginVersion}`);\n\t\t\treturn idOrder === 0 ? comparePluginVersionsV1(left.pluginVersion, right.pluginVersion) : idOrder;\n\t\t}),\n\t);\n}\n\n/**\n * First-party plugins of an explicitly selected Profile are trusted by\n * default: builtins ship with the product and the user chose the Profile\n * explicitly. Installed third-party versions are still verified through the\n * active-binding resolver; host-injected verifiedPlugins always win.\n */\nexport function defaultBuiltinVerifiedPluginsV1(profileId: string): readonly VerifiedToolPluginV1[] {\n\tconst profile = profiles.find((candidate) => candidate.id === profileId);\n\tif (profile === undefined) return [];\n\treturn profile.pluginIds.flatMap((pluginId) => {\n\t\tconst manifest = manifests[pluginId];\n\t\treturn manifest === undefined ? [] : [{ pluginId: manifest.id, version: manifest.pluginVersion }];\n\t});\n}\n\nexport function resolveBuiltinPluginProfileV1(input: {\n\treadonly profileId: string;\n\treadonly host: HostFactsV1;\n\t/** Optional subset of the selected builtin Profile's plugins. */\n\treadonly selectedPluginIds?: readonly string[];\n\treadonly disabledPluginIds?: readonly string[];\n\treadonly verifiedPlugins?: readonly VerifiedToolPluginV1[];\n\t/** Explicit host-selected active manifests; never inferred from disk. */\n\treadonly manifestOverrides?: BuiltinPluginManifestOverridesV1;\n}): BuiltinPluginProfileResolutionV1 {\n\tconst profile = profiles.find((candidate) => candidate.id === input.profileId);\n\tif (profile === undefined) return { status: \"not_found\", profileId: input.profileId };\n\tconst requestedPluginIds = input.selectedPluginIds;\n\tconst requestedDisabledPluginIds = input.disabledPluginIds;\n\tif (requestedPluginIds !== undefined || requestedDisabledPluginIds !== undefined) {\n\t\tconst availablePluginIds = new Set(profile.pluginIds);\n\t\tconst duplicatePluginIds: string[] = [];\n\t\tconst unknownPluginIds: string[] = [];\n\t\tfor (const requestedIds of [requestedPluginIds ?? [], requestedDisabledPluginIds ?? []]) {\n\t\t\tconst seen = new Set<string>();\n\t\t\tfor (const pluginId of requestedIds) {\n\t\t\t\tif (!availablePluginIds.has(pluginId) && !unknownPluginIds.includes(pluginId))\n\t\t\t\t\tunknownPluginIds.push(pluginId);\n\t\t\t\tif (seen.has(pluginId) && !duplicatePluginIds.includes(pluginId)) duplicatePluginIds.push(pluginId);\n\t\t\t\tseen.add(pluginId);\n\t\t\t}\n\t\t}\n\t\tif (unknownPluginIds.length > 0 || duplicatePluginIds.length > 0) {\n\t\t\treturn {\n\t\t\t\tstatus: \"invalid_selection\",\n\t\t\t\tprofileId: input.profileId,\n\t\t\t\tunknownPluginIds: Object.freeze([...new Set(unknownPluginIds)]),\n\t\t\t\tduplicatePluginIds: Object.freeze(duplicatePluginIds),\n\t\t\t};\n\t\t}\n\t}\n\tconst selected =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile.pluginIds\n\t\t\t: profile.pluginIds.filter((pluginId) => requestedPluginIds.includes(pluginId));\n\tconst selectedProfile =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile\n\t\t\t: Object.freeze({ ...profile, pluginIds: Object.freeze([...selected]) });\n\tconst disabled = new Set(input.disabledPluginIds ?? []);\n\t// D-075 S2: a Profile plugin without a builtin manifest and without a\n\t// host-installed override is a structured miss, not a startup failure. The\n\t// plugin is omitted from the resolved manifest and runtime bindings; the\n\t// remaining Profile plugins resolve normally (soft degradation).\n\tconst manifestByPluginId = new Map(\n\t\tselectedProfile.pluginIds.map((pluginId) => [pluginId, manifestFor(pluginId, input.manifestOverrides)] as const),\n\t);\n\tconst missingPluginIds = selectedProfile.pluginIds.filter(\n\t\t(pluginId) => manifestByPluginId.get(pluginId) === undefined,\n\t);\n\tconst resolution = resolvePluginProfileV1({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tplugins: selectedProfile.pluginIds.flatMap((pluginId) => {\n\t\t\tconst manifest = manifestByPluginId.get(pluginId);\n\t\t\treturn manifest === undefined\n\t\t\t\t? []\n\t\t\t\t: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmanifest,\n\t\t\t\t\t\t\t// A user-disabled plugin must not block the remaining profile. It is\n\t\t\t\t\t\t\t// still represented in the resolution diagnostics, but is omitted from\n\t\t\t\t\t\t\t// the active resolved manifest and runtime bindings.\n\t\t\t\t\t\t\trequired: !disabled.has(pluginId),\n\t\t\t\t\t\t\tdisabled: disabled.has(pluginId),\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t}),\n\t\thost: input.host,\n\t\t// The host's own version enforces each manifest's minHostVersion floor\n\t\t// at the single builtin profile resolution funnel used by production\n\t\t// loading paths.\n\t\thostVersion: VERSION,\n\t});\n\tconst merged = mergeMissingPluginResolutionsV1(resolution, missingPluginIds, disabled);\n\tif (merged.status !== \"ready\") return { status: \"resolved\", profile: selectedProfile, resolution: merged };\n\tconst resolvedPlugins = merged.resolvedManifest.plugins.map((plugin) => ({\n\t\tpluginId: plugin.pluginId,\n\t\tpluginVersion: plugin.pluginVersion,\n\t\tcapabilityRefs: plugin.capabilityRefs,\n\t\t...(plugin.selectedAdapter === undefined ? {} : { selectedAdapter: plugin.selectedAdapter }),\n\t}));\n\tconst verifiedPlugins = input.verifiedPlugins ?? [];\n\tconst assembly = assembleProfile({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tresolvedPlugins,\n\t\tverifiedPlugins,\n\t});\n\treturn {\n\t\tstatus: \"resolved\",\n\t\tprofile: selectedProfile,\n\t\tresolution: merged,\n\t\tassembly,\n\t};\n}\n\nfunction manifestFor(\n\tpluginId: string,\n\toverrides: BuiltinPluginManifestOverridesV1 | undefined,\n): PluginManifestV1 | undefined {\n\tconst manifest = overrides?.[pluginId] ?? manifests[pluginId];\n\t// A mismatched override stays a hard host error: the host selected it\n\t// explicitly, so silence would hide an identity bug. A plain absent\n\t// manifest (no builtin, no installed override) is the structured miss.\n\tif (manifest !== undefined && manifest.id !== pluginId)\n\t\tthrow new Error(`builtin manifest override does not match plugin ${pluginId}`);\n\treturn manifest;\n}\n\n/**\n * Merge structured `manifest_missing` resolutions for Profile plugins that\n * have no builtin manifest and no installed override into the resolver\n * result. Missing plugins never block the Profile (soft degradation): the\n * remaining diagnostics and the resolved manifest stay exactly what the\n * resolver produced, and the merged plugin list keeps the resolver's\n * deterministic id sort.\n */\nfunction mergeMissingPluginResolutionsV1(\n\tresolution: ProfileResolutionV1,\n\tmissingPluginIds: readonly string[],\n\tdisabled: ReadonlySet<string>,\n): ProfileResolutionV1 {\n\tif (missingPluginIds.length === 0) return resolution;\n\tconst missing: PluginResolutionV1[] = missingPluginIds.map((pluginId) => ({\n\t\tpluginId,\n\t\tpluginVersion: \"\",\n\t\trequired: !disabled.has(pluginId),\n\t\tstatus: \"manifest-missing\",\n\t\tdiagnostics: [\n\t\t\t{\n\t\t\t\tcode: \"manifest_missing\",\n\t\t\t\tmessage: `Plugin ${pluginId} has no builtin manifest and no installed active override; the plugin is omitted from this profile (install it with agent-forge plugin install)`,\n\t\t\t},\n\t\t],\n\t}));\n\tconst plugins = [...resolution.plugins, ...missing].sort((left, right) =>\n\t\tleft.pluginId.localeCompare(right.pluginId),\n\t);\n\treturn Object.freeze({\n\t\t...resolution,\n\t\tplugins: Object.freeze(plugins),\n\t\tdiagnostics: Object.freeze(plugins.flatMap((plugin) => plugin.diagnostics)),\n\t});\n}\n"]}
1
+ {"version":3,"file":"plugin-profiles.js","sourceRoot":"","sources":["../../src/profile/plugin-profiles.ts"],"names":[],"mappings":"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","sourcesContent":["import { VERSION } from \"../config.ts\";\nimport { t } from \"../core/i18n/index.ts\";\nimport { comparePluginVersionsV1 } from \"../plugins/ecosystem/catalog.ts\";\nimport { resolvePluginProfileV1 } from \"../plugins/ecosystem/resolver.ts\";\nimport type {\n\tHostFactsV1,\n\tPluginManifestV1,\n\tPluginResolutionV1,\n\tProfileResolutionV1,\n} from \"../plugins/ecosystem/types.ts\";\nimport { assembleProfile, type ProfileAssemblyResultV1, type VerifiedToolPluginV1 } from \"./profile-assembly.ts\";\n\nexport type BuiltinPluginProfileIdV1 =\n\t| \"coding-core\"\n\t| \"desktop-qa\"\n\t| \"desktop-observe\"\n\t| \"desktop-control\"\n\t| \"lsp-diagnostics\"\n\t| \"image-generation\"\n\t| \"process-exec\"\n\t| \"test-runner\"\n\t| \"workspace-files\"\n\t| \"workspace-files-write\"\n\t| \"formatter-linter\"\n\t| \"git-repository\";\n\nexport interface BuiltinPluginProfileV1 {\n\treadonly id: BuiltinPluginProfileIdV1;\n\treadonly version: string;\n\treadonly pluginIds: readonly string[];\n}\n\n/**\n * Host-owned manifest replacements for installed, verified package versions.\n *\n * Builtin manifests remain the default. A host may explicitly provide one\n * replacement per builtin plugin ID when a staged/verified/active install is\n * selected for a new Profile. The resolver never discovers files or chooses a\n * version implicitly; the replacement is part of the resulting Profile\n * identity and must still pass normal compatibility and verification checks.\n */\nexport type BuiltinPluginManifestOverridesV1 = Readonly<Record<string, PluginManifestV1>>;\n\nexport type BuiltinPluginProfileResolutionV1 =\n\t| { readonly status: \"not_found\"; readonly profileId: string }\n\t| { readonly status: \"host_facts_required\"; readonly profileId: string }\n\t| {\n\t\t\treadonly status: \"invalid_selection\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly unknownPluginIds: readonly string[];\n\t\t\treadonly duplicatePluginIds: readonly string[];\n\t }\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profile: BuiltinPluginProfileV1;\n\t\t\treadonly resolution: ProfileResolutionV1;\n\t\t\treadonly assembly?: ProfileAssemblyResultV1;\n\t };\n\n// D-075 S3: every first-party category-A plugin now ships as an independent\n// package under `plugins/` with the `agent-forge.plugin.<name>` id domain\n// (design §4.1). No embedded manifests remain; profiles resolve through the\n// install store (host-provided `manifestOverrides` from active bindings).\nconst manifests: Readonly<Record<string, PluginManifestV1>> = Object.freeze({});\n\nconst profiles: readonly BuiltinPluginProfileV1[] = Object.freeze([\n\t{ id: \"coding-core\", version: \"1\", pluginIds: [] },\n\t{\n\t\tid: \"desktop-qa\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"desktop-observe\", version: \"1\", pluginIds: [\"agent-forge.plugin.desktop-windows-observe\"] },\n\t{\n\t\tid: \"desktop-control\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.desktop-windows-observe\", \"agent-forge.plugin.desktop-windows-input\"],\n\t},\n\t{ id: \"lsp-diagnostics\", version: \"1\", pluginIds: [\"agent-forge.plugin.lsp-diagnostics\"] },\n\t{ id: \"image-generation\", version: \"1\", pluginIds: [\"agent-forge.plugin.image-generation\"] },\n\t{ id: \"process-exec\", version: \"1\", pluginIds: [\"agent-forge.plugin.process-exec\"] },\n\t{ id: \"test-runner\", version: \"1\", pluginIds: [\"agent-forge.plugin.test-runner\"] },\n\t{ id: \"workspace-files\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files\"] },\n\t{ id: \"workspace-files-write\", version: \"1\", pluginIds: [\"agent-forge.plugin.workspace-files-write\"] },\n\t{\n\t\t// D-075 S2: the plugin code ships as the independent package\n\t\t// `agent-forge.plugin.formatter-linter` (design §4.1 id domain); this\n\t\t// Profile stays the stable user entry (`--plugin-profile formatter-linter`)\n\t\t// and resolves through the install store, not an embedded manifest.\n\t\tid: \"formatter-linter\",\n\t\tversion: \"1\",\n\t\tpluginIds: [\"agent-forge.plugin.formatter-linter\"],\n\t},\n\t{ id: \"git-repository\", version: \"1\", pluginIds: [\"agent-forge.plugin.git-repository\"] },\n]);\n\nexport function listBuiltinPluginProfilesV1(): readonly BuiltinPluginProfileV1[] {\n\treturn profiles;\n}\n\n/** True when the id names a builtin plugin profile (the CLI selection vocabulary). */\nexport function isBuiltinPluginProfileIdV1(value: string): value is BuiltinPluginProfileIdV1 {\n\treturn profiles.some((profile) => profile.id === value);\n}\n\n/** Return the first-party manifest projection for catalog and selection UIs. */\nexport function listBuiltinPluginManifestsV1(): readonly PluginManifestV1[] {\n\treturn Object.freeze(\n\t\tObject.values(manifests).sort((left, right) => {\n\t\t\tconst idOrder = `${left.id}@${left.pluginVersion}`.localeCompare(`${right.id}@${right.pluginVersion}`);\n\t\t\treturn idOrder === 0 ? comparePluginVersionsV1(left.pluginVersion, right.pluginVersion) : idOrder;\n\t\t}),\n\t);\n}\n\n/**\n * First-party plugins of an explicitly selected Profile are trusted by\n * default: builtins ship with the product and the user chose the Profile\n * explicitly. Installed third-party versions are still verified through the\n * active-binding resolver; host-injected verifiedPlugins always win.\n */\nexport function defaultBuiltinVerifiedPluginsV1(profileId: string): readonly VerifiedToolPluginV1[] {\n\tconst profile = profiles.find((candidate) => candidate.id === profileId);\n\tif (profile === undefined) return [];\n\treturn profile.pluginIds.flatMap((pluginId) => {\n\t\tconst manifest = manifests[pluginId];\n\t\treturn manifest === undefined ? [] : [{ pluginId: manifest.id, version: manifest.pluginVersion }];\n\t});\n}\n\nexport function resolveBuiltinPluginProfileV1(input: {\n\treadonly profileId: string;\n\treadonly host: HostFactsV1;\n\t/** Optional subset of the selected builtin Profile's plugins. */\n\treadonly selectedPluginIds?: readonly string[];\n\treadonly disabledPluginIds?: readonly string[];\n\treadonly verifiedPlugins?: readonly VerifiedToolPluginV1[];\n\t/** Explicit host-selected active manifests; never inferred from disk. */\n\treadonly manifestOverrides?: BuiltinPluginManifestOverridesV1;\n}): BuiltinPluginProfileResolutionV1 {\n\tconst profile = profiles.find((candidate) => candidate.id === input.profileId);\n\tif (profile === undefined) return { status: \"not_found\", profileId: input.profileId };\n\tconst requestedPluginIds = input.selectedPluginIds;\n\tconst requestedDisabledPluginIds = input.disabledPluginIds;\n\tif (requestedPluginIds !== undefined || requestedDisabledPluginIds !== undefined) {\n\t\tconst availablePluginIds = new Set(profile.pluginIds);\n\t\tconst duplicatePluginIds: string[] = [];\n\t\tconst unknownPluginIds: string[] = [];\n\t\tfor (const requestedIds of [requestedPluginIds ?? [], requestedDisabledPluginIds ?? []]) {\n\t\t\tconst seen = new Set<string>();\n\t\t\tfor (const pluginId of requestedIds) {\n\t\t\t\tif (!availablePluginIds.has(pluginId) && !unknownPluginIds.includes(pluginId))\n\t\t\t\t\tunknownPluginIds.push(pluginId);\n\t\t\t\tif (seen.has(pluginId) && !duplicatePluginIds.includes(pluginId)) duplicatePluginIds.push(pluginId);\n\t\t\t\tseen.add(pluginId);\n\t\t\t}\n\t\t}\n\t\tif (unknownPluginIds.length > 0 || duplicatePluginIds.length > 0) {\n\t\t\treturn {\n\t\t\t\tstatus: \"invalid_selection\",\n\t\t\t\tprofileId: input.profileId,\n\t\t\t\tunknownPluginIds: Object.freeze([...new Set(unknownPluginIds)]),\n\t\t\t\tduplicatePluginIds: Object.freeze(duplicatePluginIds),\n\t\t\t};\n\t\t}\n\t}\n\tconst selected =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile.pluginIds\n\t\t\t: profile.pluginIds.filter((pluginId) => requestedPluginIds.includes(pluginId));\n\tconst selectedProfile =\n\t\trequestedPluginIds === undefined\n\t\t\t? profile\n\t\t\t: Object.freeze({ ...profile, pluginIds: Object.freeze([...selected]) });\n\tconst disabled = new Set(input.disabledPluginIds ?? []);\n\t// D-075 S2: a Profile plugin without a builtin manifest and without a\n\t// host-installed override is a structured miss, not a startup failure. The\n\t// plugin is omitted from the resolved manifest and runtime bindings; the\n\t// remaining Profile plugins resolve normally (soft degradation).\n\tconst manifestByPluginId = new Map(\n\t\tselectedProfile.pluginIds.map((pluginId) => [pluginId, manifestFor(pluginId, input.manifestOverrides)] as const),\n\t);\n\tconst missingPluginIds = selectedProfile.pluginIds.filter(\n\t\t(pluginId) => manifestByPluginId.get(pluginId) === undefined,\n\t);\n\tconst resolution = resolvePluginProfileV1({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tplugins: selectedProfile.pluginIds.flatMap((pluginId) => {\n\t\t\tconst manifest = manifestByPluginId.get(pluginId);\n\t\t\treturn manifest === undefined\n\t\t\t\t? []\n\t\t\t\t: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmanifest,\n\t\t\t\t\t\t\t// A user-disabled plugin must not block the remaining profile. It is\n\t\t\t\t\t\t\t// still represented in the resolution diagnostics, but is omitted from\n\t\t\t\t\t\t\t// the active resolved manifest and runtime bindings.\n\t\t\t\t\t\t\trequired: !disabled.has(pluginId),\n\t\t\t\t\t\t\tdisabled: disabled.has(pluginId),\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t}),\n\t\thost: input.host,\n\t\t// The host's own version enforces each manifest's minHostVersion floor\n\t\t// at the single builtin profile resolution funnel used by production\n\t\t// loading paths.\n\t\thostVersion: VERSION,\n\t});\n\tconst merged = mergeMissingPluginResolutionsV1(resolution, missingPluginIds, disabled);\n\tif (merged.status !== \"ready\") return { status: \"resolved\", profile: selectedProfile, resolution: merged };\n\tconst resolvedPlugins = merged.resolvedManifest.plugins.map((plugin) => ({\n\t\tpluginId: plugin.pluginId,\n\t\tpluginVersion: plugin.pluginVersion,\n\t\tcapabilityRefs: plugin.capabilityRefs,\n\t\t...(plugin.selectedAdapter === undefined ? {} : { selectedAdapter: plugin.selectedAdapter }),\n\t}));\n\tconst verifiedPlugins = input.verifiedPlugins ?? [];\n\tconst assembly = assembleProfile({\n\t\tprofileId: selectedProfile.id,\n\t\tprofileVersion: selectedProfile.version,\n\t\tresolvedPlugins,\n\t\tverifiedPlugins,\n\t});\n\treturn {\n\t\tstatus: \"resolved\",\n\t\tprofile: selectedProfile,\n\t\tresolution: merged,\n\t\tassembly,\n\t};\n}\n\nfunction manifestFor(\n\tpluginId: string,\n\toverrides: BuiltinPluginManifestOverridesV1 | undefined,\n): PluginManifestV1 | undefined {\n\tconst manifest = overrides?.[pluginId] ?? manifests[pluginId];\n\t// A mismatched override stays a hard host error: the host selected it\n\t// explicitly, so silence would hide an identity bug. A plain absent\n\t// manifest (no builtin, no installed override) is the structured miss.\n\tif (manifest !== undefined && manifest.id !== pluginId)\n\t\tthrow new Error(t(\"builtin manifest override does not match plugin {pluginId}\", { pluginId }));\n\treturn manifest;\n}\n\n/**\n * Merge structured `manifest_missing` resolutions for Profile plugins that\n * have no builtin manifest and no installed override into the resolver\n * result. Missing plugins never block the Profile (soft degradation): the\n * remaining diagnostics and the resolved manifest stay exactly what the\n * resolver produced, and the merged plugin list keeps the resolver's\n * deterministic id sort.\n */\nfunction mergeMissingPluginResolutionsV1(\n\tresolution: ProfileResolutionV1,\n\tmissingPluginIds: readonly string[],\n\tdisabled: ReadonlySet<string>,\n): ProfileResolutionV1 {\n\tif (missingPluginIds.length === 0) return resolution;\n\tconst missing: PluginResolutionV1[] = missingPluginIds.map((pluginId) => ({\n\t\tpluginId,\n\t\tpluginVersion: \"\",\n\t\trequired: !disabled.has(pluginId),\n\t\tstatus: \"manifest-missing\",\n\t\tdiagnostics: [\n\t\t\t{\n\t\t\t\tcode: \"manifest_missing\",\n\t\t\t\tmessage: `Plugin ${pluginId} has no builtin manifest and no installed active override; the plugin is omitted from this profile (install it with agent-forge plugin install)`,\n\t\t\t},\n\t\t],\n\t}));\n\tconst plugins = [...resolution.plugins, ...missing].sort((left, right) =>\n\t\tleft.pluginId.localeCompare(right.pluginId),\n\t);\n\treturn Object.freeze({\n\t\t...resolution,\n\t\tplugins: Object.freeze(plugins),\n\t\tdiagnostics: Object.freeze(plugins.flatMap((plugin) => plugin.diagnostics)),\n\t});\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"policy-manifest.d.ts","sourceRoot":"","sources":["../../src/profile/policy-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG,YAAY,GAAG,qBAAqB,CAAC;AAEjF,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,2EAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACtD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,mBAAmB,CAAC;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,uBAAuB;IACvC,aAAa,CAAC,KAAK,EAAE;QACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,YAAY,EAAE,SAAS,mBAAmB,EAAE,CAAC;KACtD,GAAG,gBAAgB,CAAC;IACrB,0FAA0F;IAC1F,oBAAoB,CACnB,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE;QACN,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;QAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;QAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;KACxB,GACC;QAAE,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAA;KAAE,CAAC;CAClF;AAcD,wBAAgB,2BAA2B,IAAI,uBAAuB,CA4CrE","sourcesContent":["/**\n * Default policy manifest (2.7e) — an explicit, declarative manifest of the\n * confirmation / permission / dangerous-operation policies a profile wants,\n * with an external selection path.\n *\n * The manifest is PURE DECLARATION: the kernel ships no policy enforcement —\n * an enforcement plugin (or none at all) attaches externally. Every entry\n * states its `enabled` flag explicitly; selecting an external policy\n * replaces or nulls (disables) a declaration and produces a NEW frozen\n * manifest plus a change record — the previous manifest stays untouched.\n * Digests reuse the key-order-stable serialization so declarations are\n * replayable.\n */\nimport type { JsonValue } from \"@agent-forge/ai\";\nimport { stableJsonDigest } from \"./identity.ts\";\n\nexport type PolicyKindV1 = \"confirmation\" | \"permission\" | \"dangerous_operation\";\n\nexport interface PolicyDeclarationV1 {\n\treadonly policyKind: PolicyKindV1;\n\treadonly policyId: string;\n\treadonly description: string;\n\t/** Stated explicitly — a policy the profile does not want is `false`. */\n\treadonly enabled: boolean;\n\treadonly defaults?: JsonValue;\n}\n\nexport interface PolicyManifestV1 {\n\treadonly manifestVersion: 1;\n\treadonly profileId: string;\n\treadonly declarations: readonly PolicyDeclarationV1[];\n\treadonly manifestDigest: string;\n}\n\nexport interface PolicyChangeRecordV1 {\n\treadonly policyKind: PolicyKindV1;\n\treadonly policyId: string;\n\treadonly action: \"disabled\" | \"external_selected\";\n\treadonly reason: string;\n}\n\nexport interface PolicyManifestBuilderV1 {\n\tbuildManifest(input: {\n\t\treadonly profileId: string;\n\t\treadonly declarations: readonly PolicyDeclarationV1[];\n\t}): PolicyManifestV1;\n\t/** The external selection path: swap in an external declaration or disable one (null). */\n\tselectExternalPolicy(\n\t\tmanifest: PolicyManifestV1,\n\t\tinput: {\n\t\t\treadonly policyKind: PolicyKindV1;\n\t\t\treadonly policyId: string;\n\t\t\treadonly external: PolicyDeclarationV1 | null;\n\t\t\treadonly reason: string;\n\t\t},\n\t): { readonly manifest: PolicyManifestV1; readonly change: PolicyChangeRecordV1 };\n}\n\nfunction assertDeclaration(value: PolicyDeclarationV1): void {\n\tif (![\"confirmation\", \"permission\", \"dangerous_operation\"].includes(value.policyKind)) {\n\t\tthrow new Error(`Policy manifest policyKind is invalid: ${String(value.policyKind)}`);\n\t}\n\tif (typeof value.policyId !== \"string\" || value.policyId.trim().length === 0) {\n\t\tthrow new Error(\"Policy manifest policyId must be a non-empty string\");\n\t}\n\tif (typeof value.enabled !== \"boolean\") {\n\t\tthrow new Error(`Policy manifest ${value.policyId}: enabled must be stated explicitly`);\n\t}\n}\n\nexport function createPolicyManifestBuilder(): PolicyManifestBuilderV1 {\n\tconst buildManifest = (input: {\n\t\treadonly profileId: string;\n\t\treadonly declarations: readonly PolicyDeclarationV1[];\n\t}): PolicyManifestV1 => {\n\t\tif (input.profileId.trim().length === 0) throw new Error(\"Policy manifest profileId must be a non-empty string\");\n\t\tfor (const declaration of input.declarations) assertDeclaration(declaration);\n\t\tconst declarations = Object.freeze(input.declarations.map((declaration) => Object.freeze({ ...declaration })));\n\t\treturn Object.freeze({\n\t\t\tmanifestVersion: 1 as const,\n\t\t\tprofileId: input.profileId,\n\t\t\tdeclarations,\n\t\t\tmanifestDigest: stableJsonDigest(declarations as unknown as JsonValue),\n\t\t});\n\t};\n\n\treturn {\n\t\tbuildManifest,\n\t\tselectExternalPolicy(manifest, input) {\n\t\t\tassertDeclaration(\n\t\t\t\tinput.external ?? {\n\t\t\t\t\tpolicyKind: input.policyKind,\n\t\t\t\t\tpolicyId: input.policyId,\n\t\t\t\t\tdescription: \"\",\n\t\t\t\t\tenabled: false,\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst kept = manifest.declarations.filter(\n\t\t\t\t(declaration) => !(declaration.policyKind === input.policyKind && declaration.policyId === input.policyId),\n\t\t\t);\n\t\t\tconst existed = kept.length !== manifest.declarations.length;\n\t\t\tconst declarations = input.external === null ? kept : [...kept, input.external];\n\t\t\tconst next = buildManifest({ profileId: manifest.profileId, declarations });\n\t\t\treturn {\n\t\t\t\tmanifest: next,\n\t\t\t\tchange: {\n\t\t\t\t\tpolicyKind: input.policyKind,\n\t\t\t\t\tpolicyId: input.policyId,\n\t\t\t\t\taction: input.external === null ? \"disabled\" : existed ? \"external_selected\" : \"external_selected\",\n\t\t\t\t\treason: input.reason,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"policy-manifest.d.ts","sourceRoot":"","sources":["../../src/profile/policy-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG,YAAY,GAAG,qBAAqB,CAAC;AAEjF,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,2EAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACtD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,mBAAmB,CAAC;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,uBAAuB;IACvC,aAAa,CAAC,KAAK,EAAE;QACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,YAAY,EAAE,SAAS,mBAAmB,EAAE,CAAC;KACtD,GAAG,gBAAgB,CAAC;IACrB,0FAA0F;IAC1F,oBAAoB,CACnB,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE;QACN,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;QAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;QAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;KACxB,GACC;QAAE,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAA;KAAE,CAAC;CAClF;AAgBD,wBAAgB,2BAA2B,IAAI,uBAAuB,CA6CrE","sourcesContent":["/**\n * Default policy manifest (2.7e) — an explicit, declarative manifest of the\n * confirmation / permission / dangerous-operation policies a profile wants,\n * with an external selection path.\n *\n * The manifest is PURE DECLARATION: the kernel ships no policy enforcement —\n * an enforcement plugin (or none at all) attaches externally. Every entry\n * states its `enabled` flag explicitly; selecting an external policy\n * replaces or nulls (disables) a declaration and produces a NEW frozen\n * manifest plus a change record — the previous manifest stays untouched.\n * Digests reuse the key-order-stable serialization so declarations are\n * replayable.\n */\nimport type { JsonValue } from \"@agent-forge/ai\";\nimport { t } from \"../core/i18n/index.ts\";\nimport { stableJsonDigest } from \"./identity.ts\";\n\nexport type PolicyKindV1 = \"confirmation\" | \"permission\" | \"dangerous_operation\";\n\nexport interface PolicyDeclarationV1 {\n\treadonly policyKind: PolicyKindV1;\n\treadonly policyId: string;\n\treadonly description: string;\n\t/** Stated explicitly — a policy the profile does not want is `false`. */\n\treadonly enabled: boolean;\n\treadonly defaults?: JsonValue;\n}\n\nexport interface PolicyManifestV1 {\n\treadonly manifestVersion: 1;\n\treadonly profileId: string;\n\treadonly declarations: readonly PolicyDeclarationV1[];\n\treadonly manifestDigest: string;\n}\n\nexport interface PolicyChangeRecordV1 {\n\treadonly policyKind: PolicyKindV1;\n\treadonly policyId: string;\n\treadonly action: \"disabled\" | \"external_selected\";\n\treadonly reason: string;\n}\n\nexport interface PolicyManifestBuilderV1 {\n\tbuildManifest(input: {\n\t\treadonly profileId: string;\n\t\treadonly declarations: readonly PolicyDeclarationV1[];\n\t}): PolicyManifestV1;\n\t/** The external selection path: swap in an external declaration or disable one (null). */\n\tselectExternalPolicy(\n\t\tmanifest: PolicyManifestV1,\n\t\tinput: {\n\t\t\treadonly policyKind: PolicyKindV1;\n\t\t\treadonly policyId: string;\n\t\t\treadonly external: PolicyDeclarationV1 | null;\n\t\t\treadonly reason: string;\n\t\t},\n\t): { readonly manifest: PolicyManifestV1; readonly change: PolicyChangeRecordV1 };\n}\n\nfunction assertDeclaration(value: PolicyDeclarationV1): void {\n\tif (![\"confirmation\", \"permission\", \"dangerous_operation\"].includes(value.policyKind)) {\n\t\tthrow new Error(\n\t\t\tt(\"Policy manifest policyKind is invalid: {policyKind}\", { policyKind: String(value.policyKind) }),\n\t\t);\n\t}\n\tif (typeof value.policyId !== \"string\" || value.policyId.trim().length === 0) {\n\t\tthrow new Error(t(\"Policy manifest policyId must be a non-empty string\"));\n\t}\n\tif (typeof value.enabled !== \"boolean\") {\n\t\tthrow new Error(t(\"Policy manifest {policyId}: enabled must be stated explicitly\", { policyId: value.policyId }));\n\t}\n}\n\nexport function createPolicyManifestBuilder(): PolicyManifestBuilderV1 {\n\tconst buildManifest = (input: {\n\t\treadonly profileId: string;\n\t\treadonly declarations: readonly PolicyDeclarationV1[];\n\t}): PolicyManifestV1 => {\n\t\tif (input.profileId.trim().length === 0)\n\t\t\tthrow new Error(t(\"Policy manifest profileId must be a non-empty string\"));\n\t\tfor (const declaration of input.declarations) assertDeclaration(declaration);\n\t\tconst declarations = Object.freeze(input.declarations.map((declaration) => Object.freeze({ ...declaration })));\n\t\treturn Object.freeze({\n\t\t\tmanifestVersion: 1 as const,\n\t\t\tprofileId: input.profileId,\n\t\t\tdeclarations,\n\t\t\tmanifestDigest: stableJsonDigest(declarations as unknown as JsonValue),\n\t\t});\n\t};\n\n\treturn {\n\t\tbuildManifest,\n\t\tselectExternalPolicy(manifest, input) {\n\t\t\tassertDeclaration(\n\t\t\t\tinput.external ?? {\n\t\t\t\t\tpolicyKind: input.policyKind,\n\t\t\t\t\tpolicyId: input.policyId,\n\t\t\t\t\tdescription: \"\",\n\t\t\t\t\tenabled: false,\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst kept = manifest.declarations.filter(\n\t\t\t\t(declaration) => !(declaration.policyKind === input.policyKind && declaration.policyId === input.policyId),\n\t\t\t);\n\t\t\tconst existed = kept.length !== manifest.declarations.length;\n\t\t\tconst declarations = input.external === null ? kept : [...kept, input.external];\n\t\t\tconst next = buildManifest({ profileId: manifest.profileId, declarations });\n\t\t\treturn {\n\t\t\t\tmanifest: next,\n\t\t\t\tchange: {\n\t\t\t\t\tpolicyKind: input.policyKind,\n\t\t\t\t\tpolicyId: input.policyId,\n\t\t\t\t\taction: input.external === null ? \"disabled\" : existed ? \"external_selected\" : \"external_selected\",\n\t\t\t\t\treason: input.reason,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
@@ -1,19 +1,20 @@
1
+ import { t } from "../core/i18n/index.js";
1
2
  import { stableJsonDigest } from "./identity.js";
2
3
  function assertDeclaration(value) {
3
4
  if (!["confirmation", "permission", "dangerous_operation"].includes(value.policyKind)) {
4
- throw new Error(`Policy manifest policyKind is invalid: ${String(value.policyKind)}`);
5
+ throw new Error(t("Policy manifest policyKind is invalid: {policyKind}", { policyKind: String(value.policyKind) }));
5
6
  }
6
7
  if (typeof value.policyId !== "string" || value.policyId.trim().length === 0) {
7
- throw new Error("Policy manifest policyId must be a non-empty string");
8
+ throw new Error(t("Policy manifest policyId must be a non-empty string"));
8
9
  }
9
10
  if (typeof value.enabled !== "boolean") {
10
- throw new Error(`Policy manifest ${value.policyId}: enabled must be stated explicitly`);
11
+ throw new Error(t("Policy manifest {policyId}: enabled must be stated explicitly", { policyId: value.policyId }));
11
12
  }
12
13
  }
13
14
  export function createPolicyManifestBuilder() {
14
15
  const buildManifest = (input) => {
15
16
  if (input.profileId.trim().length === 0)
16
- throw new Error("Policy manifest profileId must be a non-empty string");
17
+ throw new Error(t("Policy manifest profileId must be a non-empty string"));
17
18
  for (const declaration of input.declarations)
18
19
  assertDeclaration(declaration);
19
20
  const declarations = Object.freeze(input.declarations.map((declaration) => Object.freeze({ ...declaration })));
@@ -1 +1 @@
1
- {"version":3,"file":"policy-manifest.js","sourceRoot":"","sources":["../../src/profile/policy-manifest.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Default policy manifest (2.7e) — an explicit, declarative manifest of the\n * confirmation / permission / dangerous-operation policies a profile wants,\n * with an external selection path.\n *\n * The manifest is PURE DECLARATION: the kernel ships no policy enforcement —\n * an enforcement plugin (or none at all) attaches externally. Every entry\n * states its `enabled` flag explicitly; selecting an external policy\n * replaces or nulls (disables) a declaration and produces a NEW frozen\n * manifest plus a change record — the previous manifest stays untouched.\n * Digests reuse the key-order-stable serialization so declarations are\n * replayable.\n */\nimport type { JsonValue } from \"@agent-forge/ai\";\nimport { stableJsonDigest } from \"./identity.ts\";\n\nexport type PolicyKindV1 = \"confirmation\" | \"permission\" | \"dangerous_operation\";\n\nexport interface PolicyDeclarationV1 {\n\treadonly policyKind: PolicyKindV1;\n\treadonly policyId: string;\n\treadonly description: string;\n\t/** Stated explicitly — a policy the profile does not want is `false`. */\n\treadonly enabled: boolean;\n\treadonly defaults?: JsonValue;\n}\n\nexport interface PolicyManifestV1 {\n\treadonly manifestVersion: 1;\n\treadonly profileId: string;\n\treadonly declarations: readonly PolicyDeclarationV1[];\n\treadonly manifestDigest: string;\n}\n\nexport interface PolicyChangeRecordV1 {\n\treadonly policyKind: PolicyKindV1;\n\treadonly policyId: string;\n\treadonly action: \"disabled\" | \"external_selected\";\n\treadonly reason: string;\n}\n\nexport interface PolicyManifestBuilderV1 {\n\tbuildManifest(input: {\n\t\treadonly profileId: string;\n\t\treadonly declarations: readonly PolicyDeclarationV1[];\n\t}): PolicyManifestV1;\n\t/** The external selection path: swap in an external declaration or disable one (null). */\n\tselectExternalPolicy(\n\t\tmanifest: PolicyManifestV1,\n\t\tinput: {\n\t\t\treadonly policyKind: PolicyKindV1;\n\t\t\treadonly policyId: string;\n\t\t\treadonly external: PolicyDeclarationV1 | null;\n\t\t\treadonly reason: string;\n\t\t},\n\t): { readonly manifest: PolicyManifestV1; readonly change: PolicyChangeRecordV1 };\n}\n\nfunction assertDeclaration(value: PolicyDeclarationV1): void {\n\tif (![\"confirmation\", \"permission\", \"dangerous_operation\"].includes(value.policyKind)) {\n\t\tthrow new Error(`Policy manifest policyKind is invalid: ${String(value.policyKind)}`);\n\t}\n\tif (typeof value.policyId !== \"string\" || value.policyId.trim().length === 0) {\n\t\tthrow new Error(\"Policy manifest policyId must be a non-empty string\");\n\t}\n\tif (typeof value.enabled !== \"boolean\") {\n\t\tthrow new Error(`Policy manifest ${value.policyId}: enabled must be stated explicitly`);\n\t}\n}\n\nexport function createPolicyManifestBuilder(): PolicyManifestBuilderV1 {\n\tconst buildManifest = (input: {\n\t\treadonly profileId: string;\n\t\treadonly declarations: readonly PolicyDeclarationV1[];\n\t}): PolicyManifestV1 => {\n\t\tif (input.profileId.trim().length === 0) throw new Error(\"Policy manifest profileId must be a non-empty string\");\n\t\tfor (const declaration of input.declarations) assertDeclaration(declaration);\n\t\tconst declarations = Object.freeze(input.declarations.map((declaration) => Object.freeze({ ...declaration })));\n\t\treturn Object.freeze({\n\t\t\tmanifestVersion: 1 as const,\n\t\t\tprofileId: input.profileId,\n\t\t\tdeclarations,\n\t\t\tmanifestDigest: stableJsonDigest(declarations as unknown as JsonValue),\n\t\t});\n\t};\n\n\treturn {\n\t\tbuildManifest,\n\t\tselectExternalPolicy(manifest, input) {\n\t\t\tassertDeclaration(\n\t\t\t\tinput.external ?? {\n\t\t\t\t\tpolicyKind: input.policyKind,\n\t\t\t\t\tpolicyId: input.policyId,\n\t\t\t\t\tdescription: \"\",\n\t\t\t\t\tenabled: false,\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst kept = manifest.declarations.filter(\n\t\t\t\t(declaration) => !(declaration.policyKind === input.policyKind && declaration.policyId === input.policyId),\n\t\t\t);\n\t\t\tconst existed = kept.length !== manifest.declarations.length;\n\t\t\tconst declarations = input.external === null ? kept : [...kept, input.external];\n\t\t\tconst next = buildManifest({ profileId: manifest.profileId, declarations });\n\t\t\treturn {\n\t\t\t\tmanifest: next,\n\t\t\t\tchange: {\n\t\t\t\t\tpolicyKind: input.policyKind,\n\t\t\t\t\tpolicyId: input.policyId,\n\t\t\t\t\taction: input.external === null ? \"disabled\" : existed ? \"external_selected\" : \"external_selected\",\n\t\t\t\t\treason: input.reason,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"policy-manifest.js","sourceRoot":"","sources":["../../src/profile/policy-manifest.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Default policy manifest (2.7e) — an explicit, declarative manifest of the\n * confirmation / permission / dangerous-operation policies a profile wants,\n * with an external selection path.\n *\n * The manifest is PURE DECLARATION: the kernel ships no policy enforcement —\n * an enforcement plugin (or none at all) attaches externally. Every entry\n * states its `enabled` flag explicitly; selecting an external policy\n * replaces or nulls (disables) a declaration and produces a NEW frozen\n * manifest plus a change record — the previous manifest stays untouched.\n * Digests reuse the key-order-stable serialization so declarations are\n * replayable.\n */\nimport type { JsonValue } from \"@agent-forge/ai\";\nimport { t } from \"../core/i18n/index.ts\";\nimport { stableJsonDigest } from \"./identity.ts\";\n\nexport type PolicyKindV1 = \"confirmation\" | \"permission\" | \"dangerous_operation\";\n\nexport interface PolicyDeclarationV1 {\n\treadonly policyKind: PolicyKindV1;\n\treadonly policyId: string;\n\treadonly description: string;\n\t/** Stated explicitly — a policy the profile does not want is `false`. */\n\treadonly enabled: boolean;\n\treadonly defaults?: JsonValue;\n}\n\nexport interface PolicyManifestV1 {\n\treadonly manifestVersion: 1;\n\treadonly profileId: string;\n\treadonly declarations: readonly PolicyDeclarationV1[];\n\treadonly manifestDigest: string;\n}\n\nexport interface PolicyChangeRecordV1 {\n\treadonly policyKind: PolicyKindV1;\n\treadonly policyId: string;\n\treadonly action: \"disabled\" | \"external_selected\";\n\treadonly reason: string;\n}\n\nexport interface PolicyManifestBuilderV1 {\n\tbuildManifest(input: {\n\t\treadonly profileId: string;\n\t\treadonly declarations: readonly PolicyDeclarationV1[];\n\t}): PolicyManifestV1;\n\t/** The external selection path: swap in an external declaration or disable one (null). */\n\tselectExternalPolicy(\n\t\tmanifest: PolicyManifestV1,\n\t\tinput: {\n\t\t\treadonly policyKind: PolicyKindV1;\n\t\t\treadonly policyId: string;\n\t\t\treadonly external: PolicyDeclarationV1 | null;\n\t\t\treadonly reason: string;\n\t\t},\n\t): { readonly manifest: PolicyManifestV1; readonly change: PolicyChangeRecordV1 };\n}\n\nfunction assertDeclaration(value: PolicyDeclarationV1): void {\n\tif (![\"confirmation\", \"permission\", \"dangerous_operation\"].includes(value.policyKind)) {\n\t\tthrow new Error(\n\t\t\tt(\"Policy manifest policyKind is invalid: {policyKind}\", { policyKind: String(value.policyKind) }),\n\t\t);\n\t}\n\tif (typeof value.policyId !== \"string\" || value.policyId.trim().length === 0) {\n\t\tthrow new Error(t(\"Policy manifest policyId must be a non-empty string\"));\n\t}\n\tif (typeof value.enabled !== \"boolean\") {\n\t\tthrow new Error(t(\"Policy manifest {policyId}: enabled must be stated explicitly\", { policyId: value.policyId }));\n\t}\n}\n\nexport function createPolicyManifestBuilder(): PolicyManifestBuilderV1 {\n\tconst buildManifest = (input: {\n\t\treadonly profileId: string;\n\t\treadonly declarations: readonly PolicyDeclarationV1[];\n\t}): PolicyManifestV1 => {\n\t\tif (input.profileId.trim().length === 0)\n\t\t\tthrow new Error(t(\"Policy manifest profileId must be a non-empty string\"));\n\t\tfor (const declaration of input.declarations) assertDeclaration(declaration);\n\t\tconst declarations = Object.freeze(input.declarations.map((declaration) => Object.freeze({ ...declaration })));\n\t\treturn Object.freeze({\n\t\t\tmanifestVersion: 1 as const,\n\t\t\tprofileId: input.profileId,\n\t\t\tdeclarations,\n\t\t\tmanifestDigest: stableJsonDigest(declarations as unknown as JsonValue),\n\t\t});\n\t};\n\n\treturn {\n\t\tbuildManifest,\n\t\tselectExternalPolicy(manifest, input) {\n\t\t\tassertDeclaration(\n\t\t\t\tinput.external ?? {\n\t\t\t\t\tpolicyKind: input.policyKind,\n\t\t\t\t\tpolicyId: input.policyId,\n\t\t\t\t\tdescription: \"\",\n\t\t\t\t\tenabled: false,\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst kept = manifest.declarations.filter(\n\t\t\t\t(declaration) => !(declaration.policyKind === input.policyKind && declaration.policyId === input.policyId),\n\t\t\t);\n\t\t\tconst existed = kept.length !== manifest.declarations.length;\n\t\t\tconst declarations = input.external === null ? kept : [...kept, input.external];\n\t\t\tconst next = buildManifest({ profileId: manifest.profileId, declarations });\n\t\t\treturn {\n\t\t\t\tmanifest: next,\n\t\t\t\tchange: {\n\t\t\t\t\tpolicyKind: input.policyKind,\n\t\t\t\t\tpolicyId: input.policyId,\n\t\t\t\t\taction: input.external === null ? \"disabled\" : existed ? \"external_selected\" : \"external_selected\",\n\t\t\t\t\treason: input.reason,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
@@ -1,15 +1,3 @@
1
- /**
2
- * Profile registry (2.7a) — multi-source discovery, upgrades, and
3
- * compatibility for profile manifests on top of the minimal 2.0a identity.
4
- *
5
- * Sources register profiles with a priority (lower number wins). Resolution
6
- * is deterministic and replayable: filter candidates by the requested
7
- * version range, pick the highest version, break same-version ties by
8
- * source priority (the losing source is reported as superseded), and mark
9
- * deprecated winners explicitly (visible, digest still supplied — callers
10
- * decide whether to proceed). Builds on the minimal 2.0a identity/lock
11
- * without extending them.
12
- */
13
1
  export interface RegistryProfileEntryV1 {
14
2
  readonly profileId: string;
15
3
  readonly profileVersion: string;
@@ -1 +1 @@
1
- {"version":3,"file":"profile-registry.d.ts","sourceRoot":"","sources":["../../src/profile/profile-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,SAAS,sBAAsB,EAAE,CAAC;CACrD;AAED,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,mBAAmB,GAC5B;IACA,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,SAAS;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC9F,GACD;IACA,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACvB,GACD;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IACjC,cAAc,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC/C,OAAO,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,qBAAqB,CAAA;KAAE,GAAG,mBAAmB,CAAC;CACnH;AAcD,wBAAgB,qBAAqB,IAAI,iBAAiB,CAmEzD","sourcesContent":["/**\n * Profile registry (2.7a) — multi-source discovery, upgrades, and\n * compatibility for profile manifests on top of the minimal 2.0a identity.\n *\n * Sources register profiles with a priority (lower number wins). Resolution\n * is deterministic and replayable: filter candidates by the requested\n * version range, pick the highest version, break same-version ties by\n * source priority (the losing source is reported as superseded), and mark\n * deprecated winners explicitly (visible, digest still supplied — callers\n * decide whether to proceed). Builds on the minimal 2.0a identity/lock\n * without extending them.\n */\nexport interface RegistryProfileEntryV1 {\n\treadonly profileId: string;\n\treadonly profileVersion: string;\n\treadonly manifestDigest: string;\n\treadonly deprecated?: string;\n}\n\nexport interface RegistrySourceV1 {\n\treadonly sourceId: string;\n\t/** Lower priority number wins same-version ties. */\n\treadonly priority: number;\n\treadonly profiles: readonly RegistryProfileEntryV1[];\n}\n\nexport interface ProfileVersionRangeV1 {\n\treadonly min?: string;\n\treadonly max?: string;\n}\n\nexport type ProfileResolutionV1 =\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly profileVersion: string;\n\t\t\treadonly manifestDigest: string;\n\t\t\treadonly sourceId: string;\n\t\t\treadonly superseded: readonly { readonly sourceId: string; readonly profileVersion: string }[];\n\t }\n\t| {\n\t\t\treadonly status: \"deprecated\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly profileVersion: string;\n\t\t\treadonly manifestDigest: string;\n\t\t\treadonly sourceId: string;\n\t\t\treadonly reason: string;\n\t }\n\t| { readonly status: \"not_found\"; readonly profileId: string };\n\nexport interface ProfileRegistryV1 {\n\tregisterSource(source: RegistrySourceV1): void;\n\tresolve(input: { readonly profileId: string; readonly versionRange?: ProfileVersionRangeV1 }): ProfileResolutionV1;\n}\n\n/** Segment-wise numeric semver comparison (\"1.2\" < \"1.10\" < \"2.0\"). */\nfunction compareVersions(a: string, b: string): number {\n\tconst pa = a.split(\".\").map((part) => Number.parseInt(part, 10) || 0);\n\tconst pb = b.split(\".\").map((part) => Number.parseInt(part, 10) || 0);\n\tconst length = Math.max(pa.length, pb.length);\n\tfor (let index = 0; index < length; index += 1) {\n\t\tconst diff = (pa[index] ?? 0) - (pb[index] ?? 0);\n\t\tif (diff !== 0) return diff;\n\t}\n\treturn 0;\n}\n\nexport function createProfileRegistry(): ProfileRegistryV1 {\n\tconst sources: RegistrySourceV1[] = [];\n\n\treturn {\n\t\tregisterSource(source) {\n\t\t\tif (sources.some((existing) => existing.sourceId === source.sourceId)) {\n\t\t\t\tthrow new Error(`Registry source already registered: ${source.sourceId}`);\n\t\t\t}\n\t\t\tsources.push(source);\n\t\t},\n\t\tresolve({ profileId, versionRange }) {\n\t\t\tconst candidates = sources\n\t\t\t\t.flatMap((source) =>\n\t\t\t\t\tsource.profiles\n\t\t\t\t\t\t.filter((profile) => profile.profileId === profileId)\n\t\t\t\t\t\t.map((profile) => ({ source, profile })),\n\t\t\t\t)\n\t\t\t\t.filter(({ profile }) => {\n\t\t\t\t\tif (versionRange?.min !== undefined && compareVersions(profile.profileVersion, versionRange.min) < 0) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (versionRange?.max !== undefined && compareVersions(profile.profileVersion, versionRange.max) > 0) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.sort((a, b) => {\n\t\t\t\t\tconst versionDiff = compareVersions(b.profile.profileVersion, a.profile.profileVersion);\n\t\t\t\t\tif (versionDiff !== 0) return versionDiff;\n\t\t\t\t\treturn a.source.priority - b.source.priority;\n\t\t\t\t});\n\n\t\t\tif (candidates.length === 0) {\n\t\t\t\treturn { status: \"not_found\", profileId };\n\t\t\t}\n\n\t\t\tconst winner = candidates[0]!;\n\t\t\tif (winner.profile.deprecated !== undefined) {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"deprecated\",\n\t\t\t\t\tprofileId,\n\t\t\t\t\tprofileVersion: winner.profile.profileVersion,\n\t\t\t\t\tmanifestDigest: winner.profile.manifestDigest,\n\t\t\t\t\tsourceId: winner.source.sourceId,\n\t\t\t\t\treason: winner.profile.deprecated,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst superseded = candidates\n\t\t\t\t.slice(1)\n\t\t\t\t.filter(\n\t\t\t\t\t(candidate) => compareVersions(candidate.profile.profileVersion, winner.profile.profileVersion) === 0,\n\t\t\t\t)\n\t\t\t\t.map((candidate) => ({\n\t\t\t\t\tsourceId: candidate.source.sourceId,\n\t\t\t\t\tprofileVersion: candidate.profile.profileVersion,\n\t\t\t\t}));\n\t\t\treturn {\n\t\t\t\tstatus: \"resolved\",\n\t\t\t\tprofileId,\n\t\t\t\tprofileVersion: winner.profile.profileVersion,\n\t\t\t\tmanifestDigest: winner.profile.manifestDigest,\n\t\t\t\tsourceId: winner.source.sourceId,\n\t\t\t\tsuperseded,\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"profile-registry.d.ts","sourceRoot":"","sources":["../../src/profile/profile-registry.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,SAAS,sBAAsB,EAAE,CAAC;CACrD;AAED,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,mBAAmB,GAC5B;IACA,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,SAAS;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC9F,GACD;IACA,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACvB,GACD;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IACjC,cAAc,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC/C,OAAO,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,qBAAqB,CAAA;KAAE,GAAG,mBAAmB,CAAC;CACnH;AAcD,wBAAgB,qBAAqB,IAAI,iBAAiB,CAmEzD","sourcesContent":["/**\n * Profile registry (2.7a) — multi-source discovery, upgrades, and\n * compatibility for profile manifests on top of the minimal 2.0a identity.\n *\n * Sources register profiles with a priority (lower number wins). Resolution\n * is deterministic and replayable: filter candidates by the requested\n * version range, pick the highest version, break same-version ties by\n * source priority (the losing source is reported as superseded), and mark\n * deprecated winners explicitly (visible, digest still supplied — callers\n * decide whether to proceed). Builds on the minimal 2.0a identity/lock\n * without extending them.\n */\nimport { t } from \"../core/i18n/index.ts\";\n\nexport interface RegistryProfileEntryV1 {\n\treadonly profileId: string;\n\treadonly profileVersion: string;\n\treadonly manifestDigest: string;\n\treadonly deprecated?: string;\n}\n\nexport interface RegistrySourceV1 {\n\treadonly sourceId: string;\n\t/** Lower priority number wins same-version ties. */\n\treadonly priority: number;\n\treadonly profiles: readonly RegistryProfileEntryV1[];\n}\n\nexport interface ProfileVersionRangeV1 {\n\treadonly min?: string;\n\treadonly max?: string;\n}\n\nexport type ProfileResolutionV1 =\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly profileVersion: string;\n\t\t\treadonly manifestDigest: string;\n\t\t\treadonly sourceId: string;\n\t\t\treadonly superseded: readonly { readonly sourceId: string; readonly profileVersion: string }[];\n\t }\n\t| {\n\t\t\treadonly status: \"deprecated\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly profileVersion: string;\n\t\t\treadonly manifestDigest: string;\n\t\t\treadonly sourceId: string;\n\t\t\treadonly reason: string;\n\t }\n\t| { readonly status: \"not_found\"; readonly profileId: string };\n\nexport interface ProfileRegistryV1 {\n\tregisterSource(source: RegistrySourceV1): void;\n\tresolve(input: { readonly profileId: string; readonly versionRange?: ProfileVersionRangeV1 }): ProfileResolutionV1;\n}\n\n/** Segment-wise numeric semver comparison (\"1.2\" < \"1.10\" < \"2.0\"). */\nfunction compareVersions(a: string, b: string): number {\n\tconst pa = a.split(\".\").map((part) => Number.parseInt(part, 10) || 0);\n\tconst pb = b.split(\".\").map((part) => Number.parseInt(part, 10) || 0);\n\tconst length = Math.max(pa.length, pb.length);\n\tfor (let index = 0; index < length; index += 1) {\n\t\tconst diff = (pa[index] ?? 0) - (pb[index] ?? 0);\n\t\tif (diff !== 0) return diff;\n\t}\n\treturn 0;\n}\n\nexport function createProfileRegistry(): ProfileRegistryV1 {\n\tconst sources: RegistrySourceV1[] = [];\n\n\treturn {\n\t\tregisterSource(source) {\n\t\t\tif (sources.some((existing) => existing.sourceId === source.sourceId)) {\n\t\t\t\tthrow new Error(t(\"Registry source already registered: {sourceId}\", { sourceId: source.sourceId }));\n\t\t\t}\n\t\t\tsources.push(source);\n\t\t},\n\t\tresolve({ profileId, versionRange }) {\n\t\t\tconst candidates = sources\n\t\t\t\t.flatMap((source) =>\n\t\t\t\t\tsource.profiles\n\t\t\t\t\t\t.filter((profile) => profile.profileId === profileId)\n\t\t\t\t\t\t.map((profile) => ({ source, profile })),\n\t\t\t\t)\n\t\t\t\t.filter(({ profile }) => {\n\t\t\t\t\tif (versionRange?.min !== undefined && compareVersions(profile.profileVersion, versionRange.min) < 0) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (versionRange?.max !== undefined && compareVersions(profile.profileVersion, versionRange.max) > 0) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.sort((a, b) => {\n\t\t\t\t\tconst versionDiff = compareVersions(b.profile.profileVersion, a.profile.profileVersion);\n\t\t\t\t\tif (versionDiff !== 0) return versionDiff;\n\t\t\t\t\treturn a.source.priority - b.source.priority;\n\t\t\t\t});\n\n\t\t\tif (candidates.length === 0) {\n\t\t\t\treturn { status: \"not_found\", profileId };\n\t\t\t}\n\n\t\t\tconst winner = candidates[0]!;\n\t\t\tif (winner.profile.deprecated !== undefined) {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"deprecated\",\n\t\t\t\t\tprofileId,\n\t\t\t\t\tprofileVersion: winner.profile.profileVersion,\n\t\t\t\t\tmanifestDigest: winner.profile.manifestDigest,\n\t\t\t\t\tsourceId: winner.source.sourceId,\n\t\t\t\t\treason: winner.profile.deprecated,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst superseded = candidates\n\t\t\t\t.slice(1)\n\t\t\t\t.filter(\n\t\t\t\t\t(candidate) => compareVersions(candidate.profile.profileVersion, winner.profile.profileVersion) === 0,\n\t\t\t\t)\n\t\t\t\t.map((candidate) => ({\n\t\t\t\t\tsourceId: candidate.source.sourceId,\n\t\t\t\t\tprofileVersion: candidate.profile.profileVersion,\n\t\t\t\t}));\n\t\t\treturn {\n\t\t\t\tstatus: \"resolved\",\n\t\t\t\tprofileId,\n\t\t\t\tprofileVersion: winner.profile.profileVersion,\n\t\t\t\tmanifestDigest: winner.profile.manifestDigest,\n\t\t\t\tsourceId: winner.source.sourceId,\n\t\t\t\tsuperseded,\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
@@ -1,3 +1,16 @@
1
+ /**
2
+ * Profile registry (2.7a) — multi-source discovery, upgrades, and
3
+ * compatibility for profile manifests on top of the minimal 2.0a identity.
4
+ *
5
+ * Sources register profiles with a priority (lower number wins). Resolution
6
+ * is deterministic and replayable: filter candidates by the requested
7
+ * version range, pick the highest version, break same-version ties by
8
+ * source priority (the losing source is reported as superseded), and mark
9
+ * deprecated winners explicitly (visible, digest still supplied — callers
10
+ * decide whether to proceed). Builds on the minimal 2.0a identity/lock
11
+ * without extending them.
12
+ */
13
+ import { t } from "../core/i18n/index.js";
1
14
  /** Segment-wise numeric semver comparison ("1.2" < "1.10" < "2.0"). */
2
15
  function compareVersions(a, b) {
3
16
  const pa = a.split(".").map((part) => Number.parseInt(part, 10) || 0);
@@ -15,7 +28,7 @@ export function createProfileRegistry() {
15
28
  return {
16
29
  registerSource(source) {
17
30
  if (sources.some((existing) => existing.sourceId === source.sourceId)) {
18
- throw new Error(`Registry source already registered: ${source.sourceId}`);
31
+ throw new Error(t("Registry source already registered: {sourceId}", { sourceId: source.sourceId }));
19
32
  }
20
33
  sources.push(source);
21
34
  },
@@ -1 +1 @@
1
- {"version":3,"file":"profile-registry.js","sourceRoot":"","sources":["../../src/profile/profile-registry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Profile registry (2.7a) — multi-source discovery, upgrades, and\n * compatibility for profile manifests on top of the minimal 2.0a identity.\n *\n * Sources register profiles with a priority (lower number wins). Resolution\n * is deterministic and replayable: filter candidates by the requested\n * version range, pick the highest version, break same-version ties by\n * source priority (the losing source is reported as superseded), and mark\n * deprecated winners explicitly (visible, digest still supplied — callers\n * decide whether to proceed). Builds on the minimal 2.0a identity/lock\n * without extending them.\n */\nexport interface RegistryProfileEntryV1 {\n\treadonly profileId: string;\n\treadonly profileVersion: string;\n\treadonly manifestDigest: string;\n\treadonly deprecated?: string;\n}\n\nexport interface RegistrySourceV1 {\n\treadonly sourceId: string;\n\t/** Lower priority number wins same-version ties. */\n\treadonly priority: number;\n\treadonly profiles: readonly RegistryProfileEntryV1[];\n}\n\nexport interface ProfileVersionRangeV1 {\n\treadonly min?: string;\n\treadonly max?: string;\n}\n\nexport type ProfileResolutionV1 =\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly profileVersion: string;\n\t\t\treadonly manifestDigest: string;\n\t\t\treadonly sourceId: string;\n\t\t\treadonly superseded: readonly { readonly sourceId: string; readonly profileVersion: string }[];\n\t }\n\t| {\n\t\t\treadonly status: \"deprecated\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly profileVersion: string;\n\t\t\treadonly manifestDigest: string;\n\t\t\treadonly sourceId: string;\n\t\t\treadonly reason: string;\n\t }\n\t| { readonly status: \"not_found\"; readonly profileId: string };\n\nexport interface ProfileRegistryV1 {\n\tregisterSource(source: RegistrySourceV1): void;\n\tresolve(input: { readonly profileId: string; readonly versionRange?: ProfileVersionRangeV1 }): ProfileResolutionV1;\n}\n\n/** Segment-wise numeric semver comparison (\"1.2\" < \"1.10\" < \"2.0\"). */\nfunction compareVersions(a: string, b: string): number {\n\tconst pa = a.split(\".\").map((part) => Number.parseInt(part, 10) || 0);\n\tconst pb = b.split(\".\").map((part) => Number.parseInt(part, 10) || 0);\n\tconst length = Math.max(pa.length, pb.length);\n\tfor (let index = 0; index < length; index += 1) {\n\t\tconst diff = (pa[index] ?? 0) - (pb[index] ?? 0);\n\t\tif (diff !== 0) return diff;\n\t}\n\treturn 0;\n}\n\nexport function createProfileRegistry(): ProfileRegistryV1 {\n\tconst sources: RegistrySourceV1[] = [];\n\n\treturn {\n\t\tregisterSource(source) {\n\t\t\tif (sources.some((existing) => existing.sourceId === source.sourceId)) {\n\t\t\t\tthrow new Error(`Registry source already registered: ${source.sourceId}`);\n\t\t\t}\n\t\t\tsources.push(source);\n\t\t},\n\t\tresolve({ profileId, versionRange }) {\n\t\t\tconst candidates = sources\n\t\t\t\t.flatMap((source) =>\n\t\t\t\t\tsource.profiles\n\t\t\t\t\t\t.filter((profile) => profile.profileId === profileId)\n\t\t\t\t\t\t.map((profile) => ({ source, profile })),\n\t\t\t\t)\n\t\t\t\t.filter(({ profile }) => {\n\t\t\t\t\tif (versionRange?.min !== undefined && compareVersions(profile.profileVersion, versionRange.min) < 0) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (versionRange?.max !== undefined && compareVersions(profile.profileVersion, versionRange.max) > 0) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.sort((a, b) => {\n\t\t\t\t\tconst versionDiff = compareVersions(b.profile.profileVersion, a.profile.profileVersion);\n\t\t\t\t\tif (versionDiff !== 0) return versionDiff;\n\t\t\t\t\treturn a.source.priority - b.source.priority;\n\t\t\t\t});\n\n\t\t\tif (candidates.length === 0) {\n\t\t\t\treturn { status: \"not_found\", profileId };\n\t\t\t}\n\n\t\t\tconst winner = candidates[0]!;\n\t\t\tif (winner.profile.deprecated !== undefined) {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"deprecated\",\n\t\t\t\t\tprofileId,\n\t\t\t\t\tprofileVersion: winner.profile.profileVersion,\n\t\t\t\t\tmanifestDigest: winner.profile.manifestDigest,\n\t\t\t\t\tsourceId: winner.source.sourceId,\n\t\t\t\t\treason: winner.profile.deprecated,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst superseded = candidates\n\t\t\t\t.slice(1)\n\t\t\t\t.filter(\n\t\t\t\t\t(candidate) => compareVersions(candidate.profile.profileVersion, winner.profile.profileVersion) === 0,\n\t\t\t\t)\n\t\t\t\t.map((candidate) => ({\n\t\t\t\t\tsourceId: candidate.source.sourceId,\n\t\t\t\t\tprofileVersion: candidate.profile.profileVersion,\n\t\t\t\t}));\n\t\t\treturn {\n\t\t\t\tstatus: \"resolved\",\n\t\t\t\tprofileId,\n\t\t\t\tprofileVersion: winner.profile.profileVersion,\n\t\t\t\tmanifestDigest: winner.profile.manifestDigest,\n\t\t\t\tsourceId: winner.source.sourceId,\n\t\t\t\tsuperseded,\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"profile-registry.js","sourceRoot":"","sources":["../../src/profile/profile-registry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Profile registry (2.7a) — multi-source discovery, upgrades, and\n * compatibility for profile manifests on top of the minimal 2.0a identity.\n *\n * Sources register profiles with a priority (lower number wins). Resolution\n * is deterministic and replayable: filter candidates by the requested\n * version range, pick the highest version, break same-version ties by\n * source priority (the losing source is reported as superseded), and mark\n * deprecated winners explicitly (visible, digest still supplied — callers\n * decide whether to proceed). Builds on the minimal 2.0a identity/lock\n * without extending them.\n */\nimport { t } from \"../core/i18n/index.ts\";\n\nexport interface RegistryProfileEntryV1 {\n\treadonly profileId: string;\n\treadonly profileVersion: string;\n\treadonly manifestDigest: string;\n\treadonly deprecated?: string;\n}\n\nexport interface RegistrySourceV1 {\n\treadonly sourceId: string;\n\t/** Lower priority number wins same-version ties. */\n\treadonly priority: number;\n\treadonly profiles: readonly RegistryProfileEntryV1[];\n}\n\nexport interface ProfileVersionRangeV1 {\n\treadonly min?: string;\n\treadonly max?: string;\n}\n\nexport type ProfileResolutionV1 =\n\t| {\n\t\t\treadonly status: \"resolved\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly profileVersion: string;\n\t\t\treadonly manifestDigest: string;\n\t\t\treadonly sourceId: string;\n\t\t\treadonly superseded: readonly { readonly sourceId: string; readonly profileVersion: string }[];\n\t }\n\t| {\n\t\t\treadonly status: \"deprecated\";\n\t\t\treadonly profileId: string;\n\t\t\treadonly profileVersion: string;\n\t\t\treadonly manifestDigest: string;\n\t\t\treadonly sourceId: string;\n\t\t\treadonly reason: string;\n\t }\n\t| { readonly status: \"not_found\"; readonly profileId: string };\n\nexport interface ProfileRegistryV1 {\n\tregisterSource(source: RegistrySourceV1): void;\n\tresolve(input: { readonly profileId: string; readonly versionRange?: ProfileVersionRangeV1 }): ProfileResolutionV1;\n}\n\n/** Segment-wise numeric semver comparison (\"1.2\" < \"1.10\" < \"2.0\"). */\nfunction compareVersions(a: string, b: string): number {\n\tconst pa = a.split(\".\").map((part) => Number.parseInt(part, 10) || 0);\n\tconst pb = b.split(\".\").map((part) => Number.parseInt(part, 10) || 0);\n\tconst length = Math.max(pa.length, pb.length);\n\tfor (let index = 0; index < length; index += 1) {\n\t\tconst diff = (pa[index] ?? 0) - (pb[index] ?? 0);\n\t\tif (diff !== 0) return diff;\n\t}\n\treturn 0;\n}\n\nexport function createProfileRegistry(): ProfileRegistryV1 {\n\tconst sources: RegistrySourceV1[] = [];\n\n\treturn {\n\t\tregisterSource(source) {\n\t\t\tif (sources.some((existing) => existing.sourceId === source.sourceId)) {\n\t\t\t\tthrow new Error(t(\"Registry source already registered: {sourceId}\", { sourceId: source.sourceId }));\n\t\t\t}\n\t\t\tsources.push(source);\n\t\t},\n\t\tresolve({ profileId, versionRange }) {\n\t\t\tconst candidates = sources\n\t\t\t\t.flatMap((source) =>\n\t\t\t\t\tsource.profiles\n\t\t\t\t\t\t.filter((profile) => profile.profileId === profileId)\n\t\t\t\t\t\t.map((profile) => ({ source, profile })),\n\t\t\t\t)\n\t\t\t\t.filter(({ profile }) => {\n\t\t\t\t\tif (versionRange?.min !== undefined && compareVersions(profile.profileVersion, versionRange.min) < 0) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (versionRange?.max !== undefined && compareVersions(profile.profileVersion, versionRange.max) > 0) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.sort((a, b) => {\n\t\t\t\t\tconst versionDiff = compareVersions(b.profile.profileVersion, a.profile.profileVersion);\n\t\t\t\t\tif (versionDiff !== 0) return versionDiff;\n\t\t\t\t\treturn a.source.priority - b.source.priority;\n\t\t\t\t});\n\n\t\t\tif (candidates.length === 0) {\n\t\t\t\treturn { status: \"not_found\", profileId };\n\t\t\t}\n\n\t\t\tconst winner = candidates[0]!;\n\t\t\tif (winner.profile.deprecated !== undefined) {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"deprecated\",\n\t\t\t\t\tprofileId,\n\t\t\t\t\tprofileVersion: winner.profile.profileVersion,\n\t\t\t\t\tmanifestDigest: winner.profile.manifestDigest,\n\t\t\t\t\tsourceId: winner.source.sourceId,\n\t\t\t\t\treason: winner.profile.deprecated,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst superseded = candidates\n\t\t\t\t.slice(1)\n\t\t\t\t.filter(\n\t\t\t\t\t(candidate) => compareVersions(candidate.profile.profileVersion, winner.profile.profileVersion) === 0,\n\t\t\t\t)\n\t\t\t\t.map((candidate) => ({\n\t\t\t\t\tsourceId: candidate.source.sourceId,\n\t\t\t\t\tprofileVersion: candidate.profile.profileVersion,\n\t\t\t\t}));\n\t\t\treturn {\n\t\t\t\tstatus: \"resolved\",\n\t\t\t\tprofileId,\n\t\t\t\tprofileVersion: winner.profile.profileVersion,\n\t\t\t\tmanifestDigest: winner.profile.manifestDigest,\n\t\t\t\tsourceId: winner.source.sourceId,\n\t\t\t\tsuperseded,\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
@@ -7,7 +7,6 @@
7
7
  * catalog. Registered roles are validated and served as detached, frozen
8
8
  * snapshots.
9
9
  */
10
- /** Memory scopes a role may write to (aligned with the 1C.1b store scopes). */
11
10
  export type RoleWritableScopeV1 = "session" | "cycle" | "long-term";
12
11
  export interface RoleCapabilityDependencyV1 {
13
12
  readonly capabilityId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"role-catalog.d.ts","sourceRoot":"","sources":["../../src/profile/role-catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,+EAA+E;AAC/E,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,CAAC;AAEpE,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC3B;AAED,2FAA2F;AAC3F,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,sBAAsB,EAAE,SAAS,0BAA0B,EAAE,CAAC;IACvE,QAAQ,CAAC,cAAc,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACxD,QAAQ,CAAC,WAAW,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC5C,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;CACpC;AAED,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,cAAc,CAAC;IACnD,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAAC;IAChD,IAAI,IAAI,SAAS,cAAc,EAAE,CAAC;IAClC,mFAAmF;IACnF,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,cAAc,EAAE,CAAC;CAClE;AAwBD,uEAAuE;AACvE,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CA0ErE;AAED,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,SAAS,cAAc,EAAO,GAAG,aAAa,CA4BxF","sourcesContent":["/**\n * Role metadata catalog (2.2a).\n *\n * Role metadata is DISCOVERY data, not a security policy: roleId, input/output\n * schema references, capability dependencies, writable memory scopes,\n * concurrency, and completion criteria are all discoverable through the\n * catalog. Registered roles are validated and served as detached, frozen\n * snapshots.\n */\n\n/** Memory scopes a role may write to (aligned with the 1C.1b store scopes). */\nexport type RoleWritableScopeV1 = \"session\" | \"cycle\" | \"long-term\";\n\nexport interface RoleCapabilityDependencyV1 {\n\treadonly capabilityId: string;\n\treadonly capabilityVersion: number;\n\t/** Required dependencies fail role activation when missing. */\n\treadonly required: boolean;\n}\n\n/** Versioned input/output schema reference (schema bodies live with the domain plugin). */\nexport interface RoleIOSchemaRefV1 {\n\treadonly schemaId: string;\n\treadonly schemaVersion: number;\n}\n\nexport interface RoleMetadataV1 {\n\treadonly roleId: string;\n\treadonly title: string;\n\treadonly input: RoleIOSchemaRefV1;\n\treadonly output: RoleIOSchemaRefV1;\n\treadonly capabilityDependencies: readonly RoleCapabilityDependencyV1[];\n\treadonly writableScopes: readonly RoleWritableScopeV1[];\n\treadonly concurrency: \"single\" | \"parallel\";\n\treadonly completionCriteria: string;\n}\n\nexport interface RoleCatalogV1 {\n\tregister(metadata: RoleMetadataV1): RoleMetadataV1;\n\tget(roleId: string): RoleMetadataV1 | undefined;\n\tlist(): readonly RoleMetadataV1[];\n\t/** Roles declaring the given capability as a dependency (required or optional). */\n\tfindByCapability(capabilityId: string): readonly RoleMetadataV1[];\n}\n\nconst WRITABLE_SCOPES: readonly RoleWritableScopeV1[] = [\"session\", \"cycle\", \"long-term\"];\n\nfunction assertNonEmptyString(value: unknown, label: string): asserts value is string {\n\tif (typeof value !== \"string\" || value.trim().length === 0) throw new Error(`${label} must be a non-empty string`);\n}\n\nfunction assertIOSchemaRef(value: unknown, label: string): RoleIOSchemaRefV1 {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new Error(`${label} must be a plain object`);\n\t}\n\tconst record = value as Record<string, unknown>;\n\tassertNonEmptyString(record.schemaId, `${label}.schemaId`);\n\tif (\n\t\ttypeof record.schemaVersion !== \"number\" ||\n\t\t!Number.isSafeInteger(record.schemaVersion) ||\n\t\trecord.schemaVersion < 1\n\t) {\n\t\tthrow new Error(`${label}.schemaVersion must be a positive safe integer`);\n\t}\n\treturn Object.freeze({ schemaId: record.schemaId, schemaVersion: record.schemaVersion });\n}\n\n/** Validates role metadata and returns a detached, frozen snapshot. */\nexport function validateRoleMetadataV1(value: unknown): RoleMetadataV1 {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new Error(\"Role metadata must be a plain object\");\n\t}\n\tconst record = value as Record<string, unknown>;\n\tconst required = [\n\t\t\"roleId\",\n\t\t\"title\",\n\t\t\"input\",\n\t\t\"output\",\n\t\t\"capabilityDependencies\",\n\t\t\"writableScopes\",\n\t\t\"concurrency\",\n\t\t\"completionCriteria\",\n\t];\n\tfor (const key of required) {\n\t\tif (!(key in record)) throw new Error(`Role metadata is missing required field: ${key}`);\n\t}\n\tconst unsupported = Object.keys(record)\n\t\t.filter((key) => !required.includes(key))\n\t\t.sort();\n\tif (unsupported.length > 0) throw new Error(`Role metadata has unsupported fields: ${unsupported.join(\", \")}`);\n\n\tassertNonEmptyString(record.roleId, \"Role metadata.roleId\");\n\tassertNonEmptyString(record.title, \"Role metadata.title\");\n\tconst input = assertIOSchemaRef(record.input, \"Role metadata.input\");\n\tconst output = assertIOSchemaRef(record.output, \"Role metadata.output\");\n\n\tif (!Array.isArray(record.capabilityDependencies)) {\n\t\tthrow new Error(\"Role metadata.capabilityDependencies must be an array\");\n\t}\n\tconst capabilityDependencies = record.capabilityDependencies.map((item, index) => {\n\t\tconst depLabel = `Role metadata.capabilityDependencies[${index}]`;\n\t\tif (item === null || typeof item !== \"object\" || Array.isArray(item)) {\n\t\t\tthrow new Error(`${depLabel} must be a plain object`);\n\t\t}\n\t\tconst dep = item as Record<string, unknown>;\n\t\tassertNonEmptyString(dep.capabilityId, `${depLabel}.capabilityId`);\n\t\tif (\n\t\t\ttypeof dep.capabilityVersion !== \"number\" ||\n\t\t\t!Number.isSafeInteger(dep.capabilityVersion) ||\n\t\t\tdep.capabilityVersion < 1\n\t\t) {\n\t\t\tthrow new Error(`${depLabel}.capabilityVersion must be a positive safe integer`);\n\t\t}\n\t\tif (typeof dep.required !== \"boolean\") throw new Error(`${depLabel}.required must be boolean`);\n\t\treturn Object.freeze({\n\t\t\tcapabilityId: dep.capabilityId,\n\t\t\tcapabilityVersion: dep.capabilityVersion,\n\t\t\trequired: dep.required,\n\t\t});\n\t});\n\n\tif (!Array.isArray(record.writableScopes)) throw new Error(\"Role metadata.writableScopes must be an array\");\n\tfor (const [index, scope] of record.writableScopes.entries()) {\n\t\tif (!WRITABLE_SCOPES.includes(scope as RoleWritableScopeV1)) {\n\t\t\tthrow new Error(`Role metadata.writableScopes[${index}] is invalid`);\n\t\t}\n\t}\n\tassertNonEmptyString(record.completionCriteria, \"Role metadata.completionCriteria\");\n\tif (record.concurrency !== \"single\" && record.concurrency !== \"parallel\") {\n\t\tthrow new Error(\"Role metadata.concurrency is invalid\");\n\t}\n\n\treturn Object.freeze({\n\t\troleId: record.roleId,\n\t\ttitle: record.title,\n\t\tinput,\n\t\toutput,\n\t\tcapabilityDependencies: Object.freeze(capabilityDependencies),\n\t\twritableScopes: Object.freeze([...(record.writableScopes as readonly RoleWritableScopeV1[])]),\n\t\tconcurrency: record.concurrency as RoleMetadataV1[\"concurrency\"],\n\t\tcompletionCriteria: record.completionCriteria,\n\t});\n}\n\n/** Discoverable role catalog: register, get, list (sorted), find by capability. */\nexport function createRoleCatalog(initial: readonly RoleMetadataV1[] = []): RoleCatalogV1 {\n\tconst roles = new Map<string, RoleMetadataV1>();\n\tfor (const metadata of initial) {\n\t\tconst validated = validateRoleMetadataV1(metadata);\n\t\tif (roles.has(validated.roleId)) throw new Error(`Role already registered: ${validated.roleId}`);\n\t\troles.set(validated.roleId, validated);\n\t}\n\treturn {\n\t\tregister(metadata) {\n\t\t\tconst validated = validateRoleMetadataV1(metadata);\n\t\t\tif (roles.has(validated.roleId)) throw new Error(`Role already registered: ${validated.roleId}`);\n\t\t\troles.set(validated.roleId, validated);\n\t\t\treturn validated;\n\t\t},\n\t\tget(roleId) {\n\t\t\treturn roles.get(roleId);\n\t\t},\n\t\tlist() {\n\t\t\treturn Object.freeze([...roles.values()].sort((left, right) => left.roleId.localeCompare(right.roleId)));\n\t\t},\n\t\tfindByCapability(capabilityId) {\n\t\t\treturn Object.freeze(\n\t\t\t\t[...roles.values()].filter((role) =>\n\t\t\t\t\trole.capabilityDependencies.some((dependency) => dependency.capabilityId === capabilityId),\n\t\t\t\t),\n\t\t\t);\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"role-catalog.d.ts","sourceRoot":"","sources":["../../src/profile/role-catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,CAAC;AAEpE,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC3B;AAED,2FAA2F;AAC3F,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,sBAAsB,EAAE,SAAS,0BAA0B,EAAE,CAAC;IACvE,QAAQ,CAAC,cAAc,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACxD,QAAQ,CAAC,WAAW,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC5C,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;CACpC;AAED,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,cAAc,CAAC;IACnD,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAAC;IAChD,IAAI,IAAI,SAAS,cAAc,EAAE,CAAC;IAClC,mFAAmF;IACnF,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,cAAc,EAAE,CAAC;CAClE;AAyBD,uEAAuE;AACvE,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CA4ErE;AAED,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,SAAS,cAAc,EAAO,GAAG,aAAa,CA8BxF","sourcesContent":["/**\n * Role metadata catalog (2.2a).\n *\n * Role metadata is DISCOVERY data, not a security policy: roleId, input/output\n * schema references, capability dependencies, writable memory scopes,\n * concurrency, and completion criteria are all discoverable through the\n * catalog. Registered roles are validated and served as detached, frozen\n * snapshots.\n */\n\n/** Memory scopes a role may write to (aligned with the 1C.1b store scopes). */\nimport { t } from \"../core/i18n/index.ts\";\n\nexport type RoleWritableScopeV1 = \"session\" | \"cycle\" | \"long-term\";\n\nexport interface RoleCapabilityDependencyV1 {\n\treadonly capabilityId: string;\n\treadonly capabilityVersion: number;\n\t/** Required dependencies fail role activation when missing. */\n\treadonly required: boolean;\n}\n\n/** Versioned input/output schema reference (schema bodies live with the domain plugin). */\nexport interface RoleIOSchemaRefV1 {\n\treadonly schemaId: string;\n\treadonly schemaVersion: number;\n}\n\nexport interface RoleMetadataV1 {\n\treadonly roleId: string;\n\treadonly title: string;\n\treadonly input: RoleIOSchemaRefV1;\n\treadonly output: RoleIOSchemaRefV1;\n\treadonly capabilityDependencies: readonly RoleCapabilityDependencyV1[];\n\treadonly writableScopes: readonly RoleWritableScopeV1[];\n\treadonly concurrency: \"single\" | \"parallel\";\n\treadonly completionCriteria: string;\n}\n\nexport interface RoleCatalogV1 {\n\tregister(metadata: RoleMetadataV1): RoleMetadataV1;\n\tget(roleId: string): RoleMetadataV1 | undefined;\n\tlist(): readonly RoleMetadataV1[];\n\t/** Roles declaring the given capability as a dependency (required or optional). */\n\tfindByCapability(capabilityId: string): readonly RoleMetadataV1[];\n}\n\nconst WRITABLE_SCOPES: readonly RoleWritableScopeV1[] = [\"session\", \"cycle\", \"long-term\"];\n\nfunction assertNonEmptyString(value: unknown, label: string): asserts value is string {\n\tif (typeof value !== \"string\" || value.trim().length === 0)\n\t\tthrow new Error(t(\"{label} must be a non-empty string\", { label }));\n}\n\nfunction assertIOSchemaRef(value: unknown, label: string): RoleIOSchemaRefV1 {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new Error(t(\"{label} must be a plain object\", { label }));\n\t}\n\tconst record = value as Record<string, unknown>;\n\tassertNonEmptyString(record.schemaId, `${label}.schemaId`);\n\tif (\n\t\ttypeof record.schemaVersion !== \"number\" ||\n\t\t!Number.isSafeInteger(record.schemaVersion) ||\n\t\trecord.schemaVersion < 1\n\t) {\n\t\tthrow new Error(t(\"{label}.schemaVersion must be a positive safe integer\", { label }));\n\t}\n\treturn Object.freeze({ schemaId: record.schemaId, schemaVersion: record.schemaVersion });\n}\n\n/** Validates role metadata and returns a detached, frozen snapshot. */\nexport function validateRoleMetadataV1(value: unknown): RoleMetadataV1 {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new Error(t(\"Role metadata must be a plain object\"));\n\t}\n\tconst record = value as Record<string, unknown>;\n\tconst required = [\n\t\t\"roleId\",\n\t\t\"title\",\n\t\t\"input\",\n\t\t\"output\",\n\t\t\"capabilityDependencies\",\n\t\t\"writableScopes\",\n\t\t\"concurrency\",\n\t\t\"completionCriteria\",\n\t];\n\tfor (const key of required) {\n\t\tif (!(key in record)) throw new Error(t(\"Role metadata is missing required field: {key}\", { key }));\n\t}\n\tconst unsupported = Object.keys(record)\n\t\t.filter((key) => !required.includes(key))\n\t\t.sort();\n\tif (unsupported.length > 0)\n\t\tthrow new Error(t(\"Role metadata has unsupported fields: {fields}\", { fields: unsupported.join(\", \") }));\n\n\tassertNonEmptyString(record.roleId, \"Role metadata.roleId\");\n\tassertNonEmptyString(record.title, \"Role metadata.title\");\n\tconst input = assertIOSchemaRef(record.input, \"Role metadata.input\");\n\tconst output = assertIOSchemaRef(record.output, \"Role metadata.output\");\n\n\tif (!Array.isArray(record.capabilityDependencies)) {\n\t\tthrow new Error(t(\"Role metadata.capabilityDependencies must be an array\"));\n\t}\n\tconst capabilityDependencies = record.capabilityDependencies.map((item, index) => {\n\t\tconst depLabel = `Role metadata.capabilityDependencies[${index}]`;\n\t\tif (item === null || typeof item !== \"object\" || Array.isArray(item)) {\n\t\t\tthrow new Error(t(\"{label} must be a plain object\", { label: depLabel }));\n\t\t}\n\t\tconst dep = item as Record<string, unknown>;\n\t\tassertNonEmptyString(dep.capabilityId, `${depLabel}.capabilityId`);\n\t\tif (\n\t\t\ttypeof dep.capabilityVersion !== \"number\" ||\n\t\t\t!Number.isSafeInteger(dep.capabilityVersion) ||\n\t\t\tdep.capabilityVersion < 1\n\t\t) {\n\t\t\tthrow new Error(t(\"{label}.capabilityVersion must be a positive safe integer\", { label: depLabel }));\n\t\t}\n\t\tif (typeof dep.required !== \"boolean\")\n\t\t\tthrow new Error(t(\"{label}.required must be boolean\", { label: depLabel }));\n\t\treturn Object.freeze({\n\t\t\tcapabilityId: dep.capabilityId,\n\t\t\tcapabilityVersion: dep.capabilityVersion,\n\t\t\trequired: dep.required,\n\t\t});\n\t});\n\n\tif (!Array.isArray(record.writableScopes)) throw new Error(t(\"Role metadata.writableScopes must be an array\"));\n\tfor (const [index, scope] of record.writableScopes.entries()) {\n\t\tif (!WRITABLE_SCOPES.includes(scope as RoleWritableScopeV1)) {\n\t\t\tthrow new Error(t(\"Role metadata.writableScopes[{index}] is invalid\", { index }));\n\t\t}\n\t}\n\tassertNonEmptyString(record.completionCriteria, \"Role metadata.completionCriteria\");\n\tif (record.concurrency !== \"single\" && record.concurrency !== \"parallel\") {\n\t\tthrow new Error(t(\"Role metadata.concurrency is invalid\"));\n\t}\n\n\treturn Object.freeze({\n\t\troleId: record.roleId,\n\t\ttitle: record.title,\n\t\tinput,\n\t\toutput,\n\t\tcapabilityDependencies: Object.freeze(capabilityDependencies),\n\t\twritableScopes: Object.freeze([...(record.writableScopes as readonly RoleWritableScopeV1[])]),\n\t\tconcurrency: record.concurrency as RoleMetadataV1[\"concurrency\"],\n\t\tcompletionCriteria: record.completionCriteria,\n\t});\n}\n\n/** Discoverable role catalog: register, get, list (sorted), find by capability. */\nexport function createRoleCatalog(initial: readonly RoleMetadataV1[] = []): RoleCatalogV1 {\n\tconst roles = new Map<string, RoleMetadataV1>();\n\tfor (const metadata of initial) {\n\t\tconst validated = validateRoleMetadataV1(metadata);\n\t\tif (roles.has(validated.roleId))\n\t\t\tthrow new Error(t(\"Role already registered: {roleId}\", { roleId: validated.roleId }));\n\t\troles.set(validated.roleId, validated);\n\t}\n\treturn {\n\t\tregister(metadata) {\n\t\t\tconst validated = validateRoleMetadataV1(metadata);\n\t\t\tif (roles.has(validated.roleId))\n\t\t\t\tthrow new Error(t(\"Role already registered: {roleId}\", { roleId: validated.roleId }));\n\t\t\troles.set(validated.roleId, validated);\n\t\t\treturn validated;\n\t\t},\n\t\tget(roleId) {\n\t\t\treturn roles.get(roleId);\n\t\t},\n\t\tlist() {\n\t\t\treturn Object.freeze([...roles.values()].sort((left, right) => left.roleId.localeCompare(right.roleId)));\n\t\t},\n\t\tfindByCapability(capabilityId) {\n\t\t\treturn Object.freeze(\n\t\t\t\t[...roles.values()].filter((role) =>\n\t\t\t\t\trole.capabilityDependencies.some((dependency) => dependency.capabilityId === capabilityId),\n\t\t\t\t),\n\t\t\t);\n\t\t},\n\t};\n}\n"]}
@@ -7,28 +7,30 @@
7
7
  * catalog. Registered roles are validated and served as detached, frozen
8
8
  * snapshots.
9
9
  */
10
+ /** Memory scopes a role may write to (aligned with the 1C.1b store scopes). */
11
+ import { t } from "../core/i18n/index.js";
10
12
  const WRITABLE_SCOPES = ["session", "cycle", "long-term"];
11
13
  function assertNonEmptyString(value, label) {
12
14
  if (typeof value !== "string" || value.trim().length === 0)
13
- throw new Error(`${label} must be a non-empty string`);
15
+ throw new Error(t("{label} must be a non-empty string", { label }));
14
16
  }
15
17
  function assertIOSchemaRef(value, label) {
16
18
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
17
- throw new Error(`${label} must be a plain object`);
19
+ throw new Error(t("{label} must be a plain object", { label }));
18
20
  }
19
21
  const record = value;
20
22
  assertNonEmptyString(record.schemaId, `${label}.schemaId`);
21
23
  if (typeof record.schemaVersion !== "number" ||
22
24
  !Number.isSafeInteger(record.schemaVersion) ||
23
25
  record.schemaVersion < 1) {
24
- throw new Error(`${label}.schemaVersion must be a positive safe integer`);
26
+ throw new Error(t("{label}.schemaVersion must be a positive safe integer", { label }));
25
27
  }
26
28
  return Object.freeze({ schemaId: record.schemaId, schemaVersion: record.schemaVersion });
27
29
  }
28
30
  /** Validates role metadata and returns a detached, frozen snapshot. */
29
31
  export function validateRoleMetadataV1(value) {
30
32
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
31
- throw new Error("Role metadata must be a plain object");
33
+ throw new Error(t("Role metadata must be a plain object"));
32
34
  }
33
35
  const record = value;
34
36
  const required = [
@@ -43,34 +45,34 @@ export function validateRoleMetadataV1(value) {
43
45
  ];
44
46
  for (const key of required) {
45
47
  if (!(key in record))
46
- throw new Error(`Role metadata is missing required field: ${key}`);
48
+ throw new Error(t("Role metadata is missing required field: {key}", { key }));
47
49
  }
48
50
  const unsupported = Object.keys(record)
49
51
  .filter((key) => !required.includes(key))
50
52
  .sort();
51
53
  if (unsupported.length > 0)
52
- throw new Error(`Role metadata has unsupported fields: ${unsupported.join(", ")}`);
54
+ throw new Error(t("Role metadata has unsupported fields: {fields}", { fields: unsupported.join(", ") }));
53
55
  assertNonEmptyString(record.roleId, "Role metadata.roleId");
54
56
  assertNonEmptyString(record.title, "Role metadata.title");
55
57
  const input = assertIOSchemaRef(record.input, "Role metadata.input");
56
58
  const output = assertIOSchemaRef(record.output, "Role metadata.output");
57
59
  if (!Array.isArray(record.capabilityDependencies)) {
58
- throw new Error("Role metadata.capabilityDependencies must be an array");
60
+ throw new Error(t("Role metadata.capabilityDependencies must be an array"));
59
61
  }
60
62
  const capabilityDependencies = record.capabilityDependencies.map((item, index) => {
61
63
  const depLabel = `Role metadata.capabilityDependencies[${index}]`;
62
64
  if (item === null || typeof item !== "object" || Array.isArray(item)) {
63
- throw new Error(`${depLabel} must be a plain object`);
65
+ throw new Error(t("{label} must be a plain object", { label: depLabel }));
64
66
  }
65
67
  const dep = item;
66
68
  assertNonEmptyString(dep.capabilityId, `${depLabel}.capabilityId`);
67
69
  if (typeof dep.capabilityVersion !== "number" ||
68
70
  !Number.isSafeInteger(dep.capabilityVersion) ||
69
71
  dep.capabilityVersion < 1) {
70
- throw new Error(`${depLabel}.capabilityVersion must be a positive safe integer`);
72
+ throw new Error(t("{label}.capabilityVersion must be a positive safe integer", { label: depLabel }));
71
73
  }
72
74
  if (typeof dep.required !== "boolean")
73
- throw new Error(`${depLabel}.required must be boolean`);
75
+ throw new Error(t("{label}.required must be boolean", { label: depLabel }));
74
76
  return Object.freeze({
75
77
  capabilityId: dep.capabilityId,
76
78
  capabilityVersion: dep.capabilityVersion,
@@ -78,15 +80,15 @@ export function validateRoleMetadataV1(value) {
78
80
  });
79
81
  });
80
82
  if (!Array.isArray(record.writableScopes))
81
- throw new Error("Role metadata.writableScopes must be an array");
83
+ throw new Error(t("Role metadata.writableScopes must be an array"));
82
84
  for (const [index, scope] of record.writableScopes.entries()) {
83
85
  if (!WRITABLE_SCOPES.includes(scope)) {
84
- throw new Error(`Role metadata.writableScopes[${index}] is invalid`);
86
+ throw new Error(t("Role metadata.writableScopes[{index}] is invalid", { index }));
85
87
  }
86
88
  }
87
89
  assertNonEmptyString(record.completionCriteria, "Role metadata.completionCriteria");
88
90
  if (record.concurrency !== "single" && record.concurrency !== "parallel") {
89
- throw new Error("Role metadata.concurrency is invalid");
91
+ throw new Error(t("Role metadata.concurrency is invalid"));
90
92
  }
91
93
  return Object.freeze({
92
94
  roleId: record.roleId,
@@ -105,14 +107,14 @@ export function createRoleCatalog(initial = []) {
105
107
  for (const metadata of initial) {
106
108
  const validated = validateRoleMetadataV1(metadata);
107
109
  if (roles.has(validated.roleId))
108
- throw new Error(`Role already registered: ${validated.roleId}`);
110
+ throw new Error(t("Role already registered: {roleId}", { roleId: validated.roleId }));
109
111
  roles.set(validated.roleId, validated);
110
112
  }
111
113
  return {
112
114
  register(metadata) {
113
115
  const validated = validateRoleMetadataV1(metadata);
114
116
  if (roles.has(validated.roleId))
115
- throw new Error(`Role already registered: ${validated.roleId}`);
117
+ throw new Error(t("Role already registered: {roleId}", { roleId: validated.roleId }));
116
118
  roles.set(validated.roleId, validated);
117
119
  return validated;
118
120
  },