@theoremjs/react 0.3.0 → 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/README.md +728 -202
- package/client/composer-hints.js +1 -1
- package/client/decision-images.d.ts +76 -0
- package/client/decision-images.js +139 -0
- package/client/decision-transport.d.ts +26 -4
- package/client/decision-transport.js +79 -6
- 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/failure.d.ts +7 -10
- package/client/failure.js +9 -9
- package/client/host-call.d.ts +1 -1
- package/client/host-call.js +7 -2
- package/client/host-transport.d.ts +2 -0
- package/client/host-transport.js +3 -2
- package/client/index.d.ts +19 -11
- package/client/index.js +14 -10
- package/client/ink-waveform.d.ts +1 -1
- package/client/ink-waveform.js +1 -2
- package/client/live/apply-live-turn-tool-event.js +1 -1
- package/client/live/live-captions.d.ts +30 -0
- package/client/live/live-captions.js +105 -1
- package/client/live/live-mic-forward.d.ts +1 -0
- package/client/live/live-mic-forward.js +11 -2
- 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 +4 -2
- package/client/live/live-state.js +2 -0
- package/client/live/live-video.js +1 -1
- package/client/live/run-live-tool-call.d.ts +7 -2
- package/client/live/run-live-tool-call.js +48 -10
- 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 +52 -4
- package/client/live-client.js +250 -59
- package/client/live-messages.d.ts +51 -13
- package/client/live-messages.js +42 -9
- package/client/page-dispatch.d.ts +15 -0
- package/client/page-dispatch.js +63 -0
- package/client/run-commit.d.ts +16 -43
- package/client/run-commit.js +26 -101
- package/client/run-session.d.ts +40 -41
- package/client/run-session.js +104 -112
- package/client/schema-fields.js +27 -6
- package/client/shaped-data.js +37 -8
- package/client/source-citations.js +1 -1
- package/client/space-geometry.d.ts +39 -0
- package/client/space-geometry.js +183 -0
- package/client/state-fields.js +1 -1
- package/client/tool-result.js +30 -12
- package/client/tool-resume.d.ts +18 -1
- package/client/tool-resume.js +4 -1
- package/client/trace-feed.d.ts +1 -1
- package/client/trace-story.d.ts +2 -2
- package/client/trace-story.js +43 -19
- package/client/trace-view.d.ts +2 -2
- package/client/trace-view.js +56 -16
- package/client/transcript-groups.d.ts +28 -2
- package/client/transcript-groups.js +63 -13
- package/client/transcript-schema.d.ts +10 -0
- package/client/transcript-schema.js +120 -0
- package/client/transport.d.ts +114 -26
- package/client/transport.js +106 -32
- package/client/turn-client.d.ts +17 -8
- package/client/turn-client.js +26 -31
- package/client/voice-recorder.d.ts +1 -1
- package/client/voice-recorder.js +2 -5
- package/client/wire-line.js +5 -5
- package/client/worklets/mic-capture.js +9 -9
- package/components/InkWaveform.d.ts +12 -1
- package/components/InkWaveform.js +65 -42
- package/components/live/use-live-runner-controls.d.ts +3 -4
- package/components/live/use-live-runner-controls.js +6 -10
- package/components/live/use-live-runner-model.d.ts +10 -6
- package/components/live/use-live-runner-model.js +29 -14
- package/components/live/use-live-runner-ui.d.ts +10 -8
- package/components/live/use-live-runner-ui.js +19 -11
- package/components/live/use-live-session-client.d.ts +4 -4
- package/components/live/use-live-session-client.js +11 -8
- package/components/use-composer-voice.d.ts +4 -4
- package/components/use-composer-voice.js +8 -8
- package/components/use-editor-selection.js +4 -1
- package/components/use-voice-playback.d.ts +2 -1
- package/components/use-voice-playback.js +4 -4
- package/hooks/use-described.d.ts +5 -1
- package/hooks/use-described.js +11 -9
- 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 +25 -21
- package/hooks/use-theorem-chat-actions.js +67 -45
- package/hooks/use-theorem-chat-state.d.ts +6 -6
- package/hooks/use-theorem-chat-state.js +13 -9
- package/hooks/use-theorem-chat.d.ts +48 -14
- package/hooks/use-theorem-chat.js +329 -141
- package/hooks/use-theorem-decision.d.ts +5 -10
- package/hooks/use-theorem-decision.js +4 -67
- package/hooks/use-theorem-embedding.d.ts +18 -0
- package/hooks/use-theorem-embedding.js +12 -0
- package/hooks/use-theorem-host.d.ts +5 -4
- package/hooks/use-theorem-host.js +26 -8
- package/hooks/use-theorem-interface.d.ts +6 -3
- package/hooks/use-theorem-interface.js +12 -22
- package/index.d.ts +6 -3
- package/index.js +5 -2
- package/live.d.ts +1 -0
- package/live.js +1 -1
- package/package.json +6 -5
- 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/decision-handler.d.ts +12 -4
- package/server/decision-handler.js +29 -38
- package/server/embedding-handler.d.ts +33 -0
- package/server/embedding-handler.js +45 -0
- package/server/handler.d.ts +58 -20
- package/server/handler.js +441 -238
- package/server/mod.d.ts +15 -6
- package/server/mod.js +13 -5
- 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 +6 -1
- package/server/request-check.js +27 -12
- 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 +69 -20
- package/server/session-store.js +220 -5
- package/server/single-action.d.ts +21 -0
- package/server/single-action.js +30 -0
- package/server/steer-inbox.js +1 -1
- 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 +78 -78
- package/ui/CardWall.d.ts +10 -0
- package/ui/CardWall.js +61 -0
- package/ui/ChatComposerBar.d.ts +28 -5
- package/ui/ChatComposerBar.js +85 -30
- package/ui/ChatTranscript.d.ts +14 -1
- package/ui/ChatTranscript.js +110 -57
- package/ui/ConsoleFrame.d.ts +61 -4
- package/ui/ConsoleFrame.js +109 -9
- package/ui/DecisionAnswers.d.ts +40 -2
- package/ui/DecisionAnswers.js +166 -35
- 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 +6 -4
- package/ui/LiveRunner.js +42 -55
- package/ui/PaneState.d.ts +33 -0
- package/ui/PaneState.js +50 -0
- package/ui/SchemaFields.d.ts +1 -1
- package/ui/SchemaFields.js +54 -26
- package/ui/ShapedData.js +73 -28
- package/ui/SidePanel.d.ts +74 -5
- package/ui/SidePanel.js +82 -9
- package/ui/StateFields.d.ts +10 -2
- package/ui/StateFields.js +56 -13
- package/ui/TheoremChat.d.ts +65 -14
- package/ui/TheoremChat.js +66 -78
- package/ui/TheoremDecision.d.ts +12 -20
- package/ui/TheoremDecision.js +78 -35
- package/ui/TheoremEmbedding.d.ts +27 -0
- package/ui/TheoremEmbedding.js +122 -0
- package/ui/TheoremHost.d.ts +22 -5
- package/ui/TheoremHost.js +127 -37
- package/ui/ToolGateCard.d.ts +5 -1
- package/ui/ToolGateCard.js +30 -23
- package/ui/ToolResult.js +12 -10
- package/ui/ToolResultCharts.js +29 -12
- package/ui/TraceCharts.d.ts +2 -2
- package/ui/TraceCharts.js +48 -17
- package/ui/TraceGuardrails.d.ts +3 -2
- package/ui/TraceGuardrails.js +24 -6
- package/ui/TraceInspector.d.ts +11 -1
- package/ui/TraceInspector.js +45 -28
- package/ui/TraceInspectorPanel.d.ts +31 -9
- package/ui/TraceInspectorPanel.js +77 -39
- package/ui/TraceOverview.d.ts +7 -3
- package/ui/TraceOverview.js +44 -14
- package/ui/TraceSpanDetail.js +24 -22
- package/ui/TraceStory.js +9 -8
- package/ui/TraceValues.js +19 -9
- package/ui/TraceWaterfall.js +12 -9
- package/ui/VoiceNote.js +4 -4
- 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 +86 -68
- package/ui/built/theme.css.d.ts +9 -0
- package/ui/built/theorem.d.ts +3 -3
- package/ui/built/theorem.js +34 -5
- package/ui/built/theorem.variants.d.ts +8 -2
- package/ui/code-language.d.ts +12 -0
- package/ui/code-language.js +50 -0
- package/ui/disclosure-motion.js +53 -9
- 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.js +2 -1
- package/ui/index.d.ts +20 -9
- package/ui/index.js +20 -10
- package/ui/labels-provider.js +5 -2
- package/ui/labels.d.ts +374 -85
- package/ui/labels.js +1028 -188
- 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 +1 -1
- package/ui/theme.js +2 -2
- package/ui/theorem-theme.js +32 -10
- package/ui/trace-palette.d.ts +2 -16
- package/ui/trace-palette.js +2 -16
- package/ui/trace-patterns.d.ts +11 -3
- package/ui/trace-patterns.js +16 -3
- package/ui/transcript-copy-text.js +1 -0
- package/ui/wall-columns.d.ts +8 -0
- package/ui/wall-columns.js +19 -0
- package/client/walk-away.d.ts +0 -34
- package/client/walk-away.js +0 -48
- package/server/walk-away.d.ts +0 -22
- package/server/walk-away.js +0 -41
package/ui/TraceSpanDetail.js
CHANGED
|
@@ -15,9 +15,11 @@ import { IconArrowLeft, IconX } from '@tabler/icons-react';
|
|
|
15
15
|
import { inlineContent, TRACE_ATTRIBUTE_GROUPS, TRACE_FIELDS, TRACE_SPAN_TYPES, TRACE_STATUS, traceAttributeMeta, traceEventAttributeMeta, traceEventMeta, } from '@theoremjs/agents';
|
|
16
16
|
import { messageText, storedValue, traceActor, traceOutcome } from "../client/trace-story.js";
|
|
17
17
|
import { nanosToMs } from "../client/trace-view.js";
|
|
18
|
+
import { keyedByContent } from "./row-keys.js";
|
|
18
19
|
import { ShapedData } from "./ShapedData.js";
|
|
20
|
+
import { PanePanel, Prose } from "./SidePanel.js";
|
|
19
21
|
import { ActorMark } from "./TraceStory.js";
|
|
20
|
-
import { attributeSections, TRACE_LABEL_PX, TraceAttributeList, TraceValue, useTraceFormat } from "./TraceValues.js";
|
|
22
|
+
import { attributeSections, TRACE_LABEL_PX, TraceAttributeList, TraceValue, useTraceFormat, } from "./TraceValues.js";
|
|
21
23
|
/** A span's own field, read as an attribute of that format. */
|
|
22
24
|
function fieldMeta(field, format) {
|
|
23
25
|
return { ...field, format, group: 'record' };
|
|
@@ -37,12 +39,12 @@ function Section({ title, children }) {
|
|
|
37
39
|
}
|
|
38
40
|
function EventList({ node }) {
|
|
39
41
|
const format = useTraceFormat();
|
|
40
|
-
return (_jsx(VStack, { gap: 3, children: node.span.events.map((event,
|
|
42
|
+
return (_jsx(VStack, { gap: 3, children: keyedByContent(node.span.events, (event) => `${event.name}:${event.timeUnixNano}`).map(({ item: event, key }) => {
|
|
41
43
|
const offset = format.t('@theorem.panel.trace.offset', {
|
|
42
44
|
duration: format.duration(nanosToMs(event.timeUnixNano) - node.startMs),
|
|
43
45
|
});
|
|
44
46
|
const label = traceEventMeta(event.name)?.label ?? event.name;
|
|
45
|
-
return (_jsxs(VStack, { gap: 1, children: [_jsxs(HStack, { gap: 2, align: "center", children: [_jsx(Text, { weight: "medium", children: label }), _jsx(Text, { type: "supporting", hasTabularNumbers: true, children: offset })] }), _jsx(TraceAttributeList, { record: node.record, attributes: event.attributes, metaOf: (key) => traceEventAttributeMeta(event.name, key) })] },
|
|
47
|
+
return (_jsxs(VStack, { gap: 1, children: [_jsxs(HStack, { gap: 2, align: "center", children: [_jsx(Text, { weight: "medium", children: label }), _jsx(Text, { type: "supporting", hasTabularNumbers: true, children: offset })] }), _jsx(TraceAttributeList, { record: node.record, attributes: event.attributes, metaOf: (key) => traceEventAttributeMeta(event.name, key) })] }, key));
|
|
46
48
|
}) }));
|
|
47
49
|
}
|
|
48
50
|
function LinkList({ node }) {
|
|
@@ -54,14 +56,16 @@ const SPAN_FIELD_VALUES = {
|
|
|
54
56
|
traceId: (node) => node.span.traceId,
|
|
55
57
|
spanId: (node) => node.span.spanId,
|
|
56
58
|
};
|
|
57
|
-
/** What the span was, how long it took, what it cost and when it started. */
|
|
59
|
+
/** What the span was, how long it took, what it cost, and when it started. */
|
|
58
60
|
function spanFacts(node, turnStartMs, format) {
|
|
59
61
|
const cost = node.span.attributes['theorem.usage.cost_usd'];
|
|
60
62
|
return [
|
|
61
63
|
node.meta.label,
|
|
62
64
|
format.duration(node.durationMs),
|
|
63
65
|
...(typeof cost === 'number' ? [format.usd(cost)] : []),
|
|
64
|
-
format.t('@theorem.panel.trace.offset', {
|
|
66
|
+
format.t('@theorem.panel.trace.offset', {
|
|
67
|
+
duration: format.duration(node.startMs - turnStartMs),
|
|
68
|
+
}),
|
|
65
69
|
].join(format.t('@theorem.panel.trace.separator'));
|
|
66
70
|
}
|
|
67
71
|
function OutcomeBadge({ outcome }) {
|
|
@@ -70,24 +74,18 @@ function OutcomeBadge({ outcome }) {
|
|
|
70
74
|
return (_jsx(HoverTip, { content: outcome.doc ?? outcome.label, children: _jsx(Badge, { variant: outcome.tone, label: outcome.label }) }));
|
|
71
75
|
}
|
|
72
76
|
/** The span's status message, unless the outcome badge already says it. */
|
|
73
|
-
function StatusMessage({ node, outcome }) {
|
|
77
|
+
function StatusMessage({ node, outcome, }) {
|
|
74
78
|
const message = node.span.status.message;
|
|
75
79
|
if (!message || message.toLowerCase() === outcome?.label.toLowerCase())
|
|
76
80
|
return null;
|
|
77
81
|
return _jsx(Text, { color: "secondary", children: message });
|
|
78
82
|
}
|
|
79
|
-
/** Back (or close), then who acted, what it was, how it ended, how long it took and what it cost. */
|
|
80
|
-
function SpanHeader({ node, turnStartMs, onBack, isClose }) {
|
|
83
|
+
/** Back (or close), then who acted, what it was, how it ended, how long it took, and what it cost. */
|
|
84
|
+
function SpanHeader({ node, turnStartMs, onBack, isClose, }) {
|
|
81
85
|
const format = useTraceFormat();
|
|
82
86
|
const outcome = traceOutcome(node);
|
|
83
87
|
return (_jsxs(VStack, { gap: 2, children: [_jsx(HStack, { children: _jsx(Button, { label: format.t(isClose ? '@theorem.panel.trace.close' : '@theorem.panel.trace.back'), variant: "ghost", size: "sm", icon: _jsx(Icon, { icon: isClose ? IconX : IconArrowLeft }), onClick: onBack }) }), _jsx(Item, { startContent: _jsx(ActorMark, { actor: traceActor(node) }), label: _jsx(Text, { weight: "semibold", children: node.meta.subject ?? node.meta.label }), description: spanFacts(node, turnStartMs, format), endContent: _jsx(OutcomeBadge, { outcome: outcome }), align: "start" }), _jsx(StatusMessage, { node: node, outcome: outcome })] }));
|
|
84
88
|
}
|
|
85
|
-
function Panel({ title, doc, children }) {
|
|
86
|
-
return (_jsx(Card, { padding: 3, variant: "muted", style: { background: 'var(--color-background-surface)' }, children: _jsxs(VStack, { gap: 2, children: [_jsx(HoverTip, { content: doc ?? title, children: _jsx(Text, { type: "supporting", color: "secondary", children: title }) }), children] }) }));
|
|
87
|
-
}
|
|
88
|
-
function Prose({ text }) {
|
|
89
|
-
return _jsx("span", { style: { whiteSpace: 'pre-wrap', overflowWrap: 'anywhere' }, children: text });
|
|
90
|
-
}
|
|
91
89
|
function parsed(value) {
|
|
92
90
|
if (typeof value !== 'string')
|
|
93
91
|
return value;
|
|
@@ -115,9 +113,9 @@ function PartView({ part }) {
|
|
|
115
113
|
}
|
|
116
114
|
/** Messages as the model saw them: each one's role, then its parts. */
|
|
117
115
|
function MessageList({ messages }) {
|
|
118
|
-
return (_jsx(VStack, { gap: 3, children: messages.map((message,
|
|
119
|
-
? message.parts.filter(isObject).map((part,
|
|
120
|
-
: null] },
|
|
116
|
+
return (_jsx(VStack, { gap: 3, children: keyedByContent(messages, (message) => JSON.stringify(message)).map(({ item: message, key }) => (_jsxs(VStack, { gap: 1, children: [_jsx(HStack, { children: _jsx(Token, { label: String(message.role ?? ''), size: "sm", color: "gray" }) }), Array.isArray(message.parts)
|
|
117
|
+
? keyedByContent(message.parts.filter(isObject), (part) => JSON.stringify(part)).map(({ item: part, key: partKey }) => _jsx(PartView, { part: part }, partKey))
|
|
118
|
+
: null] }, key))) }));
|
|
121
119
|
}
|
|
122
120
|
function messagesOf(node, key) {
|
|
123
121
|
const value = inlineContent(node.record, node.span.attributes[key]);
|
|
@@ -131,13 +129,13 @@ function label(key) {
|
|
|
131
129
|
function DataPanel({ attribute, value }) {
|
|
132
130
|
if (value === undefined)
|
|
133
131
|
return null;
|
|
134
|
-
return (_jsx(
|
|
132
|
+
return (_jsx(PanePanel, { ...label(attribute), children: _jsx(ShapedData, { value: value }) }));
|
|
135
133
|
}
|
|
136
134
|
/** Text under its attribute's name; nothing when there is none. */
|
|
137
135
|
function ProsePanel({ attribute, text }) {
|
|
138
136
|
if (typeof text !== 'string' || !text)
|
|
139
137
|
return null;
|
|
140
|
-
return (_jsx(
|
|
138
|
+
return (_jsx(PanePanel, { ...label(attribute), children: _jsx(Prose, { text: text }) }));
|
|
141
139
|
}
|
|
142
140
|
function TurnIO({ node }) {
|
|
143
141
|
return (_jsxs(_Fragment, { children: [_jsx(ProsePanel, { attribute: "gen_ai.input.messages", text: messageText(node, 'gen_ai.input.messages', 'user') }), _jsx(ProsePanel, { attribute: "gen_ai.output.messages", text: messageText(node, 'gen_ai.output.messages', 'assistant') })] }));
|
|
@@ -145,7 +143,7 @@ function TurnIO({ node }) {
|
|
|
145
143
|
function CallIO({ node }) {
|
|
146
144
|
const input = messagesOf(node, 'gen_ai.input.messages');
|
|
147
145
|
const output = messagesOf(node, 'gen_ai.output.messages');
|
|
148
|
-
return (_jsxs(_Fragment, { children: [output.length > 0 ? (_jsx(
|
|
146
|
+
return (_jsxs(_Fragment, { children: [output.length > 0 ? (_jsx(PanePanel, { ...label('gen_ai.output.messages'), children: _jsx(MessageList, { messages: output }) })) : null, input.length > 0 ? (_jsx(Collapsible, { defaultIsOpen: false, trigger: _jsx(Text, { weight: "medium", children: `${label('gen_ai.input.messages').title} · ${input.length}` }), children: _jsx(Card, { padding: 3, variant: "muted", style: { background: 'var(--color-background-surface)' }, children: _jsx(MessageList, { messages: input }) }) })) : null] }));
|
|
149
147
|
}
|
|
150
148
|
function ToolIO({ node }) {
|
|
151
149
|
const { attributes } = node.span;
|
|
@@ -166,7 +164,7 @@ function SpanIO({ node }) {
|
|
|
166
164
|
return null;
|
|
167
165
|
}
|
|
168
166
|
}
|
|
169
|
-
/** The span's own fields: its type, start and IDs. */
|
|
167
|
+
/** The span's own fields: its type, start, and IDs. */
|
|
170
168
|
function SpanFields({ node }) {
|
|
171
169
|
return (_jsx(MetadataList, { columns: "single", label: { position: 'start', width: TRACE_LABEL_PX }, children: Object.keys(SPAN_FIELD_VALUES).map((key) => (_jsx(MetadataListItem, { label: SPAN_FIELD_META[key].label, children: _jsx(TraceValue, { record: node.record, meta: SPAN_FIELD_META[key], value: SPAN_FIELD_VALUES[key](node) }) }, key))) }));
|
|
172
170
|
}
|
|
@@ -184,5 +182,9 @@ export function TraceSpanDetail({ node, turnStartMs, isClose = false, onBack, on
|
|
|
184
182
|
const { span, record } = node;
|
|
185
183
|
const sections = attributeSections(span.attributes);
|
|
186
184
|
const usage = sections.find((section) => section.key === 'usage');
|
|
187
|
-
return (_jsxs(VStack, { gap: 4, children: [_jsx(SpanHeader, { node: node, turnStartMs: turnStartMs, onBack: onBack, isClose: isClose }), _jsx(SpanIO, { node: node }), usage ? (_jsx(
|
|
185
|
+
return (_jsxs(VStack, { gap: 4, children: [_jsx(SpanHeader, { node: node, turnStartMs: turnStartMs, onBack: onBack, isClose: isClose }), _jsx(SpanIO, { node: node }), usage ? (_jsx(PanePanel, { title: TRACE_ATTRIBUTE_GROUPS.usage.label, doc: TRACE_ATTRIBUTE_GROUPS.usage.doc, children: _jsx(TraceAttributeList, { record: record, attributes: usage.attributes, metaOf: traceAttributeMeta }) })) : null, node.children.length > 0 ? (_jsx(PanePanel, { title: TRACE_FIELDS.children.label, doc: TRACE_FIELDS.children.doc, children: _jsx(VStack, { gap: 0, children: node.children.map((child) => (_jsx(Item, { startContent: _jsx(ActorMark, { actor: traceActor(child) }), label: child.meta.subject ?? child.meta.label, description: child.meta.label, endContent: _jsx(Text, { type: "supporting", hasTabularNumbers: true, children: format.duration(child.durationMs) }), density: "compact", onClick: () => onOpen(child) }, child.id))) }) })) : null, _jsx(Collapsible, { defaultIsOpen: false, trigger: _jsx(Text, { weight: "medium", children: t('@theorem.panel.trace.details') }), children: _jsxs(VStack, { gap: 3, children: [_jsx(SpanFields, { node: node }), sections
|
|
186
|
+
.filter((section) => section !== usage)
|
|
187
|
+
.map((section) => (_jsx(Section, { title: section.key === 'other'
|
|
188
|
+
? t('@theorem.panel.trace.other')
|
|
189
|
+
: TRACE_ATTRIBUTE_GROUPS[section.key].label, children: _jsx(TraceAttributeList, { record: record, attributes: section.attributes, metaOf: traceAttributeMeta }) }, section.key))), span.events.length > 0 ? (_jsx(Section, { title: TRACE_FIELDS.events.label, children: _jsx(EventList, { node: node }) })) : null, span.links.length > 0 ? (_jsx(Section, { title: TRACE_FIELDS.links.label, children: _jsx(LinkList, { node: node }) })) : null, _jsx(RecordSections, { node: node })] }) })] }));
|
|
188
190
|
}
|
package/ui/TraceStory.js
CHANGED
|
@@ -7,7 +7,8 @@ import { Text } from '@astryxdesign/core/Text';
|
|
|
7
7
|
import { Tooltip } from '@astryxdesign/core/Tooltip';
|
|
8
8
|
import { VStack } from '@astryxdesign/core/VStack';
|
|
9
9
|
import { IconAlertTriangle, IconBolt, IconInputAi, IconMessageCircle, IconServer, IconTool, IconUser, } from '@tabler/icons-react';
|
|
10
|
-
import { toolArguments, traceActor, traceOutcome } from "../client/trace-story.js";
|
|
10
|
+
import { toolArguments, traceActor, traceOutcome, } from "../client/trace-story.js";
|
|
11
|
+
import { Arrive, Stream } from "./arrive.js";
|
|
11
12
|
import { useTraceFormat } from "./TraceValues.js";
|
|
12
13
|
/** Each actor's mark, shared by the story and the turn list. */
|
|
13
14
|
const ACTOR_ICON = {
|
|
@@ -78,7 +79,7 @@ function AnswerItem({ step, isSelected, select }) {
|
|
|
78
79
|
const answer = step.text ? _jsx(Quote, { text: step.text }) : undefined;
|
|
79
80
|
return (_jsx(Item, { startContent: _jsx(ActorMark, { actor: failed ? 'error' : 'model', icon: failed ? undefined : IconMessageCircle }), label: _jsx(Text, { weight: "medium", children: t(failed ? '@theorem.panel.trace.story.failed' : '@theorem.panel.trace.story.answered') }), description: failed ? traceOutcome(step.node)?.label : answer, endContent: _jsx(Offset, { ms: step.offsetMs }), align: "start", density: "compact", onClick: select, isSelected: isSelected }));
|
|
80
81
|
}
|
|
81
|
-
function StepBody({ step, isSelected, select }) {
|
|
82
|
+
function StepBody({ step, isSelected, select, }) {
|
|
82
83
|
switch (step.kind) {
|
|
83
84
|
case 'ask':
|
|
84
85
|
return _jsx(AskItem, { step: step, isSelected: isSelected, select: select });
|
|
@@ -91,11 +92,11 @@ function StepBody({ step, isSelected, select }) {
|
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
94
|
function StepItem({ step, isSelected, isDimmed, onSelect, }) {
|
|
94
|
-
return (_jsx("div", { style: {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
return (_jsx(Arrive, { children: _jsx("div", { style: {
|
|
96
|
+
paddingInlineStart: step.kind === 'span' && step.nested ? 20 : 0,
|
|
97
|
+
opacity: isDimmed ? 0.35 : 1,
|
|
98
|
+
transition: 'opacity 120ms ease',
|
|
99
|
+
}, children: _jsx(StepBody, { step: step, isSelected: isSelected, select: () => onSelect(step.node) }) }) }));
|
|
99
100
|
}
|
|
100
101
|
/**
|
|
101
102
|
* The turn, told in order: what the user asked, each model call with the tool
|
|
@@ -103,5 +104,5 @@ function StepItem({ step, isSelected, isDimmed, onSelect, }) {
|
|
|
103
104
|
* A line opens its span.
|
|
104
105
|
*/
|
|
105
106
|
export function TraceStory({ steps, selectedId, matches, onSelect, }) {
|
|
106
|
-
return (_jsx(VStack, { gap: 0, children: steps.map((step) => (_jsx(StepItem, { step: step, isSelected: step.kind === 'span' ? step.node.id === selectedId : false, isDimmed: matches !== undefined && !matches.has(step.node.id), onSelect: onSelect }, step.id))) }));
|
|
107
|
+
return (_jsx(Stream, { children: _jsx(VStack, { gap: 0, children: steps.map((step) => (_jsx(StepItem, { step: step, isSelected: step.kind === 'span' ? step.node.id === selectedId : false, isDimmed: matches !== undefined && !matches.has(step.node.id), onSelect: onSelect }, step.id))) }) }));
|
|
107
108
|
}
|
package/ui/TraceValues.js
CHANGED
|
@@ -7,11 +7,12 @@ import { Text } from '@astryxdesign/core/Text';
|
|
|
7
7
|
import { Timestamp } from '@astryxdesign/core/Timestamp';
|
|
8
8
|
import { Tooltip } from '@astryxdesign/core/Tooltip';
|
|
9
9
|
import { VStack } from '@astryxdesign/core/VStack';
|
|
10
|
-
import { useMemo, useState } from 'react';
|
|
11
10
|
import { inlineContent, TRACE_ATTRIBUTE_GROUPS, traceAttributeMeta, } from '@theoremjs/agents';
|
|
12
|
-
import {
|
|
11
|
+
import { useMemo, useState } from 'react';
|
|
12
|
+
import { nanosToMs, traceValueShape, } from "../client/trace-view.js";
|
|
13
13
|
import { workDuration } from "./labels.js";
|
|
14
14
|
import { useLabels } from "./labels-provider.js";
|
|
15
|
+
import { keyedByContent } from "./row-keys.js";
|
|
15
16
|
/** Width of every label column in the panel's lists, so they line up. */
|
|
16
17
|
export const TRACE_LABEL_PX = 120;
|
|
17
18
|
/** A span's attributes by catalog group, in the catalog's order; keys it does not name last. */
|
|
@@ -21,7 +22,10 @@ export function attributeSections(attributes) {
|
|
|
21
22
|
const group = traceAttributeMeta(key)?.group ?? 'other';
|
|
22
23
|
byGroup.set(group, { ...byGroup.get(group), [key]: value });
|
|
23
24
|
}
|
|
24
|
-
const order = [
|
|
25
|
+
const order = [
|
|
26
|
+
...Object.keys(TRACE_ATTRIBUTE_GROUPS),
|
|
27
|
+
'other',
|
|
28
|
+
];
|
|
25
29
|
return order.flatMap((key) => {
|
|
26
30
|
const grouped = byGroup.get(key);
|
|
27
31
|
return grouped ? [{ key, attributes: grouped }] : [];
|
|
@@ -32,7 +36,11 @@ export function useTraceFormat() {
|
|
|
32
36
|
const locale = useLocale();
|
|
33
37
|
return useMemo(() => {
|
|
34
38
|
const number = new Intl.NumberFormat(locale);
|
|
35
|
-
const usd = new Intl.NumberFormat(locale, {
|
|
39
|
+
const usd = new Intl.NumberFormat(locale, {
|
|
40
|
+
style: 'currency',
|
|
41
|
+
currency: 'USD',
|
|
42
|
+
maximumFractionDigits: 6,
|
|
43
|
+
});
|
|
36
44
|
const list = new Intl.ListFormat(locale, { type: 'conjunction' });
|
|
37
45
|
return {
|
|
38
46
|
t,
|
|
@@ -41,7 +49,9 @@ export function useTraceFormat() {
|
|
|
41
49
|
duration: (ms) => workDuration(t, ms),
|
|
42
50
|
list: (items) => list.format(items),
|
|
43
51
|
sum(total, format) {
|
|
44
|
-
const value = 'estimated' in total && total.estimated
|
|
52
|
+
const value = 'estimated' in total && total.estimated
|
|
53
|
+
? t('@theorem.panel.trace.about', { value: format(total.value) })
|
|
54
|
+
: format(total.value);
|
|
45
55
|
return total.complete ? value : t('@theorem.panel.trace.at_least', { value });
|
|
46
56
|
},
|
|
47
57
|
};
|
|
@@ -75,16 +85,16 @@ function StringValue({ meta, value }) {
|
|
|
75
85
|
if (option)
|
|
76
86
|
return _jsx(OptionValue, { option: option });
|
|
77
87
|
if (meta?.format === 'time')
|
|
78
|
-
return _jsx(Timestamp, { value: nanosToMs(value), format: "system_date_time", size: "base", color: "primary" });
|
|
88
|
+
return (_jsx(Timestamp, { value: nanosToMs(value), format: "system_date_time", size: "base", color: "primary" }));
|
|
79
89
|
return _jsx(Text, { wordBreak: "break-word", children: value });
|
|
80
90
|
}
|
|
81
|
-
function ScalarValue({ meta, value }) {
|
|
91
|
+
function ScalarValue({ meta, value, }) {
|
|
82
92
|
const format = useTraceFormat();
|
|
83
93
|
if (typeof value === 'boolean')
|
|
84
94
|
return _jsx(Text, { children: format.t(value ? '@theorem.panel.trace.yes' : '@theorem.panel.trace.no') });
|
|
85
95
|
return _jsx(Text, { hasTabularNumbers: true, children: formatNumber(format, meta, value) });
|
|
86
96
|
}
|
|
87
|
-
function ListValue({ meta, value }) {
|
|
97
|
+
function ListValue({ meta, value, }) {
|
|
88
98
|
const format = useTraceFormat();
|
|
89
99
|
return _jsx(Text, { children: format.list(value.map((item) => meta?.options?.[item]?.label ?? item)) });
|
|
90
100
|
}
|
|
@@ -99,7 +109,7 @@ export function TraceValue({ record, meta, value, }) {
|
|
|
99
109
|
case 'list':
|
|
100
110
|
return _jsx(ListValue, { meta: meta, value: shape.value });
|
|
101
111
|
case 'fields':
|
|
102
|
-
return (_jsx(VStack, { gap: 2, children: shape.items.map((item,
|
|
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))) }));
|
|
103
113
|
case 'stored':
|
|
104
114
|
return _jsx(StoredText, { record: record, value: value });
|
|
105
115
|
}
|
package/ui/TraceWaterfall.js
CHANGED
|
@@ -7,11 +7,11 @@ import { VStack } from '@astryxdesign/core/VStack';
|
|
|
7
7
|
import { IconZoomOut } from '@tabler/icons-react';
|
|
8
8
|
import { useMemo, useRef, useState } from 'react';
|
|
9
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";
|
|
10
|
+
import { traceActivity, traceActor, traceBars, traceOutcome, } from "../client/trace-story.js";
|
|
11
11
|
import { ChartFrame, ChartTip, FIRST_WIDTH_PX } from "./TraceOverview.js";
|
|
12
|
+
import { useTraceFormat } from "./TraceValues.js";
|
|
12
13
|
import { TRACE_HUE } from "./trace-palette.js";
|
|
13
14
|
import { ACTOR_FILL, TRACE_RADIUS, traceFill } from "./trace-patterns.js";
|
|
14
|
-
import { useTraceFormat } from "./TraceValues.js";
|
|
15
15
|
/** Slices in the activity strip. */
|
|
16
16
|
const BUCKETS = 120;
|
|
17
17
|
/** Height of one span's row, in pixels. */
|
|
@@ -41,7 +41,9 @@ function BarTip({ active, payload }) {
|
|
|
41
41
|
format.duration(node.durationMs),
|
|
42
42
|
format.t('@theorem.panel.trace.offset', { duration: format.duration(from) }),
|
|
43
43
|
...(typeof cost === 'number' ? [format.usd(cost)] : []),
|
|
44
|
-
].join(format.t('@theorem.panel.trace.separator')) }), outcome ? (_jsx(Text, { type: "supporting", children: _jsx("span", { style: {
|
|
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] }) }));
|
|
45
47
|
}
|
|
46
48
|
/** A row's name, from the chart's left edge, set in by its depth and cut to the column. */
|
|
47
49
|
function NameTick({ y: rawY, payload, rows, }) {
|
|
@@ -52,14 +54,16 @@ function NameTick({ y: rawY, payload, rows, }) {
|
|
|
52
54
|
const indent = Math.min(row.bar.depth, 4) * INDENT_PX;
|
|
53
55
|
const room = Math.floor((NAME_PX - indent - 10) / 6.2);
|
|
54
56
|
const name = row.name.length > room ? `${row.name.slice(0, Math.max(1, room - 1))}…` : row.name;
|
|
55
|
-
return (_jsxs("text", { x: indent, y: y, dy: "0.35em", fontSize: 11, fill: row.bar.node.span.status.code === 'ERROR'
|
|
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] }));
|
|
56
60
|
}
|
|
57
61
|
/** How busy the model and tools were over the turn; a drag across it picks the window to zoom into. */
|
|
58
|
-
function ActivityStrip({ root, zoom, onZoom }) {
|
|
62
|
+
function ActivityStrip({ root, zoom, onZoom, }) {
|
|
59
63
|
const activity = useMemo(() => traceActivity(root, BUCKETS), [root]);
|
|
60
64
|
const total = Math.max(root.durationMs, 1);
|
|
61
65
|
const [drag, setDrag] = useState(null);
|
|
62
|
-
// Pointer events can outrun a render; the ref always holds the drag so far.
|
|
66
|
+
// why: Pointer events can outrun a render; the ref always holds the drag so far.
|
|
63
67
|
const dragRef = useRef(null);
|
|
64
68
|
const moveDrag = (next) => {
|
|
65
69
|
dragRef.current = next;
|
|
@@ -76,14 +80,13 @@ function ActivityStrip({ root, zoom, onZoom }) {
|
|
|
76
80
|
if (done) {
|
|
77
81
|
const from = Math.min(done.from, done.to);
|
|
78
82
|
const to = Math.max(done.from, done.to);
|
|
79
|
-
// A click, not a drag: leave the zoom as it was.
|
|
80
83
|
if (to - from >= total / BUCKETS)
|
|
81
84
|
onZoom({ root: root.id, from, to });
|
|
82
85
|
}
|
|
83
86
|
moveDrag(null);
|
|
84
87
|
};
|
|
85
88
|
const shown = drag ?? zoom;
|
|
86
|
-
return (_jsx("div", { style: { cursor: 'col-resize', userSelect: 'none', touchAction: 'none' }, onPointerDown: (event) => {
|
|
89
|
+
return (_jsx("div", { role: "application", style: { cursor: 'col-resize', userSelect: 'none', touchAction: 'none' }, onPointerDown: (event) => {
|
|
87
90
|
event.currentTarget.setPointerCapture(event.pointerId);
|
|
88
91
|
const value = timeAt(event);
|
|
89
92
|
moveDrag({ from: value, to: value });
|
|
@@ -128,5 +131,5 @@ export function TraceWaterfall({ root, selectedId, matches, onSelect, }) {
|
|
|
128
131
|
const { t } = useTraceFormat();
|
|
129
132
|
const [picked, setPicked] = useState(null);
|
|
130
133
|
const zoom = picked?.root === root.id ? picked : null;
|
|
131
|
-
return (_jsxs(VStack, { gap: 2, 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 })] }));
|
|
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 })] }));
|
|
132
135
|
}
|
package/ui/VoiceNote.js
CHANGED
|
@@ -6,10 +6,10 @@ import { IconButton } from '@astryxdesign/core/IconButton';
|
|
|
6
6
|
import { VStack } from '@astryxdesign/core/VStack';
|
|
7
7
|
import { IconX } from '@tabler/icons-react';
|
|
8
8
|
import { voiceFormatFromMime } from "../client/voice-label.js";
|
|
9
|
-
import { voiceNoteName } from "./labels.js";
|
|
10
|
-
import { useLabels } from "./labels-provider.js";
|
|
11
9
|
import { InkWaveform } from "../components/InkWaveform.js";
|
|
12
10
|
import { useVoicePlayback } from "../components/use-voice-playback.js";
|
|
11
|
+
import { voiceNoteName } from "./labels.js";
|
|
12
|
+
import { useLabels } from "./labels-provider.js";
|
|
13
13
|
/** Astryx Thumbnail's height, so voice notes sit level with image attachments. */
|
|
14
14
|
const VOICE_NOTE_HEIGHT = 64;
|
|
15
15
|
const VOICE_NOTE_WIDTH = 160;
|
|
@@ -19,10 +19,10 @@ const VOICE_NOTE_WIDTH = 160;
|
|
|
19
19
|
*/
|
|
20
20
|
export function VoiceNote({ src, mimeType = 'audio/webm', label, onRemove }) {
|
|
21
21
|
const t = useLabels();
|
|
22
|
-
const { playing,
|
|
22
|
+
const { playing, levelsRef, toggle, audioProps } = useVoicePlayback();
|
|
23
23
|
const name = label ?? voiceNoteName(t, voiceFormatFromMime(mimeType));
|
|
24
24
|
const remove = t('@theorem.voice_note.remove', { name });
|
|
25
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
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,
|
|
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
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
|
+
}
|
package/ui/built/theme.css
CHANGED
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
* @generated by `astryx theme build` — do not edit manually.
|
|
3
3
|
* Source: src/ui/theorem-theme.ts
|
|
4
4
|
* Command: astryx theme build src/ui/theorem-theme.ts --out src/ui/built/theme.css
|
|
5
|
-
* CLI: @astryxdesign/cli@0.
|
|
6
|
-
* Core: @astryxdesign/core@0.
|
|
5
|
+
* CLI: @astryxdesign/cli@0.7.0
|
|
6
|
+
* Core: @astryxdesign/core@0.7.0
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
@layer reset, astryx-base, astryx-theme;
|
|
10
|
+
|
|
9
11
|
@layer reset {
|
|
10
12
|
@scope ([data-astryx-theme="theorem"]) to ([data-astryx-theme]) {
|
|
11
13
|
:where(h1, h2, h3, h4, h5, h6) {
|
|
@@ -77,67 +79,6 @@
|
|
|
77
79
|
}
|
|
78
80
|
}
|
|
79
81
|
|
|
80
|
-
@layer astryx-base {
|
|
81
|
-
:root {
|
|
82
|
-
--color-data-categorical-blue: light-dark(#0171E3, #0171E3);
|
|
83
|
-
--color-data-categorical-orange: light-dark(#EB6E00, #EB6E00);
|
|
84
|
-
--color-data-categorical-purple: light-dark(#6B1EFD, #6B1EFD);
|
|
85
|
-
--color-data-categorical-green: light-dark(#0B991F, #0B991F);
|
|
86
|
-
--color-data-categorical-pink: light-dark(#F351C0, #F351C0);
|
|
87
|
-
--color-data-categorical-cyan: light-dark(#0171A4, #0171A4);
|
|
88
|
-
--color-data-categorical-red: light-dark(#F5394F, #F5394F);
|
|
89
|
-
--color-data-categorical-teal: light-dark(#08A3A3, #08A3A3);
|
|
90
|
-
--color-data-categorical-brown: light-dark(#965E03, #965E03);
|
|
91
|
-
--color-data-categorical-indigo: light-dark(#6F8AFF, #6F8AFF);
|
|
92
|
-
--color-data-neutral: light-dark(#8494A3, #8C939B);
|
|
93
|
-
--color-data-blue-5: light-dark(#02165E, #02165E);
|
|
94
|
-
--color-data-blue-4: light-dark(#004CBC, #004CBC);
|
|
95
|
-
--color-data-blue-3: light-dark(#2694FE, #2694FE);
|
|
96
|
-
--color-data-blue-2: light-dark(#78BEFF, #78BEFF);
|
|
97
|
-
--color-data-blue-1: light-dark(#DBECFF, #DBECFF);
|
|
98
|
-
--color-data-shamrock-5: light-dark(#0B603D, #0B603D);
|
|
99
|
-
--color-data-shamrock-4: light-dark(#138546, #138546);
|
|
100
|
-
--color-data-shamrock-3: light-dark(#24BB5E, #24BB5E);
|
|
101
|
-
--color-data-shamrock-2: light-dark(#8EF7AA, #8EF7AA);
|
|
102
|
-
--color-data-shamrock-1: light-dark(#D6FEE4, #D6FEE4);
|
|
103
|
-
--color-data-orange-5: light-dark(#A13F04, #A13F04);
|
|
104
|
-
--color-data-orange-4: light-dark(#D66100, #D66100);
|
|
105
|
-
--color-data-orange-3: light-dark(#FD9537, #FD9537);
|
|
106
|
-
--color-data-orange-2: light-dark(#FDB876, #FDB876);
|
|
107
|
-
--color-data-orange-1: light-dark(#FFE6CF, #FFE6CF);
|
|
108
|
-
--color-data-pink-5: light-dark(#8E1073, #8E1073);
|
|
109
|
-
--color-data-pink-4: light-dark(#D123A1, #D123A1);
|
|
110
|
-
--color-data-pink-3: light-dark(#F989D3, #F989D3);
|
|
111
|
-
--color-data-pink-2: light-dark(#FEADE3, #FEADE3);
|
|
112
|
-
--color-data-pink-1: light-dark(#FCE3F4, #FCE3F4);
|
|
113
|
-
--color-data-purple-5: light-dark(#3E0697, #3E0697);
|
|
114
|
-
--color-data-purple-4: light-dark(#6B1EFD, #6B1EFD);
|
|
115
|
-
--color-data-purple-3: light-dark(#9081FF, #9081FF);
|
|
116
|
-
--color-data-purple-2: light-dark(#B3B0FE, #B3B0FE);
|
|
117
|
-
--color-data-purple-1: light-dark(#E8E8FB, #E8E8FB);
|
|
118
|
-
--color-data-red-5: light-dark(#9D0519, #9D0519);
|
|
119
|
-
--color-data-red-4: light-dark(#D31130, #D31130);
|
|
120
|
-
--color-data-red-3: light-dark(#FB7D87, #FB7D87);
|
|
121
|
-
--color-data-red-2: light-dark(#FFB2B8, #FFB2B8);
|
|
122
|
-
--color-data-red-1: light-dark(#FEE4E6, #FEE4E6);
|
|
123
|
-
--color-data-teal-5: light-dark(#08767D, #08767D);
|
|
124
|
-
--color-data-teal-4: light-dark(#0C9293, #0C9293);
|
|
125
|
-
--color-data-teal-3: light-dark(#0DB7AF, #0DB7AF);
|
|
126
|
-
--color-data-teal-2: light-dark(#6CE6D8, #6CE6D8);
|
|
127
|
-
--color-data-teal-1: light-dark(#D7FCF8, #D7FCF8);
|
|
128
|
-
--color-data-yellow-5: light-dark(#8A5001, #8A5001);
|
|
129
|
-
--color-data-yellow-4: light-dark(#D69804, #D69804);
|
|
130
|
-
--color-data-yellow-3: light-dark(#FBCE03, #FBCE03);
|
|
131
|
-
--color-data-yellow-2: light-dark(#FCEC85, #FCEC85);
|
|
132
|
-
--color-data-yellow-1: light-dark(#FDF6BA, #FDF6BA);
|
|
133
|
-
--color-data-gray-5: light-dark(#25363F, #333338);
|
|
134
|
-
--color-data-gray-4: light-dark(#5D6C7B, #666A72);
|
|
135
|
-
--color-data-gray-3: light-dark(#AFB9C4, #B2B8BE);
|
|
136
|
-
--color-data-gray-2: light-dark(#CCD3DB, #D0D3D6);
|
|
137
|
-
--color-data-gray-1: light-dark(#F1F4F7, #F2F4F6);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
82
|
@layer astryx-theme {
|
|
142
83
|
:root { color-scheme: light dark; }
|
|
143
84
|
html[data-theme="light"] { color-scheme: light; }
|
|
@@ -641,6 +582,15 @@
|
|
|
641
582
|
--astryx-card-padding: var(--spacing-3);
|
|
642
583
|
}
|
|
643
584
|
|
|
585
|
+
.astryx-card[data-variant="bubble"] {
|
|
586
|
+
background-color: var(--color-neutral);
|
|
587
|
+
border-radius: var(--radius-chat);
|
|
588
|
+
--astryx-card-padding-inline: var(--spacing-4);
|
|
589
|
+
--astryx-card-padding-block-start: var(--spacing-3);
|
|
590
|
+
--astryx-card-padding-block-end: var(--spacing-3);
|
|
591
|
+
--_card-radius: var(--radius-chat);
|
|
592
|
+
}
|
|
593
|
+
|
|
644
594
|
.astryx-section {
|
|
645
595
|
--astryx-section-padding: var(--spacing-3);
|
|
646
596
|
}
|
|
@@ -681,11 +631,15 @@
|
|
|
681
631
|
align-self: baseline;
|
|
682
632
|
}
|
|
683
633
|
|
|
634
|
+
.astryx-code-block[data-container="card"] {
|
|
635
|
+
border-radius: var(--radius-container);
|
|
636
|
+
}
|
|
637
|
+
|
|
684
638
|
.astryx-layout-panel:where([role="complementary"]) {
|
|
685
639
|
transition: width var(--duration-medium) var(--ease-standard);
|
|
686
640
|
}
|
|
687
641
|
|
|
688
|
-
.astryx-layout-panel:where([data-resizing] + [role="complementary"]) {
|
|
642
|
+
.astryx-layout-panel:where([data-resizing] + [role="complementary"], [role="complementary"]:has(+ [data-resizing])) {
|
|
689
643
|
transition: none;
|
|
690
644
|
}
|
|
691
645
|
|
|
@@ -742,15 +696,79 @@
|
|
|
742
696
|
}
|
|
743
697
|
|
|
744
698
|
@layer astryx-theme {
|
|
699
|
+
@media (width < 1024px) and (pointer: coarse) {
|
|
700
|
+
@scope ([data-astryx-theme="theorem"]) to ([data-astryx-theme]) {
|
|
701
|
+
:scope {
|
|
702
|
+
--font-size-4xs: 0.4375rem;
|
|
703
|
+
--font-size-3xs: 0.5rem;
|
|
704
|
+
--font-size-2xs: 0.625rem;
|
|
705
|
+
--font-size-xs: 0.75rem;
|
|
706
|
+
--font-size-sm: 0.875rem;
|
|
707
|
+
--font-size-base: 1rem;
|
|
708
|
+
--font-size-lg: 1.1875rem;
|
|
709
|
+
--font-size-xl: 1.375rem;
|
|
710
|
+
--font-size-2xl: 1.625rem;
|
|
711
|
+
--font-size-3xl: 1.875rem;
|
|
712
|
+
--font-size-4xl: 2.25rem;
|
|
713
|
+
--font-size-5xl: 2.625rem;
|
|
714
|
+
--text-heading-1-size: var(--font-size-2xl);
|
|
715
|
+
--text-heading-1-weight: var(--font-weight-semibold);
|
|
716
|
+
--text-heading-1-leading: 1.3846;
|
|
717
|
+
--text-heading-2-size: var(--font-size-xl);
|
|
718
|
+
--text-heading-2-weight: var(--font-weight-semibold);
|
|
719
|
+
--text-heading-2-leading: 1.4545;
|
|
720
|
+
--text-heading-3-size: var(--font-size-lg);
|
|
721
|
+
--text-heading-3-weight: var(--font-weight-bold);
|
|
722
|
+
--text-heading-3-leading: 1.4737;
|
|
723
|
+
--text-heading-4-size: var(--font-size-base);
|
|
724
|
+
--text-heading-4-weight: var(--font-weight-bold);
|
|
725
|
+
--text-heading-4-leading: 1.5;
|
|
726
|
+
--text-heading-5-size: var(--font-size-sm);
|
|
727
|
+
--text-heading-5-weight: var(--font-weight-semibold);
|
|
728
|
+
--text-heading-5-leading: 1.4286;
|
|
729
|
+
--text-heading-6-size: var(--font-size-xs);
|
|
730
|
+
--text-heading-6-weight: var(--font-weight-semibold);
|
|
731
|
+
--text-heading-6-leading: 1.6667;
|
|
732
|
+
--text-body-size: var(--font-size-base);
|
|
733
|
+
--text-body-weight: var(--font-weight-normal);
|
|
734
|
+
--text-body-leading: 1.5;
|
|
735
|
+
--text-large-size: var(--font-size-lg);
|
|
736
|
+
--text-large-weight: var(--font-weight-semibold);
|
|
737
|
+
--text-large-leading: 1.4737;
|
|
738
|
+
--text-label-size: var(--font-size-base);
|
|
739
|
+
--text-label-weight: var(--font-weight-medium);
|
|
740
|
+
--text-label-leading: 1.5;
|
|
741
|
+
--text-code-size: var(--font-size-base);
|
|
742
|
+
--text-code-weight: var(--font-weight-normal);
|
|
743
|
+
--text-code-leading: 1.5;
|
|
744
|
+
--text-supporting-size: var(--font-size-sm);
|
|
745
|
+
--text-supporting-weight: var(--font-weight-normal);
|
|
746
|
+
--text-supporting-leading: 1.4286;
|
|
747
|
+
--text-display-1-size: var(--font-size-5xl);
|
|
748
|
+
--text-display-1-weight: var(--font-weight-normal);
|
|
749
|
+
--text-display-1-leading: 1.2381;
|
|
750
|
+
--text-display-2-size: var(--font-size-4xl);
|
|
751
|
+
--text-display-2-weight: var(--font-weight-normal);
|
|
752
|
+
--text-display-2-leading: 1.2222;
|
|
753
|
+
--text-display-3-size: var(--font-size-3xl);
|
|
754
|
+
--text-display-3-weight: var(--font-weight-normal);
|
|
755
|
+
--text-display-3-leading: 1.4667;
|
|
756
|
+
--font-family-body: Figtree, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
757
|
+
--font-family-heading: Figtree, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
758
|
+
--font-family-code: ui-monospace, "SF Mono", Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
745
763
|
@media (prefers-reduced-motion: reduce) {
|
|
746
764
|
@scope ([data-astryx-theme="theorem"]) to ([data-astryx-theme]) {
|
|
747
765
|
.astryx-collapsible-content {
|
|
748
|
-
|
|
749
|
-
|
|
766
|
+
transition: none;
|
|
767
|
+
}
|
|
750
768
|
|
|
751
769
|
.astryx-layout-panel:where([role="complementary"]) {
|
|
752
|
-
|
|
753
|
-
|
|
770
|
+
transition: none;
|
|
771
|
+
}
|
|
754
772
|
}
|
|
755
773
|
}
|
|
756
774
|
}
|