@agent-native/core 0.52.0 → 0.54.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 (267) hide show
  1. package/README.md +41 -95
  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 +64 -1
  7. package/dist/action.d.ts.map +1 -1
  8. package/dist/action.js +73 -2
  9. package/dist/action.js.map +1 -1
  10. package/dist/agent/index.d.ts +1 -0
  11. package/dist/agent/index.d.ts.map +1 -1
  12. package/dist/agent/index.js +1 -0
  13. package/dist/agent/index.js.map +1 -1
  14. package/dist/agent/observational-memory/compactor.d.ts +43 -0
  15. package/dist/agent/observational-memory/compactor.d.ts.map +1 -0
  16. package/dist/agent/observational-memory/compactor.js +50 -0
  17. package/dist/agent/observational-memory/compactor.js.map +1 -0
  18. package/dist/agent/observational-memory/config.d.ts +37 -0
  19. package/dist/agent/observational-memory/config.d.ts.map +1 -0
  20. package/dist/agent/observational-memory/config.js +48 -0
  21. package/dist/agent/observational-memory/config.js.map +1 -0
  22. package/dist/agent/observational-memory/index.d.ts +26 -0
  23. package/dist/agent/observational-memory/index.d.ts.map +1 -0
  24. package/dist/agent/observational-memory/index.js +25 -0
  25. package/dist/agent/observational-memory/index.js.map +1 -0
  26. package/dist/agent/observational-memory/internal-run.d.ts +37 -0
  27. package/dist/agent/observational-memory/internal-run.d.ts.map +1 -0
  28. package/dist/agent/observational-memory/internal-run.js +59 -0
  29. package/dist/agent/observational-memory/internal-run.js.map +1 -0
  30. package/dist/agent/observational-memory/message-text.d.ts +13 -0
  31. package/dist/agent/observational-memory/message-text.d.ts.map +1 -0
  32. package/dist/agent/observational-memory/message-text.js +46 -0
  33. package/dist/agent/observational-memory/message-text.js.map +1 -0
  34. package/dist/agent/observational-memory/migrations.d.ts +13 -0
  35. package/dist/agent/observational-memory/migrations.d.ts.map +1 -0
  36. package/dist/agent/observational-memory/migrations.js +43 -0
  37. package/dist/agent/observational-memory/migrations.js.map +1 -0
  38. package/dist/agent/observational-memory/observer.d.ts +37 -0
  39. package/dist/agent/observational-memory/observer.d.ts.map +1 -0
  40. package/dist/agent/observational-memory/observer.js +82 -0
  41. package/dist/agent/observational-memory/observer.js.map +1 -0
  42. package/dist/agent/observational-memory/plugin.d.ts +16 -0
  43. package/dist/agent/observational-memory/plugin.d.ts.map +1 -0
  44. package/dist/agent/observational-memory/plugin.js +26 -0
  45. package/dist/agent/observational-memory/plugin.js.map +1 -0
  46. package/dist/agent/observational-memory/prompts.d.ts +27 -0
  47. package/dist/agent/observational-memory/prompts.d.ts.map +1 -0
  48. package/dist/agent/observational-memory/prompts.js +42 -0
  49. package/dist/agent/observational-memory/prompts.js.map +1 -0
  50. package/dist/agent/observational-memory/read.d.ts +45 -0
  51. package/dist/agent/observational-memory/read.d.ts.map +1 -0
  52. package/dist/agent/observational-memory/read.js +97 -0
  53. package/dist/agent/observational-memory/read.js.map +1 -0
  54. package/dist/agent/observational-memory/reflector.d.ts +31 -0
  55. package/dist/agent/observational-memory/reflector.d.ts.map +1 -0
  56. package/dist/agent/observational-memory/reflector.js +76 -0
  57. package/dist/agent/observational-memory/reflector.js.map +1 -0
  58. package/dist/agent/observational-memory/schema.d.ts +267 -0
  59. package/dist/agent/observational-memory/schema.d.ts.map +1 -0
  60. package/dist/agent/observational-memory/schema.js +48 -0
  61. package/dist/agent/observational-memory/schema.js.map +1 -0
  62. package/dist/agent/observational-memory/store.d.ts +52 -0
  63. package/dist/agent/observational-memory/store.d.ts.map +1 -0
  64. package/dist/agent/observational-memory/store.js +197 -0
  65. package/dist/agent/observational-memory/store.js.map +1 -0
  66. package/dist/agent/observational-memory/types.d.ts +61 -0
  67. package/dist/agent/observational-memory/types.d.ts.map +1 -0
  68. package/dist/agent/observational-memory/types.js +9 -0
  69. package/dist/agent/observational-memory/types.js.map +1 -0
  70. package/dist/agent/processors.d.ts +146 -0
  71. package/dist/agent/processors.d.ts.map +1 -0
  72. package/dist/agent/processors.js +122 -0
  73. package/dist/agent/processors.js.map +1 -0
  74. package/dist/agent/production-agent.d.ts +25 -0
  75. package/dist/agent/production-agent.d.ts.map +1 -1
  76. package/dist/agent/production-agent.js +341 -1
  77. package/dist/agent/production-agent.js.map +1 -1
  78. package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
  79. package/dist/agent/run-loop-with-resume.js +48 -0
  80. package/dist/agent/run-loop-with-resume.js.map +1 -1
  81. package/dist/agent/run-store.d.ts +17 -0
  82. package/dist/agent/run-store.d.ts.map +1 -1
  83. package/dist/agent/run-store.js +55 -0
  84. package/dist/agent/run-store.js.map +1 -1
  85. package/dist/agent/runtime-context.d.ts +30 -0
  86. package/dist/agent/runtime-context.d.ts.map +1 -1
  87. package/dist/agent/runtime-context.js +54 -1
  88. package/dist/agent/runtime-context.js.map +1 -1
  89. package/dist/agent/tool-call-journal.d.ts +99 -0
  90. package/dist/agent/tool-call-journal.d.ts.map +1 -0
  91. package/dist/agent/tool-call-journal.js +212 -0
  92. package/dist/agent/tool-call-journal.js.map +1 -0
  93. package/dist/agent/types.d.ts +35 -0
  94. package/dist/agent/types.d.ts.map +1 -1
  95. package/dist/agent/types.js.map +1 -1
  96. package/dist/cli/add.d.ts +109 -0
  97. package/dist/cli/add.d.ts.map +1 -0
  98. package/dist/cli/add.js +352 -0
  99. package/dist/cli/add.js.map +1 -0
  100. package/dist/cli/connect.d.ts +2 -2
  101. package/dist/cli/connect.d.ts.map +1 -1
  102. package/dist/cli/connect.js +92 -24
  103. package/dist/cli/connect.js.map +1 -1
  104. package/dist/cli/eval.d.ts +17 -0
  105. package/dist/cli/eval.d.ts.map +1 -0
  106. package/dist/cli/eval.js +121 -0
  107. package/dist/cli/eval.js.map +1 -0
  108. package/dist/cli/index.js +44 -3
  109. package/dist/cli/index.js.map +1 -1
  110. package/dist/cli/mcp.d.ts.map +1 -1
  111. package/dist/cli/mcp.js +11 -5
  112. package/dist/cli/mcp.js.map +1 -1
  113. package/dist/cli/plan-local.d.ts +66 -5
  114. package/dist/cli/plan-local.d.ts.map +1 -1
  115. package/dist/cli/plan-local.js +622 -21
  116. package/dist/cli/plan-local.js.map +1 -1
  117. package/dist/cli/skills.d.ts +2 -2
  118. package/dist/cli/skills.d.ts.map +1 -1
  119. package/dist/cli/skills.js +108 -62
  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/chat/tool-call-display.d.ts +20 -1
  128. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  129. package/dist/client/chat/tool-call-display.js +32 -7
  130. package/dist/client/chat/tool-call-display.js.map +1 -1
  131. package/dist/client/sse-event-processor.d.ts +13 -0
  132. package/dist/client/sse-event-processor.d.ts.map +1 -1
  133. package/dist/client/sse-event-processor.js +21 -0
  134. package/dist/client/sse-event-processor.js.map +1 -1
  135. package/dist/coding-tools/run-code.d.ts.map +1 -1
  136. package/dist/coding-tools/run-code.js +18 -2
  137. package/dist/coding-tools/run-code.js.map +1 -1
  138. package/dist/db/client.d.ts +4 -2
  139. package/dist/db/client.d.ts.map +1 -1
  140. package/dist/db/client.js +6 -4
  141. package/dist/db/client.js.map +1 -1
  142. package/dist/deploy/route-discovery.d.ts.map +1 -1
  143. package/dist/deploy/route-discovery.js +1 -0
  144. package/dist/deploy/route-discovery.js.map +1 -1
  145. package/dist/eval/agent-runner.d.ts +63 -0
  146. package/dist/eval/agent-runner.d.ts.map +1 -0
  147. package/dist/eval/agent-runner.js +142 -0
  148. package/dist/eval/agent-runner.js.map +1 -0
  149. package/dist/eval/define-eval.d.ts +29 -0
  150. package/dist/eval/define-eval.d.ts.map +1 -0
  151. package/dist/eval/define-eval.js +43 -0
  152. package/dist/eval/define-eval.js.map +1 -0
  153. package/dist/eval/index.d.ts +18 -0
  154. package/dist/eval/index.d.ts.map +1 -0
  155. package/dist/eval/index.js +17 -0
  156. package/dist/eval/index.js.map +1 -0
  157. package/dist/eval/report.d.ts +8 -0
  158. package/dist/eval/report.d.ts.map +1 -0
  159. package/dist/eval/report.js +44 -0
  160. package/dist/eval/report.js.map +1 -0
  161. package/dist/eval/runner.d.ts +67 -0
  162. package/dist/eval/runner.d.ts.map +1 -0
  163. package/dist/eval/runner.js +256 -0
  164. package/dist/eval/runner.js.map +1 -0
  165. package/dist/eval/scorer.d.ts +83 -0
  166. package/dist/eval/scorer.d.ts.map +1 -0
  167. package/dist/eval/scorer.js +195 -0
  168. package/dist/eval/scorer.js.map +1 -0
  169. package/dist/eval/types.d.ts +162 -0
  170. package/dist/eval/types.d.ts.map +1 -0
  171. package/dist/eval/types.js +20 -0
  172. package/dist/eval/types.js.map +1 -0
  173. package/dist/extensions/fetch-tool.d.ts.map +1 -1
  174. package/dist/extensions/fetch-tool.js +80 -15
  175. package/dist/extensions/fetch-tool.js.map +1 -1
  176. package/dist/extensions/web-content.d.ts +61 -0
  177. package/dist/extensions/web-content.d.ts.map +1 -0
  178. package/dist/extensions/web-content.js +468 -0
  179. package/dist/extensions/web-content.js.map +1 -0
  180. package/dist/extensions/web-search-tool.js +3 -3
  181. package/dist/extensions/web-search-tool.js.map +1 -1
  182. package/dist/mcp/build-server.d.ts.map +1 -1
  183. package/dist/mcp/build-server.js +4 -1
  184. package/dist/mcp/build-server.js.map +1 -1
  185. package/dist/observability/traces.d.ts.map +1 -1
  186. package/dist/observability/traces.js +100 -1
  187. package/dist/observability/traces.js.map +1 -1
  188. package/dist/observability/tracing.d.ts +73 -0
  189. package/dist/observability/tracing.d.ts.map +1 -0
  190. package/dist/observability/tracing.js +126 -0
  191. package/dist/observability/tracing.js.map +1 -0
  192. package/dist/onboarding/default-steps.d.ts.map +1 -1
  193. package/dist/onboarding/default-steps.js +4 -1
  194. package/dist/onboarding/default-steps.js.map +1 -1
  195. package/dist/provider-api/actions/query-staged-dataset.d.ts +1 -1
  196. package/dist/provider-api/corpus-jobs.d.ts +80 -0
  197. package/dist/provider-api/corpus-jobs.d.ts.map +1 -1
  198. package/dist/provider-api/corpus-jobs.js +219 -22
  199. package/dist/provider-api/corpus-jobs.js.map +1 -1
  200. package/dist/provider-api/index.d.ts +24 -32
  201. package/dist/provider-api/index.d.ts.map +1 -1
  202. package/dist/provider-api/index.js +28 -1
  203. package/dist/provider-api/index.js.map +1 -1
  204. package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
  205. package/dist/scripts/agent-engines/list-agent-engines.js +10 -3
  206. package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
  207. package/dist/server/action-discovery.d.ts.map +1 -1
  208. package/dist/server/action-discovery.js +4 -0
  209. package/dist/server/action-discovery.js.map +1 -1
  210. package/dist/server/agent-chat-plugin.d.ts +9 -0
  211. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  212. package/dist/server/agent-chat-plugin.js +119 -111
  213. package/dist/server/agent-chat-plugin.js.map +1 -1
  214. package/dist/server/agent-teams.d.ts +62 -0
  215. package/dist/server/agent-teams.d.ts.map +1 -1
  216. package/dist/server/agent-teams.js +99 -2
  217. package/dist/server/agent-teams.js.map +1 -1
  218. package/dist/server/better-auth-instance.d.ts +7 -0
  219. package/dist/server/better-auth-instance.d.ts.map +1 -1
  220. package/dist/server/better-auth-instance.js +90 -0
  221. package/dist/server/better-auth-instance.js.map +1 -1
  222. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  223. package/dist/server/core-routes-plugin.js +7 -4
  224. package/dist/server/core-routes-plugin.js.map +1 -1
  225. package/dist/server/credential-provider.d.ts.map +1 -1
  226. package/dist/server/credential-provider.js +2 -0
  227. package/dist/server/credential-provider.js.map +1 -1
  228. package/dist/server/deep-link.d.ts +7 -0
  229. package/dist/server/deep-link.d.ts.map +1 -1
  230. package/dist/server/deep-link.js +13 -2
  231. package/dist/server/deep-link.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 +2 -1
  236. package/dist/server/index.d.ts.map +1 -1
  237. package/dist/server/index.js +2 -1
  238. package/dist/server/index.js.map +1 -1
  239. package/dist/templates/default/.agents/skills/actions/SKILL.md +52 -1
  240. package/dist/templates/default/.agents/skills/security/SKILL.md +22 -0
  241. package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +52 -1
  242. package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +16 -4
  243. package/dist/templates/workspace-core/.agents/skills/harness-agents/SKILL.md +20 -0
  244. package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +31 -0
  245. package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +22 -0
  246. package/docs/content/actions.md +50 -0
  247. package/docs/content/agent-teams.md +32 -0
  248. package/docs/content/blueprint-installer.md +73 -0
  249. package/docs/content/durable-resume.md +49 -0
  250. package/docs/content/evals.md +141 -0
  251. package/docs/content/external-agents.md +2 -2
  252. package/docs/content/human-approval.md +101 -0
  253. package/docs/content/observability.md +21 -0
  254. package/docs/content/observational-memory.md +63 -0
  255. package/docs/content/plan-plugin.md +5 -0
  256. package/docs/content/pr-visual-recap.md +9 -5
  257. package/docs/content/processors.md +99 -0
  258. package/docs/content/sandbox-adapters.md +134 -0
  259. package/docs/content/template-plan.md +97 -21
  260. package/package.json +10 -1
  261. package/src/templates/default/.agents/skills/actions/SKILL.md +52 -1
  262. package/src/templates/default/.agents/skills/security/SKILL.md +22 -0
  263. package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +52 -1
  264. package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +16 -4
  265. package/src/templates/workspace-core/.agents/skills/harness-agents/SKILL.md +20 -0
  266. package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +31 -0
  267. package/src/templates/workspace-core/.agents/skills/security/SKILL.md +22 -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,99 @@
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
+ * Two layers of protection are built on this: (1) a prompt-level note on resume
28
+ * (see `run-loop-with-resume.ts`) telling the model what already completed, and
29
+ * (2) tool-layer enforcement in `production-agent.ts`/`runToolCall`, which uses
30
+ * `findCompletedJournalEntry(...)` to refuse re-executing a journaled-complete
31
+ * write tool — returning the journaled result instead of running the side
32
+ * effect again. Layer 2 is the stronger guarantee.
33
+ */
34
+ import type { AgentChatEvent } from "./types.js";
35
+ /** A single recorded tool-call ledger entry, classified by outcome. */
36
+ export interface ToolCallJournalEntry {
37
+ /**
38
+ * Stable-ish identity for this tool call within the turn. The ledger event
39
+ * stream has no tool-call id, so we key by tool name + a short input
40
+ * signature + positional order, exactly enough to disambiguate repeats of the
41
+ * same tool within one turn for human/model-readable reporting.
42
+ */
43
+ key: string;
44
+ /** Tool / action name (from the `tool_start` event). */
45
+ tool: string;
46
+ /** Tool input captured at `tool_start`, if any. */
47
+ input?: Record<string, string>;
48
+ /** 0-based position of the `tool_start` among all tool calls in the turn. */
49
+ order: number;
50
+ /** Result text from the matched `tool_done`, when the call completed. */
51
+ result?: string;
52
+ }
53
+ /** Result of classifying one turn's ledger events. */
54
+ export interface ToolCallJournal {
55
+ /** Tool calls with a matching `tool_done` — already ran, do NOT re-run. */
56
+ completed: ToolCallJournalEntry[];
57
+ /**
58
+ * Tool calls with a `tool_start` but no matching `tool_done` — interrupted,
59
+ * outcome unknown. The model must decide whether re-running is safe.
60
+ */
61
+ interrupted: ToolCallJournalEntry[];
62
+ }
63
+ /**
64
+ * Classify a single turn's recorded events into completed vs interrupted tool
65
+ * calls. Pure and side-effect free — given the same events it always returns
66
+ * the same journal. A `clear` event resets the per-turn tally exactly as the
67
+ * thread rebuild does, so partial streamed output that was discarded on resume
68
+ * doesn't leave phantom open tool calls.
69
+ */
70
+ export declare function classifyToolCallJournal(events: readonly AgentChatEvent[]): ToolCallJournal;
71
+ /** True when the journal has nothing worth telling a resuming model about. */
72
+ export declare function isJournalEmpty(journal: ToolCallJournal): boolean;
73
+ /**
74
+ * Find a COMPLETED journal entry that matches a tool call about to be
75
+ * dispatched, by tool name + input signature (position-independent — a resumed
76
+ * call may sit at a different order than the original). Used by the tool-layer
77
+ * hard-block in production-agent.ts/runToolCall to skip re-executing a side
78
+ * effect that already completed in a prior interrupted chunk: when this returns
79
+ * an entry, the loop returns `entry.result` instead of running the action.
80
+ *
81
+ * Returns the FIRST unmatched completed entry for that (name + input); the
82
+ * caller is expected to claim it (mark it consumed) so two identical fresh
83
+ * calls in the same turn don't both short-circuit on one journaled completion.
84
+ * Returns undefined when there is no completed entry for this exact call —
85
+ * including every fresh call, which must execute normally.
86
+ */
87
+ export declare function findCompletedJournalEntry(journal: ToolCallJournal, toolName: string, input: unknown, consumedKeys?: Set<string>): ToolCallJournalEntry | undefined;
88
+ /**
89
+ * Build the structured resume note injected on auto-continue. Returns `null`
90
+ * when there are no completed or interrupted tool calls to report, so the
91
+ * caller can preserve the exact pre-existing "continue from where you left off"
92
+ * behavior on normal resumes (no regression for turns with no tool activity).
93
+ *
94
+ * The note is intentionally a flat, model-readable block: a list of already-run
95
+ * tool calls (with short results) the model must NOT re-run, and a separate list
96
+ * of interrupted calls whose outcome is unknown for the model to decide on.
97
+ */
98
+ export declare function buildResumeJournalNote(journal: ToolCallJournal): string | null;
99
+ //# 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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;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,212 @@
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
+ * Two layers of protection are built on this: (1) a prompt-level note on resume
28
+ * (see `run-loop-with-resume.ts`) telling the model what already completed, and
29
+ * (2) tool-layer enforcement in `production-agent.ts`/`runToolCall`, which uses
30
+ * `findCompletedJournalEntry(...)` to refuse re-executing a journaled-complete
31
+ * write tool — returning the journaled result instead of running the side
32
+ * effect again. Layer 2 is the stronger guarantee.
33
+ */
34
+ /** Max length of an input signature included in a journal key (debug-readable). */
35
+ const INPUT_SIGNATURE_MAX_CHARS = 120;
36
+ /** Max length of a per-tool-call result summary surfaced in the resume note. */
37
+ const RESULT_SUMMARY_MAX_CHARS = 400;
38
+ function inputSignature(input) {
39
+ if (!input)
40
+ return "";
41
+ let sig;
42
+ try {
43
+ // Stable key order so the same logical input produces the same signature
44
+ // regardless of how the engine serialized the object.
45
+ const sorted = Object.keys(input)
46
+ .sort()
47
+ .reduce((acc, k) => {
48
+ acc[k] = input[k];
49
+ return acc;
50
+ }, {});
51
+ sig = JSON.stringify(sorted);
52
+ }
53
+ catch {
54
+ sig = String(input);
55
+ }
56
+ return sig.length > INPUT_SIGNATURE_MAX_CHARS
57
+ ? sig.slice(0, INPUT_SIGNATURE_MAX_CHARS)
58
+ : sig;
59
+ }
60
+ /**
61
+ * Classify a single turn's recorded events into completed vs interrupted tool
62
+ * calls. Pure and side-effect free — given the same events it always returns
63
+ * the same journal. A `clear` event resets the per-turn tally exactly as the
64
+ * thread rebuild does, so partial streamed output that was discarded on resume
65
+ * doesn't leave phantom open tool calls.
66
+ */
67
+ export function classifyToolCallJournal(events) {
68
+ // Open tool_start entries awaiting a matching tool_done, in FIFO order. We
69
+ // index by tool name so a tool_done matches the OLDEST open start for that
70
+ // same tool — the dispatch loop always emits start-then-done per call, so the
71
+ // first unmatched start of a given name is the one this done belongs to.
72
+ const openByTool = new Map();
73
+ const completed = [];
74
+ let order = 0;
75
+ for (const event of events) {
76
+ if (event.type === "clear") {
77
+ // Discarded partial output: drop any not-yet-completed starts so they
78
+ // aren't reported as interrupted. Already-completed entries stay.
79
+ openByTool.clear();
80
+ continue;
81
+ }
82
+ if (event.type === "tool_start") {
83
+ const tool = event.tool ?? "unknown";
84
+ const input = (event.input ?? undefined);
85
+ const entry = {
86
+ key: `${tool}#${order}:${inputSignature(input)}`,
87
+ tool,
88
+ ...(input ? { input } : {}),
89
+ order,
90
+ };
91
+ order += 1;
92
+ const queue = openByTool.get(tool);
93
+ if (queue)
94
+ queue.push(entry);
95
+ else
96
+ openByTool.set(tool, [entry]);
97
+ continue;
98
+ }
99
+ if (event.type === "tool_done") {
100
+ const tool = event.tool ?? "unknown";
101
+ const queue = openByTool.get(tool);
102
+ const entry = queue?.shift();
103
+ if (entry) {
104
+ entry.result = event.result ?? "";
105
+ completed.push(entry);
106
+ }
107
+ // A tool_done with no open start is ignored — it can't be re-associated
108
+ // and re-reporting a duplicate done would be noise.
109
+ continue;
110
+ }
111
+ }
112
+ // Anything still open never received a tool_done → interrupted / unknown.
113
+ const interrupted = [];
114
+ for (const queue of openByTool.values()) {
115
+ for (const entry of queue)
116
+ interrupted.push(entry);
117
+ }
118
+ interrupted.sort((a, b) => a.order - b.order);
119
+ return { completed, interrupted };
120
+ }
121
+ /** True when the journal has nothing worth telling a resuming model about. */
122
+ export function isJournalEmpty(journal) {
123
+ return journal.completed.length === 0 && journal.interrupted.length === 0;
124
+ }
125
+ /**
126
+ * Find a COMPLETED journal entry that matches a tool call about to be
127
+ * dispatched, by tool name + input signature (position-independent — a resumed
128
+ * call may sit at a different order than the original). Used by the tool-layer
129
+ * hard-block in production-agent.ts/runToolCall to skip re-executing a side
130
+ * effect that already completed in a prior interrupted chunk: when this returns
131
+ * an entry, the loop returns `entry.result` instead of running the action.
132
+ *
133
+ * Returns the FIRST unmatched completed entry for that (name + input); the
134
+ * caller is expected to claim it (mark it consumed) so two identical fresh
135
+ * calls in the same turn don't both short-circuit on one journaled completion.
136
+ * Returns undefined when there is no completed entry for this exact call —
137
+ * including every fresh call, which must execute normally.
138
+ */
139
+ export function findCompletedJournalEntry(journal, toolName, input, consumedKeys) {
140
+ const wantSig = inputSignature(normalizeInputForSignature(input));
141
+ for (const entry of journal.completed) {
142
+ if (entry.tool !== toolName)
143
+ continue;
144
+ if (inputSignature(entry.input) !== wantSig)
145
+ continue;
146
+ if (consumedKeys?.has(entry.key))
147
+ continue;
148
+ consumedKeys?.add(entry.key);
149
+ return entry;
150
+ }
151
+ return undefined;
152
+ }
153
+ /**
154
+ * Coerce an arbitrary tool input into the `Record<string, string>` shape the
155
+ * journal recorded at `tool_start` so signatures compare apples-to-apples. The
156
+ * ledger stores `tool_start.input` as a string map; the live call's `input` is
157
+ * the parsed object — both pass through `inputSignature`, which sorts keys and
158
+ * JSON-stringifies, so a plain object compares correctly.
159
+ */
160
+ function normalizeInputForSignature(input) {
161
+ if (input == null || typeof input !== "object")
162
+ return undefined;
163
+ return input;
164
+ }
165
+ function summarizeResult(result) {
166
+ if (!result)
167
+ return "(no result recorded)";
168
+ const oneLine = result.replace(/\s+/g, " ").trim();
169
+ if (oneLine.length === 0)
170
+ return "(empty result)";
171
+ return oneLine.length > RESULT_SUMMARY_MAX_CHARS
172
+ ? oneLine.slice(0, RESULT_SUMMARY_MAX_CHARS) + "…"
173
+ : oneLine;
174
+ }
175
+ function describeInput(input) {
176
+ if (!input)
177
+ return "";
178
+ const sig = inputSignature(input);
179
+ return sig && sig !== "{}" ? ` input: ${sig}` : "";
180
+ }
181
+ /**
182
+ * Build the structured resume note injected on auto-continue. Returns `null`
183
+ * when there are no completed or interrupted tool calls to report, so the
184
+ * caller can preserve the exact pre-existing "continue from where you left off"
185
+ * behavior on normal resumes (no regression for turns with no tool activity).
186
+ *
187
+ * The note is intentionally a flat, model-readable block: a list of already-run
188
+ * tool calls (with short results) the model must NOT re-run, and a separate list
189
+ * of interrupted calls whose outcome is unknown for the model to decide on.
190
+ */
191
+ export function buildResumeJournalNote(journal) {
192
+ if (isJournalEmpty(journal))
193
+ return null;
194
+ const lines = [];
195
+ lines.push("Tool-call journal from the interrupted attempt (derived from the durable run ledger):");
196
+ if (journal.completed.length > 0) {
197
+ lines.push("");
198
+ lines.push("Already completed (do NOT re-run these — their side effects already happened; reuse the results below):");
199
+ for (const entry of journal.completed) {
200
+ lines.push(`- ${entry.tool}${describeInput(entry.input)} → ${summarizeResult(entry.result)}`);
201
+ }
202
+ }
203
+ if (journal.interrupted.length > 0) {
204
+ lines.push("");
205
+ 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):");
206
+ for (const entry of journal.interrupted) {
207
+ lines.push(`- ${entry.tool}${describeInput(entry.input)} → (no result recorded)`);
208
+ }
209
+ }
210
+ return lines.join("\n");
211
+ }
212
+ //# 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":"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","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 * Two layers of protection are built on this: (1) a prompt-level note on resume\n * (see `run-loop-with-resume.ts`) telling the model what already completed, and\n * (2) tool-layer enforcement in `production-agent.ts`/`runToolCall`, which uses\n * `findCompletedJournalEntry(...)` to refuse re-executing a journaled-complete\n * write tool — returning the journaled result instead of running the side\n * effect again. Layer 2 is the stronger guarantee.\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;
@@ -191,6 +215,17 @@ export type AgentChatEvent = {
191
215
  } | {
192
216
  type: "loop_limit";
193
217
  maxIterations?: number;
218
+ } | {
219
+ /**
220
+ * An in-loop `Processor` aborted the run via `abort()` (which throws a
221
+ * `TripWire`). The loop catches it, emits this event, stops cleanly, and
222
+ * surfaces the reason as a final assistant message. Structural hook for
223
+ * real-time guardrails and a proof-of-done / coverage gate.
224
+ */
225
+ type: "tripwire";
226
+ reason: string;
227
+ /** Name of the processor that aborted, when it declared one. */
228
+ processor?: string;
194
229
  } | {
195
230
  type: "auto_continue";
196
231
  reason: "run_timeout" | "loop_limit" | "no_progress" | "stream_ended" | "gateway_timeout" | "network_interrupted";
@@ -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":"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"}
@@ -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 /**\n * An in-loop `Processor` aborted the run via `abort()` (which throws a\n * `TripWire`). The loop catches it, emits this event, stops cleanly, and\n * surfaces the reason as a final assistant message. Structural hook for\n * real-time guardrails and a proof-of-done / coverage gate.\n */\n type: \"tripwire\";\n reason: string;\n /** Name of the processor that aborted, when it declared one. */\n processor?: string;\n }\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"}