@theoremjs/web 0.0.0-stage → 0.3.4-next.375.ga2d1878

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 (128) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +493 -2
  3. package/client/audio-level.d.ts +5 -0
  4. package/client/audio-level.js +24 -0
  5. package/client/chat.d.ts +144 -0
  6. package/client/chat.js +760 -0
  7. package/client/composer-drawer.d.ts +19 -0
  8. package/client/composer-drawer.js +15 -0
  9. package/client/composer-hints.d.ts +25 -0
  10. package/client/composer-hints.js +20 -0
  11. package/client/composer-primary.d.ts +18 -0
  12. package/client/composer-primary.js +29 -0
  13. package/client/decision-transport.d.ts +70 -0
  14. package/client/decision-transport.js +175 -0
  15. package/client/decode-composer-draft.d.ts +11 -0
  16. package/client/decode-composer-draft.js +12 -0
  17. package/client/embedding-input.d.ts +84 -0
  18. package/client/embedding-input.js +194 -0
  19. package/client/embedding-space.d.ts +82 -0
  20. package/client/embedding-space.js +389 -0
  21. package/client/embedding-transport.d.ts +40 -0
  22. package/client/embedding-transport.js +71 -0
  23. package/client/encode-composer-draft.d.ts +9 -0
  24. package/client/encode-composer-draft.js +34 -0
  25. package/client/encode-files.d.ts +18 -0
  26. package/client/encode-files.js +54 -0
  27. package/client/failure.d.ts +29 -0
  28. package/client/failure.js +34 -0
  29. package/client/generation-selection.d.ts +15 -0
  30. package/client/generation-selection.js +24 -0
  31. package/client/host-transport.d.ts +70 -0
  32. package/client/host-transport.js +75 -0
  33. package/client/index.d.ts +37 -0
  34. package/client/index.js +31 -0
  35. package/client/live/live-mic-forward.d.ts +30 -0
  36. package/client/live/live-mic-forward.js +46 -0
  37. package/client/live/live-page-tool.d.ts +39 -0
  38. package/client/live/live-page-tool.js +26 -0
  39. package/client/live/live-state.d.ts +13 -0
  40. package/client/live/live-state.js +22 -0
  41. package/client/live/live-tool.d.ts +11 -0
  42. package/client/live/live-tool.js +1 -0
  43. package/client/live-client.d.ts +189 -0
  44. package/client/live-client.js +829 -0
  45. package/client/live-errors.d.ts +2 -0
  46. package/client/live-errors.js +9 -0
  47. package/client/live-messages.d.ts +148 -0
  48. package/client/live-messages.js +100 -0
  49. package/client/mic-capture.d.ts +4 -0
  50. package/client/mic-capture.js +6 -0
  51. package/client/oauth-popup.d.ts +26 -0
  52. package/client/oauth-popup.js +30 -0
  53. package/client/page-dispatch.d.ts +15 -0
  54. package/client/page-dispatch.js +63 -0
  55. package/client/pcm-downsample.d.ts +4 -0
  56. package/client/pcm-downsample.js +45 -0
  57. package/client/run-commit.d.ts +34 -0
  58. package/client/run-commit.js +49 -0
  59. package/client/run-session.d.ts +79 -0
  60. package/client/run-session.js +207 -0
  61. package/client/schema-fields.d.ts +63 -0
  62. package/client/schema-fields.js +199 -0
  63. package/client/shaped-data.d.ts +118 -0
  64. package/client/shaped-data.js +343 -0
  65. package/client/source-citations.d.ts +13 -0
  66. package/client/source-citations.js +56 -0
  67. package/client/space-geometry.d.ts +39 -0
  68. package/client/space-geometry.js +183 -0
  69. package/client/tool-result.d.ts +78 -0
  70. package/client/tool-result.js +293 -0
  71. package/client/tool-resume.d.ts +50 -0
  72. package/client/tool-resume.js +14 -0
  73. package/client/trace-feed.d.ts +13 -0
  74. package/client/trace-feed.js +18 -0
  75. package/client/transcript-schema.d.ts +10 -0
  76. package/client/transcript-schema.js +120 -0
  77. package/client/transport.d.ts +264 -0
  78. package/client/transport.js +330 -0
  79. package/client/turn-client.d.ts +44 -0
  80. package/client/turn-client.js +88 -0
  81. package/client/wire-line.d.ts +56 -0
  82. package/client/wire-line.js +90 -0
  83. package/client/worklets/mic-capture.js +16 -0
  84. package/package.json +28 -4
  85. package/server/checkpoint-ownership.d.ts +6 -0
  86. package/server/checkpoint-ownership.js +42 -0
  87. package/server/conversation-store.d.ts +92 -0
  88. package/server/conversation-store.js +131 -0
  89. package/server/conversation.d.ts +193 -0
  90. package/server/conversation.js +552 -0
  91. package/server/credential-store.d.ts +24 -0
  92. package/server/credential-store.js +14 -0
  93. package/server/decision-handler.d.ts +42 -0
  94. package/server/decision-handler.js +46 -0
  95. package/server/embedding-handler.d.ts +33 -0
  96. package/server/embedding-handler.js +45 -0
  97. package/server/handler.d.ts +158 -0
  98. package/server/handler.js +775 -0
  99. package/server/json-response.d.ts +2 -0
  100. package/server/json-response.js +7 -0
  101. package/server/mcp-handler.d.ts +46 -0
  102. package/server/mcp-handler.js +312 -0
  103. package/server/mod.d.ts +27 -0
  104. package/server/mod.js +25 -0
  105. package/server/page-dispatch.d.ts +22 -0
  106. package/server/page-dispatch.js +127 -0
  107. package/server/request-body.d.ts +2 -0
  108. package/server/request-body.js +42 -0
  109. package/server/request-check.d.ts +21 -0
  110. package/server/request-check.js +49 -0
  111. package/server/session-authority.d.ts +8 -0
  112. package/server/session-authority.js +78 -0
  113. package/server/session-boundary.d.ts +26 -0
  114. package/server/session-boundary.js +64 -0
  115. package/server/session-identity.d.ts +16 -0
  116. package/server/session-identity.js +41 -0
  117. package/server/session-limits.d.ts +12 -0
  118. package/server/session-limits.js +59 -0
  119. package/server/session-store.d.ts +123 -0
  120. package/server/session-store.js +264 -0
  121. package/server/single-action.d.ts +21 -0
  122. package/server/single-action.js +30 -0
  123. package/server/steer-inbox.d.ts +35 -0
  124. package/server/steer-inbox.js +52 -0
  125. package/server/tool-operations.d.ts +6 -0
  126. package/server/tool-operations.js +132 -0
  127. package/server/turn-input.d.ts +10 -0
  128. package/server/turn-input.js +29 -0
@@ -0,0 +1,40 @@
1
+ import { type EmbeddingInput, type EmbeddingProfile, type EmbeddingResult, type EmbeddingRules, type EmbeddingTask, type Protocol, type TraceRecord } from '@theoremjs/agents';
2
+ import type { TraceFeed } from './trace-feed.ts';
3
+ import { type HttpOptions } from './transport.ts';
4
+ export type EmbeddingInterface = {
5
+ type: 'embedding';
6
+ identity: {
7
+ handle: string;
8
+ };
9
+ /** The profile's inputs held to what its default model takes. */
10
+ inputs: EmbeddingRules;
11
+ observability?: {
12
+ record: boolean;
13
+ };
14
+ };
15
+ /**
16
+ * The interface a client reads: the profile's inputs held to its default model's limits. Pass
17
+ * `protocols` when a model speaks a protocol of your own.
18
+ */
19
+ export declare function embeddingInterface(profile: Pick<EmbeddingProfile, 'identity' | 'inputs' | 'observability' | 'models' | 'defaultModel'>, protocols?: readonly Protocol[]): EmbeddingInterface;
20
+ export type EmbeddingReply = {
21
+ result: EmbeddingResult;
22
+ traces?: TraceRecord[];
23
+ };
24
+ /** What an embedding asks beyond its inputs: a named model, and what the inputs are for. */
25
+ export type EmbedOptions = {
26
+ model?: string;
27
+ task?: EmbeddingTask;
28
+ };
29
+ export interface EmbeddingTransport {
30
+ describe(signal?: AbortSignal): Promise<EmbeddingInterface>;
31
+ embed(input: EmbeddingInput | readonly EmbeddingInput[], options?: EmbedOptions, signal?: AbortSignal): Promise<EmbeddingReply>;
32
+ traces?: TraceFeed;
33
+ }
34
+ export declare function readEmbeddingReply(raw: unknown): EmbeddingReply;
35
+ /** POSTs an embedding and reads its reply; a failure keeps the trace records its body carried. */
36
+ export declare function postEmbedding(url: string, body: unknown, signal: AbortSignal | undefined, options?: HttpOptions): Promise<EmbeddingReply>;
37
+ /** Transport for a host mounted with `createTheoremEmbeddingHandler`. Default endpoint `/api/embedding`. */
38
+ export declare function createEmbeddingTransport(options?: HttpOptions & {
39
+ endpoint?: string;
40
+ }): EmbeddingTransport;
@@ -0,0 +1,71 @@
1
+ import { embeddingModelLimits, embeddingRules, resolveObservabilityPolicy, traceRecordSchema, z, } from '@theoremjs/agents';
2
+ import { postWithTraces } from "./decision-transport.js";
3
+ import { fetchJson } from "./transport.js";
4
+ import { checkWire } from "./wire-line.js";
5
+ /**
6
+ * The interface a client reads: the profile's inputs held to its default model's limits. Pass
7
+ * `protocols` when a model speaks a protocol of your own.
8
+ */
9
+ export function embeddingInterface(profile, protocols = []) {
10
+ const binding = profile.models[profile.defaultModel];
11
+ return {
12
+ type: 'embedding',
13
+ identity: { handle: profile.identity.handle },
14
+ inputs: embeddingRules(profile.inputs, binding ? embeddingModelLimits(binding, protocols) : undefined),
15
+ ...(profile.observability
16
+ ? { observability: { record: resolveObservabilityPolicy(profile.observability).record } }
17
+ : {}),
18
+ };
19
+ }
20
+ const embeddingReplySchema = z.object({
21
+ result: z.object({
22
+ model: z.string().min(1),
23
+ embeddings: z.array(z
24
+ .object({
25
+ index: z.number().int().nonnegative(),
26
+ values: z.array(z.number()),
27
+ dimensions: z.number().int().positive(),
28
+ })
29
+ .refine((embedding) => embedding.values.length === embedding.dimensions, 'vector length must match dimensions')),
30
+ usage: z
31
+ .object({
32
+ inputTokens: z.number().int().nonnegative().optional(),
33
+ costUsd: z.number().nonnegative().optional(),
34
+ estimated: z.literal(true).optional(),
35
+ })
36
+ .optional(),
37
+ }),
38
+ traces: z.array(traceRecordSchema).optional(),
39
+ });
40
+ const describedSchema = z.object({
41
+ interface: z.object({
42
+ type: z.literal('embedding'),
43
+ identity: z.object({ handle: z.string() }),
44
+ inputs: z.object({
45
+ text: z.boolean(),
46
+ attachments: z.object({ accept: z.array(z.string()) }).optional(),
47
+ maxFiles: z.number().optional(),
48
+ maxBytes: z.number().optional(),
49
+ maxTurnBytes: z.number().optional(),
50
+ limitsByMime: z.record(z.string(), z.number()).optional(),
51
+ }),
52
+ observability: z.object({ record: z.boolean() }).optional(),
53
+ }),
54
+ });
55
+ export function readEmbeddingReply(raw) {
56
+ return checkWire(embeddingReplySchema, raw, 'the embedding');
57
+ }
58
+ /** POSTs an embedding and reads its reply; a failure keeps the trace records its body carried. */
59
+ export function postEmbedding(url, body, signal, options = {}) {
60
+ return postWithTraces(url, body, signal, options, readEmbeddingReply);
61
+ }
62
+ /** Transport for a host mounted with `createTheoremEmbeddingHandler`. Default endpoint `/api/embedding`. */
63
+ export function createEmbeddingTransport(options = {}) {
64
+ const base = (options.endpoint ?? '/api/embedding').replace(/\/$/, '');
65
+ return {
66
+ async describe(signal) {
67
+ return checkWire(describedSchema, await fetchJson(base, { signal }, options), 'the embedding description').interface;
68
+ },
69
+ embed: (input, embed, signal) => postEmbedding(`${base}/embed`, { input, ...embed }, signal, options),
70
+ };
71
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Encode composer fields into a serializable `UserTurnDraft` for pending intents.
3
+ */
4
+ import type { UserTurnDraft } from '@theoremjs/agents/interface';
5
+ export declare function encodeComposerDraft(args: {
6
+ text: string;
7
+ pendingFiles?: readonly File[];
8
+ pendingVoice?: readonly File[];
9
+ }): Promise<UserTurnDraft>;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Encode composer fields into a serializable `UserTurnDraft` for pending intents.
3
+ */
4
+ import { encodeFiles } from "./encode-files.js";
5
+ export async function encodeComposerDraft(args) {
6
+ const text = args.text.trim();
7
+ const files = args.pendingFiles ?? [];
8
+ const voice = args.pendingVoice ?? [];
9
+ const encodedFiles = files.length ? await encodeFiles(files) : [];
10
+ const encodedVoice = voice.length ? await encodeFiles(voice) : [];
11
+ return {
12
+ ...(text ? { text } : {}),
13
+ ...(encodedFiles.length
14
+ ? {
15
+ attachments: encodedFiles.map((blob, index) => ({
16
+ name: blob.name,
17
+ mimeType: blob.mimeType,
18
+ sizeBytes: files[index]?.size ?? 0,
19
+ data: blob.data,
20
+ })),
21
+ }
22
+ : {}),
23
+ ...(encodedVoice.length
24
+ ? {
25
+ voice: encodedVoice.map((blob, index) => ({
26
+ name: blob.name,
27
+ mimeType: blob.mimeType,
28
+ sizeBytes: voice[index]?.size ?? 0,
29
+ data: blob.data,
30
+ })),
31
+ }
32
+ : {}),
33
+ };
34
+ }
@@ -0,0 +1,18 @@
1
+ import type { PendingAttachment, TranscriptBlock } from '@theoremjs/agents/interface';
2
+ export declare function filesToPending(files: readonly File[]): PendingAttachment[];
3
+ /**
4
+ * Rebuild `File`s from encoded pending attachments (stash / queue restore).
5
+ * Attachments without `data` cannot be restored and are skipped.
6
+ */
7
+ export declare function pendingAttachmentsToFiles(attachments: readonly PendingAttachment[]): File[];
8
+ export declare function encodeFiles(files: readonly File[]): Promise<Array<{
9
+ name: string;
10
+ mimeType: string;
11
+ data: string;
12
+ }>>;
13
+ /** Copy encoded base64 onto matching user attachment/voice transcript blocks for UI preview. */
14
+ export declare function attachPreviewData(blocks: readonly TranscriptBlock[], attachments?: ReadonlyArray<{
15
+ data: string;
16
+ }>, voice?: ReadonlyArray<{
17
+ data: string;
18
+ }>): TranscriptBlock[];
@@ -0,0 +1,54 @@
1
+ import { base64ToBytes, bytesToBase64 } from '@theoremjs/agents/kernel';
2
+ export function filesToPending(files) {
3
+ return files.map((file) => ({
4
+ name: file.name,
5
+ mimeType: file.type || 'application/octet-stream',
6
+ sizeBytes: file.size,
7
+ }));
8
+ }
9
+ /**
10
+ * Rebuild `File`s from encoded pending attachments (stash / queue restore).
11
+ * Attachments without `data` cannot be restored and are skipped.
12
+ */
13
+ export function pendingAttachmentsToFiles(attachments) {
14
+ const files = [];
15
+ for (const attachment of attachments) {
16
+ if (typeof attachment.data !== 'string' || attachment.data.length === 0)
17
+ continue;
18
+ const bytes = base64ToBytes(attachment.data);
19
+ const buffer = bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
20
+ files.push(new File([buffer], attachment.name, {
21
+ type: attachment.mimeType || 'application/octet-stream',
22
+ }));
23
+ }
24
+ return files;
25
+ }
26
+ export async function encodeFiles(files) {
27
+ const out = [];
28
+ for (const file of files) {
29
+ out.push({
30
+ name: file.name,
31
+ mimeType: file.type || 'application/octet-stream',
32
+ data: bytesToBase64(new Uint8Array(await file.arrayBuffer())),
33
+ });
34
+ }
35
+ return out;
36
+ }
37
+ /** Copy encoded base64 onto matching user attachment/voice transcript blocks for UI preview. */
38
+ export function attachPreviewData(blocks, attachments, voice) {
39
+ let attachmentIndex = 0;
40
+ let voiceIndex = 0;
41
+ return blocks.map((block) => {
42
+ if (block.kind === 'user-attachment') {
43
+ const data = attachments?.[attachmentIndex]?.data;
44
+ attachmentIndex += 1;
45
+ return data !== undefined ? { ...block, data } : block;
46
+ }
47
+ if (block.kind === 'user-voice') {
48
+ const data = voice?.[voiceIndex]?.data;
49
+ voiceIndex += 1;
50
+ return data !== undefined ? { ...block, data } : block;
51
+ }
52
+ return block;
53
+ });
54
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * One failure, two worlds, in the browser: the builder reads `errorKind` and
3
+ * `errorInternal`; the user reads `error`, the profile's wording for it.
4
+ *
5
+ * @module
6
+ */
7
+ import { type ErrorKind, type LabelOverrides } from '@theoremjs/agents';
8
+ import type { AttachmentValidationIssue } from '@theoremjs/agents/interface';
9
+ export type ClientFailure = {
10
+ /** What the user reads: the host's wording, else the profile labels' for the failure. */
11
+ error: string;
12
+ errorKind: ErrorKind;
13
+ /** Raw detail for the builder; never shown to the user. */
14
+ errorInternal?: string;
15
+ };
16
+ /**
17
+ * Word a caught value for the user with the profile's `labels` (the interface's
18
+ * `labels`). A host-reported failure keeps the host's wording.
19
+ */
20
+ export declare function clientFailure(err: unknown, labels?: LabelOverrides): ClientFailure;
21
+ /** A turn that did not run or did not finish. */
22
+ export type TurnFailure = ClientFailure & {
23
+ /** The files the profile refused, one entry per reason (the kernel's check). */
24
+ issues?: AttachmentValidationIssue[];
25
+ /** The user stopped it; nothing to show. */
26
+ aborted?: boolean;
27
+ };
28
+ /** A caught value as a turn failure; an aborted `signal` marks it the user's stop. */
29
+ export declare function turnFailure(err: unknown, labels?: LabelOverrides, signal?: AbortSignal): TurnFailure;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * One failure, two worlds, in the browser: the builder reads `errorKind` and
3
+ * `errorInternal`; the user reads `error`, the profile's wording for it.
4
+ *
5
+ * @module
6
+ */
7
+ import { describeError, errorKind, labelText, publicError, } from '@theoremjs/agents';
8
+ import { isTheoremStreamError } from "./transport.js";
9
+ /**
10
+ * Word a caught value for the user with the profile's `labels` (the interface's
11
+ * `labels`). A host-reported failure keeps the host's wording.
12
+ */
13
+ export function clientFailure(err, labels) {
14
+ if (isTheoremStreamError(err)) {
15
+ return {
16
+ error: err.publicMessage ?? labelText(`error.${err.kind}`, {}, labels),
17
+ errorKind: err.kind,
18
+ ...(err.internalMessage ? { errorInternal: err.internalMessage } : {}),
19
+ };
20
+ }
21
+ const error = publicError(err, labels);
22
+ const internal = describeError(err);
23
+ return {
24
+ error,
25
+ errorKind: errorKind(err),
26
+ ...(internal && internal !== error ? { errorInternal: internal } : {}),
27
+ };
28
+ }
29
+ /** A caught value as a turn failure; an aborted `signal` marks it the user's stop. */
30
+ export function turnFailure(err, labels, signal) {
31
+ const failure = clientFailure(err, labels);
32
+ const aborted = failure.errorKind === 'cancelled' || signal?.aborted === true;
33
+ return { ...failure, ...(aborted ? { aborted: true } : {}) };
34
+ }
@@ -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,37 @@
1
+ export { float32Rms, float32RmsToLevel, INPUT_LEVEL_GAIN, timeDomainBytesToLevel, } from './audio-level.ts';
2
+ export { type ChatController, type ChatOptions, type ChatSlots, type ChatState, type ChatUpdate, createChatController, type MessageDelivery, type SentTurn, } from './chat.ts';
3
+ export { type ComposerDrawerKind, type ComposerDrawerSummary, composerDrawerSummary, } from './composer-drawer.ts';
4
+ export { type ComposerHint, isStashShortcut, resolveComposerHint, STASH_SHORTCUT, } from './composer-hints.ts';
5
+ export { type ComposerActionState, composerActionState, composerHasPayload, } from './composer-primary.ts';
6
+ export { createDecisionTransport, type DecisionInterface, type DecisionQuestionView, type DecisionReply, type DecisionTransport, decisionAssets, decisionInterface, failedDecisionTraces, failedTraces, postDecision, readDecisionReply, withFailedTraces, } from './decision-transport.ts';
7
+ export { type ComposerDraftFields, composerFieldsFromDraft } from './decode-composer-draft.ts';
8
+ 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';
9
+ export { type EmbeddingSpace, layoutSpace, layoutSpaceSoon, outlierThreshold, placeQuery, type SpaceCluster, type SpaceDocument, type SpaceLink, type SpacePoint, } from './embedding-space.ts';
10
+ export { createEmbeddingTransport, type EmbeddingInterface, type EmbeddingReply, type EmbeddingTransport, type EmbedOptions, embeddingInterface, postEmbedding, readEmbeddingReply, } from './embedding-transport.ts';
11
+ export { encodeComposerDraft } from './encode-composer-draft.ts';
12
+ export { encodeFiles, filesToPending, pendingAttachmentsToFiles } from './encode-files.ts';
13
+ export { type ClientFailure, clientFailure, type TurnFailure, turnFailure } from './failure.ts';
14
+ export { followGenerationDefaults } from './generation-selection.ts';
15
+ export { createHostTransport, HOST_TOOL_KINDS, type HostInterface, type HostToolKind, type HostToolSource, type HostToolView, type HostTransport, hostInterface, type TheoremHostCallRequest, } from './host-transport.ts';
16
+ export type { LiveCallOptions, PageTool, PageToolAnswer, PageTools, } from './live/live-page-tool.ts';
17
+ export { pageToolMismatch, warnPageToolMismatch } from './live/live-page-tool.ts';
18
+ export { type LiveConnectPhase, type LiveSessionStatus, type LiveState, liveState, } from './live/live-state.ts';
19
+ export type { LiveGateAnswer, LiveToolGatePrompt } from './live/live-tool.ts';
20
+ export type { LiveConnection } from './live-client.ts';
21
+ export { LiveSessionClient } from './live-client.ts';
22
+ export type { ExecuteToolOnRelay, LiveSocket } from './live-messages.ts';
23
+ export { isOAuthComplete, notifyOAuthComplete } from './oauth-popup.ts';
24
+ export { type PageDispatchResult, withPageToolDispatch } from './page-dispatch.ts';
25
+ export { sessionAfter, stampWorked } from './run-commit.ts';
26
+ export { keepsConversation, type RunOutcome, resumeInterfaceTool, type StreamView, streamInterfaceDraftTurn, streamInterfaceTurn, } from './run-session.ts';
27
+ export { blankRow, type JsonSchema, missingFields, type SchemaControl, type SchemaField, sampleFromSchema, schemaControl, schemaFields, withField, } from './schema-fields.ts';
28
+ 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';
29
+ export { citationsFromBlock, type SourceCitation, type SourceCitationBlock, } from './source-citations.ts';
30
+ export type { QueryMatch } from './space-geometry.ts';
31
+ export { DOT_FLOATS, FRAME_SLOT, queryGeometry, SEGMENT_FLOATS, type SpaceGeometry, spaceGeometry, } from './space-geometry.ts';
32
+ export { hasLead, layoutResult, type ResultChart, type ResultFigure, type ResultImage, type ResultLayout, type ResultMedia, returnedMedia, timeFormats, } from './tool-result.ts';
33
+ export type { AnsweringGate, ToolDecisionAction, ToolGateResolution, } from './tool-resume.ts';
34
+ export { continueGatedToolInvocation, type PersonGateResolution } from './tool-resume.ts';
35
+ export { createTraceFeed, type TraceFeed } from './trace-feed.ts';
36
+ 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';
37
+ export { buildInvokeRequest, buildTurnRequest, foldAssistantTurn, issuedOperationId, type RunScope, type WalkAway, } from './turn-client.ts';
@@ -0,0 +1,31 @@
1
+ export { float32Rms, float32RmsToLevel, INPUT_LEVEL_GAIN, timeDomainBytesToLevel, } from "./audio-level.js";
2
+ export { createChatController, } from "./chat.js";
3
+ export { composerDrawerSummary, } from "./composer-drawer.js";
4
+ export { isStashShortcut, resolveComposerHint, STASH_SHORTCUT, } from "./composer-hints.js";
5
+ export { composerActionState, composerHasPayload, } from "./composer-primary.js";
6
+ export { createDecisionTransport, decisionAssets, decisionInterface, failedDecisionTraces, failedTraces, postDecision, readDecisionReply, withFailedTraces, } from "./decision-transport.js";
7
+ export { composerFieldsFromDraft } from "./decode-composer-draft.js";
8
+ export { addUsage, checkEmbeddingInputs, checkInputs, cosineSimilarity, embeddingBatches, fieldsInput, inputFields, MAX_BATCH_INPUTS, rankMatches, readEmbeddingInput, readEmbeddingInputs, readsAsText, splitText, } from "./embedding-input.js";
9
+ export { layoutSpace, layoutSpaceSoon, outlierThreshold, placeQuery, } from "./embedding-space.js";
10
+ export { createEmbeddingTransport, embeddingInterface, postEmbedding, readEmbeddingReply, } from "./embedding-transport.js";
11
+ export { encodeComposerDraft } from "./encode-composer-draft.js";
12
+ export { encodeFiles, filesToPending, pendingAttachmentsToFiles } from "./encode-files.js";
13
+ export { clientFailure, turnFailure } from "./failure.js";
14
+ export { followGenerationDefaults } from "./generation-selection.js";
15
+ export { createHostTransport, HOST_TOOL_KINDS, hostInterface, } from "./host-transport.js";
16
+ export { pageToolMismatch, warnPageToolMismatch } from "./live/live-page-tool.js";
17
+ export { liveState, } from "./live/live-state.js";
18
+ export { LiveSessionClient } from "./live-client.js";
19
+ export { isOAuthComplete, notifyOAuthComplete } from "./oauth-popup.js";
20
+ export { withPageToolDispatch } from "./page-dispatch.js";
21
+ export { sessionAfter, stampWorked } from "./run-commit.js";
22
+ export { keepsConversation, resumeInterfaceTool, streamInterfaceDraftTurn, streamInterfaceTurn, } from "./run-session.js";
23
+ export { blankRow, missingFields, sampleFromSchema, schemaControl, schemaFields, withField, } from "./schema-fields.js";
24
+ export { fieldLabel, fieldReading, humanize, isPlain, isProse, isRow, json, MAX_ROWS, plainReading, rowHeading, shapeOf, splitFields, unpacked, withUnit, } from "./shaped-data.js";
25
+ export { citationsFromBlock, } from "./source-citations.js";
26
+ export { DOT_FLOATS, FRAME_SLOT, queryGeometry, SEGMENT_FLOATS, spaceGeometry, } from "./space-geometry.js";
27
+ export { hasLead, layoutResult, returnedMedia, timeFormats, } from "./tool-result.js";
28
+ export { continueGatedToolInvocation } from "./tool-resume.js";
29
+ export { createTraceFeed } from "./trace-feed.js";
30
+ export { CHAT_LINES, createHttpTransport, fetchConversation, fetchRewound, hostError, isTheoremStreamError, postJson, postNdjson, readNdjsonStream, TheoremStreamError, } from "./transport.js";
31
+ 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
+ }