@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,253 @@
1
+ /**
2
+ * Thin GraphQL resolvers — `docs/06` → "Resolvers are thin: authenticate, validate, construct
3
+ * execution context and call platform services." The host's GraphQL server builds the execution
4
+ * context (from its auth) and puts it on the resolver context; every resolver here just validates
5
+ * shape and delegates to a service. No business logic lives in this layer.
6
+ */
7
+ import { DEFAULT_WARN_AT, describeWindow } from "../usage/index.js";
8
+ import { asId } from "../core/ids.js";
9
+ import { startOrEnqueueRun } from "../runtime/index.js";
10
+ import { openRunEventStream } from "../runtime/index.js";
11
+ /** Serialize a stored Run to the GraphQL RunStatus enum (underscores, not hyphens). */
12
+ const runStatus = (status) => status.replace(/-/g, "_");
13
+ /**
14
+ * `conversationId` is nullable here since #198 — a run can belong to no conversation.
15
+ *
16
+ * Null, never a placeholder. A client that receives an empty string or a synthetic id would key a cache by it
17
+ * and group unrelated automations together.
18
+ */
19
+ const toRun = (run) => ({
20
+ id: run.id,
21
+ conversationId: run.conversationId,
22
+ status: runStatus(run.status),
23
+ createdAt: run.createdAt,
24
+ finishedAt: run.finishedAt ?? null,
25
+ });
26
+ export const createResolvers = (deps) => {
27
+ const channelFor = deps.channelFor ?? ((id) => `conversation:${id}`);
28
+ const tid = (ctx) => ctx.execution.tenantId;
29
+ /**
30
+ * The quota state, from the guard rather than recomputed.
31
+ *
32
+ * Asking the guard means the panel's warning and the admission decision are the same computation. A UI that
33
+ * recomputed a threshold would eventually show "you are fine" while a run is being refused, which is worse
34
+ * than showing nothing.
35
+ */
36
+ const quotaViewFor = async (guard, execution) => {
37
+ const decision = await guard.admit(execution);
38
+ const limits = await guard.limits(execution);
39
+ if (limits.length === 0)
40
+ return null;
41
+ /**
42
+ * The **binding** limit, which is the first — shortest span (#182).
43
+ *
44
+ * Several limits can apply at once and this view describes one, because that is the shape the schema has and
45
+ * a client rendering "you have used X of Y" wants the Y that will stop them soonest. `usageReport` is the
46
+ * wrong place to widen: a caller that wants all of them should ask for all of them.
47
+ */
48
+ const binding = limits[0];
49
+ return {
50
+ window: describeWindow(binding.window),
51
+ // Null for a rolling window: no calendar period describes one, and naming the closest would be wrong
52
+ // rather than approximate.
53
+ period: binding.window.kind === "calendar" ? binding.window.period : null,
54
+ modelId: binding.modelId ?? null,
55
+ costLimitMinorUnits: binding.costMinorUnits ?? null,
56
+ inputTokenLimit: binding.inputTokens ?? null,
57
+ outputTokenLimit: binding.outputTokens ?? null,
58
+ warnAt: binding.warnAt ?? DEFAULT_WARN_AT,
59
+ warning: decision.admitted && decision.warnings.length > 0,
60
+ exceeded: !decision.admitted,
61
+ };
62
+ };
63
+ return {
64
+ Query: {
65
+ async conversations(_, args, ctx) {
66
+ return deps.conversations.list({ tenantId: tid(ctx), limit: args.limit, ...(args.cursor ? { cursor: args.cursor } : {}) });
67
+ },
68
+ async conversation(_, args, ctx) {
69
+ return deps.conversations.findById({ tenantId: tid(ctx), id: asId(args.id) });
70
+ },
71
+ async run(_, args, ctx) {
72
+ const run = await deps.runs.findById({ tenantId: tid(ctx), id: asId(args.id) });
73
+ return run ? toRun(run) : null;
74
+ },
75
+ async toolCatalog(_, args, ctx) {
76
+ return deps.toolRegistry.catalog(ctx.execution, args);
77
+ },
78
+ async usage(_, args, ctx) {
79
+ return deps.usage.totals({ tenantId: tid(ctx), ...(args.runId ? { runId: asId(args.runId) } : {}) });
80
+ },
81
+ /**
82
+ * The spend panel's one query (#140).
83
+ *
84
+ * Headline totals and buckets come from the **rollups**, so a page load never scans raw records however
85
+ * much a tenant has used. Breakdowns come from the ledger over the same bounded range — a deliberate
86
+ * trade documented on `UsageStore.breakdown`.
87
+ *
88
+ * Everything in one resolver so a panel cannot show a total from one moment and a breakdown from another;
89
+ * the discrepancy would look like a bug in the numbers rather than in the fetching.
90
+ */
91
+ async usageReport(_, args, ctx) {
92
+ const period = args.period === "hour" ? "hour" : "day";
93
+ const limit = Math.min(Math.max(1, args.breakdownLimit ?? 10), 50);
94
+ const scope = { tenantId: tid(ctx), period, from: args.from, to: args.to };
95
+ // Absent rollup support is not an error: a deployment can run without the rollup job and still answer
96
+ // from the ledger. Reported as empty buckets rather than a failure, because a panel with no chart is
97
+ // usable and a panel with an error is not.
98
+ const buckets = deps.rollups === undefined ? { items: [] } : await deps.rollups.list({ ...scope, limit: 400 });
99
+ const totals = deps.rollups === undefined
100
+ ? await deps.usage.totals({ tenantId: tid(ctx) })
101
+ : await deps.rollups.sum(scope);
102
+ const [byModel, byConversation] = await Promise.all([
103
+ deps.usage.breakdown({ tenantId: tid(ctx), from: args.from, to: args.to, by: "model", limit }),
104
+ deps.usage.breakdown({ tenantId: tid(ctx), from: args.from, to: args.to, by: "conversation", limit }),
105
+ ]);
106
+ // The quota state as the *server* computes it, so a UI cannot disagree with the enforcement. Absent
107
+ // when no limit is configured, which means unbounded — a UI must show "no limit" rather than a full bar.
108
+ const quota = deps.quota === undefined ? null : await quotaViewFor(deps.quota, ctx.execution);
109
+ return {
110
+ period,
111
+ from: args.from,
112
+ to: args.to,
113
+ totals,
114
+ buckets: buckets.items.map((b) => ({
115
+ bucketStart: b.bucketStart,
116
+ currency: b.currency,
117
+ totals: b,
118
+ })),
119
+ byModel,
120
+ byConversation,
121
+ quota,
122
+ // The currency of the buckets in range. Empty when there is no usage — a period with no spend has no
123
+ // currency, and claiming one would be inventing a fact for a UI to format with.
124
+ currency: buckets.items.find((b) => b.currency !== "")?.currency ?? "",
125
+ };
126
+ },
127
+ /**
128
+ * #163. Shaped for rendering: the optional fields are filled in rather than passed through, because a
129
+ * client that has to treat `null` as "one choice" and `undefined` as "one choice" and `false` as "one
130
+ * choice" will eventually treat one of them as "several".
131
+ */
132
+ async pendingQuestion(_, args, ctx) {
133
+ const question = await deps.questions.pending({ tenantId: tid(ctx), runId: asId(args.runId) });
134
+ if (question === null)
135
+ return null;
136
+ return {
137
+ interactionId: question.id,
138
+ runId: question.runId,
139
+ createdAt: question.createdAt,
140
+ questions: question.questions.map((q) => ({
141
+ key: q.key,
142
+ prompt: q.prompt,
143
+ options: q.options ?? [],
144
+ multiple: q.multiple === true,
145
+ // Free text with no options is the only sensible reading of a question that offers no choices, so
146
+ // it is implied there rather than left to each client to infer.
147
+ allowOther: q.allowOther === true || (q.options ?? []).length === 0,
148
+ })),
149
+ };
150
+ },
151
+ /** #163, the mirror of `pendingQuestion`. Wired the same way so the two cannot drift. */
152
+ async pendingApproval(_, args, ctx) {
153
+ const approval = await deps.approvals.pending({ tenantId: tid(ctx), runId: asId(args.runId) });
154
+ if (approval === null)
155
+ return null;
156
+ return {
157
+ interactionId: approval.id,
158
+ runId: approval.runId,
159
+ toolName: approval.toolName,
160
+ summary: approval.summary,
161
+ riskCategory: approval.riskCategory,
162
+ expiresAt: approval.expiresAt,
163
+ normalizedInput: approval.normalizedInput,
164
+ };
165
+ },
166
+ async conversationContext(_, args, ctx) {
167
+ if (!deps.inspectContext)
168
+ return null;
169
+ return deps.inspectContext(ctx.execution, {
170
+ conversationId: asId(args.conversationId),
171
+ ...(args.runId ? { runId: asId(args.runId) } : {}),
172
+ });
173
+ },
174
+ },
175
+ Mutation: {
176
+ async createConversation(_, args, ctx) {
177
+ return deps.conversations.create({ tenantId: tid(ctx), id: asId(args.id), title: args.title });
178
+ },
179
+ async renameConversation(_, args, ctx) {
180
+ return deps.conversations.update({ tenantId: tid(ctx), id: asId(args.id), expectedVersion: args.expectedVersion, patch: { title: args.title } });
181
+ },
182
+ async archiveConversation(_, args, ctx) {
183
+ return deps.conversations.update({ tenantId: tid(ctx), id: asId(args.id), expectedVersion: args.expectedVersion, patch: { archivedAt: new Date().toISOString() } });
184
+ },
185
+ async deleteConversation(_, args, ctx) {
186
+ await deps.conversations.softDelete({ tenantId: tid(ctx), id: asId(args.id) });
187
+ return true;
188
+ },
189
+ async sendMessage(_, args, ctx) {
190
+ const conversationId = asId(args.conversationId);
191
+ const runId = asId(args.runId);
192
+ // #139, AC-2: the quota check is *here*, before the conversation is claimed and before anything is
193
+ // enqueued — so a refused run leaves no slot held, no job on the queue, and no partial answer. A limit
194
+ // enforced mid-run leaves a half-written response and a user who has to guess whether to retry.
195
+ //
196
+ // Optional, because a deployment with no limits configured is valid; when it is absent nothing is
197
+ // checked, which is the same as an unbounded limit.
198
+ if (deps.quota !== undefined)
199
+ await deps.quota.assertAdmitted(ctx.execution);
200
+ const started = await startOrEnqueueRun(deps.coordinator, { tenantId: tid(ctx), conversationId, runId });
201
+ if (started === "started")
202
+ await deps.dispatcher.enqueueRun({ tenantId: tid(ctx), runId });
203
+ const run = await deps.runs.findById({ tenantId: tid(ctx), id: runId });
204
+ return run ? toRun(run) : { id: runId, conversationId, status: started === "started" ? "running" : "queued", createdAt: new Date().toISOString(), finishedAt: null };
205
+ },
206
+ async cancelRun(_, args, ctx) {
207
+ await deps.runs.requestCancel({ tenantId: tid(ctx), id: asId(args.runId), now: new Date().toISOString() });
208
+ return true;
209
+ },
210
+ async answerQuestion(_, args, ctx) {
211
+ const { resumed } = await deps.questions.answer({
212
+ tenantId: tid(ctx),
213
+ interactionId: asId(args.input.interactionId),
214
+ runId: asId(args.input.runId),
215
+ answers: args.input.answers,
216
+ });
217
+ return resumed;
218
+ },
219
+ async decideApproval(_, args, ctx) {
220
+ const { resumed } = await deps.approvals.decide({
221
+ tenantId: tid(ctx),
222
+ interactionId: asId(args.input.interactionId),
223
+ runId: asId(args.input.runId),
224
+ decision: args.input.decision,
225
+ });
226
+ return resumed;
227
+ },
228
+ },
229
+ Subscription: {
230
+ runEvents: {
231
+ subscribe(_, args, ctx) {
232
+ return openRunEventStream({
233
+ tenantId: tid(ctx),
234
+ runId: asId(args.runId),
235
+ channel: channelFor(asId(args.conversationId)),
236
+ after: args.after ?? 0,
237
+ log: deps.eventLog,
238
+ live: deps.live,
239
+ });
240
+ },
241
+ // The transport delivers each event as { runEvents: { type, runId, sequence, occurredAt, payload } }.
242
+ resolve: (event) => ({
243
+ type: event.type,
244
+ runId: event.runId,
245
+ sequence: event.sequence,
246
+ occurredAt: event.occurredAt,
247
+ payload: event,
248
+ }),
249
+ },
250
+ },
251
+ };
252
+ };
253
+ //# sourceMappingURL=resolvers.js.map
@@ -0,0 +1,11 @@
1
+ /**
2
+ * GraphQL schema (SDL) — `docs/06-graphql-and-frontend.md` → GraphQL boundary.
3
+ *
4
+ * The package ships the schema as SDL plus a thin resolver map (see `./resolvers`), so a host can
5
+ * mount it on any GraphQL server (Yoga, Apollo, Mercurius) without the library taking a server
6
+ * dependency. Resolvers stay thin: authenticate, validate, build the execution context, call a
7
+ * platform service. Subscriptions carry the stable `RunEvent` set and support resuming after a
8
+ * cursor via `openRunEventStream`.
9
+ */
10
+ export declare const typeDefs = "\n scalar JSON\n scalar DateTime\n\n type Conversation {\n id: ID!\n title: String!\n version: Int!\n archivedAt: DateTime\n createdAt: DateTime!\n updatedAt: DateTime!\n }\n\n type ConversationPage {\n items: [Conversation!]!\n nextCursor: String\n }\n\n enum RunStatus {\n queued\n running\n waiting_for_question\n waiting_for_approval\n retry_pending\n completed\n failed\n cancelled\n }\n\n type Run {\n id: ID!\n \"Null for a run that belongs to no conversation \u2014 a triggered automation rather than a chat turn (#198).\"\n conversationId: ID\n status: RunStatus!\n createdAt: DateTime!\n finishedAt: DateTime\n }\n\n type ToolCatalogEntry {\n name: String!\n label: String!\n description: String!\n category: String!\n effect: String!\n }\n\n type ToolCatalog {\n preloaded: [JSON!]!\n discoverable: [ToolCatalogEntry!]!\n meta: [ToolCatalogEntry!]!\n }\n\n type UsageTotals {\n inputTokens: Int!\n outputTokens: Int!\n cachedInputTokens: Int!\n costMinorUnits: Int!\n eventCount: Int!\n }\n\n \"One period's consumption. #139's rollups, so a chart never scans raw records.\"\n type UsageBucket {\n bucketStart: String!\n totals: UsageTotals!\n currency: String!\n }\n\n \"Consumption grouped by model or conversation over the requested range.\"\n type UsageBreakdownEntry {\n key: String!\n totals: UsageTotals!\n }\n\n \"\"\"\n Where the tenant stands against its limit.\n\n Absent when no limit is configured \u2014 which means unbounded, not zero. A UI must show \"no limit set\"\n rather than a full bar.\n \"\"\"\n type UsageQuota {\n \"\"\"\n The window in words \u2014 \"the day\", \"any 5 hours\" (#181).\n\n period stayed for the calendar case and is **null** for a rolling window, because no RollupPeriod describes\n one and returning \"hour\" for a five-hour window would be a wrong answer rather than a missing one. A client\n rendering the window reads this field; one keying a chart by bucket reads period and correctly finds nothing\n to key by.\n \"\"\"\n window: String!\n period: String\n \"The model this limit covers, or null for any model (#182).\"\n modelId: String\n costLimitMinorUnits: Int\n inputTokenLimit: Int\n outputTokenLimit: Int\n \"The fraction of the limit at which a warning shows. Sent so the UI cannot disagree with the server.\"\n warnAt: Float!\n \"True once any dimension is past warnAt and still admitted.\"\n warning: Boolean!\n \"True once any dimension has reached its limit, so work is being refused.\"\n exceeded: Boolean!\n }\n\n \"\"\"\n The usage report a spend panel renders.\n\n One query rather than several, so a panel cannot show a total from one moment and a breakdown from another.\n \"\"\"\n type UsageReport {\n period: String!\n from: String!\n to: String!\n totals: UsageTotals!\n buckets: [UsageBucket!]!\n byModel: [UsageBreakdownEntry!]!\n byConversation: [UsageBreakdownEntry!]!\n quota: UsageQuota\n currency: String!\n }\n\n \"A single transport event; payload carries the typed part / lifecycle detail.\"\n type RunEvent {\n type: String!\n runId: ID!\n sequence: Int!\n occurredAt: DateTime!\n payload: JSON!\n }\n\n \"\"\"\n One question put to a person, as it must be *rendered* \u2014 #163.\n\n The event that suspends a run carries only an interactionId, deliberately: events are thin, and a payload\n that duplicated the question would be a second copy to keep in step with the stored one. But nothing exposed\n the stored one either, so a client could answer a question it had no way to display. The example's picker\n rendered an empty text box next to \"The assistant has a question\", which is the whole gap in one screenshot.\n \"\"\"\n type PendingQuestionSpec {\n \"Stable key the answer is filed under.\"\n key: String!\n prompt: String!\n \"A short closed list, when there is one. Empty means free text.\"\n options: [String!]!\n \"Several choices are allowed, not one.\"\n multiple: Boolean!\n \"Free text is accepted alongside the options.\"\n allowOther: Boolean!\n }\n\n type PendingQuestion {\n interactionId: ID!\n runId: ID!\n questions: [PendingQuestionSpec!]!\n createdAt: DateTime!\n }\n\n \"\"\"\n The approval a run is parked on \u2014 the read side of decideApproval (#163).\n\n The same gap as pendingQuestion and milder rather than absent: approval.requested also carries only an\n interaction id, so a client had no summary to show and fell back to a generic \"Run a tool?\". Asking someone\n to authorise an action the card cannot name is how approval becomes a reflex.\n \"\"\"\n type PendingApprovalDetail {\n interactionId: ID!\n runId: ID!\n toolName: String!\n \"One line a person can decide on, written by the host's summarizer.\"\n summary: String!\n riskCategory: String!\n expiresAt: DateTime!\n \"The arguments the approval is for, so what runs is what was shown.\"\n normalizedInput: JSON!\n }\n\n input QuestionAnswerInput {\n interactionId: ID!\n runId: ID!\n answers: JSON!\n }\n\n input ApprovalDecisionInput {\n interactionId: ID!\n runId: ID!\n decision: String!\n }\n\n \"A section that shaped a turn's prompt \u2014 for the context inspector (#39).\"\n type InspectedSection {\n title: String!\n providerId: String!\n kind: String!\n provenance: String!\n estimatedTokens: Int!\n sensitivity: String!\n included: Boolean!\n prunedReason: String\n }\n\n type ContextInspection {\n sections: [InspectedSection!]!\n totalTokens: Int!\n budget: JSON!\n }\n\n type Query {\n conversations(limit: Int!, cursor: String): ConversationPage!\n conversation(id: ID!): Conversation\n run(id: ID!): Run\n toolCatalog(preloaded: [String!]!, categories: [String!]!, excluded: [String!]!): ToolCatalog!\n usage(runId: ID): UsageTotals!\n \"\"\"\n Consumption and cost by period, with breakdowns and quota state (#140).\n\n An extension of the usage query rather than a second endpoint: a panel showing a total from one query and a\n breakdown from another can show two moments at once, and the discrepancy looks like a bug in the numbers.\n \"\"\"\n usageReport(period: String!, from: String!, to: String!, breakdownLimit: Int): UsageReport!\n \"What context shaped a turn \u2014 attributes memory/tools/history that influenced the prompt.\"\n conversationContext(conversationId: ID!, runId: ID): ContextInspection\n \"\"\"\n The question a run is parked on, or null \u2014 the read side of answerQuestion (#163).\n\n Null covers both \"this run was never asked anything\" and \"it has been answered already\", because a client\n has the same thing to do in either case: show no picker. A run that is waiting is the only state with a\n question to render.\n \"\"\"\n pendingQuestion(runId: ID!): PendingQuestion\n \"The approval a run is parked on, or null (#163).\"\n pendingApproval(runId: ID!): PendingApprovalDetail\n }\n\n type Mutation {\n createConversation(id: ID!, title: String!): Conversation!\n renameConversation(id: ID!, expectedVersion: Int!, title: String!): Conversation!\n archiveConversation(id: ID!, expectedVersion: Int!): Conversation!\n deleteConversation(id: ID!): Boolean!\n sendMessage(conversationId: ID!, runId: ID!): Run!\n cancelRun(runId: ID!): Boolean!\n answerQuestion(input: QuestionAnswerInput!): Boolean!\n decideApproval(input: ApprovalDecisionInput!): Boolean!\n }\n\n type Subscription {\n \"Conversation/run events, resumable after a cursor (sequence).\"\n runEvents(runId: ID!, conversationId: ID!, after: Int): RunEvent!\n }\n";
11
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1,258 @@
1
+ /**
2
+ * GraphQL schema (SDL) — `docs/06-graphql-and-frontend.md` → GraphQL boundary.
3
+ *
4
+ * The package ships the schema as SDL plus a thin resolver map (see `./resolvers`), so a host can
5
+ * mount it on any GraphQL server (Yoga, Apollo, Mercurius) without the library taking a server
6
+ * dependency. Resolvers stay thin: authenticate, validate, build the execution context, call a
7
+ * platform service. Subscriptions carry the stable `RunEvent` set and support resuming after a
8
+ * cursor via `openRunEventStream`.
9
+ */
10
+ export const typeDefs = /* GraphQL */ `
11
+ scalar JSON
12
+ scalar DateTime
13
+
14
+ type Conversation {
15
+ id: ID!
16
+ title: String!
17
+ version: Int!
18
+ archivedAt: DateTime
19
+ createdAt: DateTime!
20
+ updatedAt: DateTime!
21
+ }
22
+
23
+ type ConversationPage {
24
+ items: [Conversation!]!
25
+ nextCursor: String
26
+ }
27
+
28
+ enum RunStatus {
29
+ queued
30
+ running
31
+ waiting_for_question
32
+ waiting_for_approval
33
+ retry_pending
34
+ completed
35
+ failed
36
+ cancelled
37
+ }
38
+
39
+ type Run {
40
+ id: ID!
41
+ "Null for a run that belongs to no conversation — a triggered automation rather than a chat turn (#198)."
42
+ conversationId: ID
43
+ status: RunStatus!
44
+ createdAt: DateTime!
45
+ finishedAt: DateTime
46
+ }
47
+
48
+ type ToolCatalogEntry {
49
+ name: String!
50
+ label: String!
51
+ description: String!
52
+ category: String!
53
+ effect: String!
54
+ }
55
+
56
+ type ToolCatalog {
57
+ preloaded: [JSON!]!
58
+ discoverable: [ToolCatalogEntry!]!
59
+ meta: [ToolCatalogEntry!]!
60
+ }
61
+
62
+ type UsageTotals {
63
+ inputTokens: Int!
64
+ outputTokens: Int!
65
+ cachedInputTokens: Int!
66
+ costMinorUnits: Int!
67
+ eventCount: Int!
68
+ }
69
+
70
+ "One period's consumption. #139's rollups, so a chart never scans raw records."
71
+ type UsageBucket {
72
+ bucketStart: String!
73
+ totals: UsageTotals!
74
+ currency: String!
75
+ }
76
+
77
+ "Consumption grouped by model or conversation over the requested range."
78
+ type UsageBreakdownEntry {
79
+ key: String!
80
+ totals: UsageTotals!
81
+ }
82
+
83
+ """
84
+ Where the tenant stands against its limit.
85
+
86
+ Absent when no limit is configured — which means unbounded, not zero. A UI must show "no limit set"
87
+ rather than a full bar.
88
+ """
89
+ type UsageQuota {
90
+ """
91
+ The window in words — "the day", "any 5 hours" (#181).
92
+
93
+ period stayed for the calendar case and is **null** for a rolling window, because no RollupPeriod describes
94
+ one and returning "hour" for a five-hour window would be a wrong answer rather than a missing one. A client
95
+ rendering the window reads this field; one keying a chart by bucket reads period and correctly finds nothing
96
+ to key by.
97
+ """
98
+ window: String!
99
+ period: String
100
+ "The model this limit covers, or null for any model (#182)."
101
+ modelId: String
102
+ costLimitMinorUnits: Int
103
+ inputTokenLimit: Int
104
+ outputTokenLimit: Int
105
+ "The fraction of the limit at which a warning shows. Sent so the UI cannot disagree with the server."
106
+ warnAt: Float!
107
+ "True once any dimension is past warnAt and still admitted."
108
+ warning: Boolean!
109
+ "True once any dimension has reached its limit, so work is being refused."
110
+ exceeded: Boolean!
111
+ }
112
+
113
+ """
114
+ The usage report a spend panel renders.
115
+
116
+ One query rather than several, so a panel cannot show a total from one moment and a breakdown from another.
117
+ """
118
+ type UsageReport {
119
+ period: String!
120
+ from: String!
121
+ to: String!
122
+ totals: UsageTotals!
123
+ buckets: [UsageBucket!]!
124
+ byModel: [UsageBreakdownEntry!]!
125
+ byConversation: [UsageBreakdownEntry!]!
126
+ quota: UsageQuota
127
+ currency: String!
128
+ }
129
+
130
+ "A single transport event; payload carries the typed part / lifecycle detail."
131
+ type RunEvent {
132
+ type: String!
133
+ runId: ID!
134
+ sequence: Int!
135
+ occurredAt: DateTime!
136
+ payload: JSON!
137
+ }
138
+
139
+ """
140
+ One question put to a person, as it must be *rendered* — #163.
141
+
142
+ The event that suspends a run carries only an interactionId, deliberately: events are thin, and a payload
143
+ that duplicated the question would be a second copy to keep in step with the stored one. But nothing exposed
144
+ the stored one either, so a client could answer a question it had no way to display. The example's picker
145
+ rendered an empty text box next to "The assistant has a question", which is the whole gap in one screenshot.
146
+ """
147
+ type PendingQuestionSpec {
148
+ "Stable key the answer is filed under."
149
+ key: String!
150
+ prompt: String!
151
+ "A short closed list, when there is one. Empty means free text."
152
+ options: [String!]!
153
+ "Several choices are allowed, not one."
154
+ multiple: Boolean!
155
+ "Free text is accepted alongside the options."
156
+ allowOther: Boolean!
157
+ }
158
+
159
+ type PendingQuestion {
160
+ interactionId: ID!
161
+ runId: ID!
162
+ questions: [PendingQuestionSpec!]!
163
+ createdAt: DateTime!
164
+ }
165
+
166
+ """
167
+ The approval a run is parked on — the read side of decideApproval (#163).
168
+
169
+ The same gap as pendingQuestion and milder rather than absent: approval.requested also carries only an
170
+ interaction id, so a client had no summary to show and fell back to a generic "Run a tool?". Asking someone
171
+ to authorise an action the card cannot name is how approval becomes a reflex.
172
+ """
173
+ type PendingApprovalDetail {
174
+ interactionId: ID!
175
+ runId: ID!
176
+ toolName: String!
177
+ "One line a person can decide on, written by the host's summarizer."
178
+ summary: String!
179
+ riskCategory: String!
180
+ expiresAt: DateTime!
181
+ "The arguments the approval is for, so what runs is what was shown."
182
+ normalizedInput: JSON!
183
+ }
184
+
185
+ input QuestionAnswerInput {
186
+ interactionId: ID!
187
+ runId: ID!
188
+ answers: JSON!
189
+ }
190
+
191
+ input ApprovalDecisionInput {
192
+ interactionId: ID!
193
+ runId: ID!
194
+ decision: String!
195
+ }
196
+
197
+ "A section that shaped a turn's prompt — for the context inspector (#39)."
198
+ type InspectedSection {
199
+ title: String!
200
+ providerId: String!
201
+ kind: String!
202
+ provenance: String!
203
+ estimatedTokens: Int!
204
+ sensitivity: String!
205
+ included: Boolean!
206
+ prunedReason: String
207
+ }
208
+
209
+ type ContextInspection {
210
+ sections: [InspectedSection!]!
211
+ totalTokens: Int!
212
+ budget: JSON!
213
+ }
214
+
215
+ type Query {
216
+ conversations(limit: Int!, cursor: String): ConversationPage!
217
+ conversation(id: ID!): Conversation
218
+ run(id: ID!): Run
219
+ toolCatalog(preloaded: [String!]!, categories: [String!]!, excluded: [String!]!): ToolCatalog!
220
+ usage(runId: ID): UsageTotals!
221
+ """
222
+ Consumption and cost by period, with breakdowns and quota state (#140).
223
+
224
+ An extension of the usage query rather than a second endpoint: a panel showing a total from one query and a
225
+ breakdown from another can show two moments at once, and the discrepancy looks like a bug in the numbers.
226
+ """
227
+ usageReport(period: String!, from: String!, to: String!, breakdownLimit: Int): UsageReport!
228
+ "What context shaped a turn — attributes memory/tools/history that influenced the prompt."
229
+ conversationContext(conversationId: ID!, runId: ID): ContextInspection
230
+ """
231
+ The question a run is parked on, or null — the read side of answerQuestion (#163).
232
+
233
+ Null covers both "this run was never asked anything" and "it has been answered already", because a client
234
+ has the same thing to do in either case: show no picker. A run that is waiting is the only state with a
235
+ question to render.
236
+ """
237
+ pendingQuestion(runId: ID!): PendingQuestion
238
+ "The approval a run is parked on, or null (#163)."
239
+ pendingApproval(runId: ID!): PendingApprovalDetail
240
+ }
241
+
242
+ type Mutation {
243
+ createConversation(id: ID!, title: String!): Conversation!
244
+ renameConversation(id: ID!, expectedVersion: Int!, title: String!): Conversation!
245
+ archiveConversation(id: ID!, expectedVersion: Int!): Conversation!
246
+ deleteConversation(id: ID!): Boolean!
247
+ sendMessage(conversationId: ID!, runId: ID!): Run!
248
+ cancelRun(runId: ID!): Boolean!
249
+ answerQuestion(input: QuestionAnswerInput!): Boolean!
250
+ decideApproval(input: ApprovalDecisionInput!): Boolean!
251
+ }
252
+
253
+ type Subscription {
254
+ "Conversation/run events, resumable after a cursor (sequence)."
255
+ runEvents(runId: ID!, conversationId: ID!, after: Int): RunEvent!
256
+ }
257
+ `;
258
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1,77 @@
1
+ /**
2
+ * SSE transport adapter — `docs/06` (embedded-profile streaming). A thin mapping from the
3
+ * transport-neutral `RunEvent` stream to Server-Sent Events frames. It takes no HTTP-framework
4
+ * dependency: `sseFrames` yields ready-to-write text frames, and `openRunEventSse` composes the
5
+ * reconnect stream (catch-up + live) with SSE encoding. The `Last-Event-ID` header a browser
6
+ * resends on reconnect maps directly to the run event `sequence`, so resuming loses no events.
7
+ */
8
+ import type { RunEvent, RunEventLog } from "../core/events.js";
9
+ import type { ConversationId, RunId, TenantId } from "../core/ids.js";
10
+ import { type LiveEventSource } from "../runtime/index.js";
11
+ /**
12
+ * The GraphQL field the frames are shaped for.
13
+ *
14
+ * Hard-coded to match the SDL's `runEvents` subscription, because that is the selection a client made.
15
+ * A client that *aliased* the field would look for its alias and not find it — see the open question
16
+ * on #111; the adapter has no way to know the alias.
17
+ */
18
+ export declare const SSE_RESULT_FIELD = "runEvents";
19
+ /**
20
+ * Encode one event as a graphql-sse `next` frame.
21
+ *
22
+ * `docs/extraction/twenty-sdk-comparison.md` records the decision: *"Match the `graphql-sse` framing
23
+ * rather than inventing a bespoke SSE protocol"* — twenty-sdk already streams GraphQL over graphql-sse,
24
+ * so a client can consume this unmodified. This previously emitted `event: <RunEvent.type>` with a raw
25
+ * `RunEvent` as `data`, which no graphql-sse client understands.
26
+ *
27
+ * The `id:` line keeps carrying `RunEvent.sequence`, which is what makes `Last-Event-ID` resume work.
28
+ *
29
+ * **A failed run is a `next` frame, not an error frame**, and that is deliberate. `run.failed` is a
30
+ * durable event with a sequence, sitting in the log like any other. Delivering it as a protocol-level
31
+ * error would leave it with no `id:` — so `Last-Event-ID` could not resume past it, and a reconnecting
32
+ * client would never learn the run ended. An `ExecutionResult` may carry both `data` and `errors`, so
33
+ * the event travels in `data` and the platform error in `errors`: clients surface it through their
34
+ * normal error path (which is what AC-3 is for) and resume keeps working.
35
+ */
36
+ export declare const toSseFrame: (event: RunEvent) => string;
37
+ /**
38
+ * The terminating frame.
39
+ *
40
+ * graphql-sse's distinct-connections mode uses `event: complete` to say the response is finished. A
41
+ * stream that simply stops is indistinguishable from a truncated one, and a client cannot tell whether
42
+ * to reconnect.
43
+ */
44
+ export declare const SSE_COMPLETE_FRAME = "event: complete\ndata: \n\n";
45
+ /**
46
+ * A stream-level failure, in the protocol's error shape.
47
+ *
48
+ * Distinct from a failed *run*: there is no sequence to preserve and nothing to resume to, so this is
49
+ * genuinely a protocol error rather than an event.
50
+ */
51
+ export declare const sseErrorFrame: (message: string) => string;
52
+ /** Parse a browser `Last-Event-ID` header into a resume cursor. Missing/invalid ⇒ 0 (from start). */
53
+ export declare const cursorFromLastEventId: (lastEventId: string | null | undefined) => number;
54
+ /**
55
+ * Map a `RunEvent` async stream to graphql-sse text frames, terminated by `complete`.
56
+ *
57
+ * The `complete` frame is emitted in a `finally`, so it is sent whether the stream ended on a terminal
58
+ * event or because the consumer stopped — a client should be told the response is over either way.
59
+ */
60
+ export declare function sseFrames(events: AsyncIterable<RunEvent>): AsyncIterable<string>;
61
+ /**
62
+ * Open a resumable SSE stream for a run: catch up from the durable log after `after`, then follow
63
+ * live, encoded as SSE frames. Ends on the run's terminal event.
64
+ */
65
+ export declare const openRunEventSse: (input: {
66
+ readonly tenantId: TenantId;
67
+ readonly runId: RunId;
68
+ readonly conversationId: ConversationId;
69
+ readonly after: number;
70
+ readonly log: RunEventLog;
71
+ readonly live: LiveEventSource;
72
+ readonly channelFor?: (conversationId: ConversationId) => string;
73
+ readonly signal?: {
74
+ readonly aborted: boolean;
75
+ };
76
+ }) => AsyncIterable<string>;
77
+ //# sourceMappingURL=sse.d.ts.map