@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.
- package/README.md +728 -202
- package/client/composer-hints.js +1 -1
- package/client/decision-images.d.ts +76 -0
- package/client/decision-images.js +139 -0
- package/client/decision-transport.d.ts +26 -4
- package/client/decision-transport.js +79 -6
- package/client/embedding-input.d.ts +84 -0
- package/client/embedding-input.js +194 -0
- package/client/embedding-space.d.ts +82 -0
- package/client/embedding-space.js +389 -0
- package/client/embedding-transport.d.ts +40 -0
- package/client/embedding-transport.js +71 -0
- package/client/failure.d.ts +7 -10
- package/client/failure.js +9 -9
- package/client/host-call.d.ts +1 -1
- package/client/host-call.js +7 -2
- package/client/host-transport.d.ts +2 -0
- package/client/host-transport.js +3 -2
- package/client/index.d.ts +19 -11
- package/client/index.js +14 -10
- package/client/ink-waveform.d.ts +1 -1
- package/client/ink-waveform.js +1 -2
- package/client/live/apply-live-turn-tool-event.js +1 -1
- package/client/live/live-captions.d.ts +30 -0
- package/client/live/live-captions.js +105 -1
- package/client/live/live-mic-forward.d.ts +1 -0
- package/client/live/live-mic-forward.js +11 -2
- package/client/live/live-page-tool.d.ts +34 -0
- package/client/live/live-page-tool.js +11 -0
- package/client/live/live-state.d.ts +4 -2
- package/client/live/live-state.js +2 -0
- package/client/live/live-video.js +1 -1
- package/client/live/run-live-tool-call.d.ts +7 -2
- package/client/live/run-live-tool-call.js +48 -10
- package/client/live/use-live-caption-log.d.ts +17 -0
- package/client/live/use-live-caption-log.js +51 -0
- package/client/live-client.d.ts +52 -4
- package/client/live-client.js +250 -59
- package/client/live-messages.d.ts +51 -13
- package/client/live-messages.js +42 -9
- package/client/page-dispatch.d.ts +15 -0
- package/client/page-dispatch.js +63 -0
- package/client/run-commit.d.ts +16 -43
- package/client/run-commit.js +26 -101
- package/client/run-session.d.ts +40 -41
- package/client/run-session.js +104 -112
- package/client/schema-fields.js +27 -6
- package/client/shaped-data.js +37 -8
- package/client/source-citations.js +1 -1
- package/client/space-geometry.d.ts +39 -0
- package/client/space-geometry.js +183 -0
- package/client/state-fields.js +1 -1
- package/client/tool-result.js +30 -12
- package/client/tool-resume.d.ts +18 -1
- package/client/tool-resume.js +4 -1
- package/client/trace-feed.d.ts +1 -1
- package/client/trace-story.d.ts +2 -2
- package/client/trace-story.js +43 -19
- package/client/trace-view.d.ts +2 -2
- package/client/trace-view.js +56 -16
- package/client/transcript-groups.d.ts +28 -2
- package/client/transcript-groups.js +63 -13
- package/client/transcript-schema.d.ts +10 -0
- package/client/transcript-schema.js +120 -0
- package/client/transport.d.ts +114 -26
- package/client/transport.js +106 -32
- package/client/turn-client.d.ts +17 -8
- package/client/turn-client.js +26 -31
- package/client/voice-recorder.d.ts +1 -1
- package/client/voice-recorder.js +2 -5
- package/client/wire-line.js +5 -5
- package/client/worklets/mic-capture.js +9 -9
- package/components/InkWaveform.d.ts +12 -1
- package/components/InkWaveform.js +65 -42
- package/components/live/use-live-runner-controls.d.ts +3 -4
- package/components/live/use-live-runner-controls.js +6 -10
- package/components/live/use-live-runner-model.d.ts +10 -6
- package/components/live/use-live-runner-model.js +29 -14
- package/components/live/use-live-runner-ui.d.ts +10 -8
- package/components/live/use-live-runner-ui.js +19 -11
- package/components/live/use-live-session-client.d.ts +4 -4
- package/components/live/use-live-session-client.js +11 -8
- package/components/use-composer-voice.d.ts +4 -4
- package/components/use-composer-voice.js +8 -8
- package/components/use-editor-selection.js +4 -1
- package/components/use-voice-playback.d.ts +2 -1
- package/components/use-voice-playback.js +4 -4
- package/hooks/use-described.d.ts +5 -1
- package/hooks/use-described.js +11 -9
- package/hooks/use-embedding-index.d.ts +27 -0
- package/hooks/use-embedding-index.js +43 -0
- package/hooks/use-one-call.d.ts +31 -0
- package/hooks/use-one-call.js +76 -0
- package/hooks/use-page-tool-warnings.d.ts +6 -0
- package/hooks/use-page-tool-warnings.js +25 -0
- package/hooks/use-second-ticker.d.ts +2 -0
- package/hooks/use-second-ticker.js +13 -0
- package/hooks/use-theorem-chat-actions.d.ts +25 -21
- package/hooks/use-theorem-chat-actions.js +67 -45
- package/hooks/use-theorem-chat-state.d.ts +6 -6
- package/hooks/use-theorem-chat-state.js +13 -9
- package/hooks/use-theorem-chat.d.ts +48 -14
- package/hooks/use-theorem-chat.js +329 -141
- package/hooks/use-theorem-decision.d.ts +5 -10
- package/hooks/use-theorem-decision.js +4 -67
- package/hooks/use-theorem-embedding.d.ts +18 -0
- package/hooks/use-theorem-embedding.js +12 -0
- package/hooks/use-theorem-host.d.ts +5 -4
- package/hooks/use-theorem-host.js +26 -8
- package/hooks/use-theorem-interface.d.ts +6 -3
- package/hooks/use-theorem-interface.js +12 -22
- package/index.d.ts +6 -3
- package/index.js +5 -2
- package/live.d.ts +1 -0
- package/live.js +1 -1
- package/package.json +6 -5
- package/server/checkpoint-ownership.d.ts +6 -0
- package/server/checkpoint-ownership.js +42 -0
- package/server/conversation-store.d.ts +92 -0
- package/server/conversation-store.js +131 -0
- package/server/conversation.d.ts +193 -0
- package/server/conversation.js +552 -0
- package/server/decision-handler.d.ts +12 -4
- package/server/decision-handler.js +29 -38
- package/server/embedding-handler.d.ts +33 -0
- package/server/embedding-handler.js +45 -0
- package/server/handler.d.ts +58 -20
- package/server/handler.js +441 -238
- package/server/mod.d.ts +15 -6
- package/server/mod.js +13 -5
- package/server/page-dispatch.d.ts +22 -0
- package/server/page-dispatch.js +127 -0
- package/server/request-body.d.ts +2 -0
- package/server/request-body.js +42 -0
- package/server/request-check.d.ts +6 -1
- package/server/request-check.js +27 -12
- package/server/session-authority.d.ts +8 -0
- package/server/session-authority.js +78 -0
- package/server/session-boundary.d.ts +26 -0
- package/server/session-boundary.js +64 -0
- package/server/session-identity.d.ts +16 -0
- package/server/session-identity.js +41 -0
- package/server/session-limits.d.ts +12 -0
- package/server/session-limits.js +59 -0
- package/server/session-store.d.ts +69 -20
- package/server/session-store.js +220 -5
- package/server/single-action.d.ts +21 -0
- package/server/single-action.js +30 -0
- package/server/steer-inbox.js +1 -1
- package/server/tool-operations.d.ts +6 -0
- package/server/tool-operations.js +132 -0
- package/server/turn-input.d.ts +10 -0
- package/server/turn-input.js +29 -0
- package/styles/ink-controls.css +78 -78
- package/ui/CardWall.d.ts +10 -0
- package/ui/CardWall.js +61 -0
- package/ui/ChatComposerBar.d.ts +28 -5
- package/ui/ChatComposerBar.js +85 -30
- package/ui/ChatTranscript.d.ts +14 -1
- package/ui/ChatTranscript.js +110 -57
- package/ui/ConsoleFrame.d.ts +61 -4
- package/ui/ConsoleFrame.js +109 -9
- package/ui/DecisionAnswers.d.ts +40 -2
- package/ui/DecisionAnswers.js +166 -35
- package/ui/DecisionImages.d.ts +16 -0
- package/ui/DecisionImages.js +46 -0
- package/ui/EmbeddingDocuments.d.ts +78 -0
- package/ui/EmbeddingDocuments.js +278 -0
- package/ui/EmbeddingQuery.d.ts +27 -0
- package/ui/EmbeddingQuery.js +95 -0
- package/ui/EmbeddingResults.d.ts +41 -0
- package/ui/EmbeddingResults.js +165 -0
- package/ui/EmbeddingSpace.d.ts +26 -0
- package/ui/EmbeddingSpace.js +106 -0
- package/ui/LiveCaptionsPanel.d.ts +22 -0
- package/ui/LiveCaptionsPanel.js +27 -0
- package/ui/LiveRunner.d.ts +6 -4
- package/ui/LiveRunner.js +42 -55
- package/ui/PaneState.d.ts +33 -0
- package/ui/PaneState.js +50 -0
- package/ui/SchemaFields.d.ts +1 -1
- package/ui/SchemaFields.js +54 -26
- package/ui/ShapedData.js +73 -28
- package/ui/SidePanel.d.ts +74 -5
- package/ui/SidePanel.js +82 -9
- package/ui/StateFields.d.ts +10 -2
- package/ui/StateFields.js +56 -13
- package/ui/TheoremChat.d.ts +65 -14
- package/ui/TheoremChat.js +66 -78
- package/ui/TheoremDecision.d.ts +12 -20
- package/ui/TheoremDecision.js +78 -35
- package/ui/TheoremEmbedding.d.ts +27 -0
- package/ui/TheoremEmbedding.js +122 -0
- package/ui/TheoremHost.d.ts +22 -5
- package/ui/TheoremHost.js +127 -37
- package/ui/ToolGateCard.d.ts +5 -1
- package/ui/ToolGateCard.js +30 -23
- package/ui/ToolResult.js +12 -10
- package/ui/ToolResultCharts.js +29 -12
- package/ui/TraceCharts.d.ts +2 -2
- package/ui/TraceCharts.js +48 -17
- package/ui/TraceGuardrails.d.ts +3 -2
- package/ui/TraceGuardrails.js +24 -6
- package/ui/TraceInspector.d.ts +11 -1
- package/ui/TraceInspector.js +45 -28
- package/ui/TraceInspectorPanel.d.ts +31 -9
- package/ui/TraceInspectorPanel.js +77 -39
- package/ui/TraceOverview.d.ts +7 -3
- package/ui/TraceOverview.js +44 -14
- package/ui/TraceSpanDetail.js +24 -22
- package/ui/TraceStory.js +9 -8
- package/ui/TraceValues.js +19 -9
- package/ui/TraceWaterfall.js +12 -9
- package/ui/VoiceNote.js +4 -4
- package/ui/approval-heading.d.ts +4 -0
- package/ui/approval-heading.js +9 -0
- package/ui/arrive.d.ts +18 -0
- package/ui/arrive.js +46 -0
- package/ui/built/theme.css +86 -68
- package/ui/built/theme.css.d.ts +9 -0
- package/ui/built/theorem.d.ts +3 -3
- package/ui/built/theorem.js +34 -5
- package/ui/built/theorem.variants.d.ts +8 -2
- package/ui/code-language.d.ts +12 -0
- package/ui/code-language.js +50 -0
- package/ui/disclosure-motion.js +53 -9
- package/ui/embedding-space-gl.d.ts +37 -0
- package/ui/embedding-space-gl.js +663 -0
- package/ui/embedding-space-view.d.ts +8 -0
- package/ui/embedding-space-view.js +8 -0
- package/ui/glide.d.ts +7 -0
- package/ui/glide.js +44 -0
- package/ui/icons.js +2 -1
- package/ui/index.d.ts +20 -9
- package/ui/index.js +20 -10
- package/ui/labels-provider.js +5 -2
- package/ui/labels.d.ts +374 -85
- package/ui/labels.js +1028 -188
- package/ui/markdown-plugins.d.ts +9 -0
- package/ui/markdown-plugins.js +13 -0
- package/ui/mcp-icon.d.ts +6 -0
- package/ui/mcp-icon.js +8 -0
- package/ui/row-keys.d.ts +19 -0
- package/ui/row-keys.js +33 -0
- package/ui/theme.d.ts +1 -1
- package/ui/theme.js +2 -2
- package/ui/theorem-theme.js +32 -10
- package/ui/trace-palette.d.ts +2 -16
- package/ui/trace-palette.js +2 -16
- package/ui/trace-patterns.d.ts +11 -3
- package/ui/trace-patterns.js +16 -3
- package/ui/transcript-copy-text.js +1 -0
- package/ui/wall-columns.d.ts +8 -0
- package/ui/wall-columns.js +19 -0
- package/client/walk-away.d.ts +0 -34
- package/client/walk-away.js +0 -48
- package/server/walk-away.d.ts +0 -22
- package/server/walk-away.js +0 -41
package/client/live-messages.js
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
12
|
-
|
|
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'),
|
|
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({
|
|
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({
|
|
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 {
|
|
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
|
+
}
|
package/client/run-commit.d.ts
CHANGED
|
@@ -1,59 +1,32 @@
|
|
|
1
|
-
import type { TheoremError,
|
|
2
|
-
import { type ComposerProfileInterface, type InterfaceTurnSession, type TranscriptBlock
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
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
|
-
|
|
56
|
-
|
|
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;
|
package/client/run-commit.js
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
...
|
|
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.
|
|
52
|
-
*
|
|
53
|
-
*
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
if (
|
|
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 (
|
|
60
|
-
view.skipped(
|
|
35
|
+
if (line.type === 'malformed') {
|
|
36
|
+
args.view.skipped(line.error);
|
|
61
37
|
return;
|
|
62
38
|
}
|
|
63
|
-
events.push(
|
|
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) {
|
package/client/run-session.d.ts
CHANGED
|
@@ -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
|
-
|
|
9
|
-
|
|
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
|
-
|
|
12
|
-
|
|
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,
|
|
21
|
-
*
|
|
22
|
-
*
|
|
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
|
|
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.
|
|
31
|
-
*
|
|
32
|
-
|
|
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
|
-
|
|
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<
|
|
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<
|
|
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
|
-
*
|
|
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>;
|