@ai-agent-forge/agent-forge 0.86.6 → 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 +19 -1
  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":"agent-session-runtime.d.ts","sourceRoot":"","sources":["../../src/core/agent-session-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { constants, copyFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { basename, join, parse, resolve } from \"node:path\";\nimport type { ImageContent, TextContent } from \"@agent-forge/ai/compat\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport type { AgentSession } from \"./agent-session.ts\";\nimport type { AgentSessionRuntimeDiagnostic, AgentSessionServices } from \"./agent-session-services.ts\";\nimport type { AgentTaskChildProfileV1 } from \"./extensions/public-api.ts\";\nimport type { CustomMessage } from \"./messages.ts\";\nimport type { CreateAgentSessionResult, PluginRejection } from \"./sdk.ts\";\nimport { assertSessionCwdExists } from \"./session-cwd.ts\";\nimport { SessionManager } from \"./session-manager.ts\";\nimport type { SessionStartMetadata } from \"./session-start.ts\";\n\n/**\n * Result returned by runtime creation.\n *\n * The caller gets the created session, its cwd-bound services, and all\n * diagnostics collected during setup.\n */\n/**\n * Fresh session-bound context passed to `withSession()` callbacks on\n * `newSession()`, `fork()`, and `switchSession()`. It targets the replacement\n * session: every call routes into the session that became current after the\n * replacement committed.\n */\nexport interface ReplacedSessionContext {\n\tsendMessage<T = unknown>(\n\t\tmessage: Pick<CustomMessage<T>, \"customType\" | \"content\" | \"display\" | \"details\">,\n\t\toptions?: { triggerTurn?: boolean; deliverAs?: \"steer\" | \"followUp\" | \"nextTurn\" },\n\t): Promise<void>;\n\n\tsendUserMessage(\n\t\tcontent: string | (TextContent | ImageContent)[],\n\t\toptions?: { deliverAs?: \"steer\" | \"followUp\"; expandPromptTemplates?: boolean },\n\t): Promise<void>;\n}\n\nexport interface CreateAgentSessionRuntimeResult extends CreateAgentSessionResult {\n\tservices: AgentSessionServices;\n\tdiagnostics: AgentSessionRuntimeDiagnostic[];\n\t/**\n\t * 仅当工厂收到 `childProfile` 时存在:叶子会话的**可核验事实**(实际生效的工具面、\n\t * 模型、模式)。runner 侧 server 用它与请求档案比对后才允许任务起跑——\"要求了但\n\t * 没人能证明\"与\"没要求\"是同一风险。\n\t */\n\tchildFacts?: {\n\t\treadonly activeTools: readonly string[];\n\t\treadonly model?: {\n\t\t\treadonly provider: string;\n\t\t\treadonly id: string;\n\t\t\treadonly contextWindow: number;\n\t\t\treadonly maxTokens: number;\n\t\t\treadonly reasoning: boolean;\n\t\t};\n\t\treadonly capabilityMode: string;\n\t\t/** 叶子实际思考级别(档案请求了 thinkingLevel 时核验用)。 */\n\t\treadonly thinkingLevel?: string;\n\t\t/** 叶子实际生效的系统提示词追加段(档案请求了 systemPromptAppend 时核验用,已含方案 APPEND_SYSTEM.md 门控结果)。 */\n\t\treadonly systemPromptAppend?: string;\n\t};\n}\n\n/**\n * Creates a full runtime for a target cwd and session manager.\n *\n * The factory closes over process-global fixed inputs, recreates cwd-bound\n * services for the effective cwd, resolves session options against those\n * services, and finally creates the AgentSession.\n */\nexport type CreateAgentSessionRuntimeFactory = (options: {\n\tcwd: string;\n\tagentDir: string;\n\tsessionManager: SessionManager;\n\tsessionStartEvent?: SessionStartMetadata;\n\t/**\n\t * 子任务档案(AgentTaskChildProfileV1):pooled runner 的叶子会话按它收窄\n\t * (tools/mode/thinkingLevel)。父会话创建路径不传该字段——档案只服务子任务。\n\t */\n\tchildProfile?: AgentTaskChildProfileV1;\n\t/**\n\t * 子代理通信面的宿主接线(D-060 S5 pooled parity):runner 叶子装配注入\n\t * post/drainInbox 闭包(身份绑定到叶子会话),叶子会话由此获得\n\t * escalate/兄弟消息工具。父会话创建路径不传该字段。\n\t */\n\tsubagentCommunicationWiring?: import(\"./sdk.ts\").CreateAgentSessionOptions[\"subagentCommunicationWiring\"];\n\t/**\n\t * 档案 model 的目标 id(D-060 pooled parity 补口):runner 侧把叶子会话模型\n\t * 解析到**自己的 scoped models**(档案不能把会话带到 runner 未授权的模型上),\n\t * 解析不到即失败并列出可用 id。父会话创建路径不传该字段。\n\t */\n\tchildModelId?: string;\n}) => Promise<CreateAgentSessionRuntimeResult>;\n\n/**\n * Thrown when /import references a JSONL file path that does not exist.\n */\nexport class SessionImportFileNotFoundError extends Error {\n\treadonly filePath: string;\n\n\tconstructor(filePath: string) {\n\t\tsuper(`File not found: ${filePath}`);\n\t\tthis.name = \"SessionImportFileNotFoundError\";\n\t\tthis.filePath = filePath;\n\t}\n}\n\nfunction extractUserMessageText(content: string | Array<{ type: string; text?: string }>): string {\n\tif (typeof content === \"string\") {\n\t\treturn content;\n\t}\n\n\treturn content\n\t\t.filter((part): part is { type: \"text\"; text: string } => part.type === \"text\" && typeof part.text === \"string\")\n\t\t.map((part) => part.text)\n\t\t.join(\"\");\n}\n\n/** Maps suite assembly findings onto the runtime diagnostic channel as info. */\nfunction toSuiteRuntimeDiagnostics(suiteDiagnostics: readonly string[]): AgentSessionRuntimeDiagnostic[] {\n\treturn suiteDiagnostics.map((message) => ({ type: \"info\" as const, message }));\n}\n\n/**\n * Owns the current AgentSession plus its cwd-bound services.\n *\n * Session replacement methods tear down the current runtime first, then create\n * and apply the next runtime. If creation fails, the error is propagated to the\n * caller. The caller is responsible for user-facing error handling.\n */\nexport class AgentSessionRuntime {\n\tprivate rebindSession?: (session: AgentSession) => Promise<void>;\n\tprivate beforeSessionInvalidate?: () => void;\n\tprivate _session: AgentSession;\n\tprivate _services: AgentSessionServices;\n\tprivate readonly createRuntime: CreateAgentSessionRuntimeFactory;\n\tprivate _diagnostics: AgentSessionRuntimeDiagnostic[];\n\tprivate _suiteDiagnostics: readonly string[];\n\tprivate _modelFallbackMessage?: string;\n\tprivate _pluginRejections: readonly PluginRejection[];\n\n\tconstructor(\n\t\t_session: AgentSession,\n\t\t_services: AgentSessionServices,\n\t\tcreateRuntime: CreateAgentSessionRuntimeFactory,\n\t\t_diagnostics: AgentSessionRuntimeDiagnostic[] = [],\n\t\t_modelFallbackMessage?: string,\n\t\t_pluginRejections: readonly PluginRejection[] = [],\n\t\t_suiteDiagnostics: readonly string[] = [],\n\t) {\n\t\tthis._session = _session;\n\t\tthis._services = _services;\n\t\tthis.createRuntime = createRuntime;\n\t\tthis._diagnostics = _diagnostics;\n\t\tthis._suiteDiagnostics = _suiteDiagnostics;\n\t\tthis._modelFallbackMessage = _modelFallbackMessage;\n\t\tthis._pluginRejections = _pluginRejections;\n\t}\n\n\tget services(): AgentSessionServices {\n\t\treturn this._services;\n\t}\n\n\t/** /metrics 数据源共享 ref(observability 插件门面,空 = 未挂载)。 */\n\tget observabilityGetMetricsRef(): AgentSessionServices[\"observabilityGetMetricsRef\"] {\n\t\treturn this._services.observabilityGetMetricsRef;\n\t}\n\n\tget session(): AgentSession {\n\t\treturn this._session;\n\t}\n\n\tget cwd(): string {\n\t\treturn this._services.cwd;\n\t}\n\n\tget diagnostics(): readonly AgentSessionRuntimeDiagnostic[] {\n\t\treturn [...this._diagnostics, ...toSuiteRuntimeDiagnostics(this._suiteDiagnostics)];\n\t}\n\n\t/**\n\t * Suite assembly findings from the last runtime creation (initial,\n\t * /new, /fork, /switch). Surfaced as info-level entries on the\n\t * `diagnostics` channel.\n\t */\n\tget suiteDiagnostics(): readonly string[] {\n\t\treturn this._suiteDiagnostics;\n\t}\n\n\tget modelFallbackMessage(): string | undefined {\n\t\treturn this._modelFallbackMessage;\n\t}\n\n\tget pluginRejections(): readonly PluginRejection[] {\n\t\treturn this._pluginRejections;\n\t}\n\n\tsetRebindSession(rebindSession?: (session: AgentSession) => Promise<void>): void {\n\t\tthis.rebindSession = rebindSession;\n\t}\n\n\t/**\n\t * Set a synchronous callback that runs after `session_shutdown` handlers finish\n\t * but before the current session is invalidated.\n\t *\n\t * This is for host-owned UI teardown that must not yield to the event loop,\n\t * such as detaching extension-provided TUI components before the old extension\n\t * context becomes stale.\n\t */\n\tsetBeforeSessionInvalidate(beforeSessionInvalidate?: () => void): void {\n\t\tthis.beforeSessionInvalidate = beforeSessionInvalidate;\n\t}\n\n\tprivate async teardownCurrent(_reason: \"new\" | \"resume\" | \"fork\", _targetSessionFile?: string): Promise<void> {\n\t\t// Settle any active response first so the aborted turn (including tool\n\t\t// results) is persisted to the outgoing session before it is replaced.\n\t\t// Internal teardown aborts deliberately skip the interruption marker.\n\t\tawait this.session._abortInternal();\n\t\tthis.beforeSessionInvalidate?.();\n\t\tawait this.session.dispose();\n\t}\n\n\tprivate apply(result: CreateAgentSessionRuntimeResult): void {\n\t\tthis._session = result.session;\n\t\tthis._services = result.services;\n\t\tthis._diagnostics = result.diagnostics;\n\t\tthis._suiteDiagnostics = result.suiteDiagnostics;\n\t\tthis._modelFallbackMessage = result.modelFallbackMessage;\n\t\tthis._pluginRejections = result.pluginRejections;\n\t}\n\n\tprivate async finishSessionReplacement(withSession?: (ctx: ReplacedSessionContext) => Promise<void>): Promise<void> {\n\t\tif (this.rebindSession) {\n\t\t\tawait this.rebindSession(this.session);\n\t\t}\n\t\tif (withSession) {\n\t\t\tawait withSession(this.session.createReplacedSessionContext());\n\t\t}\n\t}\n\n\tasync switchSession(\n\t\tsessionPath: string,\n\t\toptions?: {\n\t\t\tcwdOverride?: string;\n\t\t\twithSession?: (ctx: ReplacedSessionContext) => Promise<void>;\n\t\t},\n\t): Promise<{ cancelled: boolean }> {\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tconst sessionManager = SessionManager.open(sessionPath, undefined, options?.cwdOverride);\n\t\tassertSessionCwdExists(sessionManager, this.cwd);\n\t\tawait this.teardownCurrent(\"resume\", sessionManager.getSessionFile());\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: sessionManager.getCwd(),\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { reason: \"resume\", previousSessionFile },\n\t\t\t}),\n\t\t);\n\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\treturn { cancelled: false };\n\t}\n\n\tasync newSession(options?: {\n\t\tparentSession?: string;\n\t\tsetup?: (sessionManager: SessionManager) => Promise<void>;\n\t\twithSession?: (ctx: ReplacedSessionContext) => Promise<void>;\n\t}): Promise<{ cancelled: boolean }> {\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tconst sessionDir = this.session.sessionManager.getSessionDir();\n\t\tconst sessionManager = this.session.sessionManager.isPersisted()\n\t\t\t? SessionManager.create(this.cwd, sessionDir)\n\t\t\t: SessionManager.inMemory(this.cwd);\n\t\tif (options?.parentSession) {\n\t\t\tsessionManager.newSession({ parentSession: options.parentSession });\n\t\t}\n\n\t\tawait this.teardownCurrent(\"new\", sessionManager.getSessionFile());\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: this.cwd,\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { reason: \"new\", previousSessionFile },\n\t\t\t}),\n\t\t);\n\t\tif (options?.setup) {\n\t\t\tawait options.setup(this.session.sessionManager);\n\t\t\tconst context = this.session.sessionManager.buildSessionContext().messages;\n\t\t\tif (this.session.contextStrategyName) {\n\t\t\t\tawait this.session.replaceContext(context);\n\t\t\t} else {\n\t\t\t\tthis.session.agent.state.messages = context;\n\t\t\t}\n\t\t}\n\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\treturn { cancelled: false };\n\t}\n\n\tasync fork(\n\t\tentryId: string,\n\t\toptions?: { position?: \"before\" | \"at\"; withSession?: (ctx: ReplacedSessionContext) => Promise<void> },\n\t): Promise<{ cancelled: boolean; selectedText?: string }> {\n\t\tconst position = options?.position ?? \"before\";\n\t\tlet targetLeafId: string | null;\n\t\tlet selectedText: string | undefined;\n\n\t\tconst selectedEntry = this.session.sessionManager.getEntry(entryId);\n\t\tif (!selectedEntry) {\n\t\t\tthrow new Error(\"Invalid entry ID for forking\");\n\t\t}\n\n\t\tif (position === \"at\") {\n\t\t\ttargetLeafId = selectedEntry.id;\n\t\t} else {\n\t\t\tif (selectedEntry.type !== \"message\" || selectedEntry.message.role !== \"user\") {\n\t\t\t\tthrow new Error(\"Invalid entry ID for forking\");\n\t\t\t}\n\t\t\ttargetLeafId = selectedEntry.parentId;\n\t\t\tselectedText = extractUserMessageText(selectedEntry.message.content);\n\t\t}\n\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tif (this.session.sessionManager.isPersisted()) {\n\t\t\tconst currentSessionFile = this.session.sessionFile;\n\t\t\tif (!currentSessionFile) {\n\t\t\t\tthrow new Error(\"Persisted session is missing a session file\");\n\t\t\t}\n\t\t\tconst sessionDir = this.session.sessionManager.getSessionDir();\n\t\t\tif (!targetLeafId) {\n\t\t\t\tconst sessionManager = SessionManager.create(this.cwd, sessionDir);\n\t\t\t\tsessionManager.newSession({ parentSession: currentSessionFile });\n\t\t\t\tawait this.teardownCurrent(\"fork\", sessionManager.getSessionFile());\n\t\t\t\tthis.apply(\n\t\t\t\t\tawait this.createRuntime({\n\t\t\t\t\t\tcwd: this.cwd,\n\t\t\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\t\t\tsessionManager,\n\t\t\t\t\t\tsessionStartEvent: { reason: \"fork\", previousSessionFile },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\t\t\treturn { cancelled: false, selectedText };\n\t\t\t}\n\n\t\t\tif (!existsSync(currentSessionFile)) {\n\t\t\t\tthrow new Error(\"This session has not been saved yet. Send a message before cloning or forking it.\");\n\t\t\t}\n\t\t\tconst sessionManager = SessionManager.open(currentSessionFile, sessionDir);\n\t\t\tconst forkedSessionPath = sessionManager.createBranchedSession(targetLeafId);\n\t\t\tif (!forkedSessionPath) {\n\t\t\t\tthrow new Error(\"Failed to create forked session\");\n\t\t\t}\n\t\t\tawait this.teardownCurrent(\"fork\", sessionManager.getSessionFile());\n\t\t\tthis.apply(\n\t\t\t\tawait this.createRuntime({\n\t\t\t\t\tcwd: sessionManager.getCwd(),\n\t\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\t\tsessionManager,\n\t\t\t\t\tsessionStartEvent: { reason: \"fork\", previousSessionFile },\n\t\t\t\t}),\n\t\t\t);\n\t\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\t\treturn { cancelled: false, selectedText };\n\t\t}\n\n\t\tconst sessionManager = this.session.sessionManager;\n\t\tawait this.teardownCurrent(\"fork\", sessionManager.getSessionFile());\n\t\tif (!targetLeafId) {\n\t\t\tsessionManager.newSession({ parentSession: previousSessionFile });\n\t\t} else {\n\t\t\tsessionManager.createBranchedSession(targetLeafId);\n\t\t}\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: this.cwd,\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { reason: \"fork\", previousSessionFile },\n\t\t\t}),\n\t\t);\n\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\treturn { cancelled: false, selectedText };\n\t}\n\n\t/**\n\t * Import a session JSONL file and switch runtime state to the imported session.\n\t *\n\t * @throws {SessionImportFileNotFoundError} When the input path does not exist.\n\t * @throws {MissingSessionCwdError} When the imported session cwd cannot be resolved and no override is provided.\n\t */\n\tasync importFromJsonl(inputPath: string, cwdOverride?: string): Promise<{ cancelled: boolean }> {\n\t\tconst resolvedPath = resolvePath(inputPath);\n\t\tif (!existsSync(resolvedPath)) {\n\t\t\tthrow new SessionImportFileNotFoundError(resolvedPath);\n\t\t}\n\n\t\tconst sessionDir = this.session.sessionManager.getSessionDir();\n\t\tif (!existsSync(sessionDir)) {\n\t\t\tmkdirSync(sessionDir, { recursive: true });\n\t\t}\n\n\t\tlet destinationPath = join(sessionDir, basename(resolvedPath));\n\t\tconst sourceAlreadyStored = resolve(destinationPath) === resolvedPath;\n\t\tif (!sourceAlreadyStored) {\n\t\t\tconst { name, ext } = parse(destinationPath);\n\t\t\tlet suffix = 1;\n\t\t\twhile (existsSync(destinationPath)) {\n\t\t\t\tdestinationPath = join(sessionDir, `${name}-${suffix++}${ext}`);\n\t\t\t}\n\t\t}\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tif (!sourceAlreadyStored) {\n\t\t\tcopyFileSync(resolvedPath, destinationPath, constants.COPYFILE_EXCL);\n\t\t}\n\n\t\tconst sessionManager = SessionManager.open(destinationPath, sessionDir, cwdOverride);\n\t\tassertSessionCwdExists(sessionManager, this.cwd);\n\t\tawait this.teardownCurrent(\"resume\", sessionManager.getSessionFile());\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: sessionManager.getCwd(),\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { reason: \"resume\", previousSessionFile },\n\t\t\t}),\n\t\t);\n\t\tawait this.finishSessionReplacement();\n\t\treturn { cancelled: false };\n\t}\n\n\tasync dispose(): Promise<void> {\n\t\tthis.beforeSessionInvalidate?.();\n\t\tawait this.session.dispose();\n\t}\n}\n\n/**\n * Create the initial runtime from a runtime factory and initial session target.\n *\n * The same factory is stored on the returned AgentSessionRuntime and reused for\n * later /new, /resume, /fork, and import flows.\n */\nexport async function createAgentSessionRuntime(\n\tcreateRuntime: CreateAgentSessionRuntimeFactory,\n\toptions: {\n\t\tcwd: string;\n\t\tagentDir: string;\n\t\tsessionManager: SessionManager;\n\t\tsessionStartEvent?: SessionStartMetadata;\n\t},\n): Promise<AgentSessionRuntime> {\n\tassertSessionCwdExists(options.sessionManager, options.cwd);\n\tconst result = await createRuntime(options);\n\treturn new AgentSessionRuntime(\n\t\tresult.session,\n\t\tresult.services,\n\t\tcreateRuntime,\n\t\tresult.diagnostics,\n\t\tresult.modelFallbackMessage,\n\t\tresult.pluginRejections,\n\t\tresult.suiteDiagnostics,\n\t);\n}\n\nexport {\n\ttype AgentSessionRuntimeDiagnostic,\n\ttype AgentSessionServices,\n\ttype CreateAgentSessionFromServicesOptions,\n\ttype CreateAgentSessionServicesOptions,\n\tcreateAgentSessionFromServices,\n\tcreateAgentSessionServices,\n} from \"./agent-session-services.ts\";\n"]}
1
+ {"version":3,"file":"agent-session-runtime.d.ts","sourceRoot":"","sources":["../../src/core/agent-session-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { constants, copyFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { basename, join, parse, resolve } from \"node:path\";\nimport type { ImageContent, TextContent } from \"@agent-forge/ai/compat\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport type { AgentSession } from \"./agent-session.ts\";\nimport type { AgentSessionRuntimeDiagnostic, AgentSessionServices } from \"./agent-session-services.ts\";\nimport type { AgentTaskChildProfileV1 } from \"./extensions/public-api.ts\";\nimport { t } from \"./i18n/index.ts\";\nimport type { CustomMessage } from \"./messages.ts\";\nimport type { CreateAgentSessionResult, PluginRejection } from \"./sdk.ts\";\nimport { assertSessionCwdExists } from \"./session-cwd.ts\";\nimport { SessionManager } from \"./session-manager.ts\";\nimport type { SessionStartMetadata } from \"./session-start.ts\";\n\n/**\n * Result returned by runtime creation.\n *\n * The caller gets the created session, its cwd-bound services, and all\n * diagnostics collected during setup.\n */\n/**\n * Fresh session-bound context passed to `withSession()` callbacks on\n * `newSession()`, `fork()`, and `switchSession()`. It targets the replacement\n * session: every call routes into the session that became current after the\n * replacement committed.\n */\nexport interface ReplacedSessionContext {\n\tsendMessage<T = unknown>(\n\t\tmessage: Pick<CustomMessage<T>, \"customType\" | \"content\" | \"display\" | \"details\">,\n\t\toptions?: { triggerTurn?: boolean; deliverAs?: \"steer\" | \"followUp\" | \"nextTurn\" },\n\t): Promise<void>;\n\n\tsendUserMessage(\n\t\tcontent: string | (TextContent | ImageContent)[],\n\t\toptions?: { deliverAs?: \"steer\" | \"followUp\"; expandPromptTemplates?: boolean },\n\t): Promise<void>;\n}\n\nexport interface CreateAgentSessionRuntimeResult extends CreateAgentSessionResult {\n\tservices: AgentSessionServices;\n\tdiagnostics: AgentSessionRuntimeDiagnostic[];\n\t/**\n\t * 仅当工厂收到 `childProfile` 时存在:叶子会话的**可核验事实**(实际生效的工具面、\n\t * 模型、模式)。runner 侧 server 用它与请求档案比对后才允许任务起跑——\"要求了但\n\t * 没人能证明\"与\"没要求\"是同一风险。\n\t */\n\tchildFacts?: {\n\t\treadonly activeTools: readonly string[];\n\t\treadonly model?: {\n\t\t\treadonly provider: string;\n\t\t\treadonly id: string;\n\t\t\treadonly contextWindow: number;\n\t\t\treadonly maxTokens: number;\n\t\t\treadonly reasoning: boolean;\n\t\t};\n\t\treadonly capabilityMode: string;\n\t\t/** 叶子实际思考级别(档案请求了 thinkingLevel 时核验用)。 */\n\t\treadonly thinkingLevel?: string;\n\t\t/** 叶子实际生效的系统提示词追加段(档案请求了 systemPromptAppend 时核验用,已含方案 APPEND_SYSTEM.md 门控结果)。 */\n\t\treadonly systemPromptAppend?: string;\n\t};\n}\n\n/**\n * Creates a full runtime for a target cwd and session manager.\n *\n * The factory closes over process-global fixed inputs, recreates cwd-bound\n * services for the effective cwd, resolves session options against those\n * services, and finally creates the AgentSession.\n */\nexport type CreateAgentSessionRuntimeFactory = (options: {\n\tcwd: string;\n\tagentDir: string;\n\tsessionManager: SessionManager;\n\tsessionStartEvent?: SessionStartMetadata;\n\t/**\n\t * 子任务档案(AgentTaskChildProfileV1):pooled runner 的叶子会话按它收窄\n\t * (tools/mode/thinkingLevel)。父会话创建路径不传该字段——档案只服务子任务。\n\t */\n\tchildProfile?: AgentTaskChildProfileV1;\n\t/**\n\t * 子代理通信面的宿主接线(D-060 S5 pooled parity):runner 叶子装配注入\n\t * post/drainInbox 闭包(身份绑定到叶子会话),叶子会话由此获得\n\t * escalate/兄弟消息工具。父会话创建路径不传该字段。\n\t */\n\tsubagentCommunicationWiring?: import(\"./sdk.ts\").CreateAgentSessionOptions[\"subagentCommunicationWiring\"];\n\t/**\n\t * 档案 model 的目标 id(D-060 pooled parity 补口):runner 侧把叶子会话模型\n\t * 解析到**自己的 scoped models**(档案不能把会话带到 runner 未授权的模型上),\n\t * 解析不到即失败并列出可用 id。父会话创建路径不传该字段。\n\t */\n\tchildModelId?: string;\n}) => Promise<CreateAgentSessionRuntimeResult>;\n\n/**\n * Thrown when /import references a JSONL file path that does not exist.\n */\nexport class SessionImportFileNotFoundError extends Error {\n\treadonly filePath: string;\n\n\tconstructor(filePath: string) {\n\t\tsuper(t(\"File not found: {path}\", { path: filePath }));\n\t\tthis.name = \"SessionImportFileNotFoundError\";\n\t\tthis.filePath = filePath;\n\t}\n}\n\nfunction extractUserMessageText(content: string | Array<{ type: string; text?: string }>): string {\n\tif (typeof content === \"string\") {\n\t\treturn content;\n\t}\n\n\treturn content\n\t\t.filter((part): part is { type: \"text\"; text: string } => part.type === \"text\" && typeof part.text === \"string\")\n\t\t.map((part) => part.text)\n\t\t.join(\"\");\n}\n\n/** Maps suite assembly findings onto the runtime diagnostic channel as info. */\nfunction toSuiteRuntimeDiagnostics(suiteDiagnostics: readonly string[]): AgentSessionRuntimeDiagnostic[] {\n\treturn suiteDiagnostics.map((message) => ({ type: \"info\" as const, message }));\n}\n\n/**\n * Owns the current AgentSession plus its cwd-bound services.\n *\n * Session replacement methods tear down the current runtime first, then create\n * and apply the next runtime. If creation fails, the error is propagated to the\n * caller. The caller is responsible for user-facing error handling.\n */\nexport class AgentSessionRuntime {\n\tprivate rebindSession?: (session: AgentSession) => Promise<void>;\n\tprivate beforeSessionInvalidate?: () => void;\n\tprivate _session: AgentSession;\n\tprivate _services: AgentSessionServices;\n\tprivate readonly createRuntime: CreateAgentSessionRuntimeFactory;\n\tprivate _diagnostics: AgentSessionRuntimeDiagnostic[];\n\tprivate _suiteDiagnostics: readonly string[];\n\tprivate _modelFallbackMessage?: string;\n\tprivate _pluginRejections: readonly PluginRejection[];\n\n\tconstructor(\n\t\t_session: AgentSession,\n\t\t_services: AgentSessionServices,\n\t\tcreateRuntime: CreateAgentSessionRuntimeFactory,\n\t\t_diagnostics: AgentSessionRuntimeDiagnostic[] = [],\n\t\t_modelFallbackMessage?: string,\n\t\t_pluginRejections: readonly PluginRejection[] = [],\n\t\t_suiteDiagnostics: readonly string[] = [],\n\t) {\n\t\tthis._session = _session;\n\t\tthis._services = _services;\n\t\tthis.createRuntime = createRuntime;\n\t\tthis._diagnostics = _diagnostics;\n\t\tthis._suiteDiagnostics = _suiteDiagnostics;\n\t\tthis._modelFallbackMessage = _modelFallbackMessage;\n\t\tthis._pluginRejections = _pluginRejections;\n\t}\n\n\tget services(): AgentSessionServices {\n\t\treturn this._services;\n\t}\n\n\t/** /metrics 数据源共享 ref(observability 插件门面,空 = 未挂载)。 */\n\tget observabilityGetMetricsRef(): AgentSessionServices[\"observabilityGetMetricsRef\"] {\n\t\treturn this._services.observabilityGetMetricsRef;\n\t}\n\n\tget session(): AgentSession {\n\t\treturn this._session;\n\t}\n\n\tget cwd(): string {\n\t\treturn this._services.cwd;\n\t}\n\n\tget diagnostics(): readonly AgentSessionRuntimeDiagnostic[] {\n\t\treturn [...this._diagnostics, ...toSuiteRuntimeDiagnostics(this._suiteDiagnostics)];\n\t}\n\n\t/**\n\t * Suite assembly findings from the last runtime creation (initial,\n\t * /new, /fork, /switch). Surfaced as info-level entries on the\n\t * `diagnostics` channel.\n\t */\n\tget suiteDiagnostics(): readonly string[] {\n\t\treturn this._suiteDiagnostics;\n\t}\n\n\tget modelFallbackMessage(): string | undefined {\n\t\treturn this._modelFallbackMessage;\n\t}\n\n\tget pluginRejections(): readonly PluginRejection[] {\n\t\treturn this._pluginRejections;\n\t}\n\n\tsetRebindSession(rebindSession?: (session: AgentSession) => Promise<void>): void {\n\t\tthis.rebindSession = rebindSession;\n\t}\n\n\t/**\n\t * Set a synchronous callback that runs after `session_shutdown` handlers finish\n\t * but before the current session is invalidated.\n\t *\n\t * This is for host-owned UI teardown that must not yield to the event loop,\n\t * such as detaching extension-provided TUI components before the old extension\n\t * context becomes stale.\n\t */\n\tsetBeforeSessionInvalidate(beforeSessionInvalidate?: () => void): void {\n\t\tthis.beforeSessionInvalidate = beforeSessionInvalidate;\n\t}\n\n\tprivate async teardownCurrent(_reason: \"new\" | \"resume\" | \"fork\", _targetSessionFile?: string): Promise<void> {\n\t\t// Settle any active response first so the aborted turn (including tool\n\t\t// results) is persisted to the outgoing session before it is replaced.\n\t\t// Internal teardown aborts deliberately skip the interruption marker.\n\t\tawait this.session._abortInternal();\n\t\tthis.beforeSessionInvalidate?.();\n\t\tawait this.session.dispose();\n\t}\n\n\tprivate apply(result: CreateAgentSessionRuntimeResult): void {\n\t\tthis._session = result.session;\n\t\tthis._services = result.services;\n\t\tthis._diagnostics = result.diagnostics;\n\t\tthis._suiteDiagnostics = result.suiteDiagnostics;\n\t\tthis._modelFallbackMessage = result.modelFallbackMessage;\n\t\tthis._pluginRejections = result.pluginRejections;\n\t}\n\n\tprivate async finishSessionReplacement(withSession?: (ctx: ReplacedSessionContext) => Promise<void>): Promise<void> {\n\t\tif (this.rebindSession) {\n\t\t\tawait this.rebindSession(this.session);\n\t\t}\n\t\tif (withSession) {\n\t\t\tawait withSession(this.session.createReplacedSessionContext());\n\t\t}\n\t}\n\n\tasync switchSession(\n\t\tsessionPath: string,\n\t\toptions?: {\n\t\t\tcwdOverride?: string;\n\t\t\twithSession?: (ctx: ReplacedSessionContext) => Promise<void>;\n\t\t},\n\t): Promise<{ cancelled: boolean }> {\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tconst sessionManager = SessionManager.open(sessionPath, undefined, options?.cwdOverride);\n\t\tassertSessionCwdExists(sessionManager, this.cwd);\n\t\tawait this.teardownCurrent(\"resume\", sessionManager.getSessionFile());\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: sessionManager.getCwd(),\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { reason: \"resume\", previousSessionFile },\n\t\t\t}),\n\t\t);\n\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\treturn { cancelled: false };\n\t}\n\n\tasync newSession(options?: {\n\t\tparentSession?: string;\n\t\tsetup?: (sessionManager: SessionManager) => Promise<void>;\n\t\twithSession?: (ctx: ReplacedSessionContext) => Promise<void>;\n\t}): Promise<{ cancelled: boolean }> {\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tconst sessionDir = this.session.sessionManager.getSessionDir();\n\t\tconst sessionManager = this.session.sessionManager.isPersisted()\n\t\t\t? SessionManager.create(this.cwd, sessionDir)\n\t\t\t: SessionManager.inMemory(this.cwd);\n\t\tif (options?.parentSession) {\n\t\t\tsessionManager.newSession({ parentSession: options.parentSession });\n\t\t}\n\n\t\tawait this.teardownCurrent(\"new\", sessionManager.getSessionFile());\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: this.cwd,\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { reason: \"new\", previousSessionFile },\n\t\t\t}),\n\t\t);\n\t\tif (options?.setup) {\n\t\t\tawait options.setup(this.session.sessionManager);\n\t\t\tconst context = this.session.sessionManager.buildSessionContext().messages;\n\t\t\tif (this.session.contextStrategyName) {\n\t\t\t\tawait this.session.replaceContext(context);\n\t\t\t} else {\n\t\t\t\tthis.session.agent.state.messages = context;\n\t\t\t}\n\t\t}\n\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\treturn { cancelled: false };\n\t}\n\n\tasync fork(\n\t\tentryId: string,\n\t\toptions?: { position?: \"before\" | \"at\"; withSession?: (ctx: ReplacedSessionContext) => Promise<void> },\n\t): Promise<{ cancelled: boolean; selectedText?: string }> {\n\t\tconst position = options?.position ?? \"before\";\n\t\tlet targetLeafId: string | null;\n\t\tlet selectedText: string | undefined;\n\n\t\tconst selectedEntry = this.session.sessionManager.getEntry(entryId);\n\t\tif (!selectedEntry) {\n\t\t\tthrow new Error(t(\"Invalid entry ID for forking\"));\n\t\t}\n\n\t\tif (position === \"at\") {\n\t\t\ttargetLeafId = selectedEntry.id;\n\t\t} else {\n\t\t\tif (selectedEntry.type !== \"message\" || selectedEntry.message.role !== \"user\") {\n\t\t\t\tthrow new Error(t(\"Invalid entry ID for forking\"));\n\t\t\t}\n\t\t\ttargetLeafId = selectedEntry.parentId;\n\t\t\tselectedText = extractUserMessageText(selectedEntry.message.content);\n\t\t}\n\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tif (this.session.sessionManager.isPersisted()) {\n\t\t\tconst currentSessionFile = this.session.sessionFile;\n\t\t\tif (!currentSessionFile) {\n\t\t\t\tthrow new Error(t(\"Persisted session is missing a session file\"));\n\t\t\t}\n\t\t\tconst sessionDir = this.session.sessionManager.getSessionDir();\n\t\t\tif (!targetLeafId) {\n\t\t\t\tconst sessionManager = SessionManager.create(this.cwd, sessionDir);\n\t\t\t\tsessionManager.newSession({ parentSession: currentSessionFile });\n\t\t\t\tawait this.teardownCurrent(\"fork\", sessionManager.getSessionFile());\n\t\t\t\tthis.apply(\n\t\t\t\t\tawait this.createRuntime({\n\t\t\t\t\t\tcwd: this.cwd,\n\t\t\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\t\t\tsessionManager,\n\t\t\t\t\t\tsessionStartEvent: { reason: \"fork\", previousSessionFile },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\t\t\treturn { cancelled: false, selectedText };\n\t\t\t}\n\n\t\t\tif (!existsSync(currentSessionFile)) {\n\t\t\t\tthrow new Error(t(\"This session has not been saved yet. Send a message before cloning or forking it.\"));\n\t\t\t}\n\t\t\tconst sessionManager = SessionManager.open(currentSessionFile, sessionDir);\n\t\t\tconst forkedSessionPath = sessionManager.createBranchedSession(targetLeafId);\n\t\t\tif (!forkedSessionPath) {\n\t\t\t\tthrow new Error(t(\"Failed to create forked session\"));\n\t\t\t}\n\t\t\tawait this.teardownCurrent(\"fork\", sessionManager.getSessionFile());\n\t\t\tthis.apply(\n\t\t\t\tawait this.createRuntime({\n\t\t\t\t\tcwd: sessionManager.getCwd(),\n\t\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\t\tsessionManager,\n\t\t\t\t\tsessionStartEvent: { reason: \"fork\", previousSessionFile },\n\t\t\t\t}),\n\t\t\t);\n\t\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\t\treturn { cancelled: false, selectedText };\n\t\t}\n\n\t\tconst sessionManager = this.session.sessionManager;\n\t\tawait this.teardownCurrent(\"fork\", sessionManager.getSessionFile());\n\t\tif (!targetLeafId) {\n\t\t\tsessionManager.newSession({ parentSession: previousSessionFile });\n\t\t} else {\n\t\t\tsessionManager.createBranchedSession(targetLeafId);\n\t\t}\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: this.cwd,\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { reason: \"fork\", previousSessionFile },\n\t\t\t}),\n\t\t);\n\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\treturn { cancelled: false, selectedText };\n\t}\n\n\t/**\n\t * Import a session JSONL file and switch runtime state to the imported session.\n\t *\n\t * @throws {SessionImportFileNotFoundError} When the input path does not exist.\n\t * @throws {MissingSessionCwdError} When the imported session cwd cannot be resolved and no override is provided.\n\t */\n\tasync importFromJsonl(inputPath: string, cwdOverride?: string): Promise<{ cancelled: boolean }> {\n\t\tconst resolvedPath = resolvePath(inputPath);\n\t\tif (!existsSync(resolvedPath)) {\n\t\t\tthrow new SessionImportFileNotFoundError(resolvedPath);\n\t\t}\n\n\t\tconst sessionDir = this.session.sessionManager.getSessionDir();\n\t\tif (!existsSync(sessionDir)) {\n\t\t\tmkdirSync(sessionDir, { recursive: true });\n\t\t}\n\n\t\tlet destinationPath = join(sessionDir, basename(resolvedPath));\n\t\tconst sourceAlreadyStored = resolve(destinationPath) === resolvedPath;\n\t\tif (!sourceAlreadyStored) {\n\t\t\tconst { name, ext } = parse(destinationPath);\n\t\t\tlet suffix = 1;\n\t\t\twhile (existsSync(destinationPath)) {\n\t\t\t\tdestinationPath = join(sessionDir, `${name}-${suffix++}${ext}`);\n\t\t\t}\n\t\t}\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tif (!sourceAlreadyStored) {\n\t\t\tcopyFileSync(resolvedPath, destinationPath, constants.COPYFILE_EXCL);\n\t\t}\n\n\t\tconst sessionManager = SessionManager.open(destinationPath, sessionDir, cwdOverride);\n\t\tassertSessionCwdExists(sessionManager, this.cwd);\n\t\tawait this.teardownCurrent(\"resume\", sessionManager.getSessionFile());\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: sessionManager.getCwd(),\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { reason: \"resume\", previousSessionFile },\n\t\t\t}),\n\t\t);\n\t\tawait this.finishSessionReplacement();\n\t\treturn { cancelled: false };\n\t}\n\n\tasync dispose(): Promise<void> {\n\t\tthis.beforeSessionInvalidate?.();\n\t\tawait this.session.dispose();\n\t}\n}\n\n/**\n * Create the initial runtime from a runtime factory and initial session target.\n *\n * The same factory is stored on the returned AgentSessionRuntime and reused for\n * later /new, /resume, /fork, and import flows.\n */\nexport async function createAgentSessionRuntime(\n\tcreateRuntime: CreateAgentSessionRuntimeFactory,\n\toptions: {\n\t\tcwd: string;\n\t\tagentDir: string;\n\t\tsessionManager: SessionManager;\n\t\tsessionStartEvent?: SessionStartMetadata;\n\t},\n): Promise<AgentSessionRuntime> {\n\tassertSessionCwdExists(options.sessionManager, options.cwd);\n\tconst result = await createRuntime(options);\n\treturn new AgentSessionRuntime(\n\t\tresult.session,\n\t\tresult.services,\n\t\tcreateRuntime,\n\t\tresult.diagnostics,\n\t\tresult.modelFallbackMessage,\n\t\tresult.pluginRejections,\n\t\tresult.suiteDiagnostics,\n\t);\n}\n\nexport {\n\ttype AgentSessionRuntimeDiagnostic,\n\ttype AgentSessionServices,\n\ttype CreateAgentSessionFromServicesOptions,\n\ttype CreateAgentSessionServicesOptions,\n\tcreateAgentSessionFromServices,\n\tcreateAgentSessionServices,\n} from \"./agent-session-services.ts\";\n"]}
@@ -1,6 +1,7 @@
1
1
  import { constants, copyFileSync, existsSync, mkdirSync } from "node:fs";
2
2
  import { basename, join, parse, resolve } from "node:path";
3
3
  import { resolvePath } from "../utils/paths.js";
4
+ import { t } from "./i18n/index.js";
4
5
  import { assertSessionCwdExists } from "./session-cwd.js";
5
6
  import { SessionManager } from "./session-manager.js";
6
7
  /**
@@ -9,7 +10,7 @@ import { SessionManager } from "./session-manager.js";
9
10
  export class SessionImportFileNotFoundError extends Error {
10
11
  filePath;
11
12
  constructor(filePath) {
12
- super(`File not found: ${filePath}`);
13
+ super(t("File not found: {path}", { path: filePath }));
13
14
  this.name = "SessionImportFileNotFoundError";
14
15
  this.filePath = filePath;
15
16
  }
@@ -170,14 +171,14 @@ export class AgentSessionRuntime {
170
171
  let selectedText;
171
172
  const selectedEntry = this.session.sessionManager.getEntry(entryId);
172
173
  if (!selectedEntry) {
173
- throw new Error("Invalid entry ID for forking");
174
+ throw new Error(t("Invalid entry ID for forking"));
174
175
  }
175
176
  if (position === "at") {
176
177
  targetLeafId = selectedEntry.id;
177
178
  }
178
179
  else {
179
180
  if (selectedEntry.type !== "message" || selectedEntry.message.role !== "user") {
180
- throw new Error("Invalid entry ID for forking");
181
+ throw new Error(t("Invalid entry ID for forking"));
181
182
  }
182
183
  targetLeafId = selectedEntry.parentId;
183
184
  selectedText = extractUserMessageText(selectedEntry.message.content);
@@ -186,7 +187,7 @@ export class AgentSessionRuntime {
186
187
  if (this.session.sessionManager.isPersisted()) {
187
188
  const currentSessionFile = this.session.sessionFile;
188
189
  if (!currentSessionFile) {
189
- throw new Error("Persisted session is missing a session file");
190
+ throw new Error(t("Persisted session is missing a session file"));
190
191
  }
191
192
  const sessionDir = this.session.sessionManager.getSessionDir();
192
193
  if (!targetLeafId) {
@@ -203,12 +204,12 @@ export class AgentSessionRuntime {
203
204
  return { cancelled: false, selectedText };
204
205
  }
205
206
  if (!existsSync(currentSessionFile)) {
206
- throw new Error("This session has not been saved yet. Send a message before cloning or forking it.");
207
+ throw new Error(t("This session has not been saved yet. Send a message before cloning or forking it."));
207
208
  }
208
209
  const sessionManager = SessionManager.open(currentSessionFile, sessionDir);
209
210
  const forkedSessionPath = sessionManager.createBranchedSession(targetLeafId);
210
211
  if (!forkedSessionPath) {
211
- throw new Error("Failed to create forked session");
212
+ throw new Error(t("Failed to create forked session"));
212
213
  }
213
214
  await this.teardownCurrent("fork", sessionManager.getSessionFile());
214
215
  this.apply(await this.createRuntime({
@@ -1 +1 @@
1
- {"version":3,"file":"agent-session-runtime.js","sourceRoot":"","sources":["../../src/core/agent-session-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { constants, copyFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { basename, join, parse, resolve } from \"node:path\";\nimport type { ImageContent, TextContent } from \"@agent-forge/ai/compat\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport type { AgentSession } from \"./agent-session.ts\";\nimport type { AgentSessionRuntimeDiagnostic, AgentSessionServices } from \"./agent-session-services.ts\";\nimport type { AgentTaskChildProfileV1 } from \"./extensions/public-api.ts\";\nimport type { CustomMessage } from \"./messages.ts\";\nimport type { CreateAgentSessionResult, PluginRejection } from \"./sdk.ts\";\nimport { assertSessionCwdExists } from \"./session-cwd.ts\";\nimport { SessionManager } from \"./session-manager.ts\";\nimport type { SessionStartMetadata } from \"./session-start.ts\";\n\n/**\n * Result returned by runtime creation.\n *\n * The caller gets the created session, its cwd-bound services, and all\n * diagnostics collected during setup.\n */\n/**\n * Fresh session-bound context passed to `withSession()` callbacks on\n * `newSession()`, `fork()`, and `switchSession()`. It targets the replacement\n * session: every call routes into the session that became current after the\n * replacement committed.\n */\nexport interface ReplacedSessionContext {\n\tsendMessage<T = unknown>(\n\t\tmessage: Pick<CustomMessage<T>, \"customType\" | \"content\" | \"display\" | \"details\">,\n\t\toptions?: { triggerTurn?: boolean; deliverAs?: \"steer\" | \"followUp\" | \"nextTurn\" },\n\t): Promise<void>;\n\n\tsendUserMessage(\n\t\tcontent: string | (TextContent | ImageContent)[],\n\t\toptions?: { deliverAs?: \"steer\" | \"followUp\"; expandPromptTemplates?: boolean },\n\t): Promise<void>;\n}\n\nexport interface CreateAgentSessionRuntimeResult extends CreateAgentSessionResult {\n\tservices: AgentSessionServices;\n\tdiagnostics: AgentSessionRuntimeDiagnostic[];\n\t/**\n\t * 仅当工厂收到 `childProfile` 时存在:叶子会话的**可核验事实**(实际生效的工具面、\n\t * 模型、模式)。runner 侧 server 用它与请求档案比对后才允许任务起跑——\"要求了但\n\t * 没人能证明\"与\"没要求\"是同一风险。\n\t */\n\tchildFacts?: {\n\t\treadonly activeTools: readonly string[];\n\t\treadonly model?: {\n\t\t\treadonly provider: string;\n\t\t\treadonly id: string;\n\t\t\treadonly contextWindow: number;\n\t\t\treadonly maxTokens: number;\n\t\t\treadonly reasoning: boolean;\n\t\t};\n\t\treadonly capabilityMode: string;\n\t\t/** 叶子实际思考级别(档案请求了 thinkingLevel 时核验用)。 */\n\t\treadonly thinkingLevel?: string;\n\t\t/** 叶子实际生效的系统提示词追加段(档案请求了 systemPromptAppend 时核验用,已含方案 APPEND_SYSTEM.md 门控结果)。 */\n\t\treadonly systemPromptAppend?: string;\n\t};\n}\n\n/**\n * Creates a full runtime for a target cwd and session manager.\n *\n * The factory closes over process-global fixed inputs, recreates cwd-bound\n * services for the effective cwd, resolves session options against those\n * services, and finally creates the AgentSession.\n */\nexport type CreateAgentSessionRuntimeFactory = (options: {\n\tcwd: string;\n\tagentDir: string;\n\tsessionManager: SessionManager;\n\tsessionStartEvent?: SessionStartMetadata;\n\t/**\n\t * 子任务档案(AgentTaskChildProfileV1):pooled runner 的叶子会话按它收窄\n\t * (tools/mode/thinkingLevel)。父会话创建路径不传该字段——档案只服务子任务。\n\t */\n\tchildProfile?: AgentTaskChildProfileV1;\n\t/**\n\t * 子代理通信面的宿主接线(D-060 S5 pooled parity):runner 叶子装配注入\n\t * post/drainInbox 闭包(身份绑定到叶子会话),叶子会话由此获得\n\t * escalate/兄弟消息工具。父会话创建路径不传该字段。\n\t */\n\tsubagentCommunicationWiring?: import(\"./sdk.ts\").CreateAgentSessionOptions[\"subagentCommunicationWiring\"];\n\t/**\n\t * 档案 model 的目标 id(D-060 pooled parity 补口):runner 侧把叶子会话模型\n\t * 解析到**自己的 scoped models**(档案不能把会话带到 runner 未授权的模型上),\n\t * 解析不到即失败并列出可用 id。父会话创建路径不传该字段。\n\t */\n\tchildModelId?: string;\n}) => Promise<CreateAgentSessionRuntimeResult>;\n\n/**\n * Thrown when /import references a JSONL file path that does not exist.\n */\nexport class SessionImportFileNotFoundError extends Error {\n\treadonly filePath: string;\n\n\tconstructor(filePath: string) {\n\t\tsuper(`File not found: ${filePath}`);\n\t\tthis.name = \"SessionImportFileNotFoundError\";\n\t\tthis.filePath = filePath;\n\t}\n}\n\nfunction extractUserMessageText(content: string | Array<{ type: string; text?: string }>): string {\n\tif (typeof content === \"string\") {\n\t\treturn content;\n\t}\n\n\treturn content\n\t\t.filter((part): part is { type: \"text\"; text: string } => part.type === \"text\" && typeof part.text === \"string\")\n\t\t.map((part) => part.text)\n\t\t.join(\"\");\n}\n\n/** Maps suite assembly findings onto the runtime diagnostic channel as info. */\nfunction toSuiteRuntimeDiagnostics(suiteDiagnostics: readonly string[]): AgentSessionRuntimeDiagnostic[] {\n\treturn suiteDiagnostics.map((message) => ({ type: \"info\" as const, message }));\n}\n\n/**\n * Owns the current AgentSession plus its cwd-bound services.\n *\n * Session replacement methods tear down the current runtime first, then create\n * and apply the next runtime. If creation fails, the error is propagated to the\n * caller. The caller is responsible for user-facing error handling.\n */\nexport class AgentSessionRuntime {\n\tprivate rebindSession?: (session: AgentSession) => Promise<void>;\n\tprivate beforeSessionInvalidate?: () => void;\n\tprivate _session: AgentSession;\n\tprivate _services: AgentSessionServices;\n\tprivate readonly createRuntime: CreateAgentSessionRuntimeFactory;\n\tprivate _diagnostics: AgentSessionRuntimeDiagnostic[];\n\tprivate _suiteDiagnostics: readonly string[];\n\tprivate _modelFallbackMessage?: string;\n\tprivate _pluginRejections: readonly PluginRejection[];\n\n\tconstructor(\n\t\t_session: AgentSession,\n\t\t_services: AgentSessionServices,\n\t\tcreateRuntime: CreateAgentSessionRuntimeFactory,\n\t\t_diagnostics: AgentSessionRuntimeDiagnostic[] = [],\n\t\t_modelFallbackMessage?: string,\n\t\t_pluginRejections: readonly PluginRejection[] = [],\n\t\t_suiteDiagnostics: readonly string[] = [],\n\t) {\n\t\tthis._session = _session;\n\t\tthis._services = _services;\n\t\tthis.createRuntime = createRuntime;\n\t\tthis._diagnostics = _diagnostics;\n\t\tthis._suiteDiagnostics = _suiteDiagnostics;\n\t\tthis._modelFallbackMessage = _modelFallbackMessage;\n\t\tthis._pluginRejections = _pluginRejections;\n\t}\n\n\tget services(): AgentSessionServices {\n\t\treturn this._services;\n\t}\n\n\t/** /metrics 数据源共享 ref(observability 插件门面,空 = 未挂载)。 */\n\tget observabilityGetMetricsRef(): AgentSessionServices[\"observabilityGetMetricsRef\"] {\n\t\treturn this._services.observabilityGetMetricsRef;\n\t}\n\n\tget session(): AgentSession {\n\t\treturn this._session;\n\t}\n\n\tget cwd(): string {\n\t\treturn this._services.cwd;\n\t}\n\n\tget diagnostics(): readonly AgentSessionRuntimeDiagnostic[] {\n\t\treturn [...this._diagnostics, ...toSuiteRuntimeDiagnostics(this._suiteDiagnostics)];\n\t}\n\n\t/**\n\t * Suite assembly findings from the last runtime creation (initial,\n\t * /new, /fork, /switch). Surfaced as info-level entries on the\n\t * `diagnostics` channel.\n\t */\n\tget suiteDiagnostics(): readonly string[] {\n\t\treturn this._suiteDiagnostics;\n\t}\n\n\tget modelFallbackMessage(): string | undefined {\n\t\treturn this._modelFallbackMessage;\n\t}\n\n\tget pluginRejections(): readonly PluginRejection[] {\n\t\treturn this._pluginRejections;\n\t}\n\n\tsetRebindSession(rebindSession?: (session: AgentSession) => Promise<void>): void {\n\t\tthis.rebindSession = rebindSession;\n\t}\n\n\t/**\n\t * Set a synchronous callback that runs after `session_shutdown` handlers finish\n\t * but before the current session is invalidated.\n\t *\n\t * This is for host-owned UI teardown that must not yield to the event loop,\n\t * such as detaching extension-provided TUI components before the old extension\n\t * context becomes stale.\n\t */\n\tsetBeforeSessionInvalidate(beforeSessionInvalidate?: () => void): void {\n\t\tthis.beforeSessionInvalidate = beforeSessionInvalidate;\n\t}\n\n\tprivate async teardownCurrent(_reason: \"new\" | \"resume\" | \"fork\", _targetSessionFile?: string): Promise<void> {\n\t\t// Settle any active response first so the aborted turn (including tool\n\t\t// results) is persisted to the outgoing session before it is replaced.\n\t\t// Internal teardown aborts deliberately skip the interruption marker.\n\t\tawait this.session._abortInternal();\n\t\tthis.beforeSessionInvalidate?.();\n\t\tawait this.session.dispose();\n\t}\n\n\tprivate apply(result: CreateAgentSessionRuntimeResult): void {\n\t\tthis._session = result.session;\n\t\tthis._services = result.services;\n\t\tthis._diagnostics = result.diagnostics;\n\t\tthis._suiteDiagnostics = result.suiteDiagnostics;\n\t\tthis._modelFallbackMessage = result.modelFallbackMessage;\n\t\tthis._pluginRejections = result.pluginRejections;\n\t}\n\n\tprivate async finishSessionReplacement(withSession?: (ctx: ReplacedSessionContext) => Promise<void>): Promise<void> {\n\t\tif (this.rebindSession) {\n\t\t\tawait this.rebindSession(this.session);\n\t\t}\n\t\tif (withSession) {\n\t\t\tawait withSession(this.session.createReplacedSessionContext());\n\t\t}\n\t}\n\n\tasync switchSession(\n\t\tsessionPath: string,\n\t\toptions?: {\n\t\t\tcwdOverride?: string;\n\t\t\twithSession?: (ctx: ReplacedSessionContext) => Promise<void>;\n\t\t},\n\t): Promise<{ cancelled: boolean }> {\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tconst sessionManager = SessionManager.open(sessionPath, undefined, options?.cwdOverride);\n\t\tassertSessionCwdExists(sessionManager, this.cwd);\n\t\tawait this.teardownCurrent(\"resume\", sessionManager.getSessionFile());\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: sessionManager.getCwd(),\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { reason: \"resume\", previousSessionFile },\n\t\t\t}),\n\t\t);\n\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\treturn { cancelled: false };\n\t}\n\n\tasync newSession(options?: {\n\t\tparentSession?: string;\n\t\tsetup?: (sessionManager: SessionManager) => Promise<void>;\n\t\twithSession?: (ctx: ReplacedSessionContext) => Promise<void>;\n\t}): Promise<{ cancelled: boolean }> {\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tconst sessionDir = this.session.sessionManager.getSessionDir();\n\t\tconst sessionManager = this.session.sessionManager.isPersisted()\n\t\t\t? SessionManager.create(this.cwd, sessionDir)\n\t\t\t: SessionManager.inMemory(this.cwd);\n\t\tif (options?.parentSession) {\n\t\t\tsessionManager.newSession({ parentSession: options.parentSession });\n\t\t}\n\n\t\tawait this.teardownCurrent(\"new\", sessionManager.getSessionFile());\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: this.cwd,\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { reason: \"new\", previousSessionFile },\n\t\t\t}),\n\t\t);\n\t\tif (options?.setup) {\n\t\t\tawait options.setup(this.session.sessionManager);\n\t\t\tconst context = this.session.sessionManager.buildSessionContext().messages;\n\t\t\tif (this.session.contextStrategyName) {\n\t\t\t\tawait this.session.replaceContext(context);\n\t\t\t} else {\n\t\t\t\tthis.session.agent.state.messages = context;\n\t\t\t}\n\t\t}\n\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\treturn { cancelled: false };\n\t}\n\n\tasync fork(\n\t\tentryId: string,\n\t\toptions?: { position?: \"before\" | \"at\"; withSession?: (ctx: ReplacedSessionContext) => Promise<void> },\n\t): Promise<{ cancelled: boolean; selectedText?: string }> {\n\t\tconst position = options?.position ?? \"before\";\n\t\tlet targetLeafId: string | null;\n\t\tlet selectedText: string | undefined;\n\n\t\tconst selectedEntry = this.session.sessionManager.getEntry(entryId);\n\t\tif (!selectedEntry) {\n\t\t\tthrow new Error(\"Invalid entry ID for forking\");\n\t\t}\n\n\t\tif (position === \"at\") {\n\t\t\ttargetLeafId = selectedEntry.id;\n\t\t} else {\n\t\t\tif (selectedEntry.type !== \"message\" || selectedEntry.message.role !== \"user\") {\n\t\t\t\tthrow new Error(\"Invalid entry ID for forking\");\n\t\t\t}\n\t\t\ttargetLeafId = selectedEntry.parentId;\n\t\t\tselectedText = extractUserMessageText(selectedEntry.message.content);\n\t\t}\n\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tif (this.session.sessionManager.isPersisted()) {\n\t\t\tconst currentSessionFile = this.session.sessionFile;\n\t\t\tif (!currentSessionFile) {\n\t\t\t\tthrow new Error(\"Persisted session is missing a session file\");\n\t\t\t}\n\t\t\tconst sessionDir = this.session.sessionManager.getSessionDir();\n\t\t\tif (!targetLeafId) {\n\t\t\t\tconst sessionManager = SessionManager.create(this.cwd, sessionDir);\n\t\t\t\tsessionManager.newSession({ parentSession: currentSessionFile });\n\t\t\t\tawait this.teardownCurrent(\"fork\", sessionManager.getSessionFile());\n\t\t\t\tthis.apply(\n\t\t\t\t\tawait this.createRuntime({\n\t\t\t\t\t\tcwd: this.cwd,\n\t\t\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\t\t\tsessionManager,\n\t\t\t\t\t\tsessionStartEvent: { reason: \"fork\", previousSessionFile },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\t\t\treturn { cancelled: false, selectedText };\n\t\t\t}\n\n\t\t\tif (!existsSync(currentSessionFile)) {\n\t\t\t\tthrow new Error(\"This session has not been saved yet. Send a message before cloning or forking it.\");\n\t\t\t}\n\t\t\tconst sessionManager = SessionManager.open(currentSessionFile, sessionDir);\n\t\t\tconst forkedSessionPath = sessionManager.createBranchedSession(targetLeafId);\n\t\t\tif (!forkedSessionPath) {\n\t\t\t\tthrow new Error(\"Failed to create forked session\");\n\t\t\t}\n\t\t\tawait this.teardownCurrent(\"fork\", sessionManager.getSessionFile());\n\t\t\tthis.apply(\n\t\t\t\tawait this.createRuntime({\n\t\t\t\t\tcwd: sessionManager.getCwd(),\n\t\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\t\tsessionManager,\n\t\t\t\t\tsessionStartEvent: { reason: \"fork\", previousSessionFile },\n\t\t\t\t}),\n\t\t\t);\n\t\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\t\treturn { cancelled: false, selectedText };\n\t\t}\n\n\t\tconst sessionManager = this.session.sessionManager;\n\t\tawait this.teardownCurrent(\"fork\", sessionManager.getSessionFile());\n\t\tif (!targetLeafId) {\n\t\t\tsessionManager.newSession({ parentSession: previousSessionFile });\n\t\t} else {\n\t\t\tsessionManager.createBranchedSession(targetLeafId);\n\t\t}\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: this.cwd,\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { reason: \"fork\", previousSessionFile },\n\t\t\t}),\n\t\t);\n\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\treturn { cancelled: false, selectedText };\n\t}\n\n\t/**\n\t * Import a session JSONL file and switch runtime state to the imported session.\n\t *\n\t * @throws {SessionImportFileNotFoundError} When the input path does not exist.\n\t * @throws {MissingSessionCwdError} When the imported session cwd cannot be resolved and no override is provided.\n\t */\n\tasync importFromJsonl(inputPath: string, cwdOverride?: string): Promise<{ cancelled: boolean }> {\n\t\tconst resolvedPath = resolvePath(inputPath);\n\t\tif (!existsSync(resolvedPath)) {\n\t\t\tthrow new SessionImportFileNotFoundError(resolvedPath);\n\t\t}\n\n\t\tconst sessionDir = this.session.sessionManager.getSessionDir();\n\t\tif (!existsSync(sessionDir)) {\n\t\t\tmkdirSync(sessionDir, { recursive: true });\n\t\t}\n\n\t\tlet destinationPath = join(sessionDir, basename(resolvedPath));\n\t\tconst sourceAlreadyStored = resolve(destinationPath) === resolvedPath;\n\t\tif (!sourceAlreadyStored) {\n\t\t\tconst { name, ext } = parse(destinationPath);\n\t\t\tlet suffix = 1;\n\t\t\twhile (existsSync(destinationPath)) {\n\t\t\t\tdestinationPath = join(sessionDir, `${name}-${suffix++}${ext}`);\n\t\t\t}\n\t\t}\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tif (!sourceAlreadyStored) {\n\t\t\tcopyFileSync(resolvedPath, destinationPath, constants.COPYFILE_EXCL);\n\t\t}\n\n\t\tconst sessionManager = SessionManager.open(destinationPath, sessionDir, cwdOverride);\n\t\tassertSessionCwdExists(sessionManager, this.cwd);\n\t\tawait this.teardownCurrent(\"resume\", sessionManager.getSessionFile());\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: sessionManager.getCwd(),\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { reason: \"resume\", previousSessionFile },\n\t\t\t}),\n\t\t);\n\t\tawait this.finishSessionReplacement();\n\t\treturn { cancelled: false };\n\t}\n\n\tasync dispose(): Promise<void> {\n\t\tthis.beforeSessionInvalidate?.();\n\t\tawait this.session.dispose();\n\t}\n}\n\n/**\n * Create the initial runtime from a runtime factory and initial session target.\n *\n * The same factory is stored on the returned AgentSessionRuntime and reused for\n * later /new, /resume, /fork, and import flows.\n */\nexport async function createAgentSessionRuntime(\n\tcreateRuntime: CreateAgentSessionRuntimeFactory,\n\toptions: {\n\t\tcwd: string;\n\t\tagentDir: string;\n\t\tsessionManager: SessionManager;\n\t\tsessionStartEvent?: SessionStartMetadata;\n\t},\n): Promise<AgentSessionRuntime> {\n\tassertSessionCwdExists(options.sessionManager, options.cwd);\n\tconst result = await createRuntime(options);\n\treturn new AgentSessionRuntime(\n\t\tresult.session,\n\t\tresult.services,\n\t\tcreateRuntime,\n\t\tresult.diagnostics,\n\t\tresult.modelFallbackMessage,\n\t\tresult.pluginRejections,\n\t\tresult.suiteDiagnostics,\n\t);\n}\n\nexport {\n\ttype AgentSessionRuntimeDiagnostic,\n\ttype AgentSessionServices,\n\ttype CreateAgentSessionFromServicesOptions,\n\ttype CreateAgentSessionServicesOptions,\n\tcreateAgentSessionFromServices,\n\tcreateAgentSessionServices,\n} from \"./agent-session-services.ts\";\n"]}
1
+ {"version":3,"file":"agent-session-runtime.js","sourceRoot":"","sources":["../../src/core/agent-session-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { constants, copyFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { basename, join, parse, resolve } from \"node:path\";\nimport type { ImageContent, TextContent } from \"@agent-forge/ai/compat\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport type { AgentSession } from \"./agent-session.ts\";\nimport type { AgentSessionRuntimeDiagnostic, AgentSessionServices } from \"./agent-session-services.ts\";\nimport type { AgentTaskChildProfileV1 } from \"./extensions/public-api.ts\";\nimport { t } from \"./i18n/index.ts\";\nimport type { CustomMessage } from \"./messages.ts\";\nimport type { CreateAgentSessionResult, PluginRejection } from \"./sdk.ts\";\nimport { assertSessionCwdExists } from \"./session-cwd.ts\";\nimport { SessionManager } from \"./session-manager.ts\";\nimport type { SessionStartMetadata } from \"./session-start.ts\";\n\n/**\n * Result returned by runtime creation.\n *\n * The caller gets the created session, its cwd-bound services, and all\n * diagnostics collected during setup.\n */\n/**\n * Fresh session-bound context passed to `withSession()` callbacks on\n * `newSession()`, `fork()`, and `switchSession()`. It targets the replacement\n * session: every call routes into the session that became current after the\n * replacement committed.\n */\nexport interface ReplacedSessionContext {\n\tsendMessage<T = unknown>(\n\t\tmessage: Pick<CustomMessage<T>, \"customType\" | \"content\" | \"display\" | \"details\">,\n\t\toptions?: { triggerTurn?: boolean; deliverAs?: \"steer\" | \"followUp\" | \"nextTurn\" },\n\t): Promise<void>;\n\n\tsendUserMessage(\n\t\tcontent: string | (TextContent | ImageContent)[],\n\t\toptions?: { deliverAs?: \"steer\" | \"followUp\"; expandPromptTemplates?: boolean },\n\t): Promise<void>;\n}\n\nexport interface CreateAgentSessionRuntimeResult extends CreateAgentSessionResult {\n\tservices: AgentSessionServices;\n\tdiagnostics: AgentSessionRuntimeDiagnostic[];\n\t/**\n\t * 仅当工厂收到 `childProfile` 时存在:叶子会话的**可核验事实**(实际生效的工具面、\n\t * 模型、模式)。runner 侧 server 用它与请求档案比对后才允许任务起跑——\"要求了但\n\t * 没人能证明\"与\"没要求\"是同一风险。\n\t */\n\tchildFacts?: {\n\t\treadonly activeTools: readonly string[];\n\t\treadonly model?: {\n\t\t\treadonly provider: string;\n\t\t\treadonly id: string;\n\t\t\treadonly contextWindow: number;\n\t\t\treadonly maxTokens: number;\n\t\t\treadonly reasoning: boolean;\n\t\t};\n\t\treadonly capabilityMode: string;\n\t\t/** 叶子实际思考级别(档案请求了 thinkingLevel 时核验用)。 */\n\t\treadonly thinkingLevel?: string;\n\t\t/** 叶子实际生效的系统提示词追加段(档案请求了 systemPromptAppend 时核验用,已含方案 APPEND_SYSTEM.md 门控结果)。 */\n\t\treadonly systemPromptAppend?: string;\n\t};\n}\n\n/**\n * Creates a full runtime for a target cwd and session manager.\n *\n * The factory closes over process-global fixed inputs, recreates cwd-bound\n * services for the effective cwd, resolves session options against those\n * services, and finally creates the AgentSession.\n */\nexport type CreateAgentSessionRuntimeFactory = (options: {\n\tcwd: string;\n\tagentDir: string;\n\tsessionManager: SessionManager;\n\tsessionStartEvent?: SessionStartMetadata;\n\t/**\n\t * 子任务档案(AgentTaskChildProfileV1):pooled runner 的叶子会话按它收窄\n\t * (tools/mode/thinkingLevel)。父会话创建路径不传该字段——档案只服务子任务。\n\t */\n\tchildProfile?: AgentTaskChildProfileV1;\n\t/**\n\t * 子代理通信面的宿主接线(D-060 S5 pooled parity):runner 叶子装配注入\n\t * post/drainInbox 闭包(身份绑定到叶子会话),叶子会话由此获得\n\t * escalate/兄弟消息工具。父会话创建路径不传该字段。\n\t */\n\tsubagentCommunicationWiring?: import(\"./sdk.ts\").CreateAgentSessionOptions[\"subagentCommunicationWiring\"];\n\t/**\n\t * 档案 model 的目标 id(D-060 pooled parity 补口):runner 侧把叶子会话模型\n\t * 解析到**自己的 scoped models**(档案不能把会话带到 runner 未授权的模型上),\n\t * 解析不到即失败并列出可用 id。父会话创建路径不传该字段。\n\t */\n\tchildModelId?: string;\n}) => Promise<CreateAgentSessionRuntimeResult>;\n\n/**\n * Thrown when /import references a JSONL file path that does not exist.\n */\nexport class SessionImportFileNotFoundError extends Error {\n\treadonly filePath: string;\n\n\tconstructor(filePath: string) {\n\t\tsuper(t(\"File not found: {path}\", { path: filePath }));\n\t\tthis.name = \"SessionImportFileNotFoundError\";\n\t\tthis.filePath = filePath;\n\t}\n}\n\nfunction extractUserMessageText(content: string | Array<{ type: string; text?: string }>): string {\n\tif (typeof content === \"string\") {\n\t\treturn content;\n\t}\n\n\treturn content\n\t\t.filter((part): part is { type: \"text\"; text: string } => part.type === \"text\" && typeof part.text === \"string\")\n\t\t.map((part) => part.text)\n\t\t.join(\"\");\n}\n\n/** Maps suite assembly findings onto the runtime diagnostic channel as info. */\nfunction toSuiteRuntimeDiagnostics(suiteDiagnostics: readonly string[]): AgentSessionRuntimeDiagnostic[] {\n\treturn suiteDiagnostics.map((message) => ({ type: \"info\" as const, message }));\n}\n\n/**\n * Owns the current AgentSession plus its cwd-bound services.\n *\n * Session replacement methods tear down the current runtime first, then create\n * and apply the next runtime. If creation fails, the error is propagated to the\n * caller. The caller is responsible for user-facing error handling.\n */\nexport class AgentSessionRuntime {\n\tprivate rebindSession?: (session: AgentSession) => Promise<void>;\n\tprivate beforeSessionInvalidate?: () => void;\n\tprivate _session: AgentSession;\n\tprivate _services: AgentSessionServices;\n\tprivate readonly createRuntime: CreateAgentSessionRuntimeFactory;\n\tprivate _diagnostics: AgentSessionRuntimeDiagnostic[];\n\tprivate _suiteDiagnostics: readonly string[];\n\tprivate _modelFallbackMessage?: string;\n\tprivate _pluginRejections: readonly PluginRejection[];\n\n\tconstructor(\n\t\t_session: AgentSession,\n\t\t_services: AgentSessionServices,\n\t\tcreateRuntime: CreateAgentSessionRuntimeFactory,\n\t\t_diagnostics: AgentSessionRuntimeDiagnostic[] = [],\n\t\t_modelFallbackMessage?: string,\n\t\t_pluginRejections: readonly PluginRejection[] = [],\n\t\t_suiteDiagnostics: readonly string[] = [],\n\t) {\n\t\tthis._session = _session;\n\t\tthis._services = _services;\n\t\tthis.createRuntime = createRuntime;\n\t\tthis._diagnostics = _diagnostics;\n\t\tthis._suiteDiagnostics = _suiteDiagnostics;\n\t\tthis._modelFallbackMessage = _modelFallbackMessage;\n\t\tthis._pluginRejections = _pluginRejections;\n\t}\n\n\tget services(): AgentSessionServices {\n\t\treturn this._services;\n\t}\n\n\t/** /metrics 数据源共享 ref(observability 插件门面,空 = 未挂载)。 */\n\tget observabilityGetMetricsRef(): AgentSessionServices[\"observabilityGetMetricsRef\"] {\n\t\treturn this._services.observabilityGetMetricsRef;\n\t}\n\n\tget session(): AgentSession {\n\t\treturn this._session;\n\t}\n\n\tget cwd(): string {\n\t\treturn this._services.cwd;\n\t}\n\n\tget diagnostics(): readonly AgentSessionRuntimeDiagnostic[] {\n\t\treturn [...this._diagnostics, ...toSuiteRuntimeDiagnostics(this._suiteDiagnostics)];\n\t}\n\n\t/**\n\t * Suite assembly findings from the last runtime creation (initial,\n\t * /new, /fork, /switch). Surfaced as info-level entries on the\n\t * `diagnostics` channel.\n\t */\n\tget suiteDiagnostics(): readonly string[] {\n\t\treturn this._suiteDiagnostics;\n\t}\n\n\tget modelFallbackMessage(): string | undefined {\n\t\treturn this._modelFallbackMessage;\n\t}\n\n\tget pluginRejections(): readonly PluginRejection[] {\n\t\treturn this._pluginRejections;\n\t}\n\n\tsetRebindSession(rebindSession?: (session: AgentSession) => Promise<void>): void {\n\t\tthis.rebindSession = rebindSession;\n\t}\n\n\t/**\n\t * Set a synchronous callback that runs after `session_shutdown` handlers finish\n\t * but before the current session is invalidated.\n\t *\n\t * This is for host-owned UI teardown that must not yield to the event loop,\n\t * such as detaching extension-provided TUI components before the old extension\n\t * context becomes stale.\n\t */\n\tsetBeforeSessionInvalidate(beforeSessionInvalidate?: () => void): void {\n\t\tthis.beforeSessionInvalidate = beforeSessionInvalidate;\n\t}\n\n\tprivate async teardownCurrent(_reason: \"new\" | \"resume\" | \"fork\", _targetSessionFile?: string): Promise<void> {\n\t\t// Settle any active response first so the aborted turn (including tool\n\t\t// results) is persisted to the outgoing session before it is replaced.\n\t\t// Internal teardown aborts deliberately skip the interruption marker.\n\t\tawait this.session._abortInternal();\n\t\tthis.beforeSessionInvalidate?.();\n\t\tawait this.session.dispose();\n\t}\n\n\tprivate apply(result: CreateAgentSessionRuntimeResult): void {\n\t\tthis._session = result.session;\n\t\tthis._services = result.services;\n\t\tthis._diagnostics = result.diagnostics;\n\t\tthis._suiteDiagnostics = result.suiteDiagnostics;\n\t\tthis._modelFallbackMessage = result.modelFallbackMessage;\n\t\tthis._pluginRejections = result.pluginRejections;\n\t}\n\n\tprivate async finishSessionReplacement(withSession?: (ctx: ReplacedSessionContext) => Promise<void>): Promise<void> {\n\t\tif (this.rebindSession) {\n\t\t\tawait this.rebindSession(this.session);\n\t\t}\n\t\tif (withSession) {\n\t\t\tawait withSession(this.session.createReplacedSessionContext());\n\t\t}\n\t}\n\n\tasync switchSession(\n\t\tsessionPath: string,\n\t\toptions?: {\n\t\t\tcwdOverride?: string;\n\t\t\twithSession?: (ctx: ReplacedSessionContext) => Promise<void>;\n\t\t},\n\t): Promise<{ cancelled: boolean }> {\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tconst sessionManager = SessionManager.open(sessionPath, undefined, options?.cwdOverride);\n\t\tassertSessionCwdExists(sessionManager, this.cwd);\n\t\tawait this.teardownCurrent(\"resume\", sessionManager.getSessionFile());\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: sessionManager.getCwd(),\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { reason: \"resume\", previousSessionFile },\n\t\t\t}),\n\t\t);\n\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\treturn { cancelled: false };\n\t}\n\n\tasync newSession(options?: {\n\t\tparentSession?: string;\n\t\tsetup?: (sessionManager: SessionManager) => Promise<void>;\n\t\twithSession?: (ctx: ReplacedSessionContext) => Promise<void>;\n\t}): Promise<{ cancelled: boolean }> {\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tconst sessionDir = this.session.sessionManager.getSessionDir();\n\t\tconst sessionManager = this.session.sessionManager.isPersisted()\n\t\t\t? SessionManager.create(this.cwd, sessionDir)\n\t\t\t: SessionManager.inMemory(this.cwd);\n\t\tif (options?.parentSession) {\n\t\t\tsessionManager.newSession({ parentSession: options.parentSession });\n\t\t}\n\n\t\tawait this.teardownCurrent(\"new\", sessionManager.getSessionFile());\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: this.cwd,\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { reason: \"new\", previousSessionFile },\n\t\t\t}),\n\t\t);\n\t\tif (options?.setup) {\n\t\t\tawait options.setup(this.session.sessionManager);\n\t\t\tconst context = this.session.sessionManager.buildSessionContext().messages;\n\t\t\tif (this.session.contextStrategyName) {\n\t\t\t\tawait this.session.replaceContext(context);\n\t\t\t} else {\n\t\t\t\tthis.session.agent.state.messages = context;\n\t\t\t}\n\t\t}\n\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\treturn { cancelled: false };\n\t}\n\n\tasync fork(\n\t\tentryId: string,\n\t\toptions?: { position?: \"before\" | \"at\"; withSession?: (ctx: ReplacedSessionContext) => Promise<void> },\n\t): Promise<{ cancelled: boolean; selectedText?: string }> {\n\t\tconst position = options?.position ?? \"before\";\n\t\tlet targetLeafId: string | null;\n\t\tlet selectedText: string | undefined;\n\n\t\tconst selectedEntry = this.session.sessionManager.getEntry(entryId);\n\t\tif (!selectedEntry) {\n\t\t\tthrow new Error(t(\"Invalid entry ID for forking\"));\n\t\t}\n\n\t\tif (position === \"at\") {\n\t\t\ttargetLeafId = selectedEntry.id;\n\t\t} else {\n\t\t\tif (selectedEntry.type !== \"message\" || selectedEntry.message.role !== \"user\") {\n\t\t\t\tthrow new Error(t(\"Invalid entry ID for forking\"));\n\t\t\t}\n\t\t\ttargetLeafId = selectedEntry.parentId;\n\t\t\tselectedText = extractUserMessageText(selectedEntry.message.content);\n\t\t}\n\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tif (this.session.sessionManager.isPersisted()) {\n\t\t\tconst currentSessionFile = this.session.sessionFile;\n\t\t\tif (!currentSessionFile) {\n\t\t\t\tthrow new Error(t(\"Persisted session is missing a session file\"));\n\t\t\t}\n\t\t\tconst sessionDir = this.session.sessionManager.getSessionDir();\n\t\t\tif (!targetLeafId) {\n\t\t\t\tconst sessionManager = SessionManager.create(this.cwd, sessionDir);\n\t\t\t\tsessionManager.newSession({ parentSession: currentSessionFile });\n\t\t\t\tawait this.teardownCurrent(\"fork\", sessionManager.getSessionFile());\n\t\t\t\tthis.apply(\n\t\t\t\t\tawait this.createRuntime({\n\t\t\t\t\t\tcwd: this.cwd,\n\t\t\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\t\t\tsessionManager,\n\t\t\t\t\t\tsessionStartEvent: { reason: \"fork\", previousSessionFile },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\t\t\treturn { cancelled: false, selectedText };\n\t\t\t}\n\n\t\t\tif (!existsSync(currentSessionFile)) {\n\t\t\t\tthrow new Error(t(\"This session has not been saved yet. Send a message before cloning or forking it.\"));\n\t\t\t}\n\t\t\tconst sessionManager = SessionManager.open(currentSessionFile, sessionDir);\n\t\t\tconst forkedSessionPath = sessionManager.createBranchedSession(targetLeafId);\n\t\t\tif (!forkedSessionPath) {\n\t\t\t\tthrow new Error(t(\"Failed to create forked session\"));\n\t\t\t}\n\t\t\tawait this.teardownCurrent(\"fork\", sessionManager.getSessionFile());\n\t\t\tthis.apply(\n\t\t\t\tawait this.createRuntime({\n\t\t\t\t\tcwd: sessionManager.getCwd(),\n\t\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\t\tsessionManager,\n\t\t\t\t\tsessionStartEvent: { reason: \"fork\", previousSessionFile },\n\t\t\t\t}),\n\t\t\t);\n\t\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\t\treturn { cancelled: false, selectedText };\n\t\t}\n\n\t\tconst sessionManager = this.session.sessionManager;\n\t\tawait this.teardownCurrent(\"fork\", sessionManager.getSessionFile());\n\t\tif (!targetLeafId) {\n\t\t\tsessionManager.newSession({ parentSession: previousSessionFile });\n\t\t} else {\n\t\t\tsessionManager.createBranchedSession(targetLeafId);\n\t\t}\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: this.cwd,\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { reason: \"fork\", previousSessionFile },\n\t\t\t}),\n\t\t);\n\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\treturn { cancelled: false, selectedText };\n\t}\n\n\t/**\n\t * Import a session JSONL file and switch runtime state to the imported session.\n\t *\n\t * @throws {SessionImportFileNotFoundError} When the input path does not exist.\n\t * @throws {MissingSessionCwdError} When the imported session cwd cannot be resolved and no override is provided.\n\t */\n\tasync importFromJsonl(inputPath: string, cwdOverride?: string): Promise<{ cancelled: boolean }> {\n\t\tconst resolvedPath = resolvePath(inputPath);\n\t\tif (!existsSync(resolvedPath)) {\n\t\t\tthrow new SessionImportFileNotFoundError(resolvedPath);\n\t\t}\n\n\t\tconst sessionDir = this.session.sessionManager.getSessionDir();\n\t\tif (!existsSync(sessionDir)) {\n\t\t\tmkdirSync(sessionDir, { recursive: true });\n\t\t}\n\n\t\tlet destinationPath = join(sessionDir, basename(resolvedPath));\n\t\tconst sourceAlreadyStored = resolve(destinationPath) === resolvedPath;\n\t\tif (!sourceAlreadyStored) {\n\t\t\tconst { name, ext } = parse(destinationPath);\n\t\t\tlet suffix = 1;\n\t\t\twhile (existsSync(destinationPath)) {\n\t\t\t\tdestinationPath = join(sessionDir, `${name}-${suffix++}${ext}`);\n\t\t\t}\n\t\t}\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tif (!sourceAlreadyStored) {\n\t\t\tcopyFileSync(resolvedPath, destinationPath, constants.COPYFILE_EXCL);\n\t\t}\n\n\t\tconst sessionManager = SessionManager.open(destinationPath, sessionDir, cwdOverride);\n\t\tassertSessionCwdExists(sessionManager, this.cwd);\n\t\tawait this.teardownCurrent(\"resume\", sessionManager.getSessionFile());\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: sessionManager.getCwd(),\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { reason: \"resume\", previousSessionFile },\n\t\t\t}),\n\t\t);\n\t\tawait this.finishSessionReplacement();\n\t\treturn { cancelled: false };\n\t}\n\n\tasync dispose(): Promise<void> {\n\t\tthis.beforeSessionInvalidate?.();\n\t\tawait this.session.dispose();\n\t}\n}\n\n/**\n * Create the initial runtime from a runtime factory and initial session target.\n *\n * The same factory is stored on the returned AgentSessionRuntime and reused for\n * later /new, /resume, /fork, and import flows.\n */\nexport async function createAgentSessionRuntime(\n\tcreateRuntime: CreateAgentSessionRuntimeFactory,\n\toptions: {\n\t\tcwd: string;\n\t\tagentDir: string;\n\t\tsessionManager: SessionManager;\n\t\tsessionStartEvent?: SessionStartMetadata;\n\t},\n): Promise<AgentSessionRuntime> {\n\tassertSessionCwdExists(options.sessionManager, options.cwd);\n\tconst result = await createRuntime(options);\n\treturn new AgentSessionRuntime(\n\t\tresult.session,\n\t\tresult.services,\n\t\tcreateRuntime,\n\t\tresult.diagnostics,\n\t\tresult.modelFallbackMessage,\n\t\tresult.pluginRejections,\n\t\tresult.suiteDiagnostics,\n\t);\n}\n\nexport {\n\ttype AgentSessionRuntimeDiagnostic,\n\ttype AgentSessionServices,\n\ttype CreateAgentSessionFromServicesOptions,\n\ttype CreateAgentSessionServicesOptions,\n\tcreateAgentSessionFromServices,\n\tcreateAgentSessionServices,\n} from \"./agent-session-services.ts\";\n"]}
@@ -47,7 +47,7 @@ export interface CreateAgentSessionServicesOptions {
47
47
  resourceLoaderReloadOptions?: ResourceLoaderReloadOptions;
48
48
  /**
49
49
  * Explicit suite id (highest resolution priority, 设计 §9). Without it the
50
- * suite resolves via AGENT_FORGE_SUITE, then settings, then "assistant".
50
+ * suite resolves via AGENT_FORGE_SUITE, then settings, then "coding".
51
51
  */
52
52
  suite?: string;
53
53
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"agent-session-services.d.ts","sourceRoot":"","sources":["../../src/core/agent-session-services.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { isAbsolute, join, relative, sep } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { ThinkingLevel } from \"@agent-forge/agent-core\";\nimport type { Api, CredentialStore, Model } from \"@agent-forge/ai\";\nimport { CONFIG_DIR_NAME, getAgentDir, VERSION } from \"../config.ts\";\nimport type { HostFactsV1 } from \"../plugins/ecosystem/types.ts\";\nimport type { ObservabilityPlugin } from \"../plugins/observability-types.ts\";\nimport type {\n\tBuiltinPluginManifestOverridesV1,\n\tBuiltinPluginProfileIdV1,\n\tBuiltinPluginProfileResolutionV1,\n} from \"../profile/plugin-profiles.ts\";\nimport type { VerifiedToolPluginV1 } from \"../profile/profile-assembly.ts\";\nimport type { SuiteDefinition } from \"../profiles/builtin-suites.ts\";\nimport { createSuiteAssembly, resolveSuiteId, SUITE_ENV_VAR } from \"../profiles/suite-loader.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport { EXPERIMENTAL_PUBLIC_API_VERSION } from \"./extensions/index.ts\";\nimport { ModelRuntime } from \"./model-runtime.ts\";\nimport {\n\tDefaultResourceLoader,\n\ttype DefaultResourceLoaderOptions,\n\ttype ResourceLoader,\n\ttype ResourceLoaderReloadOptions,\n} from \"./resource-loader.ts\";\nimport {\n\ttype CreateAgentSessionOptions,\n\ttype CreateAgentSessionResult,\n\tcreateAgentSession,\n\ttype InstalledCapabilityPluginV1,\n} from \"./sdk.ts\";\nimport type { SessionManager } from \"./session-manager.ts\";\nimport type { SessionStartMetadata } from \"./session-start.ts\";\nimport { SettingsManager } from \"./settings-manager.ts\";\nimport type { ToolDefinition } from \"./tools/tool-definition.ts\";\n\n/**\n * Non-fatal issues collected while creating services or sessions.\n *\n * Runtime creation returns diagnostics to the caller instead of printing or\n * exiting. The app layer decides whether warnings should be shown and whether\n * errors should abort startup.\n */\nexport interface AgentSessionRuntimeDiagnostic {\n\ttype: \"info\" | \"warning\" | \"error\";\n\tmessage: string;\n}\n\n/**\n * Inputs for creating cwd-bound runtime services.\n *\n * These services are recreated whenever the effective session cwd changes.\n * CLI-provided resource paths should be resolved to absolute paths before they\n * reach this function, so later cwd switches do not reinterpret them.\n */\nexport interface CreateAgentSessionServicesOptions {\n\tcwd: string;\n\tagentDir?: string;\n\tsettingsManager?: SettingsManager;\n\tmodelRuntime?: ModelRuntime;\n\t/**\n\t * Credential storage used by the default model runtime (D-067 phase 1):\n\t * forwarded to `ModelRuntime.create` when `modelRuntime` is omitted.\n\t * Ignored when an explicit `modelRuntime` is supplied. Defaults to the\n\t * file at `<agentDir>/auth.json`.\n\t */\n\tcredentials?: CredentialStore;\n\tmodelRuntimeSignal?: AbortSignal;\n\tresourceLoaderOptions?: Omit<DefaultResourceLoaderOptions, \"cwd\" | \"agentDir\" | \"settingsManager\">;\n\tresourceLoaderReloadOptions?: ResourceLoaderReloadOptions;\n\t/**\n\t * Explicit suite id (highest resolution priority, 设计 §9). Without it the\n\t * suite resolves via AGENT_FORGE_SUITE, then settings, then \"assistant\".\n\t */\n\tsuite?: string;\n\t/**\n\t * Wire the full suite assembly (agents.md three-level chain, system prompt\n\t * gate, skill/extension association filters, MCP registration pool) into\n\t * these services' DefaultResourceLoader. Default false: services built\n\t * without it keep the plain loader behavior (evals and testkit\n\t * determinism). When true, the suite id is resolved exactly once here and\n\t * exposed as AgentSessionServices.suiteId so session creation reuses it\n\t * instead of resolving again. The MCP pool (设计 §4/§5) additionally reads\n\t * the mcp.json config surface, filters it by associations.mcp, and\n\t * materializes the injected servers as capability-plugin manifests\n\t * (AgentSessionServices.mcpCapabilityPluginPaths).\n\t */\n\tsuiteAssembly?: boolean;\n\t/** Optional domain plugin profile selected for this suite. */\n\tpluginProfileId?: BuiltinPluginProfileIdV1;\n\t/** Optional subset of plugins from the selected builtin Profile. */\n\tselectedPluginIds?: readonly string[];\n\t/** Optional plugin IDs disabled within the selected builtin Profile. */\n\tdisabledPluginIds?: readonly string[];\n\tpluginHost?: HostFactsV1;\n\tverifiedPlugins?: readonly VerifiedToolPluginV1[];\n\t/** Explicit host-owned active installed manifests; never discovered implicitly. */\n\tmanifestOverrides?: BuiltinPluginManifestOverridesV1;\n\t/**\n\t * Verified active installations (D-075 S2 installed-code-loading) from the\n\t * host's active-binding resolution; forwarded to session creation so their\n\t * plugin.json paths enter the sdk's candidate pool for profile members.\n\t */\n\tinstalledCapabilityPlugins?: readonly InstalledCapabilityPluginV1[];\n\t/** Host diagnostics from active-install resolution; no package data is retained. */\n\tpluginBindingDiagnostics?: readonly AgentSessionRuntimeDiagnostic[];\n}\n\n/**\n * Inputs for creating an AgentSession from already-created services.\n *\n * Use this after services exist and any cwd-bound model/tool/session options\n * have been resolved against those services.\n */\nexport interface CreateAgentSessionFromServicesOptions {\n\tservices: AgentSessionServices;\n\tsessionManager: SessionManager;\n\tsessionStartEvent?: SessionStartMetadata;\n\tmodel?: Model<Api>;\n\tstreamFn?: CreateAgentSessionOptions[\"streamFn\"];\n\tthinkingLevel?: ThinkingLevel;\n\tscopedModels?: Array<{ model: Model<Api>; thinkingLevel?: ThinkingLevel }>;\n\ttools?: string[];\n\texcludeTools?: CreateAgentSessionOptions[\"excludeTools\"];\n\tnoTools?: CreateAgentSessionOptions[\"noTools\"];\n\tcapabilityMode?: CreateAgentSessionOptions[\"capabilityMode\"];\n\tdiscoverCapabilityPlugins?: CreateAgentSessionOptions[\"discoverCapabilityPlugins\"];\n\t/**\n\t * Session trace collection (设计 §4.4/§6), forwarded to createAgentSession.\n\t * Omitted keeps the sdk default (tracing on); hosts pass `false` for\n\t * `--no-trace`.\n\t */\n\ttraceEnabled?: CreateAgentSessionOptions[\"traceEnabled\"];\n\t/**\n\t * Host-process logger forwarded to createAgentSession (设计 §5). Omitted\n\t * keeps the sdk's explicit no-logging contract (instrumentation no-ops).\n\t */\n\thostLogger?: CreateAgentSessionOptions[\"hostLogger\"];\n\tcapabilityPluginPaths?: CreateAgentSessionOptions[\"capabilityPluginPaths\"];\n\tcontextStrategyName?: CreateAgentSessionOptions[\"contextStrategyName\"];\n\tretryPolicyName?: CreateAgentSessionOptions[\"retryPolicyName\"];\n\tcompactionPolicyName?: CreateAgentSessionOptions[\"compactionPolicyName\"];\n\toverflowPolicyName?: CreateAgentSessionOptions[\"overflowPolicyName\"];\n\tbranchSummaryPolicyName?: CreateAgentSessionOptions[\"branchSummaryPolicyName\"];\n\t/** Host adapter for cancellable interaction tasks, forwarded to createAgentSession. */\n\tinteractionHost?: CreateAgentSessionOptions[\"interactionHost\"];\n\t/**\n\t * 覆盖 services 自带 loader。pooled runner 的叶子会话用它注入子任务档案的\n\t * `systemPromptAppend`(追加语义,不替换继承内容);缺省沿用 services 的 loader。\n\t */\n\tresourceLoader?: CreateAgentSessionOptions[\"resourceLoader\"];\n\t/**\n\t * Forwarded to createAgentSession. Headless subagent runners pass `false` so a\n\t * runner task session stays a leaf (no nested agent tasks; D-045 increment 2b).\n\t */\n\tenableAgentTasks?: CreateAgentSessionOptions[\"enableAgentTasks\"];\n\tcustomTools?: ToolDefinition[];\n\t/**\n\t * Explicit suite id forwarded to createAgentSession. When omitted, the\n\t * services' resolved suiteId (suiteAssembly: true) is used; without either,\n\t * createAgentSession resolves the suite itself.\n\t */\n\tsuite?: string;\n\t/**\n\t * Wire the suite's capability surface (方案系统 M3) onto the created\n\t * sessions. Default: on when the services ran the suite assembly\n\t * (suiteAssembly: true, so first-party entries get the builtin capability\n\t * whitelist and plugin-pool filtering); otherwise off, matching the sdk's\n\t * caller-supplied-loader assembly boundary.\n\t */\n\tsuiteCapabilityWiring?: boolean;\n\t/**\n\t * 子代理通信面的宿主接线(D-060 S5 pooled parity):pooled runner 的叶子会话\n\t * 用它注入 post/drainInbox 闭包(身份绑定到叶子会话,信箱为文件承载、跨进程)。\n\t */\n\tsubagentCommunicationWiring?: CreateAgentSessionOptions[\"subagentCommunicationWiring\"];\n\t/**\n\t * 承载退役切片 1(生产 CLI 默认 pooled):转发 createAgentSession 的\n\t * self-invocation 自动池化声明。仅真实 CLI 装配传 true。\n\t */\n\tsubagentPoolFromSelfInvocation?: CreateAgentSessionOptions[\"subagentPoolFromSelfInvocation\"];\n}\n\n/**\n * Coherent cwd-bound runtime services for one effective session cwd.\n *\n * This is infrastructure only. The AgentSession itself is created separately so\n * session options can be resolved against these services first.\n */\nexport interface AgentSessionServices {\n\tcwd: string;\n\t/**\n\t * /metrics 命令的数据源共享 ref(observability 插件工厂创建时写入\n\t * plugin.getMetrics、dispose 时置空;宿主装配完成后读取接进命令 options)。\n\t * 空 = 插件未挂载(/metrics 显示未装配警告)。\n\t */\n\tobservabilityGetMetricsRef?: { current?: ObservabilityPlugin[\"getMetrics\"] };\n\tagentDir: string;\n\tmodelRuntime: ModelRuntime;\n\tsettingsManager: SettingsManager;\n\tresourceLoader: ResourceLoader;\n\tdiagnostics: AgentSessionRuntimeDiagnostic[];\n\t/**\n\t * Suite id resolved for these services when `suiteAssembly` was requested;\n\t * undefined when assembly was off (no suite filtering was applied here).\n\t */\n\tsuiteId?: string;\n\tpluginProfile?: BuiltinPluginProfileResolutionV1;\n\tpluginProfileId?: BuiltinPluginProfileIdV1;\n\t/**\n\t * Verified active installations (D-075 S2) forwarded from the services\n\t * options; createAgentSessionFromServices passes them to the sdk's\n\t * installed-code-loading candidate pool.\n\t */\n\tinstalledCapabilityPlugins?: readonly InstalledCapabilityPluginV1[];\n\t/**\n\t * Capability-plugin manifest paths materialized for the suite's MCP\n\t * registration pool (M4, 设计 §4/§5). Defined only when `suiteAssembly`\n\t * injected at least one associated mcp.json server;\n\t * createAgentSessionFromServices appends them to the created session's\n\t * capabilityPluginPaths.\n\t */\n\tmcpCapabilityPluginPaths?: readonly string[];\n\t/**\n\t * Plugin ids of the MCP pool servers configured with `deferredTools: true`.\n\t * Their tools register normally but stay out of the default active set; the\n\t * session's tool_search tool discovers and activates them on demand.\n\t */\n\tmcpDeferredToolPluginIds?: readonly string[];\n}\n\n// ---------------------------------------------------------------------------\n// Suite MCP registration pool (方案系统 M4: MCP 配置面, 设计 §4/§5)\n// ---------------------------------------------------------------------------\n\n/** User-level MCP config file directly inside the agent dir. */\nconst MCP_CONFIG_FILENAME = \"mcp.json\";\n/** Generated per-server capability-plugin manifests live below this agentDir dir. */\nconst MCP_POOL_DIR = \"mcp/pool\";\n/** Shared stdio bridge module inside the pool dir (leading \"_\" keeps server names distinct). */\nconst MCP_POOL_BRIDGE_DIR = \"_bridge\";\n/** Server names are associations keys and pool directory names; \"_\" is reserved for the bridge. */\nconst MCP_SERVER_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;\n\n/**\n * Implementation backing url-configured pool entries (createMcpHttpServerPlugin).\n * Sources resolve first so development always runs the current implementation;\n * published installs ship only dist, so dist is the fallback.\n */\nconst MCP_HTTP_PLUGIN_SOURCE_PATH = fileURLToPath(new URL(\"../plugins/mcp-http.ts\", import.meta.url));\nconst MCP_HTTP_PLUGIN_DIST_PATH = fileURLToPath(new URL(\"../../dist/plugins/mcp-http.js\", import.meta.url));\n\n/** One MCP server resolved from an mcp.json configuration file. */\nexport interface SuiteMcpServerV1 {\n\t/** Server name: the associations.mcp match key and the pool directory name. */\n\treadonly name: string;\n\t/** stdio launch command; undefined for remote HTTP servers (`url` set). */\n\treadonly command?: string;\n\treadonly args: readonly string[];\n\t/** Remote HTTP endpoint; undefined for stdio servers (`command` set). */\n\treadonly url?: string;\n\t/**\n\t * Custom request headers sent with every request to a remote HTTP server;\n\t * undefined for stdio servers (`headers` there only contributes a\n\t * diagnostic and is never forwarded).\n\t */\n\treadonly headers?: Readonly<Record<string, string>>;\n\t/**\n\t * Config layer the server came from. \"project\" (`<cwd>/.agent-forge/mcp.json`)\n\t * is the third layer (设计 §4) and always passes; \"user\"\n\t * (`<agentDir>/mcp.json`) injects only when associated.\n\t */\n\treadonly scope: \"user\" | \"project\";\n\t/** Generated capability-plugin manifest path for this server. */\n\treadonly manifestPath: string;\n\t/** Whether the server's tools stay out of the default active set until tool_search activates them. */\n\treadonly deferred: boolean;\n}\n\nexport interface SuiteMcpPoolV1 {\n\t/** Injected servers in deterministic order (project first, then user). */\n\treadonly servers: readonly SuiteMcpServerV1[];\n\t/** Manifest paths ready for the session's capabilityPluginPaths channel. */\n\treadonly manifestPaths: readonly string[];\n\t/** Plugin ids whose tools are registered but excluded from the default active set. */\n\treadonly deferredPluginIds: readonly string[];\n\t/**\n\t * Diagnostics: unreadable/invalid config files, filtered non-associated\n\t * servers, project-overridden duplicates, and dangling associations.\n\t * Reported, never thrown (设计 §11.3).\n\t */\n\treadonly diagnostics: readonly string[];\n}\n\ninterface McpServerConfigV1 {\n\treadonly command?: string;\n\treadonly args: readonly string[];\n\treadonly url?: string;\n\t/** Custom request headers for remote HTTP servers; ignored (with a diagnostic) on stdio entries. */\n\treadonly headers?: Readonly<Record<string, string>>;\n\treadonly deferredTools?: boolean;\n}\n\n/**\n * Remote MCP URLs accept only http/https; any other protocol or unparseable\n * value is a configuration error, not a fallback path.\n */\nfunction isHttpUrl(value: string): boolean {\n\ttry {\n\t\tconst protocol = new URL(value).protocol;\n\t\treturn protocol === \"http:\" || protocol === \"https:\";\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Reads one mcp.json (`{ \"mcpServers\": { \"<name>\": { \"command\", \"args\" } } }`\n * for stdio servers, or `{ \"url\" }` for remote HTTP servers). Each entry must\n * carry exactly one of \"command\" and \"url\". Corruption tolerance: a missing\n * file is an empty config; an unreadable or malformed file, and invalid\n * per-server entries, contribute a diagnostic and are skipped — never thrown.\n */\nfunction parseMcpConfig(path: string): {\n\tservers: Map<string, McpServerConfigV1>;\n\tdiagnostics: string[];\n} {\n\tconst servers = new Map<string, McpServerConfigV1>();\n\tconst diagnostics: string[] = [];\n\tlet value: unknown;\n\ttry {\n\t\tvalue = JSON.parse(readFileSync(path, \"utf8\"));\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return { servers, diagnostics };\n\t\tdiagnostics.push(\n\t\t\t`MCP config at ${path} is unreadable; ignoring it. Errors: ${error instanceof Error ? error.message : String(error)}`,\n\t\t);\n\t\treturn { servers, diagnostics };\n\t}\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tdiagnostics.push(`MCP config at ${path} must be an object with an \"mcpServers\" map; ignoring it.`);\n\t\treturn { servers, diagnostics };\n\t}\n\tconst mcpServers = (value as Record<string, unknown>).mcpServers;\n\tif (mcpServers === undefined) return { servers, diagnostics };\n\tif (typeof mcpServers !== \"object\" || mcpServers === null || Array.isArray(mcpServers)) {\n\t\tdiagnostics.push(`MCP config at ${path} must carry an \"mcpServers\" object; ignoring it.`);\n\t\treturn { servers, diagnostics };\n\t}\n\tfor (const [name, entry] of Object.entries(mcpServers as Record<string, unknown>)) {\n\t\tif (!MCP_SERVER_NAME_PATTERN.test(name)) {\n\t\t\tdiagnostics.push(\n\t\t\t\t`MCP server name \"${name}\" in ${path} is invalid (must match ${MCP_SERVER_NAME_PATTERN.source}); ignoring it.`,\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof entry !== \"object\" || entry === null || Array.isArray(entry)) {\n\t\t\tdiagnostics.push(`MCP server \"${name}\" in ${path} must be an object with a \"command\" or \"url\"; ignoring it.`);\n\t\t\tcontinue;\n\t\t}\n\t\tconst config = entry as Record<string, unknown>;\n\t\tif (config.url !== undefined && (typeof config.url !== \"string\" || config.url.trim().length === 0)) {\n\t\t\tdiagnostics.push(`MCP server \"${name}\" in ${path} requires \"url\" to be a non-empty string; ignoring it.`);\n\t\t\tcontinue;\n\t\t}\n\t\tconst hasCommand = typeof config.command === \"string\" && config.command.trim().length > 0;\n\t\tconst hasUrl = typeof config.url === \"string\" && config.url.trim().length > 0;\n\t\tif (hasCommand && hasUrl) {\n\t\t\tdiagnostics.push(\n\t\t\t\t`MCP server \"${name}\" in ${path} accepts either \"command\" (stdio server) or \"url\" (remote HTTP server), not both; ignoring it.`,\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!hasCommand && !hasUrl) {\n\t\t\tdiagnostics.push(\n\t\t\t\t`MCP server \"${name}\" in ${path} requires a non-empty string \"command\" (stdio server) or \"url\" (remote HTTP server); ignoring it.`,\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tif (hasUrl && !isHttpUrl(config.url as string)) {\n\t\t\tdiagnostics.push(\n\t\t\t\t`MCP server \"${name}\" in ${path} requires \"url\" to be a valid http:// or https:// URL; ignoring it.`,\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tif (\n\t\t\tconfig.args !== undefined &&\n\t\t\t(!Array.isArray(config.args) || !config.args.every((arg) => typeof arg === \"string\"))\n\t\t) {\n\t\t\tdiagnostics.push(`MCP server \"${name}\" in ${path} requires \"args\" to be a string array; ignoring it.`);\n\t\t\tcontinue;\n\t\t}\n\t\tif (config.deferredTools !== undefined && typeof config.deferredTools !== \"boolean\") {\n\t\t\tdiagnostics.push(`MCP server \"${name}\" in ${path} requires \"deferredTools\" to be a boolean; ignoring it.`);\n\t\t\tcontinue;\n\t\t}\n\t\tif (config.headers !== undefined) {\n\t\t\tif (hasCommand) {\n\t\t\t\t// Same acceptance style as a url entry carrying args: the entry\n\t\t\t\t// loads, but the field belongs to the other transport shape.\n\t\t\t\tdiagnostics.push(\n\t\t\t\t\t`MCP server \"${name}\" in ${path} carries \"headers\" but headers only apply to remote \"url\" (HTTP) servers; ignoring them.`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconst headersValid =\n\t\t\t\t\ttypeof config.headers === \"object\" &&\n\t\t\t\t\tconfig.headers !== null &&\n\t\t\t\t\t!Array.isArray(config.headers) &&\n\t\t\t\t\tObject.values(config.headers as Record<string, unknown>).every(\n\t\t\t\t\t\t(headerValue) => typeof headerValue === \"string\" && headerValue.length > 0,\n\t\t\t\t\t);\n\t\t\t\tif (!headersValid) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\t`MCP server \"${name}\" in ${path} requires \"headers\" to be an object with non-empty string values; ignoring it.`,\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tservers.set(name, {\n\t\t\targs: (config.args as readonly string[] | undefined) ?? [],\n\t\t\tdeferredTools: config.deferredTools === true ? true : undefined,\n\t\t\t...(hasCommand\n\t\t\t\t? { command: config.command as string }\n\t\t\t\t: {\n\t\t\t\t\t\turl: config.url as string,\n\t\t\t\t\t\t// Kept verbatim (no case normalization): managed remote MCP\n\t\t\t\t\t\t// endpoints compare header names and values exactly.\n\t\t\t\t\t\t...(config.headers === undefined\n\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t: { headers: config.headers as Readonly<Record<string, string>> }),\n\t\t\t\t\t}),\n\t\t});\n\t}\n\treturn { servers, diagnostics };\n}\n\n/**\n * Generated stdio bridge shared by every injected server: JSON-RPC 2.0 over a\n * spawned child process (argv, never a shell — except on win32, where a\n * resolved `.cmd`/`.bat` shim is launched through `cmd.exe /d /s /c`, so its\n * arguments cross cmd's command-line interpreter exactly as with\n * `shell: true`), MCP initialize/tools/list\n * handshake, and one registerTool per remote tool through the public\n * capability API. Tool call policy stays host-owned; the bridge only forwards\n * requests and maps results. On win32 the transport additionally resolves\n * `.cmd`/`.bat` shims (bare names via PATH, explicit suffixes verbatim) and\n * launches them through `cmd.exe /d /s /c` with MSVCRT argv quoting, because\n * Node >= 18.20 refuses to spawn extension shims directly (EINVAL) and\n * extension-less shim names ENOENT.\n */\nconst MCP_POOL_BRIDGE_SOURCE = `// Generated by the suite MCP registration pool (agent-session-services). Do not edit.\nimport { spawn } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nconst REQUEST_TIMEOUT_MS = 30000;\n\n// Windows .cmd/.bat shims cannot be spawned directly: Node >= 18.20 raises\n// EINVAL for commands carrying a shim extension and ENOENT for bare names\n// (npx, pnpm, ...), so bare command names (no path separator) are probed\n// along PATH for a .cmd/.bat shim, and explicit .cmd/.bat commands pass\n// through for cmd.exe wrapping. Everything else - .exe/.com, path-bearing\n// executables, non-win32 platforms, and PATH misses - resolves to undefined\n// and keeps the direct spawn behavior (a miss keeps the original ENOENT).\nfunction resolveWin32ShimCommand(command) {\n\tif (process.platform !== 'win32') return undefined;\n\tconst lowered = command.toLowerCase();\n\tif (lowered.endsWith('.cmd') || lowered.endsWith('.bat')) return command;\n\tif (command.includes('/') || command.includes('\\\\\\\\')) return undefined;\n\tfor (const dir of (process.env.PATH || '').split(';')) {\n\t\tif (!dir) continue;\n\t\tconst cmdShim = join(dir, command + '.cmd');\n\t\tif (existsSync(cmdShim)) return cmdShim;\n\t\tconst batShim = join(dir, command + '.bat');\n\t\tif (existsSync(batShim)) return batShim;\n\t}\n\treturn undefined;\n}\n\n// MSVCRT argv quoting for the cmd.exe /c command string: an argument that is\n// empty or contains space/tab/quote is wrapped in double quotes, embedded\n// quotes are escaped as \\\\\", and backslashes directly before a quote (or a\n// quoted argument's trailing backslashes) double up (2n rule) so they cannot\n// escape the closing quote. Plain arguments pass through untouched.\nfunction quoteCommandString(parts) {\n\tconst quoted = [];\n\tfor (const part of parts) {\n\t\tif (part !== '' && !/[ \\\\t\"]/.test(part)) {\n\t\t\tquoted.push(part);\n\t\t\tcontinue;\n\t\t}\n\t\tlet inner = '';\n\t\tlet backslashes = 0;\n\t\tfor (const ch of part) {\n\t\t\tif (ch === '\\\\\\\\') {\n\t\t\t\tbackslashes += 1;\n\t\t\t} else if (ch === '\"') {\n\t\t\t\tinner += '\\\\\\\\'.repeat(backslashes * 2 + 1) + '\"';\n\t\t\t\tbackslashes = 0;\n\t\t\t} else {\n\t\t\t\tif (backslashes > 0) {\n\t\t\t\t\tinner += '\\\\\\\\'.repeat(backslashes);\n\t\t\t\t\tbackslashes = 0;\n\t\t\t\t}\n\t\t\t\tinner += ch;\n\t\t\t}\n\t\t}\n\t\tif (backslashes > 0) {\n\t\t\tinner += '\\\\\\\\'.repeat(backslashes * 2);\n\t\t}\n\t\tquoted.push('\"' + inner + '\"');\n\t}\n\treturn quoted.join(' ');\n}\n\nfunction startTransport(command, args) {\n\t// win32 only: wrap .cmd/.bat shims through cmd.exe (resolveWin32ShimCommand).\n\t// The MSVCRT-quoted command string gets ONE more plain outer pair of\n\t// quotes (cmd.exe dialect, not MSVCRT): /S strips that outer pair and\n\t// re-parses the inner string. windowsVerbatimArguments is required so the\n\t// pre-built string reaches cmd.exe untouched; Node's default quoting would\n\t// wrap it again and cmd.exe would see literal \\\\\" sequences instead.\n\tconst shim = resolveWin32ShimCommand(command);\n\tconst child =\n\t\tshim === undefined\n\t\t\t? spawn(command, args, { shell: false, stdio: ['pipe', 'pipe', 'pipe'] })\n\t\t\t: spawn('cmd.exe', ['/d', '/s', '/c', '\"' + quoteCommandString([shim].concat(args)) + '\"'], {\n\t\t\t\t\twindowsVerbatimArguments: true,\n\t\t\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t\t\t});\n\tlet nextId = 1;\n\tlet closed = false;\n\tlet failure = null;\n\tlet buffered = '';\n\tconst pending = new Map();\n\tconst rejectAll = (error) => {\n\t\tif (failure) return;\n\t\tfailure = error;\n\t\tclosed = true;\n\t\tfor (const request of pending.values()) request.reject(error);\n\t\tpending.clear();\n\t};\n\tchild.stdout.setEncoding('utf8');\n\tchild.stdout.on('data', (chunk) => {\n\t\tbuffered += chunk;\n\t\tconst lines = buffered.split(/\\\\r?\\\\n/);\n\t\tbuffered = lines.pop() || '';\n\t\tfor (const line of lines) {\n\t\t\tif (!line.trim()) continue;\n\t\t\tlet response;\n\t\t\ttry {\n\t\t\t\tresponse = JSON.parse(line);\n\t\t\t} catch {\n\t\t\t\trejectAll(new Error('MCP server produced a malformed JSON-RPC response'));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (response.id === undefined || response.id === null) continue;\n\t\t\tconst request = pending.get(response.id);\n\t\t\tif (!request) continue;\n\t\t\tpending.delete(response.id);\n\t\t\tif (response.error) {\n\t\t\t\trequest.reject(new Error('MCP request failed: ' + String(response.error.message || 'unknown error')));\n\t\t\t} else {\n\t\t\t\trequest.resolve(response.result);\n\t\t\t}\n\t\t}\n\t});\n\tchild.stderr.setEncoding('utf8');\n\tchild.stderr.on('data', () => undefined);\n\tchild.once('error', (error) => rejectAll(new Error('Failed to spawn MCP server: ' + error.message)));\n\tchild.once('close', (exitCode) => rejectAll(new Error('MCP server exited with code ' + String(exitCode))));\n\tconst send = (message) => {\n\t\tchild.stdin.write(JSON.stringify(message) + '\\\\n');\n\t};\n\tconst request = (method, params, signal) => {\n\t\tif (failure || closed) return Promise.reject(failure || new Error('MCP transport is closed'));\n\t\tif (signal && signal.aborted) return Promise.reject(new Error('MCP request aborted'));\n\t\tconst id = nextId++;\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tpending.delete(id);\n\t\t\t\treject(new Error('MCP request timed out: ' + method));\n\t\t\t}, REQUEST_TIMEOUT_MS);\n\t\t\tpending.set(id, {\n\t\t\t\tresolve: (result) => {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\tresolve(result);\n\t\t\t\t},\n\t\t\t\treject: (error) => {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\treject(error);\n\t\t\t\t},\n\t\t\t});\n\t\t\tif (signal) {\n\t\t\t\tsignal.addEventListener(\n\t\t\t\t\t'abort',\n\t\t\t\t\t() => {\n\t\t\t\t\t\tif (pending.delete(id)) reject(new Error('MCP request aborted'));\n\t\t\t\t\t},\n\t\t\t\t\t{ once: true },\n\t\t\t\t);\n\t\t\t}\n\t\t\tsend(Object.assign({ jsonrpc: '2.0', id, method }, params === undefined ? {} : { params }));\n\t\t});\n\t};\n\treturn {\n\t\trequest,\n\t\tnotify(method, params) {\n\t\t\tif (closed) return;\n\t\t\tsend(Object.assign({ jsonrpc: '2.0', method }, params === undefined ? {} : { params }));\n\t\t},\n\t\tclose() {\n\t\t\tif (closed) return;\n\t\t\tclosed = true;\n\t\t\tchild.stdin.end();\n\t\t\tif (!child.killed) child.kill();\n\t\t},\n\t};\n}\n\nfunction normalizeToolResult(result) {\n\tif (result && typeof result === 'object' && Array.isArray(result.content)) {\n\t\treturn { content: result.content, details: result.details };\n\t}\n\tif (result === undefined) return { content: [{ type: 'text', text: '' }], details: undefined };\n\treturn { content: [{ type: 'text', text: JSON.stringify(result) }], details: undefined };\n}\n\nexport default function createMcpStdioServerPlugin(config) {\n\treturn async (api) => {\n\t\tconst transport = startTransport(config.command, config.args || []);\n\t\ttry {\n\t\t\tawait transport.request('initialize', {\n\t\t\t\tprotocolVersion: '2024-11-05',\n\t\t\t\tcapabilities: {},\n\t\t\t\tclientInfo: { name: 'agent-forge-mcp-pool', version: '0.1.0' },\n\t\t\t});\n\t\t\ttransport.notify('notifications/initialized');\n\t\t\tconst listing = await transport.request('tools/list');\n\t\t\tif (!listing || !Array.isArray(listing.tools)) {\n\t\t\t\tthrow new Error('MCP tools/list result must contain tools[]');\n\t\t\t}\n\t\t\tfor (const tool of listing.tools) {\n\t\t\t\tif (!tool || typeof tool.name !== 'string' || !tool.name) {\n\t\t\t\t\tthrow new Error('MCP tool requires a non-empty name');\n\t\t\t\t}\n\t\t\t\tapi.registerTool({\n\t\t\t\t\tname: tool.name,\n\t\t\t\t\tlabel: tool.name,\n\t\t\t\t\tdescription: typeof tool.description === 'string' ? tool.description : 'MCP tool: ' + tool.name,\n\t\t\t\t\tparameters:\n\t\t\t\t\t\ttool.inputSchema && typeof tool.inputSchema === 'object'\n\t\t\t\t\t\t\t? tool.inputSchema\n\t\t\t\t\t\t\t: { type: 'object', properties: {} },\n\t\t\t\t\texecute: async (toolCallId, params, signal) => {\n\t\t\t\t\t\t// Dual call convention: the session passes (toolCallId, params,\n\t\t\t\t\t\t// signal); the runtime's invokeTool passes the input as the\n\t\t\t\t\t\t// single first argument.\n\t\t\t\t\t\tconst singleArgCall = params === undefined && typeof toolCallId !== 'string';\n\t\t\t\t\t\tconst input = singleArgCall ? toolCallId : params;\n\t\t\t\t\t\tconst result = await transport.request(\n\t\t\t\t\t\t\t'tools/call',\n\t\t\t\t\t\t\t{ name: tool.name, arguments: input || {} },\n\t\t\t\t\t\t\tsingleArgCall ? undefined : signal,\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn normalizeToolResult(result);\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tdispose() {\n\t\t\t\t\ttransport.close();\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (error) {\n\t\t\ttransport.close();\n\t\t\tthrow error;\n\t\t}\n\t};\n}\n`;\n\nfunction writeMcpPoolBridge(poolDir: string): void {\n\tconst bridgeDir = join(poolDir, MCP_POOL_BRIDGE_DIR);\n\tmkdirSync(bridgeDir, { recursive: true });\n\twriteFileSync(join(bridgeDir, \"index.mjs\"), MCP_POOL_BRIDGE_SOURCE, \"utf8\");\n}\n\n/**\n * Import specifier for the HTTP server plugin implementation, as written into\n * a generated pool entry below `fromDir`. Relative same-drive form matches the\n * stdio entry's style; a cross-drive relative() result stays an absolute POSIX\n * path, which the capability loader (jiti) resolves.\n */\nfunction mcpHttpPluginImportSpec(fromDir: string): string {\n\tconst implPath = existsSync(MCP_HTTP_PLUGIN_SOURCE_PATH) ? MCP_HTTP_PLUGIN_SOURCE_PATH : MCP_HTTP_PLUGIN_DIST_PATH;\n\tconst relNative = relative(fromDir, implPath);\n\tconst relPosix = relNative.split(sep).join(\"/\");\n\treturn isAbsolute(relNative) ? relPosix : `./${relPosix}`;\n}\n\n/** Materializes one server as a capability-plugin manifest; returns the manifest path. */\nfunction writeMcpPoolServer(poolDir: string, name: string, server: McpServerConfigV1): string {\n\tconst serverDir = join(poolDir, name);\n\tmkdirSync(serverDir, { recursive: true });\n\tconst manifest = {\n\t\tid: `agent-forge.mcp.${name}`,\n\t\tversion: \"0.1.0\",\n\t\t// The pool is re-materialized every session, so the declared range always\n\t\t// includes the running host (D-073): an upgraded host never rejects its\n\t\t// own generated pool manifests through the hostVersion gate.\n\t\thostVersion: `>=${VERSION}`,\n\t\tapiVersion: EXPERIMENTAL_PUBLIC_API_VERSION,\n\t\tentry: \"./index.mjs\",\n\t\trequiredCapabilities: [\"tools\"],\n\t};\n\twriteFileSync(join(serverDir, \"plugin.json\"), `${JSON.stringify(manifest, null, 2)}\\n`, \"utf8\");\n\tconst entry =\n\t\tserver.url === undefined\n\t\t\t? [\n\t\t\t\t\t\"// Generated by the suite MCP registration pool (agent-session-services). Do not edit.\",\n\t\t\t\t\t`import createMcpStdioServerPlugin from \"../${MCP_POOL_BRIDGE_DIR}/index.mjs\";`,\n\t\t\t\t\t`export default createMcpStdioServerPlugin(${JSON.stringify({ command: server.command, args: server.args })});`,\n\t\t\t\t\t\"\",\n\t\t\t\t].join(\"\\n\")\n\t\t\t: [\n\t\t\t\t\t\"// Generated by the suite MCP registration pool (agent-session-services). Do not edit.\",\n\t\t\t\t\t`import { createMcpHttpServerPlugin } from \"${mcpHttpPluginImportSpec(serverDir)}\";`,\n\t\t\t\t\t`export default createMcpHttpServerPlugin(${JSON.stringify({\n\t\t\t\t\t\turl: server.url,\n\t\t\t\t\t\t...(server.headers === undefined ? {} : { headers: server.headers }),\n\t\t\t\t\t})});`,\n\t\t\t\t\t\"\",\n\t\t\t\t].join(\"\\n\");\n\twriteFileSync(join(serverDir, \"index.mjs\"), entry, \"utf8\");\n\treturn join(serverDir, \"plugin.json\");\n}\n\n/**\n * Resolves the suite's MCP registration pool (方案系统 M4: MCP 配置面, 设计\n * §4/§5) and materializes each injected server as a capability-plugin\n * manifest below `<agentDir>/mcp/pool/`, ready for the session's\n * `capabilityPluginPaths` channel — the same way plugins directory discovery\n * injects manifests. Filtering: the project level\n * (`<cwd>/.agent-forge/mcp.json`) is the third layer (设计 §4) and always\n * passes; the user level (`<agentDir>/mcp.json`) injects only servers named\n * in `suite.associations.mcp` — an empty association list means zero\n * user-level injection, the same semantics as skills/extensions.\n */\nexport function resolveSuiteMcpPool(options: {\n\tcwd: string;\n\tagentDir: string;\n\tsuite: SuiteDefinition;\n}): SuiteMcpPoolV1 {\n\tconst { cwd, agentDir, suite } = options;\n\tconst userConfigPath = join(agentDir, MCP_CONFIG_FILENAME);\n\tconst projectConfigPath = join(cwd, CONFIG_DIR_NAME, MCP_CONFIG_FILENAME);\n\tconst user = parseMcpConfig(userConfigPath);\n\tconst project = parseMcpConfig(projectConfigPath);\n\tconst diagnostics = [...project.diagnostics, ...user.diagnostics];\n\n\tconst selected = new Map<string, McpServerConfigV1 & { scope: \"user\" | \"project\" }>();\n\t// Third layer (设计 §4): project-level servers always pass; they win name\n\t// collisions over user definitions.\n\tfor (const [name, server] of project.servers) selected.set(name, { ...server, scope: \"project\" });\n\tfor (const [name, server] of user.servers) {\n\t\tif (selected.has(name)) {\n\t\t\tdiagnostics.push(\n\t\t\t\t`MCP server \"${name}\" from ${userConfigPath} is overridden by the project-level definition at ${projectConfigPath}; keeping the project one.`,\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!suite.associations.mcp.includes(name)) {\n\t\t\tdiagnostics.push(\n\t\t\t\t`Suite \"${suite.id}\" MCP server \"${name}\" is not associated (associations.mcp); not injected.`,\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tselected.set(name, { ...server, scope: \"user\" });\n\t}\n\tfor (const name of suite.associations.mcp) {\n\t\tif (!selected.has(name)) {\n\t\t\tdiagnostics.push(\n\t\t\t\t`Suite \"${suite.id}\" dangling association \"${name}\" (mcp): not found in the discovered registry; ignored.`,\n\t\t\t);\n\t\t}\n\t}\n\n\tconst servers: SuiteMcpServerV1[] = [];\n\tconst manifestPaths: string[] = [];\n\tconst deferredPluginIds: string[] = [];\n\tif (selected.size > 0) {\n\t\tconst poolDir = join(agentDir, MCP_POOL_DIR);\n\t\twriteMcpPoolBridge(poolDir);\n\t\tfor (const [name, server] of selected) {\n\t\t\tconst manifestPath = writeMcpPoolServer(poolDir, name, server);\n\t\t\tmanifestPaths.push(manifestPath);\n\t\t\tservers.push({\n\t\t\t\tname,\n\t\t\t\targs: server.args,\n\t\t\t\tscope: server.scope,\n\t\t\t\tmanifestPath,\n\t\t\t\tdeferred: server.deferredTools === true,\n\t\t\t\t...(server.url === undefined\n\t\t\t\t\t? { command: server.command }\n\t\t\t\t\t: {\n\t\t\t\t\t\t\turl: server.url,\n\t\t\t\t\t\t\t...(server.headers === undefined ? {} : { headers: server.headers }),\n\t\t\t\t\t\t}),\n\t\t\t});\n\t\t\tif (server.deferredTools === true) {\n\t\t\t\tdeferredPluginIds.push(`agent-forge.mcp.${name}`);\n\t\t\t}\n\t\t}\n\t}\n\treturn { servers, manifestPaths, deferredPluginIds, diagnostics };\n}\n\n/**\n * Create cwd-bound runtime services.\n *\n * Returns services plus diagnostics. It does not create an AgentSession.\n */\nexport async function createAgentSessionServices(\n\toptions: CreateAgentSessionServicesOptions,\n): Promise<AgentSessionServices> {\n\tconst cwd = resolvePath(options.cwd);\n\tconst agentDir = options.agentDir ? resolvePath(options.agentDir) : getAgentDir();\n\tconst modelRuntime =\n\t\toptions.modelRuntime ??\n\t\t(await ModelRuntime.create({\n\t\t\tauthPath: join(agentDir, \"auth.json\"),\n\t\t\tmodelsPath: join(agentDir, \"models.json\"),\n\t\t\tcredentials: options.credentials,\n\t\t\tsignal: options.modelRuntimeSignal,\n\t\t}));\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\t// Suite assembly (设计 §3/§4/§8, M2): resolve once and wire the shared\n\t// assembly into this loader. Off by default so evals/testkit services keep\n\t// their fixture resources unfiltered.\n\tlet suiteId: string | undefined;\n\tlet suiteLoaderOverrides:\n\t\t| Pick<\n\t\t\t\tDefaultResourceLoaderOptions,\n\t\t\t\t\"agentsFilesOverride\" | \"skillsOverride\" | \"systemPromptOverride\" | \"appendSystemPromptOverride\"\n\t\t >\n\t\t| undefined;\n\tlet suiteLocalSkillsDir: string | undefined;\n\tlet pluginProfile: BuiltinPluginProfileResolutionV1 | undefined;\n\t/** MCP registration pool for the assembled suite (M4); undefined when assembly is off. */\n\tlet mcpPool: SuiteMcpPoolV1 | undefined;\n\tif (options.suiteAssembly) {\n\t\tsuiteId = resolveSuiteId({\n\t\t\texplicit: options.suite,\n\t\t\tenvSuite: process.env[SUITE_ENV_VAR],\n\t\t\tsettings: settingsManager,\n\t\t\tagentDir,\n\t\t});\n\t\tconst suiteAssembly = createSuiteAssembly({\n\t\t\tcwd,\n\t\t\tagentDir,\n\t\t\tsuiteId,\n\t\t\tpluginProfileId: options.pluginProfileId,\n\t\t\tselectedPluginIds: options.selectedPluginIds,\n\t\t\tdisabledPluginIds: options.disabledPluginIds,\n\t\t\tpluginHost: options.pluginHost,\n\t\t\tverifiedPlugins: options.verifiedPlugins,\n\t\t\tmanifestOverrides: options.manifestOverrides,\n\t\t});\n\t\tpluginProfile = suiteAssembly.pluginProfile;\n\t\tsuiteLoaderOverrides = suiteAssembly.loaderOverrides;\n\t\t// Suite-local skill layer (统一修复轮 B): <suiteDir>/skills rides this\n\t\t// loader's skill paths when the suite is active, mirroring the sdk's\n\t\t// self-built loader path so the two first-party entries cannot drift.\n\t\tsuiteLocalSkillsDir = suiteAssembly.localSkillsDir;\n\t\t// MCP registration pool (M4): read the mcp.json config surface, filter\n\t\t// by associations.mcp, and materialize the injected servers as\n\t\t// capability-plugin manifests for the session's explicit paths channel.\n\t\tmcpPool = resolveSuiteMcpPool({ cwd, agentDir, suite: suiteAssembly.workspace.suite });\n\t}\n\tconst additionalSkillPaths = [\n\t\t...(options.resourceLoaderOptions?.additionalSkillPaths ?? []),\n\t\t...(suiteLocalSkillsDir === undefined ? [] : [suiteLocalSkillsDir]),\n\t];\n\tconst resourceLoader = new DefaultResourceLoader({\n\t\t...(options.resourceLoaderOptions ?? {}),\n\t\t...suiteLoaderOverrides,\n\t\t...(additionalSkillPaths.length > 0 ? { additionalSkillPaths } : {}),\n\t\tcwd,\n\t\tagentDir,\n\t\tsettingsManager,\n\t});\n\tawait resourceLoader.reload(options.resourceLoaderReloadOptions);\n\n\tconst diagnostics: AgentSessionRuntimeDiagnostic[] = [];\n\tawait modelRuntime.refresh({ allowNetwork: false });\n\tfor (const message of mcpPool?.diagnostics ?? []) {\n\t\tdiagnostics.push({ type: \"info\", message });\n\t}\n\tdiagnostics.push(...(options.pluginBindingDiagnostics ?? []));\n\n\treturn {\n\t\tcwd,\n\t\tagentDir,\n\t\tmodelRuntime,\n\t\tsettingsManager,\n\t\tresourceLoader,\n\t\tdiagnostics,\n\t\t...(suiteId === undefined ? {} : { suiteId }),\n\t\t...(pluginProfile === undefined ? {} : { pluginProfile }),\n\t\t...(options.pluginProfileId === undefined ? {} : { pluginProfileId: options.pluginProfileId }),\n\t\t...(options.installedCapabilityPlugins === undefined\n\t\t\t? {}\n\t\t\t: { installedCapabilityPlugins: Object.freeze([...options.installedCapabilityPlugins]) }),\n\t\t...(mcpPool !== undefined && mcpPool.manifestPaths.length > 0\n\t\t\t? { mcpCapabilityPluginPaths: mcpPool.manifestPaths }\n\t\t\t: {}),\n\t\t...(mcpPool !== undefined && mcpPool.deferredPluginIds.length > 0\n\t\t\t? { mcpDeferredToolPluginIds: mcpPool.deferredPluginIds }\n\t\t\t: {}),\n\t};\n}\n\n/**\n * Create an AgentSession from previously created services.\n *\n * This keeps session creation separate from service creation so callers can\n * resolve model, thinking, tools, and other session inputs against the target\n * cwd before constructing the session.\n */\nexport async function createAgentSessionFromServices(\n\toptions: CreateAgentSessionFromServicesOptions,\n): Promise<CreateAgentSessionResult> {\n\treturn createAgentSession({\n\t\tcwd: options.services.cwd,\n\t\tagentDir: options.services.agentDir,\n\t\tmodelRuntime: options.services.modelRuntime,\n\t\tsettingsManager: options.services.settingsManager,\n\t\tresourceLoader: options.resourceLoader ?? options.services.resourceLoader,\n\t\tsessionManager: options.sessionManager,\n\t\tmodel: options.model,\n\t\tstreamFn: options.streamFn,\n\t\tthinkingLevel: options.thinkingLevel,\n\t\tscopedModels: options.scopedModels,\n\t\ttools: options.tools,\n\t\texcludeTools: options.excludeTools,\n\t\tnoTools: options.noTools,\n\t\tcustomTools: options.customTools,\n\t\t// Suite binding: an explicit option wins; otherwise the services' single\n\t\t// resolution result is forwarded so the sdk does not resolve again and\n\t\t// the two sides cannot drift (设计 §9).\n\t\t...(options.suite !== undefined || options.services.suiteId !== undefined\n\t\t\t? { suite: options.suite ?? options.services.suiteId }\n\t\t\t: {}),\n\t\t// Capability wiring (方案系统 M3): the sdk's caller-supplied-loader\n\t\t// boundary would leave it off for the services' own loader, so first-party\n\t\t// assembly turns it on here; an explicit option wins.\n\t\t...((options.suiteCapabilityWiring ?? options.services.suiteId !== undefined)\n\t\t\t? { suiteCapabilityWiring: true as const }\n\t\t\t: {}),\n\t\t...(options.services.pluginProfile === undefined ? {} : { pluginProfile: options.services.pluginProfile }),\n\t\t...(options.services.installedCapabilityPlugins === undefined\n\t\t\t? {}\n\t\t\t: { installedCapabilityPlugins: options.services.installedCapabilityPlugins }),\n\t\tsessionStartEvent: options.sessionStartEvent,\n\t\tcapabilityMode: options.capabilityMode,\n\t\tdiscoverCapabilityPlugins: options.discoverCapabilityPlugins,\n\t\t// Trace/log control face (设计 §4.4/§5/§6): undefined passes through, so\n\t\t// the sdk defaults (trace on, no host logging) stay in effect.\n\t\ttraceEnabled: options.traceEnabled,\n\t\thostLogger: options.hostLogger,\n\t\t// MCP registration pool (M4): the services' generated manifest paths ride\n\t\t// the explicit caller-intent channel, so they bypass associations.plugins\n\t\t// filtering (they are governed by associations.mcp, not associations.plugins);\n\t\t// caller-provided paths keep discovery-order precedence on id conflicts.\n\t\t...(options.services.mcpCapabilityPluginPaths === undefined\n\t\t\t? { capabilityPluginPaths: options.capabilityPluginPaths }\n\t\t\t: {\n\t\t\t\t\tcapabilityPluginPaths: [\n\t\t\t\t\t\t...(options.capabilityPluginPaths ?? []),\n\t\t\t\t\t\t...options.services.mcpCapabilityPluginPaths,\n\t\t\t\t\t],\n\t\t\t\t}),\n\t\t...(options.services.mcpDeferredToolPluginIds === undefined\n\t\t\t? {}\n\t\t\t: { deferredToolPluginIds: options.services.mcpDeferredToolPluginIds }),\n\t\tcontextStrategyName: options.contextStrategyName,\n\t\tretryPolicyName: options.retryPolicyName,\n\t\tcompactionPolicyName: options.compactionPolicyName,\n\t\toverflowPolicyName: options.overflowPolicyName,\n\t\tbranchSummaryPolicyName: options.branchSummaryPolicyName,\n\t\t...(options.interactionHost === undefined ? {} : { interactionHost: options.interactionHost }),\n\t\t...(options.enableAgentTasks === undefined ? {} : { enableAgentTasks: options.enableAgentTasks }),\n\t\t...(options.subagentCommunicationWiring === undefined\n\t\t\t? {}\n\t\t\t: { subagentCommunicationWiring: options.subagentCommunicationWiring }),\n\t\t...(options.subagentPoolFromSelfInvocation === undefined\n\t\t\t? {}\n\t\t\t: { subagentPoolFromSelfInvocation: options.subagentPoolFromSelfInvocation }),\n\t});\n}\n"]}
1
+ {"version":3,"file":"agent-session-services.d.ts","sourceRoot":"","sources":["../../src/core/agent-session-services.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { isAbsolute, join, relative, sep } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { ThinkingLevel } from \"@agent-forge/agent-core\";\nimport type { Api, CredentialStore, Model } from \"@agent-forge/ai\";\nimport { CONFIG_DIR_NAME, getAgentDir, VERSION } from \"../config.ts\";\nimport type { HostFactsV1 } from \"../plugins/ecosystem/types.ts\";\nimport type { ObservabilityPlugin } from \"../plugins/observability-types.ts\";\nimport type {\n\tBuiltinPluginManifestOverridesV1,\n\tBuiltinPluginProfileIdV1,\n\tBuiltinPluginProfileResolutionV1,\n} from \"../profile/plugin-profiles.ts\";\nimport type { VerifiedToolPluginV1 } from \"../profile/profile-assembly.ts\";\nimport type { SuiteDefinition } from \"../profiles/builtin-suites.ts\";\nimport { createSuiteAssembly, resolveSuiteId, SUITE_ENV_VAR } from \"../profiles/suite-loader.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport { EXPERIMENTAL_PUBLIC_API_VERSION } from \"./extensions/index.ts\";\nimport { ModelRuntime } from \"./model-runtime.ts\";\nimport {\n\tDefaultResourceLoader,\n\ttype DefaultResourceLoaderOptions,\n\ttype ResourceLoader,\n\ttype ResourceLoaderReloadOptions,\n} from \"./resource-loader.ts\";\nimport {\n\ttype CreateAgentSessionOptions,\n\ttype CreateAgentSessionResult,\n\tcreateAgentSession,\n\ttype InstalledCapabilityPluginV1,\n} from \"./sdk.ts\";\nimport type { SessionManager } from \"./session-manager.ts\";\nimport type { SessionStartMetadata } from \"./session-start.ts\";\nimport { SettingsManager } from \"./settings-manager.ts\";\nimport type { ToolDefinition } from \"./tools/tool-definition.ts\";\n\n/**\n * Non-fatal issues collected while creating services or sessions.\n *\n * Runtime creation returns diagnostics to the caller instead of printing or\n * exiting. The app layer decides whether warnings should be shown and whether\n * errors should abort startup.\n */\nexport interface AgentSessionRuntimeDiagnostic {\n\ttype: \"info\" | \"warning\" | \"error\";\n\tmessage: string;\n}\n\n/**\n * Inputs for creating cwd-bound runtime services.\n *\n * These services are recreated whenever the effective session cwd changes.\n * CLI-provided resource paths should be resolved to absolute paths before they\n * reach this function, so later cwd switches do not reinterpret them.\n */\nexport interface CreateAgentSessionServicesOptions {\n\tcwd: string;\n\tagentDir?: string;\n\tsettingsManager?: SettingsManager;\n\tmodelRuntime?: ModelRuntime;\n\t/**\n\t * Credential storage used by the default model runtime (D-067 phase 1):\n\t * forwarded to `ModelRuntime.create` when `modelRuntime` is omitted.\n\t * Ignored when an explicit `modelRuntime` is supplied. Defaults to the\n\t * file at `<agentDir>/auth.json`.\n\t */\n\tcredentials?: CredentialStore;\n\tmodelRuntimeSignal?: AbortSignal;\n\tresourceLoaderOptions?: Omit<DefaultResourceLoaderOptions, \"cwd\" | \"agentDir\" | \"settingsManager\">;\n\tresourceLoaderReloadOptions?: ResourceLoaderReloadOptions;\n\t/**\n\t * Explicit suite id (highest resolution priority, 设计 §9). Without it the\n\t * suite resolves via AGENT_FORGE_SUITE, then settings, then \"coding\".\n\t */\n\tsuite?: string;\n\t/**\n\t * Wire the full suite assembly (agents.md three-level chain, system prompt\n\t * gate, skill/extension association filters, MCP registration pool) into\n\t * these services' DefaultResourceLoader. Default false: services built\n\t * without it keep the plain loader behavior (evals and testkit\n\t * determinism). When true, the suite id is resolved exactly once here and\n\t * exposed as AgentSessionServices.suiteId so session creation reuses it\n\t * instead of resolving again. The MCP pool (设计 §4/§5) additionally reads\n\t * the mcp.json config surface, filters it by associations.mcp, and\n\t * materializes the injected servers as capability-plugin manifests\n\t * (AgentSessionServices.mcpCapabilityPluginPaths).\n\t */\n\tsuiteAssembly?: boolean;\n\t/** Optional domain plugin profile selected for this suite. */\n\tpluginProfileId?: BuiltinPluginProfileIdV1;\n\t/** Optional subset of plugins from the selected builtin Profile. */\n\tselectedPluginIds?: readonly string[];\n\t/** Optional plugin IDs disabled within the selected builtin Profile. */\n\tdisabledPluginIds?: readonly string[];\n\tpluginHost?: HostFactsV1;\n\tverifiedPlugins?: readonly VerifiedToolPluginV1[];\n\t/** Explicit host-owned active installed manifests; never discovered implicitly. */\n\tmanifestOverrides?: BuiltinPluginManifestOverridesV1;\n\t/**\n\t * Verified active installations (D-075 S2 installed-code-loading) from the\n\t * host's active-binding resolution; forwarded to session creation so their\n\t * plugin.json paths enter the sdk's candidate pool for profile members.\n\t */\n\tinstalledCapabilityPlugins?: readonly InstalledCapabilityPluginV1[];\n\t/** Host diagnostics from active-install resolution; no package data is retained. */\n\tpluginBindingDiagnostics?: readonly AgentSessionRuntimeDiagnostic[];\n}\n\n/**\n * Inputs for creating an AgentSession from already-created services.\n *\n * Use this after services exist and any cwd-bound model/tool/session options\n * have been resolved against those services.\n */\nexport interface CreateAgentSessionFromServicesOptions {\n\tservices: AgentSessionServices;\n\tsessionManager: SessionManager;\n\tsessionStartEvent?: SessionStartMetadata;\n\tmodel?: Model<Api>;\n\tstreamFn?: CreateAgentSessionOptions[\"streamFn\"];\n\tthinkingLevel?: ThinkingLevel;\n\tscopedModels?: Array<{ model: Model<Api>; thinkingLevel?: ThinkingLevel }>;\n\ttools?: string[];\n\texcludeTools?: CreateAgentSessionOptions[\"excludeTools\"];\n\tnoTools?: CreateAgentSessionOptions[\"noTools\"];\n\tcapabilityMode?: CreateAgentSessionOptions[\"capabilityMode\"];\n\tdiscoverCapabilityPlugins?: CreateAgentSessionOptions[\"discoverCapabilityPlugins\"];\n\t/**\n\t * Session trace collection (设计 §4.4/§6), forwarded to createAgentSession.\n\t * Omitted keeps the sdk default (tracing on); hosts pass `false` for\n\t * `--no-trace`.\n\t */\n\ttraceEnabled?: CreateAgentSessionOptions[\"traceEnabled\"];\n\t/**\n\t * Host-process logger forwarded to createAgentSession (设计 §5). Omitted\n\t * keeps the sdk's explicit no-logging contract (instrumentation no-ops).\n\t */\n\thostLogger?: CreateAgentSessionOptions[\"hostLogger\"];\n\tcapabilityPluginPaths?: CreateAgentSessionOptions[\"capabilityPluginPaths\"];\n\tcontextStrategyName?: CreateAgentSessionOptions[\"contextStrategyName\"];\n\tretryPolicyName?: CreateAgentSessionOptions[\"retryPolicyName\"];\n\tcompactionPolicyName?: CreateAgentSessionOptions[\"compactionPolicyName\"];\n\toverflowPolicyName?: CreateAgentSessionOptions[\"overflowPolicyName\"];\n\tbranchSummaryPolicyName?: CreateAgentSessionOptions[\"branchSummaryPolicyName\"];\n\t/** Host adapter for cancellable interaction tasks, forwarded to createAgentSession. */\n\tinteractionHost?: CreateAgentSessionOptions[\"interactionHost\"];\n\t/**\n\t * 覆盖 services 自带 loader。pooled runner 的叶子会话用它注入子任务档案的\n\t * `systemPromptAppend`(追加语义,不替换继承内容);缺省沿用 services 的 loader。\n\t */\n\tresourceLoader?: CreateAgentSessionOptions[\"resourceLoader\"];\n\t/**\n\t * Forwarded to createAgentSession. Headless subagent runners pass `false` so a\n\t * runner task session stays a leaf (no nested agent tasks; D-045 increment 2b).\n\t */\n\tenableAgentTasks?: CreateAgentSessionOptions[\"enableAgentTasks\"];\n\tcustomTools?: ToolDefinition[];\n\t/**\n\t * Explicit suite id forwarded to createAgentSession. When omitted, the\n\t * services' resolved suiteId (suiteAssembly: true) is used; without either,\n\t * createAgentSession resolves the suite itself.\n\t */\n\tsuite?: string;\n\t/**\n\t * Wire the suite's capability surface (方案系统 M3) onto the created\n\t * sessions. Default: on when the services ran the suite assembly\n\t * (suiteAssembly: true, so first-party entries get the builtin capability\n\t * whitelist and plugin-pool filtering); otherwise off, matching the sdk's\n\t * caller-supplied-loader assembly boundary.\n\t */\n\tsuiteCapabilityWiring?: boolean;\n\t/**\n\t * 子代理通信面的宿主接线(D-060 S5 pooled parity):pooled runner 的叶子会话\n\t * 用它注入 post/drainInbox 闭包(身份绑定到叶子会话,信箱为文件承载、跨进程)。\n\t */\n\tsubagentCommunicationWiring?: CreateAgentSessionOptions[\"subagentCommunicationWiring\"];\n\t/**\n\t * 承载退役切片 1(生产 CLI 默认 pooled):转发 createAgentSession 的\n\t * self-invocation 自动池化声明。仅真实 CLI 装配传 true。\n\t */\n\tsubagentPoolFromSelfInvocation?: CreateAgentSessionOptions[\"subagentPoolFromSelfInvocation\"];\n}\n\n/**\n * Coherent cwd-bound runtime services for one effective session cwd.\n *\n * This is infrastructure only. The AgentSession itself is created separately so\n * session options can be resolved against these services first.\n */\nexport interface AgentSessionServices {\n\tcwd: string;\n\t/**\n\t * /metrics 命令的数据源共享 ref(observability 插件工厂创建时写入\n\t * plugin.getMetrics、dispose 时置空;宿主装配完成后读取接进命令 options)。\n\t * 空 = 插件未挂载(/metrics 显示未装配警告)。\n\t */\n\tobservabilityGetMetricsRef?: { current?: ObservabilityPlugin[\"getMetrics\"] };\n\tagentDir: string;\n\tmodelRuntime: ModelRuntime;\n\tsettingsManager: SettingsManager;\n\tresourceLoader: ResourceLoader;\n\tdiagnostics: AgentSessionRuntimeDiagnostic[];\n\t/**\n\t * Suite id resolved for these services when `suiteAssembly` was requested;\n\t * undefined when assembly was off (no suite filtering was applied here).\n\t */\n\tsuiteId?: string;\n\tpluginProfile?: BuiltinPluginProfileResolutionV1;\n\tpluginProfileId?: BuiltinPluginProfileIdV1;\n\t/**\n\t * Verified active installations (D-075 S2) forwarded from the services\n\t * options; createAgentSessionFromServices passes them to the sdk's\n\t * installed-code-loading candidate pool.\n\t */\n\tinstalledCapabilityPlugins?: readonly InstalledCapabilityPluginV1[];\n\t/**\n\t * Capability-plugin manifest paths materialized for the suite's MCP\n\t * registration pool (M4, 设计 §4/§5). Defined only when `suiteAssembly`\n\t * injected at least one associated mcp.json server;\n\t * createAgentSessionFromServices appends them to the created session's\n\t * capabilityPluginPaths.\n\t */\n\tmcpCapabilityPluginPaths?: readonly string[];\n\t/**\n\t * Plugin ids of the MCP pool servers configured with `deferredTools: true`.\n\t * Their tools register normally but stay out of the default active set; the\n\t * session's tool_search tool discovers and activates them on demand.\n\t */\n\tmcpDeferredToolPluginIds?: readonly string[];\n}\n\n// ---------------------------------------------------------------------------\n// Suite MCP registration pool (方案系统 M4: MCP 配置面, 设计 §4/§5)\n// ---------------------------------------------------------------------------\n\n/** User-level MCP config file directly inside the agent dir. */\nconst MCP_CONFIG_FILENAME = \"mcp.json\";\n/** Generated per-server capability-plugin manifests live below this agentDir dir. */\nconst MCP_POOL_DIR = \"mcp/pool\";\n/** Shared stdio bridge module inside the pool dir (leading \"_\" keeps server names distinct). */\nconst MCP_POOL_BRIDGE_DIR = \"_bridge\";\n/** Server names are associations keys and pool directory names; \"_\" is reserved for the bridge. */\nconst MCP_SERVER_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;\n\n/**\n * Implementation backing url-configured pool entries (createMcpHttpServerPlugin).\n * Sources resolve first so development always runs the current implementation;\n * published installs ship only dist, so dist is the fallback.\n */\nconst MCP_HTTP_PLUGIN_SOURCE_PATH = fileURLToPath(new URL(\"../plugins/mcp-http.ts\", import.meta.url));\nconst MCP_HTTP_PLUGIN_DIST_PATH = fileURLToPath(new URL(\"../../dist/plugins/mcp-http.js\", import.meta.url));\n\n/** One MCP server resolved from an mcp.json configuration file. */\nexport interface SuiteMcpServerV1 {\n\t/** Server name: the associations.mcp match key and the pool directory name. */\n\treadonly name: string;\n\t/** stdio launch command; undefined for remote HTTP servers (`url` set). */\n\treadonly command?: string;\n\treadonly args: readonly string[];\n\t/** Remote HTTP endpoint; undefined for stdio servers (`command` set). */\n\treadonly url?: string;\n\t/**\n\t * Custom request headers sent with every request to a remote HTTP server;\n\t * undefined for stdio servers (`headers` there only contributes a\n\t * diagnostic and is never forwarded).\n\t */\n\treadonly headers?: Readonly<Record<string, string>>;\n\t/**\n\t * Config layer the server came from. \"project\" (`<cwd>/.agent-forge/mcp.json`)\n\t * is the third layer (设计 §4) and always passes; \"user\"\n\t * (`<agentDir>/mcp.json`) injects only when associated.\n\t */\n\treadonly scope: \"user\" | \"project\";\n\t/** Generated capability-plugin manifest path for this server. */\n\treadonly manifestPath: string;\n\t/** Whether the server's tools stay out of the default active set until tool_search activates them. */\n\treadonly deferred: boolean;\n}\n\nexport interface SuiteMcpPoolV1 {\n\t/** Injected servers in deterministic order (project first, then user). */\n\treadonly servers: readonly SuiteMcpServerV1[];\n\t/** Manifest paths ready for the session's capabilityPluginPaths channel. */\n\treadonly manifestPaths: readonly string[];\n\t/** Plugin ids whose tools are registered but excluded from the default active set. */\n\treadonly deferredPluginIds: readonly string[];\n\t/**\n\t * Diagnostics: unreadable/invalid config files, filtered non-associated\n\t * servers, project-overridden duplicates, and dangling associations.\n\t * Reported, never thrown (设计 §11.3).\n\t */\n\treadonly diagnostics: readonly string[];\n}\n\ninterface McpServerConfigV1 {\n\treadonly command?: string;\n\treadonly args: readonly string[];\n\treadonly url?: string;\n\t/** Custom request headers for remote HTTP servers; ignored (with a diagnostic) on stdio entries. */\n\treadonly headers?: Readonly<Record<string, string>>;\n\treadonly deferredTools?: boolean;\n}\n\n/**\n * Remote MCP URLs accept only http/https; any other protocol or unparseable\n * value is a configuration error, not a fallback path.\n */\nfunction isHttpUrl(value: string): boolean {\n\ttry {\n\t\tconst protocol = new URL(value).protocol;\n\t\treturn protocol === \"http:\" || protocol === \"https:\";\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Reads one mcp.json (`{ \"mcpServers\": { \"<name>\": { \"command\", \"args\" } } }`\n * for stdio servers, or `{ \"url\" }` for remote HTTP servers). Each entry must\n * carry exactly one of \"command\" and \"url\". Corruption tolerance: a missing\n * file is an empty config; an unreadable or malformed file, and invalid\n * per-server entries, contribute a diagnostic and are skipped — never thrown.\n */\nfunction parseMcpConfig(path: string): {\n\tservers: Map<string, McpServerConfigV1>;\n\tdiagnostics: string[];\n} {\n\tconst servers = new Map<string, McpServerConfigV1>();\n\tconst diagnostics: string[] = [];\n\tlet value: unknown;\n\ttry {\n\t\tvalue = JSON.parse(readFileSync(path, \"utf8\"));\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return { servers, diagnostics };\n\t\tdiagnostics.push(\n\t\t\t`MCP config at ${path} is unreadable; ignoring it. Errors: ${error instanceof Error ? error.message : String(error)}`,\n\t\t);\n\t\treturn { servers, diagnostics };\n\t}\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tdiagnostics.push(`MCP config at ${path} must be an object with an \"mcpServers\" map; ignoring it.`);\n\t\treturn { servers, diagnostics };\n\t}\n\tconst mcpServers = (value as Record<string, unknown>).mcpServers;\n\tif (mcpServers === undefined) return { servers, diagnostics };\n\tif (typeof mcpServers !== \"object\" || mcpServers === null || Array.isArray(mcpServers)) {\n\t\tdiagnostics.push(`MCP config at ${path} must carry an \"mcpServers\" object; ignoring it.`);\n\t\treturn { servers, diagnostics };\n\t}\n\tfor (const [name, entry] of Object.entries(mcpServers as Record<string, unknown>)) {\n\t\tif (!MCP_SERVER_NAME_PATTERN.test(name)) {\n\t\t\tdiagnostics.push(\n\t\t\t\t`MCP server name \"${name}\" in ${path} is invalid (must match ${MCP_SERVER_NAME_PATTERN.source}); ignoring it.`,\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof entry !== \"object\" || entry === null || Array.isArray(entry)) {\n\t\t\tdiagnostics.push(`MCP server \"${name}\" in ${path} must be an object with a \"command\" or \"url\"; ignoring it.`);\n\t\t\tcontinue;\n\t\t}\n\t\tconst config = entry as Record<string, unknown>;\n\t\tif (config.url !== undefined && (typeof config.url !== \"string\" || config.url.trim().length === 0)) {\n\t\t\tdiagnostics.push(`MCP server \"${name}\" in ${path} requires \"url\" to be a non-empty string; ignoring it.`);\n\t\t\tcontinue;\n\t\t}\n\t\tconst hasCommand = typeof config.command === \"string\" && config.command.trim().length > 0;\n\t\tconst hasUrl = typeof config.url === \"string\" && config.url.trim().length > 0;\n\t\tif (hasCommand && hasUrl) {\n\t\t\tdiagnostics.push(\n\t\t\t\t`MCP server \"${name}\" in ${path} accepts either \"command\" (stdio server) or \"url\" (remote HTTP server), not both; ignoring it.`,\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!hasCommand && !hasUrl) {\n\t\t\tdiagnostics.push(\n\t\t\t\t`MCP server \"${name}\" in ${path} requires a non-empty string \"command\" (stdio server) or \"url\" (remote HTTP server); ignoring it.`,\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tif (hasUrl && !isHttpUrl(config.url as string)) {\n\t\t\tdiagnostics.push(\n\t\t\t\t`MCP server \"${name}\" in ${path} requires \"url\" to be a valid http:// or https:// URL; ignoring it.`,\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tif (\n\t\t\tconfig.args !== undefined &&\n\t\t\t(!Array.isArray(config.args) || !config.args.every((arg) => typeof arg === \"string\"))\n\t\t) {\n\t\t\tdiagnostics.push(`MCP server \"${name}\" in ${path} requires \"args\" to be a string array; ignoring it.`);\n\t\t\tcontinue;\n\t\t}\n\t\tif (config.deferredTools !== undefined && typeof config.deferredTools !== \"boolean\") {\n\t\t\tdiagnostics.push(`MCP server \"${name}\" in ${path} requires \"deferredTools\" to be a boolean; ignoring it.`);\n\t\t\tcontinue;\n\t\t}\n\t\tif (config.headers !== undefined) {\n\t\t\tif (hasCommand) {\n\t\t\t\t// Same acceptance style as a url entry carrying args: the entry\n\t\t\t\t// loads, but the field belongs to the other transport shape.\n\t\t\t\tdiagnostics.push(\n\t\t\t\t\t`MCP server \"${name}\" in ${path} carries \"headers\" but headers only apply to remote \"url\" (HTTP) servers; ignoring them.`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconst headersValid =\n\t\t\t\t\ttypeof config.headers === \"object\" &&\n\t\t\t\t\tconfig.headers !== null &&\n\t\t\t\t\t!Array.isArray(config.headers) &&\n\t\t\t\t\tObject.values(config.headers as Record<string, unknown>).every(\n\t\t\t\t\t\t(headerValue) => typeof headerValue === \"string\" && headerValue.length > 0,\n\t\t\t\t\t);\n\t\t\t\tif (!headersValid) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\t`MCP server \"${name}\" in ${path} requires \"headers\" to be an object with non-empty string values; ignoring it.`,\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tservers.set(name, {\n\t\t\targs: (config.args as readonly string[] | undefined) ?? [],\n\t\t\tdeferredTools: config.deferredTools === true ? true : undefined,\n\t\t\t...(hasCommand\n\t\t\t\t? { command: config.command as string }\n\t\t\t\t: {\n\t\t\t\t\t\turl: config.url as string,\n\t\t\t\t\t\t// Kept verbatim (no case normalization): managed remote MCP\n\t\t\t\t\t\t// endpoints compare header names and values exactly.\n\t\t\t\t\t\t...(config.headers === undefined\n\t\t\t\t\t\t\t? {}\n\t\t\t\t\t\t\t: { headers: config.headers as Readonly<Record<string, string>> }),\n\t\t\t\t\t}),\n\t\t});\n\t}\n\treturn { servers, diagnostics };\n}\n\n/**\n * Generated stdio bridge shared by every injected server: JSON-RPC 2.0 over a\n * spawned child process (argv, never a shell — except on win32, where a\n * resolved `.cmd`/`.bat` shim is launched through `cmd.exe /d /s /c`, so its\n * arguments cross cmd's command-line interpreter exactly as with\n * `shell: true`), MCP initialize/tools/list\n * handshake, and one registerTool per remote tool through the public\n * capability API. Tool call policy stays host-owned; the bridge only forwards\n * requests and maps results. On win32 the transport additionally resolves\n * `.cmd`/`.bat` shims (bare names via PATH, explicit suffixes verbatim) and\n * launches them through `cmd.exe /d /s /c` with MSVCRT argv quoting, because\n * Node >= 18.20 refuses to spawn extension shims directly (EINVAL) and\n * extension-less shim names ENOENT.\n */\nconst MCP_POOL_BRIDGE_SOURCE = `// Generated by the suite MCP registration pool (agent-session-services). Do not edit.\nimport { spawn } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nconst REQUEST_TIMEOUT_MS = 30000;\n\n// Windows .cmd/.bat shims cannot be spawned directly: Node >= 18.20 raises\n// EINVAL for commands carrying a shim extension and ENOENT for bare names\n// (npx, pnpm, ...), so bare command names (no path separator) are probed\n// along PATH for a .cmd/.bat shim, and explicit .cmd/.bat commands pass\n// through for cmd.exe wrapping. Everything else - .exe/.com, path-bearing\n// executables, non-win32 platforms, and PATH misses - resolves to undefined\n// and keeps the direct spawn behavior (a miss keeps the original ENOENT).\nfunction resolveWin32ShimCommand(command) {\n\tif (process.platform !== 'win32') return undefined;\n\tconst lowered = command.toLowerCase();\n\tif (lowered.endsWith('.cmd') || lowered.endsWith('.bat')) return command;\n\tif (command.includes('/') || command.includes('\\\\\\\\')) return undefined;\n\tfor (const dir of (process.env.PATH || '').split(';')) {\n\t\tif (!dir) continue;\n\t\tconst cmdShim = join(dir, command + '.cmd');\n\t\tif (existsSync(cmdShim)) return cmdShim;\n\t\tconst batShim = join(dir, command + '.bat');\n\t\tif (existsSync(batShim)) return batShim;\n\t}\n\treturn undefined;\n}\n\n// MSVCRT argv quoting for the cmd.exe /c command string: an argument that is\n// empty or contains space/tab/quote is wrapped in double quotes, embedded\n// quotes are escaped as \\\\\", and backslashes directly before a quote (or a\n// quoted argument's trailing backslashes) double up (2n rule) so they cannot\n// escape the closing quote. Plain arguments pass through untouched.\nfunction quoteCommandString(parts) {\n\tconst quoted = [];\n\tfor (const part of parts) {\n\t\tif (part !== '' && !/[ \\\\t\"]/.test(part)) {\n\t\t\tquoted.push(part);\n\t\t\tcontinue;\n\t\t}\n\t\tlet inner = '';\n\t\tlet backslashes = 0;\n\t\tfor (const ch of part) {\n\t\t\tif (ch === '\\\\\\\\') {\n\t\t\t\tbackslashes += 1;\n\t\t\t} else if (ch === '\"') {\n\t\t\t\tinner += '\\\\\\\\'.repeat(backslashes * 2 + 1) + '\"';\n\t\t\t\tbackslashes = 0;\n\t\t\t} else {\n\t\t\t\tif (backslashes > 0) {\n\t\t\t\t\tinner += '\\\\\\\\'.repeat(backslashes);\n\t\t\t\t\tbackslashes = 0;\n\t\t\t\t}\n\t\t\t\tinner += ch;\n\t\t\t}\n\t\t}\n\t\tif (backslashes > 0) {\n\t\t\tinner += '\\\\\\\\'.repeat(backslashes * 2);\n\t\t}\n\t\tquoted.push('\"' + inner + '\"');\n\t}\n\treturn quoted.join(' ');\n}\n\nfunction startTransport(command, args) {\n\t// win32 only: wrap .cmd/.bat shims through cmd.exe (resolveWin32ShimCommand).\n\t// The MSVCRT-quoted command string gets ONE more plain outer pair of\n\t// quotes (cmd.exe dialect, not MSVCRT): /S strips that outer pair and\n\t// re-parses the inner string. windowsVerbatimArguments is required so the\n\t// pre-built string reaches cmd.exe untouched; Node's default quoting would\n\t// wrap it again and cmd.exe would see literal \\\\\" sequences instead.\n\tconst shim = resolveWin32ShimCommand(command);\n\tconst child =\n\t\tshim === undefined\n\t\t\t? spawn(command, args, { shell: false, stdio: ['pipe', 'pipe', 'pipe'] })\n\t\t\t: spawn('cmd.exe', ['/d', '/s', '/c', '\"' + quoteCommandString([shim].concat(args)) + '\"'], {\n\t\t\t\t\twindowsVerbatimArguments: true,\n\t\t\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t\t\t});\n\tlet nextId = 1;\n\tlet closed = false;\n\tlet failure = null;\n\tlet buffered = '';\n\tconst pending = new Map();\n\tconst rejectAll = (error) => {\n\t\tif (failure) return;\n\t\tfailure = error;\n\t\tclosed = true;\n\t\tfor (const request of pending.values()) request.reject(error);\n\t\tpending.clear();\n\t};\n\tchild.stdout.setEncoding('utf8');\n\tchild.stdout.on('data', (chunk) => {\n\t\tbuffered += chunk;\n\t\tconst lines = buffered.split(/\\\\r?\\\\n/);\n\t\tbuffered = lines.pop() || '';\n\t\tfor (const line of lines) {\n\t\t\tif (!line.trim()) continue;\n\t\t\tlet response;\n\t\t\ttry {\n\t\t\t\tresponse = JSON.parse(line);\n\t\t\t} catch {\n\t\t\t\trejectAll(new Error('MCP server produced a malformed JSON-RPC response'));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (response.id === undefined || response.id === null) continue;\n\t\t\tconst request = pending.get(response.id);\n\t\t\tif (!request) continue;\n\t\t\tpending.delete(response.id);\n\t\t\tif (response.error) {\n\t\t\t\trequest.reject(new Error('MCP request failed: ' + String(response.error.message || 'unknown error')));\n\t\t\t} else {\n\t\t\t\trequest.resolve(response.result);\n\t\t\t}\n\t\t}\n\t});\n\tchild.stderr.setEncoding('utf8');\n\tchild.stderr.on('data', () => undefined);\n\tchild.once('error', (error) => rejectAll(new Error('Failed to spawn MCP server: ' + error.message)));\n\tchild.once('close', (exitCode) => rejectAll(new Error('MCP server exited with code ' + String(exitCode))));\n\tconst send = (message) => {\n\t\tchild.stdin.write(JSON.stringify(message) + '\\\\n');\n\t};\n\tconst request = (method, params, signal) => {\n\t\tif (failure || closed) return Promise.reject(failure || new Error('MCP transport is closed'));\n\t\tif (signal && signal.aborted) return Promise.reject(new Error('MCP request aborted'));\n\t\tconst id = nextId++;\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tpending.delete(id);\n\t\t\t\treject(new Error('MCP request timed out: ' + method));\n\t\t\t}, REQUEST_TIMEOUT_MS);\n\t\t\tpending.set(id, {\n\t\t\t\tresolve: (result) => {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\tresolve(result);\n\t\t\t\t},\n\t\t\t\treject: (error) => {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\treject(error);\n\t\t\t\t},\n\t\t\t});\n\t\t\tif (signal) {\n\t\t\t\tsignal.addEventListener(\n\t\t\t\t\t'abort',\n\t\t\t\t\t() => {\n\t\t\t\t\t\tif (pending.delete(id)) reject(new Error('MCP request aborted'));\n\t\t\t\t\t},\n\t\t\t\t\t{ once: true },\n\t\t\t\t);\n\t\t\t}\n\t\t\tsend(Object.assign({ jsonrpc: '2.0', id, method }, params === undefined ? {} : { params }));\n\t\t});\n\t};\n\treturn {\n\t\trequest,\n\t\tnotify(method, params) {\n\t\t\tif (closed) return;\n\t\t\tsend(Object.assign({ jsonrpc: '2.0', method }, params === undefined ? {} : { params }));\n\t\t},\n\t\tclose() {\n\t\t\tif (closed) return;\n\t\t\tclosed = true;\n\t\t\tchild.stdin.end();\n\t\t\tif (!child.killed) child.kill();\n\t\t},\n\t};\n}\n\nfunction normalizeToolResult(result) {\n\tif (result && typeof result === 'object' && Array.isArray(result.content)) {\n\t\treturn { content: result.content, details: result.details };\n\t}\n\tif (result === undefined) return { content: [{ type: 'text', text: '' }], details: undefined };\n\treturn { content: [{ type: 'text', text: JSON.stringify(result) }], details: undefined };\n}\n\nexport default function createMcpStdioServerPlugin(config) {\n\treturn async (api) => {\n\t\tconst transport = startTransport(config.command, config.args || []);\n\t\ttry {\n\t\t\tawait transport.request('initialize', {\n\t\t\t\tprotocolVersion: '2024-11-05',\n\t\t\t\tcapabilities: {},\n\t\t\t\tclientInfo: { name: 'agent-forge-mcp-pool', version: '0.1.0' },\n\t\t\t});\n\t\t\ttransport.notify('notifications/initialized');\n\t\t\tconst listing = await transport.request('tools/list');\n\t\t\tif (!listing || !Array.isArray(listing.tools)) {\n\t\t\t\tthrow new Error('MCP tools/list result must contain tools[]');\n\t\t\t}\n\t\t\tfor (const tool of listing.tools) {\n\t\t\t\tif (!tool || typeof tool.name !== 'string' || !tool.name) {\n\t\t\t\t\tthrow new Error('MCP tool requires a non-empty name');\n\t\t\t\t}\n\t\t\t\tapi.registerTool({\n\t\t\t\t\tname: tool.name,\n\t\t\t\t\tlabel: tool.name,\n\t\t\t\t\tdescription: typeof tool.description === 'string' ? tool.description : 'MCP tool: ' + tool.name,\n\t\t\t\t\tparameters:\n\t\t\t\t\t\ttool.inputSchema && typeof tool.inputSchema === 'object'\n\t\t\t\t\t\t\t? tool.inputSchema\n\t\t\t\t\t\t\t: { type: 'object', properties: {} },\n\t\t\t\t\texecute: async (toolCallId, params, signal) => {\n\t\t\t\t\t\t// Dual call convention: the session passes (toolCallId, params,\n\t\t\t\t\t\t// signal); the runtime's invokeTool passes the input as the\n\t\t\t\t\t\t// single first argument.\n\t\t\t\t\t\tconst singleArgCall = params === undefined && typeof toolCallId !== 'string';\n\t\t\t\t\t\tconst input = singleArgCall ? toolCallId : params;\n\t\t\t\t\t\tconst result = await transport.request(\n\t\t\t\t\t\t\t'tools/call',\n\t\t\t\t\t\t\t{ name: tool.name, arguments: input || {} },\n\t\t\t\t\t\t\tsingleArgCall ? undefined : signal,\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn normalizeToolResult(result);\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tdispose() {\n\t\t\t\t\ttransport.close();\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (error) {\n\t\t\ttransport.close();\n\t\t\tthrow error;\n\t\t}\n\t};\n}\n`;\n\nfunction writeMcpPoolBridge(poolDir: string): void {\n\tconst bridgeDir = join(poolDir, MCP_POOL_BRIDGE_DIR);\n\tmkdirSync(bridgeDir, { recursive: true });\n\twriteFileSync(join(bridgeDir, \"index.mjs\"), MCP_POOL_BRIDGE_SOURCE, \"utf8\");\n}\n\n/**\n * Import specifier for the HTTP server plugin implementation, as written into\n * a generated pool entry below `fromDir`. Relative same-drive form matches the\n * stdio entry's style; a cross-drive relative() result stays an absolute POSIX\n * path, which the capability loader (jiti) resolves.\n */\nfunction mcpHttpPluginImportSpec(fromDir: string): string {\n\tconst implPath = existsSync(MCP_HTTP_PLUGIN_SOURCE_PATH) ? MCP_HTTP_PLUGIN_SOURCE_PATH : MCP_HTTP_PLUGIN_DIST_PATH;\n\tconst relNative = relative(fromDir, implPath);\n\tconst relPosix = relNative.split(sep).join(\"/\");\n\treturn isAbsolute(relNative) ? relPosix : `./${relPosix}`;\n}\n\n/** Materializes one server as a capability-plugin manifest; returns the manifest path. */\nfunction writeMcpPoolServer(poolDir: string, name: string, server: McpServerConfigV1): string {\n\tconst serverDir = join(poolDir, name);\n\tmkdirSync(serverDir, { recursive: true });\n\tconst manifest = {\n\t\tid: `agent-forge.mcp.${name}`,\n\t\tversion: \"0.1.0\",\n\t\t// The pool is re-materialized every session, so the declared range always\n\t\t// includes the running host (D-073): an upgraded host never rejects its\n\t\t// own generated pool manifests through the hostVersion gate.\n\t\thostVersion: `>=${VERSION}`,\n\t\tapiVersion: EXPERIMENTAL_PUBLIC_API_VERSION,\n\t\tentry: \"./index.mjs\",\n\t\trequiredCapabilities: [\"tools\"],\n\t};\n\twriteFileSync(join(serverDir, \"plugin.json\"), `${JSON.stringify(manifest, null, 2)}\\n`, \"utf8\");\n\tconst entry =\n\t\tserver.url === undefined\n\t\t\t? [\n\t\t\t\t\t\"// Generated by the suite MCP registration pool (agent-session-services). Do not edit.\",\n\t\t\t\t\t`import createMcpStdioServerPlugin from \"../${MCP_POOL_BRIDGE_DIR}/index.mjs\";`,\n\t\t\t\t\t`export default createMcpStdioServerPlugin(${JSON.stringify({ command: server.command, args: server.args })});`,\n\t\t\t\t\t\"\",\n\t\t\t\t].join(\"\\n\")\n\t\t\t: [\n\t\t\t\t\t\"// Generated by the suite MCP registration pool (agent-session-services). Do not edit.\",\n\t\t\t\t\t`import { createMcpHttpServerPlugin } from \"${mcpHttpPluginImportSpec(serverDir)}\";`,\n\t\t\t\t\t`export default createMcpHttpServerPlugin(${JSON.stringify({\n\t\t\t\t\t\turl: server.url,\n\t\t\t\t\t\t...(server.headers === undefined ? {} : { headers: server.headers }),\n\t\t\t\t\t})});`,\n\t\t\t\t\t\"\",\n\t\t\t\t].join(\"\\n\");\n\twriteFileSync(join(serverDir, \"index.mjs\"), entry, \"utf8\");\n\treturn join(serverDir, \"plugin.json\");\n}\n\n/**\n * Resolves the suite's MCP registration pool (方案系统 M4: MCP 配置面, 设计\n * §4/§5) and materializes each injected server as a capability-plugin\n * manifest below `<agentDir>/mcp/pool/`, ready for the session's\n * `capabilityPluginPaths` channel — the same way plugins directory discovery\n * injects manifests. Filtering: the project level\n * (`<cwd>/.agent-forge/mcp.json`) is the third layer (设计 §4) and always\n * passes; the user level (`<agentDir>/mcp.json`) injects only servers named\n * in `suite.associations.mcp` — an empty association list means zero\n * user-level injection, the same semantics as skills/extensions.\n */\nexport function resolveSuiteMcpPool(options: {\n\tcwd: string;\n\tagentDir: string;\n\tsuite: SuiteDefinition;\n}): SuiteMcpPoolV1 {\n\tconst { cwd, agentDir, suite } = options;\n\tconst userConfigPath = join(agentDir, MCP_CONFIG_FILENAME);\n\tconst projectConfigPath = join(cwd, CONFIG_DIR_NAME, MCP_CONFIG_FILENAME);\n\tconst user = parseMcpConfig(userConfigPath);\n\tconst project = parseMcpConfig(projectConfigPath);\n\tconst diagnostics = [...project.diagnostics, ...user.diagnostics];\n\n\tconst selected = new Map<string, McpServerConfigV1 & { scope: \"user\" | \"project\" }>();\n\t// Third layer (设计 §4): project-level servers always pass; they win name\n\t// collisions over user definitions.\n\tfor (const [name, server] of project.servers) selected.set(name, { ...server, scope: \"project\" });\n\tfor (const [name, server] of user.servers) {\n\t\tif (selected.has(name)) {\n\t\t\tdiagnostics.push(\n\t\t\t\t`MCP server \"${name}\" from ${userConfigPath} is overridden by the project-level definition at ${projectConfigPath}; keeping the project one.`,\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!suite.associations.mcp.includes(name)) {\n\t\t\tdiagnostics.push(\n\t\t\t\t`Suite \"${suite.id}\" MCP server \"${name}\" is not associated (associations.mcp); not injected.`,\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tselected.set(name, { ...server, scope: \"user\" });\n\t}\n\tfor (const name of suite.associations.mcp) {\n\t\tif (!selected.has(name)) {\n\t\t\tdiagnostics.push(\n\t\t\t\t`Suite \"${suite.id}\" dangling association \"${name}\" (mcp): not found in the discovered registry; ignored.`,\n\t\t\t);\n\t\t}\n\t}\n\n\tconst servers: SuiteMcpServerV1[] = [];\n\tconst manifestPaths: string[] = [];\n\tconst deferredPluginIds: string[] = [];\n\tif (selected.size > 0) {\n\t\tconst poolDir = join(agentDir, MCP_POOL_DIR);\n\t\twriteMcpPoolBridge(poolDir);\n\t\tfor (const [name, server] of selected) {\n\t\t\tconst manifestPath = writeMcpPoolServer(poolDir, name, server);\n\t\t\tmanifestPaths.push(manifestPath);\n\t\t\tservers.push({\n\t\t\t\tname,\n\t\t\t\targs: server.args,\n\t\t\t\tscope: server.scope,\n\t\t\t\tmanifestPath,\n\t\t\t\tdeferred: server.deferredTools === true,\n\t\t\t\t...(server.url === undefined\n\t\t\t\t\t? { command: server.command }\n\t\t\t\t\t: {\n\t\t\t\t\t\t\turl: server.url,\n\t\t\t\t\t\t\t...(server.headers === undefined ? {} : { headers: server.headers }),\n\t\t\t\t\t\t}),\n\t\t\t});\n\t\t\tif (server.deferredTools === true) {\n\t\t\t\tdeferredPluginIds.push(`agent-forge.mcp.${name}`);\n\t\t\t}\n\t\t}\n\t}\n\treturn { servers, manifestPaths, deferredPluginIds, diagnostics };\n}\n\n/**\n * Create cwd-bound runtime services.\n *\n * Returns services plus diagnostics. It does not create an AgentSession.\n */\nexport async function createAgentSessionServices(\n\toptions: CreateAgentSessionServicesOptions,\n): Promise<AgentSessionServices> {\n\tconst cwd = resolvePath(options.cwd);\n\tconst agentDir = options.agentDir ? resolvePath(options.agentDir) : getAgentDir();\n\tconst modelRuntime =\n\t\toptions.modelRuntime ??\n\t\t(await ModelRuntime.create({\n\t\t\tauthPath: join(agentDir, \"auth.json\"),\n\t\t\tmodelsPath: join(agentDir, \"models.json\"),\n\t\t\tcredentials: options.credentials,\n\t\t\tsignal: options.modelRuntimeSignal,\n\t\t}));\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\t// Suite assembly (设计 §3/§4/§8, M2): resolve once and wire the shared\n\t// assembly into this loader. Off by default so evals/testkit services keep\n\t// their fixture resources unfiltered.\n\tlet suiteId: string | undefined;\n\tlet suiteLoaderOverrides:\n\t\t| Pick<\n\t\t\t\tDefaultResourceLoaderOptions,\n\t\t\t\t\"agentsFilesOverride\" | \"skillsOverride\" | \"systemPromptOverride\" | \"appendSystemPromptOverride\"\n\t\t >\n\t\t| undefined;\n\tlet suiteLocalSkillsDir: string | undefined;\n\tlet pluginProfile: BuiltinPluginProfileResolutionV1 | undefined;\n\t/** MCP registration pool for the assembled suite (M4); undefined when assembly is off. */\n\tlet mcpPool: SuiteMcpPoolV1 | undefined;\n\tif (options.suiteAssembly) {\n\t\tsuiteId = resolveSuiteId({\n\t\t\texplicit: options.suite,\n\t\t\tenvSuite: process.env[SUITE_ENV_VAR],\n\t\t\tsettings: settingsManager,\n\t\t\tagentDir,\n\t\t});\n\t\tconst suiteAssembly = createSuiteAssembly({\n\t\t\tcwd,\n\t\t\tagentDir,\n\t\t\tsuiteId,\n\t\t\tpluginProfileId: options.pluginProfileId,\n\t\t\tselectedPluginIds: options.selectedPluginIds,\n\t\t\tdisabledPluginIds: options.disabledPluginIds,\n\t\t\tpluginHost: options.pluginHost,\n\t\t\tverifiedPlugins: options.verifiedPlugins,\n\t\t\tmanifestOverrides: options.manifestOverrides,\n\t\t});\n\t\tpluginProfile = suiteAssembly.pluginProfile;\n\t\tsuiteLoaderOverrides = suiteAssembly.loaderOverrides;\n\t\t// Suite-local skill layer (统一修复轮 B): <suiteDir>/skills rides this\n\t\t// loader's skill paths when the suite is active, mirroring the sdk's\n\t\t// self-built loader path so the two first-party entries cannot drift.\n\t\tsuiteLocalSkillsDir = suiteAssembly.localSkillsDir;\n\t\t// MCP registration pool (M4): read the mcp.json config surface, filter\n\t\t// by associations.mcp, and materialize the injected servers as\n\t\t// capability-plugin manifests for the session's explicit paths channel.\n\t\tmcpPool = resolveSuiteMcpPool({ cwd, agentDir, suite: suiteAssembly.workspace.suite });\n\t}\n\tconst additionalSkillPaths = [\n\t\t...(options.resourceLoaderOptions?.additionalSkillPaths ?? []),\n\t\t...(suiteLocalSkillsDir === undefined ? [] : [suiteLocalSkillsDir]),\n\t];\n\tconst resourceLoader = new DefaultResourceLoader({\n\t\t...(options.resourceLoaderOptions ?? {}),\n\t\t...suiteLoaderOverrides,\n\t\t...(additionalSkillPaths.length > 0 ? { additionalSkillPaths } : {}),\n\t\tcwd,\n\t\tagentDir,\n\t\tsettingsManager,\n\t});\n\tawait resourceLoader.reload(options.resourceLoaderReloadOptions);\n\n\tconst diagnostics: AgentSessionRuntimeDiagnostic[] = [];\n\tawait modelRuntime.refresh({ allowNetwork: false });\n\tfor (const message of mcpPool?.diagnostics ?? []) {\n\t\tdiagnostics.push({ type: \"info\", message });\n\t}\n\tdiagnostics.push(...(options.pluginBindingDiagnostics ?? []));\n\n\treturn {\n\t\tcwd,\n\t\tagentDir,\n\t\tmodelRuntime,\n\t\tsettingsManager,\n\t\tresourceLoader,\n\t\tdiagnostics,\n\t\t...(suiteId === undefined ? {} : { suiteId }),\n\t\t...(pluginProfile === undefined ? {} : { pluginProfile }),\n\t\t...(options.pluginProfileId === undefined ? {} : { pluginProfileId: options.pluginProfileId }),\n\t\t...(options.installedCapabilityPlugins === undefined\n\t\t\t? {}\n\t\t\t: { installedCapabilityPlugins: Object.freeze([...options.installedCapabilityPlugins]) }),\n\t\t...(mcpPool !== undefined && mcpPool.manifestPaths.length > 0\n\t\t\t? { mcpCapabilityPluginPaths: mcpPool.manifestPaths }\n\t\t\t: {}),\n\t\t...(mcpPool !== undefined && mcpPool.deferredPluginIds.length > 0\n\t\t\t? { mcpDeferredToolPluginIds: mcpPool.deferredPluginIds }\n\t\t\t: {}),\n\t};\n}\n\n/**\n * Create an AgentSession from previously created services.\n *\n * This keeps session creation separate from service creation so callers can\n * resolve model, thinking, tools, and other session inputs against the target\n * cwd before constructing the session.\n */\nexport async function createAgentSessionFromServices(\n\toptions: CreateAgentSessionFromServicesOptions,\n): Promise<CreateAgentSessionResult> {\n\treturn createAgentSession({\n\t\tcwd: options.services.cwd,\n\t\tagentDir: options.services.agentDir,\n\t\tmodelRuntime: options.services.modelRuntime,\n\t\tsettingsManager: options.services.settingsManager,\n\t\tresourceLoader: options.resourceLoader ?? options.services.resourceLoader,\n\t\tsessionManager: options.sessionManager,\n\t\tmodel: options.model,\n\t\tstreamFn: options.streamFn,\n\t\tthinkingLevel: options.thinkingLevel,\n\t\tscopedModels: options.scopedModels,\n\t\ttools: options.tools,\n\t\texcludeTools: options.excludeTools,\n\t\tnoTools: options.noTools,\n\t\tcustomTools: options.customTools,\n\t\t// Suite binding: an explicit option wins; otherwise the services' single\n\t\t// resolution result is forwarded so the sdk does not resolve again and\n\t\t// the two sides cannot drift (设计 §9).\n\t\t...(options.suite !== undefined || options.services.suiteId !== undefined\n\t\t\t? { suite: options.suite ?? options.services.suiteId }\n\t\t\t: {}),\n\t\t// Capability wiring (方案系统 M3): the sdk's caller-supplied-loader\n\t\t// boundary would leave it off for the services' own loader, so first-party\n\t\t// assembly turns it on here; an explicit option wins.\n\t\t...((options.suiteCapabilityWiring ?? options.services.suiteId !== undefined)\n\t\t\t? { suiteCapabilityWiring: true as const }\n\t\t\t: {}),\n\t\t...(options.services.pluginProfile === undefined ? {} : { pluginProfile: options.services.pluginProfile }),\n\t\t...(options.services.installedCapabilityPlugins === undefined\n\t\t\t? {}\n\t\t\t: { installedCapabilityPlugins: options.services.installedCapabilityPlugins }),\n\t\tsessionStartEvent: options.sessionStartEvent,\n\t\tcapabilityMode: options.capabilityMode,\n\t\tdiscoverCapabilityPlugins: options.discoverCapabilityPlugins,\n\t\t// Trace/log control face (设计 §4.4/§5/§6): undefined passes through, so\n\t\t// the sdk defaults (trace on, no host logging) stay in effect.\n\t\ttraceEnabled: options.traceEnabled,\n\t\thostLogger: options.hostLogger,\n\t\t// MCP registration pool (M4): the services' generated manifest paths ride\n\t\t// the explicit caller-intent channel, so they bypass associations.plugins\n\t\t// filtering (they are governed by associations.mcp, not associations.plugins);\n\t\t// caller-provided paths keep discovery-order precedence on id conflicts.\n\t\t...(options.services.mcpCapabilityPluginPaths === undefined\n\t\t\t? { capabilityPluginPaths: options.capabilityPluginPaths }\n\t\t\t: {\n\t\t\t\t\tcapabilityPluginPaths: [\n\t\t\t\t\t\t...(options.capabilityPluginPaths ?? []),\n\t\t\t\t\t\t...options.services.mcpCapabilityPluginPaths,\n\t\t\t\t\t],\n\t\t\t\t}),\n\t\t...(options.services.mcpDeferredToolPluginIds === undefined\n\t\t\t? {}\n\t\t\t: { deferredToolPluginIds: options.services.mcpDeferredToolPluginIds }),\n\t\tcontextStrategyName: options.contextStrategyName,\n\t\tretryPolicyName: options.retryPolicyName,\n\t\tcompactionPolicyName: options.compactionPolicyName,\n\t\toverflowPolicyName: options.overflowPolicyName,\n\t\tbranchSummaryPolicyName: options.branchSummaryPolicyName,\n\t\t...(options.interactionHost === undefined ? {} : { interactionHost: options.interactionHost }),\n\t\t...(options.enableAgentTasks === undefined ? {} : { enableAgentTasks: options.enableAgentTasks }),\n\t\t...(options.subagentCommunicationWiring === undefined\n\t\t\t? {}\n\t\t\t: { subagentCommunicationWiring: options.subagentCommunicationWiring }),\n\t\t...(options.subagentPoolFromSelfInvocation === undefined\n\t\t\t? {}\n\t\t\t: { subagentPoolFromSelfInvocation: options.subagentPoolFromSelfInvocation }),\n\t});\n}\n"]}