@theoremjs/react 0.0.0-stage → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +246 -2
- package/client/attachment-hover-preview.d.ts +11 -0
- package/client/attachment-hover-preview.js +36 -0
- package/client/audio-level.d.ts +5 -0
- package/client/audio-level.js +24 -0
- package/client/composer-attachments.d.ts +30 -0
- package/client/composer-attachments.js +33 -0
- package/client/composer-drawer.d.ts +19 -0
- package/client/composer-drawer.js +15 -0
- package/client/composer-hints.d.ts +25 -0
- package/client/composer-hints.js +20 -0
- package/client/composer-primary.d.ts +16 -0
- package/client/composer-primary.js +25 -0
- package/client/decision-transport.d.ts +48 -0
- package/client/decision-transport.js +102 -0
- package/client/decode-composer-draft.d.ts +11 -0
- package/client/decode-composer-draft.js +12 -0
- package/client/encode-composer-draft.d.ts +9 -0
- package/client/encode-composer-draft.js +34 -0
- package/client/encode-files.d.ts +18 -0
- package/client/encode-files.js +54 -0
- package/client/failure.d.ts +32 -0
- package/client/failure.js +34 -0
- package/client/generation-selection.d.ts +15 -0
- package/client/generation-selection.js +24 -0
- package/client/host-call.d.ts +51 -0
- package/client/host-call.js +42 -0
- package/client/host-transport.d.ts +68 -0
- package/client/host-transport.js +74 -0
- package/client/image-output.d.ts +6 -0
- package/client/image-output.js +13 -0
- package/client/index.d.ts +20 -0
- package/client/index.js +18 -0
- package/client/ink-waveform.d.ts +17 -0
- package/client/ink-waveform.js +69 -0
- package/client/live/apply-live-turn-tool-event.d.ts +14 -0
- package/client/live/apply-live-turn-tool-event.js +39 -0
- package/client/live/live-captions.d.ts +23 -0
- package/client/live/live-captions.js +70 -0
- package/client/live/live-mic-forward.d.ts +29 -0
- package/client/live/live-mic-forward.js +37 -0
- package/client/live/live-state.d.ts +11 -0
- package/client/live/live-state.js +20 -0
- package/client/live/live-tool.d.ts +11 -0
- package/client/live/live-tool.js +1 -0
- package/client/live/live-video.d.ts +10 -0
- package/client/live/live-video.js +71 -0
- package/client/live/run-live-tool-call.d.ts +17 -0
- package/client/live/run-live-tool-call.js +32 -0
- package/client/live-client.d.ts +141 -0
- package/client/live-client.js +638 -0
- package/client/live-errors.d.ts +2 -0
- package/client/live-errors.js +9 -0
- package/client/live-messages.d.ts +110 -0
- package/client/live-messages.js +67 -0
- package/client/mic-capture.d.ts +4 -0
- package/client/mic-capture.js +6 -0
- package/client/oauth-popup.d.ts +26 -0
- package/client/oauth-popup.js +30 -0
- package/client/pcm-downsample.d.ts +4 -0
- package/client/pcm-downsample.js +45 -0
- package/client/run-commit.d.ts +61 -0
- package/client/run-commit.js +124 -0
- package/client/run-session.d.ts +80 -0
- package/client/run-session.js +215 -0
- package/client/schema-fields.d.ts +63 -0
- package/client/schema-fields.js +178 -0
- package/client/shaped-data.d.ts +118 -0
- package/client/shaped-data.js +314 -0
- package/client/source-citations.d.ts +13 -0
- package/client/source-citations.js +56 -0
- package/client/state-fields.d.ts +16 -0
- package/client/state-fields.js +44 -0
- package/client/tool-result.d.ts +78 -0
- package/client/tool-result.js +275 -0
- package/client/tool-resume.d.ts +33 -0
- package/client/tool-resume.js +11 -0
- package/client/trace-feed.d.ts +13 -0
- package/client/trace-feed.js +18 -0
- package/client/trace-story.d.ts +163 -0
- package/client/trace-story.js +416 -0
- package/client/trace-view.d.ts +130 -0
- package/client/trace-view.js +293 -0
- package/client/transcript-groups.d.ts +114 -0
- package/client/transcript-groups.js +167 -0
- package/client/transcript-scroll.d.ts +7 -0
- package/client/transcript-scroll.js +6 -0
- package/client/transport.d.ts +176 -0
- package/client/transport.js +256 -0
- package/client/turn-client.d.ts +35 -0
- package/client/turn-client.js +93 -0
- package/client/voice-label.d.ts +2 -0
- package/client/voice-label.js +15 -0
- package/client/voice-recorder.d.ts +27 -0
- package/client/voice-recorder.js +165 -0
- package/client/walk-away.d.ts +34 -0
- package/client/walk-away.js +48 -0
- package/client/wire-line.d.ts +56 -0
- package/client/wire-line.js +90 -0
- package/client/worklets/mic-capture.js +16 -0
- package/components/InkWaveform.d.ts +10 -0
- package/components/InkWaveform.js +108 -0
- package/components/live/use-live-runner-controls.d.ts +48 -0
- package/components/live/use-live-runner-controls.js +100 -0
- package/components/live/use-live-runner-model.d.ts +45 -0
- package/components/live/use-live-runner-model.js +175 -0
- package/components/live/use-live-runner-ui.d.ts +65 -0
- package/components/live/use-live-runner-ui.js +159 -0
- package/components/live/use-live-session-client.d.ts +41 -0
- package/components/live/use-live-session-client.js +123 -0
- package/components/use-composer-voice.d.ts +28 -0
- package/components/use-composer-voice.js +90 -0
- package/components/use-editor-selection.d.ts +3 -0
- package/components/use-editor-selection.js +16 -0
- package/components/use-voice-playback.d.ts +16 -0
- package/components/use-voice-playback.js +68 -0
- package/hooks/use-described.d.ts +8 -0
- package/hooks/use-described.js +23 -0
- package/hooks/use-theorem-chat-actions.d.ts +75 -0
- package/hooks/use-theorem-chat-actions.js +265 -0
- package/hooks/use-theorem-chat-state.d.ts +66 -0
- package/hooks/use-theorem-chat-state.js +118 -0
- package/hooks/use-theorem-chat.d.ts +63 -0
- package/hooks/use-theorem-chat.js +340 -0
- package/hooks/use-theorem-decision.d.ts +23 -0
- package/hooks/use-theorem-decision.js +75 -0
- package/hooks/use-theorem-host.d.ts +44 -0
- package/hooks/use-theorem-host.js +117 -0
- package/hooks/use-theorem-interface.d.ts +19 -0
- package/hooks/use-theorem-interface.js +25 -0
- package/hooks/use-trace-records.d.ts +4 -0
- package/hooks/use-trace-records.js +7 -0
- package/index.d.ts +14 -0
- package/index.js +14 -0
- package/live.d.ts +8 -0
- package/live.js +10 -0
- package/package.json +73 -4
- package/server/credential-store.d.ts +24 -0
- package/server/credential-store.js +14 -0
- package/server/decision-handler.d.ts +34 -0
- package/server/decision-handler.js +55 -0
- package/server/handler.d.ts +114 -0
- package/server/handler.js +568 -0
- package/server/json-response.d.ts +2 -0
- package/server/json-response.js +7 -0
- package/server/mod.d.ts +16 -0
- package/server/mod.js +15 -0
- package/server/request-check.d.ts +16 -0
- package/server/request-check.js +34 -0
- package/server/session-store.d.ts +74 -0
- package/server/session-store.js +49 -0
- package/server/steer-inbox.d.ts +35 -0
- package/server/steer-inbox.js +52 -0
- package/server/walk-away.d.ts +22 -0
- package/server/walk-away.js +41 -0
- package/styles/ink-controls.css +134 -0
- package/ui/ChatComposerBar.d.ts +39 -0
- package/ui/ChatComposerBar.js +251 -0
- package/ui/ChatTranscript.d.ts +30 -0
- package/ui/ChatTranscript.js +474 -0
- package/ui/ConsoleFrame.d.ts +47 -0
- package/ui/ConsoleFrame.js +46 -0
- package/ui/DecisionAnswers.d.ts +15 -0
- package/ui/DecisionAnswers.js +102 -0
- package/ui/LiveRunner.d.ts +28 -0
- package/ui/LiveRunner.js +193 -0
- package/ui/SchemaFields.d.ts +10 -0
- package/ui/SchemaFields.js +122 -0
- package/ui/ShapedData.d.ts +11 -0
- package/ui/ShapedData.js +151 -0
- package/ui/SidePanel.d.ts +57 -0
- package/ui/SidePanel.js +50 -0
- package/ui/StateFields.d.ts +36 -0
- package/ui/StateFields.js +96 -0
- package/ui/TheoremChat.d.ts +71 -0
- package/ui/TheoremChat.js +146 -0
- package/ui/TheoremDecision.d.ts +38 -0
- package/ui/TheoremDecision.js +87 -0
- package/ui/TheoremHost.d.ts +38 -0
- package/ui/TheoremHost.js +150 -0
- package/ui/ToolGateCard.d.ts +28 -0
- package/ui/ToolGateCard.js +100 -0
- package/ui/ToolResult.d.ts +10 -0
- package/ui/ToolResult.js +60 -0
- package/ui/ToolResultCharts.d.ts +5 -0
- package/ui/ToolResultCharts.js +86 -0
- package/ui/TraceCharts.d.ts +13 -0
- package/ui/TraceCharts.js +235 -0
- package/ui/TraceGuardrails.d.ts +10 -0
- package/ui/TraceGuardrails.js +56 -0
- package/ui/TraceInspector.d.ts +6 -0
- package/ui/TraceInspector.js +189 -0
- package/ui/TraceInspectorPanel.d.ts +24 -0
- package/ui/TraceInspectorPanel.js +57 -0
- package/ui/TraceOverview.d.ts +34 -0
- package/ui/TraceOverview.js +96 -0
- package/ui/TraceSpanDetail.d.ts +10 -0
- package/ui/TraceSpanDetail.js +188 -0
- package/ui/TraceStory.d.ts +20 -0
- package/ui/TraceStory.js +107 -0
- package/ui/TraceValues.d.ts +36 -0
- package/ui/TraceValues.js +113 -0
- package/ui/TraceWaterfall.d.ts +13 -0
- package/ui/TraceWaterfall.js +132 -0
- package/ui/VoiceNote.d.ts +12 -0
- package/ui/VoiceNote.js +28 -0
- package/ui/built/theme.css +774 -0
- package/ui/built/theorem.d.ts +13 -0
- package/ui/built/theorem.js +631 -0
- package/ui/built/theorem.variants.d.ts +16 -0
- package/ui/disclosure-motion.d.ts +6 -0
- package/ui/disclosure-motion.js +163 -0
- package/ui/icons.d.ts +4 -0
- package/ui/icons.js +37 -0
- package/ui/index.d.ts +25 -0
- package/ui/index.js +29 -0
- package/ui/labels-provider.d.ts +16 -0
- package/ui/labels-provider.js +61 -0
- package/ui/labels.d.ts +1153 -0
- package/ui/labels.js +603 -0
- package/ui/theme.d.ts +10 -0
- package/ui/theme.js +13 -0
- package/ui/theorem-theme.d.ts +10 -0
- package/ui/theorem-theme.js +83 -0
- package/ui/trace-palette.d.ts +24 -0
- package/ui/trace-palette.js +24 -0
- package/ui/trace-patterns.d.ts +32 -0
- package/ui/trace-patterns.js +44 -0
- package/ui/transcript-copy-text.d.ts +4 -0
- package/ui/transcript-copy-text.js +39 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transport contract between a Theorem chat UI and the host that runs turns.
|
|
3
|
+
*
|
|
4
|
+
* The browser never holds the profile: it asks the transport to `describe` the
|
|
5
|
+
* profile's client-safe interface, then streams turns / tool invokes through it.
|
|
6
|
+
* `createHttpTransport` speaks to `createTheoremHandler` (`@theoremjs/react/server`);
|
|
7
|
+
* hosts with their own wire format implement {@link TheoremTransport} directly.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import { type ErrorKind, type TurnEvent, type TurnHistoryMessage, type TurnToolSnapshot, z } from '@theoremjs/agents';
|
|
12
|
+
import { type ProfileInterface } from '@theoremjs/agents/interface';
|
|
13
|
+
import type { TraceFeed } from './trace-feed.ts';
|
|
14
|
+
import { type MalformedEvent, type UnsupportedEvent, type WireLines } from './wire-line.ts';
|
|
15
|
+
export type { MalformedEvent, UnsupportedEvent, WireLines } from './wire-line.ts';
|
|
16
|
+
export type EncodedBlob = {
|
|
17
|
+
name: string;
|
|
18
|
+
mimeType: string;
|
|
19
|
+
data: string;
|
|
20
|
+
};
|
|
21
|
+
/** Turn input as sent over the wire (media is base64-encoded). */
|
|
22
|
+
export type TheoremTurnInput = {
|
|
23
|
+
text?: string;
|
|
24
|
+
attachments?: EncodedBlob[];
|
|
25
|
+
voice?: EncodedBlob[];
|
|
26
|
+
history?: TurnHistoryMessage[];
|
|
27
|
+
historyTokens?: number;
|
|
28
|
+
inputTokens?: number;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* State only the client holds, for hosts whose profile also lives in the browser
|
|
32
|
+
* (the playground). `createHttpTransport` never sends it: `createTheoremHandler`
|
|
33
|
+
* keeps permissions, paused calls, and tool snapshots in its own session.
|
|
34
|
+
*/
|
|
35
|
+
export type TheoremReplay = {
|
|
36
|
+
sessionPermissions?: string[];
|
|
37
|
+
name?: string;
|
|
38
|
+
input?: unknown;
|
|
39
|
+
turnInput?: TheoremTurnInput;
|
|
40
|
+
snapshot?: TurnToolSnapshot;
|
|
41
|
+
promoted?: string[];
|
|
42
|
+
model?: string;
|
|
43
|
+
effort?: string;
|
|
44
|
+
path?: string;
|
|
45
|
+
};
|
|
46
|
+
/** For a host that reads the playground's client-held state. */
|
|
47
|
+
export declare const theoremReplaySchema: z.ZodType<TheoremReplay>;
|
|
48
|
+
/**
|
|
49
|
+
* One text turn. The host resolves the profile; the client sends the conversation.
|
|
50
|
+
*
|
|
51
|
+
* A message sent while the reply waits on gates walks away from them: `abandon`
|
|
52
|
+
* names the waiting calls, and `input.history` ends on their step with those
|
|
53
|
+
* calls open. The host settles each one cancelled, streams those events first,
|
|
54
|
+
* and gives the model each call's answer before the message.
|
|
55
|
+
*/
|
|
56
|
+
export type TheoremTurnRequest = {
|
|
57
|
+
input: TheoremTurnInput;
|
|
58
|
+
previousInteractionId?: string;
|
|
59
|
+
model?: string;
|
|
60
|
+
effort?: string;
|
|
61
|
+
/** Client-generated id so mid-turn steers can find this turn's inbox. */
|
|
62
|
+
turnId?: string;
|
|
63
|
+
/** Call ids of the paused calls this message walks away from. */
|
|
64
|
+
abandon?: string[];
|
|
65
|
+
replay?: Pick<TheoremReplay, 'sessionPermissions'> & {
|
|
66
|
+
/** Each walked-away call as the client holds it, by call id, for a host without a session. */
|
|
67
|
+
abandon?: Record<string, TheoremReplay>;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
/** A `/turn` body as `createTheoremHandler` reads it. */
|
|
71
|
+
export declare const theoremTurnRequestSchema: z.ZodType<TheoremTurnRequest>;
|
|
72
|
+
/** What the user answers a gate with; walking away rides on the next message (`TheoremTurnRequest.abandon`). */
|
|
73
|
+
declare const INVOKE_DECISIONS: readonly ["approve", "deny"];
|
|
74
|
+
/**
|
|
75
|
+
* The user's answer to a tool call the host paused on a gate. `approve` runs it
|
|
76
|
+
* (with `input` when the user edited it); `deny` refuses it. The host settles
|
|
77
|
+
* each one, so the model and the trace read what the user chose. The tool's
|
|
78
|
+
* registered permission decides how long an approval lasts, not the client.
|
|
79
|
+
*/
|
|
80
|
+
export type TheoremInvokeRequest = {
|
|
81
|
+
/** Call id of the paused tool call (`tool.callId` on its gate event). */
|
|
82
|
+
gateId: string;
|
|
83
|
+
decision: (typeof INVOKE_DECISIONS)[number];
|
|
84
|
+
/** The user's edit of the model's input; only with `approve`. */
|
|
85
|
+
input?: unknown;
|
|
86
|
+
/**
|
|
87
|
+
* The key or token the user typed at a bearer or API-key sign-in gate, only
|
|
88
|
+
* with `approve`. The server saves it for the session and never sends it
|
|
89
|
+
* back; an OAuth gate resumes with the gate id alone, once the host's
|
|
90
|
+
* callback saved the token.
|
|
91
|
+
*/
|
|
92
|
+
secret?: string;
|
|
93
|
+
replay?: TheoremReplay;
|
|
94
|
+
};
|
|
95
|
+
/** An `/invoke` body as `createTheoremHandler` reads it. */
|
|
96
|
+
export declare const theoremInvokeRequestSchema: z.ZodType<TheoremInvokeRequest>;
|
|
97
|
+
/** Inject user messages into an in-flight turn. */
|
|
98
|
+
export type TheoremSteerRequest = {
|
|
99
|
+
turnId: string;
|
|
100
|
+
/** The client's id for this steer; the turn's `stage` event names it in `injected` once it lands. */
|
|
101
|
+
id: string;
|
|
102
|
+
inject: TurnHistoryMessage[];
|
|
103
|
+
};
|
|
104
|
+
/** A `/steer` body as `createTheoremHandler` reads it. */
|
|
105
|
+
export declare const theoremSteerRequestSchema: z.ZodType<TheoremSteerRequest>;
|
|
106
|
+
/** A turn event, one of a kind this client does not know (`unsupported`), or one that failed its check (`malformed`). */
|
|
107
|
+
export type ClientTurnEvent = TurnEvent | UnsupportedEvent | MalformedEvent;
|
|
108
|
+
export type TurnEventSink = (event: ClientTurnEvent) => void;
|
|
109
|
+
export interface TheoremTransport {
|
|
110
|
+
/** Client-safe interface for the host's profile (inputs, models, guardrail view). */
|
|
111
|
+
describe(signal?: AbortSignal): Promise<ProfileInterface>;
|
|
112
|
+
turn(request: TheoremTurnRequest, onEvent: TurnEventSink, signal?: AbortSignal): Promise<void>;
|
|
113
|
+
invoke(request: TheoremInvokeRequest, onEvent: TurnEventSink, signal?: AbortSignal): Promise<void>;
|
|
114
|
+
steer(request: TheoremSteerRequest): Promise<void>;
|
|
115
|
+
/** Trace records the host sends back, when it delivers them (the playground does). */
|
|
116
|
+
traces?: TraceFeed;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* A failure the host reported: its kind, the host's wording when it sent one
|
|
120
|
+
* (the profile's lexicon, applied on the host), and raw detail when the host
|
|
121
|
+
* exposes it. `clientFailure` words it for the user.
|
|
122
|
+
*/
|
|
123
|
+
export declare class TheoremStreamError extends Error {
|
|
124
|
+
readonly kind: ErrorKind;
|
|
125
|
+
readonly publicMessage?: string;
|
|
126
|
+
readonly internalMessage?: string;
|
|
127
|
+
constructor(kind: ErrorKind, publicMessage?: string, internalMessage?: string);
|
|
128
|
+
}
|
|
129
|
+
export declare function isTheoremStreamError(err: unknown): err is TheoremStreamError;
|
|
130
|
+
/** A host error reply's body (JSON reply or `{ type: 'error' }` stream line). */
|
|
131
|
+
export type HostErrorBody = {
|
|
132
|
+
error?: string;
|
|
133
|
+
errorKind?: ErrorKind;
|
|
134
|
+
errorInternal?: string;
|
|
135
|
+
};
|
|
136
|
+
/** A host's error body, as the transport and the live client read it. */
|
|
137
|
+
export declare const hostErrorBodySchema: z.ZodType<HostErrorBody>;
|
|
138
|
+
/** A host's error body as a failure: its kind (else `fallbackKind`), wording, and detail. */
|
|
139
|
+
export declare function hostError(body: HostErrorBody, fallbackKind: ErrorKind): TheoremStreamError;
|
|
140
|
+
/**
|
|
141
|
+
* Read an NDJSON reply, checking each line against `lines`: a kind it doesn't
|
|
142
|
+
* list reaches `onLine` as `unsupported`, and a line that fails its check as
|
|
143
|
+
* `malformed`; the stream goes on. An `error` line ends it.
|
|
144
|
+
*/
|
|
145
|
+
export declare function readNdjsonStream<Line extends {
|
|
146
|
+
type: string;
|
|
147
|
+
}>(response: Response, lines: WireLines<Line>, onLine: (line: Line | UnsupportedEvent | MalformedEvent) => void, signal?: AbortSignal): Promise<void>;
|
|
148
|
+
export type HttpOptions = {
|
|
149
|
+
fetch?: typeof fetch;
|
|
150
|
+
/** Extra request headers (auth tokens, CSRF). A function is re-read per request. */
|
|
151
|
+
headers?: HeadersInit | (() => HeadersInit | Promise<HeadersInit>);
|
|
152
|
+
/** Cookie policy. Default `same-origin`; use `include` when the handler is on another origin. */
|
|
153
|
+
credentials?: RequestCredentials;
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* POST JSON and stream NDJSON lines back, each checked against `lines`: turn
|
|
157
|
+
* events ({@link TURN_EVENT_SCHEMAS}), or a host's own schema beside them.
|
|
158
|
+
*/
|
|
159
|
+
export declare function postNdjson<Line extends {
|
|
160
|
+
type: string;
|
|
161
|
+
}>(url: string, body: unknown, lines: WireLines<Line>, onLine: (line: Line | UnsupportedEvent | MalformedEvent) => void, options?: HttpOptions & {
|
|
162
|
+
signal?: AbortSignal;
|
|
163
|
+
}): Promise<void>;
|
|
164
|
+
/** POST JSON; a non-OK reply throws its failure. The OK reply's body is not read. */
|
|
165
|
+
export declare function postJson(url: string, body: unknown, options?: HttpOptions): Promise<void>;
|
|
166
|
+
/** GET, or POST `body` as JSON, and read the JSON reply; a non-OK reply throws its failure. */
|
|
167
|
+
export declare function fetchJson(url: string, init: {
|
|
168
|
+
body?: unknown;
|
|
169
|
+
signal?: AbortSignal;
|
|
170
|
+
}, options?: HttpOptions): Promise<unknown>;
|
|
171
|
+
export type HttpTransportOptions = HttpOptions & {
|
|
172
|
+
/** Base URL where `createTheoremHandler` is mounted. Default `/api/theorem`. */
|
|
173
|
+
endpoint?: string;
|
|
174
|
+
};
|
|
175
|
+
/** Transport for a host mounted with `createTheoremHandler`. */
|
|
176
|
+
export declare function createHttpTransport(options?: HttpTransportOptions): TheoremTransport;
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transport contract between a Theorem chat UI and the host that runs turns.
|
|
3
|
+
*
|
|
4
|
+
* The browser never holds the profile: it asks the transport to `describe` the
|
|
5
|
+
* profile's client-safe interface, then streams turns / tool invokes through it.
|
|
6
|
+
* `createHttpTransport` speaks to `createTheoremHandler` (`@theoremjs/react/server`);
|
|
7
|
+
* hosts with their own wire format implement {@link TheoremTransport} directly.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import { describeError, errorKindSchema, isAbortError, TheoremError, TURN_EVENT_SCHEMAS, throwIfAborted, turnHistoryMessageSchema, turnToolSnapshotSchema, z, } from '@theoremjs/agents';
|
|
12
|
+
import { kindOfHttpStatus } from '@theoremjs/agents/guardrails';
|
|
13
|
+
import { profileInterfaceSchema } from '@theoremjs/agents/interface';
|
|
14
|
+
import { checkWire, parseWireJson, readWireLine, } from "./wire-line.js";
|
|
15
|
+
const encodedBlob = z.object({ name: z.string(), mimeType: z.string(), data: z.string() });
|
|
16
|
+
true;
|
|
17
|
+
const theoremTurnInput = z.object({
|
|
18
|
+
text: z.string().optional(),
|
|
19
|
+
attachments: z.array(encodedBlob).optional(),
|
|
20
|
+
voice: z.array(encodedBlob).optional(),
|
|
21
|
+
history: z.array(turnHistoryMessageSchema).optional(),
|
|
22
|
+
historyTokens: z.number().optional(),
|
|
23
|
+
inputTokens: z.number().optional(),
|
|
24
|
+
});
|
|
25
|
+
true;
|
|
26
|
+
const theoremReplay = z.object({
|
|
27
|
+
sessionPermissions: z.array(z.string()).optional(),
|
|
28
|
+
name: z.string().optional(),
|
|
29
|
+
input: z.unknown().optional(),
|
|
30
|
+
turnInput: theoremTurnInput.optional(),
|
|
31
|
+
snapshot: turnToolSnapshotSchema.optional(),
|
|
32
|
+
promoted: z.array(z.string()).optional(),
|
|
33
|
+
model: z.string().optional(),
|
|
34
|
+
effort: z.string().optional(),
|
|
35
|
+
path: z.string().optional(),
|
|
36
|
+
});
|
|
37
|
+
true;
|
|
38
|
+
/** For a host that reads the playground's client-held state. */
|
|
39
|
+
export const theoremReplaySchema = theoremReplay;
|
|
40
|
+
/** An id the client made: trimmed, never blank. */
|
|
41
|
+
const clientId = z.string().trim().min(1);
|
|
42
|
+
const theoremTurnRequest = z.object({
|
|
43
|
+
input: theoremTurnInput,
|
|
44
|
+
previousInteractionId: z.string().optional(),
|
|
45
|
+
model: z.string().optional(),
|
|
46
|
+
effort: z.string().optional(),
|
|
47
|
+
turnId: clientId.optional(),
|
|
48
|
+
abandon: z.array(z.string().min(1)).min(1).optional(),
|
|
49
|
+
replay: theoremReplay
|
|
50
|
+
.pick({ sessionPermissions: true })
|
|
51
|
+
.extend({ abandon: z.record(z.string(), theoremReplay).optional() })
|
|
52
|
+
.optional(),
|
|
53
|
+
});
|
|
54
|
+
true;
|
|
55
|
+
/** A `/turn` body as `createTheoremHandler` reads it. */
|
|
56
|
+
export const theoremTurnRequestSchema = theoremTurnRequest;
|
|
57
|
+
/** What the user answers a gate with; walking away rides on the next message (`TheoremTurnRequest.abandon`). */
|
|
58
|
+
const INVOKE_DECISIONS = ['approve', 'deny'];
|
|
59
|
+
const theoremInvokeRequest = z.object({
|
|
60
|
+
gateId: z.string().min(1),
|
|
61
|
+
decision: z.enum(INVOKE_DECISIONS),
|
|
62
|
+
input: z.unknown().optional(),
|
|
63
|
+
secret: z.string().optional(),
|
|
64
|
+
replay: theoremReplay.optional(),
|
|
65
|
+
});
|
|
66
|
+
true;
|
|
67
|
+
/** An `/invoke` body as `createTheoremHandler` reads it. */
|
|
68
|
+
export const theoremInvokeRequestSchema = theoremInvokeRequest;
|
|
69
|
+
const theoremSteerRequest = z.object({
|
|
70
|
+
turnId: clientId,
|
|
71
|
+
id: clientId,
|
|
72
|
+
inject: z.array(turnHistoryMessageSchema).min(1),
|
|
73
|
+
});
|
|
74
|
+
true;
|
|
75
|
+
/** A `/steer` body as `createTheoremHandler` reads it. */
|
|
76
|
+
export const theoremSteerRequestSchema = theoremSteerRequest;
|
|
77
|
+
/**
|
|
78
|
+
* A failure the host reported: its kind, the host's wording when it sent one
|
|
79
|
+
* (the profile's lexicon, applied on the host), and raw detail when the host
|
|
80
|
+
* exposes it. `clientFailure` words it for the user.
|
|
81
|
+
*/
|
|
82
|
+
export class TheoremStreamError extends Error {
|
|
83
|
+
kind;
|
|
84
|
+
publicMessage;
|
|
85
|
+
internalMessage;
|
|
86
|
+
constructor(kind, publicMessage, internalMessage) {
|
|
87
|
+
super(internalMessage ?? publicMessage ?? kind);
|
|
88
|
+
this.name = 'TheoremStreamError';
|
|
89
|
+
this.kind = kind;
|
|
90
|
+
if (publicMessage)
|
|
91
|
+
this.publicMessage = publicMessage;
|
|
92
|
+
if (internalMessage)
|
|
93
|
+
this.internalMessage = internalMessage;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
export function isTheoremStreamError(err) {
|
|
97
|
+
return err instanceof TheoremStreamError;
|
|
98
|
+
}
|
|
99
|
+
/** The trimmed string, or undefined when absent or blank. */
|
|
100
|
+
function textOf(value) {
|
|
101
|
+
return value?.trim() || undefined;
|
|
102
|
+
}
|
|
103
|
+
const hostErrorBody = z.object({
|
|
104
|
+
error: z.string().optional(),
|
|
105
|
+
errorKind: errorKindSchema.optional(),
|
|
106
|
+
errorInternal: z.string().optional(),
|
|
107
|
+
});
|
|
108
|
+
true;
|
|
109
|
+
/** A host's error body, as the transport and the live client read it. */
|
|
110
|
+
export const hostErrorBodySchema = hostErrorBody;
|
|
111
|
+
/** A host's error body as a failure: its kind (else `fallbackKind`), wording, and detail. */
|
|
112
|
+
export function hostError(body, fallbackKind) {
|
|
113
|
+
const publicMessage = textOf(body.error);
|
|
114
|
+
const internal = textOf(body.errorInternal);
|
|
115
|
+
return new TheoremStreamError(body.errorKind ?? fallbackKind, publicMessage, internal && internal !== publicMessage ? internal : undefined);
|
|
116
|
+
}
|
|
117
|
+
/** One NDJSON line checked against `lines`; an `error` line ends the stream as a {@link TheoremStreamError}. */
|
|
118
|
+
function parseStreamLine(lines, text) {
|
|
119
|
+
const line = readWireLine(lines, text);
|
|
120
|
+
// An `error` line passed the error event's schema, whose fields include the body's.
|
|
121
|
+
if (line.type === 'error')
|
|
122
|
+
throw hostError(hostErrorBody.parse(line), 'internal');
|
|
123
|
+
return line;
|
|
124
|
+
}
|
|
125
|
+
function flushNdjsonChunk(buffer, lines, onLine) {
|
|
126
|
+
const chunks = buffer.split('\n');
|
|
127
|
+
const rest = chunks.pop() ?? '';
|
|
128
|
+
for (const chunk of chunks) {
|
|
129
|
+
if (!chunk.trim())
|
|
130
|
+
continue;
|
|
131
|
+
onLine(parseStreamLine(lines, chunk));
|
|
132
|
+
}
|
|
133
|
+
return rest;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Read an NDJSON reply, checking each line against `lines`: a kind it doesn't
|
|
137
|
+
* list reaches `onLine` as `unsupported`, and a line that fails its check as
|
|
138
|
+
* `malformed`; the stream goes on. An `error` line ends it.
|
|
139
|
+
*/
|
|
140
|
+
export async function readNdjsonStream(response, lines, onLine, signal) {
|
|
141
|
+
if (!response.body)
|
|
142
|
+
throw new TheoremError('bad_response', 'stream reply has no body'); // lexicon-exempt: internal diagnostic
|
|
143
|
+
const reader = response.body.getReader();
|
|
144
|
+
const decoder = new TextDecoder();
|
|
145
|
+
let buffer = '';
|
|
146
|
+
const onAbort = () => {
|
|
147
|
+
void reader.cancel();
|
|
148
|
+
};
|
|
149
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
150
|
+
try {
|
|
151
|
+
for (;;) {
|
|
152
|
+
throwIfAborted(signal);
|
|
153
|
+
const { done, value } = await reader.read();
|
|
154
|
+
if (done)
|
|
155
|
+
break;
|
|
156
|
+
buffer = flushNdjsonChunk(buffer + decoder.decode(value, { stream: true }), lines, onLine);
|
|
157
|
+
}
|
|
158
|
+
const tail = buffer.trim();
|
|
159
|
+
if (tail)
|
|
160
|
+
onLine(parseStreamLine(lines, tail));
|
|
161
|
+
}
|
|
162
|
+
finally {
|
|
163
|
+
signal?.removeEventListener('abort', onAbort);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
async function resolveHeaders(options) {
|
|
167
|
+
const extra = typeof options.headers === 'function' ? await options.headers() : options.headers;
|
|
168
|
+
const headers = new Headers(extra);
|
|
169
|
+
headers.set('content-type', 'application/json');
|
|
170
|
+
return headers;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* A non-OK reply as a failure: the host's kind and wording, else the status's
|
|
174
|
+
* kind. A body that is not JSON (a proxy's page) leaves the status to speak; a
|
|
175
|
+
* JSON body that fails the error body's schema is `bad_response`.
|
|
176
|
+
*/
|
|
177
|
+
async function failureFromResponse(response) {
|
|
178
|
+
const text = await response.text();
|
|
179
|
+
let raw;
|
|
180
|
+
try {
|
|
181
|
+
raw = JSON.parse(text);
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
return hostError({ errorInternal: `HTTP ${String(response.status)}` }, kindOfHttpStatus(response.status));
|
|
185
|
+
}
|
|
186
|
+
const body = hostErrorBody.safeParse(raw);
|
|
187
|
+
if (!body.success) {
|
|
188
|
+
// lexicon-exempt: internal diagnostic; the user reads error.bad_response
|
|
189
|
+
return new TheoremError('bad_response', `HTTP ${String(response.status)} error body failed its wire check`);
|
|
190
|
+
}
|
|
191
|
+
return hostError({ ...body.data, errorInternal: body.data.errorInternal ?? `HTTP ${String(response.status)}` }, kindOfHttpStatus(response.status));
|
|
192
|
+
}
|
|
193
|
+
async function request(url, init, options) {
|
|
194
|
+
const doFetch = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
195
|
+
try {
|
|
196
|
+
return await doFetch(url, {
|
|
197
|
+
...init,
|
|
198
|
+
headers: await resolveHeaders(options),
|
|
199
|
+
credentials: options.credentials ?? 'same-origin',
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
if (isAbortError(err))
|
|
204
|
+
throw err;
|
|
205
|
+
throw new TheoremError('network', describeError(err), { cause: err });
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* POST JSON and stream NDJSON lines back, each checked against `lines`: turn
|
|
210
|
+
* events ({@link TURN_EVENT_SCHEMAS}), or a host's own schema beside them.
|
|
211
|
+
*/
|
|
212
|
+
export async function postNdjson(url, body, lines, onLine, options = {}) {
|
|
213
|
+
const response = await request(url, { method: 'POST', body: JSON.stringify(body), signal: options.signal }, options);
|
|
214
|
+
if (!response.ok)
|
|
215
|
+
throw await failureFromResponse(response);
|
|
216
|
+
await readNdjsonStream(response, lines, onLine, options.signal);
|
|
217
|
+
}
|
|
218
|
+
/** POST JSON; a non-OK reply throws its failure. The OK reply's body is not read. */
|
|
219
|
+
export async function postJson(url, body, options = {}) {
|
|
220
|
+
const response = await request(url, { method: 'POST', body: JSON.stringify(body) }, options);
|
|
221
|
+
if (!response.ok)
|
|
222
|
+
throw await failureFromResponse(response);
|
|
223
|
+
}
|
|
224
|
+
/** GET, or POST `body` as JSON, and read the JSON reply; a non-OK reply throws its failure. */
|
|
225
|
+
export async function fetchJson(url, init, options = {}) {
|
|
226
|
+
const method = init.body === undefined ? { method: 'GET' } : { method: 'POST', body: JSON.stringify(init.body) };
|
|
227
|
+
const response = await request(url, { ...method, signal: init.signal }, options);
|
|
228
|
+
if (!response.ok)
|
|
229
|
+
throw await failureFromResponse(response);
|
|
230
|
+
return parseWireJson(await response.text());
|
|
231
|
+
}
|
|
232
|
+
/** Drops trailing '/'s by scanning back, not with a regex (a `/\/+$/` scan is quadratic on long runs of '/'). */
|
|
233
|
+
function withoutTrailingSlashes(url) {
|
|
234
|
+
let end = url.length;
|
|
235
|
+
while (end > 0 && url[end - 1] === '/')
|
|
236
|
+
end -= 1;
|
|
237
|
+
return url.slice(0, end);
|
|
238
|
+
}
|
|
239
|
+
/** The host's `describe` reply. */
|
|
240
|
+
const describedSchema = z.object({ interface: profileInterfaceSchema });
|
|
241
|
+
/** Transport for a host mounted with `createTheoremHandler`. */
|
|
242
|
+
export function createHttpTransport(options = {}) {
|
|
243
|
+
const base = withoutTrailingSlashes(options.endpoint ?? '/api/theorem');
|
|
244
|
+
return {
|
|
245
|
+
async describe(signal) {
|
|
246
|
+
const response = await request(base, { method: 'GET', signal }, options);
|
|
247
|
+
if (!response.ok)
|
|
248
|
+
throw await failureFromResponse(response);
|
|
249
|
+
// lexicon-exempt: internal diagnostic; the user reads error.bad_response
|
|
250
|
+
return checkWire(describedSchema, parseWireJson(await response.text()), 'the profile description').interface;
|
|
251
|
+
},
|
|
252
|
+
turn: ({ replay: _replay, ...body }, onEvent, signal) => postNdjson(`${base}/turn`, body, TURN_EVENT_SCHEMAS, onEvent, { ...options, signal }),
|
|
253
|
+
invoke: ({ replay: _replay, ...body }, onEvent, signal) => postNdjson(`${base}/invoke`, body, TURN_EVENT_SCHEMAS, onEvent, { ...options, signal }),
|
|
254
|
+
steer: (body) => postJson(`${base}/steer`, body, options),
|
|
255
|
+
};
|
|
256
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { TurnEvent } from '@theoremjs/agents';
|
|
2
|
+
import { type AttachmentValidationIssue, type ComposerProfileInterface, type GatedToolContext, type InterfaceTurnSession, type TranscriptBlock, type UserTurnDraft } from '@theoremjs/agents/interface';
|
|
3
|
+
import type { TheoremInvokeRequest, TheoremTurnInput, TheoremTurnRequest } from './transport.ts';
|
|
4
|
+
export declare function turnInputFromSession(session: InterfaceTurnSession, overrides?: TheoremTurnInput): TheoremTurnInput;
|
|
5
|
+
/** A gated call as the client holds it, for a host without a session (the playground). */
|
|
6
|
+
export type HeldCall = {
|
|
7
|
+
name: string;
|
|
8
|
+
/** The model's input to the call. */
|
|
9
|
+
input: unknown;
|
|
10
|
+
sessionPermissions?: string[];
|
|
11
|
+
};
|
|
12
|
+
/** A paused session, and the calls it waits on that a message walks away from. */
|
|
13
|
+
export type WalkAway = {
|
|
14
|
+
paused: InterfaceTurnSession;
|
|
15
|
+
calls: readonly GatedToolContext[];
|
|
16
|
+
};
|
|
17
|
+
export declare function buildTurnRequest(iface: ComposerProfileInterface, session: InterfaceTurnSession, input: TheoremTurnInput, options?: {
|
|
18
|
+
turnId?: string;
|
|
19
|
+
walkAway?: WalkAway;
|
|
20
|
+
}): TheoremTurnRequest;
|
|
21
|
+
export declare function buildInvokeRequest(iface: ComposerProfileInterface, session: InterfaceTurnSession, args: HeldCall & {
|
|
22
|
+
gateId: string;
|
|
23
|
+
decision: TheoremInvokeRequest['decision'];
|
|
24
|
+
secret?: string;
|
|
25
|
+
}): TheoremInvokeRequest;
|
|
26
|
+
export declare function projectUserTurn(iface: ComposerProfileInterface, draft: UserTurnDraft): {
|
|
27
|
+
ok: true;
|
|
28
|
+
blocks: TranscriptBlock[];
|
|
29
|
+
draft: UserTurnDraft;
|
|
30
|
+
} | {
|
|
31
|
+
ok: false;
|
|
32
|
+
issues: AttachmentValidationIssue[];
|
|
33
|
+
};
|
|
34
|
+
export declare function prepareComposerTurn(iface: ComposerProfileInterface, text: string, pendingFiles: readonly File[], pendingVoice?: readonly File[]): ReturnType<typeof projectUserTurn>;
|
|
35
|
+
export declare function foldAssistantTurn(iface: ComposerProfileInterface, events: readonly TurnEvent[]): TranscriptBlock[];
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { foldTurnEvents, prepareUserTurn, streamThoughtsEnabled, } from '@theoremjs/agents/interface';
|
|
2
|
+
import { filesToPending } from "./encode-files.js";
|
|
3
|
+
import { defaultModel } from "./generation-selection.js";
|
|
4
|
+
export function turnInputFromSession(session, overrides = {}) {
|
|
5
|
+
return {
|
|
6
|
+
...overrides,
|
|
7
|
+
history: session.history,
|
|
8
|
+
...(session.inputTokens !== undefined ? { inputTokens: session.inputTokens } : {}),
|
|
9
|
+
...(session.historyTokens !== undefined ? { historyTokens: session.historyTokens } : {}),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function resolveModelId(iface, session) {
|
|
13
|
+
return session.selectedModel ?? defaultModel(iface);
|
|
14
|
+
}
|
|
15
|
+
function resolveEffort(iface, session, modelId) {
|
|
16
|
+
if (!modelId || !Object.hasOwn(iface.models, modelId))
|
|
17
|
+
return undefined;
|
|
18
|
+
const binding = iface.models[modelId];
|
|
19
|
+
if (!binding.allowEffortSelect)
|
|
20
|
+
return undefined;
|
|
21
|
+
return session.selectedEffort ?? binding.defaultEffort;
|
|
22
|
+
}
|
|
23
|
+
/** Model / effort selection the host should honour for this session. */
|
|
24
|
+
function generationFields(iface, session) {
|
|
25
|
+
const modelId = resolveModelId(iface, session);
|
|
26
|
+
const model = iface.allowModelSelect ? modelId : undefined;
|
|
27
|
+
const effort = resolveEffort(iface, session, modelId);
|
|
28
|
+
return { ...(model ? { model } : {}), ...(effort ? { effort } : {}) };
|
|
29
|
+
}
|
|
30
|
+
function gateReplay(iface, session, call) {
|
|
31
|
+
return {
|
|
32
|
+
name: call.name,
|
|
33
|
+
input: call.input,
|
|
34
|
+
sessionPermissions: call.sessionPermissions ?? session.sessionPermissions,
|
|
35
|
+
turnInput: turnInputFromSession(session),
|
|
36
|
+
...(session.toolSnapshot ? { snapshot: session.toolSnapshot } : {}),
|
|
37
|
+
...(session.promotedToolIds.length ? { promoted: [...session.promotedToolIds] } : {}),
|
|
38
|
+
...generationFields(iface, session),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The paused calls a message walks away from: their ids, and each call as a
|
|
43
|
+
* host without a session replays it, from the session as it paused.
|
|
44
|
+
*/
|
|
45
|
+
function abandonFields(iface, walkAway) {
|
|
46
|
+
if (!walkAway.calls.length)
|
|
47
|
+
return undefined;
|
|
48
|
+
return {
|
|
49
|
+
abandon: walkAway.calls.map((call) => call.callId),
|
|
50
|
+
replays: Object.fromEntries(walkAway.calls.map((call) => [
|
|
51
|
+
call.callId,
|
|
52
|
+
gateReplay(iface, walkAway.paused, { name: call.name, input: call.arguments }),
|
|
53
|
+
])),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export function buildTurnRequest(iface, session, input, options = {}) {
|
|
57
|
+
const walked = options.walkAway ? abandonFields(iface, options.walkAway) : undefined;
|
|
58
|
+
return {
|
|
59
|
+
previousInteractionId: session.previousInteractionId,
|
|
60
|
+
...(options.turnId ? { turnId: options.turnId } : {}),
|
|
61
|
+
...generationFields(iface, session),
|
|
62
|
+
input,
|
|
63
|
+
...(walked ? { abandon: walked.abandon } : {}),
|
|
64
|
+
replay: {
|
|
65
|
+
sessionPermissions: session.sessionPermissions,
|
|
66
|
+
...(walked ? { abandon: walked.replays } : {}),
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export function buildInvokeRequest(iface, session, args) {
|
|
71
|
+
return {
|
|
72
|
+
gateId: args.gateId,
|
|
73
|
+
decision: args.decision,
|
|
74
|
+
...(args.secret === undefined ? {} : { secret: args.secret }),
|
|
75
|
+
replay: gateReplay(iface, session, args),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
export function projectUserTurn(iface, draft) {
|
|
79
|
+
return prepareUserTurn(iface.inputs, draft, iface.guardrails);
|
|
80
|
+
}
|
|
81
|
+
export function prepareComposerTurn(iface, text, pendingFiles, pendingVoice = []) {
|
|
82
|
+
return projectUserTurn(iface, {
|
|
83
|
+
...(text.trim() ? { text } : {}),
|
|
84
|
+
...(pendingFiles.length ? { attachments: filesToPending(pendingFiles) } : {}),
|
|
85
|
+
...(pendingVoice.length ? { voice: filesToPending(pendingVoice) } : {}),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
export function foldAssistantTurn(iface, events) {
|
|
89
|
+
// Its `turn-done` blocks stay: hidden in the view, they carry the reply's worked time.
|
|
90
|
+
return foldTurnEvents(events, {
|
|
91
|
+
showThoughts: streamThoughtsEnabled(iface.outputs),
|
|
92
|
+
});
|
|
93
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** A voice note's audio format (`webm`, `wav`, `mp3`, `m4a`, `ogg`) from its MIME type; undefined when unknown. */
|
|
2
|
+
export function voiceFormatFromMime(mime) {
|
|
3
|
+
const lower = mime.toLowerCase();
|
|
4
|
+
if (lower.includes('webm'))
|
|
5
|
+
return 'webm';
|
|
6
|
+
if (lower.includes('wav'))
|
|
7
|
+
return 'wav';
|
|
8
|
+
if (lower.includes('mpeg') || lower.includes('mp3'))
|
|
9
|
+
return 'mp3';
|
|
10
|
+
if (lower.includes('mp4') || lower.includes('m4a') || lower.includes('aac'))
|
|
11
|
+
return 'm4a';
|
|
12
|
+
if (lower.includes('ogg'))
|
|
13
|
+
return 'ogg';
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Why recording failed; the user reads lexicon `voice.<code>`. */
|
|
2
|
+
export type VoiceRecorderFailureCode = 'unsupported' | 'permission' | 'unavailable' | 'failed' | 'empty';
|
|
3
|
+
/** Headless MediaRecorder session for turn-composer voice notes. */
|
|
4
|
+
export declare class ComposerVoiceRecorder {
|
|
5
|
+
private readonly accept;
|
|
6
|
+
private readonly onLevel?;
|
|
7
|
+
private stream;
|
|
8
|
+
private recorder;
|
|
9
|
+
private chunks;
|
|
10
|
+
private audioContext;
|
|
11
|
+
private analyser;
|
|
12
|
+
private source;
|
|
13
|
+
private rafId;
|
|
14
|
+
private mime;
|
|
15
|
+
private recording;
|
|
16
|
+
constructor(accept: string[], onLevel?: ((level: number) => void) | undefined);
|
|
17
|
+
start(): Promise<void>;
|
|
18
|
+
stop(): Promise<File>;
|
|
19
|
+
cancel(): void;
|
|
20
|
+
dispose(): void;
|
|
21
|
+
private startMeter;
|
|
22
|
+
private stopMeter;
|
|
23
|
+
private disposeTracks;
|
|
24
|
+
}
|
|
25
|
+
export declare function isVoiceRecorderFailure(value: unknown): value is Error & {
|
|
26
|
+
readonly code: VoiceRecorderFailureCode;
|
|
27
|
+
};
|