@agent-native/core 0.51.15 → 0.53.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 (251) hide show
  1. package/README.md +42 -96
  2. package/blueprints/action/crud.md +98 -0
  3. package/blueprints/channel/discord.md +74 -0
  4. package/blueprints/provider/stripe.md +87 -0
  5. package/blueprints/sandbox/docker.md +78 -0
  6. package/dist/action.d.ts +24 -0
  7. package/dist/action.d.ts.map +1 -1
  8. package/dist/action.js +4 -0
  9. package/dist/action.js.map +1 -1
  10. package/dist/agent/observational-memory/compactor.d.ts +43 -0
  11. package/dist/agent/observational-memory/compactor.d.ts.map +1 -0
  12. package/dist/agent/observational-memory/compactor.js +50 -0
  13. package/dist/agent/observational-memory/compactor.js.map +1 -0
  14. package/dist/agent/observational-memory/config.d.ts +37 -0
  15. package/dist/agent/observational-memory/config.d.ts.map +1 -0
  16. package/dist/agent/observational-memory/config.js +48 -0
  17. package/dist/agent/observational-memory/config.js.map +1 -0
  18. package/dist/agent/observational-memory/index.d.ts +26 -0
  19. package/dist/agent/observational-memory/index.d.ts.map +1 -0
  20. package/dist/agent/observational-memory/index.js +25 -0
  21. package/dist/agent/observational-memory/index.js.map +1 -0
  22. package/dist/agent/observational-memory/internal-run.d.ts +37 -0
  23. package/dist/agent/observational-memory/internal-run.d.ts.map +1 -0
  24. package/dist/agent/observational-memory/internal-run.js +59 -0
  25. package/dist/agent/observational-memory/internal-run.js.map +1 -0
  26. package/dist/agent/observational-memory/message-text.d.ts +13 -0
  27. package/dist/agent/observational-memory/message-text.d.ts.map +1 -0
  28. package/dist/agent/observational-memory/message-text.js +46 -0
  29. package/dist/agent/observational-memory/message-text.js.map +1 -0
  30. package/dist/agent/observational-memory/migrations.d.ts +13 -0
  31. package/dist/agent/observational-memory/migrations.d.ts.map +1 -0
  32. package/dist/agent/observational-memory/migrations.js +43 -0
  33. package/dist/agent/observational-memory/migrations.js.map +1 -0
  34. package/dist/agent/observational-memory/observer.d.ts +37 -0
  35. package/dist/agent/observational-memory/observer.d.ts.map +1 -0
  36. package/dist/agent/observational-memory/observer.js +82 -0
  37. package/dist/agent/observational-memory/observer.js.map +1 -0
  38. package/dist/agent/observational-memory/plugin.d.ts +16 -0
  39. package/dist/agent/observational-memory/plugin.d.ts.map +1 -0
  40. package/dist/agent/observational-memory/plugin.js +26 -0
  41. package/dist/agent/observational-memory/plugin.js.map +1 -0
  42. package/dist/agent/observational-memory/prompts.d.ts +27 -0
  43. package/dist/agent/observational-memory/prompts.d.ts.map +1 -0
  44. package/dist/agent/observational-memory/prompts.js +42 -0
  45. package/dist/agent/observational-memory/prompts.js.map +1 -0
  46. package/dist/agent/observational-memory/read.d.ts +47 -0
  47. package/dist/agent/observational-memory/read.d.ts.map +1 -0
  48. package/dist/agent/observational-memory/read.js +99 -0
  49. package/dist/agent/observational-memory/read.js.map +1 -0
  50. package/dist/agent/observational-memory/reflector.d.ts +31 -0
  51. package/dist/agent/observational-memory/reflector.d.ts.map +1 -0
  52. package/dist/agent/observational-memory/reflector.js +76 -0
  53. package/dist/agent/observational-memory/reflector.js.map +1 -0
  54. package/dist/agent/observational-memory/schema.d.ts +267 -0
  55. package/dist/agent/observational-memory/schema.d.ts.map +1 -0
  56. package/dist/agent/observational-memory/schema.js +48 -0
  57. package/dist/agent/observational-memory/schema.js.map +1 -0
  58. package/dist/agent/observational-memory/store.d.ts +52 -0
  59. package/dist/agent/observational-memory/store.d.ts.map +1 -0
  60. package/dist/agent/observational-memory/store.js +197 -0
  61. package/dist/agent/observational-memory/store.js.map +1 -0
  62. package/dist/agent/observational-memory/types.d.ts +61 -0
  63. package/dist/agent/observational-memory/types.d.ts.map +1 -0
  64. package/dist/agent/observational-memory/types.js +9 -0
  65. package/dist/agent/observational-memory/types.js.map +1 -0
  66. package/dist/agent/production-agent.d.ts +15 -0
  67. package/dist/agent/production-agent.d.ts.map +1 -1
  68. package/dist/agent/production-agent.js +240 -1
  69. package/dist/agent/production-agent.js.map +1 -1
  70. package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
  71. package/dist/agent/run-loop-with-resume.js +49 -0
  72. package/dist/agent/run-loop-with-resume.js.map +1 -1
  73. package/dist/agent/run-store.d.ts +17 -0
  74. package/dist/agent/run-store.d.ts.map +1 -1
  75. package/dist/agent/run-store.js +55 -0
  76. package/dist/agent/run-store.js.map +1 -1
  77. package/dist/agent/runtime-context.d.ts +30 -0
  78. package/dist/agent/runtime-context.d.ts.map +1 -1
  79. package/dist/agent/runtime-context.js +54 -1
  80. package/dist/agent/runtime-context.js.map +1 -1
  81. package/dist/agent/tool-call-journal.d.ts +101 -0
  82. package/dist/agent/tool-call-journal.d.ts.map +1 -0
  83. package/dist/agent/tool-call-journal.js +214 -0
  84. package/dist/agent/tool-call-journal.js.map +1 -0
  85. package/dist/agent/types.d.ts +24 -0
  86. package/dist/agent/types.d.ts.map +1 -1
  87. package/dist/agent/types.js.map +1 -1
  88. package/dist/cli/add.d.ts +109 -0
  89. package/dist/cli/add.d.ts.map +1 -0
  90. package/dist/cli/add.js +352 -0
  91. package/dist/cli/add.js.map +1 -0
  92. package/dist/cli/connect.d.ts +5 -4
  93. package/dist/cli/connect.d.ts.map +1 -1
  94. package/dist/cli/connect.js +157 -48
  95. package/dist/cli/connect.js.map +1 -1
  96. package/dist/cli/eval.d.ts +17 -0
  97. package/dist/cli/eval.d.ts.map +1 -0
  98. package/dist/cli/eval.js +121 -0
  99. package/dist/cli/eval.js.map +1 -0
  100. package/dist/cli/index.js +44 -3
  101. package/dist/cli/index.js.map +1 -1
  102. package/dist/cli/mcp-config-writers.d.ts +20 -13
  103. package/dist/cli/mcp-config-writers.d.ts.map +1 -1
  104. package/dist/cli/mcp-config-writers.js +152 -13
  105. package/dist/cli/mcp-config-writers.js.map +1 -1
  106. package/dist/cli/mcp.d.ts +2 -2
  107. package/dist/cli/mcp.d.ts.map +1 -1
  108. package/dist/cli/mcp.js +50 -196
  109. package/dist/cli/mcp.js.map +1 -1
  110. package/dist/cli/plan-local.d.ts +69 -6
  111. package/dist/cli/plan-local.d.ts.map +1 -1
  112. package/dist/cli/plan-local.js +517 -23
  113. package/dist/cli/plan-local.js.map +1 -1
  114. package/dist/cli/recap.d.ts.map +1 -1
  115. package/dist/cli/recap.js +1 -1
  116. package/dist/cli/recap.js.map +1 -1
  117. package/dist/cli/skills.d.ts +13 -6
  118. package/dist/cli/skills.d.ts.map +1 -1
  119. package/dist/cli/skills.js +287 -111
  120. package/dist/cli/skills.js.map +1 -1
  121. package/dist/client/AssistantChat.d.ts.map +1 -1
  122. package/dist/client/AssistantChat.js +118 -92
  123. package/dist/client/AssistantChat.js.map +1 -1
  124. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  125. package/dist/client/agent-chat-adapter.js +16 -0
  126. package/dist/client/agent-chat-adapter.js.map +1 -1
  127. package/dist/client/agent-engine-key.d.ts +6 -4
  128. package/dist/client/agent-engine-key.d.ts.map +1 -1
  129. package/dist/client/agent-engine-key.js +9 -6
  130. package/dist/client/agent-engine-key.js.map +1 -1
  131. package/dist/client/chat/run-recovery.js +1 -1
  132. package/dist/client/chat/run-recovery.js.map +1 -1
  133. package/dist/client/chat/tool-call-display.d.ts +20 -1
  134. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  135. package/dist/client/chat/tool-call-display.js +32 -7
  136. package/dist/client/chat/tool-call-display.js.map +1 -1
  137. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  138. package/dist/client/settings/SettingsPanel.js +7 -14
  139. package/dist/client/settings/SettingsPanel.js.map +1 -1
  140. package/dist/client/sse-event-processor.d.ts +13 -0
  141. package/dist/client/sse-event-processor.d.ts.map +1 -1
  142. package/dist/client/sse-event-processor.js +21 -0
  143. package/dist/client/sse-event-processor.js.map +1 -1
  144. package/dist/coding-tools/run-code.d.ts +7 -0
  145. package/dist/coding-tools/run-code.d.ts.map +1 -1
  146. package/dist/coding-tools/run-code.js +21 -106
  147. package/dist/coding-tools/run-code.js.map +1 -1
  148. package/dist/coding-tools/sandbox/adapter.d.ts +79 -0
  149. package/dist/coding-tools/sandbox/adapter.d.ts.map +1 -0
  150. package/dist/coding-tools/sandbox/adapter.js +24 -0
  151. package/dist/coding-tools/sandbox/adapter.js.map +1 -0
  152. package/dist/coding-tools/sandbox/index.d.ts +51 -0
  153. package/dist/coding-tools/sandbox/index.d.ts.map +1 -0
  154. package/dist/coding-tools/sandbox/index.js +79 -0
  155. package/dist/coding-tools/sandbox/index.js.map +1 -0
  156. package/dist/coding-tools/sandbox/local-child-process-adapter.d.ts +24 -0
  157. package/dist/coding-tools/sandbox/local-child-process-adapter.d.ts.map +1 -0
  158. package/dist/coding-tools/sandbox/local-child-process-adapter.js +141 -0
  159. package/dist/coding-tools/sandbox/local-child-process-adapter.js.map +1 -0
  160. package/dist/db/client.d.ts +4 -2
  161. package/dist/db/client.d.ts.map +1 -1
  162. package/dist/db/client.js +6 -4
  163. package/dist/db/client.js.map +1 -1
  164. package/dist/deploy/route-discovery.d.ts.map +1 -1
  165. package/dist/deploy/route-discovery.js +1 -0
  166. package/dist/deploy/route-discovery.js.map +1 -1
  167. package/dist/eval/agent-runner.d.ts +63 -0
  168. package/dist/eval/agent-runner.d.ts.map +1 -0
  169. package/dist/eval/agent-runner.js +142 -0
  170. package/dist/eval/agent-runner.js.map +1 -0
  171. package/dist/eval/define-eval.d.ts +29 -0
  172. package/dist/eval/define-eval.d.ts.map +1 -0
  173. package/dist/eval/define-eval.js +43 -0
  174. package/dist/eval/define-eval.js.map +1 -0
  175. package/dist/eval/index.d.ts +18 -0
  176. package/dist/eval/index.d.ts.map +1 -0
  177. package/dist/eval/index.js +17 -0
  178. package/dist/eval/index.js.map +1 -0
  179. package/dist/eval/report.d.ts +8 -0
  180. package/dist/eval/report.d.ts.map +1 -0
  181. package/dist/eval/report.js +44 -0
  182. package/dist/eval/report.js.map +1 -0
  183. package/dist/eval/runner.d.ts +67 -0
  184. package/dist/eval/runner.d.ts.map +1 -0
  185. package/dist/eval/runner.js +256 -0
  186. package/dist/eval/runner.js.map +1 -0
  187. package/dist/eval/scorer.d.ts +83 -0
  188. package/dist/eval/scorer.d.ts.map +1 -0
  189. package/dist/eval/scorer.js +195 -0
  190. package/dist/eval/scorer.js.map +1 -0
  191. package/dist/eval/types.d.ts +162 -0
  192. package/dist/eval/types.d.ts.map +1 -0
  193. package/dist/eval/types.js +20 -0
  194. package/dist/eval/types.js.map +1 -0
  195. package/dist/observability/traces.d.ts.map +1 -1
  196. package/dist/observability/traces.js +100 -1
  197. package/dist/observability/traces.js.map +1 -1
  198. package/dist/observability/tracing.d.ts +73 -0
  199. package/dist/observability/tracing.d.ts.map +1 -0
  200. package/dist/observability/tracing.js +126 -0
  201. package/dist/observability/tracing.js.map +1 -0
  202. package/dist/onboarding/default-steps.d.ts.map +1 -1
  203. package/dist/onboarding/default-steps.js +4 -1
  204. package/dist/onboarding/default-steps.js.map +1 -1
  205. package/dist/provider-api/actions/query-staged-dataset.d.ts +1 -1
  206. package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
  207. package/dist/scripts/agent-engines/list-agent-engines.js +10 -3
  208. package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
  209. package/dist/server/action-discovery.d.ts.map +1 -1
  210. package/dist/server/action-discovery.js +4 -0
  211. package/dist/server/action-discovery.js.map +1 -1
  212. package/dist/server/agent-chat-plugin.d.ts +9 -0
  213. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  214. package/dist/server/agent-chat-plugin.js +118 -110
  215. package/dist/server/agent-chat-plugin.js.map +1 -1
  216. package/dist/server/agent-engine-api-key-route.d.ts +37 -0
  217. package/dist/server/agent-engine-api-key-route.d.ts.map +1 -0
  218. package/dist/server/agent-engine-api-key-route.js +105 -0
  219. package/dist/server/agent-engine-api-key-route.js.map +1 -0
  220. package/dist/server/agent-teams.d.ts +62 -0
  221. package/dist/server/agent-teams.d.ts.map +1 -1
  222. package/dist/server/agent-teams.js +99 -2
  223. package/dist/server/agent-teams.js.map +1 -1
  224. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  225. package/dist/server/core-routes-plugin.js +17 -10
  226. package/dist/server/core-routes-plugin.js.map +1 -1
  227. package/dist/server/create-server.js +1 -1
  228. package/dist/server/create-server.js.map +1 -1
  229. package/dist/server/credential-provider.d.ts.map +1 -1
  230. package/dist/server/credential-provider.js +2 -0
  231. package/dist/server/credential-provider.js.map +1 -1
  232. package/dist/server/framework-request-handler.d.ts.map +1 -1
  233. package/dist/server/framework-request-handler.js +33 -1
  234. package/dist/server/framework-request-handler.js.map +1 -1
  235. package/dist/server/index.d.ts +1 -0
  236. package/dist/server/index.d.ts.map +1 -1
  237. package/dist/server/index.js +1 -0
  238. package/dist/server/index.js.map +1 -1
  239. package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +17 -4
  240. package/dist/templates/workspace-core/.agents/skills/harness-agents/SKILL.md +20 -0
  241. package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +20 -0
  242. package/docs/content/agent-teams.md +32 -0
  243. package/docs/content/blueprint-installer.md +73 -0
  244. package/docs/content/evals.md +141 -0
  245. package/docs/content/pr-visual-recap.md +7 -4
  246. package/docs/content/sandbox-adapters.md +134 -0
  247. package/docs/content/template-plan.md +20 -8
  248. package/package.json +5 -1
  249. package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +17 -4
  250. package/src/templates/workspace-core/.agents/skills/harness-agents/SKILL.md +20 -0
  251. package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +20 -0
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-context.js","sourceRoot":"","sources":["../../src/agent/runtime-context.ts"],"names":[],"mappings":"AAKA,SAAS,eAAe,CAAC,QAAgB;IACvC,IAAI,CAAC;QACH,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;QAClE,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,IAAU,EAAE,QAAgB;IAClD,OAAO,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE;QACtC,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,MAAM;QACf,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,MAAM;QACb,GAAG,EAAE,SAAS;QACd,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,SAAS;QACjB,YAAY,EAAE,OAAO;KACtB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAClB,CAAC;AAED,SAAS,UAAU,CAAC,IAAU,EAAE,QAAgB;IAC9C,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE;QAC7C,QAAQ,EAAE,QAAQ;QAClB,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;QAChB,GAAG,EAAE,SAAS;KACf,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,EAAE,KAAK,IAAI,MAAM,CAAC;IACzE,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,KAAK,IAAI,IAAI,CAAC;IACzE,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,EAAE,KAAK,IAAI,IAAI,CAAC;IACrE,OAAO,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,UAAiC,EAAE;IAEnC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;IACtC,MAAM,QAAQ,GACZ,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC;QACvE,CAAC,CAAC,OAAO,CAAC,QAAQ;QAClB,CAAC,CAAC,KAAK,CAAC;IAEZ,OAAO;;;cAGK,GAAG,CAAC,WAAW,EAAE;kBACb,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC;mBACrB,QAAQ;yBACF,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC;yBACzB,cAAc,CAAC,GAAG,EAAE,QAAQ,CAAC;;mBAEnC,CAAC;AACpB,CAAC","sourcesContent":["export interface RuntimeContextOptions {\n now?: Date;\n timezone?: string | null;\n}\n\nfunction isValidTimezone(timezone: string): boolean {\n try {\n new Intl.DateTimeFormat(\"en-US\", { timeZone: timezone }).format();\n return true;\n } catch {\n return false;\n }\n}\n\nfunction formatDateTime(date: Date, timezone: string): string {\n return new Intl.DateTimeFormat(\"en-US\", {\n timeZone: timezone,\n weekday: \"long\",\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n timeZoneName: \"short\",\n }).format(date);\n}\n\nfunction formatDate(date: Date, timezone: string): string {\n const parts = new Intl.DateTimeFormat(\"en-CA\", {\n timeZone: timezone,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n }).formatToParts(date);\n const year = parts.find((part) => part.type === \"year\")?.value ?? \"1970\";\n const month = parts.find((part) => part.type === \"month\")?.value ?? \"01\";\n const day = parts.find((part) => part.type === \"day\")?.value ?? \"01\";\n return `${year}-${month}-${day}`;\n}\n\nexport function buildRuntimeContextPrompt(\n options: RuntimeContextOptions = {},\n): string {\n const now = options.now ?? new Date();\n const timezone =\n typeof options.timezone === \"string\" && isValidTimezone(options.timezone)\n ? options.timezone\n : \"UTC\";\n\n return `\n\n<runtime-context>\ncurrentUtc: ${now.toISOString()}\ncurrentDateUtc: ${formatDate(now, \"UTC\")}\ncurrentTimezone: ${timezone}\ncurrentDateInTimezone: ${formatDate(now, timezone)}\ncurrentTimeInTimezone: ${formatDateTime(now, timezone)}\nUse this runtime context as authoritative for relative dates such as today, yesterday, tomorrow, this week, and last month. Resolve relative dates to explicit calendar dates before querying data or creating artifacts, and include the exact date or date range in factual answers.\n</runtime-context>`;\n}\n"]}
1
+ {"version":3,"file":"runtime-context.js","sourceRoot":"","sources":["../../src/agent/runtime-context.ts"],"names":[],"mappings":"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","sourcesContent":["export interface RuntimeContextOptions {\n now?: Date;\n timezone?: string | null;\n /**\n * Delegation depth of the agent this prompt is built for. 0 = the top-level\n * (user-facing) agent, 1 = a sub-agent spawned by the top-level agent, and so\n * on. Threaded through so a spawned sub-agent knows how deep it sits and\n * whether it is still allowed to delegate further. Omitted (or 0) for the\n * top-level chat. See `MAX_SUBAGENT_DELEGATION_DEPTH`.\n */\n delegationDepth?: number;\n}\n\n/**\n * Default hard cap on sub-agent delegation depth. The top-level agent is depth\n * 0 and may spawn sub-agents (depth 1); those may spawn once more (depth 2);\n * a spawn that would create a depth-3 sub-agent is refused. Borrowed from the\n * \"sub-agents must not infinitely spawn sub-agents\" runaway/cost safety rail.\n *\n * Override at deploy time via `AGENT_NATIVE_MAX_SUBAGENT_DEPTH` (see\n * `resolveMaxSubagentDelegationDepth`).\n */\nexport const MAX_SUBAGENT_DELEGATION_DEPTH = 2;\n\n/**\n * Upper bound the env override is clamped to. A misconfigured very-large value\n * would defeat the guardrail entirely, so we cap it at a still-generous depth.\n */\nconst MAX_SUBAGENT_DELEGATION_DEPTH_CEILING = 16;\n\n/** Env var name that overrides the default sub-agent delegation-depth cap. */\nexport const MAX_SUBAGENT_DELEGATION_DEPTH_ENV =\n \"AGENT_NATIVE_MAX_SUBAGENT_DEPTH\";\n\n/**\n * Resolve the effective maximum sub-agent delegation depth.\n *\n * Reads `AGENT_NATIVE_MAX_SUBAGENT_DEPTH` and, when it parses to a finite\n * non-negative integer, clamps it to `[0, MAX_SUBAGENT_DELEGATION_DEPTH_CEILING]`.\n * Any invalid value (non-numeric, negative, NaN, Infinity, fractional) falls\n * back to `MAX_SUBAGENT_DELEGATION_DEPTH` so a typo can never silently disable\n * the guardrail. `0` is a valid override meaning \"no sub-agents may be spawned\".\n */\nexport function resolveMaxSubagentDelegationDepth(\n env: Record<string, string | undefined> = process.env,\n): number {\n const raw = env[MAX_SUBAGENT_DELEGATION_DEPTH_ENV];\n if (raw === undefined) return MAX_SUBAGENT_DELEGATION_DEPTH;\n const trimmed = raw.trim();\n if (trimmed === \"\") return MAX_SUBAGENT_DELEGATION_DEPTH;\n // Only accept plain non-negative integers; reject \"2.5\", \"1e3\", \"0x4\", etc.\n if (!/^\\d+$/.test(trimmed)) return MAX_SUBAGENT_DELEGATION_DEPTH;\n const parsed = Number(trimmed);\n if (!Number.isSafeInteger(parsed) || parsed < 0) {\n return MAX_SUBAGENT_DELEGATION_DEPTH;\n }\n return Math.min(parsed, MAX_SUBAGENT_DELEGATION_DEPTH_CEILING);\n}\n\nfunction isValidTimezone(timezone: string): boolean {\n try {\n new Intl.DateTimeFormat(\"en-US\", { timeZone: timezone }).format();\n return true;\n } catch {\n return false;\n }\n}\n\nfunction formatDateTime(date: Date, timezone: string): string {\n return new Intl.DateTimeFormat(\"en-US\", {\n timeZone: timezone,\n weekday: \"long\",\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n timeZoneName: \"short\",\n }).format(date);\n}\n\nfunction formatDate(date: Date, timezone: string): string {\n const parts = new Intl.DateTimeFormat(\"en-CA\", {\n timeZone: timezone,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n }).formatToParts(date);\n const year = parts.find((part) => part.type === \"year\")?.value ?? \"1970\";\n const month = parts.find((part) => part.type === \"month\")?.value ?? \"01\";\n const day = parts.find((part) => part.type === \"day\")?.value ?? \"01\";\n return `${year}-${month}-${day}`;\n}\n\nexport function buildRuntimeContextPrompt(\n options: RuntimeContextOptions = {},\n): string {\n const now = options.now ?? new Date();\n const timezone =\n typeof options.timezone === \"string\" && isValidTimezone(options.timezone)\n ? options.timezone\n : \"UTC\";\n\n const depth =\n typeof options.delegationDepth === \"number\" &&\n Number.isFinite(options.delegationDepth) &&\n options.delegationDepth > 0\n ? Math.floor(options.delegationDepth)\n : 0;\n const maxDepth = resolveMaxSubagentDelegationDepth();\n const delegationLine =\n depth > 0\n ? `\\ndelegationDepth: ${depth}\\nmaxDelegationDepth: ${maxDepth}\\n${\n depth >= maxDepth\n ? `You are a sub-agent at the maximum delegation depth (${maxDepth}); you cannot spawn further sub-agents. Do the work yourself.`\n : `You are a sub-agent at delegation depth ${depth} (limit ${maxDepth}); spawn additional sub-agents only when truly necessary.`\n }`\n : \"\";\n\n return `\n\n<runtime-context>\ncurrentUtc: ${now.toISOString()}\ncurrentDateUtc: ${formatDate(now, \"UTC\")}\ncurrentTimezone: ${timezone}\ncurrentDateInTimezone: ${formatDate(now, timezone)}\ncurrentTimeInTimezone: ${formatDateTime(now, timezone)}${delegationLine}\nUse this runtime context as authoritative for relative dates such as today, yesterday, tomorrow, this week, and last month. Resolve relative dates to explicit calendar dates before querying data or creating artifacts, and include the exact date or date range in factual answers.\n</runtime-context>`;\n}\n"]}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Per-turn tool-call journal — derived (not separately recorded) from the
3
+ * existing run-event ledger. Borrowed from Flue's durable-execution journal:
4
+ * when an agent run resumes after an interruption (gateway/transport drop, cold
5
+ * start, soft-timeout auto-continue), we classify the tool calls already in the
6
+ * ledger so the resumed model does NOT re-execute side effects it already
7
+ * completed (re-sending an email, re-creating a ticket) and so it is explicitly
8
+ * told about any tool call that started but whose outcome was never recorded.
9
+ *
10
+ * IMPORTANT — this is a pure read-over-the-ledger view. There is no new
11
+ * recording hook anywhere in the hot path. The classification reuses the exact
12
+ * positional `tool_start` → `tool_done` matching that `thread-data-builder.ts`
13
+ * already relies on to rebuild durable turns:
14
+ *
15
+ * - `tool_start` events carry `{ tool, input }` (no tool-call id at this
16
+ * layer; the ledger event stream omits it).
17
+ * - `tool_done` events carry `{ tool, result }`.
18
+ * - A `tool_done` is matched to the OLDEST still-open `tool_start` for the
19
+ * same tool name (FIFO per tool), mirroring how the dispatch loop emits a
20
+ * start immediately before its matching done.
21
+ *
22
+ * A `tool_start` with no matching `tool_done` is the dangerous case: the call
23
+ * began, its side effect may or may not have landed, and the interruption ate
24
+ * the result. We surface those as "interrupted / unknown outcome" so the model
25
+ * decides rather than blindly re-running.
26
+ *
27
+ * TODO(charlie-merge): optional hard-block — refuse re-execution of
28
+ * journaled-complete tool calls at the tool layer in
29
+ * production-agent.ts/runToolCall (CHARLIE owns that file). The prompt-level
30
+ * journal here is the shippable first cut; the tool-layer enforcement is the
31
+ * stronger guarantee and must wait until CHARLIE's loop edits land. When wiring
32
+ * it, key off `classifyToolCallJournal(...).completed` and short-circuit a
33
+ * re-dispatched write tool whose (tool name + input + order) matches a
34
+ * completed entry, returning the journaled result instead of executing.
35
+ */
36
+ import type { AgentChatEvent } from "./types.js";
37
+ /** A single recorded tool-call ledger entry, classified by outcome. */
38
+ export interface ToolCallJournalEntry {
39
+ /**
40
+ * Stable-ish identity for this tool call within the turn. The ledger event
41
+ * stream has no tool-call id, so we key by tool name + a short input
42
+ * signature + positional order, exactly enough to disambiguate repeats of the
43
+ * same tool within one turn for human/model-readable reporting.
44
+ */
45
+ key: string;
46
+ /** Tool / action name (from the `tool_start` event). */
47
+ tool: string;
48
+ /** Tool input captured at `tool_start`, if any. */
49
+ input?: Record<string, string>;
50
+ /** 0-based position of the `tool_start` among all tool calls in the turn. */
51
+ order: number;
52
+ /** Result text from the matched `tool_done`, when the call completed. */
53
+ result?: string;
54
+ }
55
+ /** Result of classifying one turn's ledger events. */
56
+ export interface ToolCallJournal {
57
+ /** Tool calls with a matching `tool_done` — already ran, do NOT re-run. */
58
+ completed: ToolCallJournalEntry[];
59
+ /**
60
+ * Tool calls with a `tool_start` but no matching `tool_done` — interrupted,
61
+ * outcome unknown. The model must decide whether re-running is safe.
62
+ */
63
+ interrupted: ToolCallJournalEntry[];
64
+ }
65
+ /**
66
+ * Classify a single turn's recorded events into completed vs interrupted tool
67
+ * calls. Pure and side-effect free — given the same events it always returns
68
+ * the same journal. A `clear` event resets the per-turn tally exactly as the
69
+ * thread rebuild does, so partial streamed output that was discarded on resume
70
+ * doesn't leave phantom open tool calls.
71
+ */
72
+ export declare function classifyToolCallJournal(events: readonly AgentChatEvent[]): ToolCallJournal;
73
+ /** True when the journal has nothing worth telling a resuming model about. */
74
+ export declare function isJournalEmpty(journal: ToolCallJournal): boolean;
75
+ /**
76
+ * Find a COMPLETED journal entry that matches a tool call about to be
77
+ * dispatched, by tool name + input signature (position-independent — a resumed
78
+ * call may sit at a different order than the original). Used by the tool-layer
79
+ * hard-block in production-agent.ts/runToolCall to skip re-executing a side
80
+ * effect that already completed in a prior interrupted chunk: when this returns
81
+ * an entry, the loop returns `entry.result` instead of running the action.
82
+ *
83
+ * Returns the FIRST unmatched completed entry for that (name + input); the
84
+ * caller is expected to claim it (mark it consumed) so two identical fresh
85
+ * calls in the same turn don't both short-circuit on one journaled completion.
86
+ * Returns undefined when there is no completed entry for this exact call —
87
+ * including every fresh call, which must execute normally.
88
+ */
89
+ export declare function findCompletedJournalEntry(journal: ToolCallJournal, toolName: string, input: unknown, consumedKeys?: Set<string>): ToolCallJournalEntry | undefined;
90
+ /**
91
+ * Build the structured resume note injected on auto-continue. Returns `null`
92
+ * when there are no completed or interrupted tool calls to report, so the
93
+ * caller can preserve the exact pre-existing "continue from where you left off"
94
+ * behavior on normal resumes (no regression for turns with no tool activity).
95
+ *
96
+ * The note is intentionally a flat, model-readable block: a list of already-run
97
+ * tool calls (with short results) the model must NOT re-run, and a separate list
98
+ * of interrupted calls whose outcome is unknown for the model to decide on.
99
+ */
100
+ export declare function buildResumeJournalNote(journal: ToolCallJournal): string | null;
101
+ //# sourceMappingURL=tool-call-journal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-call-journal.d.ts","sourceRoot":"","sources":["../../src/agent/tool-call-journal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,uEAAuE;AACvE,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,sDAAsD;AACtD,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,SAAS,EAAE,oBAAoB,EAAE,CAAC;IAClC;;;OAGG;IACH,WAAW,EAAE,oBAAoB,EAAE,CAAC;CACrC;AA6BD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,cAAc,EAAE,GAChC,eAAe,CAyDjB;AAED,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAEhE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GACzB,oBAAoB,GAAG,SAAS,CAUlC;AA+BD;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,eAAe,GACvB,MAAM,GAAG,IAAI,CAiCf"}
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Per-turn tool-call journal — derived (not separately recorded) from the
3
+ * existing run-event ledger. Borrowed from Flue's durable-execution journal:
4
+ * when an agent run resumes after an interruption (gateway/transport drop, cold
5
+ * start, soft-timeout auto-continue), we classify the tool calls already in the
6
+ * ledger so the resumed model does NOT re-execute side effects it already
7
+ * completed (re-sending an email, re-creating a ticket) and so it is explicitly
8
+ * told about any tool call that started but whose outcome was never recorded.
9
+ *
10
+ * IMPORTANT — this is a pure read-over-the-ledger view. There is no new
11
+ * recording hook anywhere in the hot path. The classification reuses the exact
12
+ * positional `tool_start` → `tool_done` matching that `thread-data-builder.ts`
13
+ * already relies on to rebuild durable turns:
14
+ *
15
+ * - `tool_start` events carry `{ tool, input }` (no tool-call id at this
16
+ * layer; the ledger event stream omits it).
17
+ * - `tool_done` events carry `{ tool, result }`.
18
+ * - A `tool_done` is matched to the OLDEST still-open `tool_start` for the
19
+ * same tool name (FIFO per tool), mirroring how the dispatch loop emits a
20
+ * start immediately before its matching done.
21
+ *
22
+ * A `tool_start` with no matching `tool_done` is the dangerous case: the call
23
+ * began, its side effect may or may not have landed, and the interruption ate
24
+ * the result. We surface those as "interrupted / unknown outcome" so the model
25
+ * decides rather than blindly re-running.
26
+ *
27
+ * TODO(charlie-merge): optional hard-block — refuse re-execution of
28
+ * journaled-complete tool calls at the tool layer in
29
+ * production-agent.ts/runToolCall (CHARLIE owns that file). The prompt-level
30
+ * journal here is the shippable first cut; the tool-layer enforcement is the
31
+ * stronger guarantee and must wait until CHARLIE's loop edits land. When wiring
32
+ * it, key off `classifyToolCallJournal(...).completed` and short-circuit a
33
+ * re-dispatched write tool whose (tool name + input + order) matches a
34
+ * completed entry, returning the journaled result instead of executing.
35
+ */
36
+ /** Max length of an input signature included in a journal key (debug-readable). */
37
+ const INPUT_SIGNATURE_MAX_CHARS = 120;
38
+ /** Max length of a per-tool-call result summary surfaced in the resume note. */
39
+ const RESULT_SUMMARY_MAX_CHARS = 400;
40
+ function inputSignature(input) {
41
+ if (!input)
42
+ return "";
43
+ let sig;
44
+ try {
45
+ // Stable key order so the same logical input produces the same signature
46
+ // regardless of how the engine serialized the object.
47
+ const sorted = Object.keys(input)
48
+ .sort()
49
+ .reduce((acc, k) => {
50
+ acc[k] = input[k];
51
+ return acc;
52
+ }, {});
53
+ sig = JSON.stringify(sorted);
54
+ }
55
+ catch {
56
+ sig = String(input);
57
+ }
58
+ return sig.length > INPUT_SIGNATURE_MAX_CHARS
59
+ ? sig.slice(0, INPUT_SIGNATURE_MAX_CHARS)
60
+ : sig;
61
+ }
62
+ /**
63
+ * Classify a single turn's recorded events into completed vs interrupted tool
64
+ * calls. Pure and side-effect free — given the same events it always returns
65
+ * the same journal. A `clear` event resets the per-turn tally exactly as the
66
+ * thread rebuild does, so partial streamed output that was discarded on resume
67
+ * doesn't leave phantom open tool calls.
68
+ */
69
+ export function classifyToolCallJournal(events) {
70
+ // Open tool_start entries awaiting a matching tool_done, in FIFO order. We
71
+ // index by tool name so a tool_done matches the OLDEST open start for that
72
+ // same tool — the dispatch loop always emits start-then-done per call, so the
73
+ // first unmatched start of a given name is the one this done belongs to.
74
+ const openByTool = new Map();
75
+ const completed = [];
76
+ let order = 0;
77
+ for (const event of events) {
78
+ if (event.type === "clear") {
79
+ // Discarded partial output: drop any not-yet-completed starts so they
80
+ // aren't reported as interrupted. Already-completed entries stay.
81
+ openByTool.clear();
82
+ continue;
83
+ }
84
+ if (event.type === "tool_start") {
85
+ const tool = event.tool ?? "unknown";
86
+ const input = (event.input ?? undefined);
87
+ const entry = {
88
+ key: `${tool}#${order}:${inputSignature(input)}`,
89
+ tool,
90
+ ...(input ? { input } : {}),
91
+ order,
92
+ };
93
+ order += 1;
94
+ const queue = openByTool.get(tool);
95
+ if (queue)
96
+ queue.push(entry);
97
+ else
98
+ openByTool.set(tool, [entry]);
99
+ continue;
100
+ }
101
+ if (event.type === "tool_done") {
102
+ const tool = event.tool ?? "unknown";
103
+ const queue = openByTool.get(tool);
104
+ const entry = queue?.shift();
105
+ if (entry) {
106
+ entry.result = event.result ?? "";
107
+ completed.push(entry);
108
+ }
109
+ // A tool_done with no open start is ignored — it can't be re-associated
110
+ // and re-reporting a duplicate done would be noise.
111
+ continue;
112
+ }
113
+ }
114
+ // Anything still open never received a tool_done → interrupted / unknown.
115
+ const interrupted = [];
116
+ for (const queue of openByTool.values()) {
117
+ for (const entry of queue)
118
+ interrupted.push(entry);
119
+ }
120
+ interrupted.sort((a, b) => a.order - b.order);
121
+ return { completed, interrupted };
122
+ }
123
+ /** True when the journal has nothing worth telling a resuming model about. */
124
+ export function isJournalEmpty(journal) {
125
+ return journal.completed.length === 0 && journal.interrupted.length === 0;
126
+ }
127
+ /**
128
+ * Find a COMPLETED journal entry that matches a tool call about to be
129
+ * dispatched, by tool name + input signature (position-independent — a resumed
130
+ * call may sit at a different order than the original). Used by the tool-layer
131
+ * hard-block in production-agent.ts/runToolCall to skip re-executing a side
132
+ * effect that already completed in a prior interrupted chunk: when this returns
133
+ * an entry, the loop returns `entry.result` instead of running the action.
134
+ *
135
+ * Returns the FIRST unmatched completed entry for that (name + input); the
136
+ * caller is expected to claim it (mark it consumed) so two identical fresh
137
+ * calls in the same turn don't both short-circuit on one journaled completion.
138
+ * Returns undefined when there is no completed entry for this exact call —
139
+ * including every fresh call, which must execute normally.
140
+ */
141
+ export function findCompletedJournalEntry(journal, toolName, input, consumedKeys) {
142
+ const wantSig = inputSignature(normalizeInputForSignature(input));
143
+ for (const entry of journal.completed) {
144
+ if (entry.tool !== toolName)
145
+ continue;
146
+ if (inputSignature(entry.input) !== wantSig)
147
+ continue;
148
+ if (consumedKeys?.has(entry.key))
149
+ continue;
150
+ consumedKeys?.add(entry.key);
151
+ return entry;
152
+ }
153
+ return undefined;
154
+ }
155
+ /**
156
+ * Coerce an arbitrary tool input into the `Record<string, string>` shape the
157
+ * journal recorded at `tool_start` so signatures compare apples-to-apples. The
158
+ * ledger stores `tool_start.input` as a string map; the live call's `input` is
159
+ * the parsed object — both pass through `inputSignature`, which sorts keys and
160
+ * JSON-stringifies, so a plain object compares correctly.
161
+ */
162
+ function normalizeInputForSignature(input) {
163
+ if (input == null || typeof input !== "object")
164
+ return undefined;
165
+ return input;
166
+ }
167
+ function summarizeResult(result) {
168
+ if (!result)
169
+ return "(no result recorded)";
170
+ const oneLine = result.replace(/\s+/g, " ").trim();
171
+ if (oneLine.length === 0)
172
+ return "(empty result)";
173
+ return oneLine.length > RESULT_SUMMARY_MAX_CHARS
174
+ ? oneLine.slice(0, RESULT_SUMMARY_MAX_CHARS) + "…"
175
+ : oneLine;
176
+ }
177
+ function describeInput(input) {
178
+ if (!input)
179
+ return "";
180
+ const sig = inputSignature(input);
181
+ return sig && sig !== "{}" ? ` input: ${sig}` : "";
182
+ }
183
+ /**
184
+ * Build the structured resume note injected on auto-continue. Returns `null`
185
+ * when there are no completed or interrupted tool calls to report, so the
186
+ * caller can preserve the exact pre-existing "continue from where you left off"
187
+ * behavior on normal resumes (no regression for turns with no tool activity).
188
+ *
189
+ * The note is intentionally a flat, model-readable block: a list of already-run
190
+ * tool calls (with short results) the model must NOT re-run, and a separate list
191
+ * of interrupted calls whose outcome is unknown for the model to decide on.
192
+ */
193
+ export function buildResumeJournalNote(journal) {
194
+ if (isJournalEmpty(journal))
195
+ return null;
196
+ const lines = [];
197
+ lines.push("Tool-call journal from the interrupted attempt (derived from the durable run ledger):");
198
+ if (journal.completed.length > 0) {
199
+ lines.push("");
200
+ lines.push("Already completed (do NOT re-run these — their side effects already happened; reuse the results below):");
201
+ for (const entry of journal.completed) {
202
+ lines.push(`- ${entry.tool}${describeInput(entry.input)} → ${summarizeResult(entry.result)}`);
203
+ }
204
+ }
205
+ if (journal.interrupted.length > 0) {
206
+ lines.push("");
207
+ lines.push("Interrupted / unknown outcome (these started but no result was recorded before the cut-off — do not assume they succeeded OR failed; if re-running could duplicate a side effect, verify state first):");
208
+ for (const entry of journal.interrupted) {
209
+ lines.push(`- ${entry.tool}${describeInput(entry.input)} → (no result recorded)`);
210
+ }
211
+ }
212
+ return lines.join("\n");
213
+ }
214
+ //# sourceMappingURL=tool-call-journal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-call-journal.js","sourceRoot":"","sources":["../../src/agent/tool-call-journal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAkCH,mFAAmF;AACnF,MAAM,yBAAyB,GAAG,GAAG,CAAC;AAEtC,gFAAgF;AAChF,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAErC,SAAS,cAAc,CAAC,KAAyC;IAC/D,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,yEAAyE;QACzE,sDAAsD;QACtD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;aAC9B,IAAI,EAAE;aACN,MAAM,CAAyB,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;YACzC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAClB,OAAO,GAAG,CAAC;QACb,CAAC,EAAE,EAAE,CAAC,CAAC;QACT,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,GAAG,yBAAyB;QAC3C,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,yBAAyB,CAAC;QACzC,CAAC,CAAC,GAAG,CAAC;AACV,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CACrC,MAAiC;IAEjC,2EAA2E;IAC3E,2EAA2E;IAC3E,8EAA8E;IAC9E,yEAAyE;IACzE,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkC,CAAC;IAC7D,MAAM,SAAS,GAA2B,EAAE,CAAC;IAC7C,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3B,sEAAsE;YACtE,kEAAkE;YAClE,UAAU,CAAC,KAAK,EAAE,CAAC;YACnB,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,SAAS,CAAC;YACrC,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,SAAS,CAE1B,CAAC;YACd,MAAM,KAAK,GAAyB;gBAClC,GAAG,EAAE,GAAG,IAAI,IAAI,KAAK,IAAI,cAAc,CAAC,KAAK,CAAC,EAAE;gBAChD,IAAI;gBACJ,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3B,KAAK;aACN,CAAC;YACF,KAAK,IAAI,CAAC,CAAC;YACX,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACnC,IAAI,KAAK;gBAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;;gBACxB,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;YACnC,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAC/B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,SAAS,CAAC;YACrC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACnC,MAAM,KAAK,GAAG,KAAK,EAAE,KAAK,EAAE,CAAC;YAC7B,IAAI,KAAK,EAAE,CAAC;gBACV,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC;gBAClC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACxB,CAAC;YACD,wEAAwE;YACxE,oDAAoD;YACpD,SAAS;QACX,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,MAAM,WAAW,GAA2B,EAAE,CAAC;IAC/C,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;QACxC,KAAK,MAAM,KAAK,IAAI,KAAK;YAAE,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrD,CAAC;IACD,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAE9C,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC;AACpC,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,cAAc,CAAC,OAAwB;IACrD,OAAO,OAAO,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC;AAC5E,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,yBAAyB,CACvC,OAAwB,EACxB,QAAgB,EAChB,KAAc,EACd,YAA0B;IAE1B,MAAM,OAAO,GAAG,cAAc,CAAC,0BAA0B,CAAC,KAAK,CAAC,CAAC,CAAC;IAClE,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;YAAE,SAAS;QACtC,IAAI,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,OAAO;YAAE,SAAS;QACtD,IAAI,YAAY,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;YAAE,SAAS;QAC3C,YAAY,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,0BAA0B,CACjC,KAAc;IAEd,IAAI,KAAK,IAAI,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IACjE,OAAO,KAA+B,CAAC;AACzC,CAAC;AAED,SAAS,eAAe,CAAC,MAA0B;IACjD,IAAI,CAAC,MAAM;QAAE,OAAO,sBAAsB,CAAC;IAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACnD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,gBAAgB,CAAC;IAClD,OAAO,OAAO,CAAC,MAAM,GAAG,wBAAwB;QAC9C,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,wBAAwB,CAAC,GAAG,GAAG;QAClD,CAAC,CAAC,OAAO,CAAC;AACd,CAAC;AAED,SAAS,aAAa,CAAC,KAAyC;IAC9D,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,MAAM,GAAG,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IAClC,OAAO,GAAG,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACrD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAAwB;IAExB,IAAI,cAAc,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CACR,uFAAuF,CACxF,CAAC;IAEF,IAAI,OAAO,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CACR,yGAAyG,CAC1G,CAAC;QACF,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YACtC,KAAK,CAAC,IAAI,CACR,KAAK,KAAK,CAAC,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAClF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CACR,wMAAwM,CACzM,CAAC;QACF,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACxC,KAAK,CAAC,IAAI,CACR,KAAK,KAAK,CAAC,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,yBAAyB,CACtE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC","sourcesContent":["/**\n * Per-turn tool-call journal — derived (not separately recorded) from the\n * existing run-event ledger. Borrowed from Flue's durable-execution journal:\n * when an agent run resumes after an interruption (gateway/transport drop, cold\n * start, soft-timeout auto-continue), we classify the tool calls already in the\n * ledger so the resumed model does NOT re-execute side effects it already\n * completed (re-sending an email, re-creating a ticket) and so it is explicitly\n * told about any tool call that started but whose outcome was never recorded.\n *\n * IMPORTANT — this is a pure read-over-the-ledger view. There is no new\n * recording hook anywhere in the hot path. The classification reuses the exact\n * positional `tool_start` → `tool_done` matching that `thread-data-builder.ts`\n * already relies on to rebuild durable turns:\n *\n * - `tool_start` events carry `{ tool, input }` (no tool-call id at this\n * layer; the ledger event stream omits it).\n * - `tool_done` events carry `{ tool, result }`.\n * - A `tool_done` is matched to the OLDEST still-open `tool_start` for the\n * same tool name (FIFO per tool), mirroring how the dispatch loop emits a\n * start immediately before its matching done.\n *\n * A `tool_start` with no matching `tool_done` is the dangerous case: the call\n * began, its side effect may or may not have landed, and the interruption ate\n * the result. We surface those as \"interrupted / unknown outcome\" so the model\n * decides rather than blindly re-running.\n *\n * TODO(charlie-merge): optional hard-block — refuse re-execution of\n * journaled-complete tool calls at the tool layer in\n * production-agent.ts/runToolCall (CHARLIE owns that file). The prompt-level\n * journal here is the shippable first cut; the tool-layer enforcement is the\n * stronger guarantee and must wait until CHARLIE's loop edits land. When wiring\n * it, key off `classifyToolCallJournal(...).completed` and short-circuit a\n * re-dispatched write tool whose (tool name + input + order) matches a\n * completed entry, returning the journaled result instead of executing.\n */\n\nimport type { AgentChatEvent } from \"./types.js\";\n\n/** A single recorded tool-call ledger entry, classified by outcome. */\nexport interface ToolCallJournalEntry {\n /**\n * Stable-ish identity for this tool call within the turn. The ledger event\n * stream has no tool-call id, so we key by tool name + a short input\n * signature + positional order, exactly enough to disambiguate repeats of the\n * same tool within one turn for human/model-readable reporting.\n */\n key: string;\n /** Tool / action name (from the `tool_start` event). */\n tool: string;\n /** Tool input captured at `tool_start`, if any. */\n input?: Record<string, string>;\n /** 0-based position of the `tool_start` among all tool calls in the turn. */\n order: number;\n /** Result text from the matched `tool_done`, when the call completed. */\n result?: string;\n}\n\n/** Result of classifying one turn's ledger events. */\nexport interface ToolCallJournal {\n /** Tool calls with a matching `tool_done` — already ran, do NOT re-run. */\n completed: ToolCallJournalEntry[];\n /**\n * Tool calls with a `tool_start` but no matching `tool_done` — interrupted,\n * outcome unknown. The model must decide whether re-running is safe.\n */\n interrupted: ToolCallJournalEntry[];\n}\n\n/** Max length of an input signature included in a journal key (debug-readable). */\nconst INPUT_SIGNATURE_MAX_CHARS = 120;\n\n/** Max length of a per-tool-call result summary surfaced in the resume note. */\nconst RESULT_SUMMARY_MAX_CHARS = 400;\n\nfunction inputSignature(input: Record<string, string> | undefined): string {\n if (!input) return \"\";\n let sig: string;\n try {\n // Stable key order so the same logical input produces the same signature\n // regardless of how the engine serialized the object.\n const sorted = Object.keys(input)\n .sort()\n .reduce<Record<string, string>>((acc, k) => {\n acc[k] = input[k];\n return acc;\n }, {});\n sig = JSON.stringify(sorted);\n } catch {\n sig = String(input);\n }\n return sig.length > INPUT_SIGNATURE_MAX_CHARS\n ? sig.slice(0, INPUT_SIGNATURE_MAX_CHARS)\n : sig;\n}\n\n/**\n * Classify a single turn's recorded events into completed vs interrupted tool\n * calls. Pure and side-effect free — given the same events it always returns\n * the same journal. A `clear` event resets the per-turn tally exactly as the\n * thread rebuild does, so partial streamed output that was discarded on resume\n * doesn't leave phantom open tool calls.\n */\nexport function classifyToolCallJournal(\n events: readonly AgentChatEvent[],\n): ToolCallJournal {\n // Open tool_start entries awaiting a matching tool_done, in FIFO order. We\n // index by tool name so a tool_done matches the OLDEST open start for that\n // same tool — the dispatch loop always emits start-then-done per call, so the\n // first unmatched start of a given name is the one this done belongs to.\n const openByTool = new Map<string, ToolCallJournalEntry[]>();\n const completed: ToolCallJournalEntry[] = [];\n let order = 0;\n\n for (const event of events) {\n if (event.type === \"clear\") {\n // Discarded partial output: drop any not-yet-completed starts so they\n // aren't reported as interrupted. Already-completed entries stay.\n openByTool.clear();\n continue;\n }\n\n if (event.type === \"tool_start\") {\n const tool = event.tool ?? \"unknown\";\n const input = (event.input ?? undefined) as\n | Record<string, string>\n | undefined;\n const entry: ToolCallJournalEntry = {\n key: `${tool}#${order}:${inputSignature(input)}`,\n tool,\n ...(input ? { input } : {}),\n order,\n };\n order += 1;\n const queue = openByTool.get(tool);\n if (queue) queue.push(entry);\n else openByTool.set(tool, [entry]);\n continue;\n }\n\n if (event.type === \"tool_done\") {\n const tool = event.tool ?? \"unknown\";\n const queue = openByTool.get(tool);\n const entry = queue?.shift();\n if (entry) {\n entry.result = event.result ?? \"\";\n completed.push(entry);\n }\n // A tool_done with no open start is ignored — it can't be re-associated\n // and re-reporting a duplicate done would be noise.\n continue;\n }\n }\n\n // Anything still open never received a tool_done → interrupted / unknown.\n const interrupted: ToolCallJournalEntry[] = [];\n for (const queue of openByTool.values()) {\n for (const entry of queue) interrupted.push(entry);\n }\n interrupted.sort((a, b) => a.order - b.order);\n\n return { completed, interrupted };\n}\n\n/** True when the journal has nothing worth telling a resuming model about. */\nexport function isJournalEmpty(journal: ToolCallJournal): boolean {\n return journal.completed.length === 0 && journal.interrupted.length === 0;\n}\n\n/**\n * Find a COMPLETED journal entry that matches a tool call about to be\n * dispatched, by tool name + input signature (position-independent — a resumed\n * call may sit at a different order than the original). Used by the tool-layer\n * hard-block in production-agent.ts/runToolCall to skip re-executing a side\n * effect that already completed in a prior interrupted chunk: when this returns\n * an entry, the loop returns `entry.result` instead of running the action.\n *\n * Returns the FIRST unmatched completed entry for that (name + input); the\n * caller is expected to claim it (mark it consumed) so two identical fresh\n * calls in the same turn don't both short-circuit on one journaled completion.\n * Returns undefined when there is no completed entry for this exact call —\n * including every fresh call, which must execute normally.\n */\nexport function findCompletedJournalEntry(\n journal: ToolCallJournal,\n toolName: string,\n input: unknown,\n consumedKeys?: Set<string>,\n): ToolCallJournalEntry | undefined {\n const wantSig = inputSignature(normalizeInputForSignature(input));\n for (const entry of journal.completed) {\n if (entry.tool !== toolName) continue;\n if (inputSignature(entry.input) !== wantSig) continue;\n if (consumedKeys?.has(entry.key)) continue;\n consumedKeys?.add(entry.key);\n return entry;\n }\n return undefined;\n}\n\n/**\n * Coerce an arbitrary tool input into the `Record<string, string>` shape the\n * journal recorded at `tool_start` so signatures compare apples-to-apples. The\n * ledger stores `tool_start.input` as a string map; the live call's `input` is\n * the parsed object — both pass through `inputSignature`, which sorts keys and\n * JSON-stringifies, so a plain object compares correctly.\n */\nfunction normalizeInputForSignature(\n input: unknown,\n): Record<string, string> | undefined {\n if (input == null || typeof input !== \"object\") return undefined;\n return input as Record<string, string>;\n}\n\nfunction summarizeResult(result: string | undefined): string {\n if (!result) return \"(no result recorded)\";\n const oneLine = result.replace(/\\s+/g, \" \").trim();\n if (oneLine.length === 0) return \"(empty result)\";\n return oneLine.length > RESULT_SUMMARY_MAX_CHARS\n ? oneLine.slice(0, RESULT_SUMMARY_MAX_CHARS) + \"…\"\n : oneLine;\n}\n\nfunction describeInput(input: Record<string, string> | undefined): string {\n if (!input) return \"\";\n const sig = inputSignature(input);\n return sig && sig !== \"{}\" ? ` input: ${sig}` : \"\";\n}\n\n/**\n * Build the structured resume note injected on auto-continue. Returns `null`\n * when there are no completed or interrupted tool calls to report, so the\n * caller can preserve the exact pre-existing \"continue from where you left off\"\n * behavior on normal resumes (no regression for turns with no tool activity).\n *\n * The note is intentionally a flat, model-readable block: a list of already-run\n * tool calls (with short results) the model must NOT re-run, and a separate list\n * of interrupted calls whose outcome is unknown for the model to decide on.\n */\nexport function buildResumeJournalNote(\n journal: ToolCallJournal,\n): string | null {\n if (isJournalEmpty(journal)) return null;\n\n const lines: string[] = [];\n lines.push(\n \"Tool-call journal from the interrupted attempt (derived from the durable run ledger):\",\n );\n\n if (journal.completed.length > 0) {\n lines.push(\"\");\n lines.push(\n \"Already completed (do NOT re-run these — their side effects already happened; reuse the results below):\",\n );\n for (const entry of journal.completed) {\n lines.push(\n `- ${entry.tool}${describeInput(entry.input)} → ${summarizeResult(entry.result)}`,\n );\n }\n }\n\n if (journal.interrupted.length > 0) {\n lines.push(\"\");\n lines.push(\n \"Interrupted / unknown outcome (these started but no result was recorded before the cut-off — do not assume they succeeded OR failed; if re-running could duplicate a side effect, verify state first):\",\n );\n for (const entry of journal.interrupted) {\n lines.push(\n `- ${entry.tool}${describeInput(entry.input)} → (no result recorded)`,\n );\n }\n }\n\n return lines.join(\"\\n\");\n}\n"]}
@@ -121,6 +121,16 @@ export interface AgentChatRequest {
121
121
  scope?: AgentChatScope | null;
122
122
  /** When true, expose this chat turn as a user-visible run in RunsTray. */
123
123
  trackInRunsTray?: boolean;
124
+ /**
125
+ * Approval grants for human-in-the-loop actions. Each entry is a stable
126
+ * approval key (see the `approval_required` event's `approvalKey`). When the
127
+ * agent calls an action declared `needsApproval`, the loop pauses and emits
128
+ * `approval_required`; the client re-issues the turn (typically an empty
129
+ * continuation) with the approved call's key here so the gate lets it run.
130
+ * Keys not present here keep the action paused. The model never sees or sets
131
+ * this — it is supplied by the human's approve affordance.
132
+ */
133
+ approvedToolCalls?: string[];
124
134
  }
125
135
  export type AgentChatEvent = {
126
136
  type: "text";
@@ -141,6 +151,20 @@ export type AgentChatEvent = {
141
151
  tool: string;
142
152
  result: string;
143
153
  mcpApp?: AgentMcpAppPayload;
154
+ } | {
155
+ /**
156
+ * The agent tried to call an action declared `needsApproval` and the loop
157
+ * paused instead of executing it. The client should surface an
158
+ * approve/deny affordance; on approve, re-issue the turn with
159
+ * `approvedToolCalls: [approvalKey]` so the gate lets this call run.
160
+ */
161
+ type: "approval_required";
162
+ tool: string;
163
+ input: Record<string, string>;
164
+ /** Stable key the client echoes back in `approvedToolCalls` to approve. */
165
+ approvalKey: string;
166
+ /** The model-side tool-call id for this paused call, when available. */
167
+ toolCallId?: string;
144
168
  } | {
145
169
  type: "agent_call";
146
170
  agent: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agent/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agent/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAChB,MAAM,EACN;YACE,IAAI,EAAE,MAAM,CAAC;YACb,WAAW,CAAC,EAAE,MAAM,CAAC;YACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;SACjB,CACF,CAAC;QACF,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CACH;AAED,2CAA2C;AAC3C,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC;AAEpC,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,8BAA8B,GACtC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IACE,IAAI,EAAE,WAAW,CAAC;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,GACD;IACE,IAAI,EAAE,aAAa,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEN,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,8BAA8B,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,cAAc,CAAC;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,CACN,KAAK,EAAE,MAAM;IACb,4EAA4E;IAC5E,KAAK,CAAC,EAAE,GAAG,KACR,mBAAmB,EAAE,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;CAC7D;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,0BAA0B,EAAE,CAAC;IACjD,UAAU,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACpC,iFAAiF;IACjF,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uFAAuF;IACvF,IAAI,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACtB,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,sFAAsF;IACtF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0FAA0F;IAC1F,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qFAAqF;IACrF,KAAK,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAC9B,0EAA0E;IAC1E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;;;OAQG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GACnE;IACE,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,kBAAkB,CAAC;CAC7B,GACD;IACE;;;;;OAKG;IACH,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GACD;IACE,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;CACpC,GACD;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACxD;IACE,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;CAC7C,GACD;IACE,IAAI,EAAE,mBAAmB,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GACD;IACE,IAAI,EAAE,qBAAqB,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,GACD;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IACE,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AACH;;;GAGG;GACD;IAAE,IAAI,EAAE,iBAAiB,CAAA;CAAE,GAC3B;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9C;IACE,IAAI,EAAE,eAAe,CAAC;IACtB,MAAM,EACF,aAAa,GACb,YAAY,GACZ,aAAa,GACb,cAAc,GACd,iBAAiB,GACjB,qBAAqB,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GACD;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtB,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,cAAc,CAAC;CACvB;AAED,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/agent/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ReasoningEffort } from \"../shared/reasoning-effort.js\";\nimport type { AgentMcpAppPayload } from \"../mcp-client/app-result.js\";\n\nexport interface ActionTool {\n description: string;\n parameters?: {\n type: \"object\";\n properties: Record<\n string,\n {\n type: string;\n description?: string;\n enum?: string[];\n }\n >;\n required?: string[];\n };\n}\n\n/** @deprecated Use `ActionTool` instead */\nexport type ScriptTool = ActionTool;\n\nexport interface AgentMessage {\n role: \"user\" | \"assistant\";\n content: string;\n}\n\nexport type AgentChatStructuredContentPart =\n | { type: \"text\"; text: string }\n | {\n type: \"tool-call\";\n id?: string;\n toolCallId?: string;\n name?: string;\n toolName?: string;\n input?: unknown;\n args?: unknown;\n }\n | {\n type: \"tool-result\";\n toolCallId: string;\n /** Persisted for replay; omitted in older rows is backfilled server-side. */\n toolName?: string;\n toolInput?: string;\n content: string;\n isError?: boolean;\n };\n\nexport interface AgentChatStructuredMessage {\n role: \"user\" | \"assistant\";\n content: AgentChatStructuredContentPart[];\n}\n\nexport interface AgentChatReference {\n type: \"file\" | \"skill\" | \"mention\" | \"agent\" | \"custom-agent\";\n path: string;\n name: string;\n source: string;\n refType?: string;\n refId?: string;\n}\n\nexport interface MentionProviderItem {\n id: string;\n label: string;\n description?: string;\n icon?: string;\n refType: string;\n refId?: string;\n refPath?: string;\n}\n\nexport interface MentionProvider {\n label: string;\n icon?: string;\n search: (\n query: string,\n /** The H3 event for the current request — use to make internal API calls */\n event?: any,\n ) => MentionProviderItem[] | Promise<MentionProviderItem[]>;\n}\n\nexport interface AgentChatAttachment {\n type: string;\n name: string;\n data?: string;\n contentType?: string;\n text?: string;\n}\n\nexport interface AgentChatScope {\n type: string;\n id: string;\n label?: string;\n}\n\nexport interface AgentChatRequest {\n message: string;\n /**\n * User-visible text to persist in chat history. `message` may be normalized\n * for the model (for example mention markup or internal continuation text).\n */\n displayMessage?: string;\n history?: AgentMessage[];\n /**\n * Provider-neutral transcript used for run recovery. Unlike `history`,\n * this preserves assistant tool calls and matching tool results so\n * continuation turns do not re-run completed read-only tools.\n */\n structuredHistory?: AgentChatStructuredMessage[];\n references?: AgentChatReference[];\n threadId?: string;\n attachments?: AgentChatAttachment[];\n /** Internal retry/continuation requests should not create visible user turns. */\n internalContinuation?: boolean;\n /**\n * Stable identity for the logical assistant turn this request belongs to.\n * The client sends the SAME turnId for the initial POST and every\n * auto-continuation re-POST of one turn, so the server can fold each\n * continuation run's output onto a single durable assistant message instead\n * of dropping the earlier chunks. Defaults to the run id when absent.\n */\n turnId?: string;\n /** Execution mode for this turn. Plan mode is read-only and proposes before acting. */\n mode?: \"act\" | \"plan\";\n /** Per-request model override (ephemeral, from the composer model picker). */\n model?: string;\n /** Per-request engine override (sent alongside model for cross-provider switches). */\n engine?: string;\n /** Per-request reasoning effort override (ephemeral, from the composer picker). */\n effort?: ReasoningEffort;\n /** Usage-tracking label for this call (e.g. \"chat\", \"summarize\"). Default: \"chat\". */\n usageLabel?: string;\n /** Stable browser tab id so screen/url context and navigation commands are tab-scoped. */\n browserTabId?: string;\n /** Resource scope for this chat thread, e.g. the deck currently bound to the tab. */\n scope?: AgentChatScope | null;\n /** When true, expose this chat turn as a user-visible run in RunsTray. */\n trackInRunsTray?: boolean;\n}\n\nexport type AgentChatEvent =\n | { type: \"text\"; text: string }\n | { type: \"thinking\"; text: string }\n | { type: \"activity\"; label: string; tool?: string }\n | { type: \"tool_start\"; tool: string; input: Record<string, string> }\n | {\n type: \"tool_done\";\n tool: string;\n result: string;\n mcpApp?: AgentMcpAppPayload;\n }\n | {\n type: \"agent_call\";\n agent: string;\n status: \"start\" | \"done\" | \"error\";\n }\n | { type: \"agent_call_text\"; agent: string; text: string }\n | {\n type: \"agent_task\";\n taskId: string;\n threadId: string;\n description: string;\n status: \"running\" | \"completed\" | \"errored\";\n }\n | {\n type: \"agent_task_update\";\n taskId: string;\n preview: string;\n currentStep?: string;\n }\n | {\n type: \"agent_task_complete\";\n taskId: string;\n summary: string;\n }\n | { type: \"done\" }\n | {\n type: \"error\";\n error: string;\n /**\n * Optional machine-readable error code. Builder gateway uses codes\n * like \"credits-limit-monthly\" / \"unauthorized\" / \"gateway_not_enabled\"\n * so the chat UI can render a structured CTA (e.g. upgrade button).\n */\n errorCode?: string;\n /** Optional link paired with errorCode — e.g. Builder billing page. */\n upgradeUrl?: string;\n /** Optional details for expandable UI/debugging. */\n details?: string;\n /** True when the user can reasonably continue/retry from partial work. */\n recoverable?: boolean;\n }\n /**\n * Legacy SSE terminal event. New streams emit\n * `{ type: \"error\", errorCode: \"missing_credentials\" }` instead.\n */\n | { type: \"missing_api_key\" }\n | { type: \"loop_limit\"; maxIterations?: number }\n | {\n type: \"auto_continue\";\n reason:\n | \"run_timeout\"\n | \"loop_limit\"\n | \"no_progress\"\n | \"stream_ended\"\n | \"gateway_timeout\"\n | \"network_interrupted\";\n maxIterations?: number;\n }\n | { type: \"clear\" };\n\nexport interface RunEvent {\n seq: number;\n event: AgentChatEvent;\n}\n\nexport type RunStatus = \"running\" | \"completed\" | \"errored\" | \"aborted\";\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/agent/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ReasoningEffort } from \"../shared/reasoning-effort.js\";\nimport type { AgentMcpAppPayload } from \"../mcp-client/app-result.js\";\n\nexport interface ActionTool {\n description: string;\n parameters?: {\n type: \"object\";\n properties: Record<\n string,\n {\n type: string;\n description?: string;\n enum?: string[];\n }\n >;\n required?: string[];\n };\n}\n\n/** @deprecated Use `ActionTool` instead */\nexport type ScriptTool = ActionTool;\n\nexport interface AgentMessage {\n role: \"user\" | \"assistant\";\n content: string;\n}\n\nexport type AgentChatStructuredContentPart =\n | { type: \"text\"; text: string }\n | {\n type: \"tool-call\";\n id?: string;\n toolCallId?: string;\n name?: string;\n toolName?: string;\n input?: unknown;\n args?: unknown;\n }\n | {\n type: \"tool-result\";\n toolCallId: string;\n /** Persisted for replay; omitted in older rows is backfilled server-side. */\n toolName?: string;\n toolInput?: string;\n content: string;\n isError?: boolean;\n };\n\nexport interface AgentChatStructuredMessage {\n role: \"user\" | \"assistant\";\n content: AgentChatStructuredContentPart[];\n}\n\nexport interface AgentChatReference {\n type: \"file\" | \"skill\" | \"mention\" | \"agent\" | \"custom-agent\";\n path: string;\n name: string;\n source: string;\n refType?: string;\n refId?: string;\n}\n\nexport interface MentionProviderItem {\n id: string;\n label: string;\n description?: string;\n icon?: string;\n refType: string;\n refId?: string;\n refPath?: string;\n}\n\nexport interface MentionProvider {\n label: string;\n icon?: string;\n search: (\n query: string,\n /** The H3 event for the current request — use to make internal API calls */\n event?: any,\n ) => MentionProviderItem[] | Promise<MentionProviderItem[]>;\n}\n\nexport interface AgentChatAttachment {\n type: string;\n name: string;\n data?: string;\n contentType?: string;\n text?: string;\n}\n\nexport interface AgentChatScope {\n type: string;\n id: string;\n label?: string;\n}\n\nexport interface AgentChatRequest {\n message: string;\n /**\n * User-visible text to persist in chat history. `message` may be normalized\n * for the model (for example mention markup or internal continuation text).\n */\n displayMessage?: string;\n history?: AgentMessage[];\n /**\n * Provider-neutral transcript used for run recovery. Unlike `history`,\n * this preserves assistant tool calls and matching tool results so\n * continuation turns do not re-run completed read-only tools.\n */\n structuredHistory?: AgentChatStructuredMessage[];\n references?: AgentChatReference[];\n threadId?: string;\n attachments?: AgentChatAttachment[];\n /** Internal retry/continuation requests should not create visible user turns. */\n internalContinuation?: boolean;\n /**\n * Stable identity for the logical assistant turn this request belongs to.\n * The client sends the SAME turnId for the initial POST and every\n * auto-continuation re-POST of one turn, so the server can fold each\n * continuation run's output onto a single durable assistant message instead\n * of dropping the earlier chunks. Defaults to the run id when absent.\n */\n turnId?: string;\n /** Execution mode for this turn. Plan mode is read-only and proposes before acting. */\n mode?: \"act\" | \"plan\";\n /** Per-request model override (ephemeral, from the composer model picker). */\n model?: string;\n /** Per-request engine override (sent alongside model for cross-provider switches). */\n engine?: string;\n /** Per-request reasoning effort override (ephemeral, from the composer picker). */\n effort?: ReasoningEffort;\n /** Usage-tracking label for this call (e.g. \"chat\", \"summarize\"). Default: \"chat\". */\n usageLabel?: string;\n /** Stable browser tab id so screen/url context and navigation commands are tab-scoped. */\n browserTabId?: string;\n /** Resource scope for this chat thread, e.g. the deck currently bound to the tab. */\n scope?: AgentChatScope | null;\n /** When true, expose this chat turn as a user-visible run in RunsTray. */\n trackInRunsTray?: boolean;\n /**\n * Approval grants for human-in-the-loop actions. Each entry is a stable\n * approval key (see the `approval_required` event's `approvalKey`). When the\n * agent calls an action declared `needsApproval`, the loop pauses and emits\n * `approval_required`; the client re-issues the turn (typically an empty\n * continuation) with the approved call's key here so the gate lets it run.\n * Keys not present here keep the action paused. The model never sees or sets\n * this — it is supplied by the human's approve affordance.\n */\n approvedToolCalls?: string[];\n}\n\nexport type AgentChatEvent =\n | { type: \"text\"; text: string }\n | { type: \"thinking\"; text: string }\n | { type: \"activity\"; label: string; tool?: string }\n | { type: \"tool_start\"; tool: string; input: Record<string, string> }\n | {\n type: \"tool_done\";\n tool: string;\n result: string;\n mcpApp?: AgentMcpAppPayload;\n }\n | {\n /**\n * The agent tried to call an action declared `needsApproval` and the loop\n * paused instead of executing it. The client should surface an\n * approve/deny affordance; on approve, re-issue the turn with\n * `approvedToolCalls: [approvalKey]` so the gate lets this call run.\n */\n type: \"approval_required\";\n tool: string;\n input: Record<string, string>;\n /** Stable key the client echoes back in `approvedToolCalls` to approve. */\n approvalKey: string;\n /** The model-side tool-call id for this paused call, when available. */\n toolCallId?: string;\n }\n | {\n type: \"agent_call\";\n agent: string;\n status: \"start\" | \"done\" | \"error\";\n }\n | { type: \"agent_call_text\"; agent: string; text: string }\n | {\n type: \"agent_task\";\n taskId: string;\n threadId: string;\n description: string;\n status: \"running\" | \"completed\" | \"errored\";\n }\n | {\n type: \"agent_task_update\";\n taskId: string;\n preview: string;\n currentStep?: string;\n }\n | {\n type: \"agent_task_complete\";\n taskId: string;\n summary: string;\n }\n | { type: \"done\" }\n | {\n type: \"error\";\n error: string;\n /**\n * Optional machine-readable error code. Builder gateway uses codes\n * like \"credits-limit-monthly\" / \"unauthorized\" / \"gateway_not_enabled\"\n * so the chat UI can render a structured CTA (e.g. upgrade button).\n */\n errorCode?: string;\n /** Optional link paired with errorCode — e.g. Builder billing page. */\n upgradeUrl?: string;\n /** Optional details for expandable UI/debugging. */\n details?: string;\n /** True when the user can reasonably continue/retry from partial work. */\n recoverable?: boolean;\n }\n /**\n * Legacy SSE terminal event. New streams emit\n * `{ type: \"error\", errorCode: \"missing_credentials\" }` instead.\n */\n | { type: \"missing_api_key\" }\n | { type: \"loop_limit\"; maxIterations?: number }\n | {\n type: \"auto_continue\";\n reason:\n | \"run_timeout\"\n | \"loop_limit\"\n | \"no_progress\"\n | \"stream_ended\"\n | \"gateway_timeout\"\n | \"network_interrupted\";\n maxIterations?: number;\n }\n | { type: \"clear\" };\n\nexport interface RunEvent {\n seq: number;\n event: AgentChatEvent;\n}\n\nexport type RunStatus = \"running\" | \"completed\" | \"errored\" | \"aborted\";\n"]}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * `agent-native add <kind> [name|url]` — the **blueprint installer**.
3
+ *
4
+ * Borrowed from Flue's `flue add`: instead of being a dumb scaffolder that
5
+ * writes files for you, this command emits a curated Markdown *integration
6
+ * blueprint* to stdout. You pipe that blueprint into your own coding agent,
7
+ * which applies the changes against the live repo:
8
+ *
9
+ * agent-native add provider stripe | claude
10
+ * agent-native add channel discord | codex
11
+ *
12
+ * This fits the agent-applies-changes, filesystem-first house style: the
13
+ * framework supplies the recipe (the canonical files to touch, the rules to
14
+ * honor, the verification step), and the coding agent does the editing with
15
+ * full repo context.
16
+ *
17
+ * A bare name resolves a curated blueprint from `blueprints/<kind>/<name>.md`.
18
+ * A URL instead of a name emits a GENERIC "research-and-integrate" blueprint
19
+ * for that kind with the URL embedded as the research starting point (mirrors
20
+ * Flue: a URL is a research seed, not a known recipe).
21
+ *
22
+ * Blueprint `.md` files ship in the published package via the `blueprints`
23
+ * entry in `package.json` `files`, so they live at
24
+ * `node_modules/@agent-native/core/blueprints/**` at runtime. Resolution works
25
+ * both from source (tsx: `src/cli` → `../../blueprints`) and from the compiled
26
+ * package (`dist/cli` → `../../blueprints`), with an upward-walk fallback.
27
+ */
28
+ /** A coarse classification of what `add` resolved for a given invocation. */
29
+ export type AddBlueprintSource = {
30
+ kind: "curated";
31
+ blueprintKind: string;
32
+ name: string;
33
+ path: string;
34
+ } | {
35
+ kind: "generic-url";
36
+ blueprintKind: string;
37
+ url: string;
38
+ };
39
+ export interface ResolvedBlueprint {
40
+ /** The Markdown to print to stdout (piped into a coding agent). */
41
+ markdown: string;
42
+ source: AddBlueprintSource;
43
+ }
44
+ /**
45
+ * Locate the directory that holds the blueprint `.md` recipes.
46
+ *
47
+ * Both `src/cli` (tsx/source) and `dist/cli` (published) sit two levels under
48
+ * the package root, where `blueprints/` lives, so `../../blueprints` from this
49
+ * module's directory is the primary path. We additionally walk upward looking
50
+ * for a `blueprints` directory as a resilience fallback (e.g. unusual bundler
51
+ * layouts). An explicit override is honored for tests.
52
+ */
53
+ export declare function resolveBlueprintsRoot(overrideRoot?: string): string;
54
+ /** True for an argument that should be treated as a research URL, not a name. */
55
+ export declare function looksLikeUrl(value: string): boolean;
56
+ /** List the blueprint kinds (subdirectories) available, sorted. */
57
+ export declare function listKinds(root: string): string[];
58
+ /** List the blueprint names available under a kind, sorted (no `.md`). */
59
+ export declare function listBlueprintNames(root: string, kind: string): string[];
60
+ /** A flat catalog of every kind and its blueprint names. */
61
+ export declare function listCatalog(root: string): Array<{
62
+ kind: string;
63
+ names: string[];
64
+ }>;
65
+ /** Render the `--list` / no-args catalog text. */
66
+ export declare function formatCatalog(root: string): string;
67
+ /**
68
+ * Build the generic "research-and-integrate" blueprint emitted when the user
69
+ * passes a URL instead of a known blueprint name. Mirrors Flue: a URL is a
70
+ * research seed. We keep this self-contained — the coding agent reading it has
71
+ * no other context.
72
+ */
73
+ export declare function buildGenericUrlBlueprint(kind: string, url: string): string;
74
+ /**
75
+ * Resolve a blueprint for a `kind` + optional `name`/`url`.
76
+ *
77
+ * - A known name → the curated `blueprints/<kind>/<name>.md`.
78
+ * - A URL → the generic research-and-integrate blueprint for the kind.
79
+ * - Unknown name → throws `AddResolutionError` listing what's available.
80
+ */
81
+ export declare function resolveBlueprint(opts: {
82
+ kind: string;
83
+ nameOrUrl?: string;
84
+ root: string;
85
+ }): ResolvedBlueprint;
86
+ /** Thrown for an unknown kind/name; the CLI prints the message and exits 1. */
87
+ export declare class AddResolutionError extends Error {
88
+ constructor(message: string);
89
+ }
90
+ interface ParsedAddArgs {
91
+ list: boolean;
92
+ help: boolean;
93
+ /** Accepted as an explicit no-op alias for the default print behavior. */
94
+ print: boolean;
95
+ positionals: string[];
96
+ }
97
+ export declare function parseAddArgs(argv: string[]): ParsedAddArgs;
98
+ /**
99
+ * CLI entry point. Returns the process exit code so the dispatcher / tests can
100
+ * assert on it. Writes the blueprint Markdown to stdout and diagnostics to
101
+ * stderr so `... | claude` only receives the blueprint.
102
+ */
103
+ export declare function runAdd(argv: string[], io?: {
104
+ out?: (s: string) => void;
105
+ err?: (s: string) => void;
106
+ root?: string;
107
+ }): number;
108
+ export {};
109
+ //# sourceMappingURL=add.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/cli/add.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAMH,6EAA6E;AAC7E,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACtE;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAChC,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAkBnE;AAUD,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,mEAAmE;AACnE,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAOhD;AAED,0EAA0E;AAC1E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAQvE;AAED,4DAA4D;AAC5D,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC,CAKD;AAED,kDAAkD;AAClD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA4BlD;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAwD1E;AA+BD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,iBAAiB,CAkDpB;AAeD,+EAA+E;AAC/E,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED,UAAU,aAAa;IACrB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,0EAA0E;IAC1E,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,CAkB1D;AAyBD;;;;GAIG;AACH,wBAAgB,MAAM,CACpB,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,GAAE;IACF,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1B,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;CACV,GACL,MAAM,CAoCR"}