@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,123 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button } from '@astryxdesign/core/Button';
|
|
3
|
+
import { CodeBlock } from '@astryxdesign/core/CodeBlock';
|
|
4
|
+
import { useLocale } from '@astryxdesign/core/i18n';
|
|
5
|
+
import { MetadataList, MetadataListItem } from '@astryxdesign/core/MetadataList';
|
|
6
|
+
import { Text } from '@astryxdesign/core/Text';
|
|
7
|
+
import { Timestamp } from '@astryxdesign/core/Timestamp';
|
|
8
|
+
import { Tooltip } from '@astryxdesign/core/Tooltip';
|
|
9
|
+
import { VStack } from '@astryxdesign/core/VStack';
|
|
10
|
+
import { inlineContent, TRACE_ATTRIBUTE_GROUPS, traceAttributeMeta, } from '@theoremjs/agents';
|
|
11
|
+
import { useMemo, useState } from 'react';
|
|
12
|
+
import { nanosToMs, traceValueShape, } from "../client/trace-view.js";
|
|
13
|
+
import { workDuration } from "./labels.js";
|
|
14
|
+
import { useLabels } from "./labels-provider.js";
|
|
15
|
+
import { keyedByContent } from "./row-keys.js";
|
|
16
|
+
/** Width of every label column in the panel's lists, so they line up. */
|
|
17
|
+
export const TRACE_LABEL_PX = 120;
|
|
18
|
+
/** A span's attributes by catalog group, in the catalog's order; keys it does not name last. */
|
|
19
|
+
export function attributeSections(attributes) {
|
|
20
|
+
const byGroup = new Map();
|
|
21
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
22
|
+
const group = traceAttributeMeta(key)?.group ?? 'other';
|
|
23
|
+
byGroup.set(group, { ...byGroup.get(group), [key]: value });
|
|
24
|
+
}
|
|
25
|
+
const order = [
|
|
26
|
+
...Object.keys(TRACE_ATTRIBUTE_GROUPS),
|
|
27
|
+
'other',
|
|
28
|
+
];
|
|
29
|
+
return order.flatMap((key) => {
|
|
30
|
+
const grouped = byGroup.get(key);
|
|
31
|
+
return grouped ? [{ key, attributes: grouped }] : [];
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
export function useTraceFormat() {
|
|
35
|
+
const t = useLabels();
|
|
36
|
+
const locale = useLocale();
|
|
37
|
+
return useMemo(() => {
|
|
38
|
+
const number = new Intl.NumberFormat(locale);
|
|
39
|
+
const usd = new Intl.NumberFormat(locale, {
|
|
40
|
+
style: 'currency',
|
|
41
|
+
currency: 'USD',
|
|
42
|
+
maximumFractionDigits: 6,
|
|
43
|
+
});
|
|
44
|
+
const list = new Intl.ListFormat(locale, { type: 'conjunction' });
|
|
45
|
+
return {
|
|
46
|
+
t,
|
|
47
|
+
number: (value) => number.format(value),
|
|
48
|
+
usd: (value) => usd.format(value),
|
|
49
|
+
duration: (ms) => workDuration(t, ms),
|
|
50
|
+
list: (items) => list.format(items),
|
|
51
|
+
sum(total, format) {
|
|
52
|
+
const value = 'estimated' in total && total.estimated
|
|
53
|
+
? t('@theorem.panel.trace.about', { value: format(total.value) })
|
|
54
|
+
: format(total.value);
|
|
55
|
+
return total.complete ? value : t('@theorem.panel.trace.at_least', { value });
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}, [t, locale]);
|
|
59
|
+
}
|
|
60
|
+
/** A value as it was stored, with its references rebuilt, shown on click. */
|
|
61
|
+
function StoredText({ record, value }) {
|
|
62
|
+
const { t } = useTraceFormat();
|
|
63
|
+
const [isShown, setIsShown] = useState(false);
|
|
64
|
+
const inlined = inlineContent(record, value);
|
|
65
|
+
return (_jsxs(VStack, { gap: 1, children: [_jsx(Button, { label: t(isShown ? '@theorem.panel.trace.hide_text' : '@theorem.panel.trace.show_text'), variant: "ghost", size: "sm", "aria-expanded": isShown, onClick: () => setIsShown((shown) => !shown) }), isShown ? (_jsx(CodeBlock, { code: typeof inlined === 'string' ? inlined : JSON.stringify(inlined, null, 2), language: typeof inlined === 'string' ? 'text' : 'json', isWrapped: true, size: "sm", hasCopyButton: true })) : null] }));
|
|
66
|
+
}
|
|
67
|
+
/** An option's label, with its meaning on hover. */
|
|
68
|
+
function OptionValue({ option }) {
|
|
69
|
+
return (_jsx(Tooltip, { content: option.doc, children: _jsx(Text, { children: option.label }) }));
|
|
70
|
+
}
|
|
71
|
+
function formatNumber(format, meta, value) {
|
|
72
|
+
switch (meta?.format) {
|
|
73
|
+
case 'usd':
|
|
74
|
+
return format.usd(value);
|
|
75
|
+
case 'milliseconds':
|
|
76
|
+
return format.duration(value);
|
|
77
|
+
case 'seconds':
|
|
78
|
+
return format.duration(value * 1_000);
|
|
79
|
+
default:
|
|
80
|
+
return format.number(value);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function StringValue({ meta, value }) {
|
|
84
|
+
const option = meta?.options?.[value];
|
|
85
|
+
if (option)
|
|
86
|
+
return _jsx(OptionValue, { option: option });
|
|
87
|
+
if (meta?.format === 'time')
|
|
88
|
+
return (_jsx(Timestamp, { value: nanosToMs(value), format: "system_date_time", size: "base", color: "primary" }));
|
|
89
|
+
return _jsx(Text, { wordBreak: "break-word", children: value });
|
|
90
|
+
}
|
|
91
|
+
function ScalarValue({ meta, value, }) {
|
|
92
|
+
const format = useTraceFormat();
|
|
93
|
+
if (typeof value === 'boolean')
|
|
94
|
+
return _jsx(Text, { children: format.t(value ? '@theorem.panel.trace.yes' : '@theorem.panel.trace.no') });
|
|
95
|
+
return _jsx(Text, { hasTabularNumbers: true, children: formatNumber(format, meta, value) });
|
|
96
|
+
}
|
|
97
|
+
function ListValue({ meta, value, }) {
|
|
98
|
+
const format = useTraceFormat();
|
|
99
|
+
return _jsx(Text, { children: format.list(value.map((item) => meta?.options?.[item]?.label ?? item)) });
|
|
100
|
+
}
|
|
101
|
+
/** One attribute value, read by its catalog entry; a key the catalog does not name reads by its shape. */
|
|
102
|
+
export function TraceValue({ record, meta, value, }) {
|
|
103
|
+
const shape = traceValueShape(meta, value);
|
|
104
|
+
switch (shape.kind) {
|
|
105
|
+
case 'text':
|
|
106
|
+
return _jsx(StringValue, { meta: meta, value: shape.value });
|
|
107
|
+
case 'scalar':
|
|
108
|
+
return _jsx(ScalarValue, { meta: meta, value: shape.value });
|
|
109
|
+
case 'list':
|
|
110
|
+
return _jsx(ListValue, { meta: meta, value: shape.value });
|
|
111
|
+
case 'fields':
|
|
112
|
+
return (_jsx(VStack, { gap: 2, children: keyedByContent(shape.items, (item) => JSON.stringify(item)).map(({ item, key }) => (_jsx(TraceAttributeList, { record: record, attributes: item, metaOf: (key) => shape.fields[key] }, key))) }));
|
|
113
|
+
case 'stored':
|
|
114
|
+
return _jsx(StoredText, { record: record, value: value });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/** Attributes as label and value rows, worded by `metaOf`; a key it does not name shows as recorded. */
|
|
118
|
+
export function TraceAttributeList({ record, attributes, metaOf, maxNumOfItems, title, }) {
|
|
119
|
+
const entries = Object.entries(attributes);
|
|
120
|
+
if (entries.length === 0)
|
|
121
|
+
return null;
|
|
122
|
+
return (_jsx(MetadataList, { columns: "single", label: { position: 'start', width: TRACE_LABEL_PX }, maxNumOfItems: maxNumOfItems, title: title, children: entries.map(([key, value]) => (_jsx(MetadataListItem, { label: metaOf(key)?.label ?? key, children: _jsx(TraceValue, { record: record, meta: metaOf(key), value: value }) }, key))) }));
|
|
123
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TraceNode } from '../client/trace-view.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Every span of the turn on one time axis, nested by depth and coloured by
|
|
4
|
+
* who acted. Above it, how busy the model and tools were over the turn; drag
|
|
5
|
+
* across that strip to zoom the rows into the window, as in a performance
|
|
6
|
+
* profile. A bar opens its span.
|
|
7
|
+
*/
|
|
8
|
+
export declare function TraceWaterfall({ root, selectedId, matches, onSelect, }: {
|
|
9
|
+
root: TraceNode;
|
|
10
|
+
selectedId: string | undefined;
|
|
11
|
+
matches: ReadonlySet<string> | undefined;
|
|
12
|
+
onSelect: (node: TraceNode) => void;
|
|
13
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button } from '@astryxdesign/core/Button';
|
|
3
|
+
import { HStack } from '@astryxdesign/core/HStack';
|
|
4
|
+
import { Icon } from '@astryxdesign/core/Icon';
|
|
5
|
+
import { Text } from '@astryxdesign/core/Text';
|
|
6
|
+
import { VStack } from '@astryxdesign/core/VStack';
|
|
7
|
+
import { IconZoomOut } from '@tabler/icons-react';
|
|
8
|
+
import { useMemo, useRef, useState } from 'react';
|
|
9
|
+
import { Area, AreaChart, Bar, BarChart, CartesianGrid, Cell, ReferenceArea, ResponsiveContainer, Tooltip, XAxis, YAxis, } from 'recharts';
|
|
10
|
+
import { traceActivity, traceActor, traceBars, traceOutcome, } from "../client/trace-story.js";
|
|
11
|
+
import { ChartFrame, ChartTip, FIRST_WIDTH_PX } from "./TraceOverview.js";
|
|
12
|
+
import { useTraceFormat } from "./TraceValues.js";
|
|
13
|
+
import { TRACE_HUE } from "./trace-palette.js";
|
|
14
|
+
import { ACTOR_FILL, TRACE_RADIUS, traceFill } from "./trace-patterns.js";
|
|
15
|
+
/** Slices in the activity strip. */
|
|
16
|
+
const BUCKETS = 120;
|
|
17
|
+
/** Height of one span's row, in pixels. */
|
|
18
|
+
const ROW_PX = 22;
|
|
19
|
+
/** Height of the time axis under the rows. */
|
|
20
|
+
const AXIS_PX = 24;
|
|
21
|
+
/** Height of the activity strip. */
|
|
22
|
+
const STRIP_PX = 36;
|
|
23
|
+
/** Room right of the plot, so the last tick's label fits. */
|
|
24
|
+
const PLOT_RIGHT_PX = 4;
|
|
25
|
+
/** Width of the name column, in pixels. */
|
|
26
|
+
const NAME_PX = 132;
|
|
27
|
+
/** Indent per level of nesting in the name column. */
|
|
28
|
+
const INDENT_PX = 8;
|
|
29
|
+
function barHatch(node) {
|
|
30
|
+
return ACTOR_FILL[traceActor(node)];
|
|
31
|
+
}
|
|
32
|
+
function BarTip({ active, payload }) {
|
|
33
|
+
const format = useTraceFormat();
|
|
34
|
+
const row = payload?.[0]?.payload;
|
|
35
|
+
if (!active || !row)
|
|
36
|
+
return null;
|
|
37
|
+
const { node, from } = row.bar;
|
|
38
|
+
const outcome = traceOutcome(node);
|
|
39
|
+
const cost = node.span.attributes['theorem.usage.cost_usd'];
|
|
40
|
+
return (_jsx(ChartTip, { children: _jsxs(VStack, { gap: 0, children: [_jsx(Text, { weight: "medium", children: row.name }), _jsx(Text, { type: "supporting", color: "secondary", children: node.meta.label }), _jsx(Text, { type: "supporting", hasTabularNumbers: true, children: [
|
|
41
|
+
format.duration(node.durationMs),
|
|
42
|
+
format.t('@theorem.panel.trace.offset', { duration: format.duration(from) }),
|
|
43
|
+
...(typeof cost === 'number' ? [format.usd(cost)] : []),
|
|
44
|
+
].join(format.t('@theorem.panel.trace.separator')) }), outcome ? (_jsx(Text, { type: "supporting", children: _jsx("span", { style: {
|
|
45
|
+
color: outcome.tone === 'error' ? TRACE_HUE.oxblood : 'var(--color-text-secondary)',
|
|
46
|
+
}, children: outcome.label }) })) : null] }) }));
|
|
47
|
+
}
|
|
48
|
+
/** A row's name, from the chart's left edge, set in by its depth and cut to the column. */
|
|
49
|
+
function NameTick({ y: rawY, payload, rows, }) {
|
|
50
|
+
const row = typeof payload?.value === 'string' ? rows.get(payload.value) : undefined;
|
|
51
|
+
const y = Number(rawY);
|
|
52
|
+
if (!row || Number.isNaN(y))
|
|
53
|
+
return null;
|
|
54
|
+
const indent = Math.min(row.bar.depth, 4) * INDENT_PX;
|
|
55
|
+
const room = Math.floor((NAME_PX - indent - 10) / 6.2);
|
|
56
|
+
const name = row.name.length > room ? `${row.name.slice(0, Math.max(1, room - 1))}…` : row.name;
|
|
57
|
+
return (_jsxs("text", { x: indent, y: y, dy: "0.35em", fontSize: 11, fill: row.bar.node.span.status.code === 'ERROR'
|
|
58
|
+
? TRACE_HUE.oxblood
|
|
59
|
+
: 'var(--color-text-secondary)', children: [_jsx("title", { children: row.name }), name] }));
|
|
60
|
+
}
|
|
61
|
+
/** How busy the model and tools were over the turn; a drag across it picks the window to zoom into. */
|
|
62
|
+
function ActivityStrip({ root, zoom, onZoom, }) {
|
|
63
|
+
const activity = useMemo(() => traceActivity(root, BUCKETS), [root]);
|
|
64
|
+
const total = Math.max(root.durationMs, 1);
|
|
65
|
+
const [drag, setDrag] = useState(null);
|
|
66
|
+
// why: Pointer events can outrun a render; the ref always holds the drag so far.
|
|
67
|
+
const dragRef = useRef(null);
|
|
68
|
+
const moveDrag = (next) => {
|
|
69
|
+
dragRef.current = next;
|
|
70
|
+
setDrag(next);
|
|
71
|
+
};
|
|
72
|
+
/** The time under a pointer on the strip, in ms from the turn's start. */
|
|
73
|
+
const timeAt = (event) => {
|
|
74
|
+
const box = event.currentTarget.getBoundingClientRect();
|
|
75
|
+
const share = (event.clientX - box.left - NAME_PX) / Math.max(box.width - NAME_PX - PLOT_RIGHT_PX, 1);
|
|
76
|
+
return Math.min(Math.max(share, 0), 1) * total;
|
|
77
|
+
};
|
|
78
|
+
const endDrag = () => {
|
|
79
|
+
const done = dragRef.current;
|
|
80
|
+
if (done) {
|
|
81
|
+
const from = Math.min(done.from, done.to);
|
|
82
|
+
const to = Math.max(done.from, done.to);
|
|
83
|
+
if (to - from >= total / BUCKETS)
|
|
84
|
+
onZoom({ root: root.id, from, to });
|
|
85
|
+
}
|
|
86
|
+
moveDrag(null);
|
|
87
|
+
};
|
|
88
|
+
const shown = drag ?? zoom;
|
|
89
|
+
return (_jsx("div", { role: "application", style: { cursor: 'col-resize', userSelect: 'none', touchAction: 'none' }, onPointerDown: (event) => {
|
|
90
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
91
|
+
const value = timeAt(event);
|
|
92
|
+
moveDrag({ from: value, to: value });
|
|
93
|
+
}, onPointerMove: (event) => {
|
|
94
|
+
const current = dragRef.current;
|
|
95
|
+
if (current)
|
|
96
|
+
moveDrag({ from: current.from, to: timeAt(event) });
|
|
97
|
+
}, onPointerUp: endDrag, onPointerCancel: () => moveDrag(null), onMouseDown: (event) => event.preventDefault(), children: _jsx(ResponsiveContainer, { width: "100%", height: STRIP_PX, initialDimension: { width: FIRST_WIDTH_PX, height: STRIP_PX }, children: _jsxs(AreaChart, { data: activity, margin: { top: 2, right: PLOT_RIGHT_PX, bottom: 0, left: NAME_PX }, accessibilityLayer: false, children: [_jsx(XAxis, { dataKey: "at", type: "number", domain: [0, total], hide: true }), _jsx(YAxis, { hide: true, domain: [0, 2] }), _jsx(Area, { type: "monotone", dataKey: "model", stackId: "busy", activeDot: false, stroke: "none", fill: traceFill('clear'), fillOpacity: 1, isAnimationActive: false }), _jsx(Area, { type: "monotone", dataKey: "tools", stackId: "busy", activeDot: false, stroke: "none", fill: traceFill('hatch'), fillOpacity: 1, isAnimationActive: false }), shown ? (_jsx(ReferenceArea, { x1: shown.from, x2: shown.to, fill: "var(--color-text-primary)", fillOpacity: drag ? 0.12 : 0.08, stroke: "var(--color-border-emphasized)" })) : null] }) }) }));
|
|
98
|
+
}
|
|
99
|
+
/** A bar's opacity: faded when the search passed it over, the turn itself half-strength, and the rest dimmed around a selection. */
|
|
100
|
+
function barOpacity(row, selectedId, matches) {
|
|
101
|
+
if (matches && !matches.has(row.id))
|
|
102
|
+
return 0.25;
|
|
103
|
+
if (row.bar.depth === 0)
|
|
104
|
+
return 0.45;
|
|
105
|
+
return !selectedId || row.id === selectedId ? 1 : 0.5;
|
|
106
|
+
}
|
|
107
|
+
/** One bar per span over the time window, named on the left. */
|
|
108
|
+
function SpanBars({ root, domain, selectedId, matches, onSelect, }) {
|
|
109
|
+
const format = useTraceFormat();
|
|
110
|
+
const rows = useMemo(() => traceBars(root).map((bar) => ({
|
|
111
|
+
id: bar.node.id,
|
|
112
|
+
bar,
|
|
113
|
+
range: [bar.from, bar.to],
|
|
114
|
+
name: bar.node.meta.subject ?? bar.node.meta.label,
|
|
115
|
+
})), [root]);
|
|
116
|
+
const byId = useMemo(() => new Map(rows.map((row) => [row.id, row])), [rows]);
|
|
117
|
+
const height = rows.length * ROW_PX + AXIS_PX;
|
|
118
|
+
return (_jsx(ChartFrame, { children: _jsx(ResponsiveContainer, { width: "100%", height: height, initialDimension: { width: FIRST_WIDTH_PX, height }, children: _jsxs(BarChart, { data: rows, layout: "vertical", accessibilityLayer: false, margin: { top: 0, right: PLOT_RIGHT_PX, bottom: 0, left: 0 }, barCategoryGap: 4, onClick: (state) => {
|
|
119
|
+
const row = rows[Number(state?.activeIndex)];
|
|
120
|
+
if (row)
|
|
121
|
+
onSelect(row.bar.node);
|
|
122
|
+
}, style: { cursor: 'pointer' }, children: [_jsx(CartesianGrid, { horizontal: false, stroke: "var(--color-border)", strokeDasharray: "2 4" }), _jsx(XAxis, { type: "number", domain: domain, allowDataOverflow: true, tickFormatter: (value) => format.duration(value), tick: { fill: 'var(--color-text-secondary)', fontSize: 11 }, axisLine: { stroke: 'var(--color-border)' }, tickLine: false, height: AXIS_PX, tickCount: 5 }), _jsx(YAxis, { type: "category", dataKey: "id", width: NAME_PX, axisLine: false, tickLine: false, interval: 0, tick: (props) => _jsx(NameTick, { ...props, rows: byId }) }), _jsx(Tooltip, { content: (props) => _jsx(BarTip, { ...props }), cursor: { fill: 'var(--color-overlay-hover)' }, isAnimationActive: false }), _jsx(Bar, { dataKey: "range", minPointSize: 2, radius: TRACE_RADIUS, isAnimationActive: false, style: { cursor: 'pointer' }, children: rows.map((row) => (_jsx(Cell, { fill: traceFill(barHatch(row.bar.node)), opacity: barOpacity(row, selectedId, matches) }, row.id))) })] }) }) }));
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Every span of the turn on one time axis, nested by depth and coloured by
|
|
126
|
+
* who acted. Above it, how busy the model and tools were over the turn; drag
|
|
127
|
+
* across that strip to zoom the rows into the window, as in a performance
|
|
128
|
+
* profile. A bar opens its span.
|
|
129
|
+
*/
|
|
130
|
+
export function TraceWaterfall({ root, selectedId, matches, onSelect, }) {
|
|
131
|
+
const { t } = useTraceFormat();
|
|
132
|
+
const [picked, setPicked] = useState(null);
|
|
133
|
+
const zoom = picked?.root === root.id ? picked : null;
|
|
134
|
+
return (_jsxs(VStack, { gap: 2, className: "theorem-arrive", children: [_jsxs(HStack, { gap: 2, align: "center", justify: "between", children: [_jsx(Text, { type: "supporting", color: "secondary", children: t('@theorem.panel.trace.timeline.zoom') }), zoom ? (_jsx(Button, { label: t('@theorem.panel.trace.timeline.reset'), variant: "ghost", size: "sm", icon: _jsx(Icon, { icon: IconZoomOut }), onClick: () => setPicked(null) })) : null] }), _jsx(ActivityStrip, { root: root, zoom: zoom, onZoom: setPicked }), _jsx(SpanBars, { root: root, domain: zoom ? [zoom.from, zoom.to] : [0, Math.max(root.durationMs, 1)], selectedId: selectedId, matches: matches, onSelect: onSelect })] }));
|
|
135
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type VoiceNoteProps = {
|
|
2
|
+
src: string;
|
|
3
|
+
mimeType?: string;
|
|
4
|
+
label?: string;
|
|
5
|
+
/** Composer only: removes the staged note. */
|
|
6
|
+
onRemove?: () => void;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Voice note as an Astryx ClickableCard holding the ink waveform (the one live
|
|
10
|
+
* uses): click to play or pause; the bars move while it plays.
|
|
11
|
+
*/
|
|
12
|
+
export declare function VoiceNote({ src, mimeType, label, onRemove }: VoiceNoteProps): import("react").JSX.Element;
|
package/ui/VoiceNote.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ClickableCard } from '@astryxdesign/core/ClickableCard';
|
|
3
|
+
import { HStack } from '@astryxdesign/core/HStack';
|
|
4
|
+
import { Icon } from '@astryxdesign/core/Icon';
|
|
5
|
+
import { IconButton } from '@astryxdesign/core/IconButton';
|
|
6
|
+
import { VStack } from '@astryxdesign/core/VStack';
|
|
7
|
+
import { IconX } from '@tabler/icons-react';
|
|
8
|
+
import { voiceFormatFromMime } from "../client/voice-label.js";
|
|
9
|
+
import { InkWaveform } from "../components/InkWaveform.js";
|
|
10
|
+
import { useVoicePlayback } from "../components/use-voice-playback.js";
|
|
11
|
+
import { voiceNoteName } from "./labels.js";
|
|
12
|
+
import { useLabels } from "./labels-provider.js";
|
|
13
|
+
/** Astryx Thumbnail's height, so voice notes sit level with image attachments. */
|
|
14
|
+
const VOICE_NOTE_HEIGHT = 64;
|
|
15
|
+
const VOICE_NOTE_WIDTH = 160;
|
|
16
|
+
/**
|
|
17
|
+
* Voice note as an Astryx ClickableCard holding the ink waveform (the one live
|
|
18
|
+
* uses): click to play or pause; the bars move while it plays.
|
|
19
|
+
*/
|
|
20
|
+
export function VoiceNote({ src, mimeType = 'audio/webm', label, onRemove }) {
|
|
21
|
+
const t = useLabels();
|
|
22
|
+
const { playing, levelsRef, toggle, audioProps } = useVoicePlayback();
|
|
23
|
+
const name = label ?? voiceNoteName(t, voiceFormatFromMime(mimeType));
|
|
24
|
+
const remove = t('@theorem.voice_note.remove', { name });
|
|
25
|
+
return (_jsxs(HStack, { gap: 1, vAlign: "center", children: [_jsx(ClickableCard, { label: t(playing ? '@theorem.voice_note.pause' : '@theorem.voice_note.play', { name }), onClick: () => {
|
|
26
|
+
void toggle();
|
|
27
|
+
}, padding: 0, width: VOICE_NOTE_WIDTH, height: VOICE_NOTE_HEIGHT, children: _jsx(VStack, { width: "100%", height: "100%", paddingInline: 2, paddingBlockStart: 2, style: { color: 'var(--color-icon-primary)' }, "aria-hidden": "true", children: _jsx(InkWaveform, { frozen: !playing, levelsRef: levelsRef, status: playing ? 'speaking' : 'ready', variant: "pill" }) }) }), onRemove ? (_jsx(IconButton, { label: remove, tooltip: remove, variant: "ghost", size: "sm", icon: _jsx(Icon, { icon: IconX }), onClick: onRemove })) : null, _jsx("audio", { ...audioProps, src: src, hidden: true })] }));
|
|
28
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ToolGate } from '@theoremjs/agents/kernel';
|
|
2
|
+
import type { LabelText } from './labels.ts';
|
|
3
|
+
/** "@concierge wants to check the weather": the tool's `labels.request`, else its name in words. */
|
|
4
|
+
export declare function approvalHeading(t: LabelText, gate: ToolGate, toolName: string, agent?: string): string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { humanize } from "../client/shaped-data.js";
|
|
2
|
+
/** "@concierge wants to check the weather": the tool's `labels.request`, else its name in words. */
|
|
3
|
+
export function approvalHeading(t, gate, toolName, agent) {
|
|
4
|
+
const request = gate.request ??
|
|
5
|
+
t('@theorem.gate.approval.use_tool', { tool: humanize(toolName).toLowerCase() });
|
|
6
|
+
return agent
|
|
7
|
+
? t('@theorem.gate.approval.title', { agent, request })
|
|
8
|
+
: t('@theorem.gate.approval.title_no_agent', { request });
|
|
9
|
+
}
|
package/ui/arrive.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type CSSProperties, type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Items under this ease in one after another, in tree order. An item that
|
|
4
|
+
* mounts later (a span that just landed, a chart whose module just loaded)
|
|
5
|
+
* eases in on its own. Already-shown items do not replay.
|
|
6
|
+
*/
|
|
7
|
+
export declare function Stream({ children }: {
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
}): import("react").JSX.Element;
|
|
10
|
+
/** Class and delay for one item. Nothing outside a {@link Stream}. */
|
|
11
|
+
export declare function useArrive(): {
|
|
12
|
+
className: string;
|
|
13
|
+
style?: CSSProperties;
|
|
14
|
+
} | null;
|
|
15
|
+
/** A block that eases in with its siblings under {@link Stream}. */
|
|
16
|
+
export declare function Arrive({ children }: {
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
}): string | number | bigint | boolean | import("react").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | null | undefined;
|
package/ui/arrive.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, use, useRef, useState } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* How long each later item waits. Short enough that a handful still read as
|
|
5
|
+
* one arrival, long enough that the order is visible.
|
|
6
|
+
*/
|
|
7
|
+
const STEP_MS = 64;
|
|
8
|
+
/** Past this, the rest start together so a long list is not still waiting. */
|
|
9
|
+
const CAP = 10;
|
|
10
|
+
const ArriveSeq = createContext(null);
|
|
11
|
+
/**
|
|
12
|
+
* Items under this ease in one after another, in tree order. An item that
|
|
13
|
+
* mounts later (a span that just landed, a chart whose module just loaded)
|
|
14
|
+
* eases in on its own. Already-shown items do not replay.
|
|
15
|
+
*/
|
|
16
|
+
export function Stream({ children }) {
|
|
17
|
+
const seq = useRef(0);
|
|
18
|
+
// why: Each render starts again. Items remember the place they took, so a
|
|
19
|
+
// re-render does not hand that place to someone else.
|
|
20
|
+
seq.current = 0;
|
|
21
|
+
return _jsx(ArriveSeq, { value: seq, children: children });
|
|
22
|
+
}
|
|
23
|
+
/** Class and delay for one item. Nothing outside a {@link Stream}. */
|
|
24
|
+
export function useArrive() {
|
|
25
|
+
const seq = use(ArriveSeq);
|
|
26
|
+
const slot = useRef(null);
|
|
27
|
+
if (seq && slot.current === null) {
|
|
28
|
+
slot.current = seq.current;
|
|
29
|
+
seq.current += 1;
|
|
30
|
+
}
|
|
31
|
+
const index = seq ? slot.current : null;
|
|
32
|
+
const [delay] = useState(() => (index === null ? 0 : Math.min(index, CAP) * STEP_MS));
|
|
33
|
+
if (index === null)
|
|
34
|
+
return null;
|
|
35
|
+
return {
|
|
36
|
+
className: 'theorem-arrive',
|
|
37
|
+
style: delay > 0 ? { animationDelay: `${String(delay)}ms` } : undefined,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/** A block that eases in with its siblings under {@link Stream}. */
|
|
41
|
+
export function Arrive({ children }) {
|
|
42
|
+
const arrive = useArrive();
|
|
43
|
+
if (!arrive)
|
|
44
|
+
return children;
|
|
45
|
+
return (_jsx("div", { className: arrive.className, style: arrive.style, children: children }));
|
|
46
|
+
}
|