@retinue/agentkit 0.1.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 (405) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +310 -0
  3. package/dist/adapters/bullmq/consumer.d.ts +33 -0
  4. package/dist/adapters/bullmq/consumer.js +41 -0
  5. package/dist/adapters/bullmq/dispatcher.d.ts +74 -0
  6. package/dist/adapters/bullmq/dispatcher.js +160 -0
  7. package/dist/adapters/bullmq/export.d.ts +31 -0
  8. package/dist/adapters/bullmq/export.js +53 -0
  9. package/dist/adapters/bullmq/extraction.d.ts +42 -0
  10. package/dist/adapters/bullmq/extraction.js +63 -0
  11. package/dist/adapters/bullmq/index.d.ts +13 -0
  12. package/dist/adapters/bullmq/index.js +13 -0
  13. package/dist/adapters/bullmq/lock.d.ts +77 -0
  14. package/dist/adapters/bullmq/lock.js +126 -0
  15. package/dist/adapters/bullmq/queue.d.ts +50 -0
  16. package/dist/adapters/bullmq/queue.js +81 -0
  17. package/dist/adapters/memory/artifact-exports.d.ts +11 -0
  18. package/dist/adapters/memory/artifact-exports.js +102 -0
  19. package/dist/adapters/memory/artifacts.d.ts +15 -0
  20. package/dist/adapters/memory/artifacts.js +134 -0
  21. package/dist/adapters/memory/blobs.d.ts +7 -0
  22. package/dist/adapters/memory/blobs.js +27 -0
  23. package/dist/adapters/memory/evaluation.d.ts +18 -0
  24. package/dist/adapters/memory/evaluation.js +148 -0
  25. package/dist/adapters/memory/files.d.ts +27 -0
  26. package/dist/adapters/memory/files.js +0 -0
  27. package/dist/adapters/memory/flows.d.ts +16 -0
  28. package/dist/adapters/memory/flows.js +117 -0
  29. package/dist/adapters/memory/hitl.d.ts +9 -0
  30. package/dist/adapters/memory/hitl.js +130 -0
  31. package/dist/adapters/memory/idempotency.d.ts +13 -0
  32. package/dist/adapters/memory/idempotency.js +32 -0
  33. package/dist/adapters/memory/index.d.ts +39 -0
  34. package/dist/adapters/memory/index.js +107 -0
  35. package/dist/adapters/memory/knowledge.d.ts +43 -0
  36. package/dist/adapters/memory/knowledge.js +248 -0
  37. package/dist/adapters/memory/mcp.d.ts +9 -0
  38. package/dist/adapters/memory/mcp.js +37 -0
  39. package/dist/adapters/memory/message-store.d.ts +17 -0
  40. package/dist/adapters/memory/message-store.js +70 -0
  41. package/dist/adapters/memory/principal-memory.d.ts +7 -0
  42. package/dist/adapters/memory/principal-memory.js +83 -0
  43. package/dist/adapters/memory/runtime.d.ts +29 -0
  44. package/dist/adapters/memory/runtime.js +0 -0
  45. package/dist/adapters/memory/sessions.d.ts +29 -0
  46. package/dist/adapters/memory/sessions.js +0 -0
  47. package/dist/adapters/memory/skills.d.ts +10 -0
  48. package/dist/adapters/memory/skills.js +41 -0
  49. package/dist/adapters/memory/thread-summary.d.ts +7 -0
  50. package/dist/adapters/memory/thread-summary.js +29 -0
  51. package/dist/adapters/memory/usage-limits.d.ts +13 -0
  52. package/dist/adapters/memory/usage-limits.js +72 -0
  53. package/dist/adapters/memory/usage.d.ts +16 -0
  54. package/dist/adapters/memory/usage.js +279 -0
  55. package/dist/adapters/otel/index.d.ts +111 -0
  56. package/dist/adapters/otel/index.js +133 -0
  57. package/dist/adapters/postgres/artifact-exports.d.ts +12 -0
  58. package/dist/adapters/postgres/artifact-exports.js +117 -0
  59. package/dist/adapters/postgres/artifacts.d.ts +16 -0
  60. package/dist/adapters/postgres/artifacts.js +172 -0
  61. package/dist/adapters/postgres/checkpoint-store.d.ts +16 -0
  62. package/dist/adapters/postgres/checkpoint-store.js +34 -0
  63. package/dist/adapters/postgres/config.d.ts +15 -0
  64. package/dist/adapters/postgres/config.js +187 -0
  65. package/dist/adapters/postgres/conversation-store.d.ts +4 -0
  66. package/dist/adapters/postgres/conversation-store.js +82 -0
  67. package/dist/adapters/postgres/evaluation.d.ts +17 -0
  68. package/dist/adapters/postgres/evaluation.js +193 -0
  69. package/dist/adapters/postgres/file-content.d.ts +30 -0
  70. package/dist/adapters/postgres/file-content.js +111 -0
  71. package/dist/adapters/postgres/files.d.ts +19 -0
  72. package/dist/adapters/postgres/files.js +209 -0
  73. package/dist/adapters/postgres/flows.d.ts +20 -0
  74. package/dist/adapters/postgres/flows.js +206 -0
  75. package/dist/adapters/postgres/hitl.d.ts +5 -0
  76. package/dist/adapters/postgres/hitl.js +247 -0
  77. package/dist/adapters/postgres/index.d.ts +35 -0
  78. package/dist/adapters/postgres/index.js +35 -0
  79. package/dist/adapters/postgres/knowledge.d.ts +48 -0
  80. package/dist/adapters/postgres/knowledge.js +255 -0
  81. package/dist/adapters/postgres/memory.d.ts +14 -0
  82. package/dist/adapters/postgres/memory.js +194 -0
  83. package/dist/adapters/postgres/message-store.d.ts +11 -0
  84. package/dist/adapters/postgres/message-store.js +145 -0
  85. package/dist/adapters/postgres/migrations.d.ts +69 -0
  86. package/dist/adapters/postgres/migrations.js +1594 -0
  87. package/dist/adapters/postgres/pg-executor.d.ts +19 -0
  88. package/dist/adapters/postgres/pg-executor.js +32 -0
  89. package/dist/adapters/postgres/retention.d.ts +26 -0
  90. package/dist/adapters/postgres/retention.js +59 -0
  91. package/dist/adapters/postgres/rollups.d.ts +17 -0
  92. package/dist/adapters/postgres/rollups.js +267 -0
  93. package/dist/adapters/postgres/run-coordinator.d.ts +5 -0
  94. package/dist/adapters/postgres/run-coordinator.js +98 -0
  95. package/dist/adapters/postgres/run-event-log.d.ts +26 -0
  96. package/dist/adapters/postgres/run-event-log.js +30 -0
  97. package/dist/adapters/postgres/run-store.d.ts +4 -0
  98. package/dist/adapters/postgres/run-store.js +199 -0
  99. package/dist/adapters/postgres/schema.d.ts +39 -0
  100. package/dist/adapters/postgres/schema.js +70 -0
  101. package/dist/adapters/postgres/session-state.d.ts +7 -0
  102. package/dist/adapters/postgres/session-state.js +99 -0
  103. package/dist/adapters/postgres/sql.d.ts +8 -0
  104. package/dist/adapters/postgres/sql.js +2 -0
  105. package/dist/adapters/postgres/transaction.d.ts +37 -0
  106. package/dist/adapters/postgres/transaction.js +93 -0
  107. package/dist/adapters/postgres/unit-of-work.d.ts +18 -0
  108. package/dist/adapters/postgres/unit-of-work.js +8 -0
  109. package/dist/adapters/postgres/usage-limits.d.ts +15 -0
  110. package/dist/adapters/postgres/usage-limits.js +136 -0
  111. package/dist/adapters/postgres/usage.d.ts +15 -0
  112. package/dist/adapters/postgres/usage.js +226 -0
  113. package/dist/adapters/redis/index.d.ts +9 -0
  114. package/dist/adapters/redis/index.js +9 -0
  115. package/dist/adapters/redis/realtime.d.ts +74 -0
  116. package/dist/adapters/redis/realtime.js +112 -0
  117. package/dist/adapters/supabase/index.d.ts +88 -0
  118. package/dist/adapters/supabase/index.js +84 -0
  119. package/dist/adapters/supabase/realtime.d.ts +30 -0
  120. package/dist/adapters/supabase/realtime.js +53 -0
  121. package/dist/adapters/supabase/rls.d.ts +99 -0
  122. package/dist/adapters/supabase/rls.js +216 -0
  123. package/dist/adapters/supabase/storage.d.ts +50 -0
  124. package/dist/adapters/supabase/storage.js +207 -0
  125. package/dist/agents/agent.d.ts +66 -0
  126. package/dist/agents/agent.js +209 -0
  127. package/dist/agents/define.d.ts +21 -0
  128. package/dist/agents/define.js +63 -0
  129. package/dist/agents/engine.d.ts +98 -0
  130. package/dist/agents/engine.js +462 -0
  131. package/dist/agents/index.d.ts +50 -0
  132. package/dist/agents/index.js +17 -0
  133. package/dist/artifacts/index.d.ts +114 -0
  134. package/dist/artifacts/index.js +219 -0
  135. package/dist/authorization/index.d.ts +76 -0
  136. package/dist/authorization/index.js +76 -0
  137. package/dist/capabilities/index.d.ts +120 -0
  138. package/dist/capabilities/index.js +167 -0
  139. package/dist/capabilities/runtime.d.ts +89 -0
  140. package/dist/capabilities/runtime.js +84 -0
  141. package/dist/citations/index.d.ts +161 -0
  142. package/dist/citations/index.js +182 -0
  143. package/dist/context/assembler.d.ts +82 -0
  144. package/dist/context/assembler.js +129 -0
  145. package/dist/context/compaction.d.ts +45 -0
  146. package/dist/context/compaction.js +55 -0
  147. package/dist/context/index.d.ts +75 -0
  148. package/dist/context/index.js +17 -0
  149. package/dist/core/content-parts.d.ts +194 -0
  150. package/dist/core/content-parts.js +23 -0
  151. package/dist/core/context.d.ts +51 -0
  152. package/dist/core/context.js +9 -0
  153. package/dist/core/env.d.ts +25 -0
  154. package/dist/core/env.js +41 -0
  155. package/dist/core/errors.d.ts +30 -0
  156. package/dist/core/errors.js +65 -0
  157. package/dist/core/events.d.ts +139 -0
  158. package/dist/core/events.js +99 -0
  159. package/dist/core/ids.d.ts +52 -0
  160. package/dist/core/ids.js +13 -0
  161. package/dist/core/index.d.ts +9 -0
  162. package/dist/core/index.js +9 -0
  163. package/dist/core/tokens.d.ts +22 -0
  164. package/dist/core/tokens.js +22 -0
  165. package/dist/core/validation.d.ts +34 -0
  166. package/dist/core/validation.js +176 -0
  167. package/dist/documents/extraction.d.ts +121 -0
  168. package/dist/documents/extraction.js +293 -0
  169. package/dist/documents/index.d.ts +199 -0
  170. package/dist/documents/index.js +65 -0
  171. package/dist/documents/parsers/pdf.d.ts +47 -0
  172. package/dist/documents/parsers/pdf.js +508 -0
  173. package/dist/documents/parsers/text.d.ts +59 -0
  174. package/dist/documents/parsers/text.js +325 -0
  175. package/dist/documents/read-tool.d.ts +52 -0
  176. package/dist/documents/read-tool.js +109 -0
  177. package/dist/documents/render.d.ts +29 -0
  178. package/dist/documents/render.js +59 -0
  179. package/dist/documents/vision.d.ts +159 -0
  180. package/dist/documents/vision.js +214 -0
  181. package/dist/entries/adapters-bullmq.d.ts +8 -0
  182. package/dist/entries/adapters-bullmq.js +8 -0
  183. package/dist/entries/adapters-otel.d.ts +13 -0
  184. package/dist/entries/adapters-otel.js +13 -0
  185. package/dist/entries/adapters-postgres.d.ts +10 -0
  186. package/dist/entries/adapters-postgres.js +10 -0
  187. package/dist/entries/adapters-redis.d.ts +3 -0
  188. package/dist/entries/adapters-redis.js +3 -0
  189. package/dist/entries/context.d.ts +20 -0
  190. package/dist/entries/context.js +20 -0
  191. package/dist/entries/flows.d.ts +15 -0
  192. package/dist/entries/flows.js +15 -0
  193. package/dist/entries/hitl.d.ts +10 -0
  194. package/dist/entries/hitl.js +10 -0
  195. package/dist/entries/knowledge.d.ts +18 -0
  196. package/dist/entries/knowledge.js +19 -0
  197. package/dist/entries/mcp.d.ts +10 -0
  198. package/dist/entries/mcp.js +10 -0
  199. package/dist/entries/observability.d.ts +14 -0
  200. package/dist/entries/observability.js +16 -0
  201. package/dist/entries/persistence.d.ts +11 -0
  202. package/dist/entries/persistence.js +11 -0
  203. package/dist/entries/providers.d.ts +14 -0
  204. package/dist/entries/providers.js +14 -0
  205. package/dist/entries/runtime.d.ts +13 -0
  206. package/dist/entries/runtime.js +13 -0
  207. package/dist/entries/server.d.ts +24 -0
  208. package/dist/entries/server.js +24 -0
  209. package/dist/entries/tools.d.ts +21 -0
  210. package/dist/entries/tools.js +21 -0
  211. package/dist/entries/usage.d.ts +10 -0
  212. package/dist/entries/usage.js +10 -0
  213. package/dist/evaluation/gate.d.ts +168 -0
  214. package/dist/evaluation/gate.js +180 -0
  215. package/dist/evaluation/graders.d.ts +125 -0
  216. package/dist/evaluation/graders.js +203 -0
  217. package/dist/evaluation/index.d.ts +120 -0
  218. package/dist/evaluation/index.js +183 -0
  219. package/dist/evaluation/judge.d.ts +75 -0
  220. package/dist/evaluation/judge.js +111 -0
  221. package/dist/export/index.d.ts +162 -0
  222. package/dist/export/index.js +363 -0
  223. package/dist/export/markdown.d.ts +19 -0
  224. package/dist/export/markdown.js +29 -0
  225. package/dist/export/pdf.d.ts +73 -0
  226. package/dist/export/pdf.js +407 -0
  227. package/dist/files/context.d.ts +97 -0
  228. package/dist/files/context.js +185 -0
  229. package/dist/files/index.d.ts +210 -0
  230. package/dist/files/index.js +338 -0
  231. package/dist/files/read-tool.d.ts +81 -0
  232. package/dist/files/read-tool.js +163 -0
  233. package/dist/files/turn-parts.d.ts +96 -0
  234. package/dist/files/turn-parts.js +171 -0
  235. package/dist/flows/index.d.ts +270 -0
  236. package/dist/flows/index.js +62 -0
  237. package/dist/flows/interpreter.d.ts +146 -0
  238. package/dist/flows/interpreter.js +426 -0
  239. package/dist/flows/runner.d.ts +145 -0
  240. package/dist/flows/runner.js +270 -0
  241. package/dist/graphql/index.d.ts +8 -0
  242. package/dist/graphql/index.js +8 -0
  243. package/dist/graphql/resolvers.d.ts +237 -0
  244. package/dist/graphql/resolvers.js +253 -0
  245. package/dist/graphql/schema.d.ts +11 -0
  246. package/dist/graphql/schema.js +258 -0
  247. package/dist/graphql/sse.d.ts +77 -0
  248. package/dist/graphql/sse.js +100 -0
  249. package/dist/hitl/approved-execution.d.ts +127 -0
  250. package/dist/hitl/approved-execution.js +177 -0
  251. package/dist/hitl/index.d.ts +79 -0
  252. package/dist/hitl/index.js +12 -0
  253. package/dist/hitl/service.d.ts +221 -0
  254. package/dist/hitl/service.js +268 -0
  255. package/dist/idempotency/index.d.ts +70 -0
  256. package/dist/idempotency/index.js +59 -0
  257. package/dist/index.d.ts +103 -0
  258. package/dist/index.js +60 -0
  259. package/dist/knowledge/chunking.d.ts +57 -0
  260. package/dist/knowledge/chunking.js +158 -0
  261. package/dist/knowledge/index.d.ts +119 -0
  262. package/dist/knowledge/index.js +166 -0
  263. package/dist/knowledge/retrieval.d.ts +146 -0
  264. package/dist/knowledge/retrieval.js +170 -0
  265. package/dist/loadtest/harness.d.ts +168 -0
  266. package/dist/loadtest/harness.js +507 -0
  267. package/dist/loadtest/index.d.ts +13 -0
  268. package/dist/loadtest/index.js +13 -0
  269. package/dist/loadtest/injection.d.ts +89 -0
  270. package/dist/loadtest/injection.js +147 -0
  271. package/dist/loadtest/metrics.d.ts +197 -0
  272. package/dist/loadtest/metrics.js +160 -0
  273. package/dist/loadtest/runbooks.d.ts +28 -0
  274. package/dist/loadtest/runbooks.js +159 -0
  275. package/dist/loadtest/scenario.d.ts +104 -0
  276. package/dist/loadtest/scenario.js +208 -0
  277. package/dist/mcp/egress.d.ts +53 -0
  278. package/dist/mcp/egress.js +115 -0
  279. package/dist/mcp/index.d.ts +93 -0
  280. package/dist/mcp/index.js +33 -0
  281. package/dist/mcp/provider.d.ts +62 -0
  282. package/dist/mcp/provider.js +0 -0
  283. package/dist/models/index.d.ts +98 -0
  284. package/dist/models/index.js +74 -0
  285. package/dist/models/pricing.d.ts +24 -0
  286. package/dist/models/pricing.js +37 -0
  287. package/dist/models/provider-factory.d.ts +31 -0
  288. package/dist/models/provider-factory.js +67 -0
  289. package/dist/models/streaming.d.ts +145 -0
  290. package/dist/models/streaming.js +272 -0
  291. package/dist/models/vision.d.ts +38 -0
  292. package/dist/models/vision.js +62 -0
  293. package/dist/persistence/index.d.ts +1654 -0
  294. package/dist/persistence/index.js +226 -0
  295. package/dist/principal-memory/index.d.ts +106 -0
  296. package/dist/principal-memory/index.js +89 -0
  297. package/dist/retention/index.d.ts +89 -0
  298. package/dist/retention/index.js +70 -0
  299. package/dist/runtime/checkpoint.d.ts +37 -0
  300. package/dist/runtime/checkpoint.js +22 -0
  301. package/dist/runtime/index.d.ts +118 -0
  302. package/dist/runtime/index.js +69 -0
  303. package/dist/runtime/retry.d.ts +95 -0
  304. package/dist/runtime/retry.js +126 -0
  305. package/dist/runtime/serialization.d.ts +85 -0
  306. package/dist/runtime/serialization.js +95 -0
  307. package/dist/runtime/streaming.d.ts +54 -0
  308. package/dist/runtime/streaming.js +115 -0
  309. package/dist/runtime/worker.d.ts +130 -0
  310. package/dist/runtime/worker.js +405 -0
  311. package/dist/security/checklist.d.ts +53 -0
  312. package/dist/security/checklist.js +204 -0
  313. package/dist/security/findings.d.ts +56 -0
  314. package/dist/security/findings.js +168 -0
  315. package/dist/security/index.d.ts +14 -0
  316. package/dist/security/index.js +14 -0
  317. package/dist/security/prompt-safety.d.ts +100 -0
  318. package/dist/security/prompt-safety.js +133 -0
  319. package/dist/server/boot.d.ts +32 -0
  320. package/dist/server/boot.js +36 -0
  321. package/dist/server/cli-worker.d.ts +37 -0
  322. package/dist/server/cli-worker.js +151 -0
  323. package/dist/server/cli.d.ts +27 -0
  324. package/dist/server/cli.js +74 -0
  325. package/dist/server/config.d.ts +42 -0
  326. package/dist/server/config.js +127 -0
  327. package/dist/server/health.d.ts +59 -0
  328. package/dist/server/health.js +90 -0
  329. package/dist/server/host.d.ts +39 -0
  330. package/dist/server/host.js +124 -0
  331. package/dist/server/index.d.ts +15 -0
  332. package/dist/server/index.js +15 -0
  333. package/dist/server/main.d.ts +16 -0
  334. package/dist/server/main.js +31 -0
  335. package/dist/server/sse-route.d.ts +21 -0
  336. package/dist/server/sse-route.js +282 -0
  337. package/dist/skills/index.d.ts +67 -0
  338. package/dist/skills/index.js +31 -0
  339. package/dist/skills/resolver.d.ts +54 -0
  340. package/dist/skills/resolver.js +121 -0
  341. package/dist/teams/index.d.ts +93 -0
  342. package/dist/teams/index.js +207 -0
  343. package/dist/telemetry/index.d.ts +157 -0
  344. package/dist/telemetry/index.js +71 -0
  345. package/dist/telemetry/instrument.d.ts +108 -0
  346. package/dist/telemetry/instrument.js +232 -0
  347. package/dist/telemetry/log-events.d.ts +17 -0
  348. package/dist/telemetry/log-events.js +58 -0
  349. package/dist/telemetry/metrics.d.ts +123 -0
  350. package/dist/telemetry/metrics.js +135 -0
  351. package/dist/telemetry/noop.d.ts +39 -0
  352. package/dist/telemetry/noop.js +143 -0
  353. package/dist/telemetry/redaction.d.ts +64 -0
  354. package/dist/telemetry/redaction.js +153 -0
  355. package/dist/telemetry/spans.d.ts +56 -0
  356. package/dist/telemetry/spans.js +78 -0
  357. package/dist/telemetry/trace-context.d.ts +55 -0
  358. package/dist/telemetry/trace-context.js +60 -0
  359. package/dist/toolkit/compute.d.ts +53 -0
  360. package/dist/toolkit/compute.js +152 -0
  361. package/dist/toolkit/data.d.ts +98 -0
  362. package/dist/toolkit/data.js +235 -0
  363. package/dist/toolkit/http.d.ts +113 -0
  364. package/dist/toolkit/http.js +205 -0
  365. package/dist/toolkit/index.d.ts +21 -0
  366. package/dist/toolkit/index.js +17 -0
  367. package/dist/toolkit/web.d.ts +107 -0
  368. package/dist/toolkit/web.js +147 -0
  369. package/dist/tools/define.d.ts +25 -0
  370. package/dist/tools/define.js +45 -0
  371. package/dist/tools/delegating.d.ts +132 -0
  372. package/dist/tools/delegating.js +211 -0
  373. package/dist/tools/index.d.ts +129 -0
  374. package/dist/tools/index.js +33 -0
  375. package/dist/tools/library/compute.d.ts +11 -0
  376. package/dist/tools/library/compute.js +46 -0
  377. package/dist/tools/library/data.d.ts +16 -0
  378. package/dist/tools/library/data.js +92 -0
  379. package/dist/tools/library/http.d.ts +28 -0
  380. package/dist/tools/library/http.js +71 -0
  381. package/dist/tools/library/index.d.ts +97 -0
  382. package/dist/tools/library/index.js +134 -0
  383. package/dist/tools/library/knowledge.d.ts +39 -0
  384. package/dist/tools/library/knowledge.js +58 -0
  385. package/dist/tools/library/web.d.ts +19 -0
  386. package/dist/tools/library/web.js +65 -0
  387. package/dist/tools/meta-tools.d.ts +19 -0
  388. package/dist/tools/meta-tools.js +36 -0
  389. package/dist/tools/registry.d.ts +146 -0
  390. package/dist/tools/registry.js +291 -0
  391. package/dist/usage/index.d.ts +105 -0
  392. package/dist/usage/index.js +20 -0
  393. package/dist/usage/quota.d.ts +258 -0
  394. package/dist/usage/quota.js +510 -0
  395. package/dist/usage/recorder.d.ts +29 -0
  396. package/dist/usage/recorder.js +96 -0
  397. package/dist/usage/rollups.d.ts +121 -0
  398. package/dist/usage/rollups.js +157 -0
  399. package/dist/worker/export.d.ts +57 -0
  400. package/dist/worker/export.js +81 -0
  401. package/dist/worker/extraction.d.ts +57 -0
  402. package/dist/worker/extraction.js +84 -0
  403. package/dist/worker/main.d.ts +103 -0
  404. package/dist/worker/main.js +159 -0
  405. package/package.json +187 -0
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Built-in meta-tools — `docs/03-intelligence-runtime.md` → Tool registry.
3
+ *
4
+ * These are always present and never provider-supplied. They are the model's interface to the
5
+ * two-tier tool system: a compact catalog sits in context, and the model uses `learn_tools` to pull
6
+ * a schema, `execute_tool` to run one, and `read_tool_output` to fetch a result that was spilled to
7
+ * blob storage. `load_skill` and `ask_questions` are handled by their own subsystems (skills / HITL);
8
+ * their descriptors live here so the catalog advertises them uniformly.
9
+ *
10
+ * `request_approval` is the odd one out, and its description says so. The model does not have to call
11
+ * it: the run path raises the approval itself when the gate refuses a call
12
+ * (`../hitl/approved-execution.ts`), which is the safer arrangement — a model that *forgot* to ask
13
+ * would otherwise be a model that published without asking. It stays in the catalog because the doc
14
+ * names it and because a model that announces the ask reads better than one that silently stalls.
15
+ */
16
+ const meta = (name, label, description) => ({
17
+ name,
18
+ label,
19
+ description,
20
+ category: "meta",
21
+ inputSchema: {},
22
+ outputSchema: {},
23
+ effect: "read",
24
+ approvalPolicy: "never",
25
+ requiresIdempotencyKey: false,
26
+ });
27
+ export const META_TOOL_DESCRIPTORS = {
28
+ learn_tools: meta("learn_tools", "Learn tools", "Fetch the full input/output schemas for named tools before using them."),
29
+ execute_tool: meta("execute_tool", "Execute tool", "Run a tool by name with validated input; authorization is rechecked at execution."),
30
+ load_skill: meta("load_skill", "Load skill", "Load a named skill's instructions into context on demand."),
31
+ ask_questions: meta("ask_questions", "Ask questions", "Ask the user consequential questions that cannot be resolved from context or tools."),
32
+ request_approval: meta("request_approval", "Request approval", "Request human approval before a policy-classified action such as publishing or sending. The platform also raises this automatically when a gated tool is called without approval, so a call is never performed unapproved because this was not used."),
33
+ read_tool_output: meta("read_tool_output", "Read tool output", "Read back a large tool result that was spilled to storage and referenced."),
34
+ };
35
+ export const META_TOOL_DESCRIPTOR_LIST = Object.values(META_TOOL_DESCRIPTORS);
36
+ //# sourceMappingURL=meta-tools.js.map
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Tool registry runtime — `docs/03-intelligence-runtime.md` → Tool registry.
3
+ *
4
+ * Builds the permission-filtered compact catalog, resolves lazy schemas via `learn_tools`, and
5
+ * executes tools with the guarantees the spec demands:
6
+ *
7
+ * - **Only task-relevant schemas enter context.** The catalog is compact (no schemas); only
8
+ * preloaded tools carry schemas up front, and everything else is fetched on demand.
9
+ * - **Unauthorized tools are unlearnable and unexecutable.** Discovery, `learn_tools` and
10
+ * `execute_tool` all go through the same `AuthorizationPolicy`, so a tool the caller may not use
11
+ * is absent from the catalog, omitted from `learn`, and rejected if executed directly.
12
+ * - **Re-auth + re-validate at execution**, even when the tool was discoverable earlier.
13
+ * - **Shared success/error envelope**, and **large results are spilled** to blob storage and
14
+ * referenced, read back through `read_tool_output`.
15
+ * - **External/destructive writes require an idempotency key**, so a retried call returns the first
16
+ * result instead of firing the side effect twice.
17
+ */
18
+ import type { ExecutionContext } from "../core/context.js";
19
+ import type { BlobRef } from "../core/ids.js";
20
+ import { type AuthorizationPolicy } from "../authorization/index.js";
21
+ import { type IdempotencyStore } from "../idempotency/index.js";
22
+ import type { BlobStore } from "../persistence/index.js";
23
+ import type { OneTimeApprovalRef, ShadowRecorder, ToolCatalogEntry, ToolDescriptor, ToolProvider, ToolResult } from "./index.js";
24
+ /** Validates a tool input against its (opaque) `inputSchema`. Default duck-types a zod schema. */
25
+ export interface SchemaValidator {
26
+ validate(schema: unknown, value: unknown): {
27
+ ok: true;
28
+ value: unknown;
29
+ } | {
30
+ ok: false;
31
+ message: string;
32
+ };
33
+ }
34
+ /** Default validator: run a zod-like schema's `safeParse`; pass through anything else (tool self-validates). */
35
+ export declare const zodishValidator: SchemaValidator;
36
+ export type ToolPolicyView = {
37
+ readonly preloaded: readonly string[];
38
+ readonly categories: readonly string[];
39
+ readonly excluded: readonly string[];
40
+ };
41
+ export type ToolCatalog = {
42
+ /** Preloaded tools carry full schemas — commonly required, loaded up front. */
43
+ readonly preloaded: readonly ToolDescriptor[];
44
+ /** Everything else the caller may use — compact entries, schemas fetched via `learn_tools`. */
45
+ readonly discoverable: readonly ToolCatalogEntry[];
46
+ /** Always-present meta-tools. */
47
+ readonly meta: readonly ToolCatalogEntry[];
48
+ };
49
+ /** Structural approval check (satisfied by the HITL `ApprovalGate`) — kept structural to avoid a
50
+ * tools→hitl dependency. Returns false when the tool needs approval and the call carries neither a
51
+ * standing grant nor a valid one-time approval. */
52
+ export interface ApprovalCheck {
53
+ isAllowed(context: ExecutionContext, tool: {
54
+ readonly name: string;
55
+ readonly category: string;
56
+ readonly approvalPolicy: ApprovalPolicyValue;
57
+ },
58
+ /** The single approved execution this call is, when it is one. Verified by the implementation. */
59
+ oneTime?: OneTimeApprovalRef): Promise<boolean>;
60
+ }
61
+ type ApprovalPolicyValue = "never" | "policy" | "always";
62
+ /**
63
+ * A tool that can never run, and why — #162.
64
+ *
65
+ * One type for both fail-closed layers, because wiring one and not the other is precisely the case that
66
+ * misled in #155: the report has to say *which* layer is unwired, or it sends the reader to the wrong file.
67
+ *
68
+ * `kind` is a union with one arm today rather than a bare string, so a second class of unrunnable tool has an
69
+ * obvious place to go and an exhaustive switch over it keeps compiling.
70
+ */
71
+ export type ToolMisconfiguration = {
72
+ readonly kind: "approval-check-missing";
73
+ readonly layer: "registry" | "delegating-envelope";
74
+ readonly toolName: string;
75
+ readonly approvalPolicy: string;
76
+ /** The exact field the reader has to set, named so the report is actionable without a grep. */
77
+ readonly configField: string;
78
+ } | {
79
+ /**
80
+ * Two providers offering the same tool name — #188.
81
+ *
82
+ * Found when the first-party tool library became a second first-party provider. `findAuthorized` takes the
83
+ * **first** match, so a provider listed earlier silently shadows a later one: the catalogue shows the name
84
+ * twice, possibly with different descriptions and different effects, and execution picks one of them with
85
+ * nothing recording which. A `read` tool shadowing an `external-write` tool of the same name is an
86
+ * unapproved write; the reverse is a read that suddenly needs a human.
87
+ *
88
+ * MCP-imported tools are namespaced `mcp__<server>__<tool>` precisely so a remote server cannot do this.
89
+ * Nothing was stopping two local providers.
90
+ */
91
+ readonly kind: "duplicate-tool-name";
92
+ readonly layer: "registry";
93
+ readonly toolName: string;
94
+ readonly providerIds: readonly string[];
95
+ readonly configField: string;
96
+ };
97
+ export type ToolRegistryConfig = {
98
+ readonly providers: readonly ToolProvider[];
99
+ readonly authorization: AuthorizationPolicy;
100
+ readonly idempotency?: IdempotencyStore;
101
+ readonly blobs?: BlobStore;
102
+ /** Makes approval unbypassable: a policy-classified tool cannot execute directly without a grant. */
103
+ readonly approval?: ApprovalCheck;
104
+ /**
105
+ * Where "this tool can never run" is reported — #162.
106
+ *
107
+ * Optional, and its absence costs diagnosability rather than safety: the refusal still happens either way,
108
+ * and it still carries a message naming the tool and this config field. What the sink adds is a report at
109
+ * the *first* such call rather than one per call, which is the difference between noticing a wiring bug and
110
+ * reading the same refusal a hundred times.
111
+ *
112
+ * Called at most once per tool name per registry.
113
+ */
114
+ readonly onMisconfiguration?: (report: ToolMisconfiguration) => void;
115
+ /** Results whose JSON exceeds this are spilled to `blobs` and referenced. Default 8 KiB. */
116
+ readonly maxInlineOutputBytes?: number;
117
+ readonly validator?: SchemaValidator;
118
+ /**
119
+ * Where a shadow run's suppressed writes go (#126).
120
+ *
121
+ * Here as well as on the delegating envelope, and the registry's is the one that matters. #126 put
122
+ * suppression only in the envelope, which covers **delegating tools only** — so a gated tool that is not
123
+ * one, every MCP-imported external write included, reached its own `execute` and performed a real write
124
+ * in a shadow run. That is a bigger hole than the missing parity record the approval-loop work found.
125
+ *
126
+ * Required when the run says it is shadow: `context.shadow === true` with no recorder is refused rather
127
+ * than performed, the same fail-closed rule as the envelope's.
128
+ */
129
+ readonly shadow?: ShadowRecorder;
130
+ };
131
+ export interface ToolRegistry {
132
+ catalog(context: ExecutionContext, policy: ToolPolicyView): Promise<ToolCatalog>;
133
+ learn(context: ExecutionContext, names: readonly string[]): Promise<readonly ToolDescriptor[]>;
134
+ execute(context: ExecutionContext, input: {
135
+ name: string;
136
+ input: unknown;
137
+ idempotencyKey?: string;
138
+ toolCallId?: string;
139
+ /** Present when this call is the execution a human approved; see `OneTimeApprovalRef`. */
140
+ approval?: OneTimeApprovalRef;
141
+ }): Promise<ToolResult>;
142
+ readOutput(context: ExecutionContext, ref: BlobRef): Promise<ToolResult>;
143
+ }
144
+ export declare const createToolRegistry: (config: ToolRegistryConfig) => ToolRegistry;
145
+ export {};
146
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1,291 @@
1
+ /**
2
+ * Tool registry runtime — `docs/03-intelligence-runtime.md` → Tool registry.
3
+ *
4
+ * Builds the permission-filtered compact catalog, resolves lazy schemas via `learn_tools`, and
5
+ * executes tools with the guarantees the spec demands:
6
+ *
7
+ * - **Only task-relevant schemas enter context.** The catalog is compact (no schemas); only
8
+ * preloaded tools carry schemas up front, and everything else is fetched on demand.
9
+ * - **Unauthorized tools are unlearnable and unexecutable.** Discovery, `learn_tools` and
10
+ * `execute_tool` all go through the same `AuthorizationPolicy`, so a tool the caller may not use
11
+ * is absent from the catalog, omitted from `learn`, and rejected if executed directly.
12
+ * - **Re-auth + re-validate at execution**, even when the tool was discoverable earlier.
13
+ * - **Shared success/error envelope**, and **large results are spilled** to blob storage and
14
+ * referenced, read back through `read_tool_output`.
15
+ * - **External/destructive writes require an idempotency key**, so a retried call returns the first
16
+ * result instead of firing the side effect twice.
17
+ */
18
+ import { assertToolAuthorized } from "../authorization/index.js";
19
+ import { deriveIdempotencyKey } from "../idempotency/index.js";
20
+ import { META_TOOL_DESCRIPTOR_LIST } from "./meta-tools.js";
21
+ /** Default validator: run a zod-like schema's `safeParse`; pass through anything else (tool self-validates). */
22
+ export const zodishValidator = {
23
+ validate(schema, value) {
24
+ const parse = schema
25
+ ?.safeParse;
26
+ if (typeof parse !== "function")
27
+ return { ok: true, value };
28
+ const result = parse(value);
29
+ return result.success
30
+ ? { ok: true, value: result.data }
31
+ : { ok: false, message: result.error?.message ?? "input failed schema validation" };
32
+ },
33
+ };
34
+ const compact = (d) => ({
35
+ name: d.name,
36
+ label: d.label,
37
+ description: d.description,
38
+ category: d.category,
39
+ effect: d.effect,
40
+ });
41
+ const invalidInput = (message) => ({ code: "invalid_input", message, retryable: false });
42
+ /** A wiring problem, not a caller problem: retrying the identical call cannot help. */
43
+ const capabilityUnavailable = (message) => ({
44
+ code: "capability_unavailable",
45
+ message,
46
+ retryable: false,
47
+ });
48
+ const requiresKey = (effect, requires) => requires || effect === "external-write" || effect === "destructive";
49
+ export const createToolRegistry = (config) => {
50
+ const maxInline = config.maxInlineOutputBytes ?? 8 * 1024;
51
+ const validator = config.validator ?? zodishValidator;
52
+ /**
53
+ * Reported once per tool, not once per call — #162 AC-2.
54
+ *
55
+ * A construction-time scan is not possible: `ToolProvider.listTools` takes an `ExecutionContext`, so which
56
+ * gated tools exist is not knowable until a request is being served. First encounter is therefore the
57
+ * earliest honest moment to say so, and the memo is what keeps it from becoming per-call noise.
58
+ */
59
+ const reported = new Set();
60
+ const reportMisconfiguration = (d) => {
61
+ if (config.onMisconfiguration === undefined || reported.has(d.name))
62
+ return;
63
+ reported.add(d.name);
64
+ config.onMisconfiguration({
65
+ kind: "approval-check-missing",
66
+ layer: "registry",
67
+ toolName: d.name,
68
+ approvalPolicy: d.approvalPolicy,
69
+ configField: "ToolRegistryConfig.approval",
70
+ });
71
+ };
72
+ /**
73
+ * Names offered by more than one provider, remembered so `execute` can say why it refused.
74
+ *
75
+ * Per registry rather than per call: which tools exist depends on the context, so a name can be ambiguous for
76
+ * one caller and fine for another, but a name that was ever ambiguous is a wiring bug worth reporting once.
77
+ */
78
+ const ambiguous = new Map();
79
+ /** Resolve every tool the caller could use, then keep only the authorized, unambiguous ones. */
80
+ const authorizedTools = async (context) => {
81
+ const all = [];
82
+ const providersByName = new Map();
83
+ for (const provider of config.providers) {
84
+ for (const tool of await provider.listTools(context)) {
85
+ all.push(tool);
86
+ providersByName.set(tool.descriptor.name, [...(providersByName.get(tool.descriptor.name) ?? []), provider.id]);
87
+ }
88
+ }
89
+ /**
90
+ * A duplicated name is **dropped, not resolved**.
91
+ *
92
+ * Picking one is the behaviour this replaces, and the problem with it is that both choices are defensible
93
+ * and neither is visible: first-wins hides the second tool, last-wins hides the first, and either way the
94
+ * catalogue and the executor can disagree about what a name means. Refusing makes the wiring bug loud at
95
+ * the cost of one tool, which is the right trade for a name whose meaning is genuinely unknown.
96
+ */
97
+ const duplicated = new Set();
98
+ for (const [name, providerIds] of providersByName) {
99
+ if (providerIds.length <= 1)
100
+ continue;
101
+ duplicated.add(name);
102
+ if (!ambiguous.has(name)) {
103
+ ambiguous.set(name, providerIds);
104
+ config.onMisconfiguration?.({
105
+ kind: "duplicate-tool-name",
106
+ layer: "registry",
107
+ toolName: name,
108
+ providerIds,
109
+ configField: "ToolRegistryConfig.providers",
110
+ });
111
+ }
112
+ }
113
+ const usable = all.filter((t) => !duplicated.has(t.descriptor.name));
114
+ const descriptors = usable.map((t) => t.descriptor);
115
+ const permitted = new Set((await config.authorization.filterTools(context, descriptors)).map((d) => d.name));
116
+ return usable.filter((t) => permitted.has(t.descriptor.name));
117
+ };
118
+ const findAuthorized = async (context, name) => (await authorizedTools(context)).find((t) => t.descriptor.name === name) ?? null;
119
+ return {
120
+ async catalog(context, policy) {
121
+ const excluded = new Set(policy.excluded);
122
+ const preloadNames = new Set(policy.preloaded);
123
+ const preloadCategories = new Set(policy.categories);
124
+ const tools = (await authorizedTools(context)).filter((t) => !excluded.has(t.descriptor.name));
125
+ const preloaded = [];
126
+ const discoverable = [];
127
+ for (const tool of tools) {
128
+ const d = tool.descriptor;
129
+ if (preloadNames.has(d.name) || preloadCategories.has(d.category))
130
+ preloaded.push(d);
131
+ else
132
+ discoverable.push(compact(d));
133
+ }
134
+ return { preloaded, discoverable, meta: META_TOOL_DESCRIPTOR_LIST.map(compact) };
135
+ },
136
+ async learn(context, names) {
137
+ // Only authorized tools are returned — an unauthorized name is silently unlearnable.
138
+ const wanted = new Set(names);
139
+ return (await authorizedTools(context)).map((t) => t.descriptor).filter((d) => wanted.has(d.name));
140
+ },
141
+ async execute(context, input) {
142
+ const tool = await findAuthorized(context, input.name);
143
+ // Not found OR not authorized → both reject; execution is never a way around discovery filtering.
144
+ if (!tool) {
145
+ const providerIds = ambiguous.get(input.name);
146
+ if (providerIds !== undefined) {
147
+ // Named precisely, because "unknown tool" would send a reader looking for a missing registration when
148
+ // the actual problem is two of them.
149
+ return {
150
+ ok: false,
151
+ error: capabilityUnavailable(`Tool ${input.name} is offered by more than one provider (${providerIds.join(", ")}), so which one ` +
152
+ `runs is undefined. Rename or remove one — see ToolRegistryConfig.providers.`),
153
+ };
154
+ }
155
+ await assertToolAuthorized(config.authorization, context, { name: input.name, category: "unknown" });
156
+ return { ok: false, error: invalidInput(`Unknown tool ${input.name}`) };
157
+ }
158
+ const d = tool.descriptor;
159
+ // Re-authorize at execution even though it was discoverable earlier.
160
+ await assertToolAuthorized(config.authorization, context, { name: d.name, category: d.category });
161
+ // Shadow mode, and **before** the approval gate (#126).
162
+ //
163
+ // Before it for the reason #126 gave: a shadow run must not ask a human to approve something that
164
+ // will not happen, because that teaches people approving is meaningless. And *here* rather than only
165
+ // in the envelope, because the envelope covers delegating tools and this covers every tool — an
166
+ // MCP-imported external write is gated, is not a delegating tool, and would otherwise execute for
167
+ // real in a shadow run.
168
+ //
169
+ // Suppressed on the effect, not on the approval policy: a `destructive` tool whose policy someone
170
+ // set to `never` is still something a shadow run must not do.
171
+ if (context.shadow === true && (d.effect === "external-write" || d.effect === "destructive")) {
172
+ if (!config.shadow)
173
+ return {
174
+ ok: false,
175
+ error: {
176
+ code: "capability_unavailable",
177
+ message: `Tool ${d.name} is a ${d.effect} and this run is in shadow mode with no recorder configured`,
178
+ retryable: false,
179
+ },
180
+ };
181
+ // Validated first, so what is recorded is what would have been sent rather than what the model
182
+ // typed. The gate has not run, so this is the earliest point the input is trustworthy.
183
+ const shadowValidated = validator.validate(d.inputSchema, input.input);
184
+ if (!shadowValidated.ok)
185
+ return { ok: false, error: invalidInput(`Invalid input for ${d.name}: ${shadowValidated.message}`) };
186
+ await config.shadow.record(context, {
187
+ ...(context.runId === undefined ? {} : { runId: context.runId }),
188
+ toolName: d.name,
189
+ // A non-delegating tool wraps nothing, and saying so is more useful than an empty string.
190
+ delegatesTo: d.delegatesTo ?? `${d.name} (not a delegating tool)`,
191
+ effect: d.effect,
192
+ input: shadowValidated.value,
193
+ idempotencyKey: (input.idempotencyKey ?? `shadow:${d.name}`),
194
+ wouldRequireApproval: d.approvalPolicy !== "never",
195
+ });
196
+ // Not stored under the idempotency key: a suppressed call must not become the cached answer for a
197
+ // later real one.
198
+ return { ok: true, data: { suppressed: true, reason: "shadow-mode", wouldHaveCalled: d.name } };
199
+ }
200
+ // Approval gate: a policy-classified tool cannot be executed directly without a standing grant.
201
+ // Fail CLOSED — if no approval check is wired, a policy/always tool (e.g. every MCP external
202
+ // write) is refused rather than silently executed unapproved.
203
+ if (d.approvalPolicy !== "never") {
204
+ /**
205
+ * The two refusals are told apart — #162.
206
+ *
207
+ * Both used to be `approval_required: Tool <name> requires approval`: the correct refusal of a call
208
+ * nobody approved, and a registry with no approval check at all, where *nothing* could ever be
209
+ * approved. #155 lost two debugging rounds to that, and filed #158 against the platform for a bug
210
+ * that was its own missing wiring — fixing the envelope's gate changed nothing observable, because
211
+ * this second layer was still refusing with the identical message, which made the wrong diagnosis
212
+ * look confirmed.
213
+ *
214
+ * The safety behaviour is untouched: absent check still means refused. Only the story changes.
215
+ */
216
+ if (config.approval === undefined) {
217
+ reportMisconfiguration(d);
218
+ return {
219
+ ok: false,
220
+ error: {
221
+ code: "capability_unavailable",
222
+ message: `Tool ${d.name} has approvalPolicy "${d.approvalPolicy}" and no approval check is configured ` +
223
+ `(ToolRegistryConfig.approval), so it can never run. This is a wiring error, not a refusal.`,
224
+ retryable: false,
225
+ },
226
+ };
227
+ }
228
+ const allowed = await config.approval.isAllowed(context, { name: d.name, category: d.category, approvalPolicy: d.approvalPolicy }, input.approval);
229
+ if (!allowed)
230
+ return { ok: false, error: { code: "approval_required", message: `Tool ${d.name} requires approval`, retryable: false } };
231
+ }
232
+ // Re-validate input against the descriptor's schema.
233
+ const validated = validator.validate(d.inputSchema, input.input);
234
+ if (!validated.ok)
235
+ return { ok: false, error: invalidInput(`Invalid input for ${d.name}: ${validated.message}`) };
236
+ // External/destructive writes must carry an idempotency key.
237
+ let idempotencyKey = input.idempotencyKey;
238
+ if (idempotencyKey === undefined && input.toolCallId !== undefined && context.runId !== undefined) {
239
+ idempotencyKey = deriveIdempotencyKey({
240
+ tenantId: context.tenantId,
241
+ runId: context.runId,
242
+ toolCallId: input.toolCallId,
243
+ });
244
+ }
245
+ if (requiresKey(d.effect, d.requiresIdempotencyKey) && idempotencyKey === undefined) {
246
+ return { ok: false, error: invalidInput(`Tool ${d.name} (${d.effect}) requires an idempotency key`) };
247
+ }
248
+ // Replay: a retried idempotent call returns the stored result instead of re-firing.
249
+ if (idempotencyKey !== undefined && config.idempotency) {
250
+ const prior = await config.idempotency.get({ tenantId: context.tenantId, key: idempotencyKey });
251
+ if (prior && !prior.firstSeen)
252
+ return prior.result;
253
+ }
254
+ const result = await tool.execute({
255
+ context,
256
+ input: validated.value,
257
+ ...(idempotencyKey ? { idempotencyKey } : {}),
258
+ ...(input.approval ? { approval: input.approval } : {}),
259
+ });
260
+ const spilled = await maybeSpill(context, result);
261
+ if (idempotencyKey !== undefined && config.idempotency) {
262
+ await config.idempotency.put({ tenantId: context.tenantId, key: idempotencyKey, result: spilled });
263
+ }
264
+ return spilled;
265
+ },
266
+ async readOutput(context, ref) {
267
+ if (!config.blobs)
268
+ return { ok: false, error: invalidInput("blob storage is not configured") };
269
+ const value = await config.blobs.get({ tenantId: context.tenantId, ref });
270
+ if (value === null)
271
+ return { ok: false, error: { code: "not_found", message: `No spilled output ${ref}`, retryable: false } };
272
+ return { ok: true, data: value };
273
+ },
274
+ };
275
+ /** Spill an oversize success payload to blob storage and reference it. */
276
+ async function maybeSpill(context, result) {
277
+ if (!result.ok || result.spilledOutputRef !== undefined)
278
+ return result;
279
+ const bytes = Buffer.byteLength(JSON.stringify(result.data ?? null), "utf8");
280
+ if (bytes <= maxInline || !config.blobs)
281
+ return result;
282
+ const ref = await config.blobs.put({ tenantId: context.tenantId, value: result.data });
283
+ return {
284
+ ok: true,
285
+ data: { truncated: true, byteSize: bytes, note: "Result spilled; read it with read_tool_output." },
286
+ spilledOutputRef: ref,
287
+ truncated: true,
288
+ };
289
+ }
290
+ };
291
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Usage recording port — `docs/12-usage-and-accounting.md`. **Frozen v1.**
3
+ *
4
+ * The runtime records usage from the day it exists (REQ-005); rollups, quotas and reporting are
5
+ * built on top in REQ-013 without reopening the runtime. Shape only here.
6
+ */
7
+ import type { ExecutionContext } from "../core/context.js";
8
+ import type { ConversationId, PrincipalId, RunId } from "../core/ids.js";
9
+ import type { ModelPricing } from "../models/index.js";
10
+ export type UsageEvent = {
11
+ readonly id: string;
12
+ readonly tenantId: string;
13
+ /**
14
+ * Who consumed it — #175.
15
+ *
16
+ * A usage record carried a tenant and no principal, so "what has this person spent" was unanswerable: the data
17
+ * was never recorded. Per-user metrics and per-user limits both start here.
18
+ *
19
+ * Stamped by the recorder from the **trusted context**, never from the event payload — the same rule `tenantId`
20
+ * follows, and for the same reason: a caller that could name the principal on a usage event could bill someone
21
+ * else's budget.
22
+ *
23
+ * Optional on the type, because rows written before this exist and a record with an unknown principal is a
24
+ * fact rather than a thing to invent. It is nullable in storage for that reason too.
25
+ */
26
+ readonly principalId?: PrincipalId;
27
+ readonly conversationId?: ConversationId;
28
+ readonly runId: RunId;
29
+ readonly stepId?: string;
30
+ readonly toolCallId?: string;
31
+ readonly modelId: string;
32
+ readonly inputTokens: number;
33
+ readonly outputTokens: number;
34
+ readonly cachedInputTokens: number;
35
+ readonly reasoningTokens?: number;
36
+ /**
37
+ * Non-text input this turn carried — #185 AC-4.
38
+ *
39
+ * Absent means "not counted", not "none". A row written before the count existed and a genuinely text-only
40
+ * turn are different facts, and a zero would merge them.
41
+ */
42
+ readonly imageCount?: number;
43
+ readonly audioSeconds?: number;
44
+ /** Integer minor units in the tenant's accounting currency. */
45
+ readonly costMinorUnits: number;
46
+ readonly currency: string;
47
+ readonly occurredAt: string;
48
+ };
49
+ /**
50
+ * The key an append is idempotent on: `(runId, stepId)` when a step is known, else the event id.
51
+ *
52
+ * Lives here rather than in an adapter so every adapter dedupes identically **by construction**. The
53
+ * reference adapter owned a private copy of this, which meant "both adapters agree" was a
54
+ * coincidence — the same situation `DEFAULT_SESSION_STATE_MAX_BYTES` was in before #97 moved it to
55
+ * the port. A recovered run re-recording a step it already logged must be a no-op in every adapter,
56
+ * because the alternative is double-counting real money.
57
+ */
58
+ export declare const usageDedupeKey: (event: Pick<UsageEvent, "id" | "runId"> & {
59
+ readonly stepId?: string;
60
+ }) => string;
61
+ /** What a caller supplies; the recorder stamps `id`, `tenantId` and `occurredAt`. */
62
+ /**
63
+ * What a caller supplies. `id`, `tenantId`, `principalId` and `occurredAt` are the recorder's to stamp.
64
+ *
65
+ * `principalId` moved into that set by #175: identity comes from the execution context, so accepting it here
66
+ * would be accepting a claim about whose budget to charge.
67
+ */
68
+ export type UsageEventInput = Omit<UsageEvent, "id" | "tenantId" | "principalId" | "occurredAt">;
69
+ export type CostEstimate = {
70
+ readonly modelId: string;
71
+ readonly inputTokens: number;
72
+ readonly maxOutputTokens: number;
73
+ };
74
+ export type Reservation = {
75
+ readonly id: string;
76
+ /** False when the estimate would exceed a run or tenant ceiling. */
77
+ readonly withinCeiling: boolean;
78
+ };
79
+ export interface UsageRecorder {
80
+ /** Append a usage event for a realized step. Append-only and idempotent on `(runId, stepId)`. */
81
+ record(context: ExecutionContext, event: UsageEventInput): Promise<void>;
82
+ /** Pre-flight ceiling check before a provider call, against the run's remaining budget. */
83
+ reserve(context: ExecutionContext, estimate: CostEstimate): Promise<Reservation>;
84
+ }
85
+ /** Per-run cost/token ceiling (from `ExecutionLimits`, doc 04). Any field omitted is unbounded. */
86
+ export type UsageCeiling = {
87
+ readonly costMinorUnits?: number;
88
+ readonly inputTokens?: number;
89
+ readonly outputTokens?: number;
90
+ };
91
+ /**
92
+ * Provider-aware token estimate used for budgeting and pre-flight ceiling checks (doc 03/12).
93
+ * Actuals from the provider response are authoritative and reconcile these estimates afterwards.
94
+ */
95
+ export interface TokenCounter {
96
+ estimate(text: string): number;
97
+ }
98
+ /** Resolves a model's pricing at execution time so cost is computed from live rates, not guesses. */
99
+ export interface PricingResolver {
100
+ resolve(modelId: string): ModelPricing | null;
101
+ }
102
+ export * from "./recorder.js";
103
+ export * from "./quota.js";
104
+ export * from "./rollups.js";
105
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Usage recording port — `docs/12-usage-and-accounting.md`. **Frozen v1.**
3
+ *
4
+ * The runtime records usage from the day it exists (REQ-005); rollups, quotas and reporting are
5
+ * built on top in REQ-013 without reopening the runtime. Shape only here.
6
+ */
7
+ /**
8
+ * The key an append is idempotent on: `(runId, stepId)` when a step is known, else the event id.
9
+ *
10
+ * Lives here rather than in an adapter so every adapter dedupes identically **by construction**. The
11
+ * reference adapter owned a private copy of this, which meant "both adapters agree" was a
12
+ * coincidence — the same situation `DEFAULT_SESSION_STATE_MAX_BYTES` was in before #97 moved it to
13
+ * the port. A recovered run re-recording a step it already logged must be a no-op in every adapter,
14
+ * because the alternative is double-counting real money.
15
+ */
16
+ export const usageDedupeKey = (event) => (event.stepId === undefined ? event.id : `${event.runId}:${event.stepId}`);
17
+ export * from "./recorder.js";
18
+ export * from "./quota.js";
19
+ export * from "./rollups.js";
20
+ //# sourceMappingURL=index.js.map