gemi 0.59.0 → 0.61.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 (237) hide show
  1. package/dist/ai/Agent.d.ts +533 -25
  2. package/dist/ai/Agent.d.ts.map +1 -1
  3. package/dist/ai/Agent.test-d.d.ts +2 -0
  4. package/dist/ai/Agent.test-d.d.ts.map +1 -0
  5. package/dist/ai/AgentController.d.ts +275 -6
  6. package/dist/ai/AgentController.d.ts.map +1 -1
  7. package/dist/ai/AgentProvider.d.ts +255 -0
  8. package/dist/ai/AgentProvider.d.ts.map +1 -0
  9. package/dist/ai/Schema.d.ts +125 -0
  10. package/dist/ai/Schema.d.ts.map +1 -0
  11. package/dist/ai/Schema.test-d.d.ts +2 -0
  12. package/dist/ai/Schema.test-d.d.ts.map +1 -0
  13. package/dist/ai/client/index.d.ts +24 -0
  14. package/dist/ai/client/index.d.ts.map +1 -0
  15. package/dist/ai/client/index.js +1053 -0
  16. package/dist/ai/client/index.js.map +1 -0
  17. package/dist/ai/client/reducer.d.ts +127 -0
  18. package/dist/ai/client/reducer.d.ts.map +1 -0
  19. package/dist/ai/client/reducer.test-d.d.ts +2 -0
  20. package/dist/ai/client/reducer.test-d.d.ts.map +1 -0
  21. package/dist/ai/client/sse.d.ts +54 -0
  22. package/dist/ai/client/sse.d.ts.map +1 -0
  23. package/dist/ai/example.d.ts +129 -0
  24. package/dist/ai/example.d.ts.map +1 -0
  25. package/dist/ai/index.d.ts +35 -0
  26. package/dist/ai/index.d.ts.map +1 -0
  27. package/dist/ai/index.js +20 -0
  28. package/dist/ai/index.js.map +23 -0
  29. package/dist/ai/live/harness.d.ts +137 -0
  30. package/dist/ai/live/harness.d.ts.map +1 -0
  31. package/dist/ai/providers/call.d.ts +42 -0
  32. package/dist/ai/providers/call.d.ts.map +1 -0
  33. package/dist/ai/providers/capabilities.d.ts +50 -0
  34. package/dist/ai/providers/capabilities.d.ts.map +1 -0
  35. package/dist/ai/providers/errors.d.ts +37 -0
  36. package/dist/ai/providers/errors.d.ts.map +1 -0
  37. package/dist/ai/providers/fakeProvider.d.ts +35 -0
  38. package/dist/ai/providers/fakeProvider.d.ts.map +1 -0
  39. package/dist/ai/providers/http.d.ts +46 -0
  40. package/dist/ai/providers/http.d.ts.map +1 -0
  41. package/dist/ai/providers/request.d.ts +69 -0
  42. package/dist/ai/providers/request.d.ts.map +1 -0
  43. package/dist/ai/providers/stream.d.ts +42 -0
  44. package/dist/ai/providers/stream.d.ts.map +1 -0
  45. package/dist/ai/signing.d.ts +195 -0
  46. package/dist/ai/signing.d.ts.map +1 -0
  47. package/dist/ai/store/LiveRuns.d.ts +142 -0
  48. package/dist/ai/store/LiveRuns.d.ts.map +1 -0
  49. package/dist/ai/store/MemoryAgentStore.d.ts +61 -0
  50. package/dist/ai/store/MemoryAgentStore.d.ts.map +1 -0
  51. package/dist/ai/store/index.d.ts +4 -0
  52. package/dist/ai/store/index.d.ts.map +1 -0
  53. package/dist/ai/store/sse.d.ts +58 -0
  54. package/dist/ai/store/sse.d.ts.map +1 -0
  55. package/dist/ai/store/stubAgentRun.d.ts +56 -0
  56. package/dist/ai/store/stubAgentRun.d.ts.map +1 -0
  57. package/dist/ai/types.d.ts +443 -0
  58. package/dist/ai/types.d.ts.map +1 -0
  59. package/dist/ai/useChat.d.ts +253 -7
  60. package/dist/ai/useChat.d.ts.map +1 -1
  61. package/dist/bin/gemi.js +500 -16
  62. package/dist/bin/gemi.js.map +10 -5
  63. package/dist/chunk-1aqzcgfr.js +5 -0
  64. package/dist/chunk-1aqzcgfr.js.map +10 -0
  65. package/dist/{chunk-get4mkx8.js → chunk-1b7e9rj7.js} +2 -2
  66. package/dist/{chunk-get4mkx8.js.map → chunk-1b7e9rj7.js.map} +1 -1
  67. package/dist/{chunk-gfma8e03.js → chunk-3aemqfdr.js} +2 -2
  68. package/dist/{chunk-gfma8e03.js.map → chunk-3aemqfdr.js.map} +1 -1
  69. package/dist/{chunk-j06g4sqc.js → chunk-528n3vgy.js} +2 -2
  70. package/dist/{chunk-j06g4sqc.js.map → chunk-528n3vgy.js.map} +1 -1
  71. package/dist/{chunk-2khdxyjb.js → chunk-57a0nqfj.js} +1 -1
  72. package/dist/chunk-57a0nqfj.js.map +10 -0
  73. package/dist/{chunk-c40n5r4v.js → chunk-5mhcwnyd.js} +2 -2
  74. package/dist/{chunk-c40n5r4v.js.map → chunk-5mhcwnyd.js.map} +1 -1
  75. package/dist/{chunk-gwchvzdp.js → chunk-71pk1mxx.js} +2 -2
  76. package/dist/{chunk-gwchvzdp.js.map → chunk-71pk1mxx.js.map} +1 -1
  77. package/dist/{chunk-spbgpndn.js → chunk-7t1hjs9f.js} +2 -2
  78. package/dist/{chunk-spbgpndn.js.map → chunk-7t1hjs9f.js.map} +1 -1
  79. package/dist/{chunk-9gsdcjt7.js → chunk-7xvaace2.js} +3 -3
  80. package/dist/{chunk-9gsdcjt7.js.map → chunk-7xvaace2.js.map} +1 -1
  81. package/dist/{chunk-fxy42w6n.js → chunk-8ag0da2s.js} +2 -2
  82. package/dist/{chunk-fxy42w6n.js.map → chunk-8ag0da2s.js.map} +1 -1
  83. package/dist/chunk-8r8epsef.js +5 -0
  84. package/dist/chunk-8r8epsef.js.map +11 -0
  85. package/dist/chunk-91cj3nxk.js +6 -0
  86. package/dist/{chunk-txhcx69q.js.map → chunk-91cj3nxk.js.map} +2 -2
  87. package/dist/{chunk-0fm6jh9b.js → chunk-9nmvm20t.js} +2 -2
  88. package/dist/{chunk-0fm6jh9b.js.map → chunk-9nmvm20t.js.map} +1 -1
  89. package/dist/{chunk-98a3k7bp.js → chunk-9xpa7dpy.js} +2 -2
  90. package/dist/{chunk-98a3k7bp.js.map → chunk-9xpa7dpy.js.map} +1 -1
  91. package/dist/{chunk-qva4841r.js → chunk-a1exbqcq.js} +3 -3
  92. package/dist/{chunk-qva4841r.js.map → chunk-a1exbqcq.js.map} +1 -1
  93. package/dist/{chunk-cw9y6k15.js → chunk-bb19bwg6.js} +2 -2
  94. package/dist/{chunk-cw9y6k15.js.map → chunk-bb19bwg6.js.map} +1 -1
  95. package/dist/{chunk-3gvjn3q4.js → chunk-cf7bvd12.js} +1 -1
  96. package/dist/{chunk-rkbv3df7.js → chunk-djp2xeqe.js} +2 -2
  97. package/dist/{chunk-rkbv3df7.js.map → chunk-djp2xeqe.js.map} +1 -1
  98. package/dist/chunk-ds44bqr9.js +4 -0
  99. package/dist/{chunk-4mcyyh1v.js.map → chunk-ds44bqr9.js.map} +4 -9
  100. package/dist/{chunk-wzvs3sym.js → chunk-exndjhza.js} +3 -3
  101. package/dist/{chunk-wzvs3sym.js.map → chunk-exndjhza.js.map} +1 -1
  102. package/dist/{chunk-f6dd4gd8.js → chunk-f233yzxf.js} +2 -2
  103. package/dist/{chunk-f6dd4gd8.js.map → chunk-f233yzxf.js.map} +1 -1
  104. package/dist/chunk-fz5g2z6h.js +4 -0
  105. package/dist/{chunk-fbvvqf9b.js.map → chunk-fz5g2z6h.js.map} +2 -2
  106. package/dist/{chunk-vj9538yn.js → chunk-gcszdwcb.js} +2 -2
  107. package/dist/{chunk-vj9538yn.js.map → chunk-gcszdwcb.js.map} +1 -1
  108. package/dist/{chunk-pkjq9833.js → chunk-htesx7ym.js} +4 -4
  109. package/dist/{chunk-pkjq9833.js.map → chunk-htesx7ym.js.map} +1 -1
  110. package/dist/chunk-hyxmmj9b.js +5 -0
  111. package/dist/{chunk-n412aa9s.js.map → chunk-hyxmmj9b.js.map} +2 -2
  112. package/dist/{chunk-stq96kya.js → chunk-k2sjvt0c.js} +2 -2
  113. package/dist/{chunk-stq96kya.js.map → chunk-k2sjvt0c.js.map} +1 -1
  114. package/dist/{chunk-zhbrkpb3.js → chunk-k75phgj4.js} +4 -4
  115. package/dist/{chunk-zhbrkpb3.js.map → chunk-k75phgj4.js.map} +1 -1
  116. package/dist/{chunk-y64j80v9.js → chunk-m0tp7zjp.js} +2 -2
  117. package/dist/{chunk-y64j80v9.js.map → chunk-m0tp7zjp.js.map} +1 -1
  118. package/dist/{chunk-06j6rsew.js → chunk-m45j7p1y.js} +2 -2
  119. package/dist/{chunk-06j6rsew.js.map → chunk-m45j7p1y.js.map} +1 -1
  120. package/dist/chunk-mca9wsvs.js +5 -0
  121. package/dist/{chunk-z2tcxwyr.js.map → chunk-mca9wsvs.js.map} +3 -4
  122. package/dist/{chunk-tey1xayb.js → chunk-ms13evzp.js} +2 -2
  123. package/dist/{chunk-tey1xayb.js.map → chunk-ms13evzp.js.map} +1 -1
  124. package/dist/{chunk-bn1v4sfs.js → chunk-r962ae93.js} +2 -2
  125. package/dist/{chunk-bn1v4sfs.js.map → chunk-r962ae93.js.map} +1 -1
  126. package/dist/{chunk-23h0dmx2.js → chunk-s41ees18.js} +2 -2
  127. package/dist/{chunk-23h0dmx2.js.map → chunk-s41ees18.js.map} +1 -1
  128. package/dist/chunk-snb68dgr.js +4 -0
  129. package/dist/{chunk-hwhw98hc.js.map → chunk-snb68dgr.js.map} +1 -1
  130. package/dist/chunk-sz051605.js +5 -0
  131. package/dist/chunk-sz051605.js.map +14 -0
  132. package/dist/{chunk-2cwcfwg3.js → chunk-tr3cbx8k.js} +2 -2
  133. package/dist/{chunk-2cwcfwg3.js.map → chunk-tr3cbx8k.js.map} +2 -2
  134. package/dist/{chunk-dgasxgsm.js → chunk-vqcswg7h.js} +2 -2
  135. package/dist/{chunk-dgasxgsm.js.map → chunk-vqcswg7h.js.map} +2 -2
  136. package/dist/{chunk-zqsfanvk.js → chunk-wpb1xpdp.js} +2 -2
  137. package/dist/{chunk-zqsfanvk.js.map → chunk-wpb1xpdp.js.map} +1 -1
  138. package/dist/{chunk-z1e55w67.js → chunk-ybqss0jy.js} +2 -2
  139. package/dist/{chunk-z1e55w67.js.map → chunk-ybqss0jy.js.map} +1 -1
  140. package/dist/{chunk-cejf873g.js → chunk-yk5wqmyh.js} +2 -2
  141. package/dist/{chunk-cejf873g.js.map → chunk-yk5wqmyh.js.map} +1 -1
  142. package/dist/{chunk-8kj3zrm9.js → chunk-ywntv8yw.js} +4 -4
  143. package/dist/{chunk-8kj3zrm9.js.map → chunk-ywntv8yw.js.map} +1 -1
  144. package/dist/chunks/{ThemeProvider-ByU4BQdL.js → ThemeProvider-BZ2SsSZ3.js} +60 -39
  145. package/dist/chunks/ThemeProvider-BZ2SsSZ3.js.map +1 -0
  146. package/dist/chunks/useParams-BN3XXfmG.js +20 -0
  147. package/dist/chunks/useParams-BN3XXfmG.js.map +1 -0
  148. package/dist/client/index.js +3 -3
  149. package/dist/client/index.js.map +1 -1
  150. package/dist/client/useDictionary.d.ts.map +1 -1
  151. package/dist/config/index.d.ts +2 -0
  152. package/dist/config/index.d.ts.map +1 -1
  153. package/dist/config/index.js +2 -2
  154. package/dist/config/index.js.map +3 -3
  155. package/dist/database/index.js +1 -1
  156. package/dist/facades/index.js +2 -2
  157. package/dist/facades/index.js.map +1 -1
  158. package/dist/http/ApiRouter.d.ts +30 -2
  159. package/dist/http/ApiRouter.d.ts.map +1 -1
  160. package/dist/http/index.js +2 -2
  161. package/dist/http/index.js.map +1 -1
  162. package/dist/i18n/defineDictionary.d.ts +7 -4
  163. package/dist/i18n/defineDictionary.d.ts.map +1 -1
  164. package/dist/i18n/dictionaryRegistry.d.ts +38 -14
  165. package/dist/i18n/dictionaryRegistry.d.ts.map +1 -1
  166. package/dist/i18n/dictionaryRuntime.js +1 -1
  167. package/dist/i18n/index.js +2 -2
  168. package/dist/i18n/index.js.map +2 -2
  169. package/dist/kernel/index.js +2 -2
  170. package/dist/kernel/index.js.map +2 -2
  171. package/dist/orm/index.js +2 -2
  172. package/dist/orm/index.js.map +2 -2
  173. package/dist/server/index.js +1 -1
  174. package/dist/services/index.js +2 -2
  175. package/dist/services/index.js.map +2 -2
  176. package/dist/testing/index.js +2 -1
  177. package/dist/testing/index.js.map +1 -1
  178. package/package.json +5 -2
  179. package/skills/gemi-react-best-practices/SKILL.md +231 -0
  180. package/skills/gemi-react-best-practices/rules/_sections.md +56 -0
  181. package/skills/gemi-react-best-practices/rules/_template.md +28 -0
  182. package/skills/gemi-react-best-practices/rules/bundle-deep-imports.md +48 -0
  183. package/skills/gemi-react-best-practices/rules/bundle-mount-gate-heavy-panels.md +63 -0
  184. package/skills/gemi-react-best-practices/rules/client-form-vs-mutation-hooks.md +57 -0
  185. package/skills/gemi-react-best-practices/rules/client-loading-error-exports.md +54 -0
  186. package/skills/gemi-react-best-practices/rules/client-no-effect-data-flow.md +68 -0
  187. package/skills/gemi-react-best-practices/rules/client-typed-links.md +51 -0
  188. package/skills/gemi-react-best-practices/rules/controller-authorize-every-tenant-read.md +65 -0
  189. package/skills/gemi-react-best-practices/rules/controller-parse-request-at-the-boundary.md +54 -0
  190. package/skills/gemi-react-best-practices/rules/controller-redirect-facade-throws.md +68 -0
  191. package/skills/gemi-react-best-practices/rules/controller-request-schema.md +61 -0
  192. package/skills/gemi-react-best-practices/rules/controller-throw-framework-errors.md +57 -0
  193. package/skills/gemi-react-best-practices/rules/i18n-define-dictionary-inline.md +58 -0
  194. package/skills/gemi-react-best-practices/rules/orm-analytics-connection.md +53 -0
  195. package/skills/gemi-react-best-practices/rules/orm-include-not-n-plus-one.md +56 -0
  196. package/skills/gemi-react-best-practices/rules/orm-paginate-helper.md +69 -0
  197. package/skills/gemi-react-best-practices/rules/orm-plain-rows-by-default.md +55 -0
  198. package/skills/gemi-react-best-practices/rules/orm-select-narrow.md +58 -0
  199. package/skills/gemi-react-best-practices/rules/orm-transaction-no-io.md +54 -0
  200. package/skills/gemi-react-best-practices/rules/orm-transaction-sequential.md +64 -0
  201. package/skills/gemi-react-best-practices/rules/payload-dont-overprefetch.md +54 -0
  202. package/skills/gemi-react-best-practices/rules/payload-instant-vs-prefetch.md +58 -0
  203. package/skills/gemi-react-best-practices/rules/payload-minimal-view-props.md +51 -0
  204. package/skills/gemi-react-best-practices/rules/payload-parallel-controller-work.md +56 -0
  205. package/skills/gemi-react-best-practices/rules/payload-prefetch-late-queries.md +58 -0
  206. package/skills/gemi-react-best-practices/rules/payload-prefetch-mirrors-usequery.md +52 -0
  207. package/skills/gemi-react-best-practices/rules/query-debounce-search-variant.md +52 -0
  208. package/skills/gemi-react-best-practices/rules/query-keep-previous-data.md +40 -0
  209. package/skills/gemi-react-best-practices/rules/query-lazy-vs-mount-gate.md +54 -0
  210. package/skills/gemi-react-best-practices/rules/query-mutate-over-refetch.md +55 -0
  211. package/skills/gemi-react-best-practices/rules/query-no-hand-rolled-fetch.md +60 -0
  212. package/skills/gemi-react-best-practices/rules/query-revalidate-on-focus.md +44 -0
  213. package/skills/gemi-react-best-practices/rules/query-share-cache-key.md +51 -0
  214. package/skills/gemi-react-best-practices/rules/query-suspense-default.md +52 -0
  215. package/skills/gemi-react-best-practices/rules/routing-cache-policy-constants.md +53 -0
  216. package/skills/gemi-react-best-practices/rules/routing-middleware-dsl.md +60 -0
  217. package/skills/gemi-react-best-practices/rules/routing-resource-routes.md +59 -0
  218. package/skills/gemi-react-best-practices/rules/routing-routers-are-classes.md +55 -0
  219. package/skills/gemi-react-best-practices/rules/service-lazy-not-module-scope.md +63 -0
  220. package/skills/gemi-react-best-practices/rules/service-queue-is-in-memory.md +52 -0
  221. package/skills/gemi-react-best-practices/rules/service-static-token-and-name.md +52 -0
  222. package/skills/gemi-react-best-practices/rules/structure-discovered-vs-registered.md +71 -0
  223. package/skills/gemi-react-best-practices/rules/structure-do-not-reinvent-the-framework.md +58 -0
  224. package/skills/gemi-react-best-practices/rules/testing-assert-behaviour-over-markup.md +54 -0
  225. package/skills/gemi-react-best-practices/rules/testing-match-the-suite.md +57 -0
  226. package/skills/gemi-react-best-practices/rules/testing-page-seeds-real-inputs.md +65 -0
  227. package/dist/chunk-2khdxyjb.js.map +0 -10
  228. package/dist/chunk-4mcyyh1v.js +0 -4
  229. package/dist/chunk-fbvvqf9b.js +0 -4
  230. package/dist/chunk-hwhw98hc.js +0 -4
  231. package/dist/chunk-n412aa9s.js +0 -5
  232. package/dist/chunk-q0y0j3ne.js +0 -5
  233. package/dist/chunk-q0y0j3ne.js.map +0 -11
  234. package/dist/chunk-txhcx69q.js +0 -6
  235. package/dist/chunk-z2tcxwyr.js +0 -5
  236. package/dist/chunks/ThemeProvider-ByU4BQdL.js.map +0 -1
  237. /package/dist/{chunk-3gvjn3q4.js.map → chunk-cf7bvd12.js.map} +0 -0
@@ -1,8 +1,277 @@
1
- import { Agent } from "./Agent";
2
- import { HttpRequest } from "../http";
3
- export declare class AgentController<T extends Agent<any> = Agent<any>> {
4
- private agent;
5
- constructor(agent: T);
6
- stream(req: HttpRequest): void;
1
+ import { Controller } from "../http/Controller";
2
+ import { HttpRequest } from "../http/HttpRequest";
3
+ import type { MiddlewareInput } from "../http/middlewareList";
4
+ import type { AgentRun, AgentRunResult, AnyAgent, ToolShapesOf } from "./Agent";
5
+ import { FrameCursorEvictedError, liveRuns as defaultLiveRuns, LiveRunNotFoundError, MemoryLiveRuns } from "./store/LiveRuns";
6
+ import { defaultAgentStore, MemoryAgentStore } from "./store/MemoryAgentStore";
7
+ import type { AgentError, AgentMessage, PendingToolCall, ToolShapes } from "./types";
8
+ /**
9
+ * Where conversations live.
10
+ *
11
+ * Stateless is the default and nothing here is required to hold a conversation:
12
+ * the client can carry its own history, and a pending approval travels in it
13
+ * safely because the server signed it. What a store buys is a conversation that
14
+ * survives the browser — and, with `/attach`, one whose interrupted turn is
15
+ * still there after a refresh.
16
+ */
17
+ export interface AgentStore {
18
+ /**
19
+ * Where a `threadId` comes from. `ApiRouter.agent()` mounts no route for
20
+ * this: the app writes one, calls it here, and hands the id to `useChat` —
21
+ * the mount is the app's because it is where ownership gets recorded, and a
22
+ * store that holds no user cannot do that for it. An id that did not come out
23
+ * of here is `null` from `loadThread` and a 404 from the controller, unless
24
+ * the store's ids are the client's by design (`MemoryAgentStore`'s
25
+ * `clientOwnedIds`).
26
+ */
27
+ createThread(params: {
28
+ userId?: string | number;
29
+ }): Promise<{
30
+ threadId: string;
31
+ }>;
32
+ /**
33
+ * The history, or `null` for a thread the store does not have.
34
+ *
35
+ * `null` and `[]` are different answers and the controller acts on the
36
+ * difference: an empty array is a conversation with nothing in it yet, and a
37
+ * turn on it runs; `null` is a 404 before anything runs. A store that answers
38
+ * `[]` for an id it has never seen turns an expired or mistyped thread into a
39
+ * fresh conversation with no signal, and persists the next turn under the
40
+ * dead id. Only a store whose ids are minted by the client should do that,
41
+ * and then on purpose — see `MemoryAgentStore`'s `clientOwnedIds`.
42
+ */
43
+ loadThread(threadId: string): Promise<AgentMessage[] | null>;
44
+ /**
45
+ * Upsert by message id: replace a message the thread already holds, append
46
+ * one it does not, and keep the order the thread had. Called with a thread
47
+ * `loadThread` just found; must not create one.
48
+ *
49
+ * The name says append because that is what almost every call is, but a
50
+ * turn that resolves a pending call reports the earlier assistant message
51
+ * again — same id, now with the result attached — and a store that only
52
+ * appends ends up with both versions. A table keyed by message id has the
53
+ * lookup already but still needs an insert-or-update rather than a plain
54
+ * insert, which would fail on the key; a store that is a list has to look
55
+ * before it pushes.
56
+ */
57
+ appendMessages(threadId: string, messages: AgentMessage[]): Promise<void>;
7
58
  }
59
+ /** The default: conversations last as long as the process. */
60
+ export { defaultAgentStore, MemoryAgentStore };
61
+ /**
62
+ * The runs currently in flight, and their frames.
63
+ *
64
+ * A run outlives the request that started it, so something has to hold it while
65
+ * no one is listening, and hold what it emitted meanwhile so a returning client
66
+ * can catch up rather than start over. That is all this is: a per-process map
67
+ * plus a bounded buffer.
68
+ *
69
+ * Per-process is not an implementation shortcut that a better store fixes — a
70
+ * running generator lives in one process, and a second server cannot attach to
71
+ * it. Reattachment therefore needs the request to land where the run is: one
72
+ * server, sticky routing, or a proxy that forwards by `runId`. Worth saying out
73
+ * loud, because the failure mode behind a round-robin load balancer is a
74
+ * refresh that usually works.
75
+ *
76
+ * This is the read side, which is all `attach` and `stop` need. Registering a
77
+ * run and replaying its buffer are on `MemoryLiveRuns`, the only implementation
78
+ * there can be — see the note there for why a second one would not help.
79
+ */
80
+ export interface LiveRuns {
81
+ /** What the client asks after a refresh: is anything still going here? */
82
+ find(params: {
83
+ threadId: string;
84
+ }): Promise<{
85
+ runId: string;
86
+ seq: number;
87
+ } | null>;
88
+ get(runId: string): AgentRun | null;
89
+ /** Kept for a short while after `run-end`, so a refresh a second late still
90
+ * sees the tail instead of an empty screen. */
91
+ ttlMs: number;
92
+ }
93
+ export { FrameCursorEvictedError, LiveRunNotFoundError, MemoryLiveRuns, defaultLiveRuns as liveRuns, };
94
+ export type AgentHookContext = {
95
+ req: HttpRequest<any, any>;
96
+ runId: string;
97
+ threadId?: string;
98
+ };
99
+ /**
100
+ * `Controller.kind` is typed as the literal `"controller"`, so a subclass that
101
+ * declares a `kind` of its own fails the static-side check (TS2417). Widening
102
+ * it belongs in `http/Controller.ts`, which this slice does not own; erasing
103
+ * the static side of the base here is the smaller change and costs nothing —
104
+ * `Controller.kind` has no reader, in this package or out of it.
105
+ */
106
+ declare const ControllerBase: new () => Controller;
107
+ export declare abstract class AgentController<A extends AnyAgent = AnyAgent> extends ControllerBase {
108
+ static kind: "agent-controller";
109
+ /** The agent this controller serves. A property rather than a constructor
110
+ * argument so `Router.agent(ChatController)` can take the class, matching how
111
+ * every other controller is mounted. */
112
+ abstract agent: A;
113
+ /**
114
+ * Defaults to the process-wide `MemoryAgentStore`.
115
+ *
116
+ * Whatever you put here, make it something that outlives the request: this
117
+ * controller is constructed fresh for every call, so `store = new
118
+ * MemoryAgentStore()` written here is an empty store on every turn and a
119
+ * threaded conversation silently reads back nothing. Assign a module-level
120
+ * instance, or a store whose state is somewhere else entirely.
121
+ */
122
+ store: AgentStore;
123
+ /**
124
+ * Defaults to the process-wide map. Overridable so a test — or an app running
125
+ * two agents that must not see each other's runs — can hold its own; not so
126
+ * that it can be moved off the process, which is not a thing that can be
127
+ * done. See `MemoryLiveRuns`.
128
+ */
129
+ liveRuns: MemoryLiveRuns;
130
+ /** Appended to the agent's static instructions for this request — the user's
131
+ * name, tenant, today's date. */
132
+ instructions(req: HttpRequest<any, any>): string | Promise<string> | void;
133
+ /**
134
+ * `POST /<path>` — one route for every client turn. A first message, an
135
+ * approval, an answer to a question and a client tool's result are all just
136
+ * the next turn, so none of them gets an endpoint of its own.
137
+ */
138
+ stream(req?: HttpRequest<any, any>): Promise<Response>;
139
+ /**
140
+ * A thread holds one run at a time; a new turn on it ends the old one first.
141
+ *
142
+ * Since a dropped connection no longer stops a run, a user who sends again
143
+ * mid-answer used to leave the first run going. It could not see the new
144
+ * turn, the new run's `loadThread` could not see its answer, and both
145
+ * appended when they finished — in whichever order the model returned them,
146
+ * so the thread read `user2, assistant2, user1, assistant1`. `byThread` then
147
+ * named the second run while the first was still live and unstoppable by
148
+ * `threadId`.
149
+ *
150
+ * Stopping the old run and waiting for its transcript to land is chosen over
151
+ * refusing the new turn with a 409, because sending again *is* the stop: it
152
+ * is what `useChat.send` means, and a client that has to poll `/stop` until
153
+ * the run is really gone before it may post the turn it has already shown is
154
+ * a worse client for no better thread. The cost is that the new turn waits
155
+ * for the old run to unwind, which is as long as its slowest tool in flight —
156
+ * and that wait is the thing that puts `assistant1` before `user2`.
157
+ *
158
+ * The wait is on `persistRun`, not on `run.result()`. `result()` settling is
159
+ * the transcript being final, not stored: `appendMessages` runs after it, and
160
+ * a `loadThread` in that gap reads a history the old answer is missing from,
161
+ * which is the original bug by a shorter route. It is also *only* that:
162
+ * `persistRun` settles once the transcript is stored and lets the app's
163
+ * hooks run on without it, so a slow `onMessage` is not a slow thread and a
164
+ * hung one is not a hung thread.
165
+ *
166
+ * The lock around it is what makes a *third* turn wait for the second rather
167
+ * than for the first. Two turns arriving together both see the same live
168
+ * run, both stop it, both wait for it, and both start — the same race, one
169
+ * message later. Under the lock the later one finds the earlier one
170
+ * registered and stops that instead. Per process, like `LiveRuns`, and for
171
+ * the same reason: the run it guards lives here.
172
+ */
173
+ private withThread;
174
+ /**
175
+ * `POST /<path>/attach` — subscribe to a run already in progress, from a
176
+ * cursor. This is a read of a live run, not a continuation of a stopped one:
177
+ * the work never paused, the listener changed.
178
+ *
179
+ * The cursor is `from`, else the client's `cursor`, else `Last-Event-ID`,
180
+ * else the oldest frame still buffered — and it is honoured only for the run
181
+ * the client's `runId` names. A cursor the buffer has dropped is a 410 naming
182
+ * what survives; *no* cursor is the tail, because a page reattaching on mount
183
+ * has no transcript to leave a hole in. See `resolveCursor`.
184
+ */
185
+ attach(req?: HttpRequest<any, any>): Promise<Response>;
186
+ /**
187
+ * `POST /<path>/stop` — the explicit cancel. Since a dropped connection no
188
+ * longer stops a run, this and a later turn on the same thread are the only
189
+ * things that do, and it is why stopping cannot be a client-side concern:
190
+ * the tool loop is here, and a client that stops reading has not stopped
191
+ * step four from charging a card.
192
+ *
193
+ * Returns as soon as the run is aborted, not when it has finished unwinding.
194
+ * The terminal events — the stopped tool results, the aborted message — go
195
+ * out on the run's own stream, so whoever is watching it sees the ending,
196
+ * and `onMessage` records it whether anyone is watching or not.
197
+ *
198
+ * Answers `{ stopped }` normally, and a `Response` only to reject a request
199
+ * it could not read — the union is the error, not a second success shape.
200
+ */
201
+ stop(req?: HttpRequest<any, any>): Promise<{
202
+ stopped: boolean;
203
+ } | Response>;
204
+ /** `POST /<path>/files` — uploads an attachment and returns its file id. */
205
+ upload(req?: HttpRequest<any, any>): Promise<{
206
+ fileId: string;
207
+ }>;
208
+ /**
209
+ * Protected, not private: these exist to be overridden. `onMessage` fires for
210
+ * every completed message, user and assistant alike, and is the intended
211
+ * persistence point for an app that is not using `store`.
212
+ */
213
+ protected onMessage(message: AgentMessage, ctx: AgentHookContext): void | Promise<void>;
214
+ protected onToolCall(call: {
215
+ toolCallId: string;
216
+ name: string;
217
+ input: unknown;
218
+ }, ctx: AgentHookContext): void | Promise<void>;
219
+ /** Fires before the stream ends `awaiting-input` — where to notify whoever
220
+ * has to approve, if they are not the person watching the stream. */
221
+ protected onAwaitingInput(pending: PendingToolCall[], ctx: AgentHookContext): void | Promise<void>;
222
+ protected onError(error: AgentError, ctx: AgentHookContext): void | Promise<void>;
223
+ protected onStreamComplete(result: AgentRunResult<ToolShapesOf<A["tools"]>, any>, ctx: AgentHookContext): void | Promise<void>;
224
+ /**
225
+ * WHAT HAPPENS WHEN A HOOK THROWS: it is reported and the run carries on.
226
+ *
227
+ * The alternative is to fail the run, and that trade is not close. These
228
+ * hooks are an app's persistence and notification points; the run is a model
229
+ * call the user has already been charged for and whose tools may already have
230
+ * charged a card. Letting a failed `INSERT` in `onMessage` abort a generation
231
+ * mid-sentence loses the answer as well as the row, and the user cannot
232
+ * retry into a better outcome. So the answer survives and the failure is
233
+ * logged.
234
+ *
235
+ * It is logged rather than routed to `onError`: `onError` is itself a hook,
236
+ * and a hook that throws inside the handler for hooks that throw is a loop.
237
+ * Override this to send it somewhere with a pager attached.
238
+ */
239
+ protected reportHookFailure(error: unknown): void;
240
+ private dispatchEvent;
241
+ /**
242
+ * Runs after the stream is over, whether or not anyone was still watching it.
243
+ *
244
+ * The messages come from `result()` rather than from the event stream because
245
+ * assembling a message out of deltas is the agent's job and doing it twice is
246
+ * how the two copies drift. It also means a stopped run persists the same way
247
+ * a finished one does: `stop()` finalizes the transcript, so by the time this
248
+ * resolves there is a valid history to store.
249
+ *
250
+ * Settles when the transcript is in the store, not when the app is done with
251
+ * it. The next turn on this thread waits on this (see `withThread`), and the
252
+ * hooks are the app's: an `onMessage` that writes to something slow would
253
+ * make every later turn wait for it, once per message of the old run, and
254
+ * one that never settles — which `safely` cannot catch — would hold the
255
+ * thread, and every turn queued on it, behind an open connection each. So
256
+ * the hooks run on after this on their own, reported the same way.
257
+ */
258
+ private persistRun;
259
+ /** The hooks on a finished run, in order. Never rejects: see `safely`. */
260
+ private notifyRun;
261
+ private safely;
262
+ }
263
+ export type AgentRouteMethod = "stream" | "attach" | "stop" | "upload";
264
+ export type AgentMiddlewareConfig = Partial<Record<AgentRouteMethod, MiddlewareInput>>;
265
+ export type AgentRoute<T extends new () => AgentController<any>> = {
266
+ __internal_brand: "AgentRoute";
267
+ controller: T;
268
+ middleware(config: AgentMiddlewareConfig): AgentRoute<T>;
269
+ };
270
+ /** What `CreateRPC` should produce for an agent route: enough for the client to
271
+ * type its messages, and nothing that drags server code into the bundle. */
272
+ export type AgentRouteRPC<T extends new () => AgentController<any>> = {
273
+ __agent: true;
274
+ tools: InstanceType<T>["agent"] extends AnyAgent ? ToolShapesOf<InstanceType<T>["agent"]["tools"]> : ToolShapes;
275
+ output: unknown;
276
+ };
8
277
  //# sourceMappingURL=AgentController.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AgentController.d.ts","sourceRoot":"","sources":["../../ai/AgentController.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,EAAqB,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtC,qBAAa,eAAe,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC;IAChD,OAAO,CAAC,KAAK;gBAAL,KAAK,EAAE,CAAC;IAE5B,MAAM,CAAC,GAAG,EAAE,WAAW;CAGxB"}
1
+ {"version":3,"file":"AgentController.d.ts","sourceRoot":"","sources":["../../ai/AgentController.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,255 @@
1
+ import type { ReasoningEffort } from "./Agent";
2
+ import { type ResponsesEndpoint } from "./providers/call";
3
+ import type { JSONSchema } from "./Schema";
4
+ import type { AgentError, AgentMessage, FinishReason, Usage } from "./types";
5
+ /**
6
+ * A provider makes one model call. It does not run the tool loop.
7
+ *
8
+ * The split matters: approvals, `maxSteps`, deferred tools, skill loading and
9
+ * persistence are all provider-independent, and putting them in the provider
10
+ * would mean writing them again for the second provider. So the provider's
11
+ * whole job is to translate gemi's messages into a request, and the response
12
+ * stream back into `ProviderEvent`s. Everything above that lives in `Agent`.
13
+ *
14
+ * v1 targets OpenAI's Responses API — native reasoning items and strict
15
+ * structured output without reassembling them by hand. The interface is kept
16
+ * free of anything Responses-specific so a Chat Completions provider (for older
17
+ * Azure deployments and OpenAI-compatible gateways) can be added later without
18
+ * touching Agent, Controller or the client.
19
+ */
20
+ /** What a provider will actually honour, so `Agent` can drop the rest rather
21
+ * than have a request rejected at runtime. */
22
+ export type ProviderCapabilities = {
23
+ reasoning: boolean;
24
+ structuredOutput: boolean;
25
+ fileInput: boolean;
26
+ parallelToolCalls: boolean;
27
+ /**
28
+ * Tool search, and with it deferred loading. Only recent models have it, so a
29
+ * provider that answers `false` is sent every schema inline and the agent
30
+ * runs identically — deferral is a token optimization, and an optimization
31
+ * that changed behaviour when unavailable would not be one.
32
+ */
33
+ toolSearch: boolean;
34
+ };
35
+ /** A tool as the model is shown it: schema only, no implementation. */
36
+ export type ProviderToolSpec = {
37
+ name: string;
38
+ description: string;
39
+ parameters: JSONSchema;
40
+ strict: boolean;
41
+ /** `defer_loading`: send the name and description, withhold the schema until
42
+ * the model searches for it. Ignored when `capabilities.toolSearch` is
43
+ * false. */
44
+ deferred?: boolean;
45
+ };
46
+ /** Tools grouped for search. Flattened back to a list by a provider without
47
+ * tool search, since the grouping exists to be searched. */
48
+ export type ProviderToolNamespace = {
49
+ name: string;
50
+ description: string;
51
+ tools: ProviderToolSpec[];
52
+ };
53
+ export interface ProviderStreamParams {
54
+ messages: AgentMessage[];
55
+ systemPrompt?: string;
56
+ tools?: (ProviderToolSpec | ProviderToolNamespace)[];
57
+ /** Set when the agent declares an `output` schema; the provider turns it into
58
+ * whatever its own strict-JSON parameter is. */
59
+ output?: {
60
+ name: string;
61
+ schema: JSONSchema;
62
+ };
63
+ /** Optional: silently dropped by a provider whose `capabilities.reasoning`
64
+ * is false, since a model that cannot reason should not fail a request. */
65
+ reasoning?: ReasoningEffort;
66
+ temperature?: number;
67
+ maxOutputTokens?: number;
68
+ signal?: AbortSignal;
69
+ }
70
+ /**
71
+ * The events of a single model call. Deliberately smaller than
72
+ * `AgentStreamEvent`: no run, message, tool-result or approval events, because
73
+ * a provider knows about none of those.
74
+ */
75
+ export type ProviderEvent = {
76
+ type: "text-delta";
77
+ delta: string;
78
+ } | {
79
+ type: "reasoning-delta";
80
+ delta: string;
81
+ id?: string;
82
+ }
83
+ /** Arguments arrive as JSON fragments; the provider passes them through and
84
+ * `Agent` assembles and validates against the tool's schema. */
85
+ | {
86
+ type: "tool-call-delta";
87
+ toolCallId: string;
88
+ name: string;
89
+ argsDelta: string;
90
+ namespace?: string;
91
+ }
92
+ /**
93
+ * `name` IS FLAT AND STAYS FLAT. This was an open question and the API has
94
+ * answered it: a call to a function that lives inside a namespace comes back
95
+ * as `{name: "getOrder", namespace: "crm"}`, not as `"crm.getOrder"` —
96
+ * recorded in `providers/__fixtures__/openai-tool-search.sse` and pinned by
97
+ * a test that reads that file. So `name` is already the key `Agent`'s tool
98
+ * registry is built on, which is what makes tool names having to be globally
99
+ * unique within an agent (see `ToolNamespace`) the right rule rather than an
100
+ * inconvenience.
101
+ *
102
+ * `namespace` is carried beside it, absent for a tool that was listed bare.
103
+ * It is provenance, not identity: it says which group the model chose to
104
+ * look in, which is worth recording next to the call and is worthless for
105
+ * finding the tool. Folding it into `name` would make a name that is
106
+ * sometimes qualified and sometimes not, and nothing could match on that.
107
+ */
108
+ | {
109
+ type: "tool-call";
110
+ toolCallId: string;
111
+ name: string;
112
+ args: string;
113
+ namespace?: string;
114
+ }
115
+ /**
116
+ * The model went looking for a deferred tool and pulled its schema in. Worth
117
+ * surfacing rather than swallowing: it is a step the user paid for, and the
118
+ * pause before it is otherwise unexplained.
119
+ *
120
+ * TWO FIELDS, not one. `loaded` is the function names — `["listOrders",
121
+ * "getOrder"]` — and `namespaces` is the groups they came out of —
122
+ * `["crm"]`. Search results arrive as a tree of namespaces containing
123
+ * functions, so a single flat list has to pick one level and throw the other
124
+ * away, and both levels are worth saying: "searched crm, loaded getOrder"
125
+ * reads better than either half, and the group is the thing the model
126
+ * actually chose between.
127
+ *
128
+ * `namespaces` is required rather than optional because the parser always
129
+ * knows the answer, and an optional field would let a future provider forget
130
+ * to fill it in silently. Empty means the search returned bare functions.
131
+ */
132
+ | {
133
+ type: "tool-search";
134
+ loaded: string[];
135
+ namespaces: string[];
136
+ } | {
137
+ type: "output-delta";
138
+ delta: string;
139
+ } | {
140
+ type: "finish";
141
+ reason: FinishReason;
142
+ usage: Usage;
143
+ } | {
144
+ type: "error";
145
+ error: AgentError;
146
+ };
147
+ export type ProviderStream = AsyncIterable<ProviderEvent>;
148
+ export type ProviderConfig = {
149
+ apiKey?: string;
150
+ baseURL?: string;
151
+ timeoutMs?: number;
152
+ maxRetries?: number;
153
+ headers?: Record<string, string>;
154
+ };
155
+ export declare abstract class AgentProvider {
156
+ abstract readonly model: string;
157
+ abstract readonly capabilities: ProviderCapabilities;
158
+ /** The model ids this provider knows about — for autocomplete only; any
159
+ * string is still accepted, because a new model must not require a gemi
160
+ * release to use. */
161
+ static models(): readonly string[];
162
+ abstract stream(params: ProviderStreamParams): ProviderStream;
163
+ /**
164
+ * Uploads a file and returns the id a `FilePart` carries. Message history
165
+ * therefore holds provider file ids, which is the trade for getting vision
166
+ * and PDF input without gemi owning a storage story in v1.
167
+ */
168
+ abstract upload(file: File): Promise<string>;
169
+ /**
170
+ * Maps a provider's error body onto the normalized codes, so an app can
171
+ * branch on `rate_limited` without knowing whose rate limit it was.
172
+ *
173
+ * Shared rather than abstract-in-practice: Azure answers the same error
174
+ * envelope as OpenAI, and the one place it differs — the content filter's
175
+ * code, buried in `innererror` — is handled by reading both.
176
+ */
177
+ normalizeError(error: unknown): AgentError;
178
+ }
179
+ export declare class OpenAIProvider extends AgentProvider {
180
+ readonly model: string;
181
+ readonly capabilities: ProviderCapabilities;
182
+ protected readonly config: ProviderConfig;
183
+ constructor(model: string, config?: ProviderConfig);
184
+ /** Config defaults come from gemi's config (`ai.openai`), so an app that has
185
+ * set `OPENAI_API_KEY` writes only the model name. */
186
+ static model(model: string, config?: ProviderConfig): OpenAIProvider;
187
+ static models(): readonly string[];
188
+ stream(params: ProviderStreamParams): ProviderStream;
189
+ upload(file: File): Promise<string>;
190
+ protected baseURL(): string;
191
+ protected endpoint(): ResponsesEndpoint;
192
+ }
193
+ export type AzureConfig = ProviderConfig & {
194
+ /**
195
+ * The resource host, with or without a trailing `/openai`. Both spellings
196
+ * work — `https://<resource>.cognitiveservices.azure.com` and
197
+ * `https://<resource>.openai.azure.com` — and neither is rewritten, because
198
+ * only one of them exists for a resource that was not created as
199
+ * kind=OpenAI. See `azureBase` for what is done to it.
200
+ */
201
+ endpoint?: string;
202
+ /**
203
+ * Just the resource name, when there is no endpoint to hand. `<name>` is
204
+ * expanded to `https://<name>.cognitiveservices.azure.com/openai`.
205
+ */
206
+ resourceName?: string;
207
+ apiVersion?: string;
208
+ /**
209
+ * The deployment to call, when it is not named after the model. Azure lets
210
+ * whoever ran the template call it anything, and plenty of them are called
211
+ * `prod` — this is the override the class comment promises.
212
+ */
213
+ deployment?: string;
214
+ /**
215
+ * For Entra ID instead of a key. A function, not a token, because these
216
+ * expire mid-conversation.
217
+ */
218
+ getToken?: () => Promise<string>;
219
+ };
220
+ /**
221
+ * Its own class rather than a flag on `OpenAIProvider`: Azure names the
222
+ * deployment rather than the model, pins an api-version, authenticates with an
223
+ * `api-key` header or an Entra token, and puts the resource in the host. One
224
+ * class carrying both shapes means every field is conditionally meaningful.
225
+ *
226
+ * (It used to put the deployment in the URL as well. It does not: the Responses
227
+ * API serves no such path — see `azureBase` for the measurements.)
228
+ *
229
+ * The API stays symmetrical — `.model()`, not `.deployment()`. Apps name a
230
+ * model; mapping that onto a deployment is this class's problem, and an app
231
+ * that named its deployment differently overrides it in config.
232
+ */
233
+ export declare class AzureOpenAIProvider extends AgentProvider {
234
+ readonly model: string;
235
+ readonly capabilities: ProviderCapabilities;
236
+ protected readonly config: AzureConfig;
237
+ constructor(model: string, config?: AzureConfig);
238
+ /** Defaults from gemi's config (`ai.azure`). */
239
+ static model(model: string, config?: AzureConfig): AzureOpenAIProvider;
240
+ static models(): readonly string[];
241
+ stream(params: ProviderStreamParams): ProviderStream;
242
+ upload(file: File): Promise<string>;
243
+ protected deployment(): string;
244
+ /**
245
+ * The resource base, `<host>/openai`, from whichever of the three ways it was
246
+ * configured. A bare resource name expands to the `cognitiveservices` host
247
+ * rather than the `openai.azure.com` one: both answer for a resource created
248
+ * as kind=OpenAI, only `cognitiveservices` answers for an AI Foundry or
249
+ * multi-service resource, so it is the spelling that is right more often. An
250
+ * app on the other one sets `endpoint` and nothing rewrites it.
251
+ */
252
+ protected base(): string;
253
+ protected endpoint(): ResponsesEndpoint;
254
+ }
255
+ //# sourceMappingURL=AgentProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentProvider.d.ts","sourceRoot":"","sources":["../../ai/AgentProvider.ts"],"names":[],"mappings":"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"}