@dungle-scrubs/admin-ui-soft 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/GUIDE.md +110 -0
- package/LICENSE +21 -0
- package/README.md +36 -2
- package/THIRD-PARTY-NOTICES.md +25 -0
- package/UPSTREAM-VENDORED-CHANGES.md +317 -0
- package/VENDORED-CHANGES.md +60 -0
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/ai/compositions/agent-console/agent-console.d.ts +109 -0
- package/dist/ai/compositions/agent-console/agent-console.js +644 -0
- package/dist/ai/compositions/attention-feed/attention-feed.d.ts +127 -0
- package/dist/ai/compositions/attention-feed/attention-feed.js +626 -0
- package/dist/ai/compositions/conversation-browser/conversation-browser.d.ts +126 -0
- package/dist/ai/compositions/conversation-browser/conversation-browser.js +364 -0
- package/dist/ai/compositions/redaction-marker/redaction-marker.d.ts +42 -0
- package/dist/ai/compositions/redaction-marker/redaction-marker.js +202 -0
- package/dist/ai/compositions/run-inspector/json-view.js +164 -0
- package/dist/ai/compositions/run-inspector/run-inspector.d.ts +66 -0
- package/dist/ai/compositions/run-inspector/run-inspector.js +703 -0
- package/dist/ai/compositions/run-inspector/run-model.js +155 -0
- package/dist/ai/compositions/tool-approval/json-args.js +54 -0
- package/dist/ai/compositions/tool-approval/tool-approval.d.ts +57 -0
- package/dist/ai/compositions/tool-approval/tool-approval.js +331 -0
- package/dist/ai/compositions/tool-call-row/tool-call-row.js +74 -0
- package/dist/ai/compositions/transcript-viewer/to-thread-messages.js +65 -0
- package/dist/ai/compositions/transcript-viewer/transcript-viewer.d.ts +63 -0
- package/dist/ai/compositions/transcript-viewer/transcript-viewer.js +471 -0
- package/dist/ai/compositions/usage-meter/usage-format.js +107 -0
- package/dist/ai/compositions/usage-meter/usage-meter.d.ts +32 -0
- package/dist/ai/compositions/usage-meter/usage-meter.js +258 -0
- package/dist/ai/testing/mock-clock.d.ts +31 -0
- package/dist/ai/testing/mock-clock.js +66 -0
- package/dist/ai/testing/mock-reply.d.ts +70 -0
- package/dist/ai/testing/mock-reply.js +100 -0
- package/dist/ai/testing/mock-runtime.d.ts +86 -0
- package/dist/ai/testing/mock-runtime.js +384 -0
- package/dist/ai/types.d.ts +323 -0
- package/dist/ai.css +1088 -0
- package/dist/ai.d.ts +160 -0
- package/dist/ai.js +158 -0
- package/dist/components/assistant-ui/elements/activity-graph.d.ts +14 -0
- package/dist/components/assistant-ui/elements/activity-graph.js +69 -0
- package/dist/components/assistant-ui/elements/agent-card.d.ts +21 -0
- package/dist/components/assistant-ui/elements/agent-card.js +75 -0
- package/dist/components/assistant-ui/elements/agent-handoff.d.ts +13 -0
- package/dist/components/assistant-ui/elements/agent-handoff.js +47 -0
- package/dist/components/assistant-ui/elements/agent-plan.d.ts +16 -0
- package/dist/components/assistant-ui/elements/agent-plan.js +93 -0
- package/dist/components/assistant-ui/elements/agent-status.aui.d.ts +24 -0
- package/dist/components/assistant-ui/elements/agent-status.aui.js +161 -0
- package/dist/components/assistant-ui/elements/agent-status.d.ts +17 -0
- package/dist/components/assistant-ui/elements/agent-status.js +47 -0
- package/dist/components/assistant-ui/elements/approval-card.d.ts +31 -0
- package/dist/components/assistant-ui/elements/approval-card.js +99 -0
- package/dist/components/assistant-ui/elements/artifact-card.d.ts +12 -0
- package/dist/components/assistant-ui/elements/artifact-card.js +47 -0
- package/dist/components/assistant-ui/elements/assistant-modal.aui.d.ts +7 -0
- package/dist/components/assistant-ui/elements/assistant-modal.aui.js +276 -0
- package/dist/components/assistant-ui/elements/assistant-sidebar.aui.d.ts +7 -0
- package/dist/components/assistant-ui/elements/assistant-sidebar.aui.js +18 -0
- package/dist/components/assistant-ui/elements/attachment.aui.d.ts +9 -0
- package/dist/components/assistant-ui/elements/attachment.aui.js +143 -0
- package/dist/components/assistant-ui/elements/background-inbox.d.ts +18 -0
- package/dist/components/assistant-ui/elements/background-inbox.js +65 -0
- package/dist/components/assistant-ui/elements/canvas-split.d.ts +25 -0
- package/dist/components/assistant-ui/elements/canvas-split.js +106 -0
- package/dist/components/assistant-ui/elements/chart.d.ts +19 -0
- package/dist/components/assistant-ui/elements/chart.js +105 -0
- package/dist/components/assistant-ui/elements/chat-panel.d.ts +15 -0
- package/dist/components/assistant-ui/elements/chat-panel.js +82 -0
- package/dist/components/assistant-ui/elements/checkpoint-history.d.ts +17 -0
- package/dist/components/assistant-ui/elements/checkpoint-history.js +60 -0
- package/dist/components/assistant-ui/elements/code-diff.d.ts +18 -0
- package/dist/components/assistant-ui/elements/code-diff.js +89 -0
- package/dist/components/assistant-ui/elements/code-runner.d.ts +15 -0
- package/dist/components/assistant-ui/elements/code-runner.js +108 -0
- package/dist/components/assistant-ui/elements/command-palette.d.ts +20 -0
- package/dist/components/assistant-ui/elements/command-palette.js +129 -0
- package/dist/components/assistant-ui/elements/comparison-card.d.ts +18 -0
- package/dist/components/assistant-ui/elements/comparison-card.js +58 -0
- package/dist/components/assistant-ui/elements/composer-trigger-popover.aui.d.ts +51 -0
- package/dist/components/assistant-ui/elements/composer-trigger-popover.aui.js +104 -0
- package/dist/components/assistant-ui/elements/composer.d.ts +91 -0
- package/dist/components/assistant-ui/elements/composer.js +416 -0
- package/dist/components/assistant-ui/elements/computer-use.d.ts +19 -0
- package/dist/components/assistant-ui/elements/computer-use.js +84 -0
- package/dist/components/assistant-ui/elements/confidence-marker.d.ts +20 -0
- package/dist/components/assistant-ui/elements/confidence-marker.js +58 -0
- package/dist/components/assistant-ui/elements/connection-state.d.ts +13 -0
- package/dist/components/assistant-ui/elements/connection-state.js +59 -0
- package/dist/components/assistant-ui/elements/context-breakdown.d.ts +15 -0
- package/dist/components/assistant-ui/elements/context-breakdown.js +91 -0
- package/dist/components/assistant-ui/elements/context-display.aui.d.ts +25 -0
- package/dist/components/assistant-ui/elements/context-display.aui.js +26 -0
- package/dist/components/assistant-ui/elements/context-display.d.ts +43 -0
- package/dist/components/assistant-ui/elements/context-display.js +300 -0
- package/dist/components/assistant-ui/elements/conversation-map.aui.d.ts +9 -0
- package/dist/components/assistant-ui/elements/conversation-map.aui.js +177 -0
- package/dist/components/assistant-ui/elements/conversation-map.d.ts +19 -0
- package/dist/components/assistant-ui/elements/conversation-map.js +84 -0
- package/dist/components/assistant-ui/elements/conversation-search.d.ts +20 -0
- package/dist/components/assistant-ui/elements/conversation-search.js +75 -0
- package/dist/components/assistant-ui/elements/cost-meter.d.ts +19 -0
- package/dist/components/assistant-ui/elements/cost-meter.js +76 -0
- package/dist/components/assistant-ui/elements/data-table.d.ts +72 -0
- package/dist/components/assistant-ui/elements/data-table.js +368 -0
- package/dist/components/assistant-ui/elements/day-separator.d.ts +16 -0
- package/dist/components/assistant-ui/elements/day-separator.js +44 -0
- package/dist/components/assistant-ui/elements/diagram.d.ts +15 -0
- package/dist/components/assistant-ui/elements/diagram.js +65 -0
- package/dist/components/assistant-ui/elements/directive-text.aui.d.ts +11 -0
- package/dist/components/assistant-ui/elements/directive-text.aui.js +18 -0
- package/dist/components/assistant-ui/elements/directive-text.d.ts +32 -0
- package/dist/components/assistant-ui/elements/directive-text.js +35 -0
- package/dist/components/assistant-ui/elements/document-reference.d.ts +17 -0
- package/dist/components/assistant-ui/elements/document-reference.js +62 -0
- package/dist/components/assistant-ui/elements/draft-restore.d.ts +12 -0
- package/dist/components/assistant-ui/elements/draft-restore.js +43 -0
- package/dist/components/assistant-ui/elements/edit-message.d.ts +15 -0
- package/dist/components/assistant-ui/elements/edit-message.js +63 -0
- package/dist/components/assistant-ui/elements/elicitation-form.d.ts +23 -0
- package/dist/components/assistant-ui/elements/elicitation-form.js +112 -0
- package/dist/components/assistant-ui/elements/empty-state.d.ts +16 -0
- package/dist/components/assistant-ui/elements/empty-state.js +71 -0
- package/dist/components/assistant-ui/elements/error-state.d.ts +13 -0
- package/dist/components/assistant-ui/elements/error-state.js +52 -0
- package/dist/components/assistant-ui/elements/feedback-dialog.d.ts +15 -0
- package/dist/components/assistant-ui/elements/feedback-dialog.js +77 -0
- package/dist/components/assistant-ui/elements/file-tree.d.ts +20 -0
- package/dist/components/assistant-ui/elements/file-tree.js +74 -0
- package/dist/components/assistant-ui/elements/file.d.ts +52 -0
- package/dist/components/assistant-ui/elements/file.js +222 -0
- package/dist/components/assistant-ui/elements/flow-graph.d.ts +23 -0
- package/dist/components/assistant-ui/elements/flow-graph.js +72 -0
- package/dist/components/assistant-ui/elements/follow-up-suggestions.aui.d.ts +7 -0
- package/dist/components/assistant-ui/elements/follow-up-suggestions.aui.js +30 -0
- package/dist/components/assistant-ui/elements/generative-ui.d.ts +8 -0
- package/dist/components/assistant-ui/elements/generative-ui.js +27 -0
- package/dist/components/assistant-ui/elements/geo-map.d.ts +29 -0
- package/dist/components/assistant-ui/elements/geo-map.js +190 -0
- package/dist/components/assistant-ui/elements/guardrail-notice.d.ts +15 -0
- package/dist/components/assistant-ui/elements/guardrail-notice.js +59 -0
- package/dist/components/assistant-ui/elements/heat-graph.d.ts +9 -0
- package/dist/components/assistant-ui/elements/heat-graph.js +90 -0
- package/dist/components/assistant-ui/elements/image-gallery.d.ts +22 -0
- package/dist/components/assistant-ui/elements/image-gallery.js +192 -0
- package/dist/components/assistant-ui/elements/image-generation.d.ts +11 -0
- package/dist/components/assistant-ui/elements/image-generation.js +64 -0
- package/dist/components/assistant-ui/elements/image.d.ts +59 -0
- package/dist/components/assistant-ui/elements/image.js +416 -0
- package/dist/components/assistant-ui/elements/inline-citation.d.ts +23 -0
- package/dist/components/assistant-ui/elements/inline-citation.js +90 -0
- package/dist/components/assistant-ui/elements/job-progress.d.ts +25 -0
- package/dist/components/assistant-ui/elements/job-progress.js +102 -0
- package/dist/components/assistant-ui/elements/launcher-bubble.d.ts +15 -0
- package/dist/components/assistant-ui/elements/launcher-bubble.js +71 -0
- package/dist/components/assistant-ui/elements/link-preview.d.ts +17 -0
- package/dist/components/assistant-ui/elements/link-preview.js +77 -0
- package/dist/components/assistant-ui/elements/loading-state.d.ts +13 -0
- package/dist/components/assistant-ui/elements/loading-state.js +33 -0
- package/dist/components/assistant-ui/elements/logos.d.ts +10 -0
- package/dist/components/assistant-ui/elements/logos.js +63 -0
- package/dist/components/assistant-ui/elements/map-answer.d.ts +19 -0
- package/dist/components/assistant-ui/elements/map-answer.js +120 -0
- package/dist/components/assistant-ui/elements/markdown-text.d.ts +11 -0
- package/dist/components/assistant-ui/elements/markdown-text.js +152 -0
- package/dist/components/assistant-ui/elements/math-block.d.ts +25 -0
- package/dist/components/assistant-ui/elements/math-block.js +60 -0
- package/dist/components/assistant-ui/elements/mcp-config.aui.d.ts +28 -0
- package/dist/components/assistant-ui/elements/mcp-config.aui.js +380 -0
- package/dist/components/assistant-ui/elements/mcp-server-panel.d.ts +20 -0
- package/dist/components/assistant-ui/elements/mcp-server-panel.js +114 -0
- package/dist/components/assistant-ui/elements/media-player.d.ts +21 -0
- package/dist/components/assistant-ui/elements/media-player.js +302 -0
- package/dist/components/assistant-ui/elements/memory-chips.d.ts +16 -0
- package/dist/components/assistant-ui/elements/memory-chips.js +44 -0
- package/dist/components/assistant-ui/elements/mermaid-diagram.aui.d.ts +14 -0
- package/dist/components/assistant-ui/elements/mermaid-diagram.aui.js +43 -0
- package/dist/components/assistant-ui/elements/mermaid-diagram.d.ts +20 -0
- package/dist/components/assistant-ui/elements/mermaid-diagram.js +258 -0
- package/dist/components/assistant-ui/elements/message-actions.d.ts +17 -0
- package/dist/components/assistant-ui/elements/message-actions.js +57 -0
- package/dist/components/assistant-ui/elements/message-attachment.d.ts +18 -0
- package/dist/components/assistant-ui/elements/message-attachment.js +58 -0
- package/dist/components/assistant-ui/elements/message-branches.d.ts +12 -0
- package/dist/components/assistant-ui/elements/message-branches.js +55 -0
- package/dist/components/assistant-ui/elements/message-pair.d.ts +16 -0
- package/dist/components/assistant-ui/elements/message-pair.js +63 -0
- package/dist/components/assistant-ui/elements/message-queue.d.ts +15 -0
- package/dist/components/assistant-ui/elements/message-queue.js +70 -0
- package/dist/components/assistant-ui/elements/message-timing.aui.d.ts +30 -0
- package/dist/components/assistant-ui/elements/message-timing.aui.js +98 -0
- package/dist/components/assistant-ui/elements/message-timing.d.ts +14 -0
- package/dist/components/assistant-ui/elements/message-timing.js +26 -0
- package/dist/components/assistant-ui/elements/mobile-composer.d.ts +18 -0
- package/dist/components/assistant-ui/elements/mobile-composer.js +76 -0
- package/dist/components/assistant-ui/elements/model-picker.d.ts +19 -0
- package/dist/components/assistant-ui/elements/model-picker.js +68 -0
- package/dist/components/assistant-ui/elements/model-selector.aui.d.ts +23 -0
- package/dist/components/assistant-ui/elements/model-selector.aui.js +79 -0
- package/dist/components/assistant-ui/elements/model-selector.d.ts +130 -0
- package/dist/components/assistant-ui/elements/model-selector.js +399 -0
- package/dist/components/assistant-ui/elements/number-ticker.d.ts +10 -0
- package/dist/components/assistant-ui/elements/number-ticker.js +41 -0
- package/dist/components/assistant-ui/elements/onboarding.d.ts +17 -0
- package/dist/components/assistant-ui/elements/onboarding.js +69 -0
- package/dist/components/assistant-ui/elements/option-list.d.ts +39 -0
- package/dist/components/assistant-ui/elements/option-list.js +176 -0
- package/dist/components/assistant-ui/elements/permission-grant.d.ts +14 -0
- package/dist/components/assistant-ui/elements/permission-grant.js +84 -0
- package/dist/components/assistant-ui/elements/prompt-library.d.ts +20 -0
- package/dist/components/assistant-ui/elements/prompt-library.js +121 -0
- package/dist/components/assistant-ui/elements/question-flow.d.ts +24 -0
- package/dist/components/assistant-ui/elements/question-flow.js +180 -0
- package/dist/components/assistant-ui/elements/quota-banner.d.ts +14 -0
- package/dist/components/assistant-ui/elements/quota-banner.js +68 -0
- package/dist/components/assistant-ui/elements/quote-reply.d.ts +20 -0
- package/dist/components/assistant-ui/elements/quote-reply.js +66 -0
- package/dist/components/assistant-ui/elements/quote.aui.d.ts +61 -0
- package/dist/components/assistant-ui/elements/quote.aui.js +170 -0
- package/dist/components/assistant-ui/elements/read-aloud.d.ts +16 -0
- package/dist/components/assistant-ui/elements/read-aloud.js +66 -0
- package/dist/components/assistant-ui/elements/reasoning-effort.d.ts +17 -0
- package/dist/components/assistant-ui/elements/reasoning-effort.js +67 -0
- package/dist/components/assistant-ui/elements/reasoning-panel.d.ts +20 -0
- package/dist/components/assistant-ui/elements/reasoning-panel.js +60 -0
- package/dist/components/assistant-ui/elements/reasoning.aui.d.ts +24 -0
- package/dist/components/assistant-ui/elements/reasoning.aui.js +70 -0
- package/dist/components/assistant-ui/elements/reasoning.d.ts +38 -0
- package/dist/components/assistant-ui/elements/reasoning.js +194 -0
- package/dist/components/assistant-ui/elements/recommendation-card.d.ts +16 -0
- package/dist/components/assistant-ui/elements/recommendation-card.js +65 -0
- package/dist/components/assistant-ui/elements/regenerate-menu.d.ts +18 -0
- package/dist/components/assistant-ui/elements/regenerate-menu.js +46 -0
- package/dist/components/assistant-ui/elements/research-report.d.ts +19 -0
- package/dist/components/assistant-ui/elements/research-report.js +63 -0
- package/dist/components/assistant-ui/elements/retrieval-chunks.d.ts +19 -0
- package/dist/components/assistant-ui/elements/retrieval-chunks.js +86 -0
- package/dist/components/assistant-ui/elements/reviewable-diff.d.ts +21 -0
- package/dist/components/assistant-ui/elements/reviewable-diff.js +104 -0
- package/dist/components/assistant-ui/elements/schedule-card.d.ts +19 -0
- package/dist/components/assistant-ui/elements/schedule-card.js +80 -0
- package/dist/components/assistant-ui/elements/score-breakdown.d.ts +19 -0
- package/dist/components/assistant-ui/elements/score-breakdown.js +107 -0
- package/dist/components/assistant-ui/elements/scroll-anchor.d.ts +15 -0
- package/dist/components/assistant-ui/elements/scroll-anchor.js +104 -0
- package/dist/components/assistant-ui/elements/settings-panel.d.ts +23 -0
- package/dist/components/assistant-ui/elements/settings-panel.js +108 -0
- package/dist/components/assistant-ui/elements/shared-conversation.d.ts +18 -0
- package/dist/components/assistant-ui/elements/shared-conversation.js +56 -0
- package/dist/components/assistant-ui/elements/shiki-highlighter.aui.d.ts +29 -0
- package/dist/components/assistant-ui/elements/shiki-highlighter.aui.js +31 -0
- package/dist/components/assistant-ui/elements/shiki-highlighter.d.ts +26 -0
- package/dist/components/assistant-ui/elements/shiki-highlighter.js +49 -0
- package/dist/components/assistant-ui/elements/sources.aui.d.ts +24 -0
- package/dist/components/assistant-ui/elements/sources.aui.js +121 -0
- package/dist/components/assistant-ui/elements/sources.d.ts +21 -0
- package/dist/components/assistant-ui/elements/sources.js +109 -0
- package/dist/components/assistant-ui/elements/speaker-identity.d.ts +17 -0
- package/dist/components/assistant-ui/elements/speaker-identity.js +45 -0
- package/dist/components/assistant-ui/elements/spec-sheet.d.ts +17 -0
- package/dist/components/assistant-ui/elements/spec-sheet.js +39 -0
- package/dist/components/assistant-ui/elements/stopped-run.d.ts +12 -0
- package/dist/components/assistant-ui/elements/stopped-run.js +44 -0
- package/dist/components/assistant-ui/elements/streaming-text.d.ts +15 -0
- package/dist/components/assistant-ui/elements/streaming-text.js +45 -0
- package/dist/components/assistant-ui/elements/subagent-list.d.ts +17 -0
- package/dist/components/assistant-ui/elements/subagent-list.js +74 -0
- package/dist/components/assistant-ui/elements/suggestions.d.ts +14 -0
- package/dist/components/assistant-ui/elements/suggestions.js +25 -0
- package/dist/components/assistant-ui/elements/surfaces.d.ts +42 -0
- package/dist/components/assistant-ui/elements/surfaces.js +87 -0
- package/dist/components/assistant-ui/elements/syntax-highlighter.d.ts +7 -0
- package/dist/components/assistant-ui/elements/syntax-highlighter.js +41 -0
- package/dist/components/assistant-ui/elements/task-card.aui.d.ts +24 -0
- package/dist/components/assistant-ui/elements/task-card.aui.js +136 -0
- package/dist/components/assistant-ui/elements/task-card.d.ts +22 -0
- package/dist/components/assistant-ui/elements/task-card.js +104 -0
- package/dist/components/assistant-ui/elements/terminal-block.d.ts +27 -0
- package/dist/components/assistant-ui/elements/terminal-block.js +266 -0
- package/dist/components/assistant-ui/elements/thinking-indicator.d.ts +10 -0
- package/dist/components/assistant-ui/elements/thinking-indicator.js +30 -0
- package/dist/components/assistant-ui/elements/thread-list.aui.d.ts +39 -0
- package/dist/components/assistant-ui/elements/thread-list.aui.js +331 -0
- package/dist/components/assistant-ui/elements/thread-list.d.ts +19 -0
- package/dist/components/assistant-ui/elements/thread-list.js +72 -0
- package/dist/components/assistant-ui/elements/thread-search.d.ts +20 -0
- package/dist/components/assistant-ui/elements/thread-search.js +94 -0
- package/dist/components/assistant-ui/elements/thread.aui.d.ts +36 -0
- package/dist/components/assistant-ui/elements/thread.aui.js +625 -0
- package/dist/components/assistant-ui/elements/threadlist-sidebar.aui.d.ts +19 -0
- package/dist/components/assistant-ui/elements/threadlist-sidebar.aui.js +75 -0
- package/dist/components/assistant-ui/elements/timeline.d.ts +18 -0
- package/dist/components/assistant-ui/elements/timeline.js +40 -0
- package/dist/components/assistant-ui/elements/todo-list.d.ts +21 -0
- package/dist/components/assistant-ui/elements/todo-list.js +100 -0
- package/dist/components/assistant-ui/elements/tool-call.d.ts +17 -0
- package/dist/components/assistant-ui/elements/tool-call.js +70 -0
- package/dist/components/assistant-ui/elements/tool-error.d.ts +16 -0
- package/dist/components/assistant-ui/elements/tool-error.js +62 -0
- package/dist/components/assistant-ui/elements/tool-fallback.aui.d.ts +44 -0
- package/dist/components/assistant-ui/elements/tool-fallback.aui.js +542 -0
- package/dist/components/assistant-ui/elements/tool-group.aui.d.ts +37 -0
- package/dist/components/assistant-ui/elements/tool-group.aui.js +104 -0
- package/dist/components/assistant-ui/elements/tool-group.d.ts +20 -0
- package/dist/components/assistant-ui/elements/tool-group.js +71 -0
- package/dist/components/assistant-ui/elements/tool-timeline.d.ts +44 -0
- package/dist/components/assistant-ui/elements/tool-timeline.js +109 -0
- package/dist/components/assistant-ui/elements/tooltip-icon-button.d.ts +12 -0
- package/dist/components/assistant-ui/elements/tooltip-icon-button.js +30 -0
- package/dist/components/assistant-ui/elements/trace-waterfall.d.ts +33 -0
- package/dist/components/assistant-ui/elements/trace-waterfall.js +102 -0
- package/dist/components/assistant-ui/elements/typing-indicator.d.ts +9 -0
- package/dist/components/assistant-ui/elements/typing-indicator.js +45 -0
- package/dist/components/assistant-ui/elements/voice-conversation.aui.d.ts +11 -0
- package/dist/components/assistant-ui/elements/voice-conversation.aui.js +54 -0
- package/dist/components/assistant-ui/elements/voice-conversation.d.ts +21 -0
- package/dist/components/assistant-ui/elements/voice-conversation.js +110 -0
- package/dist/components/assistant-ui/elements/voice.aui.d.ts +22 -0
- package/dist/components/assistant-ui/elements/voice.aui.js +100 -0
- package/dist/components/assistant-ui/elements/voice.d.ts +15 -0
- package/dist/components/assistant-ui/elements/voice.js +400 -0
- package/dist/components/assistant-ui/elements/web-preview.d.ts +18 -0
- package/dist/components/assistant-ui/elements/web-preview.js +61 -0
- package/dist/components/assistant-ui/elements/web-search.d.ts +17 -0
- package/dist/components/assistant-ui/elements/web-search.js +54 -0
- package/dist/components/assistant-ui/utils/href.d.ts +13 -0
- package/dist/components/assistant-ui/utils/href.js +39 -0
- package/dist/components/assistant-ui/utils/range.d.ts +22 -0
- package/dist/components/assistant-ui/utils/range.js +48 -0
- package/dist/components/assistant-ui/utils/task.d.ts +14 -0
- package/dist/components/assistant-ui/utils/task.js +75 -0
- package/dist/components/icons/github.js +13 -0
- package/dist/components/theme-provider.d.ts +16 -0
- package/dist/components/theme-provider.js +116 -0
- package/dist/components/ui/accordion.d.ts +8 -0
- package/dist/components/ui/accordion.js +53 -0
- package/dist/components/ui/alert-dialog.d.ts +20 -0
- package/dist/components/ui/alert-dialog.js +93 -0
- package/dist/components/ui/alert.d.ts +12 -0
- package/dist/components/ui/alert.js +42 -0
- package/dist/components/ui/aspect-ratio.d.ts +6 -0
- package/dist/components/ui/aspect-ratio.js +13 -0
- package/dist/components/ui/attachment.d.ts +25 -0
- package/dist/components/ui/attachment.js +103 -0
- package/dist/components/ui/avatar.d.ts +13 -0
- package/dist/components/ui/avatar.js +50 -0
- package/dist/components/ui/badge.d.ts +14 -0
- package/dist/components/ui/badge.js +30 -0
- package/dist/components/ui/breadcrumb.d.ts +12 -0
- package/dist/components/ui/breadcrumb.js +71 -0
- package/dist/components/ui/bubble.d.ts +18 -0
- package/dist/components/ui/bubble.js +72 -0
- package/dist/components/ui/button-group.d.ts +12 -0
- package/dist/components/ui/button-group.js +41 -0
- package/dist/components/ui/button.d.ts +19 -0
- package/dist/components/ui/button.js +71 -0
- package/dist/components/ui/calendar.d.ts +12 -0
- package/dist/components/ui/calendar.js +108 -0
- package/dist/components/ui/card.d.ts +13 -0
- package/dist/components/ui/card.js +55 -0
- package/dist/components/ui/carousel.d.ts +30 -0
- package/dist/components/ui/carousel.js +131 -0
- package/dist/components/ui/chart.d.ts +46 -0
- package/dist/components/ui/chart.js +148 -0
- package/dist/components/ui/checkbox.d.ts +5 -0
- package/dist/components/ui/checkbox.js +20 -0
- package/dist/components/ui/collapsible.d.ts +7 -0
- package/dist/components/ui/collapsible.js +23 -0
- package/dist/components/ui/combobox.d.ts +26 -0
- package/dist/components/ui/combobox.js +161 -0
- package/dist/components/ui/command.d.ts +21 -0
- package/dist/components/ui/command.js +87 -0
- package/dist/components/ui/context-menu.d.ts +31 -0
- package/dist/components/ui/context-menu.js +132 -0
- package/dist/components/ui/dialog.d.ts +19 -0
- package/dist/components/ui/dialog.js +91 -0
- package/dist/components/ui/diff-viewer.d.ts +100 -0
- package/dist/components/ui/diff-viewer.js +461 -0
- package/dist/components/ui/direction.d.ts +2 -0
- package/dist/components/ui/direction.js +2 -0
- package/dist/components/ui/dot-matrix.d.ts +150 -0
- package/dist/components/ui/dot-matrix.js +248 -0
- package/dist/components/ui/drawer.d.ts +18 -0
- package/dist/components/ui/drawer.js +123 -0
- package/dist/components/ui/dropdown-menu.d.ts +31 -0
- package/dist/components/ui/dropdown-menu.js +136 -0
- package/dist/components/ui/empty.d.ts +13 -0
- package/dist/components/ui/empty.js +59 -0
- package/dist/components/ui/field.d.ts +26 -0
- package/dist/components/ui/field.js +109 -0
- package/dist/components/ui/hover-card.d.ts +7 -0
- package/dist/components/ui/hover-card.js +36 -0
- package/dist/components/ui/input-group.d.ts +20 -0
- package/dist/components/ui/input-group.js +77 -0
- package/dist/components/ui/input-otp.d.ts +13 -0
- package/dist/components/ui/input-otp.js +46 -0
- package/dist/components/ui/input.d.ts +5 -0
- package/dist/components/ui/input.js +14 -0
- package/dist/components/ui/item.d.ts +24 -0
- package/dist/components/ui/item.js +120 -0
- package/dist/components/ui/kbd.d.ts +5 -0
- package/dist/components/ui/kbd.js +19 -0
- package/dist/components/ui/label.d.ts +5 -0
- package/dist/components/ui/label.js +12 -0
- package/dist/components/ui/marker.d.ts +12 -0
- package/dist/components/ui/marker.js +42 -0
- package/dist/components/ui/menubar.d.ts +31 -0
- package/dist/components/ui/menubar.js +135 -0
- package/dist/components/ui/message-scroller.d.ts +12 -0
- package/dist/components/ui/message-scroller.js +59 -0
- package/dist/components/ui/message.d.ts +12 -0
- package/dist/components/ui/message.js +48 -0
- package/dist/components/ui/native-select.d.ts +10 -0
- package/dist/components/ui/native-select.js +37 -0
- package/dist/components/ui/navigation-menu.d.ts +13 -0
- package/dist/components/ui/navigation-menu.js +82 -0
- package/dist/components/ui/number-roll.d.ts +21 -0
- package/dist/components/ui/number-roll.js +269 -0
- package/dist/components/ui/pagination.d.ts +19 -0
- package/dist/components/ui/pagination.js +79 -0
- package/dist/components/ui/popover.d.ts +11 -0
- package/dist/components/ui/popover.js +54 -0
- package/dist/components/ui/progress.d.ts +9 -0
- package/dist/components/ui/progress.js +44 -0
- package/dist/components/ui/questionnaire.d.ts +21 -0
- package/dist/components/ui/questionnaire.js +169 -0
- package/dist/components/ui/radio-group.d.ts +7 -0
- package/dist/components/ui/radio-group.js +26 -0
- package/dist/components/ui/resizable.d.ts +9 -0
- package/dist/components/ui/resizable.js +28 -0
- package/dist/components/ui/scroll-area.d.ts +6 -0
- package/dist/components/ui/scroll-area.js +35 -0
- package/dist/components/ui/select.d.ts +17 -0
- package/dist/components/ui/select.js +96 -0
- package/dist/components/ui/separator.d.ts +5 -0
- package/dist/components/ui/separator.js +14 -0
- package/dist/components/ui/sheet.d.ts +16 -0
- package/dist/components/ui/sheet.js +87 -0
- package/dist/components/ui/sidebar.d.ts +65 -0
- package/dist/components/ui/sidebar.js +386 -0
- package/dist/components/ui/skeleton.d.ts +4 -0
- package/dist/components/ui/skeleton.js +12 -0
- package/dist/components/ui/slider.d.ts +5 -0
- package/dist/components/ui/slider.js +33 -0
- package/dist/components/ui/spinner.d.ts +4 -0
- package/dist/components/ui/spinner.js +15 -0
- package/dist/components/ui/switch.d.ts +7 -0
- package/dist/components/ui/switch.js +19 -0
- package/dist/components/ui/table.d.ts +12 -0
- package/dist/components/ui/table.js +65 -0
- package/dist/components/ui/tabs.d.ts +12 -0
- package/dist/components/ui/tabs.js +45 -0
- package/dist/components/ui/textarea.d.ts +5 -0
- package/dist/components/ui/textarea.js +12 -0
- package/dist/components/ui/toast.d.ts +18 -0
- package/dist/components/ui/toast.js +121 -0
- package/dist/components/ui/toggle-group.d.ts +13 -0
- package/dist/components/ui/toggle-group.js +51 -0
- package/dist/components/ui/toggle.d.ts +10 -0
- package/dist/components/ui/toggle.js +35 -0
- package/dist/components/ui/tooltip.d.ts +8 -0
- package/dist/components/ui/tooltip.js +43 -0
- package/dist/compositions/app-rail/app-rail.d.ts +19 -0
- package/dist/compositions/app-rail/app-rail.js +58 -0
- package/dist/compositions/app-shell/app-shell.d.ts +56 -0
- package/dist/compositions/app-shell/app-shell.js +143 -0
- package/dist/compositions/app-shell/theme-toggle.d.ts +10 -0
- package/dist/compositions/app-shell/theme-toggle.js +65 -0
- package/dist/compositions/confirm-action/confirm-action.d.ts +48 -0
- package/dist/compositions/confirm-action/confirm-action.js +48 -0
- package/dist/compositions/data-table/data-table-state.d.ts +23 -0
- package/dist/compositions/data-table/data-table-state.js +46 -0
- package/dist/compositions/data-table/data-table.d.ts +185 -0
- package/dist/compositions/data-table/data-table.js +615 -0
- package/dist/compositions/date-range-picker/date-range-options.d.ts +28 -0
- package/dist/compositions/date-range-picker/date-range-options.js +61 -0
- package/dist/compositions/date-range-picker/date-range-picker.d.ts +55 -0
- package/dist/compositions/date-range-picker/date-range-picker.js +409 -0
- package/dist/compositions/decision-queue/decision-queue.d.ts +114 -0
- package/dist/compositions/decision-queue/decision-queue.js +478 -0
- package/dist/compositions/event-feed/event-feed.d.ts +59 -0
- package/dist/compositions/event-feed/event-feed.js +105 -0
- package/dist/compositions/feedback.d.ts +20 -0
- package/dist/compositions/feedback.js +49 -0
- package/dist/compositions/fields.d.ts +64 -0
- package/dist/compositions/fields.js +293 -0
- package/dist/compositions/form-kit/form-context.d.ts +10 -0
- package/dist/compositions/form-kit/form-context.js +12 -0
- package/dist/compositions/form-kit/form-fields.d.ts +95 -0
- package/dist/compositions/form-kit/form-fields.js +233 -0
- package/dist/compositions/form-kit/form-kit.d.ts +128 -0
- package/dist/compositions/form-kit/form-kit.js +119 -0
- package/dist/compositions/inspector/inspector.d.ts +53 -0
- package/dist/compositions/inspector/inspector.js +80 -0
- package/dist/compositions/layout.d.ts +36 -0
- package/dist/compositions/layout.js +86 -0
- package/dist/compositions/state-blocks/state-blocks.d.ts +42 -0
- package/dist/compositions/state-blocks/state-blocks.js +81 -0
- package/dist/compositions/status-panel/status-panel.d.ts +94 -0
- package/dist/compositions/status-panel/status-panel.js +189 -0
- package/dist/fonts/InterVariable.woff2 +0 -0
- package/dist/fonts/inter.css +15 -0
- package/dist/hooks/use-attachment-src.js +35 -0
- package/dist/hooks/use-copy-to-clipboard.js +34 -0
- package/dist/hooks/use-mobile.d.ts +3 -0
- package/dist/hooks/use-mobile.js +18 -0
- package/dist/index.d.ts +102 -0
- package/dist/index.js +102 -0
- package/dist/lib/context-level.js +7 -0
- package/dist/lib/elapsed.js +61 -0
- package/dist/lib/iso-date.js +30 -0
- package/dist/lib/motion-loop.js +41 -0
- package/dist/lib/pointer.js +14 -0
- package/dist/lib/status-tone.d.ts +7 -0
- package/dist/lib/status-tone.js +55 -0
- package/dist/lib/triage-keys.js +229 -0
- package/dist/lib/utils.js +2 -0
- package/dist/motion/alert-toast/alert-toast.d.ts +51 -0
- package/dist/motion/alert-toast/alert-toast.js +226 -0
- package/dist/motion/branch-menu/branch-menu.d.ts +47 -0
- package/dist/motion/branch-menu/branch-menu.js +287 -0
- package/dist/motion/check-item/check-item.d.ts +24 -0
- package/dist/motion/check-item/check-item.js +110 -0
- package/dist/motion/dial/dial.d.ts +39 -0
- package/dist/motion/dial/dial.js +290 -0
- package/dist/motion/dictation-button/dictation-button.d.ts +45 -0
- package/dist/motion/dictation-button/dictation-button.js +232 -0
- package/dist/motion/hold-button/hold-button.d.ts +37 -0
- package/dist/motion/hold-button/hold-button.js +192 -0
- package/dist/motion/masonry-grid/masonry-grid.d.ts +42 -0
- package/dist/motion/masonry-grid/masonry-grid.js +145 -0
- package/dist/motion/prompt-composer/prompt-composer.d.ts +90 -0
- package/dist/motion/prompt-composer/prompt-composer.js +374 -0
- package/dist/motion/scrub-select/scrub-select.d.ts +33 -0
- package/dist/motion/scrub-select/scrub-select.js +346 -0
- package/dist/motion/spotlight-grid/spotlight-grid.d.ts +40 -0
- package/dist/motion/spotlight-grid/spotlight-grid.js +171 -0
- package/dist/motion/star-rating/star-rating.d.ts +32 -0
- package/dist/motion/star-rating/star-rating.js +191 -0
- package/dist/motion/status-glyph/status-glyph.d.ts +28 -0
- package/dist/motion/status-glyph/status-glyph.js +171 -0
- package/dist/motion/stepper/stepper.d.ts +56 -0
- package/dist/motion/stepper/stepper.js +211 -0
- package/dist/motion/swipe-row/swipe-row.d.ts +52 -0
- package/dist/motion/swipe-row/swipe-row.js +208 -0
- package/dist/motion/thinking-trace/thinking-trace.d.ts +32 -0
- package/dist/motion/thinking-trace/thinking-trace.js +186 -0
- package/dist/motion/tool-call-chip/tool-call-chip.d.ts +36 -0
- package/dist/motion/tool-call-chip/tool-call-chip.js +135 -0
- package/dist/motion/working-indicator/working-indicator.d.ts +38 -0
- package/dist/motion/working-indicator/working-indicator.js +171 -0
- package/dist/styles.css +828 -0
- package/dist/tokens.css +230 -0
- package/licenses/Inter-OFL.txt +92 -0
- package/licenses/assistant-ui-MIT.txt +21 -0
- package/licenses/shadcn-MIT.md +21 -0
- package/package.json +131 -3
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
//#region src/ai/compositions/usage-meter/usage-format.ts
|
|
2
|
+
/** A finite, non-negative number, or `undefined`. */
|
|
3
|
+
function known(value) {
|
|
4
|
+
return value !== void 0 && Number.isFinite(value) && value >= 0 ? value : void 0;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* A token count, compact: 840, 48.2k, 1.2M. Like formatLatency, the unit is
|
|
8
|
+
* chosen after rounding, so 999,950 reads "1M", not "1000k".
|
|
9
|
+
*/
|
|
10
|
+
function formatTokens(tokens) {
|
|
11
|
+
const trim = (value) => value.toFixed(1).replace(/\.0$/, "");
|
|
12
|
+
const count = Math.round(tokens);
|
|
13
|
+
if (count < 1e3) return `${count}`;
|
|
14
|
+
const thousands = Math.round(count / 100) / 10;
|
|
15
|
+
if (thousands < 1e3) return `${trim(thousands)}k`;
|
|
16
|
+
return `${trim(Math.round(count / 1e5) / 10)}M`;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A cost in US dollars. Agent calls often cost fractions of a cent, so a cost
|
|
20
|
+
* under a dollar keeps up to four decimals ("$0.0034", "$0.0912", "$0.42")
|
|
21
|
+
* rather than rounding to "$0.00"; a dollar or more keeps two.
|
|
22
|
+
*/
|
|
23
|
+
function formatCost(costUsd) {
|
|
24
|
+
if (costUsd > 0 && costUsd < 1e-4) return "<$0.0001";
|
|
25
|
+
const decimals = costUsd < 1 ? 4 : 2;
|
|
26
|
+
return `$${costUsd.toLocaleString("en-US", {
|
|
27
|
+
minimumFractionDigits: 2,
|
|
28
|
+
maximumFractionDigits: decimals
|
|
29
|
+
})}`;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A wall-clock duration: 840 ms, 2.4 s, 1 m 12 s. Each unit is chosen after
|
|
33
|
+
* rounding to the precision it prints, so 999.6 ms reads "1 s", not "1000 ms",
|
|
34
|
+
* and 59,950 ms reads "1 m", not "60 s".
|
|
35
|
+
*/
|
|
36
|
+
function formatLatency(latencyMs) {
|
|
37
|
+
const ms = Math.round(latencyMs);
|
|
38
|
+
if (ms < 1e3) return `${ms} ms`;
|
|
39
|
+
const tenths = Math.round(latencyMs / 100);
|
|
40
|
+
if (tenths < 600) return `${(tenths / 10).toFixed(1).replace(/\.0$/, "")} s`;
|
|
41
|
+
const totalSeconds = Math.round(latencyMs / 1e3);
|
|
42
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
43
|
+
const seconds = totalSeconds % 60;
|
|
44
|
+
return seconds === 0 ? `${minutes} m` : `${minutes} m ${seconds} s`;
|
|
45
|
+
}
|
|
46
|
+
/** Reads a Usage record, dropping missing, negative and non-finite numbers. */
|
|
47
|
+
function readUsage(usage) {
|
|
48
|
+
const inputTokens = known(usage.inputTokens);
|
|
49
|
+
const outputTokens = known(usage.outputTokens);
|
|
50
|
+
const hasTokens = inputTokens !== void 0 || outputTokens !== void 0;
|
|
51
|
+
return {
|
|
52
|
+
model: usage.model?.trim() || void 0,
|
|
53
|
+
inputTokens,
|
|
54
|
+
outputTokens,
|
|
55
|
+
cachedInputTokens: known(usage.cachedInputTokens),
|
|
56
|
+
reasoningTokens: known(usage.reasoningTokens),
|
|
57
|
+
totalTokens: hasTokens ? (inputTokens ?? 0) + (outputTokens ?? 0) : void 0,
|
|
58
|
+
costUsd: known(usage.costUsd),
|
|
59
|
+
contextWindow: known(usage.contextWindow) || void 0,
|
|
60
|
+
latencyMs: known(usage.latencyMs)
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** Whether the reading has anything to show. */
|
|
64
|
+
function isEmptyReading(reading) {
|
|
65
|
+
return Object.values(reading).every((value) => value === void 0);
|
|
66
|
+
}
|
|
67
|
+
/** Whether the reading carries any token count, including only a cached or reasoning subset. */
|
|
68
|
+
function hasTokenCounts(reading) {
|
|
69
|
+
return [
|
|
70
|
+
reading.inputTokens,
|
|
71
|
+
reading.cachedInputTokens,
|
|
72
|
+
reading.outputTokens,
|
|
73
|
+
reading.reasoningTokens
|
|
74
|
+
].some((tokens) => tokens !== void 0);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* What fills the context window, split so the slices add up to the total.
|
|
78
|
+
* admin-ui's Usage contract counts cached input inside input and reasoning
|
|
79
|
+
* inside output, so each pair splits into the subset and the rest. Empty
|
|
80
|
+
* slices are left out.
|
|
81
|
+
*/
|
|
82
|
+
function contextSlices(reading) {
|
|
83
|
+
const input = reading.inputTokens ?? 0;
|
|
84
|
+
const output = reading.outputTokens ?? 0;
|
|
85
|
+
const cached = Math.min(reading.cachedInputTokens ?? 0, input);
|
|
86
|
+
const reasoning = Math.min(reading.reasoningTokens ?? 0, output);
|
|
87
|
+
return [
|
|
88
|
+
{
|
|
89
|
+
label: "Input",
|
|
90
|
+
tokens: input - cached
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
label: "Cached input",
|
|
94
|
+
tokens: cached
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
label: "Output",
|
|
98
|
+
tokens: output - reasoning
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
label: "Reasoning",
|
|
102
|
+
tokens: reasoning
|
|
103
|
+
}
|
|
104
|
+
].filter((slice) => slice.tokens > 0);
|
|
105
|
+
}
|
|
106
|
+
//#endregion
|
|
107
|
+
export { contextSlices, formatCost, formatLatency, formatTokens, hasTokenCounts, isEmptyReading, readUsage };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Usage } from "../../types.js";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
//#region src/ai/compositions/usage-meter/usage-meter.d.ts
|
|
4
|
+
export type UsageMeterVariant = "compact" | "expanded";
|
|
5
|
+
/** What the usage covers. */
|
|
6
|
+
export type UsageMeterScope = "run" | "thread";
|
|
7
|
+
export interface UsageMeterProps {
|
|
8
|
+
/** The usage to show. Fields it does not carry are hidden, never shown as zero. */
|
|
9
|
+
usage: Usage;
|
|
10
|
+
/**
|
|
11
|
+
* `compact` is an inline reading for a header (model, tokens in and out,
|
|
12
|
+
* cost, latency and a context ring); `expanded` is a breakdown panel.
|
|
13
|
+
* Defaults to `compact`.
|
|
14
|
+
*/
|
|
15
|
+
variant?: UsageMeterVariant;
|
|
16
|
+
/** Whether the usage covers one run or a whole thread. Defaults to `run`. */
|
|
17
|
+
scope?: UsageMeterScope;
|
|
18
|
+
/** Which side the compact context ring's breakdown opens on. Defaults to `bottom`. */
|
|
19
|
+
contextSide?: "top" | "bottom" | "left" | "right";
|
|
20
|
+
className?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Tokens in and out, cost, context-window use and latency for one run or a
|
|
24
|
+
* whole thread, from a `Usage` record. A field the record does not carry is
|
|
25
|
+
* hidden: a run with no cost shows no cost row, not "$0.00".
|
|
26
|
+
*
|
|
27
|
+
* Built on the registry's ContextDisplay ring (compact), CostMeter and
|
|
28
|
+
* ContextBreakdown (expanded). Usage is always a prop, so nothing here reads
|
|
29
|
+
* thread state or needs `@assistant-ui/ai-sdk`.
|
|
30
|
+
*/
|
|
31
|
+
export declare function UsageMeter({ usage, variant, scope, contextSide, className }: UsageMeterProps): React.JSX.Element;
|
|
32
|
+
//#endregion
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { mono, paper } from "../../../components/assistant-ui/elements/surfaces.js";
|
|
2
|
+
import { ContextBreakdown } from "../../../components/assistant-ui/elements/context-breakdown.js";
|
|
3
|
+
import { ContextDisplay } from "../../../components/assistant-ui/elements/context-display.aui.js";
|
|
4
|
+
import { CostMeter } from "../../../components/assistant-ui/elements/cost-meter.js";
|
|
5
|
+
import { contextSlices, formatCost, formatLatency, formatTokens, hasTokenCounts, isEmptyReading, readUsage } from "./usage-format.js";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { cn } from "cn";
|
|
8
|
+
import { TimerIcon } from "lucide-react";
|
|
9
|
+
//#region src/ai/compositions/usage-meter/usage-meter.tsx
|
|
10
|
+
const SCOPE_TITLE = {
|
|
11
|
+
run: "Run usage",
|
|
12
|
+
thread: "Thread usage"
|
|
13
|
+
};
|
|
14
|
+
const SCOPE_LABEL = {
|
|
15
|
+
run: "this run",
|
|
16
|
+
thread: "this thread"
|
|
17
|
+
};
|
|
18
|
+
const SLICE_TINT = {
|
|
19
|
+
Input: "bg-info",
|
|
20
|
+
"Cached input": "bg-info",
|
|
21
|
+
Output: "bg-violet-500",
|
|
22
|
+
Reasoning: "bg-violet-300"
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* The counts the ring's breakdown lists: the same split as the expanded
|
|
26
|
+
* panel (uncached input, cached input, output less reasoning, reasoning), so
|
|
27
|
+
* the rows add up to the total the ring shows.
|
|
28
|
+
*/
|
|
29
|
+
function ringUsage(reading, totalTokens) {
|
|
30
|
+
const slices = contextSlices(reading);
|
|
31
|
+
const slice = (label) => slices.find((item) => item.label === label)?.tokens;
|
|
32
|
+
return {
|
|
33
|
+
totalTokens,
|
|
34
|
+
inputTokens: slice("Input"),
|
|
35
|
+
cachedInputTokens: slice("Cached input"),
|
|
36
|
+
outputTokens: slice("Output"),
|
|
37
|
+
reasoningTokens: slice("Reasoning")
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Tokens in and out, cost, context-window use and latency for one run or a
|
|
42
|
+
* whole thread, from a `Usage` record. A field the record does not carry is
|
|
43
|
+
* hidden: a run with no cost shows no cost row, not "$0.00".
|
|
44
|
+
*
|
|
45
|
+
* Built on the registry's ContextDisplay ring (compact), CostMeter and
|
|
46
|
+
* ContextBreakdown (expanded). Usage is always a prop, so nothing here reads
|
|
47
|
+
* thread state or needs `@assistant-ui/ai-sdk`.
|
|
48
|
+
*/
|
|
49
|
+
function UsageMeter({ usage, variant = "compact", scope = "run", contextSide = "bottom", className }) {
|
|
50
|
+
const reading = readUsage(usage);
|
|
51
|
+
return variant === "expanded" ? /* @__PURE__ */ jsx(ExpandedUsage, {
|
|
52
|
+
reading,
|
|
53
|
+
scope,
|
|
54
|
+
className
|
|
55
|
+
}) : /* @__PURE__ */ jsx(CompactUsage, {
|
|
56
|
+
reading,
|
|
57
|
+
scope,
|
|
58
|
+
side: contextSide,
|
|
59
|
+
className
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
/** One term and its value; the term is for assistive technology only. */
|
|
63
|
+
function Stat({ term, children, className }) {
|
|
64
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
65
|
+
"data-slot": "usage-meter-stat",
|
|
66
|
+
className: cn("flex items-center", className),
|
|
67
|
+
children: [/* @__PURE__ */ jsx("dt", {
|
|
68
|
+
className: "sr-only",
|
|
69
|
+
children: term
|
|
70
|
+
}), /* @__PURE__ */ jsx("dd", {
|
|
71
|
+
className: "flex min-w-0 items-center gap-1",
|
|
72
|
+
children
|
|
73
|
+
})]
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/** A count with its unit word ("in", "out") shown but not read twice. */
|
|
77
|
+
function TokenStat({ term, tokens, unit }) {
|
|
78
|
+
return /* @__PURE__ */ jsxs(Stat, {
|
|
79
|
+
term,
|
|
80
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
81
|
+
className: "text-foreground tabular-nums",
|
|
82
|
+
children: formatTokens(tokens)
|
|
83
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
84
|
+
"aria-hidden": "true",
|
|
85
|
+
children: unit
|
|
86
|
+
})]
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
function CompactUsage({ reading, scope, side, className }) {
|
|
90
|
+
const title = SCOPE_TITLE[scope];
|
|
91
|
+
const { contextWindow, totalTokens } = reading;
|
|
92
|
+
return /* @__PURE__ */ jsx("div", {
|
|
93
|
+
role: "group",
|
|
94
|
+
"aria-label": title,
|
|
95
|
+
"data-slot": "usage-meter",
|
|
96
|
+
"data-variant": "compact",
|
|
97
|
+
className: cn("text-muted-foreground inline-flex max-w-full text-xs", className),
|
|
98
|
+
children: isEmptyReading(reading) ? /* @__PURE__ */ jsx("span", { children: "No usage recorded" }) : /* @__PURE__ */ jsxs("dl", {
|
|
99
|
+
className: "flex min-w-0 flex-wrap items-center gap-x-3 gap-y-1",
|
|
100
|
+
children: [
|
|
101
|
+
reading.model ? /* @__PURE__ */ jsx(Stat, {
|
|
102
|
+
term: "Model",
|
|
103
|
+
className: "min-w-0",
|
|
104
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
105
|
+
className: "text-foreground truncate font-mono text-[11px]",
|
|
106
|
+
children: reading.model
|
|
107
|
+
})
|
|
108
|
+
}) : null,
|
|
109
|
+
reading.inputTokens !== void 0 ? /* @__PURE__ */ jsx(TokenStat, {
|
|
110
|
+
term: "Input tokens",
|
|
111
|
+
tokens: reading.inputTokens,
|
|
112
|
+
unit: "in"
|
|
113
|
+
}) : null,
|
|
114
|
+
reading.outputTokens !== void 0 ? /* @__PURE__ */ jsx(TokenStat, {
|
|
115
|
+
term: "Output tokens",
|
|
116
|
+
tokens: reading.outputTokens,
|
|
117
|
+
unit: "out"
|
|
118
|
+
}) : null,
|
|
119
|
+
reading.inputTokens === void 0 && reading.cachedInputTokens !== void 0 ? /* @__PURE__ */ jsx(TokenStat, {
|
|
120
|
+
term: "Cached input tokens",
|
|
121
|
+
tokens: reading.cachedInputTokens,
|
|
122
|
+
unit: "cached"
|
|
123
|
+
}) : null,
|
|
124
|
+
reading.outputTokens === void 0 && reading.reasoningTokens !== void 0 ? /* @__PURE__ */ jsx(TokenStat, {
|
|
125
|
+
term: "Reasoning tokens",
|
|
126
|
+
tokens: reading.reasoningTokens,
|
|
127
|
+
unit: "reasoning"
|
|
128
|
+
}) : null,
|
|
129
|
+
reading.costUsd !== void 0 ? /* @__PURE__ */ jsx(Stat, {
|
|
130
|
+
term: "Cost",
|
|
131
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
132
|
+
className: "text-foreground tabular-nums",
|
|
133
|
+
children: formatCost(reading.costUsd)
|
|
134
|
+
})
|
|
135
|
+
}) : null,
|
|
136
|
+
reading.latencyMs !== void 0 ? /* @__PURE__ */ jsxs(Stat, {
|
|
137
|
+
term: "Latency",
|
|
138
|
+
children: [/* @__PURE__ */ jsx(TimerIcon, {
|
|
139
|
+
"aria-hidden": "true",
|
|
140
|
+
className: "size-3.5"
|
|
141
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
142
|
+
className: "text-foreground tabular-nums",
|
|
143
|
+
children: formatLatency(reading.latencyMs)
|
|
144
|
+
})]
|
|
145
|
+
}) : null,
|
|
146
|
+
contextWindow !== void 0 && totalTokens !== void 0 ? /* @__PURE__ */ jsx(Stat, {
|
|
147
|
+
term: "Context window",
|
|
148
|
+
children: /* @__PURE__ */ jsx(ContextDisplay.Ring, {
|
|
149
|
+
modelContextWindow: contextWindow,
|
|
150
|
+
side,
|
|
151
|
+
className: "-my-1 -ms-1 px-1 outline-none hover:bg-foreground/[0.04] focus-visible:bg-foreground/[0.04] focus-visible:text-foreground focus-visible:ring-1 focus-visible:ring-ring/70",
|
|
152
|
+
usage: ringUsage(reading, totalTokens)
|
|
153
|
+
})
|
|
154
|
+
}) : null
|
|
155
|
+
]
|
|
156
|
+
})
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
const flatSection = "max-w-none rounded-none border-0 border-t border-border/60 bg-transparent px-4 py-3.5 dark:bg-transparent";
|
|
160
|
+
function ExpandedUsage({ reading, scope, className }) {
|
|
161
|
+
const title = SCOPE_TITLE[scope];
|
|
162
|
+
const hasTokens = reading.totalTokens !== void 0;
|
|
163
|
+
const showContext = hasTokens && reading.contextWindow !== void 0;
|
|
164
|
+
const showTokenList = !showContext && hasTokenCounts(reading);
|
|
165
|
+
const slices = contextSlices(reading);
|
|
166
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
167
|
+
"aria-label": title,
|
|
168
|
+
"data-slot": "usage-meter",
|
|
169
|
+
"data-variant": "expanded",
|
|
170
|
+
className: cn(paper, "flex w-full max-w-sm flex-col overflow-hidden rounded-2xl", className),
|
|
171
|
+
children: [
|
|
172
|
+
/* @__PURE__ */ jsxs("header", {
|
|
173
|
+
className: "flex min-w-0 items-center gap-3 px-4 py-3.5",
|
|
174
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
175
|
+
className: "flex min-w-0 flex-1 flex-col gap-0.5",
|
|
176
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
177
|
+
className: "text-[13.5px] font-medium",
|
|
178
|
+
children: title
|
|
179
|
+
}), reading.model ? /* @__PURE__ */ jsx("span", {
|
|
180
|
+
className: cn(mono, "text-muted-foreground truncate"),
|
|
181
|
+
children: reading.model
|
|
182
|
+
}) : null]
|
|
183
|
+
}), reading.latencyMs !== void 0 ? /* @__PURE__ */ jsx("dl", {
|
|
184
|
+
className: "text-muted-foreground shrink-0 text-xs",
|
|
185
|
+
children: /* @__PURE__ */ jsxs(Stat, {
|
|
186
|
+
term: "Latency",
|
|
187
|
+
children: [/* @__PURE__ */ jsx(TimerIcon, {
|
|
188
|
+
"aria-hidden": "true",
|
|
189
|
+
className: "size-3.5"
|
|
190
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
191
|
+
className: "text-foreground tabular-nums",
|
|
192
|
+
children: formatLatency(reading.latencyMs)
|
|
193
|
+
})]
|
|
194
|
+
})
|
|
195
|
+
}) : null]
|
|
196
|
+
}),
|
|
197
|
+
isEmptyReading(reading) ? /* @__PURE__ */ jsxs("p", {
|
|
198
|
+
className: "text-muted-foreground border-border/60 border-t px-4 py-3.5 text-xs",
|
|
199
|
+
children: [
|
|
200
|
+
"No usage recorded for ",
|
|
201
|
+
SCOPE_LABEL[scope],
|
|
202
|
+
"."
|
|
203
|
+
]
|
|
204
|
+
}) : null,
|
|
205
|
+
reading.costUsd !== void 0 ? /* @__PURE__ */ jsx(CostMeter, {
|
|
206
|
+
className: cn(flatSection, "[&>div:has(>[role=meter])]:hidden"),
|
|
207
|
+
runCost: formatCost(reading.costUsd),
|
|
208
|
+
scopeLabel: SCOPE_LABEL[scope],
|
|
209
|
+
lines: hasTokens ? [{
|
|
210
|
+
model: reading.model ?? "All models",
|
|
211
|
+
inputTokens: reading.inputTokens ?? 0,
|
|
212
|
+
outputTokens: reading.outputTokens ?? 0,
|
|
213
|
+
cost: formatCost(reading.costUsd),
|
|
214
|
+
share: 1
|
|
215
|
+
}] : []
|
|
216
|
+
}) : null,
|
|
217
|
+
showContext ? /* @__PURE__ */ jsx(ContextBreakdown, {
|
|
218
|
+
className: flatSection,
|
|
219
|
+
limit: reading.contextWindow ?? 0,
|
|
220
|
+
segments: slices.map((slice) => ({
|
|
221
|
+
...slice,
|
|
222
|
+
tint: SLICE_TINT[slice.label] ?? "bg-foreground/25"
|
|
223
|
+
}))
|
|
224
|
+
}) : null,
|
|
225
|
+
showTokenList ? /* @__PURE__ */ jsx(TokenList, { reading }) : null
|
|
226
|
+
]
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
/** Token counts with no context window to measure them against. */
|
|
230
|
+
function TokenList({ reading }) {
|
|
231
|
+
const rows = [
|
|
232
|
+
["Input", reading.inputTokens],
|
|
233
|
+
["Cached input", reading.cachedInputTokens],
|
|
234
|
+
["Output", reading.outputTokens],
|
|
235
|
+
["Reasoning", reading.reasoningTokens]
|
|
236
|
+
];
|
|
237
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
238
|
+
className: "border-border/60 flex flex-col gap-3 border-t px-4 py-3.5",
|
|
239
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
240
|
+
className: "text-[13.5px] font-medium",
|
|
241
|
+
children: "Tokens"
|
|
242
|
+
}), /* @__PURE__ */ jsx("dl", {
|
|
243
|
+
className: "flex flex-col gap-1.5",
|
|
244
|
+
children: rows.map(([term, tokens]) => tokens === void 0 ? null : /* @__PURE__ */ jsxs("div", {
|
|
245
|
+
className: "flex items-baseline gap-2",
|
|
246
|
+
children: [/* @__PURE__ */ jsx("dt", {
|
|
247
|
+
className: "text-muted-foreground min-w-0 flex-1 truncate text-[13px]",
|
|
248
|
+
children: term
|
|
249
|
+
}), /* @__PURE__ */ jsx("dd", {
|
|
250
|
+
className: cn(mono, "text-muted-foreground shrink-0 tabular-nums"),
|
|
251
|
+
children: tokens.toLocaleString("en-US")
|
|
252
|
+
})]
|
|
253
|
+
}, term))
|
|
254
|
+
})]
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
//#endregion
|
|
258
|
+
export { UsageMeter };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//#region src/ai/testing/mock-clock.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The time source `MockRuntimeProvider` schedules its streaming on. The
|
|
4
|
+
* default is the real clock; a story's play function passes a manual clock and
|
|
5
|
+
* advances it with `tick()`, so streamed output is deterministic.
|
|
6
|
+
*/
|
|
7
|
+
export type MockClock = {
|
|
8
|
+
/** The current time in epoch milliseconds. */
|
|
9
|
+
now(): number;
|
|
10
|
+
/** Runs `callback` after `ms` milliseconds; returns a handle for `clear`. */
|
|
11
|
+
schedule(callback: () => void, ms: number): number;
|
|
12
|
+
/** Cancels a scheduled callback. Unknown handles are ignored. */
|
|
13
|
+
clear(handle: number): void;
|
|
14
|
+
};
|
|
15
|
+
/** A clock that only moves when told to. */
|
|
16
|
+
export type ManualClock = MockClock & {
|
|
17
|
+
/** Moves time forward by `ms`, running every callback that falls due, in order. */
|
|
18
|
+
tick(ms: number): void;
|
|
19
|
+
/** Runs every scheduled callback, including ones they schedule, until none is left. */
|
|
20
|
+
runAll(): void;
|
|
21
|
+
/** How many callbacks are waiting. */
|
|
22
|
+
readonly pending: number;
|
|
23
|
+
};
|
|
24
|
+
/** The real clock: `Date.now` and `setTimeout`. */
|
|
25
|
+
export declare const realClock: MockClock;
|
|
26
|
+
/**
|
|
27
|
+
* Creates a manual clock. Time starts at `startAt` (default: the real time
|
|
28
|
+
* when the clock is created) and moves only through `tick` and `runAll`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function createManualClock(startAt?: number): ManualClock;
|
|
31
|
+
//#endregion
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
//#region src/ai/testing/mock-clock.ts
|
|
2
|
+
/** The real clock: `Date.now` and `setTimeout`. */
|
|
3
|
+
const realClock = {
|
|
4
|
+
now: () => Date.now(),
|
|
5
|
+
schedule: (callback, ms) => window.setTimeout(callback, ms),
|
|
6
|
+
clear: (handle) => window.clearTimeout(handle)
|
|
7
|
+
};
|
|
8
|
+
const RUN_ALL_LIMIT = 1e4;
|
|
9
|
+
/**
|
|
10
|
+
* Creates a manual clock. Time starts at `startAt` (default: the real time
|
|
11
|
+
* when the clock is created) and moves only through `tick` and `runAll`.
|
|
12
|
+
*/
|
|
13
|
+
function createManualClock(startAt = Date.now()) {
|
|
14
|
+
let now = startAt;
|
|
15
|
+
let nextId = 1;
|
|
16
|
+
let timers = [];
|
|
17
|
+
const takeNextDue = (until) => {
|
|
18
|
+
let next;
|
|
19
|
+
for (const timer of timers) {
|
|
20
|
+
if (timer.at > until) continue;
|
|
21
|
+
if (next === void 0 || timer.at < next.at || timer.at === next.at && timer.id < next.id) next = timer;
|
|
22
|
+
}
|
|
23
|
+
if (next !== void 0) {
|
|
24
|
+
const due = next;
|
|
25
|
+
timers = timers.filter((timer) => timer !== due);
|
|
26
|
+
}
|
|
27
|
+
return next;
|
|
28
|
+
};
|
|
29
|
+
return {
|
|
30
|
+
now: () => now,
|
|
31
|
+
schedule(callback, ms) {
|
|
32
|
+
const id = nextId++;
|
|
33
|
+
timers.push({
|
|
34
|
+
id,
|
|
35
|
+
at: now + Math.max(0, ms),
|
|
36
|
+
callback
|
|
37
|
+
});
|
|
38
|
+
return id;
|
|
39
|
+
},
|
|
40
|
+
clear(handle) {
|
|
41
|
+
timers = timers.filter((timer) => timer.id !== handle);
|
|
42
|
+
},
|
|
43
|
+
tick(ms) {
|
|
44
|
+
const until = now + Math.max(0, ms);
|
|
45
|
+
for (let due = takeNextDue(until); due !== void 0; due = takeNextDue(until)) {
|
|
46
|
+
now = due.at;
|
|
47
|
+
due.callback();
|
|
48
|
+
}
|
|
49
|
+
now = until;
|
|
50
|
+
},
|
|
51
|
+
runAll() {
|
|
52
|
+
for (let count = 0; timers.length > 0; count++) {
|
|
53
|
+
if (count >= RUN_ALL_LIMIT) throw new Error(`ManualClock.runAll: still scheduling after ${RUN_ALL_LIMIT} callbacks`);
|
|
54
|
+
const due = takeNextDue(Number.POSITIVE_INFINITY);
|
|
55
|
+
if (due === void 0) break;
|
|
56
|
+
now = Math.max(now, due.at);
|
|
57
|
+
due.callback();
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
get pending() {
|
|
61
|
+
return timers.length;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
66
|
+
export { createManualClock, realClock };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { ThreadMessageLike } from "@assistant-ui/react";
|
|
2
|
+
//#region src/ai/testing/mock-reply.d.ts
|
|
3
|
+
/** A JSON value as assistant-ui's message parts carry it. */
|
|
4
|
+
type ReplyJson = string | number | boolean | null | readonly ReplyJson[] | {
|
|
5
|
+
readonly [key: string]: ReplyJson;
|
|
6
|
+
};
|
|
7
|
+
/** A JSON object, such as a tool call's arguments. */
|
|
8
|
+
type ReplyJsonObject = {
|
|
9
|
+
readonly [key: string]: ReplyJson;
|
|
10
|
+
};
|
|
11
|
+
/** Streams `text` into the reply one word at a time. */
|
|
12
|
+
export type MockTextPart = {
|
|
13
|
+
readonly type: "text";
|
|
14
|
+
readonly text: string;
|
|
15
|
+
};
|
|
16
|
+
/** Streams `text` as the agent's reasoning, one word at a time. */
|
|
17
|
+
export type MockReasoningPart = {
|
|
18
|
+
readonly type: "reasoning";
|
|
19
|
+
readonly text: string;
|
|
20
|
+
};
|
|
21
|
+
/** Adds a source citation to the reply. */
|
|
22
|
+
export type MockSourcePart = {
|
|
23
|
+
readonly type: "source";
|
|
24
|
+
readonly url: string;
|
|
25
|
+
readonly title?: string;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Calls a tool: the call appears with its arguments, runs for `durationMs`,
|
|
29
|
+
* then settles with `result` (or fails with it when `isError`). With
|
|
30
|
+
* `approval`, the call stops before running until the owner approves or
|
|
31
|
+
* denies it in the UI.
|
|
32
|
+
*/
|
|
33
|
+
export type MockToolCallPart = {
|
|
34
|
+
readonly type: "tool-call";
|
|
35
|
+
readonly toolName: string;
|
|
36
|
+
readonly args: ReplyJsonObject;
|
|
37
|
+
/** What the tool returns. Leave it out to keep the call running forever. */
|
|
38
|
+
readonly result?: ReplyJson;
|
|
39
|
+
/** Whether `result` is an error. */
|
|
40
|
+
readonly isError?: boolean;
|
|
41
|
+
/** How long the call runs before its result lands, in ms. Default 800. */
|
|
42
|
+
readonly durationMs?: number;
|
|
43
|
+
/** A stable id; generated from the part's position when absent. */
|
|
44
|
+
readonly toolCallId?: string;
|
|
45
|
+
/** Gate the call on an owner decision, with this prompt. */
|
|
46
|
+
readonly approval?: {
|
|
47
|
+
readonly prompt?: string;
|
|
48
|
+
/** What the agent says when the owner denies the call; the reply ends there. */
|
|
49
|
+
readonly deniedText?: string;
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
/** Pauses the stream, as a model does between steps. */
|
|
53
|
+
export type MockWaitPart = {
|
|
54
|
+
readonly type: "wait";
|
|
55
|
+
readonly ms: number;
|
|
56
|
+
};
|
|
57
|
+
/** One scripted piece of a reply, played in order. */
|
|
58
|
+
export type MockReplyPart = MockTextPart | MockReasoningPart | MockSourcePart | MockToolCallPart | MockWaitPart;
|
|
59
|
+
/** A scripted assistant reply that `MockRuntimeProvider` streams on its clock. */
|
|
60
|
+
export type MockReply = {
|
|
61
|
+
/** The reply's parts, streamed in order. */
|
|
62
|
+
readonly parts: readonly MockReplyPart[];
|
|
63
|
+
/** Delay before the first token, in ms (time to first token). Default 400. */
|
|
64
|
+
readonly firstTokenMs?: number;
|
|
65
|
+
/** Delay between streamed words, in ms. Default 40. */
|
|
66
|
+
readonly tokenMs?: number;
|
|
67
|
+
/** End the reply with this error after the parts, as a failed run. */
|
|
68
|
+
readonly error?: string;
|
|
69
|
+
};
|
|
70
|
+
//#endregion
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
//#region src/ai/testing/mock-reply.ts
|
|
2
|
+
const DEFAULT_FIRST_TOKEN_MS = 400;
|
|
3
|
+
const DEFAULT_TOKEN_MS = 40;
|
|
4
|
+
const DEFAULT_TOOL_MS = 800;
|
|
5
|
+
const DEFAULT_DENIED_TEXT = "Understood. I did not run it.";
|
|
6
|
+
/** Splits text into words that keep their trailing whitespace. */
|
|
7
|
+
function tokenize(text) {
|
|
8
|
+
return text.match(/\s*\S+\s*/g) ?? (text.length > 0 ? [text] : []);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Turns a reply script into timed steps. Pure: the same script always gives
|
|
12
|
+
* the same steps, which is what makes a streamed story deterministic.
|
|
13
|
+
*/
|
|
14
|
+
function planReply(reply, idPrefix = "call") {
|
|
15
|
+
const firstTokenMs = reply.firstTokenMs ?? DEFAULT_FIRST_TOKEN_MS;
|
|
16
|
+
const tokenMs = reply.tokenMs ?? DEFAULT_TOKEN_MS;
|
|
17
|
+
const steps = [];
|
|
18
|
+
let partCount = 0;
|
|
19
|
+
let pendingDelay = 0;
|
|
20
|
+
const push = (op, delayMs) => {
|
|
21
|
+
const firstDelay = steps.length === 0 ? firstTokenMs : delayMs;
|
|
22
|
+
steps.push({
|
|
23
|
+
delayMs: firstDelay + pendingDelay,
|
|
24
|
+
op
|
|
25
|
+
});
|
|
26
|
+
pendingDelay = 0;
|
|
27
|
+
};
|
|
28
|
+
reply.parts.forEach((part, partIndex) => {
|
|
29
|
+
switch (part.type) {
|
|
30
|
+
case "wait":
|
|
31
|
+
pendingDelay += part.ms;
|
|
32
|
+
return;
|
|
33
|
+
case "text":
|
|
34
|
+
case "reasoning": {
|
|
35
|
+
const [first, ...rest] = tokenize(part.text);
|
|
36
|
+
if (first === void 0) return;
|
|
37
|
+
const index = partCount++;
|
|
38
|
+
push({
|
|
39
|
+
type: "add-part",
|
|
40
|
+
part: {
|
|
41
|
+
type: part.type,
|
|
42
|
+
text: first
|
|
43
|
+
}
|
|
44
|
+
}, tokenMs);
|
|
45
|
+
for (const token of rest) push({
|
|
46
|
+
type: "append-text",
|
|
47
|
+
index,
|
|
48
|
+
text: token
|
|
49
|
+
}, tokenMs);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
case "source":
|
|
53
|
+
partCount++;
|
|
54
|
+
push({
|
|
55
|
+
type: "add-part",
|
|
56
|
+
part: {
|
|
57
|
+
type: "source",
|
|
58
|
+
sourceType: "url",
|
|
59
|
+
id: `${idPrefix}-source-${partIndex}`,
|
|
60
|
+
url: part.url,
|
|
61
|
+
...part.title !== void 0 ? { title: part.title } : {}
|
|
62
|
+
}
|
|
63
|
+
}, tokenMs);
|
|
64
|
+
return;
|
|
65
|
+
case "tool-call": {
|
|
66
|
+
partCount++;
|
|
67
|
+
const toolCallId = part.toolCallId ?? `${idPrefix}-${partIndex}`;
|
|
68
|
+
push({
|
|
69
|
+
type: "add-part",
|
|
70
|
+
part: {
|
|
71
|
+
type: "tool-call",
|
|
72
|
+
toolCallId,
|
|
73
|
+
toolName: part.toolName,
|
|
74
|
+
args: part.args,
|
|
75
|
+
argsText: JSON.stringify(part.args, null, 2),
|
|
76
|
+
...part.approval !== void 0 ? { approval: {
|
|
77
|
+
id: `${toolCallId}-approval`,
|
|
78
|
+
...part.approval.prompt !== void 0 ? { prompt: part.approval.prompt } : {}
|
|
79
|
+
} } : {}
|
|
80
|
+
}
|
|
81
|
+
}, tokenMs);
|
|
82
|
+
if (part.approval !== void 0) push({
|
|
83
|
+
type: "await-approval",
|
|
84
|
+
toolCallId,
|
|
85
|
+
deniedText: part.approval.deniedText ?? DEFAULT_DENIED_TEXT
|
|
86
|
+
}, 0);
|
|
87
|
+
if (part.result !== void 0) push({
|
|
88
|
+
type: "settle-tool",
|
|
89
|
+
toolCallId,
|
|
90
|
+
result: part.result,
|
|
91
|
+
isError: part.isError ?? false
|
|
92
|
+
}, part.durationMs ?? DEFAULT_TOOL_MS);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
return steps;
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
export { planReply, tokenize };
|