@theoremjs/web 0.0.0-stage → 0.3.4-next.373.gab46e23

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 (120) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +437 -2
  3. package/client/audio-level.d.ts +5 -0
  4. package/client/audio-level.js +24 -0
  5. package/client/decision-transport.d.ts +70 -0
  6. package/client/decision-transport.js +175 -0
  7. package/client/decode-composer-draft.d.ts +11 -0
  8. package/client/decode-composer-draft.js +12 -0
  9. package/client/embedding-input.d.ts +84 -0
  10. package/client/embedding-input.js +194 -0
  11. package/client/embedding-space.d.ts +82 -0
  12. package/client/embedding-space.js +389 -0
  13. package/client/embedding-transport.d.ts +40 -0
  14. package/client/embedding-transport.js +71 -0
  15. package/client/encode-composer-draft.d.ts +9 -0
  16. package/client/encode-composer-draft.js +34 -0
  17. package/client/encode-files.d.ts +18 -0
  18. package/client/encode-files.js +54 -0
  19. package/client/failure.d.ts +29 -0
  20. package/client/failure.js +34 -0
  21. package/client/generation-selection.d.ts +15 -0
  22. package/client/generation-selection.js +24 -0
  23. package/client/host-transport.d.ts +70 -0
  24. package/client/host-transport.js +75 -0
  25. package/client/index.d.ts +33 -0
  26. package/client/index.js +27 -0
  27. package/client/live/live-mic-forward.d.ts +30 -0
  28. package/client/live/live-mic-forward.js +46 -0
  29. package/client/live/live-page-tool.d.ts +34 -0
  30. package/client/live/live-page-tool.js +11 -0
  31. package/client/live/live-state.d.ts +13 -0
  32. package/client/live/live-state.js +22 -0
  33. package/client/live/live-tool.d.ts +11 -0
  34. package/client/live/live-tool.js +1 -0
  35. package/client/live-client.d.ts +189 -0
  36. package/client/live-client.js +829 -0
  37. package/client/live-errors.d.ts +2 -0
  38. package/client/live-errors.js +9 -0
  39. package/client/live-messages.d.ts +148 -0
  40. package/client/live-messages.js +100 -0
  41. package/client/mic-capture.d.ts +4 -0
  42. package/client/mic-capture.js +6 -0
  43. package/client/oauth-popup.d.ts +26 -0
  44. package/client/oauth-popup.js +30 -0
  45. package/client/page-dispatch.d.ts +15 -0
  46. package/client/page-dispatch.js +63 -0
  47. package/client/pcm-downsample.d.ts +4 -0
  48. package/client/pcm-downsample.js +45 -0
  49. package/client/run-commit.d.ts +34 -0
  50. package/client/run-commit.js +49 -0
  51. package/client/run-session.d.ts +79 -0
  52. package/client/run-session.js +207 -0
  53. package/client/schema-fields.d.ts +63 -0
  54. package/client/schema-fields.js +199 -0
  55. package/client/shaped-data.d.ts +118 -0
  56. package/client/shaped-data.js +343 -0
  57. package/client/source-citations.d.ts +13 -0
  58. package/client/source-citations.js +56 -0
  59. package/client/space-geometry.d.ts +39 -0
  60. package/client/space-geometry.js +183 -0
  61. package/client/tool-result.d.ts +78 -0
  62. package/client/tool-result.js +293 -0
  63. package/client/tool-resume.d.ts +50 -0
  64. package/client/tool-resume.js +14 -0
  65. package/client/trace-feed.d.ts +13 -0
  66. package/client/trace-feed.js +18 -0
  67. package/client/transcript-schema.d.ts +10 -0
  68. package/client/transcript-schema.js +120 -0
  69. package/client/transport.d.ts +264 -0
  70. package/client/transport.js +330 -0
  71. package/client/turn-client.d.ts +44 -0
  72. package/client/turn-client.js +88 -0
  73. package/client/wire-line.d.ts +56 -0
  74. package/client/wire-line.js +90 -0
  75. package/client/worklets/mic-capture.js +16 -0
  76. package/package.json +28 -4
  77. package/server/checkpoint-ownership.d.ts +6 -0
  78. package/server/checkpoint-ownership.js +42 -0
  79. package/server/conversation-store.d.ts +92 -0
  80. package/server/conversation-store.js +131 -0
  81. package/server/conversation.d.ts +193 -0
  82. package/server/conversation.js +552 -0
  83. package/server/credential-store.d.ts +24 -0
  84. package/server/credential-store.js +14 -0
  85. package/server/decision-handler.d.ts +42 -0
  86. package/server/decision-handler.js +46 -0
  87. package/server/embedding-handler.d.ts +33 -0
  88. package/server/embedding-handler.js +45 -0
  89. package/server/handler.d.ts +158 -0
  90. package/server/handler.js +775 -0
  91. package/server/json-response.d.ts +2 -0
  92. package/server/json-response.js +7 -0
  93. package/server/mcp-handler.d.ts +46 -0
  94. package/server/mcp-handler.js +312 -0
  95. package/server/mod.d.ts +27 -0
  96. package/server/mod.js +25 -0
  97. package/server/page-dispatch.d.ts +22 -0
  98. package/server/page-dispatch.js +127 -0
  99. package/server/request-body.d.ts +2 -0
  100. package/server/request-body.js +42 -0
  101. package/server/request-check.d.ts +21 -0
  102. package/server/request-check.js +49 -0
  103. package/server/session-authority.d.ts +8 -0
  104. package/server/session-authority.js +78 -0
  105. package/server/session-boundary.d.ts +26 -0
  106. package/server/session-boundary.js +64 -0
  107. package/server/session-identity.d.ts +16 -0
  108. package/server/session-identity.js +41 -0
  109. package/server/session-limits.d.ts +12 -0
  110. package/server/session-limits.js +59 -0
  111. package/server/session-store.d.ts +123 -0
  112. package/server/session-store.js +264 -0
  113. package/server/single-action.d.ts +21 -0
  114. package/server/single-action.js +30 -0
  115. package/server/steer-inbox.d.ts +35 -0
  116. package/server/steer-inbox.js +52 -0
  117. package/server/tool-operations.d.ts +6 -0
  118. package/server/tool-operations.js +132 -0
  119. package/server/turn-input.d.ts +10 -0
  120. package/server/turn-input.js +29 -0
@@ -0,0 +1,15 @@
1
+ import { type ComposerProfileInterface } from '@theoremjs/agents/interface';
2
+ /** A model and effort for the next turn. */
3
+ export type GenerationSelection = {
4
+ model?: string;
5
+ effort?: string;
6
+ };
7
+ /** The profile's default model (its first, when it names none). */
8
+ export declare function defaultModel(iface: ComposerProfileInterface): string | undefined;
9
+ /**
10
+ * The selection for `iface`, given what was `selected` under the `previous` interface (none on
11
+ * first load). A pick that was on the previous default follows the new one, and a pick `iface` no
12
+ * longer has falls back to its default; any other pick is kept. Model and effort are each judged
13
+ * this way, the effort against its model's default, and a new model takes its own default effort.
14
+ */
15
+ export declare function followGenerationDefaults(iface: ComposerProfileInterface, selected: GenerationSelection, previous: ComposerProfileInterface | undefined): GenerationSelection;
@@ -0,0 +1,24 @@
1
+ import { defaultInterfaceEffort } from '@theoremjs/agents/interface';
2
+ /** The profile's default model (its first, when it names none). */
3
+ export function defaultModel(iface) {
4
+ return iface.defaultModel ?? Object.keys(iface.models)[0];
5
+ }
6
+ /**
7
+ * The selection for `iface`, given what was `selected` under the `previous` interface (none on
8
+ * first load). A pick that was on the previous default follows the new one, and a pick `iface` no
9
+ * longer has falls back to its default; any other pick is kept. Model and effort are each judged
10
+ * this way, the effort against its model's default, and a new model takes its own default effort.
11
+ */
12
+ export function followGenerationDefaults(iface, selected, previous) {
13
+ const keepModel = selected.model !== undefined &&
14
+ Object.hasOwn(iface.models, selected.model) &&
15
+ (previous === undefined || selected.model !== defaultModel(previous));
16
+ const model = keepModel ? selected.model : defaultModel(iface);
17
+ const efforts = model === undefined ? undefined : iface.models[model]?.efforts;
18
+ const keepEffort = model === selected.model &&
19
+ selected.effort !== undefined &&
20
+ efforts !== undefined &&
21
+ Object.hasOwn(efforts, selected.effort) &&
22
+ (previous === undefined || selected.effort !== defaultInterfaceEffort(previous, model));
23
+ return { model, effort: keepEffort ? selected.effort : defaultInterfaceEffort(iface, model) };
24
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * The browser side of a host profile: the tools the host lets the page call,
3
+ * each with the schemas its request and response are drawn from, and the calls
4
+ * themselves, streamed as the kernel runs them.
5
+ *
6
+ * @module
7
+ */
8
+ import { type Profile, type ToolAccess, type ToolPermission, z } from '@theoremjs/agents';
9
+ import type { PageDispatchResult } from './page-dispatch.ts';
10
+ import type { TraceFeed } from './trace-feed.ts';
11
+ import { type HttpOptions, type TheoremInvokeRequest, type TurnEventSink } from './transport.ts';
12
+ /** How a tool reaches its work: a function on the host, an HTTP endpoint, or an MCP server. */
13
+ export declare const HOST_TOOL_KINDS: readonly ["function", "http", "mcp"];
14
+ export type HostToolKind = (typeof HOST_TOOL_KINDS)[number];
15
+ /** One tool as the page sees it. Its endpoint, headers, and credentials stay on the host. */
16
+ export type HostToolView = {
17
+ name: string;
18
+ description: string;
19
+ kind: HostToolKind;
20
+ access: ToolAccess;
21
+ permission: ToolPermission;
22
+ /** JSON Schema for the call's input: the form is drawn from it. */
23
+ inputSchema: Record<string, unknown>;
24
+ /** JSON Schema for the tool's output: the result is laid out from it. */
25
+ outputSchema: Record<string, unknown>;
26
+ };
27
+ /** What a host profile shows the page. */
28
+ export type HostInterface = {
29
+ type: 'host';
30
+ id: string;
31
+ tools: HostToolView[];
32
+ observability?: {
33
+ record: boolean;
34
+ };
35
+ };
36
+ /** A tool as registered: the fields the page's view keeps. */
37
+ export type HostToolSource = {
38
+ type: string;
39
+ name: string;
40
+ description: string;
41
+ access: ToolAccess;
42
+ permission: ToolPermission;
43
+ inputSchema: Record<string, unknown>;
44
+ outputSchema: Record<string, unknown>;
45
+ };
46
+ /** The page's view of a host profile: its allowed tools, in the order it allows them. */
47
+ export declare function hostInterface(profile: Pick<Extract<Profile, {
48
+ type: 'host';
49
+ }>, 'id' | 'tools' | 'observability'>, tools: (name: string) => HostToolSource | undefined): HostInterface;
50
+ /** One call of one of the host's tools. */
51
+ export type TheoremHostCallRequest = {
52
+ name: string;
53
+ input: unknown;
54
+ };
55
+ /** A `/call` body as `createTheoremHostHandler` reads it. */
56
+ export declare const theoremHostCallRequestSchema: z.ZodType<TheoremHostCallRequest>;
57
+ export interface HostTransport {
58
+ pageResult?(result: PageDispatchResult, signal?: AbortSignal): Promise<void>;
59
+ describe(signal?: AbortSignal): Promise<HostInterface>;
60
+ /** Runs one tool; its events stream to `onEvent`, ending in `done`. */
61
+ call(request: TheoremHostCallRequest, onEvent: TurnEventSink, signal?: AbortSignal): Promise<void>;
62
+ /** The user's answer to a call the host paused on a gate. */
63
+ invoke(request: TheoremInvokeRequest, onEvent: TurnEventSink, signal?: AbortSignal): Promise<void>;
64
+ /** Where the host's trace records land, for the inspector. */
65
+ traces?: TraceFeed;
66
+ }
67
+ /** Transport for a host mounted with `createTheoremHostHandler`. Default endpoint `/api/host`. */
68
+ export declare function createHostTransport(options?: HttpOptions & {
69
+ endpoint?: string;
70
+ }): HostTransport;
@@ -0,0 +1,75 @@
1
+ /**
2
+ * The browser side of a host profile: the tools the host lets the page call,
3
+ * each with the schemas its request and response are drawn from, and the calls
4
+ * themselves, streamed as the kernel runs them.
5
+ *
6
+ * @module
7
+ */
8
+ import { resolveObservabilityPolicy, TOOL_ACCESS, TOOL_PERMISSION, TURN_EVENT_SCHEMAS, z, } from '@theoremjs/agents';
9
+ import { fetchJson, postJson, postNdjson, } from "./transport.js";
10
+ import { checkWire } from "./wire-line.js";
11
+ /** How a tool reaches its work: a function on the host, an HTTP endpoint, or an MCP server. */
12
+ export const HOST_TOOL_KINDS = ['function', 'http', 'mcp'];
13
+ function isHostToolKind(type) {
14
+ return HOST_TOOL_KINDS.includes(type);
15
+ }
16
+ /** The page's view of a host profile: its allowed tools, in the order it allows them. */
17
+ export function hostInterface(profile, tools) {
18
+ return {
19
+ type: 'host',
20
+ id: profile.id,
21
+ tools: profile.tools.allow.flatMap((name) => {
22
+ const tool = tools(name);
23
+ if (!tool || !isHostToolKind(tool.type))
24
+ return [];
25
+ return [
26
+ {
27
+ name: tool.name,
28
+ description: tool.description,
29
+ kind: tool.type,
30
+ access: tool.access,
31
+ permission: tool.permission,
32
+ inputSchema: tool.inputSchema,
33
+ outputSchema: tool.outputSchema,
34
+ },
35
+ ];
36
+ }),
37
+ ...(profile.observability
38
+ ? { observability: { record: resolveObservabilityPolicy(profile.observability).record } }
39
+ : {}),
40
+ };
41
+ }
42
+ const theoremHostCallRequest = z.object({ name: z.string().min(1).max(128), input: z.unknown() });
43
+ true;
44
+ /** A `/call` body as `createTheoremHostHandler` reads it. */
45
+ export const theoremHostCallRequestSchema = theoremHostCallRequest;
46
+ const schemaObject = z.record(z.string(), z.unknown());
47
+ const describedSchema = z.object({
48
+ interface: z.object({
49
+ type: z.literal('host'),
50
+ id: z.string(),
51
+ tools: z.array(z.object({
52
+ name: z.string(),
53
+ description: z.string(),
54
+ kind: z.enum(HOST_TOOL_KINDS),
55
+ access: z.enum(TOOL_ACCESS),
56
+ permission: z.enum(TOOL_PERMISSION),
57
+ inputSchema: schemaObject,
58
+ outputSchema: schemaObject,
59
+ })),
60
+ observability: z.object({ record: z.boolean() }).optional(),
61
+ }),
62
+ });
63
+ /** Transport for a host mounted with `createTheoremHostHandler`. Default endpoint `/api/host`. */
64
+ export function createHostTransport(options = {}) {
65
+ const base = (options.endpoint ?? '/api/host').replace(/\/$/, '');
66
+ return {
67
+ pageResult: (body, signal) => postJson(`${base}/page-result`, body, { ...options, signal }),
68
+ async describe(signal) {
69
+ // labels-exempt: internal diagnostic; the user reads error.bad_response
70
+ return checkWire(describedSchema, await fetchJson(base, { signal }, options), 'the host description').interface;
71
+ },
72
+ call: (body, onEvent, signal) => postNdjson(`${base}/call`, body, TURN_EVENT_SCHEMAS, onEvent, { ...options, signal }),
73
+ invoke: ({ replay: _replay, ...body }, onEvent, signal) => postNdjson(`${base}/invoke`, body, TURN_EVENT_SCHEMAS, onEvent, { ...options, signal }),
74
+ };
75
+ }
@@ -0,0 +1,33 @@
1
+ export { float32Rms, float32RmsToLevel, INPUT_LEVEL_GAIN, timeDomainBytesToLevel, } from './audio-level.ts';
2
+ export { createDecisionTransport, type DecisionInterface, type DecisionQuestionView, type DecisionReply, type DecisionTransport, decisionAssets, decisionInterface, failedDecisionTraces, failedTraces, postDecision, readDecisionReply, withFailedTraces, } from './decision-transport.ts';
3
+ export { type ComposerDraftFields, composerFieldsFromDraft } from './decode-composer-draft.ts';
4
+ export { addUsage, checkEmbeddingInputs, checkInputs, cosineSimilarity, type EmbeddingFields, type EmbeddingInputCheck, type EmbeddingMatch, type EmbeddingMediaPart, type EmbeddingSplit, embeddingBatches, fieldsInput, inputFields, MAX_BATCH_INPUTS, rankMatches, readEmbeddingInput, readEmbeddingInputs, readsAsText, splitText, } from './embedding-input.ts';
5
+ export { type EmbeddingSpace, layoutSpace, layoutSpaceSoon, outlierThreshold, placeQuery, type SpaceCluster, type SpaceDocument, type SpaceLink, type SpacePoint, } from './embedding-space.ts';
6
+ export { createEmbeddingTransport, type EmbeddingInterface, type EmbeddingReply, type EmbeddingTransport, type EmbedOptions, embeddingInterface, postEmbedding, readEmbeddingReply, } from './embedding-transport.ts';
7
+ export { encodeComposerDraft } from './encode-composer-draft.ts';
8
+ export { encodeFiles, filesToPending, pendingAttachmentsToFiles } from './encode-files.ts';
9
+ export { type ClientFailure, clientFailure, type TurnFailure, turnFailure } from './failure.ts';
10
+ export { followGenerationDefaults } from './generation-selection.ts';
11
+ export { createHostTransport, HOST_TOOL_KINDS, type HostInterface, type HostToolKind, type HostToolSource, type HostToolView, type HostTransport, hostInterface, type TheoremHostCallRequest, } from './host-transport.ts';
12
+ export type { LiveCallOptions, PageTool, PageToolAnswer, PageTools, } from './live/live-page-tool.ts';
13
+ export { pageToolMismatch } from './live/live-page-tool.ts';
14
+ export { type LiveConnectPhase, type LiveSessionStatus, type LiveState, liveState, } from './live/live-state.ts';
15
+ export type { LiveGateAnswer, LiveToolGatePrompt } from './live/live-tool.ts';
16
+ export type { LiveConnection } from './live-client.ts';
17
+ export { LiveSessionClient } from './live-client.ts';
18
+ export type { ExecuteToolOnRelay, LiveSocket } from './live-messages.ts';
19
+ export { isOAuthComplete, notifyOAuthComplete } from './oauth-popup.ts';
20
+ export { type PageDispatchResult, withPageToolDispatch } from './page-dispatch.ts';
21
+ export { sessionAfter, stampWorked } from './run-commit.ts';
22
+ export { keepsConversation, type RunOutcome, resumeInterfaceTool, type StreamView, streamInterfaceDraftTurn, streamInterfaceTurn, } from './run-session.ts';
23
+ export { blankRow, type JsonSchema, missingFields, type SchemaControl, type SchemaField, sampleFromSchema, schemaControl, schemaFields, withField, } from './schema-fields.ts';
24
+ export { fieldLabel, fieldReading, humanize, isPlain, isProse, isRow, json, type ListRow, MAX_ROWS, type PlainReading, plainReading, type Row, rowHeading, type Section, type Shape, shapeOf, splitFields, unpacked, withUnit, } from './shaped-data.ts';
25
+ export { citationsFromBlock, type SourceCitation, type SourceCitationBlock, } from './source-citations.ts';
26
+ export type { QueryMatch } from './space-geometry.ts';
27
+ export { DOT_FLOATS, FRAME_SLOT, queryGeometry, SEGMENT_FLOATS, type SpaceGeometry, spaceGeometry, } from './space-geometry.ts';
28
+ export { hasLead, layoutResult, type ResultChart, type ResultFigure, type ResultImage, type ResultLayout, type ResultMedia, returnedMedia, timeFormats, } from './tool-result.ts';
29
+ export type { AnsweringGate, ToolDecisionAction, ToolGateResolution, } from './tool-resume.ts';
30
+ export { continueGatedToolInvocation, type PersonGateResolution } from './tool-resume.ts';
31
+ export { createTraceFeed, type TraceFeed } from './trace-feed.ts';
32
+ export { CHAT_LINES, type ChatLine, type ChatLineSink, type ClientTurnEvent, type ConversationLine, type ConversationView, createHttpTransport, fetchConversation, fetchRewound, type HostErrorBody, type HttpOptions, type HttpTransportOptions, hostError, isTheoremStreamError, type MalformedEvent, postJson, postNdjson, readNdjsonStream, type TheoremConversationRequest, type TheoremInvokeRequest, type TheoremReplay, type TheoremRewindRequest, type TheoremRewound, type TheoremSteerRequest, TheoremStreamError, type TheoremTransport, type TheoremTurnInput, type TheoremTurnRequest, type TurnEventSink, type UnsupportedEvent, type WireLines, } from './transport.ts';
33
+ export { buildInvokeRequest, buildTurnRequest, foldAssistantTurn, issuedOperationId, type RunScope, type WalkAway, } from './turn-client.ts';
@@ -0,0 +1,27 @@
1
+ export { float32Rms, float32RmsToLevel, INPUT_LEVEL_GAIN, timeDomainBytesToLevel, } from "./audio-level.js";
2
+ export { createDecisionTransport, decisionAssets, decisionInterface, failedDecisionTraces, failedTraces, postDecision, readDecisionReply, withFailedTraces, } from "./decision-transport.js";
3
+ export { composerFieldsFromDraft } from "./decode-composer-draft.js";
4
+ export { addUsage, checkEmbeddingInputs, checkInputs, cosineSimilarity, embeddingBatches, fieldsInput, inputFields, MAX_BATCH_INPUTS, rankMatches, readEmbeddingInput, readEmbeddingInputs, readsAsText, splitText, } from "./embedding-input.js";
5
+ export { layoutSpace, layoutSpaceSoon, outlierThreshold, placeQuery, } from "./embedding-space.js";
6
+ export { createEmbeddingTransport, embeddingInterface, postEmbedding, readEmbeddingReply, } from "./embedding-transport.js";
7
+ export { encodeComposerDraft } from "./encode-composer-draft.js";
8
+ export { encodeFiles, filesToPending, pendingAttachmentsToFiles } from "./encode-files.js";
9
+ export { clientFailure, turnFailure } from "./failure.js";
10
+ export { followGenerationDefaults } from "./generation-selection.js";
11
+ export { createHostTransport, HOST_TOOL_KINDS, hostInterface, } from "./host-transport.js";
12
+ export { pageToolMismatch } from "./live/live-page-tool.js";
13
+ export { liveState, } from "./live/live-state.js";
14
+ export { LiveSessionClient } from "./live-client.js";
15
+ export { isOAuthComplete, notifyOAuthComplete } from "./oauth-popup.js";
16
+ export { withPageToolDispatch } from "./page-dispatch.js";
17
+ export { sessionAfter, stampWorked } from "./run-commit.js";
18
+ export { keepsConversation, resumeInterfaceTool, streamInterfaceDraftTurn, streamInterfaceTurn, } from "./run-session.js";
19
+ export { blankRow, missingFields, sampleFromSchema, schemaControl, schemaFields, withField, } from "./schema-fields.js";
20
+ export { fieldLabel, fieldReading, humanize, isPlain, isProse, isRow, json, MAX_ROWS, plainReading, rowHeading, shapeOf, splitFields, unpacked, withUnit, } from "./shaped-data.js";
21
+ export { citationsFromBlock, } from "./source-citations.js";
22
+ export { DOT_FLOATS, FRAME_SLOT, queryGeometry, SEGMENT_FLOATS, spaceGeometry, } from "./space-geometry.js";
23
+ export { hasLead, layoutResult, returnedMedia, timeFormats, } from "./tool-result.js";
24
+ export { continueGatedToolInvocation } from "./tool-resume.js";
25
+ export { createTraceFeed } from "./trace-feed.js";
26
+ export { CHAT_LINES, createHttpTransport, fetchConversation, fetchRewound, hostError, isTheoremStreamError, postJson, postNdjson, readNdjsonStream, TheoremStreamError, } from "./transport.js";
27
+ export { buildInvokeRequest, buildTurnRequest, foldAssistantTurn, issuedOperationId, } from "./turn-client.js";
@@ -0,0 +1,30 @@
1
+ import type { ToolCallEvent, TurnEventOf } from '@theoremjs/agents';
2
+ /** Whether a mic frame should be sent upstream given mute / socket / barge-in gates. */
3
+ export declare function shouldForwardMicFrame(args: {
4
+ isMuted: boolean;
5
+ socketOpen: boolean;
6
+ modelPlaying: boolean;
7
+ rms: number;
8
+ bargeInRmsWhileSpeaking: number;
9
+ }): boolean;
10
+ /** Classify live evidence transcription into a UI transcript callback payload. */
11
+ export declare function liveTranscriptFromEvidence(event: TurnEventOf<'evidence'>): {
12
+ text: string;
13
+ isUser: boolean;
14
+ interim: boolean;
15
+ } | null;
16
+ export type LiveToolCallDraft = {
17
+ operationId?: string;
18
+ id: string;
19
+ name: string;
20
+ arguments: Record<string, unknown>;
21
+ };
22
+ /**
23
+ * Fold a tool turn event into cancelled-id / runnable-call lists. The model's
24
+ * call is runnable; a failure in the same batch (a name or arguments the
25
+ * provider could not use) is not: the session answered the model with it.
26
+ */
27
+ export declare function applyLiveToolTurnEvent(tool: ToolCallEvent, accum: {
28
+ cancelledToolIds: Set<string>;
29
+ toolCalls: LiveToolCallDraft[];
30
+ }): void;
@@ -0,0 +1,46 @@
1
+ /** Whether a mic frame should be sent upstream given mute / socket / barge-in gates. */
2
+ export function shouldForwardMicFrame(args) {
3
+ if (args.isMuted || !args.socketOpen)
4
+ return false;
5
+ if (args.modelPlaying && args.rms < args.bargeInRmsWhileSpeaking)
6
+ return false;
7
+ return true;
8
+ }
9
+ /** Classify live evidence transcription into a UI transcript callback payload. */
10
+ export function liveTranscriptFromEvidence(event) {
11
+ const { evidence, text } = event;
12
+ if (!text)
13
+ return null;
14
+ if (evidence.kind !== 'input_transcription' && evidence.kind !== 'output_transcription')
15
+ return null;
16
+ return {
17
+ text,
18
+ isUser: evidence.kind === 'input_transcription',
19
+ interim: evidence.interim === true,
20
+ };
21
+ }
22
+ /**
23
+ * Fold a tool turn event into cancelled-id / runnable-call lists. The model's
24
+ * call is runnable; a failure in the same batch (a name or arguments the
25
+ * provider could not use) is not: the session answered the model with it.
26
+ */
27
+ export function applyLiveToolTurnEvent(tool, accum) {
28
+ if (tool.phase === undefined) {
29
+ accum.toolCalls.push({
30
+ id: tool.callId,
31
+ name: tool.name,
32
+ arguments: tool.arguments,
33
+ ...(tool.operationId ? { operationId: tool.operationId } : {}),
34
+ });
35
+ return;
36
+ }
37
+ if (tool.phase === 'cancel') {
38
+ accum.cancelledToolIds.add(tool.callId);
39
+ return;
40
+ }
41
+ if (tool.phase !== 'error')
42
+ return;
43
+ const failed = accum.toolCalls.findIndex((draft) => draft.id === tool.callId);
44
+ if (failed !== -1)
45
+ accum.toolCalls.splice(failed, 1);
46
+ }
@@ -0,0 +1,34 @@
1
+ /** The page's result for a call: the tool's output schema checks it, then the model reads it. */
2
+ export type PageToolAnswer = {
3
+ output: unknown;
4
+ };
5
+ /** One page tool: what the page does for a call the model made, and what it tells the model. */
6
+ export type PageTool = (args: Record<string, unknown>, call: {
7
+ callId: string;
8
+ operationId: string;
9
+ }) => PageToolAnswer | Promise<PageToolAnswer>;
10
+ /**
11
+ * The page's tools, by name: each answers a tool the profile declares with
12
+ * `answeredBy: 'page'`. Any other tool runs on the relay, gates and all.
13
+ */
14
+ export type PageTools = Record<string, PageTool>;
15
+ /** What a host gives a live call. */
16
+ export type LiveCallOptions = {
17
+ /** The value chosen for each of the profile's `inputs.slots`, read as the call starts. */
18
+ slots?: Record<string, string>;
19
+ /**
20
+ * What the page tells the agent: any JSON. It goes with the call's opening, and
21
+ * again whenever it changes, as background the agent reads without replying.
22
+ */
23
+ context?: unknown;
24
+ pageTools?: PageTools;
25
+ };
26
+ /**
27
+ * Where the page's tools and the profile's disagree, for the builder: a page
28
+ * tool with no handler here leaves the model unanswered, and a handler for a
29
+ * tool the profile does not give the page never runs.
30
+ */
31
+ export declare function pageToolMismatch(declared: readonly string[], handled: readonly string[]): {
32
+ unanswered: string[];
33
+ unused: string[];
34
+ };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Where the page's tools and the profile's disagree, for the builder: a page
3
+ * tool with no handler here leaves the model unanswered, and a handler for a
4
+ * tool the profile does not give the page never runs.
5
+ */
6
+ export function pageToolMismatch(declared, handled) {
7
+ return {
8
+ unanswered: declared.filter((name) => !handled.includes(name)),
9
+ unused: handled.filter((name) => !declared.includes(name)),
10
+ };
11
+ }
@@ -0,0 +1,13 @@
1
+ export type LiveSessionStatus = 'disconnected' | 'connecting'
2
+ /** The call dropped and the client is taking it up again. */
3
+ | 'reconnecting' | 'ready' | 'listening' | 'speaking' | 'working' | 'error';
4
+ export type LiveConnectPhase = 'socket' | 'microphone';
5
+ /** What a live call is doing, for its status line; the UI words it. */
6
+ export type LiveState = 'calling_tool' | 'connecting' | 'reconnecting' | 'requesting_mic' | 'speaking' | 'connected' | 'muted' | 'listening' | 'error' | 'ended';
7
+ export declare function liveState(args: {
8
+ status: LiveSessionStatus;
9
+ connectPhase: LiveConnectPhase | null;
10
+ toolName: string | null;
11
+ isMuted: boolean;
12
+ voiceEnabled?: boolean;
13
+ }): LiveState;
@@ -0,0 +1,22 @@
1
+ export function liveState(args) {
2
+ if (args.status === 'reconnecting')
3
+ return 'reconnecting';
4
+ if (args.toolName)
5
+ return 'calling_tool';
6
+ if (args.connectPhase === 'socket')
7
+ return 'connecting';
8
+ if (args.connectPhase === 'microphone')
9
+ return 'requesting_mic';
10
+ if (args.status === 'speaking')
11
+ return 'speaking';
12
+ if (args.status === 'listening' || args.status === 'ready') {
13
+ if (args.voiceEnabled === false)
14
+ return 'connected';
15
+ return args.isMuted ? 'muted' : 'listening';
16
+ }
17
+ if (args.status === 'connecting')
18
+ return 'connecting';
19
+ if (args.status === 'error')
20
+ return 'error';
21
+ return 'ended';
22
+ }
@@ -0,0 +1,11 @@
1
+ import type { ToolGate } from '@theoremjs/agents/kernel';
2
+ import type { ToolGateResolution } from '../tool-resume.ts';
3
+ /** A gate the user is asked to answer, for the model's call `callId`. */
4
+ export type LiveToolGatePrompt = {
5
+ callId: string;
6
+ toolName: string;
7
+ input: Record<string, unknown>;
8
+ gate: ToolGate;
9
+ };
10
+ /** The user's answer to a live gate, or `withdrawn`: the model cancelled the call, so nothing is asked. */
11
+ export type LiveGateAnswer = ToolGateResolution | 'withdrawn';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Pure client-side SDK for THEOREM Gemini 3.1 Flash Live sessions over WebSocket relay.
3
+ *
4
+ * Handles:
5
+ * - Bidirectional WebSocket connection to `/api/live/relay`.
6
+ * - 16-bit 16kHz PCM microphone audio recording & streaming.
7
+ * - Gapless 24kHz PCM / WAV model voice playback scheduling.
8
+ * - Barge-in interruption cancellation (instant audio queue flush).
9
+ * - Quiet-mic gate while model audio plays (reduces false barge-in from speaker bleed).
10
+ * - UI tool execution and response routing.
11
+ *
12
+ * @module
13
+ */
14
+ import { type SessionEventOf, type TraceRecord } from '@theoremjs/agents';
15
+ import type { LiveConnectPhase, LiveSessionStatus } from './live/live-state.ts';
16
+ import { type ExecuteToolOnRelay, type LiveToolStep } from './live-messages.ts';
17
+ import { type ClientTurnEvent } from './transport.ts';
18
+ export type { LiveConnection, LiveSocket } from './live-messages.ts';
19
+ import type { LiveSocket } from './live-messages.ts';
20
+ export interface LiveClientOptions {
21
+ profile?: string;
22
+ /** The host's own JSON for its relay, sent as the open message's `host`. */
23
+ openMessage?: Record<string, unknown>;
24
+ /** The value chosen for each of the profile's `inputs.slots`, fixed for the call. */
25
+ slots?: Record<string, string>;
26
+ /** What the page tells the agent as the call opens; `setContext` replaces it during the call. */
27
+ context?: unknown;
28
+ relayUrl?: string;
29
+ /** In-process connections reuse the same microphone, playback, and tool client. */
30
+ createSocket?: () => LiveSocket;
31
+ /** When false, skip microphone capture; session still receives model audio. */
32
+ voiceIngress?: boolean;
33
+ onStatusChange?: (status: LiveSessionStatus) => void;
34
+ onConnectPhase?: (phase: LiveConnectPhase | null) => void;
35
+ onTranscript?: (text: string, isUser: boolean, meta?: {
36
+ interim?: boolean;
37
+ }) => void;
38
+ /**
39
+ * Every event the session sends, `unsupported` for a kind this client does
40
+ * not know, and `malformed` for one that failed its check (left out; the call goes on).
41
+ */
42
+ onTurnEvent?: (event: ClientTurnEvent) => void;
43
+ /** A trace record the session wrote, when the relay delivers them. */
44
+ onTrace?: (record: TraceRecord) => void;
45
+ /** A failure, typed by kind; word it with `clientFailure` and the interface's `labels`. */
46
+ onError?: (error: Error) => void;
47
+ /** Provider signalled the upstream session is draining (e.g. goAway). */
48
+ onSessionClosing?: (timeLeftMs?: number) => void;
49
+ /**
50
+ * The provider ended the session after warning it would: not a failure.
51
+ * `session.message` is the user's line; `session.ended` the close, for the builder.
52
+ */
53
+ onSessionEnded?: (session: SessionEventOf<'ended'>) => void;
54
+ /**
55
+ * The model called a tool. The host runs it with `executeToolOnRelay` and
56
+ * answers its gates; the session answers the model. A throw reaches `onError`.
57
+ */
58
+ onToolCall: (name: string, args: Record<string, unknown>, meta: {
59
+ callId: string;
60
+ operationId: string;
61
+ }) => Promise<void>;
62
+ /** The relay opened the call: the id it gave the call, and the profile it runs. */
63
+ onSessionReady?: (info: {
64
+ sessionId?: string;
65
+ profile?: string;
66
+ }) => void;
67
+ onVolumeLevel?: (level: number, isUser: boolean) => void;
68
+ }
69
+ export declare class LiveSessionClient {
70
+ private ws;
71
+ private audioContext;
72
+ private micStream;
73
+ private micSource;
74
+ private micWorklet;
75
+ private micWorkletModuleLoaded;
76
+ private playbackNodes;
77
+ private playbackBus;
78
+ private playbackAnalyser;
79
+ private playbackMeterFrame;
80
+ private playbackMeterBuffer;
81
+ private nextPlaybackTime;
82
+ private status;
83
+ /** Server reported background work (reasoning / async tools) still in flight. */
84
+ private serverWorking;
85
+ private micActivating;
86
+ private connectTimeout;
87
+ private isMuted;
88
+ private options;
89
+ /** Serialize control-plane handling (tools / status) without waiting on audio decode. */
90
+ private inboundChain;
91
+ /** Ordered model-audio playback queue (separate so tools are not stuck behind decode). */
92
+ private audioChain;
93
+ /**
94
+ * Tool calls, one at a time in the order the model made them. Apart from
95
+ * `inboundChain`: a call waits on the relay's reply, which arrives inbound.
96
+ */
97
+ private toolChain;
98
+ /** Bumped on barge-in / cancel so stale audioChain work is skipped. */
99
+ private audioEpoch;
100
+ private pendingExecuteResults;
101
+ /** The page's context package, and the JSON of the one the relay last got. */
102
+ private context;
103
+ private sentContext;
104
+ /** The provider's latest handle for taking this call up again after a drop. */
105
+ private history;
106
+ private providerState;
107
+ /** The session said it ended, or failed: a close after that is the end, not a drop. */
108
+ private sessionOver;
109
+ /** When the call dropped, for the time away a resume reports. */
110
+ private droppedAt;
111
+ /** When the call that could not reconnect dropped: the next call takes it up again. */
112
+ private lostAt;
113
+ private reconnectTries;
114
+ private reconnectTimer;
115
+ constructor(options: LiveClientOptions);
116
+ private setStatus;
117
+ /** Still opening: the first connect, or a try at taking a dropped call up again. */
118
+ private get opening();
119
+ private setConnectPhase;
120
+ private clearConnectTimeout;
121
+ private detachWebSocket;
122
+ private clearReconnect;
123
+ private teardownConnection;
124
+ /** End the session on `error`: a failed connect or a lost socket. */
125
+ private failSession;
126
+ private createSocket;
127
+ /**
128
+ * Start a call. After one that dropped and could not reconnect, it takes that call up again,
129
+ * so the agent neither greets twice nor forgets; after a hang-up it is a new call.
130
+ */
131
+ connect(): Promise<void>;
132
+ /** A lost call that cannot be taken up again, its handle refused or expired, starts as a new one. */
133
+ private startOver;
134
+ /** The first message: the call's values, and the handle and time away when it takes a dropped call up again. */
135
+ private openMessage;
136
+ /** The socket closed while the call was open: take it up again if the provider gave a handle, else end. */
137
+ private handleDrop;
138
+ private scheduleReconnect;
139
+ /** A try at opening failed: a reconnect waits and tries again, a first connect fails the call. */
140
+ private failOpen;
141
+ private open;
142
+ private ensureAudioContext;
143
+ private activateMicrophone;
144
+ private sendMicFrame;
145
+ private reportMicVolume;
146
+ private forwardMicBuffer;
147
+ private setupMicrophonePipeline;
148
+ private ensurePlaybackBus;
149
+ private stopPlaybackMeter;
150
+ private startPlaybackMeter;
151
+ private processServerEnvelope;
152
+ private enqueueServerMessage;
153
+ private handleReadyEnvelope;
154
+ /** The call is open, first or again: the page's context catches up with what changed meanwhile. */
155
+ private becomeReady;
156
+ private handleExecuteToolResultEnvelope;
157
+ private tryHandleControlEnvelope;
158
+ private collectInboundTurn;
159
+ private processTurnEvent;
160
+ private handleEvidenceTurnEvent;
161
+ private handleSessionTurnEvent;
162
+ /** Hand the session's closing and end to the host; `true` when it was one of them. */
163
+ private notifySessionLifecycle;
164
+ /** Status to settle into once model speech stops. */
165
+ private restingStatus;
166
+ private collectMediaTurnEvent;
167
+ private handleDoneTurnEvent;
168
+ private scheduleMediaChunks;
169
+ /** The relay runs `LiveSession.executeTool`; see `ExecuteToolOnRelay`. */
170
+ executeToolOnRelay(args: Parameters<ExecuteToolOnRelay>[0]): Promise<LiveToolStep>;
171
+ private enqueueAudioChunk;
172
+ cancelPlayback(): void;
173
+ toggleMute(): boolean;
174
+ sendText(text: string): void;
175
+ /**
176
+ * The call's slot values. An open call is taken up again with them when the provider gave a
177
+ * handle; with none, the next call has them.
178
+ */
179
+ setSlots(slots: Record<string, string> | undefined): void;
180
+ /**
181
+ * Replace the page's context package. In a call it reaches the agent as
182
+ * background, with no reply; before one, it goes with the call's opening.
183
+ */
184
+ setContext(context: unknown): void;
185
+ private flushContext;
186
+ sendVideo(data: string, mimeType?: string): void;
187
+ disconnect(): void;
188
+ private cleanupAudio;
189
+ }