@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,11 @@
|
|
|
1
|
+
/** Hover-card geometry for composer attachment pills (model-sculpt agent_chat parity). */
|
|
2
|
+
export type AttachPreviewStyle = {
|
|
3
|
+
left: number;
|
|
4
|
+
top?: number;
|
|
5
|
+
bottom?: number;
|
|
6
|
+
};
|
|
7
|
+
export declare function formatAttachmentSize(bytes?: number): string;
|
|
8
|
+
export declare function resolveAttachPreviewStyle(anchor: Pick<DOMRect, 'left' | 'top' | 'bottom'>, viewport?: {
|
|
9
|
+
width: number;
|
|
10
|
+
height: number;
|
|
11
|
+
}): AttachPreviewStyle;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** Hover-card geometry for composer attachment pills (model-sculpt agent_chat parity). */
|
|
2
|
+
const ATTACH_PREVIEW_WIDTH_PX = 240;
|
|
3
|
+
const ATTACH_PREVIEW_OFFSET_PX = 6;
|
|
4
|
+
const ATTACH_PREVIEW_VIEWPORT_PAD_PX = 8;
|
|
5
|
+
/** Prefer anchoring above the chip when this much space exists. */
|
|
6
|
+
const ATTACH_PREVIEW_ABOVE_THRESHOLD_PX = 190;
|
|
7
|
+
export function formatAttachmentSize(bytes) {
|
|
8
|
+
if (!bytes || bytes <= 0)
|
|
9
|
+
return '';
|
|
10
|
+
if (bytes < 1024)
|
|
11
|
+
return `${String(bytes)} B`;
|
|
12
|
+
if (bytes < 1024 * 1024)
|
|
13
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
14
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
15
|
+
}
|
|
16
|
+
function clampAttachPreviewLeft(anchorLeft, viewportWidth) {
|
|
17
|
+
const maxLeft = Math.max(ATTACH_PREVIEW_VIEWPORT_PAD_PX, viewportWidth - ATTACH_PREVIEW_WIDTH_PX - ATTACH_PREVIEW_VIEWPORT_PAD_PX);
|
|
18
|
+
return Math.min(Math.max(ATTACH_PREVIEW_VIEWPORT_PAD_PX, anchorLeft), maxLeft);
|
|
19
|
+
}
|
|
20
|
+
export function resolveAttachPreviewStyle(anchor, viewport = {
|
|
21
|
+
width: globalThis.innerWidth ?? 0,
|
|
22
|
+
height: globalThis.innerHeight ?? 0,
|
|
23
|
+
}) {
|
|
24
|
+
const left = clampAttachPreviewLeft(anchor.left, viewport.width);
|
|
25
|
+
const hasRoomAbove = anchor.top > ATTACH_PREVIEW_ABOVE_THRESHOLD_PX;
|
|
26
|
+
if (hasRoomAbove) {
|
|
27
|
+
return {
|
|
28
|
+
left,
|
|
29
|
+
bottom: Math.max(ATTACH_PREVIEW_VIEWPORT_PAD_PX, viewport.height - anchor.top + ATTACH_PREVIEW_OFFSET_PX),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
left,
|
|
34
|
+
top: Math.min(viewport.height - ATTACH_PREVIEW_VIEWPORT_PAD_PX, anchor.bottom + ATTACH_PREVIEW_OFFSET_PX),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Shared mic RMS → waveform level scaling for live and turn-composer paths. */
|
|
2
|
+
export declare const INPUT_LEVEL_GAIN = 4;
|
|
3
|
+
export declare function float32Rms(samples: Float32Array): number;
|
|
4
|
+
export declare function float32RmsToLevel(samples: Float32Array): number;
|
|
5
|
+
export declare function timeDomainBytesToLevel(samples: Uint8Array<ArrayBufferLike>): number;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Shared mic RMS → waveform level scaling for live and turn-composer paths. */
|
|
2
|
+
export const INPUT_LEVEL_GAIN = 4;
|
|
3
|
+
export function float32Rms(samples) {
|
|
4
|
+
let sum = 0;
|
|
5
|
+
for (const sample of samples) {
|
|
6
|
+
sum += sample * sample;
|
|
7
|
+
}
|
|
8
|
+
if (samples.length === 0)
|
|
9
|
+
return 0;
|
|
10
|
+
return Math.sqrt(sum / samples.length);
|
|
11
|
+
}
|
|
12
|
+
export function float32RmsToLevel(samples) {
|
|
13
|
+
return Math.min(1, float32Rms(samples) * INPUT_LEVEL_GAIN);
|
|
14
|
+
}
|
|
15
|
+
export function timeDomainBytesToLevel(samples) {
|
|
16
|
+
let sum = 0;
|
|
17
|
+
for (const sample of samples) {
|
|
18
|
+
const normalized = (sample - 128) / 128;
|
|
19
|
+
sum += normalized * normalized;
|
|
20
|
+
}
|
|
21
|
+
if (samples.length === 0)
|
|
22
|
+
return 0;
|
|
23
|
+
return Math.min(1, Math.sqrt(sum / samples.length) * INPUT_LEVEL_GAIN);
|
|
24
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage file picks against profile `maxFiles` (shared with voice). Excess
|
|
3
|
+
* incoming files are dropped; the limit hit is an issue the caller words
|
|
4
|
+
* (`attachmentIssueText`).
|
|
5
|
+
*/
|
|
6
|
+
import type { AttachmentValidationIssue } from '@theoremjs/agents/interface';
|
|
7
|
+
export type StageComposerFilesArgs = {
|
|
8
|
+
existing: readonly File[];
|
|
9
|
+
incoming: readonly File[];
|
|
10
|
+
/** Profile `inputs.maxFiles`. When omitted, no cap. */
|
|
11
|
+
maxFiles?: number;
|
|
12
|
+
/** Staged voice notes that share the same maxFiles budget. */
|
|
13
|
+
voiceCount?: number;
|
|
14
|
+
};
|
|
15
|
+
export type StageComposerFilesResult = {
|
|
16
|
+
files: File[];
|
|
17
|
+
dropped: number;
|
|
18
|
+
/** `too_many_files` when the cap dropped a file. */
|
|
19
|
+
issues: AttachmentValidationIssue[];
|
|
20
|
+
};
|
|
21
|
+
/** Append `incoming` to `existing`, dropping overflow past maxFiles − voice. */
|
|
22
|
+
export declare function stageComposerFiles(args: StageComposerFilesArgs): StageComposerFilesResult;
|
|
23
|
+
/**
|
|
24
|
+
* Whether a new voice note fits under maxFiles.
|
|
25
|
+
* Recording clears any prior staged voice first, so only `fileCount` matters.
|
|
26
|
+
*/
|
|
27
|
+
export declare function canStageVoice(args: {
|
|
28
|
+
fileCount: number;
|
|
29
|
+
maxFiles?: number;
|
|
30
|
+
}): boolean;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage file picks against profile `maxFiles` (shared with voice). Excess
|
|
3
|
+
* incoming files are dropped; the limit hit is an issue the caller words
|
|
4
|
+
* (`attachmentIssueText`).
|
|
5
|
+
*/
|
|
6
|
+
/** Append `incoming` to `existing`, dropping overflow past maxFiles − voice. */
|
|
7
|
+
export function stageComposerFiles(args) {
|
|
8
|
+
const { existing, incoming, maxFiles } = args;
|
|
9
|
+
const voiceCount = Math.max(0, args.voiceCount ?? 0);
|
|
10
|
+
if (maxFiles === undefined || !Number.isFinite(maxFiles) || maxFiles < 0) {
|
|
11
|
+
return { files: [...existing, ...incoming], dropped: 0, issues: [] };
|
|
12
|
+
}
|
|
13
|
+
const room = Math.max(0, maxFiles - voiceCount - existing.length);
|
|
14
|
+
if (incoming.length <= room) {
|
|
15
|
+
return { files: [...existing, ...incoming], dropped: 0, issues: [] };
|
|
16
|
+
}
|
|
17
|
+
const kept = room === 0 ? [] : incoming.slice(0, room);
|
|
18
|
+
return {
|
|
19
|
+
files: [...existing, ...kept],
|
|
20
|
+
dropped: incoming.length - kept.length,
|
|
21
|
+
issues: [{ code: 'too_many_files', params: { maxFiles } }],
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Whether a new voice note fits under maxFiles.
|
|
26
|
+
* Recording clears any prior staged voice first, so only `fileCount` matters.
|
|
27
|
+
*/
|
|
28
|
+
export function canStageVoice(args) {
|
|
29
|
+
const maxFiles = args.maxFiles;
|
|
30
|
+
if (maxFiles === undefined || !Number.isFinite(maxFiles))
|
|
31
|
+
return true;
|
|
32
|
+
return args.fileCount < maxFiles;
|
|
33
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ComposerPendingMessage } from '@theoremjs/agents/interface';
|
|
2
|
+
/** What waits in the composer, by kind; the UI words each kind. */
|
|
3
|
+
export type ComposerDrawerKind = 'steer' | 'queue' | 'stash' | 'attached';
|
|
4
|
+
/** Collapsed-drawer header: the total, then each waiting kind's count, in display order. */
|
|
5
|
+
export type ComposerDrawerSummary = {
|
|
6
|
+
count: number;
|
|
7
|
+
parts: {
|
|
8
|
+
kind: ComposerDrawerKind;
|
|
9
|
+
n: number;
|
|
10
|
+
}[];
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* What's waiting in the composer, by kind: steering, queued, stashed, attached
|
|
14
|
+
* (files and voice notes). Null when nothing waits.
|
|
15
|
+
*/
|
|
16
|
+
export declare function composerDrawerSummary(args: {
|
|
17
|
+
pendingMessages: readonly Pick<ComposerPendingMessage, 'kind'>[];
|
|
18
|
+
attachmentCount: number;
|
|
19
|
+
}): ComposerDrawerSummary | null;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What's waiting in the composer, by kind: steering, queued, stashed, attached
|
|
3
|
+
* (files and voice notes). Null when nothing waits.
|
|
4
|
+
*/
|
|
5
|
+
export function composerDrawerSummary(args) {
|
|
6
|
+
const countOf = (kind) => args.pendingMessages.filter((message) => message.kind === kind).length;
|
|
7
|
+
const parts = [
|
|
8
|
+
{ kind: 'steer', n: countOf('steer') },
|
|
9
|
+
{ kind: 'queue', n: countOf('queue') },
|
|
10
|
+
{ kind: 'stash', n: countOf('stash') },
|
|
11
|
+
{ kind: 'attached', n: args.attachmentCount },
|
|
12
|
+
].filter((part) => part.n > 0);
|
|
13
|
+
const count = parts.reduce((sum, part) => sum + part.n, 0);
|
|
14
|
+
return count === 0 ? null : { count, parts };
|
|
15
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composer hints — ephemeral guidance about the current composer interaction
|
|
3
|
+
* (not pending-message state). Mirrors seance's `stash-selected-draft` hint.
|
|
4
|
+
*/
|
|
5
|
+
/** Stash shortcut in Astryx `Kbd` notation (`mod` is ⌘ on macOS, Ctrl elsewhere). */
|
|
6
|
+
export declare const STASH_SHORTCUT = "mod+shift+s";
|
|
7
|
+
/** Which hint applies, and its shortcut; the UI words it. */
|
|
8
|
+
export type ComposerHint = {
|
|
9
|
+
id: 'stash-selected-draft';
|
|
10
|
+
shortcut: string;
|
|
11
|
+
};
|
|
12
|
+
/** Whether a keydown is the stash shortcut (⌘⇧S / Ctrl+Shift+S). */
|
|
13
|
+
export declare function isStashShortcut(event: {
|
|
14
|
+
code: string;
|
|
15
|
+
metaKey: boolean;
|
|
16
|
+
ctrlKey: boolean;
|
|
17
|
+
shiftKey: boolean;
|
|
18
|
+
altKey: boolean;
|
|
19
|
+
}): boolean;
|
|
20
|
+
/** The stash hint — shown while the whole draft is selected in the focused input and it can be stashed. */
|
|
21
|
+
export declare function resolveComposerHint(args: {
|
|
22
|
+
draftText: string;
|
|
23
|
+
selectedText: string;
|
|
24
|
+
canStash: boolean;
|
|
25
|
+
}): ComposerHint | null;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composer hints — ephemeral guidance about the current composer interaction
|
|
3
|
+
* (not pending-message state). Mirrors seance's `stash-selected-draft` hint.
|
|
4
|
+
*/
|
|
5
|
+
/** Stash shortcut in Astryx `Kbd` notation (`mod` is ⌘ on macOS, Ctrl elsewhere). */
|
|
6
|
+
export const STASH_SHORTCUT = 'mod+shift+s';
|
|
7
|
+
/** Whether a keydown is the stash shortcut (⌘⇧S / Ctrl+Shift+S). */
|
|
8
|
+
export function isStashShortcut(event) {
|
|
9
|
+
return (event.code === 'KeyS' && event.shiftKey && !event.altKey && (event.metaKey || event.ctrlKey));
|
|
10
|
+
}
|
|
11
|
+
/** The stash hint — shown while the whole draft is selected in the focused input and it can be stashed. */
|
|
12
|
+
export function resolveComposerHint(args) {
|
|
13
|
+
const draft = args.draftText.trim();
|
|
14
|
+
if (!args.canStash || !draft || args.selectedText.trim() !== draft)
|
|
15
|
+
return null;
|
|
16
|
+
return {
|
|
17
|
+
id: 'stash-selected-draft',
|
|
18
|
+
shortcut: STASH_SHORTCUT,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type ComposerMenuAction, type ComposerPrimaryAction, type ComposerProfileInterface, type ComposerRunPhase } from '@theoremjs/agents/interface';
|
|
2
|
+
export type ComposerActionState = {
|
|
3
|
+
primary: ComposerPrimaryAction;
|
|
4
|
+
menuActions: ComposerMenuAction[];
|
|
5
|
+
/** Send is off while recording, with nothing to act on, or with an empty draft to send or queue. */
|
|
6
|
+
primaryDisabled: boolean;
|
|
7
|
+
};
|
|
8
|
+
/** The composer's primary button and send menu for the current draft and run phase. */
|
|
9
|
+
export declare function composerActionState(args: {
|
|
10
|
+
iface: ComposerProfileInterface;
|
|
11
|
+
phase: ComposerRunPhase;
|
|
12
|
+
draftText: string;
|
|
13
|
+
pendingFiles: readonly File[];
|
|
14
|
+
pendingVoice: readonly File[];
|
|
15
|
+
recording: boolean;
|
|
16
|
+
}): ComposerActionState;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { resolveComposerMenuActions, resolveComposerPrimary, userDraftHasPayload, } from '@theoremjs/agents/interface';
|
|
2
|
+
function fileSpecs(files) {
|
|
3
|
+
return files.map((file) => ({
|
|
4
|
+
name: file.name,
|
|
5
|
+
mimeType: file.type || 'application/octet-stream',
|
|
6
|
+
sizeBytes: file.size,
|
|
7
|
+
}));
|
|
8
|
+
}
|
|
9
|
+
/** The composer's primary button and send menu for the current draft and run phase. */
|
|
10
|
+
export function composerActionState(args) {
|
|
11
|
+
const allowSteering = 'allowSteering' in args.iface && Boolean(args.iface.allowSteering);
|
|
12
|
+
const hasPayload = userDraftHasPayload({
|
|
13
|
+
...(args.draftText.trim() ? { text: args.draftText } : {}),
|
|
14
|
+
...(args.pendingFiles.length ? { attachments: fileSpecs(args.pendingFiles) } : {}),
|
|
15
|
+
...(args.pendingVoice.length ? { voice: fileSpecs(args.pendingVoice) } : {}),
|
|
16
|
+
});
|
|
17
|
+
const context = { phase: args.phase, hasPayload, allowSteering };
|
|
18
|
+
const primary = resolveComposerPrimary(context);
|
|
19
|
+
const needsPayload = primary === 'send' || primary === 'queue';
|
|
20
|
+
return {
|
|
21
|
+
primary,
|
|
22
|
+
menuActions: resolveComposerMenuActions(context),
|
|
23
|
+
primaryDisabled: args.recording || primary === 'none' || (needsPayload && !hasPayload),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { DecisionAsset, DecisionJson } from '@theoremjs/agents';
|
|
2
|
+
/**
|
|
3
|
+
* An image the page holds for a decision, by its reference: the text the state and the questions
|
|
4
|
+
* write where the image goes, such as `<pantry_shelf>`.
|
|
5
|
+
*/
|
|
6
|
+
export type DecisionImages = Record<string, DecisionAsset>;
|
|
7
|
+
/** The image types a decision reads. */
|
|
8
|
+
export declare const IMAGE_ACCEPT = "image/png,image/jpeg";
|
|
9
|
+
/**
|
|
10
|
+
* A reference for a file that no image holds yet: its base name in angle brackets, then `_2`, `_3`,
|
|
11
|
+
* and so on. The model reads any text as a reference, so the brackets keep it from matching words.
|
|
12
|
+
*/
|
|
13
|
+
export declare function imageName(file: string, taken: readonly string[]): string;
|
|
14
|
+
/** A file as an asset, or null when it is not a PNG or JPEG. */
|
|
15
|
+
export declare function readImage(file: File): Promise<DecisionAsset | null>;
|
|
16
|
+
/** The image as a `src` the page can show. */
|
|
17
|
+
export declare function imageSrc(image: DecisionAsset): string;
|
|
18
|
+
/** The held images the state still names, the only ones a decision sends. */
|
|
19
|
+
export declare function namedImages(images: DecisionImages, state: DecisionJson): DecisionImages;
|
|
20
|
+
/**
|
|
21
|
+
* The field a dropped file becomes: its reference, unused by any image or field, and the field
|
|
22
|
+
* named after it, such as `plant` holding `<plant>`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function imageField(file: string, images: DecisionImages, fields: readonly string[]): {
|
|
25
|
+
key: string;
|
|
26
|
+
reference: string;
|
|
27
|
+
};
|
|
28
|
+
/** The state as named fields, or undefined when it is a list, a value, or nothing. */
|
|
29
|
+
export declare function stateFields(state: DecisionJson | undefined): Record<string, DecisionJson> | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* The images and state after files are dropped: each file a field named after it, holding a
|
|
32
|
+
* reference no image the page or the host holds, nor any field, has yet.
|
|
33
|
+
*/
|
|
34
|
+
export declare function droppedImages(dropped: readonly (readonly [File, DecisionAsset])[], held: {
|
|
35
|
+
images: DecisionImages;
|
|
36
|
+
host?: DecisionImages;
|
|
37
|
+
state: Record<string, DecisionJson>;
|
|
38
|
+
}): {
|
|
39
|
+
images: DecisionImages;
|
|
40
|
+
state: Record<string, DecisionJson>;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* The image a box answer is drawn on: `field` itself when it is a held reference, else the one at
|
|
44
|
+
* that state field, else the first the state refers to, else the first held. A box answer names no image, so this is the
|
|
45
|
+
* page's best reading of where it points.
|
|
46
|
+
*/
|
|
47
|
+
export declare function boxSource(images: DecisionImages, state: DecisionJson, field?: string): DecisionAsset | undefined;
|
|
48
|
+
/** A box answer's edges, each a share of the image from its top or left. */
|
|
49
|
+
export type DecisionBox = {
|
|
50
|
+
top: number;
|
|
51
|
+
bottom: number;
|
|
52
|
+
left: number;
|
|
53
|
+
right: number;
|
|
54
|
+
};
|
|
55
|
+
/** The box in an image's pixels, and an outline that stays visible at any size. */
|
|
56
|
+
export declare function boxRect(box: DecisionBox, width: number, height: number): {
|
|
57
|
+
x: number;
|
|
58
|
+
y: number;
|
|
59
|
+
width: number;
|
|
60
|
+
height: number;
|
|
61
|
+
line: number;
|
|
62
|
+
};
|
|
63
|
+
/** The colours a marked image is drawn in: the box's outline, and the shade over the rest. */
|
|
64
|
+
export type BoxMarks = {
|
|
65
|
+
outline: string;
|
|
66
|
+
shade: string;
|
|
67
|
+
};
|
|
68
|
+
/** The whole image with the box outlined and the rest shaded, as a PNG `src`. */
|
|
69
|
+
export declare function markedBox(src: string, box: DecisionBox, marks: BoxMarks): Promise<string>;
|
|
70
|
+
/** The part of an image a box takes, as the frame's size and the image's place inside it, in percent. */
|
|
71
|
+
export declare function cropOf(box: DecisionBox): {
|
|
72
|
+
width: number;
|
|
73
|
+
height: number;
|
|
74
|
+
left: number;
|
|
75
|
+
top: number;
|
|
76
|
+
};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
const MIME_TYPES = new Set(['image/png', 'image/jpeg']);
|
|
2
|
+
/** The image types a decision reads. */
|
|
3
|
+
export const IMAGE_ACCEPT = 'image/png,image/jpeg';
|
|
4
|
+
/**
|
|
5
|
+
* A reference for a file that no image holds yet: its base name in angle brackets, then `_2`, `_3`,
|
|
6
|
+
* and so on. The model reads any text as a reference, so the brackets keep it from matching words.
|
|
7
|
+
*/
|
|
8
|
+
export function imageName(file, taken) {
|
|
9
|
+
const base = file
|
|
10
|
+
.replace(/\.[^.]*$/, '')
|
|
11
|
+
.toLowerCase()
|
|
12
|
+
.replace(/[^a-z0-9]+/g, '_')
|
|
13
|
+
.replace(/^_+|_+$/g, '') || 'image';
|
|
14
|
+
let name = `<${base}>`;
|
|
15
|
+
for (let n = 2; taken.includes(name); n += 1)
|
|
16
|
+
name = `<${base}_${String(n)}>`;
|
|
17
|
+
return name;
|
|
18
|
+
}
|
|
19
|
+
/** A file as an asset, or null when it is not a PNG or JPEG. */
|
|
20
|
+
export async function readImage(file) {
|
|
21
|
+
if (!MIME_TYPES.has(file.type))
|
|
22
|
+
return null;
|
|
23
|
+
const bytes = new Uint8Array(await file.arrayBuffer());
|
|
24
|
+
let binary = '';
|
|
25
|
+
for (let i = 0; i < bytes.length; i += 0x8000)
|
|
26
|
+
binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000));
|
|
27
|
+
return { mimeType: file.type, data: btoa(binary) };
|
|
28
|
+
}
|
|
29
|
+
/** The image as a `src` the page can show. */
|
|
30
|
+
export function imageSrc(image) {
|
|
31
|
+
return `data:${image.mimeType};base64,${image.data}`;
|
|
32
|
+
}
|
|
33
|
+
function mentions(value, name) {
|
|
34
|
+
if (typeof value === 'string')
|
|
35
|
+
return value === name;
|
|
36
|
+
if (Array.isArray(value))
|
|
37
|
+
return value.some((each) => mentions(each, name));
|
|
38
|
+
if (value !== null && typeof value === 'object')
|
|
39
|
+
return Object.values(value).some((each) => mentions(each, name));
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
/** The held images the state still names, the only ones a decision sends. */
|
|
43
|
+
export function namedImages(images, state) {
|
|
44
|
+
return Object.fromEntries(Object.entries(images).filter(([name]) => mentions(state, name)));
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The field a dropped file becomes: its reference, unused by any image or field, and the field
|
|
48
|
+
* named after it, such as `plant` holding `<plant>`.
|
|
49
|
+
*/
|
|
50
|
+
export function imageField(file, images, fields) {
|
|
51
|
+
const reference = imageName(file, [...Object.keys(images), ...fields.map((key) => `<${key}>`)]);
|
|
52
|
+
return { key: reference.slice(1, -1), reference };
|
|
53
|
+
}
|
|
54
|
+
/** The state as named fields, or undefined when it is a list, a value, or nothing. */
|
|
55
|
+
export function stateFields(state) {
|
|
56
|
+
return state !== null && typeof state === 'object' && !Array.isArray(state) ? state : undefined;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The images and state after files are dropped: each file a field named after it, holding a
|
|
60
|
+
* reference no image the page or the host holds, nor any field, has yet.
|
|
61
|
+
*/
|
|
62
|
+
export function droppedImages(dropped, held) {
|
|
63
|
+
let { images, state } = held;
|
|
64
|
+
for (const [file, image] of dropped) {
|
|
65
|
+
const { key, reference } = imageField(file.name, { ...held.host, ...images }, Object.keys(state));
|
|
66
|
+
images = { ...images, [reference]: image };
|
|
67
|
+
state = { ...state, [key]: reference };
|
|
68
|
+
}
|
|
69
|
+
return { images, state };
|
|
70
|
+
}
|
|
71
|
+
function at(state, path) {
|
|
72
|
+
let value = state;
|
|
73
|
+
for (const step of path.split('.')) {
|
|
74
|
+
if (value === null || typeof value !== 'object')
|
|
75
|
+
return undefined;
|
|
76
|
+
value = Array.isArray(value) ? value[Number(step)] : value[step];
|
|
77
|
+
}
|
|
78
|
+
return value;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The image a box answer is drawn on: `field` itself when it is a held reference, else the one at
|
|
82
|
+
* that state field, else the first the state refers to, else the first held. A box answer names no image, so this is the
|
|
83
|
+
* page's best reading of where it points.
|
|
84
|
+
*/
|
|
85
|
+
export function boxSource(images, state, field) {
|
|
86
|
+
const names = Object.keys(images);
|
|
87
|
+
const pointed = field === undefined || field in images ? field : at(state, field);
|
|
88
|
+
const named = (typeof pointed === 'string' && pointed in images ? pointed : undefined) ??
|
|
89
|
+
names.find((name) => mentions(state, name));
|
|
90
|
+
return images[named ?? names[0] ?? ''];
|
|
91
|
+
}
|
|
92
|
+
/** The box in an image's pixels, and an outline that stays visible at any size. */
|
|
93
|
+
export function boxRect(box, width, height) {
|
|
94
|
+
return {
|
|
95
|
+
x: box.left * width,
|
|
96
|
+
y: box.top * height,
|
|
97
|
+
width: (box.right - box.left) * width,
|
|
98
|
+
height: (box.bottom - box.top) * height,
|
|
99
|
+
line: Math.max(2, Math.round(Math.min(width, height) / 200)),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/** How much of the shade's colour lies over the rest of the image, so the image still shows through it. */
|
|
103
|
+
const SHADE_ALPHA = 0.45;
|
|
104
|
+
/** The whole image with the box outlined and the rest shaded, as a PNG `src`. */
|
|
105
|
+
export async function markedBox(src, box, marks) {
|
|
106
|
+
const image = new Image();
|
|
107
|
+
image.src = src;
|
|
108
|
+
await image.decode();
|
|
109
|
+
const canvas = document.createElement('canvas');
|
|
110
|
+
canvas.width = image.naturalWidth;
|
|
111
|
+
canvas.height = image.naturalHeight;
|
|
112
|
+
const context = canvas.getContext('2d');
|
|
113
|
+
if (!context)
|
|
114
|
+
return src;
|
|
115
|
+
const rect = boxRect(box, canvas.width, canvas.height);
|
|
116
|
+
context.drawImage(image, 0, 0);
|
|
117
|
+
context.fillStyle = marks.shade;
|
|
118
|
+
context.globalAlpha = SHADE_ALPHA;
|
|
119
|
+
context.beginPath();
|
|
120
|
+
context.rect(0, 0, canvas.width, canvas.height);
|
|
121
|
+
context.rect(rect.x, rect.y, rect.width, rect.height);
|
|
122
|
+
context.fill('evenodd');
|
|
123
|
+
context.globalAlpha = 1;
|
|
124
|
+
context.strokeStyle = marks.outline;
|
|
125
|
+
context.lineWidth = rect.line;
|
|
126
|
+
context.strokeRect(rect.x, rect.y, rect.width, rect.height);
|
|
127
|
+
return canvas.toDataURL('image/png');
|
|
128
|
+
}
|
|
129
|
+
/** The part of an image a box takes, as the frame's size and the image's place inside it, in percent. */
|
|
130
|
+
export function cropOf(box) {
|
|
131
|
+
const width = box.right - box.left;
|
|
132
|
+
const height = box.bottom - box.top;
|
|
133
|
+
return {
|
|
134
|
+
width: 100 / width,
|
|
135
|
+
height: 100 / height,
|
|
136
|
+
left: (-box.left / width) * 100,
|
|
137
|
+
top: (-box.top / height) * 100,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The browser side of a decision profile: what the host lets the page see of
|
|
3
|
+
* it, and the one call that asks its questions about some state.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import { type DecisionAsset, type DecisionJson, type DecisionProfile, type DecisionQuestion, type DecisionResult, type TraceRecord } from '@theoremjs/agents';
|
|
8
|
+
import type { TraceFeed } from './trace-feed.ts';
|
|
9
|
+
import { type HttpOptions } from './transport.ts';
|
|
10
|
+
/** One question as the page sees it: its answer type and the names of its options or levels. Instructions stay on the host. */
|
|
11
|
+
export type DecisionQuestionView = {
|
|
12
|
+
id: string;
|
|
13
|
+
type: DecisionQuestion['type'];
|
|
14
|
+
/** A choice's labels, a score's levels from 0 up; empty for a number. */
|
|
15
|
+
labels: string[];
|
|
16
|
+
/**
|
|
17
|
+
* A box's image: the one its question gives, a reference or a state field, else the field its
|
|
18
|
+
* instructions first name in backticks.
|
|
19
|
+
*/
|
|
20
|
+
field?: string;
|
|
21
|
+
};
|
|
22
|
+
/** What a decision profile shows the page. */
|
|
23
|
+
export type DecisionInterface = {
|
|
24
|
+
type: 'decision';
|
|
25
|
+
identity: {
|
|
26
|
+
handle: string;
|
|
27
|
+
};
|
|
28
|
+
contract: string;
|
|
29
|
+
maxStateBytes?: number;
|
|
30
|
+
questions: DecisionQuestionView[];
|
|
31
|
+
/** The host's own images, by the reference its questions write, sent with every decision. */
|
|
32
|
+
images?: Record<string, DecisionAsset>;
|
|
33
|
+
observability?: {
|
|
34
|
+
record: boolean;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
/** The page's view of a decision profile, the questions its host asks, and the host's own images. */
|
|
38
|
+
export declare function decisionInterface(profile: Pick<DecisionProfile, 'identity' | 'decision' | 'inputs' | 'observability'>, questions: Record<string, DecisionQuestion>, images?: Record<string, DecisionAsset>): DecisionInterface;
|
|
39
|
+
/**
|
|
40
|
+
* The images a decision sends: the host's own and the page's. A page image may not take a name
|
|
41
|
+
* the host's use, so the questions always read the host's picture.
|
|
42
|
+
*/
|
|
43
|
+
export declare function decisionAssets(host: Record<string, DecisionAsset> | undefined, page: Record<string, DecisionAsset> | undefined): Record<string, DecisionAsset> | undefined;
|
|
44
|
+
/** A decision's reply: the answers, and the trace records a host that delivers them sent back. */
|
|
45
|
+
export type DecisionReply = {
|
|
46
|
+
result: DecisionResult;
|
|
47
|
+
traces?: TraceRecord[];
|
|
48
|
+
};
|
|
49
|
+
export interface DecisionTransport {
|
|
50
|
+
describe(signal?: AbortSignal): Promise<DecisionInterface>;
|
|
51
|
+
/** `assets` are the images the state names, by reference. */
|
|
52
|
+
decide(state: Exclude<DecisionJson, null>, signal?: AbortSignal, assets?: Record<string, DecisionAsset>): Promise<DecisionReply>;
|
|
53
|
+
/** Where the host's trace records land, for the inspector. */
|
|
54
|
+
traces?: TraceFeed;
|
|
55
|
+
}
|
|
56
|
+
/** Marks a decision's failure with the trace records it left, for the page's inspector. */
|
|
57
|
+
export declare function withFailedTraces(err: unknown, traces: readonly TraceRecord[]): unknown;
|
|
58
|
+
/** The trace records a failed decision left; none when its host sent none. */
|
|
59
|
+
export declare function failedTraces(err: unknown): readonly TraceRecord[];
|
|
60
|
+
export declare const failedDecisionTraces: typeof failedTraces;
|
|
61
|
+
/** POSTs `body` and reads its reply with `read`; a failure keeps the trace records its body carried. */
|
|
62
|
+
export declare function postWithTraces<Reply>(url: string, body: unknown, signal: AbortSignal | undefined, options: HttpOptions, read: (raw: unknown) => Reply): Promise<Reply>;
|
|
63
|
+
/** POSTs a decision and reads its reply; a failure keeps the trace records its body carried. */
|
|
64
|
+
export declare function postDecision(url: string, body: unknown, signal: AbortSignal | undefined, options?: HttpOptions): Promise<DecisionReply>;
|
|
65
|
+
/** A host's decide reply, checked: the answers, and any trace records it delivers. */
|
|
66
|
+
export declare function readDecisionReply(raw: unknown): DecisionReply;
|
|
67
|
+
/** Transport for a host mounted with `createTheoremDecisionHandler`. Default endpoint `/api/decision`. */
|
|
68
|
+
export declare function createDecisionTransport(options?: HttpOptions & {
|
|
69
|
+
endpoint?: string;
|
|
70
|
+
}): DecisionTransport;
|