@theoremjs/react 0.3.0 → 0.3.1

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 (258) hide show
  1. package/README.md +728 -202
  2. package/client/composer-hints.js +1 -1
  3. package/client/decision-images.d.ts +76 -0
  4. package/client/decision-images.js +139 -0
  5. package/client/decision-transport.d.ts +26 -4
  6. package/client/decision-transport.js +79 -6
  7. package/client/embedding-input.d.ts +84 -0
  8. package/client/embedding-input.js +194 -0
  9. package/client/embedding-space.d.ts +82 -0
  10. package/client/embedding-space.js +389 -0
  11. package/client/embedding-transport.d.ts +40 -0
  12. package/client/embedding-transport.js +71 -0
  13. package/client/failure.d.ts +7 -10
  14. package/client/failure.js +9 -9
  15. package/client/host-call.d.ts +1 -1
  16. package/client/host-call.js +7 -2
  17. package/client/host-transport.d.ts +2 -0
  18. package/client/host-transport.js +3 -2
  19. package/client/index.d.ts +19 -11
  20. package/client/index.js +14 -10
  21. package/client/ink-waveform.d.ts +1 -1
  22. package/client/ink-waveform.js +1 -2
  23. package/client/live/apply-live-turn-tool-event.js +1 -1
  24. package/client/live/live-captions.d.ts +30 -0
  25. package/client/live/live-captions.js +105 -1
  26. package/client/live/live-mic-forward.d.ts +1 -0
  27. package/client/live/live-mic-forward.js +11 -2
  28. package/client/live/live-page-tool.d.ts +34 -0
  29. package/client/live/live-page-tool.js +11 -0
  30. package/client/live/live-state.d.ts +4 -2
  31. package/client/live/live-state.js +2 -0
  32. package/client/live/live-video.js +1 -1
  33. package/client/live/run-live-tool-call.d.ts +7 -2
  34. package/client/live/run-live-tool-call.js +48 -10
  35. package/client/live/use-live-caption-log.d.ts +17 -0
  36. package/client/live/use-live-caption-log.js +51 -0
  37. package/client/live-client.d.ts +52 -4
  38. package/client/live-client.js +250 -59
  39. package/client/live-messages.d.ts +51 -13
  40. package/client/live-messages.js +42 -9
  41. package/client/page-dispatch.d.ts +15 -0
  42. package/client/page-dispatch.js +63 -0
  43. package/client/run-commit.d.ts +16 -43
  44. package/client/run-commit.js +26 -101
  45. package/client/run-session.d.ts +40 -41
  46. package/client/run-session.js +104 -112
  47. package/client/schema-fields.js +27 -6
  48. package/client/shaped-data.js +37 -8
  49. package/client/source-citations.js +1 -1
  50. package/client/space-geometry.d.ts +39 -0
  51. package/client/space-geometry.js +183 -0
  52. package/client/state-fields.js +1 -1
  53. package/client/tool-result.js +30 -12
  54. package/client/tool-resume.d.ts +18 -1
  55. package/client/tool-resume.js +4 -1
  56. package/client/trace-feed.d.ts +1 -1
  57. package/client/trace-story.d.ts +2 -2
  58. package/client/trace-story.js +43 -19
  59. package/client/trace-view.d.ts +2 -2
  60. package/client/trace-view.js +56 -16
  61. package/client/transcript-groups.d.ts +28 -2
  62. package/client/transcript-groups.js +63 -13
  63. package/client/transcript-schema.d.ts +10 -0
  64. package/client/transcript-schema.js +120 -0
  65. package/client/transport.d.ts +114 -26
  66. package/client/transport.js +106 -32
  67. package/client/turn-client.d.ts +17 -8
  68. package/client/turn-client.js +26 -31
  69. package/client/voice-recorder.d.ts +1 -1
  70. package/client/voice-recorder.js +2 -5
  71. package/client/wire-line.js +5 -5
  72. package/client/worklets/mic-capture.js +9 -9
  73. package/components/InkWaveform.d.ts +12 -1
  74. package/components/InkWaveform.js +65 -42
  75. package/components/live/use-live-runner-controls.d.ts +3 -4
  76. package/components/live/use-live-runner-controls.js +6 -10
  77. package/components/live/use-live-runner-model.d.ts +10 -6
  78. package/components/live/use-live-runner-model.js +29 -14
  79. package/components/live/use-live-runner-ui.d.ts +10 -8
  80. package/components/live/use-live-runner-ui.js +19 -11
  81. package/components/live/use-live-session-client.d.ts +4 -4
  82. package/components/live/use-live-session-client.js +11 -8
  83. package/components/use-composer-voice.d.ts +4 -4
  84. package/components/use-composer-voice.js +8 -8
  85. package/components/use-editor-selection.js +4 -1
  86. package/components/use-voice-playback.d.ts +2 -1
  87. package/components/use-voice-playback.js +4 -4
  88. package/hooks/use-described.d.ts +5 -1
  89. package/hooks/use-described.js +11 -9
  90. package/hooks/use-embedding-index.d.ts +27 -0
  91. package/hooks/use-embedding-index.js +43 -0
  92. package/hooks/use-one-call.d.ts +31 -0
  93. package/hooks/use-one-call.js +76 -0
  94. package/hooks/use-page-tool-warnings.d.ts +6 -0
  95. package/hooks/use-page-tool-warnings.js +25 -0
  96. package/hooks/use-second-ticker.d.ts +2 -0
  97. package/hooks/use-second-ticker.js +13 -0
  98. package/hooks/use-theorem-chat-actions.d.ts +25 -21
  99. package/hooks/use-theorem-chat-actions.js +67 -45
  100. package/hooks/use-theorem-chat-state.d.ts +6 -6
  101. package/hooks/use-theorem-chat-state.js +13 -9
  102. package/hooks/use-theorem-chat.d.ts +48 -14
  103. package/hooks/use-theorem-chat.js +329 -141
  104. package/hooks/use-theorem-decision.d.ts +5 -10
  105. package/hooks/use-theorem-decision.js +4 -67
  106. package/hooks/use-theorem-embedding.d.ts +18 -0
  107. package/hooks/use-theorem-embedding.js +12 -0
  108. package/hooks/use-theorem-host.d.ts +5 -4
  109. package/hooks/use-theorem-host.js +26 -8
  110. package/hooks/use-theorem-interface.d.ts +6 -3
  111. package/hooks/use-theorem-interface.js +12 -22
  112. package/index.d.ts +6 -3
  113. package/index.js +5 -2
  114. package/live.d.ts +1 -0
  115. package/live.js +1 -1
  116. package/package.json +6 -5
  117. package/server/checkpoint-ownership.d.ts +6 -0
  118. package/server/checkpoint-ownership.js +42 -0
  119. package/server/conversation-store.d.ts +92 -0
  120. package/server/conversation-store.js +131 -0
  121. package/server/conversation.d.ts +193 -0
  122. package/server/conversation.js +552 -0
  123. package/server/decision-handler.d.ts +12 -4
  124. package/server/decision-handler.js +29 -38
  125. package/server/embedding-handler.d.ts +33 -0
  126. package/server/embedding-handler.js +45 -0
  127. package/server/handler.d.ts +58 -20
  128. package/server/handler.js +441 -238
  129. package/server/mod.d.ts +15 -6
  130. package/server/mod.js +13 -5
  131. package/server/page-dispatch.d.ts +22 -0
  132. package/server/page-dispatch.js +127 -0
  133. package/server/request-body.d.ts +2 -0
  134. package/server/request-body.js +42 -0
  135. package/server/request-check.d.ts +6 -1
  136. package/server/request-check.js +27 -12
  137. package/server/session-authority.d.ts +8 -0
  138. package/server/session-authority.js +78 -0
  139. package/server/session-boundary.d.ts +26 -0
  140. package/server/session-boundary.js +64 -0
  141. package/server/session-identity.d.ts +16 -0
  142. package/server/session-identity.js +41 -0
  143. package/server/session-limits.d.ts +12 -0
  144. package/server/session-limits.js +59 -0
  145. package/server/session-store.d.ts +69 -20
  146. package/server/session-store.js +220 -5
  147. package/server/single-action.d.ts +21 -0
  148. package/server/single-action.js +30 -0
  149. package/server/steer-inbox.js +1 -1
  150. package/server/tool-operations.d.ts +6 -0
  151. package/server/tool-operations.js +132 -0
  152. package/server/turn-input.d.ts +10 -0
  153. package/server/turn-input.js +29 -0
  154. package/styles/ink-controls.css +78 -78
  155. package/ui/CardWall.d.ts +10 -0
  156. package/ui/CardWall.js +61 -0
  157. package/ui/ChatComposerBar.d.ts +28 -5
  158. package/ui/ChatComposerBar.js +85 -30
  159. package/ui/ChatTranscript.d.ts +14 -1
  160. package/ui/ChatTranscript.js +110 -57
  161. package/ui/ConsoleFrame.d.ts +61 -4
  162. package/ui/ConsoleFrame.js +109 -9
  163. package/ui/DecisionAnswers.d.ts +40 -2
  164. package/ui/DecisionAnswers.js +166 -35
  165. package/ui/DecisionImages.d.ts +16 -0
  166. package/ui/DecisionImages.js +46 -0
  167. package/ui/EmbeddingDocuments.d.ts +78 -0
  168. package/ui/EmbeddingDocuments.js +278 -0
  169. package/ui/EmbeddingQuery.d.ts +27 -0
  170. package/ui/EmbeddingQuery.js +95 -0
  171. package/ui/EmbeddingResults.d.ts +41 -0
  172. package/ui/EmbeddingResults.js +165 -0
  173. package/ui/EmbeddingSpace.d.ts +26 -0
  174. package/ui/EmbeddingSpace.js +106 -0
  175. package/ui/LiveCaptionsPanel.d.ts +22 -0
  176. package/ui/LiveCaptionsPanel.js +27 -0
  177. package/ui/LiveRunner.d.ts +6 -4
  178. package/ui/LiveRunner.js +42 -55
  179. package/ui/PaneState.d.ts +33 -0
  180. package/ui/PaneState.js +50 -0
  181. package/ui/SchemaFields.d.ts +1 -1
  182. package/ui/SchemaFields.js +54 -26
  183. package/ui/ShapedData.js +73 -28
  184. package/ui/SidePanel.d.ts +74 -5
  185. package/ui/SidePanel.js +82 -9
  186. package/ui/StateFields.d.ts +10 -2
  187. package/ui/StateFields.js +56 -13
  188. package/ui/TheoremChat.d.ts +65 -14
  189. package/ui/TheoremChat.js +66 -78
  190. package/ui/TheoremDecision.d.ts +12 -20
  191. package/ui/TheoremDecision.js +78 -35
  192. package/ui/TheoremEmbedding.d.ts +27 -0
  193. package/ui/TheoremEmbedding.js +122 -0
  194. package/ui/TheoremHost.d.ts +22 -5
  195. package/ui/TheoremHost.js +127 -37
  196. package/ui/ToolGateCard.d.ts +5 -1
  197. package/ui/ToolGateCard.js +30 -23
  198. package/ui/ToolResult.js +12 -10
  199. package/ui/ToolResultCharts.js +29 -12
  200. package/ui/TraceCharts.d.ts +2 -2
  201. package/ui/TraceCharts.js +48 -17
  202. package/ui/TraceGuardrails.d.ts +3 -2
  203. package/ui/TraceGuardrails.js +24 -6
  204. package/ui/TraceInspector.d.ts +11 -1
  205. package/ui/TraceInspector.js +45 -28
  206. package/ui/TraceInspectorPanel.d.ts +31 -9
  207. package/ui/TraceInspectorPanel.js +77 -39
  208. package/ui/TraceOverview.d.ts +7 -3
  209. package/ui/TraceOverview.js +44 -14
  210. package/ui/TraceSpanDetail.js +24 -22
  211. package/ui/TraceStory.js +9 -8
  212. package/ui/TraceValues.js +19 -9
  213. package/ui/TraceWaterfall.js +12 -9
  214. package/ui/VoiceNote.js +4 -4
  215. package/ui/approval-heading.d.ts +4 -0
  216. package/ui/approval-heading.js +9 -0
  217. package/ui/arrive.d.ts +18 -0
  218. package/ui/arrive.js +46 -0
  219. package/ui/built/theme.css +86 -68
  220. package/ui/built/theme.css.d.ts +9 -0
  221. package/ui/built/theorem.d.ts +3 -3
  222. package/ui/built/theorem.js +34 -5
  223. package/ui/built/theorem.variants.d.ts +8 -2
  224. package/ui/code-language.d.ts +12 -0
  225. package/ui/code-language.js +50 -0
  226. package/ui/disclosure-motion.js +53 -9
  227. package/ui/embedding-space-gl.d.ts +37 -0
  228. package/ui/embedding-space-gl.js +663 -0
  229. package/ui/embedding-space-view.d.ts +8 -0
  230. package/ui/embedding-space-view.js +8 -0
  231. package/ui/glide.d.ts +7 -0
  232. package/ui/glide.js +44 -0
  233. package/ui/icons.js +2 -1
  234. package/ui/index.d.ts +20 -9
  235. package/ui/index.js +20 -10
  236. package/ui/labels-provider.js +5 -2
  237. package/ui/labels.d.ts +374 -85
  238. package/ui/labels.js +1028 -188
  239. package/ui/markdown-plugins.d.ts +9 -0
  240. package/ui/markdown-plugins.js +13 -0
  241. package/ui/mcp-icon.d.ts +6 -0
  242. package/ui/mcp-icon.js +8 -0
  243. package/ui/row-keys.d.ts +19 -0
  244. package/ui/row-keys.js +33 -0
  245. package/ui/theme.d.ts +1 -1
  246. package/ui/theme.js +2 -2
  247. package/ui/theorem-theme.js +32 -10
  248. package/ui/trace-palette.d.ts +2 -16
  249. package/ui/trace-palette.js +2 -16
  250. package/ui/trace-patterns.d.ts +11 -3
  251. package/ui/trace-patterns.js +16 -3
  252. package/ui/transcript-copy-text.js +1 -0
  253. package/ui/wall-columns.d.ts +8 -0
  254. package/ui/wall-columns.js +19 -0
  255. package/client/walk-away.d.ts +0 -34
  256. package/client/walk-away.js +0 -48
  257. package/server/walk-away.d.ts +0 -22
  258. package/server/walk-away.js +0 -41
@@ -1,3 +1,4 @@
1
+ import { providerCheckpointSchema } from '@theoremjs/agents';
1
2
  /**
2
3
  * The live wire between the browser and a host's relay: the messages the live
3
4
  * client sends (a relay reads them with `parseLiveClientMessage`) and the envelopes it reads
@@ -5,48 +6,78 @@
5
6
  *
6
7
  * @module
7
8
  */
8
- import { GATE_DECISIONS, toolGateSchema, traceRecordSchema, TURN_EVENT_SCHEMAS, z, } from '@theoremjs/agents';
9
+ import { GATE_DECISIONS, TURN_EVENT_SCHEMAS, toolGateSchema, traceRecordSchema, turnHistoryMessageSchema, z, } from '@theoremjs/agents';
9
10
  import { hostErrorBodySchema } from "./transport.js";
10
11
  import { readWireLine, readWireValue, } from "./wire-line.js";
11
- /** The longest context message a relay accepts. */
12
- const LIVE_CONTEXT_MAX_CHARS = 2000;
12
+ const liveOpenMessage = z.object({
13
+ type: z.literal('open'),
14
+ history: z.array(turnHistoryMessageSchema).optional(),
15
+ slots: z.record(z.string(), z.string()).optional(),
16
+ context: z.unknown().optional(),
17
+ resume: z
18
+ .object({ providerState: providerCheckpointSchema, awayMs: z.number().nonnegative() })
19
+ .optional(),
20
+ host: z.record(z.string(), z.unknown()).optional(),
21
+ });
22
+ true;
23
+ /** The live client's first message, as `parseLiveOpenMessage` checks it for a relay. */
24
+ export const liveOpenMessageSchema = liveOpenMessage;
13
25
  const liveClientMessage = z.discriminatedUnion('type', [
14
26
  z.object({ type: z.literal('audio'), data: z.string() }),
15
- z.object({ type: z.literal('video'), data: z.string(), mimeType: z.string(),
16
- }),
27
+ z.object({ type: z.literal('video'), data: z.string(), mimeType: z.string() }),
17
28
  z.object({ type: z.literal('text'), text: z.string() }),
18
- z.object({ type: z.literal('context'), text: z.string().max(LIVE_CONTEXT_MAX_CHARS) }),
29
+ z.object({ type: z.literal('context'), context: z.unknown() }),
19
30
  z.object({
20
31
  type: z.literal('executeTool'),
21
32
  callId: z.string().min(1),
33
+ operationId: z.string().min(1).max(256),
22
34
  decision: z.enum(GATE_DECISIONS).optional(),
23
35
  input: z.unknown().optional(),
24
36
  secret: z.string().optional(),
25
37
  output: z.unknown().optional(),
38
+ grantId: z.string().min(1).optional(),
39
+ unanswered: z.literal(true).optional(),
26
40
  }),
27
41
  ]);
28
42
  true;
29
43
  /** The live client's messages, as `parseLiveClientMessage` checks them for a relay. */
30
44
  export const liveClientMessageSchema = liveClientMessage;
31
45
  const liveServerEnvelopeKinds = {
32
- ready: z.object({ type: z.literal('ready'), profile: z.string().optional(), sessionId: z.string().optional(),
46
+ ready: z.object({
47
+ type: z.literal('ready'),
48
+ profile: z.string().optional(),
49
+ sessionId: z.string().optional(),
33
50
  }),
34
51
  events: z.object({ type: z.literal('events'), events: z.array(z.unknown()) }),
35
52
  trace: z.object({ type: z.literal('trace'), record: traceRecordSchema }),
36
53
  error: z.object({ type: z.literal('error') }).and(hostErrorBodySchema),
37
54
  executeToolResult: z.discriminatedUnion('status', [
38
- z.object({ type: z.literal('executeToolResult'), callId: z.string(), status: z.literal('settled'),
55
+ z.object({
56
+ type: z.literal('executeToolResult'),
57
+ callId: z.string().min(1),
58
+ operationId: z.string().min(1).max(256),
59
+ status: z.literal('dispatched'),
60
+ grantId: z.string().min(1),
61
+ arguments: z.record(z.string(), z.unknown()),
62
+ }),
63
+ z.object({
64
+ type: z.literal('executeToolResult'),
65
+ callId: z.string(),
66
+ status: z.literal('settled'),
67
+ operationId: z.string().min(1).max(256),
39
68
  }),
40
69
  z.object({
41
70
  type: z.literal('executeToolResult'),
42
71
  callId: z.string(),
43
72
  status: z.literal('gated'),
73
+ operationId: z.string().min(1).max(256),
44
74
  gate: toolGateSchema,
45
75
  }),
46
76
  z.object({
47
77
  type: z.literal('executeToolResult'),
48
78
  callId: z.string(),
49
79
  status: z.literal('refused'),
80
+ operationId: z.string().min(1).max(256),
50
81
  body: hostErrorBodySchema,
51
82
  }),
52
83
  ]),
@@ -62,6 +93,8 @@ export function parseLiveServerEnvelope(text) {
62
93
  const envelope = readWireLine(liveServerEnvelopeLines, text);
63
94
  if (envelope.type !== 'events')
64
95
  return envelope;
65
- return { type: 'events', events: envelope.events.map((event) => readWireValue(TURN_EVENT_SCHEMAS, event)),
96
+ return {
97
+ type: 'events',
98
+ events: envelope.events.map((event) => readWireValue(TURN_EVENT_SCHEMAS, event)),
66
99
  };
67
100
  }
@@ -0,0 +1,15 @@
1
+ import type { HostTransport } from './host-transport.ts';
2
+ import type { PageTools } from './live/live-page-tool.ts';
3
+ import type { TheoremTransport } from './transport.ts';
4
+ export type PageDispatchResult = {
5
+ callId: string;
6
+ operationId: string;
7
+ grantId: string;
8
+ page: {
9
+ output: unknown;
10
+ } | {
11
+ unanswered: true;
12
+ };
13
+ };
14
+ export declare function withPageToolDispatch(transport: TheoremTransport, tools?: PageTools): TheoremTransport;
15
+ export declare function withPageToolDispatch(transport: HostTransport, tools?: PageTools): HostTransport;
@@ -0,0 +1,63 @@
1
+ import { errorKind, publicError } from '@theoremjs/agents';
2
+ export function withPageToolDispatch(transport, tools) {
3
+ const sink = (onEvent, signal) => {
4
+ const dispatched = new Set();
5
+ return (event) => {
6
+ onEvent(event);
7
+ if (event.type !== 'tool' || event.tool.phase !== 'dispatch')
8
+ return;
9
+ const { tool } = event;
10
+ if (!transport.pageResult || !tool.operationId || signal?.aborted)
11
+ return;
12
+ const key = JSON.stringify([tool.operationId, tool.grantId]);
13
+ if (dispatched.has(key))
14
+ return;
15
+ dispatched.add(key);
16
+ const callback = tools && Object.hasOwn(tools, tool.name) ? tools[tool.name] : undefined;
17
+ const reference = {
18
+ callId: tool.callId,
19
+ operationId: tool.operationId,
20
+ grantId: tool.grantId,
21
+ };
22
+ void Promise.resolve()
23
+ .then(async () => {
24
+ if (signal?.aborted)
25
+ return;
26
+ const page = callback
27
+ ? await Promise.resolve()
28
+ .then(() => callback(tool.arguments, reference))
29
+ .catch(() => ({ unanswered: true }))
30
+ : { unanswered: true };
31
+ await transport.pageResult?.({ ...reference, page }, signal);
32
+ })
33
+ .catch((error) => {
34
+ if (!signal?.aborted)
35
+ onEvent({ type: 'error', errorKind: errorKind(error), error: publicError(error) });
36
+ });
37
+ };
38
+ };
39
+ // why: A chat's stream also carries the conversation's ref, which no page tool reads.
40
+ const chatSink = (onLine, signal) => {
41
+ const events = sink(onLine, signal);
42
+ return (line) => (line.type === 'conversation' ? onLine(line) : events(line));
43
+ };
44
+ if ('call' in transport) {
45
+ const host = {
46
+ ...transport,
47
+ describe: transport.describe.bind(transport),
48
+ invoke: (request, onEvent, signal) => transport.invoke(request, sink(onEvent, signal), signal),
49
+ call: (request, onEvent, signal) => transport.call(request, sink(onEvent, signal), signal),
50
+ };
51
+ return host;
52
+ }
53
+ const chat = {
54
+ ...transport,
55
+ describe: transport.describe.bind(transport),
56
+ invoke: (request, onLine, signal) => transport.invoke(request, chatSink(onLine, signal), signal),
57
+ turn: (request, onLine, signal) => transport.turn(request, chatSink(onLine, signal), signal),
58
+ steer: transport.steer.bind(transport),
59
+ conversation: transport.conversation.bind(transport),
60
+ rewind: transport.rewind.bind(transport),
61
+ };
62
+ return chat;
63
+ }
@@ -1,59 +1,32 @@
1
- import type { TheoremError, TurnBlob, TurnEvent } from '@theoremjs/agents';
2
- import { type ComposerProfileInterface, type InterfaceTurnSession, type TranscriptBlock, type UserTurnHistoryMedia } from '@theoremjs/agents/interface';
3
- import { type TurnFailure } from './failure.ts';
4
- import type { TheoremTransport, TurnEventSink } from './transport.ts';
5
- /** The turn is over: every event it streamed, gate resumes included, enters history once. */
6
- export declare function commitCompletedTurn(session: InterfaceTurnSession, events: TurnEvent[], media?: UserTurnHistoryMedia): InterfaceTurnSession;
7
- export declare function toTurnMedia(encodedAttachments?: TurnBlob[], encodedVoice?: TurnBlob[]): UserTurnHistoryMedia;
1
+ import type { TheoremError, TurnEvent } from '@theoremjs/agents';
2
+ import { type ComposerProfileInterface, type InterfaceTurnSession, type TranscriptBlock } from '@theoremjs/agents/interface';
3
+ import type { ChatLineSink, ConversationLine } from './transport.ts';
4
+ /**
5
+ * The session once a reply's events are in: a reply that waits on a gate
6
+ * keeps its events beside the transcript until the gate settles; any other is over.
7
+ */
8
+ export declare function sessionAfter(session: InterfaceTurnSession, events: readonly TurnEvent[]): InterfaceTurnSession;
8
9
  /** Where a run shows itself as it streams: the reply so far, and each line the stream left out. */
9
10
  export type StreamView = {
10
11
  blocks(blocks: TranscriptBlock[]): void;
11
12
  /** A `malformed` line: left out, and the reply goes on. */
12
13
  skipped(error: TheoremError): void;
13
14
  };
14
- export declare function continueAfterTool(args: {
15
- iface: ComposerProfileInterface;
16
- transport: TheoremTransport;
17
- session: InterfaceTurnSession;
18
- view: StreamView;
19
- seedEvents: TurnEvent[];
20
- }): Promise<{
21
- ok: true;
22
- session: InterfaceTurnSession;
23
- assistantBlocks: TranscriptBlock[];
24
- } | TurnFailure>;
25
- /** A turn that failed partway, committed as far as it got. */
26
- export declare function failTurnStream(args: {
27
- session: InterfaceTurnSession;
28
- events: TurnEvent[];
29
- media: UserTurnHistoryMedia;
30
- failure: TurnFailure;
31
- }): TurnFailure;
32
15
  /**
33
- * An answer to `callId`'s gate that failed. Once the call settled, the reply
34
- * commits as far as it got, or waits on its next gate; before, the reply waits
35
- * on the gate as it did (the host puts the call back), and the answer can go again.
16
+ * Streams into `events`, which the caller owns, so a stream that fails still
17
+ * leaves what it delivered. A `conversation` line goes to `onConversation`. An
18
+ * `unsupported` line is the host's to read on its own transport, and a
19
+ * `malformed` one goes to `view.skipped`: neither enters the reply.
36
20
  */
37
- export declare function failGateAnswer(args: {
38
- /** The paused session the answer went out from. */
39
- session: InterfaceTurnSession;
40
- callId: string;
41
- /** The paused reply's events, then the answer's as far as they came. */
42
- events: TurnEvent[];
43
- failure: TurnFailure;
44
- }): TurnFailure;
45
- export declare function finalizeTurnStream(args: {
46
- session: InterfaceTurnSession;
47
- events: TurnEvent[];
48
- media: UserTurnHistoryMedia;
49
- }): InterfaceTurnSession;
50
21
  export declare function streamFoldedTurn(args: {
51
22
  iface: ComposerProfileInterface;
52
23
  view: StreamView;
53
24
  /** Seeded by the caller, and filled as the stream delivers. */
54
25
  events: TurnEvent[];
55
- stream: (onEvent: TurnEventSink) => Promise<void>;
56
- }): Promise<TurnEvent[]>;
26
+ /** The page adopts each ref from its transport; a run reads them only to know its message posted. */
27
+ onConversation?(line: ConversationLine): void;
28
+ stream: (onLine: ChatLineSink) => Promise<void>;
29
+ }): Promise<void>;
57
30
  /** `blocks` with its last `turn-done` carrying the reply's work. */
58
31
  export declare function stampWorked(blocks: TranscriptBlock[], worked: {
59
32
  workedMs: number;
@@ -1,17 +1,16 @@
1
- import { appendAssistantEventsToHistory, appendUserDraftToHistory, applyTurnEventsToSession, gatedToolFromEvents, settlesToolCall, } from '@theoremjs/agents/interface';
2
- import { turnFailure } from "./failure.js";
3
- import { buildTurnRequest, foldAssistantTurn, turnInputFromSession } from "./turn-client.js";
4
- /** The turn's history before its reply: a turn not yet started adds the user's message. */
5
- function turnBaseHistory(session, media) {
6
- return session.pendingUserDraft
7
- ? appendUserDraftToHistory(session.history, session.pendingUserDraft, media)
8
- : session.history;
9
- }
10
- /** The turn is over: every event it streamed, gate resumes included, enters history once. */
11
- export function commitCompletedTurn(session, events, media = {}) {
1
+ import { applyTurnEventsToSession, gatedToolFromEvents, } from '@theoremjs/agents/interface';
2
+ import { foldAssistantTurn } from "./turn-client.js";
3
+ /**
4
+ * The session once a reply's events are in: a reply that waits on a gate
5
+ * keeps its events beside the transcript until the gate settles; any other is over.
6
+ */
7
+ export function sessionAfter(session, events) {
8
+ const applied = applyTurnEventsToSession(session, events);
9
+ const gatedTool = gatedToolFromEvents(events);
10
+ if (gatedTool)
11
+ return { ...applied, gatedTool, assistantEvents: [...events] };
12
12
  return {
13
- ...applyTurnEventsToSession(session, events),
14
- history: appendAssistantEventsToHistory(turnBaseHistory(session, media), events),
13
+ ...applied,
15
14
  gatedTool: null,
16
15
  assistantEvents: [],
17
16
  pendingUserDraft: null,
@@ -19,101 +18,27 @@ export function commitCompletedTurn(session, events, media = {}) {
19
18
  promotedToolIds: [],
20
19
  };
21
20
  }
22
- /**
23
- * The turn waits at a gate. History stops at the user's message and the events
24
- * wait in `assistantEvents`, so the gated step enters history whole once it settles.
25
- */
26
- function pauseTurn(session, events, media = {}) {
27
- return {
28
- ...applyTurnEventsToSession(session, events),
29
- history: turnBaseHistory(session, media),
30
- gatedTool: gatedToolFromEvents(events),
31
- assistantEvents: [...events],
32
- pendingUserDraft: null,
33
- };
34
- }
35
- export function toTurnMedia(encodedAttachments, encodedVoice) {
36
- return {
37
- ...(encodedAttachments?.length ? { attachments: encodedAttachments } : {}),
38
- ...(encodedVoice?.length ? { voice: encodedVoice } : {}),
39
- };
40
- }
41
- /**
42
- * A failed turn with the conversation it leaves: the user's message and what the
43
- * reply got through (its text and the tool calls that settled), so the next turn
44
- * picks up from there. A stopped reply leaves the transcript, so only the message stays.
45
- */
46
- function withFailedTurnSession(failure, commit, events, seedEvents = []) {
47
- return { ...failure, session: commit(failure.aborted ? seedEvents : events) };
48
- }
49
21
  /**
50
22
  * Streams into `events`, which the caller owns, so a stream that fails still
51
- * leaves what it delivered. An `unsupported` line is the host's to read on its
52
- * own transport, and a `malformed` one goes to `view.skipped`: neither enters
53
- * the turn, its history or its transcript.
23
+ * leaves what it delivered. A `conversation` line goes to `onConversation`. An
24
+ * `unsupported` line is the host's to read on its own transport, and a
25
+ * `malformed` one goes to `view.skipped`: neither enters the reply.
54
26
  */
55
- async function streamFoldedEvents(stream, view, iface, events) {
56
- await stream((event) => {
57
- if (event.type === 'unsupported')
27
+ export function streamFoldedTurn(args) {
28
+ return args.stream((line) => {
29
+ if (line.type === 'conversation') {
30
+ args.onConversation?.(line);
31
+ return;
32
+ }
33
+ if (line.type === 'unsupported')
58
34
  return;
59
- if (event.type === 'malformed') {
60
- view.skipped(event.error);
35
+ if (line.type === 'malformed') {
36
+ args.view.skipped(line.error);
61
37
  return;
62
38
  }
63
- events.push(event);
64
- view.blocks(foldAssistantTurn(iface, events));
39
+ args.events.push(line);
40
+ args.view.blocks(foldAssistantTurn(args.iface, args.events));
65
41
  });
66
- return events;
67
- }
68
- export async function continueAfterTool(args) {
69
- const events = [...args.seedEvents];
70
- // The model reads the turn so far: the settled gate and everything before it.
71
- const sent = {
72
- ...args.session,
73
- history: appendAssistantEventsToHistory(args.session.history, args.seedEvents),
74
- };
75
- try {
76
- await streamFoldedEvents((onEvent) => args.transport.turn(buildTurnRequest(args.iface, sent, turnInputFromSession(sent)), onEvent), args.view, args.iface, events);
77
- if (gatedToolFromEvents(events)) {
78
- return {
79
- ok: true,
80
- session: pauseTurn(args.session, events),
81
- assistantBlocks: foldAssistantTurn(args.iface, events),
82
- };
83
- }
84
- return {
85
- ok: true,
86
- session: commitCompletedTurn(args.session, events),
87
- assistantBlocks: foldAssistantTurn(args.iface, events),
88
- };
89
- }
90
- catch (err) {
91
- return withFailedTurnSession(turnFailure(err, args.iface.lexicon), (kept) => commitCompletedTurn(args.session, kept), events, args.seedEvents);
92
- }
93
- }
94
- /** A turn that failed partway, committed as far as it got. */
95
- export function failTurnStream(args) {
96
- return withFailedTurnSession(args.failure, (kept) => commitCompletedTurn(args.session, kept, args.media), args.events);
97
- }
98
- /**
99
- * An answer to `callId`'s gate that failed. Once the call settled, the reply
100
- * commits as far as it got, or waits on its next gate; before, the reply waits
101
- * on the gate as it did (the host puts the call back), and the answer can go again.
102
- */
103
- export function failGateAnswer(args) {
104
- const answered = args.events.slice(args.session.assistantEvents.length);
105
- if (!answered.some((event) => settlesToolCall(event, args.callId)))
106
- return args.failure;
107
- return { ...args.failure, session: finalizeTurnStream({ session: args.session, events: args.events, media: {} }) };
108
- }
109
- export function finalizeTurnStream(args) {
110
- if (gatedToolFromEvents(args.events)) {
111
- return pauseTurn(args.session, args.events, args.media);
112
- }
113
- return commitCompletedTurn(args.session, args.events, args.media);
114
- }
115
- export function streamFoldedTurn(args) {
116
- return streamFoldedEvents(args.stream, args.view, args.iface, args.events);
117
42
  }
118
43
  /** `blocks` with its last `turn-done` carrying the reply's work. */
119
44
  export function stampWorked(blocks, worked) {
@@ -1,39 +1,56 @@
1
+ import { type TurnEvent } from '@theoremjs/agents';
1
2
  import { type ComposerProfileInterface, type InterfaceTurnSession, type TranscriptBlock, type UserTurnDraft } from '@theoremjs/agents/interface';
2
3
  import { type TurnFailure } from './failure.ts';
3
4
  import { type StreamView } from './run-commit.ts';
4
- import type { TheoremTransport } from './transport.ts';
5
5
  import { type ToolGateResolution } from './tool-resume.ts';
6
+ import { type TheoremTransport } from './transport.ts';
7
+ import { type RunScope } from './turn-client.ts';
6
8
  export type { TurnFailure } from './failure.ts';
7
9
  export type { StreamView } from './run-commit.ts';
8
- export type StreamTurnSuccess = {
9
- ok: true;
10
+ /**
11
+ * Whether the host keeps this chat's conversation. A stateless profile keeps
12
+ * none: the page holds its transcript, and nothing goes on from a ref.
13
+ */
14
+ export declare function keepsConversation(iface: ComposerProfileInterface): boolean;
15
+ /**
16
+ * What one run left. A host that keeps the conversation is the truth for the
17
+ * rest: the page draws it again from the last ref the stream carried. A
18
+ * stateless chat keeps the reply as the run streamed it.
19
+ */
20
+ export type RunOutcome = {
21
+ /** The session the run went out from, with any permission the answer granted. */
10
22
  session: InterfaceTurnSession;
11
- userBlocks: TranscriptBlock[];
12
- assistantBlocks: TranscriptBlock[];
23
+ /** The reply's events: a gate's answer starts from the paused reply's. */
24
+ events: TurnEvent[];
25
+ /** The message reached the conversation: the host's when it keeps one (the ref marked `posted`), else the page's. */
26
+ posted: boolean;
27
+ failure?: TurnFailure;
13
28
  };
14
29
  export type StreamInterfaceTurnBaseArgs = {
15
30
  iface: ComposerProfileInterface;
16
31
  transport: TheoremTransport;
17
32
  session: InterfaceTurnSession;
33
+ scope: RunScope;
18
34
  view: StreamView;
19
35
  /**
20
- * Fires once the message posts, before its reply streams, with the blocks
21
- * the transcript gains: a walked-away reply's settled blocks, then the
22
- * message's own (with media preview data).
36
+ * Fires once the message posts, with the blocks the transcript gains: a
37
+ * walked-away reply's settled blocks, then the message's own (with media
38
+ * preview data). Walking away, it posts once the host has it.
23
39
  */
24
- onUserBlocks?: (blocks: TranscriptBlock[]) => void;
40
+ onUserBlocks: (blocks: TranscriptBlock[]) => void;
25
41
  signal?: AbortSignal;
26
- turnId?: string;
27
42
  /**
28
43
  * Send while the reply waits on gates: the message walks away from every
29
44
  * waiting call in its own request, and the host settles each one cancelled
30
- * ahead of the reply. `workedMs` is the paused reply's work so far, which
31
- * its settled blocks keep. Without it, a waiting session refuses the send
32
- * (`session.gate_pending`).
45
+ * ahead of the reply. Without it, or in a chat the host keeps no
46
+ * conversation for, a waiting session refuses the send (`session.gate_pending`).
47
+ */
48
+ walkAway?: boolean;
49
+ /**
50
+ * The transcript before this message. Sent once, only when the host answers that it can no
51
+ * longer open the conversation, so a host that restores from it (the studio) goes on.
33
52
  */
34
- walkAway?: {
35
- workedMs: number;
36
- };
53
+ transcript?: readonly TranscriptBlock[];
37
54
  };
38
55
  export type StreamInterfaceTurnArgs = StreamInterfaceTurnBaseArgs & {
39
56
  text: string;
@@ -43,38 +60,20 @@ export type StreamInterfaceTurnArgs = StreamInterfaceTurnBaseArgs & {
43
60
  export type StreamInterfaceDraftTurnArgs = StreamInterfaceTurnBaseArgs & {
44
61
  draft: UserTurnDraft;
45
62
  };
46
- export declare function streamInterfaceTurn(args: StreamInterfaceTurnArgs): Promise<StreamTurnSuccess | TurnFailure>;
63
+ export declare function streamInterfaceTurn(args: StreamInterfaceTurnArgs): Promise<RunOutcome>;
47
64
  /** Send a turn from an already-encoded pending draft (queue drain / send now). */
48
- export declare function streamInterfaceDraftTurn(args: StreamInterfaceDraftTurnArgs): Promise<StreamTurnSuccess | TurnFailure>;
65
+ export declare function streamInterfaceDraftTurn(args: StreamInterfaceDraftTurnArgs): Promise<RunOutcome>;
49
66
  /**
50
67
  * Send the user's answer to the gate the session waits on. The host settles
51
- * the call either way (an approval runs it; a refusal records it declined),
52
- * so the model and the trace read what the user chose.
68
+ * the call either way (an approval runs it; a refusal records it declined), so
69
+ * the model and the trace read what the user chose. A host that keeps the
70
+ * conversation goes on with the reply in the same stream once no call waits.
53
71
  */
54
72
  export declare function resumeInterfaceTool(args: {
55
73
  iface: ComposerProfileInterface;
56
74
  transport: TheoremTransport;
57
75
  session: InterfaceTurnSession;
76
+ scope: RunScope;
58
77
  resolution: ToolGateResolution;
59
78
  view: StreamView;
60
- }): Promise<{
61
- ok: true;
62
- session: InterfaceTurnSession;
63
- assistantBlocks: TranscriptBlock[];
64
- } | TurnFailure>;
65
- export declare function applyTurnResultToTranscript(args: {
66
- blocks: TranscriptBlock[];
67
- streamBlocks: TranscriptBlock[];
68
- session: InterfaceTurnSession;
69
- userBlocks?: TranscriptBlock[];
70
- assistantBlocks: TranscriptBlock[];
71
- /** The reply's work so far, stamped on its latest `turn-done` so the time stays with the blocks. */
72
- worked?: {
73
- workedMs: number;
74
- endedAt: number;
75
- };
76
- }): {
77
- blocks: TranscriptBlock[];
78
- streamBlocks: TranscriptBlock[];
79
- session: InterfaceTurnSession;
80
- };
79
+ }): Promise<RunOutcome>;