@theoremjs/react 0.0.0-stage → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +772 -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-images.d.ts +76 -0
- package/client/decision-images.js +139 -0
- package/client/decision-transport.d.ts +70 -0
- package/client/decision-transport.js +175 -0
- package/client/decode-composer-draft.d.ts +11 -0
- package/client/decode-composer-draft.js +12 -0
- package/client/embedding-input.d.ts +84 -0
- package/client/embedding-input.js +194 -0
- package/client/embedding-space.d.ts +82 -0
- package/client/embedding-space.js +389 -0
- package/client/embedding-transport.d.ts +40 -0
- package/client/embedding-transport.js +71 -0
- package/client/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 +29 -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 +47 -0
- package/client/host-transport.d.ts +70 -0
- package/client/host-transport.js +75 -0
- package/client/image-output.d.ts +6 -0
- package/client/image-output.js +13 -0
- package/client/index.d.ts +28 -0
- package/client/index.js +22 -0
- package/client/ink-waveform.d.ts +17 -0
- package/client/ink-waveform.js +68 -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 +53 -0
- package/client/live/live-captions.js +174 -0
- package/client/live/live-mic-forward.d.ts +30 -0
- package/client/live/live-mic-forward.js +46 -0
- package/client/live/live-page-tool.d.ts +34 -0
- package/client/live/live-page-tool.js +11 -0
- package/client/live/live-state.d.ts +13 -0
- package/client/live/live-state.js +22 -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 +22 -0
- package/client/live/run-live-tool-call.js +70 -0
- package/client/live/use-live-caption-log.d.ts +17 -0
- package/client/live/use-live-caption-log.js +51 -0
- package/client/live-client.d.ts +189 -0
- package/client/live-client.js +829 -0
- package/client/live-errors.d.ts +2 -0
- package/client/live-errors.js +9 -0
- package/client/live-messages.d.ts +148 -0
- package/client/live-messages.js +100 -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/page-dispatch.d.ts +15 -0
- package/client/page-dispatch.js +63 -0
- package/client/pcm-downsample.d.ts +4 -0
- package/client/pcm-downsample.js +45 -0
- package/client/run-commit.d.ts +34 -0
- package/client/run-commit.js +49 -0
- package/client/run-session.d.ts +79 -0
- package/client/run-session.js +207 -0
- package/client/schema-fields.d.ts +63 -0
- package/client/schema-fields.js +199 -0
- package/client/shaped-data.d.ts +118 -0
- package/client/shaped-data.js +343 -0
- package/client/source-citations.d.ts +13 -0
- package/client/source-citations.js +56 -0
- package/client/space-geometry.d.ts +39 -0
- package/client/space-geometry.js +183 -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 +293 -0
- package/client/tool-resume.d.ts +50 -0
- package/client/tool-resume.js +14 -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 +440 -0
- package/client/trace-view.d.ts +130 -0
- package/client/trace-view.js +333 -0
- package/client/transcript-groups.d.ts +140 -0
- package/client/transcript-groups.js +217 -0
- package/client/transcript-schema.d.ts +10 -0
- package/client/transcript-schema.js +120 -0
- package/client/transcript-scroll.d.ts +7 -0
- package/client/transcript-scroll.js +6 -0
- package/client/transport.d.ts +264 -0
- package/client/transport.js +330 -0
- package/client/turn-client.d.ts +44 -0
- package/client/turn-client.js +88 -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 +162 -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 +21 -0
- package/components/InkWaveform.js +131 -0
- package/components/live/use-live-runner-controls.d.ts +47 -0
- package/components/live/use-live-runner-controls.js +96 -0
- package/components/live/use-live-runner-model.d.ts +49 -0
- package/components/live/use-live-runner-model.js +190 -0
- package/components/live/use-live-runner-ui.d.ts +67 -0
- package/components/live/use-live-runner-ui.js +167 -0
- package/components/live/use-live-session-client.d.ts +41 -0
- package/components/live/use-live-session-client.js +126 -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 +19 -0
- package/components/use-voice-playback.d.ts +17 -0
- package/components/use-voice-playback.js +68 -0
- package/hooks/use-described.d.ts +12 -0
- package/hooks/use-described.js +25 -0
- package/hooks/use-embedding-index.d.ts +27 -0
- package/hooks/use-embedding-index.js +43 -0
- package/hooks/use-one-call.d.ts +31 -0
- package/hooks/use-one-call.js +76 -0
- package/hooks/use-page-tool-warnings.d.ts +6 -0
- package/hooks/use-page-tool-warnings.js +25 -0
- package/hooks/use-second-ticker.d.ts +2 -0
- package/hooks/use-second-ticker.js +13 -0
- package/hooks/use-theorem-chat-actions.d.ts +79 -0
- package/hooks/use-theorem-chat-actions.js +287 -0
- package/hooks/use-theorem-chat-state.d.ts +66 -0
- package/hooks/use-theorem-chat-state.js +122 -0
- package/hooks/use-theorem-chat.d.ts +97 -0
- package/hooks/use-theorem-chat.js +528 -0
- package/hooks/use-theorem-decision.d.ts +18 -0
- package/hooks/use-theorem-decision.js +12 -0
- package/hooks/use-theorem-embedding.d.ts +18 -0
- package/hooks/use-theorem-embedding.js +12 -0
- package/hooks/use-theorem-host.d.ts +45 -0
- package/hooks/use-theorem-host.js +135 -0
- package/hooks/use-theorem-interface.d.ts +22 -0
- package/hooks/use-theorem-interface.js +15 -0
- package/hooks/use-trace-records.d.ts +4 -0
- package/hooks/use-trace-records.js +7 -0
- package/index.d.ts +17 -0
- package/index.js +17 -0
- package/live.d.ts +9 -0
- package/live.js +10 -0
- package/package.json +74 -4
- package/server/checkpoint-ownership.d.ts +6 -0
- package/server/checkpoint-ownership.js +42 -0
- package/server/conversation-store.d.ts +92 -0
- package/server/conversation-store.js +131 -0
- package/server/conversation.d.ts +193 -0
- package/server/conversation.js +552 -0
- package/server/credential-store.d.ts +24 -0
- package/server/credential-store.js +14 -0
- package/server/decision-handler.d.ts +42 -0
- package/server/decision-handler.js +46 -0
- package/server/embedding-handler.d.ts +33 -0
- package/server/embedding-handler.js +45 -0
- package/server/handler.d.ts +152 -0
- package/server/handler.js +771 -0
- package/server/json-response.d.ts +2 -0
- package/server/json-response.js +7 -0
- package/server/mod.d.ts +25 -0
- package/server/mod.js +23 -0
- package/server/page-dispatch.d.ts +22 -0
- package/server/page-dispatch.js +127 -0
- package/server/request-body.d.ts +2 -0
- package/server/request-body.js +42 -0
- package/server/request-check.d.ts +21 -0
- package/server/request-check.js +49 -0
- package/server/session-authority.d.ts +8 -0
- package/server/session-authority.js +78 -0
- package/server/session-boundary.d.ts +26 -0
- package/server/session-boundary.js +64 -0
- package/server/session-identity.d.ts +16 -0
- package/server/session-identity.js +41 -0
- package/server/session-limits.d.ts +12 -0
- package/server/session-limits.js +59 -0
- package/server/session-store.d.ts +123 -0
- package/server/session-store.js +264 -0
- package/server/single-action.d.ts +21 -0
- package/server/single-action.js +30 -0
- package/server/steer-inbox.d.ts +35 -0
- package/server/steer-inbox.js +52 -0
- package/server/tool-operations.d.ts +6 -0
- package/server/tool-operations.js +132 -0
- package/server/turn-input.d.ts +10 -0
- package/server/turn-input.js +29 -0
- package/styles/ink-controls.css +134 -0
- package/ui/CardWall.d.ts +10 -0
- package/ui/CardWall.js +61 -0
- package/ui/ChatComposerBar.d.ts +62 -0
- package/ui/ChatComposerBar.js +306 -0
- package/ui/ChatTranscript.d.ts +43 -0
- package/ui/ChatTranscript.js +527 -0
- package/ui/ConsoleFrame.d.ts +104 -0
- package/ui/ConsoleFrame.js +146 -0
- package/ui/DecisionAnswers.d.ts +53 -0
- package/ui/DecisionAnswers.js +233 -0
- package/ui/DecisionImages.d.ts +16 -0
- package/ui/DecisionImages.js +46 -0
- package/ui/EmbeddingDocuments.d.ts +78 -0
- package/ui/EmbeddingDocuments.js +278 -0
- package/ui/EmbeddingQuery.d.ts +27 -0
- package/ui/EmbeddingQuery.js +95 -0
- package/ui/EmbeddingResults.d.ts +41 -0
- package/ui/EmbeddingResults.js +165 -0
- package/ui/EmbeddingSpace.d.ts +26 -0
- package/ui/EmbeddingSpace.js +106 -0
- package/ui/LiveCaptionsPanel.d.ts +22 -0
- package/ui/LiveCaptionsPanel.js +27 -0
- package/ui/LiveRunner.d.ts +30 -0
- package/ui/LiveRunner.js +180 -0
- package/ui/PaneState.d.ts +33 -0
- package/ui/PaneState.js +50 -0
- package/ui/SchemaFields.d.ts +10 -0
- package/ui/SchemaFields.js +150 -0
- package/ui/ShapedData.d.ts +11 -0
- package/ui/ShapedData.js +196 -0
- package/ui/SidePanel.d.ts +126 -0
- package/ui/SidePanel.js +123 -0
- package/ui/StateFields.d.ts +44 -0
- package/ui/StateFields.js +139 -0
- package/ui/TheoremChat.d.ts +122 -0
- package/ui/TheoremChat.js +134 -0
- package/ui/TheoremDecision.d.ts +30 -0
- package/ui/TheoremDecision.js +130 -0
- package/ui/TheoremEmbedding.d.ts +27 -0
- package/ui/TheoremEmbedding.js +122 -0
- package/ui/TheoremHost.d.ts +55 -0
- package/ui/TheoremHost.js +240 -0
- package/ui/ToolGateCard.d.ts +32 -0
- package/ui/ToolGateCard.js +107 -0
- package/ui/ToolResult.d.ts +10 -0
- package/ui/ToolResult.js +62 -0
- package/ui/ToolResultCharts.d.ts +5 -0
- package/ui/ToolResultCharts.js +103 -0
- package/ui/TraceCharts.d.ts +13 -0
- package/ui/TraceCharts.js +266 -0
- package/ui/TraceGuardrails.d.ts +11 -0
- package/ui/TraceGuardrails.js +74 -0
- package/ui/TraceInspector.d.ts +16 -0
- package/ui/TraceInspector.js +206 -0
- package/ui/TraceInspectorPanel.d.ts +46 -0
- package/ui/TraceInspectorPanel.js +95 -0
- package/ui/TraceOverview.d.ts +38 -0
- package/ui/TraceOverview.js +126 -0
- package/ui/TraceSpanDetail.d.ts +10 -0
- package/ui/TraceSpanDetail.js +190 -0
- package/ui/TraceStory.d.ts +20 -0
- package/ui/TraceStory.js +108 -0
- package/ui/TraceValues.d.ts +36 -0
- package/ui/TraceValues.js +123 -0
- package/ui/TraceWaterfall.d.ts +13 -0
- package/ui/TraceWaterfall.js +135 -0
- package/ui/VoiceNote.d.ts +12 -0
- package/ui/VoiceNote.js +28 -0
- package/ui/approval-heading.d.ts +4 -0
- package/ui/approval-heading.js +9 -0
- package/ui/arrive.d.ts +18 -0
- package/ui/arrive.js +46 -0
- package/ui/built/theme.css +792 -0
- package/ui/built/theme.css.d.ts +9 -0
- package/ui/built/theorem.d.ts +13 -0
- package/ui/built/theorem.js +660 -0
- package/ui/built/theorem.variants.d.ts +22 -0
- package/ui/code-language.d.ts +12 -0
- package/ui/code-language.js +50 -0
- package/ui/disclosure-motion.d.ts +6 -0
- package/ui/disclosure-motion.js +207 -0
- package/ui/embedding-space-gl.d.ts +37 -0
- package/ui/embedding-space-gl.js +663 -0
- package/ui/embedding-space-view.d.ts +8 -0
- package/ui/embedding-space-view.js +8 -0
- package/ui/glide.d.ts +7 -0
- package/ui/glide.js +44 -0
- package/ui/icons.d.ts +4 -0
- package/ui/icons.js +38 -0
- package/ui/index.d.ts +36 -0
- package/ui/index.js +39 -0
- package/ui/labels-provider.d.ts +16 -0
- package/ui/labels-provider.js +64 -0
- package/ui/labels.d.ts +1442 -0
- package/ui/labels.js +1443 -0
- package/ui/markdown-plugins.d.ts +9 -0
- package/ui/markdown-plugins.js +13 -0
- package/ui/mcp-icon.d.ts +6 -0
- package/ui/mcp-icon.js +8 -0
- package/ui/row-keys.d.ts +19 -0
- package/ui/row-keys.js +33 -0
- package/ui/theme.d.ts +10 -0
- package/ui/theme.js +13 -0
- package/ui/theorem-theme.d.ts +10 -0
- package/ui/theorem-theme.js +105 -0
- package/ui/trace-palette.d.ts +10 -0
- package/ui/trace-palette.js +10 -0
- package/ui/trace-patterns.d.ts +40 -0
- package/ui/trace-patterns.js +57 -0
- package/ui/transcript-copy-text.d.ts +4 -0
- package/ui/transcript-copy-text.js +40 -0
- package/ui/wall-columns.d.ts +8 -0
- package/ui/wall-columns.js +19 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every value that reaches the browser over a wire (NDJSON lines, live
|
|
3
|
+
* envelopes) is checked against its schema here. A line or event of a kind the
|
|
4
|
+
* client does not know is reported as `unsupported`, and one that fails its
|
|
5
|
+
* check (not JSON, no kind, or a known kind that fails its schema) as
|
|
6
|
+
* `malformed`; either way the reply goes on. A whole reply that fails its check
|
|
7
|
+
* (the profile description) is `bad_response`.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import { TheoremError, z } from '@theoremjs/agents';
|
|
12
|
+
/**
|
|
13
|
+
* A line or envelope of a kind the client does not know. The server never
|
|
14
|
+
* sends it; the client's parser makes it so the host sees what arrived. Theorem
|
|
15
|
+
* shows nothing for it.
|
|
16
|
+
*/
|
|
17
|
+
export type UnsupportedEvent = {
|
|
18
|
+
type: 'unsupported';
|
|
19
|
+
received: string;
|
|
20
|
+
raw: unknown;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* A line or event that failed its wire check. The server never sends it; the
|
|
24
|
+
* client's reader makes it, leaves the line out, and the reply goes on. `error`
|
|
25
|
+
* is `bad_response`: its message names what broke, never the value, and the
|
|
26
|
+
* user reads `session.part_skipped`.
|
|
27
|
+
*/
|
|
28
|
+
export type MalformedEvent = {
|
|
29
|
+
type: 'malformed';
|
|
30
|
+
error: TheoremError;
|
|
31
|
+
};
|
|
32
|
+
/** Every kind a wire carries, and the schema a value of that kind must pass. */
|
|
33
|
+
export type WireLines<Line extends {
|
|
34
|
+
type: string;
|
|
35
|
+
}> = {
|
|
36
|
+
readonly [K in Line['type']]: z.ZodType<Extract<Line, {
|
|
37
|
+
type: K;
|
|
38
|
+
}>>;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Issue paths and codes only: a failure names what broke, never the value. A
|
|
42
|
+
* union that matched no branch lists each branch's issues.
|
|
43
|
+
*/
|
|
44
|
+
export declare function issueSummary(error: z.ZodError): string;
|
|
45
|
+
/** `raw` as `schema` reads it; one that fails is `bad_response`, naming `what`. */
|
|
46
|
+
export declare function checkWire<T>(schema: z.ZodType<T>, raw: unknown, what: string): T;
|
|
47
|
+
/** One wire value: a known kind that passed its schema, `unsupported`, or `malformed`. */
|
|
48
|
+
export declare function readWireValue<Line extends {
|
|
49
|
+
type: string;
|
|
50
|
+
}>(lines: WireLines<Line>, raw: unknown): Line | UnsupportedEvent | MalformedEvent;
|
|
51
|
+
/** One wire line's text: {@link readWireValue} of its JSON, or `malformed` when it is not JSON. */
|
|
52
|
+
export declare function readWireLine<Line extends {
|
|
53
|
+
type: string;
|
|
54
|
+
}>(lines: WireLines<Line>, text: string): Line | UnsupportedEvent | MalformedEvent;
|
|
55
|
+
/** A whole reply's JSON text as a value; text that is not JSON is `bad_response`. */
|
|
56
|
+
export declare function parseWireJson(text: string): unknown;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every value that reaches the browser over a wire (NDJSON lines, live
|
|
3
|
+
* envelopes) is checked against its schema here. A line or event of a kind the
|
|
4
|
+
* client does not know is reported as `unsupported`, and one that fails its
|
|
5
|
+
* check (not JSON, no kind, or a known kind that fails its schema) as
|
|
6
|
+
* `malformed`; either way the reply goes on. A whole reply that fails its check
|
|
7
|
+
* (the profile description) is `bad_response`.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import { TheoremError, z } from '@theoremjs/agents';
|
|
12
|
+
const wireKind = z.object({ type: z.string() });
|
|
13
|
+
function isKnown(lines, type) {
|
|
14
|
+
return Object.hasOwn(lines, type);
|
|
15
|
+
}
|
|
16
|
+
function issuesSummary(issues, at) {
|
|
17
|
+
return issues
|
|
18
|
+
.map((issue) => {
|
|
19
|
+
const path = [...at, ...issue.path];
|
|
20
|
+
const head = `${path.map(String).join('.') || '(root)'} ${issue.code}`;
|
|
21
|
+
if (issue.code !== 'invalid_union' || issue.errors.length === 0)
|
|
22
|
+
return head;
|
|
23
|
+
return `${head} [${issue.errors.map((branch) => issuesSummary(branch, path)).join(' | ')}]`;
|
|
24
|
+
})
|
|
25
|
+
.join('; ');
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Issue paths and codes only: a failure names what broke, never the value. A
|
|
29
|
+
* union that matched no branch lists each branch's issues.
|
|
30
|
+
*/
|
|
31
|
+
export function issueSummary(error) {
|
|
32
|
+
return issuesSummary(error.issues, []);
|
|
33
|
+
}
|
|
34
|
+
function badResponse(what, error) {
|
|
35
|
+
// labels-exempt: internal diagnostic; the user reads error.bad_response
|
|
36
|
+
return new TheoremError('bad_response', `${what} failed its wire check: ${issueSummary(error)}`);
|
|
37
|
+
}
|
|
38
|
+
/** `raw` as `schema` reads it; one that fails is `bad_response`, naming `what`. */
|
|
39
|
+
export function checkWire(schema, raw, what) {
|
|
40
|
+
const parsed = schema.safeParse(raw);
|
|
41
|
+
if (!parsed.success)
|
|
42
|
+
throw badResponse(what, parsed.error);
|
|
43
|
+
return parsed.data;
|
|
44
|
+
}
|
|
45
|
+
function malformed(message) {
|
|
46
|
+
return {
|
|
47
|
+
type: 'malformed',
|
|
48
|
+
error: new TheoremError('bad_response', message, { copy: { key: 'session.part_skipped' } }),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/** One wire value: a known kind that passed its schema, `unsupported`, or `malformed`. */
|
|
52
|
+
export function readWireValue(lines, raw) {
|
|
53
|
+
const kind = wireKind.safeParse(raw);
|
|
54
|
+
// labels-exempt: internal diagnostic; the user reads session.part_skipped
|
|
55
|
+
if (!kind.success)
|
|
56
|
+
return malformed(`a line without a kind failed its wire check: ${issueSummary(kind.error)}`);
|
|
57
|
+
const { type } = kind.data;
|
|
58
|
+
if (!isKnown(lines, type))
|
|
59
|
+
return { type: 'unsupported', received: type, raw };
|
|
60
|
+
const line = lines[type].safeParse(raw);
|
|
61
|
+
if (line.success)
|
|
62
|
+
return line.data;
|
|
63
|
+
// labels-exempt: internal diagnostic; the user reads session.part_skipped
|
|
64
|
+
return malformed(`a '${type}' line failed its wire check: ${issueSummary(line.error)}`);
|
|
65
|
+
}
|
|
66
|
+
/** JSON text as a value, or undefined when it is not JSON. The parser's own error quotes the text, so it is not kept. */
|
|
67
|
+
function jsonValue(text) {
|
|
68
|
+
try {
|
|
69
|
+
return { value: JSON.parse(text) };
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
if (err instanceof SyntaxError)
|
|
73
|
+
return undefined;
|
|
74
|
+
throw err;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/** One wire line's text: {@link readWireValue} of its JSON, or `malformed` when it is not JSON. */
|
|
78
|
+
export function readWireLine(lines, text) {
|
|
79
|
+
const json = jsonValue(text);
|
|
80
|
+
// labels-exempt: internal diagnostic; the user reads session.part_skipped
|
|
81
|
+
return json ? readWireValue(lines, json.value) : malformed('a line is not JSON');
|
|
82
|
+
}
|
|
83
|
+
/** A whole reply's JSON text as a value; text that is not JSON is `bad_response`. */
|
|
84
|
+
export function parseWireJson(text) {
|
|
85
|
+
const json = jsonValue(text);
|
|
86
|
+
// labels-exempt: internal diagnostic; the user reads error.bad_response
|
|
87
|
+
if (!json)
|
|
88
|
+
throw new TheoremError('bad_response', 'a line is not JSON');
|
|
89
|
+
return json.value;
|
|
90
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AudioWorklet processor that forwards mono mic frames to the main thread.
|
|
3
|
+
* Plain JS: it runs in the AudioWorkletGlobalScope as its own module, loaded
|
|
4
|
+
* by URL (see `../mic-capture.ts`), so it imports nothing and ships as is.
|
|
5
|
+
*/
|
|
6
|
+
registerProcessor(
|
|
7
|
+
'mic-capture-processor',
|
|
8
|
+
class MicCaptureProcessor extends AudioWorkletProcessor {
|
|
9
|
+
process(inputs) {
|
|
10
|
+
const channel = inputs[0][0];
|
|
11
|
+
const copy = new Float32Array(channel);
|
|
12
|
+
this.port.postMessage(copy, [copy.buffer]);
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
import { type InkWaveStatus } from '../client/ink-waveform.ts';
|
|
3
|
+
/** Mic and speaker levels. A host on the audio clock writes this; the bars read it each frame. */
|
|
4
|
+
export type InkWaveLevels = {
|
|
5
|
+
input: number;
|
|
6
|
+
output: number;
|
|
7
|
+
};
|
|
8
|
+
export type InkWaveformProps = {
|
|
9
|
+
status?: InkWaveStatus;
|
|
10
|
+
inputLevel?: number;
|
|
11
|
+
outputLevel?: number;
|
|
12
|
+
/**
|
|
13
|
+
* Latest levels, read each frame. When set, it wins over `inputLevel` and
|
|
14
|
+
* `outputLevel`, so a host can move the bars without rendering.
|
|
15
|
+
*/
|
|
16
|
+
levelsRef?: RefObject<InkWaveLevels>;
|
|
17
|
+
toolActive?: boolean;
|
|
18
|
+
frozen?: boolean;
|
|
19
|
+
variant?: 'default' | 'hero' | 'pill' | 'strip';
|
|
20
|
+
};
|
|
21
|
+
export declare function InkWaveform({ status, inputLevel, outputLevel, levelsRef, toolActive, frozen, variant, }: InkWaveformProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useMemo, useRef } from 'react';
|
|
3
|
+
import { computeInkBarTargets, INK_WAVE_BAR_COUNT, INK_WAVE_HERO_BAR_COUNT, inkWaveDriver, inkWavePhases, } from "../client/ink-waveform.js";
|
|
4
|
+
const REST_HEIGHT = 0.06;
|
|
5
|
+
const WAVE_CONFIG = {
|
|
6
|
+
hero: {
|
|
7
|
+
viewWidth: 960,
|
|
8
|
+
viewHeight: 720,
|
|
9
|
+
preserveAspect: 'xMidYMax slice',
|
|
10
|
+
strokeWidth: 2,
|
|
11
|
+
barCount: INK_WAVE_HERO_BAR_COUNT,
|
|
12
|
+
},
|
|
13
|
+
pill: {
|
|
14
|
+
viewWidth: 480,
|
|
15
|
+
viewHeight: 120,
|
|
16
|
+
preserveAspect: 'none',
|
|
17
|
+
strokeWidth: 3,
|
|
18
|
+
barCount: INK_WAVE_BAR_COUNT,
|
|
19
|
+
},
|
|
20
|
+
strip: {
|
|
21
|
+
viewWidth: 1600,
|
|
22
|
+
viewHeight: 48,
|
|
23
|
+
preserveAspect: 'none',
|
|
24
|
+
strokeWidth: 2,
|
|
25
|
+
barCount: 120,
|
|
26
|
+
},
|
|
27
|
+
default: {
|
|
28
|
+
viewWidth: 480,
|
|
29
|
+
viewHeight: 320,
|
|
30
|
+
preserveAspect: 'xMidYMax meet',
|
|
31
|
+
strokeWidth: 2,
|
|
32
|
+
barCount: INK_WAVE_BAR_COUNT,
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
function resolveWaveDimensions(variant) {
|
|
36
|
+
const cfg = WAVE_CONFIG[variant] ?? WAVE_CONFIG.default;
|
|
37
|
+
const gap = (cfg.viewWidth - cfg.strokeWidth * cfg.barCount) / (cfg.barCount + 1);
|
|
38
|
+
return { ...cfg, gap };
|
|
39
|
+
}
|
|
40
|
+
/** One frame's bar targets. The live ref's levels win over the last render's; a frozen wave moves to none. */
|
|
41
|
+
function frameTargets(snap, phases, timeMs) {
|
|
42
|
+
const { input, output } = snap.levelsRef?.current ?? {
|
|
43
|
+
input: snap.inputLevel,
|
|
44
|
+
output: snap.outputLevel,
|
|
45
|
+
};
|
|
46
|
+
const heard = snap.frozen ? { input: 0, output: 0 } : { input, output };
|
|
47
|
+
return computeInkBarTargets({
|
|
48
|
+
phases,
|
|
49
|
+
timeMs,
|
|
50
|
+
driver: inkWaveDriver(snap.status, snap.toolActive, input, output, snap.frozen),
|
|
51
|
+
inputLevel: heard.input,
|
|
52
|
+
outputLevel: heard.output,
|
|
53
|
+
frozen: snap.frozen,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Paints bar heights onto the mounted lines. The motion is the same as
|
|
58
|
+
* `computeInkBarTargets` plus the per-frame ease; React never sees a frame,
|
|
59
|
+
* so a strip of bars does not reconcile on the audio clock.
|
|
60
|
+
*/
|
|
61
|
+
function usePaintedWave(svgRef, snapRef, phases, barCount, viewHeight) {
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
const svg = svgRef.current;
|
|
64
|
+
if (!svg)
|
|
65
|
+
return;
|
|
66
|
+
const lines = svg.children;
|
|
67
|
+
const count = Math.min(barCount, lines.length);
|
|
68
|
+
const heights = new Float64Array(count);
|
|
69
|
+
heights.fill(REST_HEIGHT);
|
|
70
|
+
const restY = viewHeight - REST_HEIGHT * (viewHeight - 4);
|
|
71
|
+
for (let index = 0; index < count; index++) {
|
|
72
|
+
lines[index].y2.baseVal.value = restY;
|
|
73
|
+
}
|
|
74
|
+
let frame = 0;
|
|
75
|
+
const tick = (time) => {
|
|
76
|
+
const snap = snapRef.current;
|
|
77
|
+
const targets = frameTargets(snap, phases, time);
|
|
78
|
+
const alpha = snap.frozen ? 0.2 : 0.14;
|
|
79
|
+
for (let index = 0; index < count; index++) {
|
|
80
|
+
const height = heights[index] + (targets[index] - heights[index]) * alpha;
|
|
81
|
+
heights[index] = height;
|
|
82
|
+
lines[index].y2.baseVal.value = viewHeight - height * (viewHeight - 4);
|
|
83
|
+
}
|
|
84
|
+
frame = requestAnimationFrame(tick);
|
|
85
|
+
};
|
|
86
|
+
frame = requestAnimationFrame(tick);
|
|
87
|
+
return () => {
|
|
88
|
+
cancelAnimationFrame(frame);
|
|
89
|
+
};
|
|
90
|
+
}, [svgRef, snapRef, phases, barCount, viewHeight]);
|
|
91
|
+
}
|
|
92
|
+
export function InkWaveform({ status = 'disconnected', inputLevel = 0, outputLevel = 0, levelsRef, toolActive = false, frozen = false, variant = 'default', }) {
|
|
93
|
+
const { viewWidth, viewHeight, preserveAspect, strokeWidth, barCount, gap } = resolveWaveDimensions(variant);
|
|
94
|
+
const phases = useMemo(() => inkWavePhases(barCount), [barCount]);
|
|
95
|
+
const xs = useMemo(() => {
|
|
96
|
+
const next = new Array(barCount);
|
|
97
|
+
for (let index = 0; index < barCount; index++) {
|
|
98
|
+
next[index] = gap + index * (strokeWidth + gap) + strokeWidth / 2;
|
|
99
|
+
}
|
|
100
|
+
return next;
|
|
101
|
+
}, [barCount, gap, strokeWidth]);
|
|
102
|
+
const svgRef = useRef(null);
|
|
103
|
+
const snapRef = useRef({
|
|
104
|
+
status,
|
|
105
|
+
inputLevel,
|
|
106
|
+
outputLevel,
|
|
107
|
+
levelsRef,
|
|
108
|
+
toolActive,
|
|
109
|
+
frozen,
|
|
110
|
+
});
|
|
111
|
+
snapRef.current.status = status;
|
|
112
|
+
snapRef.current.inputLevel = inputLevel;
|
|
113
|
+
snapRef.current.outputLevel = outputLevel;
|
|
114
|
+
snapRef.current.levelsRef = levelsRef;
|
|
115
|
+
snapRef.current.toolActive = toolActive;
|
|
116
|
+
snapRef.current.frozen = frozen;
|
|
117
|
+
usePaintedWave(svgRef, snapRef, phases, barCount, viewHeight);
|
|
118
|
+
const className = [
|
|
119
|
+
'ink-wave',
|
|
120
|
+
variant === 'hero' ? 'ink-wave--hero' : '',
|
|
121
|
+
variant === 'pill' ? 'ink-wave--pill' : '',
|
|
122
|
+
variant === 'strip' ? 'ink-wave--strip' : '',
|
|
123
|
+
]
|
|
124
|
+
.filter(Boolean)
|
|
125
|
+
.join(' ');
|
|
126
|
+
const restY = viewHeight - REST_HEIGHT * (viewHeight - 4);
|
|
127
|
+
return (_jsx("svg", { ref: svgRef, className: className, "aria-hidden": "true", viewBox: `0 0 ${String(viewWidth)} ${String(viewHeight)}`, preserveAspectRatio: preserveAspect,
|
|
128
|
+
// why: Attribute defaults for hosts without ink-controls.css (the Astryx UI);
|
|
129
|
+
// the live stylesheet overrides them where it loads.
|
|
130
|
+
width: "100%", height: "100%", children: xs.map((x) => (_jsx("line", { className: "ink-wave__bar", x1: x, x2: x, y1: viewHeight, y2: restY, strokeWidth: strokeWidth, stroke: "currentColor", strokeLinecap: "square" }, x))) }));
|
|
131
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type Dispatch, type MutableRefObject, type SetStateAction } from 'react';
|
|
2
|
+
import { type LiveCaptionState } from '../../client/live/live-captions.ts';
|
|
3
|
+
import type { LiveConnectPhase, LiveSessionStatus } from '../../client/live/live-state.ts';
|
|
4
|
+
import { type LiveFacingMode, type LiveVideoCapture } from '../../client/live/live-video.ts';
|
|
5
|
+
import type { LiveConnection, LiveSessionClient } from '../../client/live-client.ts';
|
|
6
|
+
/** Media + session lifecycle handlers for LiveRunner. */
|
|
7
|
+
export declare function useLiveRunnerControls(args: {
|
|
8
|
+
clientRef: MutableRefObject<LiveSessionClient | null>;
|
|
9
|
+
videoCaptureRef: MutableRefObject<LiveVideoCapture | null>;
|
|
10
|
+
connectionRef: MutableRefObject<() => LiveConnection | Promise<LiveConnection>>;
|
|
11
|
+
statusRef: MutableRefObject<LiveSessionStatus>;
|
|
12
|
+
isMutedRef: MutableRefObject<boolean>;
|
|
13
|
+
sessionPermissionsRef: MutableRefObject<string[]>;
|
|
14
|
+
ensureClient: (connection: LiveConnection) => LiveSessionClient;
|
|
15
|
+
clearClient: () => void;
|
|
16
|
+
cancelGateDecision: (reason?: string) => void;
|
|
17
|
+
stopVideo: () => void;
|
|
18
|
+
resetCaptions: () => void;
|
|
19
|
+
sessionActive: boolean;
|
|
20
|
+
textAvailable: boolean;
|
|
21
|
+
videoAvailable: boolean;
|
|
22
|
+
voiceAvailable: boolean;
|
|
23
|
+
isVideoOn: boolean;
|
|
24
|
+
textDraft: string;
|
|
25
|
+
setTextDraft: Dispatch<SetStateAction<string>>;
|
|
26
|
+
setCaptions: Dispatch<SetStateAction<LiveCaptionState>>;
|
|
27
|
+
reportFailure: (err: unknown) => void;
|
|
28
|
+
clearFailure: () => void;
|
|
29
|
+
setIsMuted: Dispatch<SetStateAction<boolean>>;
|
|
30
|
+
setSessionActive: Dispatch<SetStateAction<boolean>>;
|
|
31
|
+
setSessionPermissions: Dispatch<SetStateAction<string[]>>;
|
|
32
|
+
setStatus: Dispatch<SetStateAction<LiveSessionStatus>>;
|
|
33
|
+
setConnectPhase: Dispatch<SetStateAction<LiveConnectPhase | null>>;
|
|
34
|
+
setInputLevel: Dispatch<SetStateAction<number>>;
|
|
35
|
+
setOutputLevel: Dispatch<SetStateAction<number>>;
|
|
36
|
+
setVideoPreview: Dispatch<SetStateAction<HTMLVideoElement | null>>;
|
|
37
|
+
setVideoFacingMode: Dispatch<SetStateAction<LiveFacingMode>>;
|
|
38
|
+
setIsVideoOn: Dispatch<SetStateAction<boolean>>;
|
|
39
|
+
}): {
|
|
40
|
+
teardownSession: () => void;
|
|
41
|
+
startSession: () => Promise<void>;
|
|
42
|
+
handleSendText: (text?: string) => void;
|
|
43
|
+
handleToggleVideo: () => Promise<void>;
|
|
44
|
+
handleFlipCamera: () => Promise<void>;
|
|
45
|
+
handleToggleMic: () => void;
|
|
46
|
+
handleRestart: () => Promise<void>;
|
|
47
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import { applyLiveTranscript } from "../../client/live/live-captions.js";
|
|
3
|
+
import { startLiveVideoCapture, } from "../../client/live/live-video.js";
|
|
4
|
+
/** Media + session lifecycle handlers for LiveRunner. */
|
|
5
|
+
export function useLiveRunnerControls(args) {
|
|
6
|
+
const teardownSession = useCallback(() => {
|
|
7
|
+
args.cancelGateDecision();
|
|
8
|
+
args.clearClient();
|
|
9
|
+
args.stopVideo();
|
|
10
|
+
args.setIsMuted(false);
|
|
11
|
+
args.isMutedRef.current = false;
|
|
12
|
+
args.setSessionActive(false);
|
|
13
|
+
args.setSessionPermissions([]);
|
|
14
|
+
args.sessionPermissionsRef.current = [];
|
|
15
|
+
args.statusRef.current = 'disconnected';
|
|
16
|
+
args.setStatus('disconnected');
|
|
17
|
+
args.setConnectPhase(null);
|
|
18
|
+
args.setInputLevel(0);
|
|
19
|
+
args.setOutputLevel(0);
|
|
20
|
+
}, [args]);
|
|
21
|
+
const startSession = useCallback(async () => {
|
|
22
|
+
args.clearFailure();
|
|
23
|
+
args.resetCaptions();
|
|
24
|
+
try {
|
|
25
|
+
const liveClient = args.ensureClient(await args.connectionRef.current());
|
|
26
|
+
if (args.statusRef.current === 'disconnected' || args.statusRef.current === 'error') {
|
|
27
|
+
await liveClient.connect();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
args.reportFailure(err);
|
|
32
|
+
}
|
|
33
|
+
}, [args]);
|
|
34
|
+
const handleSendText = useCallback((text) => {
|
|
35
|
+
const message = (typeof text === 'string' ? text : args.textDraft).trim();
|
|
36
|
+
if (!message || !args.clientRef.current || !args.sessionActive || !args.textAvailable)
|
|
37
|
+
return;
|
|
38
|
+
args.clientRef.current.sendText(message);
|
|
39
|
+
args.setTextDraft('');
|
|
40
|
+
args.setCaptions((prev) => applyLiveTranscript(prev, message, true, false, { forceNew: true }));
|
|
41
|
+
}, [args]);
|
|
42
|
+
const handleToggleVideo = useCallback(async () => {
|
|
43
|
+
if (!args.clientRef.current || !args.sessionActive || !args.videoAvailable)
|
|
44
|
+
return;
|
|
45
|
+
if (args.isVideoOn) {
|
|
46
|
+
args.stopVideo();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const capture = await startLiveVideoCapture((base64) => {
|
|
51
|
+
args.clientRef.current?.sendVideo(base64);
|
|
52
|
+
});
|
|
53
|
+
args.videoCaptureRef.current = capture;
|
|
54
|
+
args.setVideoPreview(capture.video);
|
|
55
|
+
args.setVideoFacingMode(capture.facingMode());
|
|
56
|
+
args.setIsVideoOn(true);
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
args.reportFailure(err);
|
|
60
|
+
args.stopVideo();
|
|
61
|
+
}
|
|
62
|
+
}, [args]);
|
|
63
|
+
const handleFlipCamera = useCallback(async () => {
|
|
64
|
+
const capture = args.videoCaptureRef.current;
|
|
65
|
+
if (!capture || !args.sessionActive || !args.isVideoOn)
|
|
66
|
+
return;
|
|
67
|
+
try {
|
|
68
|
+
const facing = await capture.flip();
|
|
69
|
+
args.setVideoFacingMode(facing);
|
|
70
|
+
args.setVideoPreview(capture.video);
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
args.reportFailure(err);
|
|
74
|
+
}
|
|
75
|
+
}, [args]);
|
|
76
|
+
const handleToggleMic = useCallback(() => {
|
|
77
|
+
if (!args.clientRef.current || !args.sessionActive || !args.voiceAvailable)
|
|
78
|
+
return;
|
|
79
|
+
const muted = args.clientRef.current.toggleMute();
|
|
80
|
+
args.isMutedRef.current = muted;
|
|
81
|
+
args.setIsMuted(muted);
|
|
82
|
+
}, [args]);
|
|
83
|
+
const handleRestart = useCallback(async () => {
|
|
84
|
+
teardownSession();
|
|
85
|
+
await startSession();
|
|
86
|
+
}, [startSession, teardownSession]);
|
|
87
|
+
return {
|
|
88
|
+
teardownSession,
|
|
89
|
+
startSession,
|
|
90
|
+
handleSendText,
|
|
91
|
+
handleToggleVideo,
|
|
92
|
+
handleFlipCamera,
|
|
93
|
+
handleToggleMic,
|
|
94
|
+
handleRestart,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { LiveProfileInterface } from '@theoremjs/agents/interface';
|
|
2
|
+
import { type LiveCaptionState, type LiveCaptionTurn } from '../../client/live/live-captions.ts';
|
|
3
|
+
import type { LiveCallOptions } from '../../client/live/live-page-tool.ts';
|
|
4
|
+
import type { LiveConnection } from '../../client/live-client.ts';
|
|
5
|
+
/**
|
|
6
|
+
* Owns LiveRunner state, session client, and stage callbacks.
|
|
7
|
+
* `connection` resolves what the call opens: a host with a fixed profile returns
|
|
8
|
+
* its id; the studio returns its draft as the relay's open message. `options`
|
|
9
|
+
* are the host's part in the call: its slots, the page's context, and its page tools.
|
|
10
|
+
*/
|
|
11
|
+
export declare function useLiveRunnerModel(iface: LiveProfileInterface, connection: () => LiveConnection | Promise<LiveConnection>, options?: LiveCallOptions): {
|
|
12
|
+
handle: string;
|
|
13
|
+
traces: import("../../index.ts").TraceFeed;
|
|
14
|
+
callStarted: boolean;
|
|
15
|
+
pastCalls: LiveCaptionTurn[][];
|
|
16
|
+
captions: LiveCaptionState;
|
|
17
|
+
failure: import("../../index.ts").ClientFailure | null;
|
|
18
|
+
sessionEnded: string | null;
|
|
19
|
+
levelsRef: import("react").RefObject<{
|
|
20
|
+
input: number;
|
|
21
|
+
output: number;
|
|
22
|
+
}>;
|
|
23
|
+
isMuted: boolean;
|
|
24
|
+
isVideoOn: boolean;
|
|
25
|
+
sessionActive: boolean;
|
|
26
|
+
liveState: import("../../index.ts").LiveState;
|
|
27
|
+
activeTool: string | null;
|
|
28
|
+
status: import("../../index.ts").LiveSessionStatus;
|
|
29
|
+
textAvailable: boolean;
|
|
30
|
+
textDraft: string;
|
|
31
|
+
toolActive: boolean;
|
|
32
|
+
videoAvailable: boolean;
|
|
33
|
+
videoFacingMode: import("../../client/live/live-video.ts").LiveFacingMode;
|
|
34
|
+
videoPreview: HTMLVideoElement | null;
|
|
35
|
+
voiceAvailable: boolean;
|
|
36
|
+
canRestart: boolean;
|
|
37
|
+
gatePrompt: import("../../index.ts").LiveToolGatePrompt | null;
|
|
38
|
+
setTextDraft: import("react").Dispatch<import("react").SetStateAction<string>>;
|
|
39
|
+
handleEnd: () => void;
|
|
40
|
+
startCall: (options: {
|
|
41
|
+
video: boolean;
|
|
42
|
+
}) => void;
|
|
43
|
+
handleRestart: () => Promise<void>;
|
|
44
|
+
handleSendText: (text?: string) => void;
|
|
45
|
+
handleToggleMic: () => void;
|
|
46
|
+
handleFlipCamera: () => Promise<void>;
|
|
47
|
+
handleToggleVideo: () => Promise<void>;
|
|
48
|
+
resolveGateDecision: (resolution: import("../../index.ts").ToolGateResolution) => void;
|
|
49
|
+
};
|