@adea-ai/ui 0.140.0 → 0.142.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/dist/components/composites/appearance-editor/appearance-editor.js +2 -2
- package/dist/components/composites/appearance-editor/appearance-editor.js.map +1 -1
- package/dist/components/composites/catalog-browser/catalog-browser-group.js +1 -1
- package/dist/components/composites/chain-of-thought/chain-of-thought.d.ts +56 -0
- package/dist/components/composites/chain-of-thought/chain-of-thought.d.ts.map +1 -0
- package/dist/components/composites/chain-of-thought/chain-of-thought.js +117 -0
- package/dist/components/composites/chain-of-thought/chain-of-thought.js.map +1 -0
- package/dist/components/composites/chain-of-thought/index.d.ts +2 -0
- package/dist/components/composites/chain-of-thought/index.d.ts.map +1 -0
- package/dist/components/composites/chain-of-thought/index.js +2 -0
- package/dist/components/composites/chat/chat.d.ts +67 -0
- package/dist/components/composites/chat/chat.d.ts.map +1 -0
- package/dist/components/composites/chat/chat.js +179 -0
- package/dist/components/composites/chat/chat.js.map +1 -0
- package/dist/components/composites/chat/index.d.ts +2 -0
- package/dist/components/composites/chat/index.d.ts.map +1 -0
- package/dist/components/composites/chat/index.js +2 -0
- package/dist/components/composites/checkpoint/checkpoint-model.d.ts +34 -0
- package/dist/components/composites/checkpoint/checkpoint-model.d.ts.map +1 -0
- package/dist/components/composites/checkpoint/checkpoint-model.js +48 -0
- package/dist/components/composites/checkpoint/checkpoint-model.js.map +1 -0
- package/dist/components/composites/checkpoint/checkpoint.d.ts +48 -0
- package/dist/components/composites/checkpoint/checkpoint.d.ts.map +1 -0
- package/dist/components/composites/checkpoint/checkpoint.js +160 -0
- package/dist/components/composites/checkpoint/checkpoint.js.map +1 -0
- package/dist/components/composites/checkpoint/index.d.ts +3 -0
- package/dist/components/composites/checkpoint/index.d.ts.map +1 -0
- package/dist/components/composites/checkpoint/index.js +3 -0
- package/dist/components/composites/confirmation/confirmation-model.d.ts +45 -0
- package/dist/components/composites/confirmation/confirmation-model.d.ts.map +1 -0
- package/dist/components/composites/confirmation/confirmation-model.js +51 -0
- package/dist/components/composites/confirmation/confirmation-model.js.map +1 -0
- package/dist/components/composites/confirmation/confirmation.d.ts +72 -0
- package/dist/components/composites/confirmation/confirmation.d.ts.map +1 -0
- package/dist/components/composites/confirmation/confirmation.js +300 -0
- package/dist/components/composites/confirmation/confirmation.js.map +1 -0
- package/dist/components/composites/confirmation/index.d.ts +3 -0
- package/dist/components/composites/confirmation/index.d.ts.map +1 -0
- package/dist/components/composites/confirmation/index.js +3 -0
- package/dist/components/composites/context/context-model.d.ts +69 -0
- package/dist/components/composites/context/context-model.d.ts.map +1 -0
- package/dist/components/composites/context/context-model.js +122 -0
- package/dist/components/composites/context/context-model.js.map +1 -0
- package/dist/components/composites/context/context.d.ts +38 -0
- package/dist/components/composites/context/context.d.ts.map +1 -0
- package/dist/components/composites/context/context.js +234 -0
- package/dist/components/composites/context/context.js.map +1 -0
- package/dist/components/composites/context/index.d.ts +3 -0
- package/dist/components/composites/context/index.d.ts.map +1 -0
- package/dist/components/composites/context/index.js +3 -0
- package/dist/components/composites/file-tree/build-file-tree.d.ts +138 -0
- package/dist/components/composites/file-tree/build-file-tree.d.ts.map +1 -0
- package/dist/components/composites/file-tree/build-file-tree.js +325 -0
- package/dist/components/composites/file-tree/build-file-tree.js.map +1 -0
- package/dist/components/composites/file-tree/file-tree.d.ts +74 -0
- package/dist/components/composites/file-tree/file-tree.d.ts.map +1 -0
- package/dist/components/composites/file-tree/file-tree.js +389 -0
- package/dist/components/composites/file-tree/file-tree.js.map +1 -0
- package/dist/components/composites/file-tree/index.d.ts +3 -0
- package/dist/components/composites/file-tree/index.d.ts.map +1 -0
- package/dist/components/composites/file-tree/index.js +3 -0
- package/dist/components/composites/inline-citation/citation.d.ts +37 -0
- package/dist/components/composites/inline-citation/citation.d.ts.map +1 -0
- package/dist/components/composites/inline-citation/citation.js +52 -0
- package/dist/components/composites/inline-citation/citation.js.map +1 -0
- package/dist/components/composites/inline-citation/index.d.ts +3 -0
- package/dist/components/composites/inline-citation/index.d.ts.map +1 -0
- package/dist/components/composites/inline-citation/index.js +3 -0
- package/dist/components/composites/inline-citation/inline-citation.d.ts +64 -0
- package/dist/components/composites/inline-citation/inline-citation.d.ts.map +1 -0
- package/dist/components/composites/inline-citation/inline-citation.js +272 -0
- package/dist/components/composites/inline-citation/inline-citation.js.map +1 -0
- package/dist/components/composites/message-scroller/index.d.ts +3 -0
- package/dist/components/composites/message-scroller/index.d.ts.map +1 -0
- package/dist/components/composites/message-scroller/index.js +3 -0
- package/dist/components/composites/message-scroller/message-scroller.d.ts +55 -0
- package/dist/components/composites/message-scroller/message-scroller.d.ts.map +1 -0
- package/dist/components/composites/message-scroller/message-scroller.js +201 -0
- package/dist/components/composites/message-scroller/message-scroller.js.map +1 -0
- package/dist/components/composites/message-scroller/scroll-anchor.d.ts +66 -0
- package/dist/components/composites/message-scroller/scroll-anchor.d.ts.map +1 -0
- package/dist/components/composites/message-scroller/scroll-anchor.js +122 -0
- package/dist/components/composites/message-scroller/scroll-anchor.js.map +1 -0
- package/dist/components/composites/model-selector/index.d.ts +3 -0
- package/dist/components/composites/model-selector/index.d.ts.map +1 -0
- package/dist/components/composites/model-selector/index.js +3 -0
- package/dist/components/composites/model-selector/model-selector.d.ts +55 -0
- package/dist/components/composites/model-selector/model-selector.d.ts.map +1 -0
- package/dist/components/composites/model-selector/model-selector.js +490 -0
- package/dist/components/composites/model-selector/model-selector.js.map +1 -0
- package/dist/components/composites/model-selector/models.d.ts +51 -0
- package/dist/components/composites/model-selector/models.d.ts.map +1 -0
- package/dist/components/composites/model-selector/models.js +71 -0
- package/dist/components/composites/model-selector/models.js.map +1 -0
- package/dist/components/composites/plan/index.d.ts +2 -0
- package/dist/components/composites/plan/index.d.ts.map +1 -0
- package/dist/components/composites/plan/index.js +2 -0
- package/dist/components/composites/plan/plan.d.ts +61 -0
- package/dist/components/composites/plan/plan.d.ts.map +1 -0
- package/dist/components/composites/plan/plan.js +130 -0
- package/dist/components/composites/plan/plan.js.map +1 -0
- package/dist/components/composites/queue/index.d.ts +2 -0
- package/dist/components/composites/queue/index.d.ts.map +1 -0
- package/dist/components/composites/queue/index.js +2 -0
- package/dist/components/composites/queue/queue.d.ts +77 -0
- package/dist/components/composites/queue/queue.d.ts.map +1 -0
- package/dist/components/composites/queue/queue.js +271 -0
- package/dist/components/composites/queue/queue.js.map +1 -0
- package/dist/components/composites/reasoning/index.d.ts +2 -0
- package/dist/components/composites/reasoning/index.d.ts.map +1 -0
- package/dist/components/composites/reasoning/index.js +2 -0
- package/dist/components/composites/reasoning/reasoning.d.ts +62 -0
- package/dist/components/composites/reasoning/reasoning.d.ts.map +1 -0
- package/dist/components/composites/reasoning/reasoning.js +156 -0
- package/dist/components/composites/reasoning/reasoning.js.map +1 -0
- package/dist/components/composites/sources/index.d.ts +3 -0
- package/dist/components/composites/sources/index.d.ts.map +1 -0
- package/dist/components/composites/sources/index.js +3 -0
- package/dist/components/composites/sources/source.d.ts +46 -0
- package/dist/components/composites/sources/source.d.ts.map +1 -0
- package/dist/components/composites/sources/source.js +74 -0
- package/dist/components/composites/sources/source.js.map +1 -0
- package/dist/components/composites/sources/sources.d.ts +45 -0
- package/dist/components/composites/sources/sources.d.ts.map +1 -0
- package/dist/components/composites/sources/sources.js +175 -0
- package/dist/components/composites/sources/sources.js.map +1 -0
- package/dist/components/composites/stack-trace/index.d.ts +3 -0
- package/dist/components/composites/stack-trace/index.d.ts.map +1 -0
- package/dist/components/composites/stack-trace/index.js +3 -0
- package/dist/components/composites/stack-trace/parse-stack-trace.d.ts +118 -0
- package/dist/components/composites/stack-trace/parse-stack-trace.d.ts.map +1 -0
- package/dist/components/composites/stack-trace/parse-stack-trace.js +376 -0
- package/dist/components/composites/stack-trace/parse-stack-trace.js.map +1 -0
- package/dist/components/composites/stack-trace/stack-trace.d.ts +63 -0
- package/dist/components/composites/stack-trace/stack-trace.d.ts.map +1 -0
- package/dist/components/composites/stack-trace/stack-trace.js +491 -0
- package/dist/components/composites/stack-trace/stack-trace.js.map +1 -0
- package/dist/components/composites/subagent/index.d.ts +2 -0
- package/dist/components/composites/subagent/index.d.ts.map +1 -0
- package/dist/components/composites/subagent/index.js +2 -0
- package/dist/components/composites/subagent/subagent.d.ts +55 -0
- package/dist/components/composites/subagent/subagent.d.ts.map +1 -0
- package/dist/components/composites/subagent/subagent.js +138 -0
- package/dist/components/composites/subagent/subagent.js.map +1 -0
- package/dist/components/composites/suggestion/index.d.ts +2 -0
- package/dist/components/composites/suggestion/index.d.ts.map +1 -0
- package/dist/components/composites/suggestion/index.js +2 -0
- package/dist/components/composites/suggestion/suggestion.d.ts +37 -0
- package/dist/components/composites/suggestion/suggestion.d.ts.map +1 -0
- package/dist/components/composites/suggestion/suggestion.js +100 -0
- package/dist/components/composites/suggestion/suggestion.js.map +1 -0
- package/dist/components/composites/task/index.d.ts +2 -0
- package/dist/components/composites/task/index.d.ts.map +1 -0
- package/dist/components/composites/task/index.js +2 -0
- package/dist/components/composites/task/task.d.ts +96 -0
- package/dist/components/composites/task/task.d.ts.map +1 -0
- package/dist/components/composites/task/task.js +311 -0
- package/dist/components/composites/task/task.js.map +1 -0
- package/dist/components/composites/terminal/ansi.d.ts +101 -0
- package/dist/components/composites/terminal/ansi.d.ts.map +1 -0
- package/dist/components/composites/terminal/ansi.js +544 -0
- package/dist/components/composites/terminal/ansi.js.map +1 -0
- package/dist/components/composites/terminal/index.d.ts +4 -0
- package/dist/components/composites/terminal/index.d.ts.map +1 -0
- package/dist/components/composites/terminal/index.js +4 -0
- package/dist/components/composites/terminal/terminal-model.d.ts +63 -0
- package/dist/components/composites/terminal/terminal-model.d.ts.map +1 -0
- package/dist/components/composites/terminal/terminal-model.js +69 -0
- package/dist/components/composites/terminal/terminal-model.js.map +1 -0
- package/dist/components/composites/terminal/terminal.d.ts +88 -0
- package/dist/components/composites/terminal/terminal.d.ts.map +1 -0
- package/dist/components/composites/terminal/terminal.js +500 -0
- package/dist/components/composites/terminal/terminal.js.map +1 -0
- package/dist/components/composites/test-results/index.d.ts +3 -0
- package/dist/components/composites/test-results/index.d.ts.map +1 -0
- package/dist/components/composites/test-results/index.js +3 -0
- package/dist/components/composites/test-results/test-results-model.d.ts +154 -0
- package/dist/components/composites/test-results/test-results-model.d.ts.map +1 -0
- package/dist/components/composites/test-results/test-results-model.js +252 -0
- package/dist/components/composites/test-results/test-results-model.js.map +1 -0
- package/dist/components/composites/test-results/test-results.d.ts +60 -0
- package/dist/components/composites/test-results/test-results.d.ts.map +1 -0
- package/dist/components/composites/test-results/test-results.js +631 -0
- package/dist/components/composites/test-results/test-results.js.map +1 -0
- package/dist/components/composites/tool/format-tool-value.d.ts +37 -0
- package/dist/components/composites/tool/format-tool-value.d.ts.map +1 -0
- package/dist/components/composites/tool/format-tool-value.js +135 -0
- package/dist/components/composites/tool/format-tool-value.js.map +1 -0
- package/dist/components/composites/tool/index.d.ts +3 -0
- package/dist/components/composites/tool/index.d.ts.map +1 -0
- package/dist/components/composites/tool/index.js +3 -0
- package/dist/components/composites/tool/tool.d.ts +69 -0
- package/dist/components/composites/tool/tool.d.ts.map +1 -0
- package/dist/components/composites/tool/tool.js +214 -0
- package/dist/components/composites/tool/tool.js.map +1 -0
- package/dist/components/composites/update-dialog/update-dialog.js +1 -1
- package/dist/components/conversation/conversation-surface.d.ts +7 -0
- package/dist/components/conversation/conversation-surface.d.ts.map +1 -1
- package/dist/components/conversation/conversation-surface.js +2 -0
- package/dist/components/conversation/conversation-surface.js.map +1 -1
- package/dist/components/conversation/scroll-follow-core.d.ts +24 -0
- package/dist/components/conversation/scroll-follow-core.d.ts.map +1 -1
- package/dist/components/conversation/scroll-follow-core.js +23 -1
- package/dist/components/conversation/scroll-follow-core.js.map +1 -1
- package/dist/components/conversation/scroll-follow.d.ts +3 -0
- package/dist/components/conversation/scroll-follow.d.ts.map +1 -1
- package/dist/components/conversation/scroll-follow.js +80 -1
- package/dist/components/conversation/scroll-follow.js.map +1 -1
- package/dist/components/ui/attachment/attachment.d.ts +58 -0
- package/dist/components/ui/attachment/attachment.d.ts.map +1 -0
- package/dist/components/ui/attachment/attachment.js +279 -0
- package/dist/components/ui/attachment/attachment.js.map +1 -0
- package/dist/components/ui/attachment/index.d.ts +2 -0
- package/dist/components/ui/attachment/index.d.ts.map +1 -0
- package/dist/components/ui/attachment/index.js +2 -0
- package/dist/components/ui/badge/badge.d.ts +1 -1
- package/dist/components/ui/bubble/bubble.d.ts +33 -0
- package/dist/components/ui/bubble/bubble.d.ts.map +1 -0
- package/dist/components/ui/bubble/bubble.js +95 -0
- package/dist/components/ui/bubble/bubble.js.map +1 -0
- package/dist/components/ui/bubble/index.d.ts +2 -0
- package/dist/components/ui/bubble/index.d.ts.map +1 -0
- package/dist/components/ui/bubble/index.js +2 -0
- package/dist/components/ui/button/button.d.ts +1 -1
- package/dist/components/ui/code-block/code-block.d.ts +56 -3
- package/dist/components/ui/code-block/code-block.d.ts.map +1 -1
- package/dist/components/ui/code-block/code-block.js +231 -50
- package/dist/components/ui/code-block/code-block.js.map +1 -1
- package/dist/components/ui/code-block/index.d.ts +1 -1
- package/dist/components/ui/code-block/index.d.ts.map +1 -1
- package/dist/components/ui/code-block/index.js +2 -2
- package/dist/components/ui/field/number-field.d.ts +21 -4
- package/dist/components/ui/field/number-field.d.ts.map +1 -1
- package/dist/components/ui/field/number-field.js +22 -11
- package/dist/components/ui/field/number-field.js.map +1 -1
- package/dist/components/ui/marker/index.d.ts +2 -0
- package/dist/components/ui/marker/index.d.ts.map +1 -0
- package/dist/components/ui/marker/index.js +2 -0
- package/dist/components/ui/marker/marker.d.ts +35 -0
- package/dist/components/ui/marker/marker.d.ts.map +1 -0
- package/dist/components/ui/marker/marker.js +123 -0
- package/dist/components/ui/marker/marker.js.map +1 -0
- package/dist/components/ui/message/cite-ranges.d.ts +42 -0
- package/dist/components/ui/message/cite-ranges.d.ts.map +1 -0
- package/dist/components/ui/message/cite-ranges.js +105 -0
- package/dist/components/ui/message/cite-ranges.js.map +1 -0
- package/dist/components/ui/message/index.d.ts +4 -0
- package/dist/components/ui/message/index.d.ts.map +1 -0
- package/dist/components/ui/message/index.js +4 -0
- package/dist/components/ui/message/message.d.ts +95 -0
- package/dist/components/ui/message/message.d.ts.map +1 -0
- package/dist/components/ui/message/message.js +443 -0
- package/dist/components/ui/message/message.js.map +1 -0
- package/dist/components/ui/message/parse-message-text.d.ts +93 -0
- package/dist/components/ui/message/parse-message-text.d.ts.map +1 -0
- package/dist/components/ui/message/parse-message-text.js +365 -0
- package/dist/components/ui/message/parse-message-text.js.map +1 -0
- package/dist/components/ui/questionnaire/index.d.ts +2 -0
- package/dist/components/ui/questionnaire/index.d.ts.map +1 -0
- package/dist/components/ui/questionnaire/index.js +2 -0
- package/dist/components/ui/questionnaire/questionnaire.d.ts +83 -0
- package/dist/components/ui/questionnaire/questionnaire.d.ts.map +1 -0
- package/dist/components/ui/questionnaire/questionnaire.js +470 -0
- package/dist/components/ui/questionnaire/questionnaire.js.map +1 -0
- package/dist/components/ui/status-chip/status-chip.d.ts +1 -1
- package/dist/components/ui/switch/switch.js +11 -11
- package/dist/components/ui/switch/switch.js.map +1 -1
- package/dist/components/ui/trace/index.d.ts +2 -0
- package/dist/components/ui/trace/index.d.ts.map +1 -0
- package/dist/components/ui/trace/index.js +2 -0
- package/dist/components/ui/trace/trace.d.ts +72 -0
- package/dist/components/ui/trace/trace.d.ts.map +1 -0
- package/dist/components/ui/trace/trace.js +340 -0
- package/dist/components/ui/trace/trace.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +46 -5
- package/dist/r/attachment.json +25 -0
- package/dist/r/bubble.json +22 -0
- package/dist/r/chain-of-thought.json +26 -0
- package/dist/r/chat.json +24 -0
- package/dist/r/checkpoint.json +35 -0
- package/dist/r/confirmation.json +34 -0
- package/dist/r/context.json +33 -0
- package/dist/r/file-tree.json +32 -0
- package/dist/r/inline-citation.json +35 -0
- package/dist/r/marker.json +22 -0
- package/dist/r/message-scroller.json +31 -0
- package/dist/r/message.json +33 -0
- package/dist/r/model-selector.json +34 -0
- package/dist/r/plan.json +26 -0
- package/dist/r/questionnaire.json +28 -0
- package/dist/r/queue.json +26 -0
- package/dist/r/reasoning.json +26 -0
- package/dist/r/registry.json +811 -52
- package/dist/r/sources.json +32 -0
- package/dist/r/src/components/composites/chain-of-thought/chain-of-thought.tsx +141 -0
- package/dist/r/src/components/composites/chain-of-thought/index.ts +11 -0
- package/dist/r/src/components/composites/chat/chat.tsx +190 -0
- package/dist/r/src/components/composites/chat/index.ts +11 -0
- package/dist/r/src/components/composites/checkpoint/checkpoint-model.ts +71 -0
- package/dist/r/src/components/composites/checkpoint/checkpoint.tsx +214 -0
- package/dist/r/src/components/composites/checkpoint/index.ts +8 -0
- package/dist/r/src/components/composites/confirmation/confirmation-model.ts +83 -0
- package/dist/r/src/components/composites/confirmation/confirmation.tsx +311 -0
- package/dist/r/src/components/composites/confirmation/index.ts +9 -0
- package/dist/r/src/components/composites/context/context-model.ts +168 -0
- package/dist/r/src/components/composites/context/context.tsx +187 -0
- package/dist/r/src/components/composites/context/index.ts +18 -0
- package/dist/r/src/components/composites/file-tree/build-file-tree.ts +456 -0
- package/dist/r/src/components/composites/file-tree/file-tree.tsx +405 -0
- package/dist/r/src/components/composites/file-tree/index.ts +25 -0
- package/dist/r/src/components/composites/inline-citation/citation.ts +78 -0
- package/dist/r/src/components/composites/inline-citation/index.ts +9 -0
- package/dist/r/src/components/composites/inline-citation/inline-citation.tsx +285 -0
- package/dist/r/src/components/composites/message-scroller/index.ts +2 -0
- package/dist/r/src/components/composites/message-scroller/message-scroller.tsx +301 -0
- package/dist/r/src/components/composites/message-scroller/scroll-anchor.ts +170 -0
- package/dist/r/src/components/composites/model-selector/index.ts +14 -0
- package/dist/r/src/components/composites/model-selector/model-selector.tsx +420 -0
- package/dist/r/src/components/composites/model-selector/models.ts +103 -0
- package/dist/r/src/components/composites/plan/index.ts +1 -0
- package/dist/r/src/components/composites/plan/plan.tsx +155 -0
- package/dist/r/src/components/composites/queue/index.ts +10 -0
- package/dist/r/src/components/composites/queue/queue.tsx +264 -0
- package/dist/r/src/components/composites/reasoning/index.ts +1 -0
- package/dist/r/src/components/composites/reasoning/reasoning.tsx +176 -0
- package/dist/r/src/components/composites/sources/index.ts +11 -0
- package/dist/r/src/components/composites/sources/source.ts +116 -0
- package/dist/r/src/components/composites/sources/sources.tsx +163 -0
- package/dist/r/src/components/composites/stack-trace/index.ts +19 -0
- package/dist/r/src/components/composites/stack-trace/parse-stack-trace.ts +507 -0
- package/dist/r/src/components/composites/stack-trace/stack-trace.tsx +395 -0
- package/dist/r/src/components/composites/subagent/index.ts +1 -0
- package/dist/r/src/components/composites/subagent/subagent.tsx +159 -0
- package/dist/r/src/components/composites/suggestion/index.ts +1 -0
- package/dist/r/src/components/composites/suggestion/suggestion.tsx +140 -0
- package/dist/r/src/components/composites/task/index.ts +14 -0
- package/dist/r/src/components/composites/task/task.tsx +317 -0
- package/dist/r/src/components/composites/terminal/ansi.ts +674 -0
- package/dist/r/src/components/composites/terminal/index.ts +20 -0
- package/dist/r/src/components/composites/terminal/terminal-model.ts +111 -0
- package/dist/r/src/components/composites/terminal/terminal.tsx +574 -0
- package/dist/r/src/components/composites/test-results/index.ts +20 -0
- package/dist/r/src/components/composites/test-results/test-results-model.ts +368 -0
- package/dist/r/src/components/composites/test-results/test-results.tsx +586 -0
- package/dist/r/src/components/composites/tool/format-tool-value.ts +221 -0
- package/dist/r/src/components/composites/tool/index.ts +2 -0
- package/dist/r/src/components/composites/tool/tool.tsx +228 -0
- package/dist/r/src/components/conversation/conversation-surface.tsx +9 -0
- package/dist/r/src/components/conversation/scroll-follow-core.ts +31 -0
- package/dist/r/src/components/conversation/scroll-follow.ts +92 -0
- package/dist/r/src/components/ui/attachment/attachment.tsx +282 -0
- package/dist/r/src/components/ui/attachment/index.ts +10 -0
- package/dist/r/src/components/ui/bubble/bubble.tsx +86 -0
- package/dist/r/src/components/ui/bubble/index.ts +1 -0
- package/dist/r/src/components/ui/code-block/code-block.tsx +256 -26
- package/dist/r/src/components/ui/code-block/index.ts +9 -1
- package/dist/r/src/components/ui/field/number-field.tsx +51 -14
- package/dist/r/src/components/ui/marker/index.ts +1 -0
- package/dist/r/src/components/ui/marker/marker.tsx +90 -0
- package/dist/r/src/components/ui/message/cite-ranges.ts +144 -0
- package/dist/r/src/components/ui/message/index.ts +23 -0
- package/dist/r/src/components/ui/message/message.tsx +434 -0
- package/dist/r/src/components/ui/message/parse-message-text.ts +450 -0
- package/dist/r/src/components/ui/questionnaire/index.ts +10 -0
- package/dist/r/src/components/ui/questionnaire/questionnaire.tsx +446 -0
- package/dist/r/src/components/ui/trace/index.ts +9 -0
- package/dist/r/src/components/ui/trace/trace.tsx +334 -0
- package/dist/r/src/styles/base.css +34 -0
- package/dist/r/stack-trace.json +32 -0
- package/dist/r/subagent.json +27 -0
- package/dist/r/suggestion.json +24 -0
- package/dist/r/task.json +28 -0
- package/dist/r/terminal.json +35 -0
- package/dist/r/test-results.json +33 -0
- package/dist/r/tool.json +31 -0
- package/dist/r/trace.json +25 -0
- package/package.json +6 -3
- package/registry.json +811 -52
- package/src/components/composites/chain-of-thought/chain-of-thought.tsx +141 -0
- package/src/components/composites/chain-of-thought/index.ts +11 -0
- package/src/components/composites/chat/chat.tsx +190 -0
- package/src/components/composites/chat/index.ts +11 -0
- package/src/components/composites/checkpoint/checkpoint-model.ts +71 -0
- package/src/components/composites/checkpoint/checkpoint.tsx +214 -0
- package/src/components/composites/checkpoint/index.ts +8 -0
- package/src/components/composites/confirmation/confirmation-model.ts +83 -0
- package/src/components/composites/confirmation/confirmation.tsx +311 -0
- package/src/components/composites/confirmation/index.ts +9 -0
- package/src/components/composites/context/context-model.ts +168 -0
- package/src/components/composites/context/context.tsx +187 -0
- package/src/components/composites/context/index.ts +18 -0
- package/src/components/composites/file-tree/build-file-tree.ts +456 -0
- package/src/components/composites/file-tree/file-tree.tsx +405 -0
- package/src/components/composites/file-tree/index.ts +25 -0
- package/src/components/composites/inline-citation/citation.ts +78 -0
- package/src/components/composites/inline-citation/index.ts +9 -0
- package/src/components/composites/inline-citation/inline-citation.tsx +285 -0
- package/src/components/composites/message-scroller/index.ts +2 -0
- package/src/components/composites/message-scroller/message-scroller.tsx +301 -0
- package/src/components/composites/message-scroller/scroll-anchor.ts +170 -0
- package/src/components/composites/model-selector/index.ts +14 -0
- package/src/components/composites/model-selector/model-selector.tsx +420 -0
- package/src/components/composites/model-selector/models.ts +103 -0
- package/src/components/composites/plan/index.ts +1 -0
- package/src/components/composites/plan/plan.tsx +155 -0
- package/src/components/composites/queue/index.ts +10 -0
- package/src/components/composites/queue/queue.tsx +264 -0
- package/src/components/composites/reasoning/index.ts +1 -0
- package/src/components/composites/reasoning/reasoning.tsx +176 -0
- package/src/components/composites/sources/index.ts +11 -0
- package/src/components/composites/sources/source.ts +116 -0
- package/src/components/composites/sources/sources.tsx +163 -0
- package/src/components/composites/stack-trace/index.ts +19 -0
- package/src/components/composites/stack-trace/parse-stack-trace.ts +507 -0
- package/src/components/composites/stack-trace/stack-trace.tsx +395 -0
- package/src/components/composites/subagent/index.ts +1 -0
- package/src/components/composites/subagent/subagent.tsx +159 -0
- package/src/components/composites/suggestion/index.ts +1 -0
- package/src/components/composites/suggestion/suggestion.tsx +140 -0
- package/src/components/composites/task/index.ts +14 -0
- package/src/components/composites/task/task.tsx +317 -0
- package/src/components/composites/terminal/ansi.ts +674 -0
- package/src/components/composites/terminal/index.ts +20 -0
- package/src/components/composites/terminal/terminal-model.ts +111 -0
- package/src/components/composites/terminal/terminal.tsx +574 -0
- package/src/components/composites/test-results/index.ts +20 -0
- package/src/components/composites/test-results/test-results-model.ts +368 -0
- package/src/components/composites/test-results/test-results.tsx +586 -0
- package/src/components/composites/tool/format-tool-value.ts +221 -0
- package/src/components/composites/tool/index.ts +2 -0
- package/src/components/composites/tool/tool.tsx +228 -0
- package/src/components/conversation/conversation-surface.tsx +9 -0
- package/src/components/conversation/scroll-follow-core.ts +31 -0
- package/src/components/conversation/scroll-follow.ts +92 -0
- package/src/components/ui/attachment/attachment.tsx +282 -0
- package/src/components/ui/attachment/index.ts +10 -0
- package/src/components/ui/bubble/bubble.tsx +86 -0
- package/src/components/ui/bubble/index.ts +1 -0
- package/src/components/ui/code-block/code-block.tsx +256 -26
- package/src/components/ui/code-block/index.ts +9 -1
- package/src/components/ui/field/number-field.tsx +51 -14
- package/src/components/ui/marker/index.ts +1 -0
- package/src/components/ui/marker/marker.tsx +90 -0
- package/src/components/ui/message/cite-ranges.ts +144 -0
- package/src/components/ui/message/index.ts +23 -0
- package/src/components/ui/message/message.tsx +434 -0
- package/src/components/ui/message/parse-message-text.ts +450 -0
- package/src/components/ui/questionnaire/index.ts +10 -0
- package/src/components/ui/questionnaire/questionnaire.tsx +446 -0
- package/src/components/ui/trace/index.ts +9 -0
- package/src/components/ui/trace/trace.tsx +334 -0
- package/src/index.ts +26 -0
- package/src/styles/base.css +34 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sources.js","names":["BookOpen","createSignal","For","Show","splitProps","Button","TextLink","Trace","TraceDetail","TraceLine","TraceProps","SOURCE_SNIPPET_LIMIT","boundText","safeSourceUrl","sourceHost","sourceTitle","sourcesLabel","Source","SourcesProps","Omit","sources","label","open","defaultOpen","onOpenChange","initialVisible","DEFAULT_VISIBLE","Sources","props","local","rest","expanded","setExpanded","limit","Math","max","floor","hidden","length","visible","slice","_$createComponent","when","children","_$mergeProps","icon","title","_el$","_tmpl$","_$insert","each","source","index","SourceRow","position","type","variant","size","aria-expanded","onClick","value","_$memo","href","url","host","snippet","withheld","undefined","_el$2","_tmpl$4","_el$3","firstChild","_el$4","nextSibling","fallback","_el$7","_tmpl$5","_el$8","_el$9","_el$1","_el$0","target","rel","_el$10","_tmpl$6","_el$11","_el$13","_el$12","_tmpl$7","_el$5","_tmpl$2","_el$6","_tmpl$3","_$createComponent","_$mergeProps","_$memo"],"sources":["../../../../src/components/composites/sources/sources.tsx"],"sourcesContent":["import { BookOpen } from 'lucide-solid'\nimport { createSignal, For, Show, splitProps } from 'solid-js'\nimport { Button } from '../../ui/button'\nimport { TextLink } from '../../ui/text-link'\nimport { Trace, TraceDetail, TraceLine, type TraceProps } from '../../ui/trace'\nimport {\n SOURCE_SNIPPET_LIMIT,\n boundText,\n safeSourceUrl,\n sourceHost,\n sourceTitle,\n sourcesLabel,\n type Source,\n} from './source'\n\n/**\n * Sources.\n *\n * The links a reply used, as one `Trace` line — \"Used 4 sources\" — that expands\n * into the list. It lives under the answer with the rest of the agent's activity\n * rather than as a card of its own, because a reader who wants to check a claim\n * will open it and one who does not should not have to scroll past it. For a\n * marker inside a sentence use `InlineCitation`, which points at the same\n * `Source` shape; the two are numbered the same way (position in this list).\n *\n * ## What it will and will not say\n *\n * - **No sources, no line.** An empty list renders nothing: \"Used 0 sources\" is a\n * claim about an answer that may simply not have been grounded.\n * - **A row is a link only with a safe address.** `http:`, `https:` and `mailto:`\n * without embedded credentials (`safeSourceUrl`). Any other address is not\n * linked and not printed — the row says the address was not linked, so the\n * reader knows something was withheld instead of finding a dead title.\n * - **The host is read from the parsed URL**, never from the title, so a title\n * that reads \"docs.example.com\" cannot make a link to somewhere else look like it.\n * - **Nothing is merged.** Two entries that share a URL are two rows, with their\n * own numbers; the host may have cited two passages and the citations point at\n * positions.\n * - **Hostile and long values are bounded.** Titles, hosts and snippets are\n * clipped and stripped of direction overrides (`boundText`), and are only ever\n * text nodes.\n * - **A long list is shown in pages.** Past `initialVisible` the rest is behind a\n * button that names how many there are, so a 200-source answer is not 200 rows\n * the moment it opens. The button stays in place and toggles, so focus is never\n * left on a control that has just disappeared.\n */\nexport type SourcesProps = Omit<TraceProps, 'children'> & {\n sources: readonly Source[]\n /** Replaces the default \"Used N sources\" for another language or a different verb. */\n label?: string\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n /** Rows shown before the \"Show all\" button. Default 25. */\n initialVisible?: number\n}\n\nconst DEFAULT_VISIBLE = 25\n\nexport function Sources(props: SourcesProps) {\n const [local, rest] = splitProps(props, [\n 'sources',\n 'label',\n 'open',\n 'defaultOpen',\n 'onOpenChange',\n 'initialVisible',\n ])\n const [expanded, setExpanded] = createSignal(false)\n const limit = () => Math.max(1, Math.floor(local.initialVisible ?? DEFAULT_VISIBLE))\n const hidden = () => Math.max(0, local.sources.length - limit())\n const visible = () => (expanded() ? local.sources : local.sources.slice(0, limit()))\n\n return (\n <Show when={local.sources.length > 0}>\n <Trace aria-label=\"Sources\" data-slot=\"sources\" {...rest}>\n <TraceLine\n icon={<BookOpen />}\n title={local.label ?? sourcesLabel(local.sources.length)}\n open={local.open}\n defaultOpen={local.defaultOpen}\n onOpenChange={local.onOpenChange}\n >\n <TraceDetail>\n <ol class=\"m-0 flex list-none flex-col gap-2 p-0\" aria-label=\"Sources used\">\n <For each={visible()}>\n {(source, index) => <SourceRow source={source} position={index() + 1} />}\n </For>\n </ol>\n <Show when={hidden() > 0}>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"xs\"\n class=\"mt-1\"\n aria-expanded={expanded()}\n onClick={() => setExpanded((value) => !value)}\n >\n {expanded() ? 'Show fewer sources' : `Show all ${local.sources.length} sources`}\n </Button>\n </Show>\n </TraceDetail>\n </TraceLine>\n </Trace>\n </Show>\n )\n}\n\nfunction SourceRow(props: { source: Source; position: number }) {\n const href = () => safeSourceUrl(props.source.url)\n const host = () => sourceHost(props.source.url)\n const title = () => sourceTitle(props.source)\n const snippet = () =>\n props.source.snippet ? boundText(props.source.snippet, SOURCE_SNIPPET_LIMIT) : ''\n // An address was supplied but is not one we link: say so rather than go silent.\n const withheld = () => props.source.url !== undefined && props.source.url !== '' && !href()\n\n return (\n <li data-slot=\"source\" class=\"flex min-w-0 items-baseline gap-2\">\n <span\n aria-hidden=\"true\"\n class=\"w-5 shrink-0 text-end text-xs text-muted-foreground tabular-nums\"\n >\n {props.position}\n </span>\n <div class=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n <Show\n when={href()}\n fallback={\n <span class=\"text-sm text-foreground [overflow-wrap:anywhere]\">\n <span class=\"visually-hidden\">Source {props.position}: </span>\n {title()}\n </span>\n }\n >\n {(url) => (\n <TextLink\n href={url()}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n class=\"w-fit max-w-full text-sm [overflow-wrap:anywhere]\"\n >\n <span class=\"visually-hidden\">Source {props.position}: </span>\n {title()}\n <span class=\"visually-hidden\"> (opens in a new tab)</span>\n </TextLink>\n )}\n </Show>\n <Show when={host() || withheld()}>\n <span class=\"text-xs text-muted-foreground [overflow-wrap:anywhere]\">\n {host()}\n <Show when={withheld()}>{host() ? ' · ' : ''}Address not linked</Show>\n </span>\n </Show>\n <Show when={snippet()}>\n <p class=\"m-0 line-clamp-3 text-xs text-muted-foreground [overflow-wrap:anywhere]\">\n {snippet()}\n </p>\n </Show>\n </div>\n </li>\n )\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { StackTrace, STACK_TRACE_MAX_BLOCKS, type StackTraceProps } from './stack-trace';
|
|
2
|
+
export { classifyFrame, dedentLines, describeFrameGroup, frameLocation, groupStackEntries, parseStackTrace, splitLocation, STACK_MAX_LINES, type ParsedStackTrace, type ParseStackTraceOptions, type StackBlock, type StackEntry, type StackFrame, type StackFrameKind, type StackTraceFormat, type StackTraceHeader, } from './parse-stack-trace';
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/stack-trace/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAA;AACxF,OAAO,EACL,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,eAAe,EACf,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACtB,MAAM,qBAAqB,CAAA"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { STACK_MAX_LINES, classifyFrame, dedentLines, describeFrameGroup, frameLocation, groupStackEntries, parseStackTrace, splitLocation } from "./parse-stack-trace.js";
|
|
2
|
+
import { STACK_TRACE_MAX_BLOCKS, StackTrace } from "./stack-trace.js";
|
|
3
|
+
export { STACK_MAX_LINES, STACK_TRACE_MAX_BLOCKS, StackTrace, classifyFrame, dedentLines, describeFrameGroup, frameLocation, groupStackEntries, parseStackTrace, splitLocation };
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stack traces, read without being trusted or trimmed.
|
|
3
|
+
*
|
|
4
|
+
* A trace is text a runtime wrote about itself, and every language writes it
|
|
5
|
+
* differently. This parses the three a coding agent meets most — V8/Node
|
|
6
|
+
* (`at fn (file:line:col)`), Python (`File "x", line N, in fn`) and Rust panic
|
|
7
|
+
* backtraces (` 0: symbol` then `at file:line:col`) — into frames, and does
|
|
8
|
+
* three things a formatter would not:
|
|
9
|
+
*
|
|
10
|
+
* - **It never hides a line.** Every input line ends up in `entries`, as a frame
|
|
11
|
+
* or as text, in order. A line the parser does not recognise is text, and a
|
|
12
|
+
* trace it recognises nothing in has `format: 'unknown'` and `frames: []`, so a
|
|
13
|
+
* caller falls back to showing the raw string. The header (error type and
|
|
14
|
+
* message) is lifted out of the entries only when it is unambiguous.
|
|
15
|
+
* - **It makes no claim about whose code a frame is without evidence.** A frame
|
|
16
|
+
* is a dependency when its path says so (`node_modules`, `site-packages`,
|
|
17
|
+
* `.cargo/registry`), internal when it belongs to the runtime (`node:` URLs,
|
|
18
|
+
* Python's frozen modules, Rust's `std`), and first-party otherwise. A host that
|
|
19
|
+
* knows better passes `classify`.
|
|
20
|
+
* - **It is bounded.** Lines over 4 000 characters are never run through a
|
|
21
|
+
* pattern, and input past 10 000 lines is kept as one trailing text entry. Every
|
|
22
|
+
* pattern is anchored and linear, so a hostile trace cannot make parsing slow.
|
|
23
|
+
*
|
|
24
|
+
* Parsing is line-oriented and each line is classified on its own, so a trace
|
|
25
|
+
* that mixes formats (a Node process that shells out to Python) keeps both.
|
|
26
|
+
*/
|
|
27
|
+
export type StackFrameKind = 'first-party' | 'dependency' | 'internal';
|
|
28
|
+
export type StackTraceFormat = 'v8' | 'python' | 'rust' | 'unknown';
|
|
29
|
+
export type StackFrame = Readonly<{
|
|
30
|
+
/** The line exactly as written, minus its line ending. */
|
|
31
|
+
raw: string;
|
|
32
|
+
function?: string;
|
|
33
|
+
/** The path or URL as written. Undefined for `<anonymous>`, `native` and the like. */
|
|
34
|
+
file?: string;
|
|
35
|
+
line?: number;
|
|
36
|
+
column?: number;
|
|
37
|
+
kind: StackFrameKind;
|
|
38
|
+
async?: true;
|
|
39
|
+
/** Lines the runtime printed beneath the frame, such as Python's source line. */
|
|
40
|
+
detail?: readonly string[];
|
|
41
|
+
}>;
|
|
42
|
+
export type StackEntry = Readonly<{
|
|
43
|
+
type: 'frame';
|
|
44
|
+
frame: StackFrame;
|
|
45
|
+
}> | Readonly<{
|
|
46
|
+
type: 'text';
|
|
47
|
+
text: string;
|
|
48
|
+
}>;
|
|
49
|
+
export type StackTraceHeader = Readonly<{
|
|
50
|
+
/** `TypeError`, `ValueError`, `thread 'main' panicked`. */
|
|
51
|
+
type?: string;
|
|
52
|
+
message: string;
|
|
53
|
+
/** Where a Rust panic says it happened. */
|
|
54
|
+
location?: string;
|
|
55
|
+
}>;
|
|
56
|
+
export type ParsedStackTrace = Readonly<{
|
|
57
|
+
format: StackTraceFormat;
|
|
58
|
+
header?: StackTraceHeader;
|
|
59
|
+
/** Everything that is not the header, in order. */
|
|
60
|
+
entries: readonly StackEntry[];
|
|
61
|
+
frames: readonly StackFrame[];
|
|
62
|
+
}>;
|
|
63
|
+
export type ParseStackTraceOptions = {
|
|
64
|
+
/** Override the built-in first-party/dependency/internal guess for a frame. */
|
|
65
|
+
classify?: (frame: StackFrame) => StackFrameKind | undefined;
|
|
66
|
+
};
|
|
67
|
+
export declare const STACK_MAX_LINES = 10000;
|
|
68
|
+
/** Split `path:line:col` from the right, so a Windows drive or a URL port stays in the path. */
|
|
69
|
+
export declare function splitLocation(location: string): {
|
|
70
|
+
file: string;
|
|
71
|
+
line?: number;
|
|
72
|
+
column?: number;
|
|
73
|
+
};
|
|
74
|
+
/** The built-in guess at whose code a frame is. See the module comment. */
|
|
75
|
+
export declare function classifyFrame(frame: Omit<StackFrame, 'kind'>, format: StackTraceFormat): StackFrameKind;
|
|
76
|
+
/** Parse a stack trace. Never throws, and every input line appears in the result. */
|
|
77
|
+
export declare function parseStackTrace(text: string, options?: ParseStackTraceOptions): ParsedStackTrace;
|
|
78
|
+
export type StackBlock = Readonly<{
|
|
79
|
+
type: 'frame';
|
|
80
|
+
frame: StackFrame;
|
|
81
|
+
}> | Readonly<{
|
|
82
|
+
type: 'text';
|
|
83
|
+
text: string;
|
|
84
|
+
}> | Readonly<{
|
|
85
|
+
type: 'group';
|
|
86
|
+
frames: readonly StackFrame[];
|
|
87
|
+
}>;
|
|
88
|
+
/**
|
|
89
|
+
* Fold runs of dependency and runtime frames into groups, so a trace reads as
|
|
90
|
+
* the code the reader owns with the framework's frames one click away.
|
|
91
|
+
*
|
|
92
|
+
* A run of one stays a frame — a disclosure around a single line costs more than
|
|
93
|
+
* it saves. When there is no first-party frame at all nothing is grouped:
|
|
94
|
+
* collapsing everything would hide the entire trace behind a button, which is the
|
|
95
|
+
* opposite of what a reader who owns none of the frames needs.
|
|
96
|
+
*/
|
|
97
|
+
export declare function groupStackEntries(entries: readonly StackEntry[], collapse?: boolean): readonly StackBlock[];
|
|
98
|
+
/** What a collapsed group says it holds. */
|
|
99
|
+
export declare function describeFrameGroup(frames: readonly StackFrame[]): string;
|
|
100
|
+
/** `file:line:col`, with whichever parts the frame has. */
|
|
101
|
+
export declare function frameLocation(frame: StackFrame): string | undefined;
|
|
102
|
+
/** Remove the indentation every non-blank line shares, so a source snippet sits flush. */
|
|
103
|
+
export declare function dedentLines(lines: readonly string[]): string[];
|
|
104
|
+
export type BoundedLines = Readonly<{
|
|
105
|
+
lines: string[];
|
|
106
|
+
/** Lines beyond the bound that are not in `lines` at all. */
|
|
107
|
+
omittedLines: number;
|
|
108
|
+
/** Characters beyond the bound, in omitted lines and in the cut end of the last shown line. */
|
|
109
|
+
omittedChars: number;
|
|
110
|
+
}>;
|
|
111
|
+
/**
|
|
112
|
+
* The first lines of `lines`, up to `maxLines` of them and `maxChars` characters
|
|
113
|
+
* between them, with what was left out counted rather than dropped silently. It
|
|
114
|
+
* visits the shown lines and adds up the length of the rest, so the cost does not
|
|
115
|
+
* depend on how much text there is to omit.
|
|
116
|
+
*/
|
|
117
|
+
export declare function boundLines(lines: readonly string[], maxLines: number, maxChars: number): BoundedLines;
|
|
118
|
+
//# sourceMappingURL=parse-stack-trace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-stack-trace.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/stack-trace/parse-stack-trace.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
//#region src/components/composites/stack-trace/parse-stack-trace.ts
|
|
2
|
+
var STACK_MAX_LINES = 1e4;
|
|
3
|
+
var LINE_PATTERN_LIMIT = 4e3;
|
|
4
|
+
function trailingNumber(value) {
|
|
5
|
+
let i = value.length;
|
|
6
|
+
while (i > 0 && value.charCodeAt(i - 1) >= 48 && value.charCodeAt(i - 1) <= 57) i -= 1;
|
|
7
|
+
if (i === value.length || i === 0 || value[i - 1] !== ":" || value.length - i > 9) return void 0;
|
|
8
|
+
return {
|
|
9
|
+
value: Number(value.slice(i)),
|
|
10
|
+
rest: value.slice(0, i - 1)
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/** Split `path:line:col` from the right, so a Windows drive or a URL port stays in the path. */
|
|
14
|
+
function splitLocation(location) {
|
|
15
|
+
const last = trailingNumber(location);
|
|
16
|
+
if (!last || last.rest === "") return { file: location };
|
|
17
|
+
const before = trailingNumber(last.rest);
|
|
18
|
+
if (before && before.rest !== "") return {
|
|
19
|
+
file: before.rest,
|
|
20
|
+
line: before.value,
|
|
21
|
+
column: last.value
|
|
22
|
+
};
|
|
23
|
+
return {
|
|
24
|
+
file: last.rest,
|
|
25
|
+
line: last.value
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
var FILE_LIKE = /[\\/]|\.[A-Za-z0-9]{1,6}$/;
|
|
29
|
+
var URL_LIKE = /^node:/i;
|
|
30
|
+
/** Whether a V8 location is a place in a file rather than a runtime annotation. */
|
|
31
|
+
function v8Location(location) {
|
|
32
|
+
if (location === "<anonymous>" || location === "native" || /^index \d+$/.test(location)) return {};
|
|
33
|
+
if (location.startsWith("eval at ")) return {};
|
|
34
|
+
const split = splitLocation(location);
|
|
35
|
+
if (split.line !== void 0 || FILE_LIKE.test(split.file) || URL_LIKE.test(split.file)) return {
|
|
36
|
+
file: split.file,
|
|
37
|
+
line: split.line,
|
|
38
|
+
column: split.column
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function parseV8(trimmed) {
|
|
42
|
+
if (!trimmed.startsWith("at ")) return void 0;
|
|
43
|
+
const rest = trimmed.slice(3);
|
|
44
|
+
if (rest === "") return void 0;
|
|
45
|
+
let fn;
|
|
46
|
+
let location;
|
|
47
|
+
if (rest.endsWith(")") && rest.includes(" (")) {
|
|
48
|
+
const open = rest.indexOf(" (");
|
|
49
|
+
fn = rest.slice(0, open);
|
|
50
|
+
location = rest.slice(open + 2, -1);
|
|
51
|
+
} else location = rest;
|
|
52
|
+
const parsed = v8Location(location);
|
|
53
|
+
if (!parsed) return void 0;
|
|
54
|
+
if (fn === void 0 && parsed.file === void 0 && location !== "<anonymous>" && location !== "native") return;
|
|
55
|
+
const draft = {
|
|
56
|
+
raw: trimmed,
|
|
57
|
+
format: "v8",
|
|
58
|
+
...parsed
|
|
59
|
+
};
|
|
60
|
+
if (fn !== void 0) {
|
|
61
|
+
if (fn.startsWith("async ")) {
|
|
62
|
+
draft.async = true;
|
|
63
|
+
fn = fn.slice(6);
|
|
64
|
+
}
|
|
65
|
+
if (fn !== "") draft.function = fn;
|
|
66
|
+
}
|
|
67
|
+
return draft;
|
|
68
|
+
}
|
|
69
|
+
var PYTHON_FRAME = /^File "(.*)", line (\d+)(?:, in (.*))?$/;
|
|
70
|
+
function parsePython(trimmed) {
|
|
71
|
+
const match = PYTHON_FRAME.exec(trimmed);
|
|
72
|
+
if (!match) return void 0;
|
|
73
|
+
const draft = {
|
|
74
|
+
raw: trimmed,
|
|
75
|
+
format: "python",
|
|
76
|
+
file: match[1],
|
|
77
|
+
line: Number(match[2])
|
|
78
|
+
};
|
|
79
|
+
if (match[3]) draft.function = match[3];
|
|
80
|
+
return draft;
|
|
81
|
+
}
|
|
82
|
+
var RUST_FRAME = /^(\d+):\s+(?:0x[0-9a-fA-F]+ - )?(\S.*)$/;
|
|
83
|
+
var RUST_LOCATION = /^at\s+(\S.*)$/;
|
|
84
|
+
function parseRustFrame(trimmed, rustContext) {
|
|
85
|
+
const match = RUST_FRAME.exec(trimmed);
|
|
86
|
+
if (!match) return void 0;
|
|
87
|
+
const symbol = match[2];
|
|
88
|
+
if (!rustContext && !symbol.includes("::")) return void 0;
|
|
89
|
+
return {
|
|
90
|
+
raw: trimmed,
|
|
91
|
+
format: "rust",
|
|
92
|
+
function: symbol
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
var INTERNAL_RUST_SYMBOLS = /^(?:std|core|alloc)::|^<?(?:\w+ as )?(?:std|core|alloc)::|^(?:rust_begin_unwind|rust_panic|__rust_|_start$|__libc_|_main$)/;
|
|
96
|
+
/** The built-in guess at whose code a frame is. See the module comment. */
|
|
97
|
+
function classifyFrame(frame, format) {
|
|
98
|
+
const file = frame.file?.replaceAll("\\", "/");
|
|
99
|
+
if (format === "rust") {
|
|
100
|
+
if (file !== void 0) {
|
|
101
|
+
if (file.startsWith("/rustc/") || /\/library\/(?:std|core|alloc)\//.test(file)) return "internal";
|
|
102
|
+
if (/\/\.cargo\/(?:registry|git)\/|\/registry\/src\//.test(file)) return "dependency";
|
|
103
|
+
return "first-party";
|
|
104
|
+
}
|
|
105
|
+
return frame.function !== void 0 && INTERNAL_RUST_SYMBOLS.test(frame.function) ? "internal" : "first-party";
|
|
106
|
+
}
|
|
107
|
+
if (file === void 0) return "internal";
|
|
108
|
+
if (format === "python") {
|
|
109
|
+
if (/\/(?:site|dist)-packages\//.test(file)) return "dependency";
|
|
110
|
+
if (file.startsWith("<") || /\/lib\/python\d/i.test(file) || /\/python\d[\d.]*\/lib\//i.test(file)) return "internal";
|
|
111
|
+
return "first-party";
|
|
112
|
+
}
|
|
113
|
+
if (file.startsWith("node:") || file.startsWith("internal/") || file.startsWith("wasm://")) return "internal";
|
|
114
|
+
if (file.includes("/node_modules/") || file.startsWith("node_modules/")) return "dependency";
|
|
115
|
+
return "first-party";
|
|
116
|
+
}
|
|
117
|
+
function finishFrame(draft, options) {
|
|
118
|
+
const { format, detail, ...base } = draft;
|
|
119
|
+
const shape = detail && detail.length > 0 ? {
|
|
120
|
+
...base,
|
|
121
|
+
detail
|
|
122
|
+
} : base;
|
|
123
|
+
const guess = classifyFrame(shape, format);
|
|
124
|
+
const override = options?.classify?.({
|
|
125
|
+
...shape,
|
|
126
|
+
kind: guess
|
|
127
|
+
});
|
|
128
|
+
return {
|
|
129
|
+
...shape,
|
|
130
|
+
kind: override ?? guess
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
var TYPE_AND_MESSAGE = /^([A-Za-z_$][\w$.]*)(?::\s?([\s\S]*))?$/;
|
|
134
|
+
function splitTypeAndMessage(lines) {
|
|
135
|
+
const first = lines[0] ?? "";
|
|
136
|
+
const match = TYPE_AND_MESSAGE.exec(first);
|
|
137
|
+
const tail = lines.slice(1);
|
|
138
|
+
if (!match) return { message: lines.join("\n") };
|
|
139
|
+
const message = [match[2] ?? "", ...tail].join("\n").replace(/^\n+/, "");
|
|
140
|
+
return {
|
|
141
|
+
type: match[1],
|
|
142
|
+
message
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/** Parse a stack trace. Never throws, and every input line appears in the result. */
|
|
146
|
+
function parseStackTrace(text, options) {
|
|
147
|
+
const rawLines = text.split("\n");
|
|
148
|
+
const overflow = rawLines.length > 1e4 ? rawLines.splice(STACK_MAX_LINES) : [];
|
|
149
|
+
const rustContext = /panicked at|stack backtrace|RUST_BACKTRACE/.test(text.slice(0, 2e5));
|
|
150
|
+
const items = [];
|
|
151
|
+
let python;
|
|
152
|
+
let rust;
|
|
153
|
+
for (const original of rawLines) {
|
|
154
|
+
const line = original.endsWith("\r") ? original.slice(0, -1) : original;
|
|
155
|
+
const trimmed = line.trim();
|
|
156
|
+
if (line.length > LINE_PATTERN_LIMIT || trimmed === "") {
|
|
157
|
+
python = rust = void 0;
|
|
158
|
+
items.push({
|
|
159
|
+
type: "text",
|
|
160
|
+
text: line
|
|
161
|
+
});
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
if (python && /^\s/.test(line) && !trimmed.startsWith("File \"")) {
|
|
165
|
+
(python.detail ??= []).push(line);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (rust && rust.file === void 0 && RUST_LOCATION.test(trimmed)) {
|
|
169
|
+
const split = splitLocation(RUST_LOCATION.exec(trimmed)[1]);
|
|
170
|
+
rust.file = split.file;
|
|
171
|
+
rust.line = split.line;
|
|
172
|
+
rust.column = split.column;
|
|
173
|
+
rust.raw = `${rust.raw}\n${line}`;
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
const draft = parsePython(trimmed) ?? parseRustFrame(trimmed, rustContext) ?? parseV8(trimmed);
|
|
177
|
+
python = draft?.format === "python" ? draft : void 0;
|
|
178
|
+
rust = draft?.format === "rust" ? draft : void 0;
|
|
179
|
+
if (draft) items.push({
|
|
180
|
+
type: "frame",
|
|
181
|
+
draft
|
|
182
|
+
});
|
|
183
|
+
else items.push({
|
|
184
|
+
type: "text",
|
|
185
|
+
text: line
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
if (overflow.length > 0) items.push({
|
|
189
|
+
type: "text",
|
|
190
|
+
text: overflow.join("\n")
|
|
191
|
+
});
|
|
192
|
+
const counts = {
|
|
193
|
+
v8: 0,
|
|
194
|
+
python: 0,
|
|
195
|
+
rust: 0
|
|
196
|
+
};
|
|
197
|
+
for (const item of items) if (item.type === "frame") counts[item.draft.format] += 1;
|
|
198
|
+
const format = counts.v8 + counts.python + counts.rust === 0 ? "unknown" : counts.python >= counts.v8 && counts.python >= counts.rust ? "python" : counts.rust >= counts.v8 ? "rust" : "v8";
|
|
199
|
+
const entries = items.map((item) => item.type === "text" ? item : {
|
|
200
|
+
type: "frame",
|
|
201
|
+
frame: finishFrame(item.draft, options)
|
|
202
|
+
});
|
|
203
|
+
if (format === "unknown") return {
|
|
204
|
+
format,
|
|
205
|
+
entries,
|
|
206
|
+
frames: []
|
|
207
|
+
};
|
|
208
|
+
const header = liftHeader(entries, format);
|
|
209
|
+
const frames = entries.flatMap((entry) => entry.type === "frame" ? [entry.frame] : []);
|
|
210
|
+
return {
|
|
211
|
+
format,
|
|
212
|
+
...header && { header },
|
|
213
|
+
entries,
|
|
214
|
+
frames
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Take the header out of the entries it came from. V8 and Rust print it before
|
|
219
|
+
* the frames; Python prints it after. The lifted lines are removed so they are
|
|
220
|
+
* drawn once, as the header, and nothing else is touched.
|
|
221
|
+
*/
|
|
222
|
+
function liftHeader(entries, format) {
|
|
223
|
+
const firstFrame = entries.findIndex((entry) => entry.type === "frame");
|
|
224
|
+
if (format === "python") {
|
|
225
|
+
let last = entries.length - 1;
|
|
226
|
+
while (last >= 0 && (entries[last].type !== "text" || isBlank(entries[last]))) last -= 1;
|
|
227
|
+
let lastFrame = entries.length - 1;
|
|
228
|
+
while (lastFrame >= 0 && entries[lastFrame].type !== "frame") lastFrame -= 1;
|
|
229
|
+
const entry = entries[last];
|
|
230
|
+
if (!entry || entry.type !== "text" || last < lastFrame || /^\s/.test(entry.text) || !TYPE_AND_MESSAGE.test(entry.text.trim())) return;
|
|
231
|
+
entries.splice(last, 1);
|
|
232
|
+
return splitTypeAndMessage([entry.text.trim()]);
|
|
233
|
+
}
|
|
234
|
+
if (format === "rust") {
|
|
235
|
+
const panicAt = entries.findIndex((entry, index) => index < firstFrame && entry.type === "text" && /panicked at/.test(entry.text));
|
|
236
|
+
if (panicAt < 0) return void 0;
|
|
237
|
+
const first = entries[panicAt].text.trim();
|
|
238
|
+
const at = first.indexOf(" at ");
|
|
239
|
+
if (at < 0) return void 0;
|
|
240
|
+
const type = first.slice(0, at).trim();
|
|
241
|
+
const after = first.slice(at + 4);
|
|
242
|
+
const old = /^'(.*)', (\S.*)$/.exec(after);
|
|
243
|
+
let consumed = 1;
|
|
244
|
+
let message;
|
|
245
|
+
let location;
|
|
246
|
+
if (old) {
|
|
247
|
+
message = old[1];
|
|
248
|
+
location = old[2];
|
|
249
|
+
} else {
|
|
250
|
+
location = after.replace(/:$/, "");
|
|
251
|
+
const body = [];
|
|
252
|
+
for (let i = panicAt + 1; i < firstFrame; i += 1) {
|
|
253
|
+
const entry = entries[i];
|
|
254
|
+
if (entry.type !== "text" || isBlank(entry) || /^(?:note:|stack backtrace:)/.test(entry.text.trim())) break;
|
|
255
|
+
body.push(entry.text);
|
|
256
|
+
consumed += 1;
|
|
257
|
+
}
|
|
258
|
+
message = body.join("\n");
|
|
259
|
+
}
|
|
260
|
+
entries.splice(panicAt, consumed);
|
|
261
|
+
return {
|
|
262
|
+
type,
|
|
263
|
+
message,
|
|
264
|
+
...location && { location }
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
if (firstFrame <= 0) return void 0;
|
|
268
|
+
let start = firstFrame;
|
|
269
|
+
while (start > 0 && entries[start - 1].type === "text" && !isBlank(entries[start - 1])) start -= 1;
|
|
270
|
+
if (start === firstFrame) return void 0;
|
|
271
|
+
const lines = entries.slice(start, firstFrame).map((entry) => entry.text);
|
|
272
|
+
entries.splice(start, firstFrame - start);
|
|
273
|
+
return splitTypeAndMessage(lines);
|
|
274
|
+
}
|
|
275
|
+
function isBlank(entry) {
|
|
276
|
+
return entry.type === "text" && entry.text.trim() === "";
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Fold runs of dependency and runtime frames into groups, so a trace reads as
|
|
280
|
+
* the code the reader owns with the framework's frames one click away.
|
|
281
|
+
*
|
|
282
|
+
* A run of one stays a frame — a disclosure around a single line costs more than
|
|
283
|
+
* it saves. When there is no first-party frame at all nothing is grouped:
|
|
284
|
+
* collapsing everything would hide the entire trace behind a button, which is the
|
|
285
|
+
* opposite of what a reader who owns none of the frames needs.
|
|
286
|
+
*/
|
|
287
|
+
function groupStackEntries(entries, collapse = true) {
|
|
288
|
+
const hasFirstParty = entries.some((entry) => entry.type === "frame" && entry.frame.kind === "first-party");
|
|
289
|
+
if (!collapse || !hasFirstParty) return entries;
|
|
290
|
+
const blocks = [];
|
|
291
|
+
let run = [];
|
|
292
|
+
const flush = () => {
|
|
293
|
+
if (run.length >= 2) blocks.push({
|
|
294
|
+
type: "group",
|
|
295
|
+
frames: run
|
|
296
|
+
});
|
|
297
|
+
else for (const frame of run) blocks.push({
|
|
298
|
+
type: "frame",
|
|
299
|
+
frame
|
|
300
|
+
});
|
|
301
|
+
run = [];
|
|
302
|
+
};
|
|
303
|
+
for (const entry of entries) {
|
|
304
|
+
if (entry.type === "frame" && entry.frame.kind !== "first-party") {
|
|
305
|
+
run.push(entry.frame);
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
flush();
|
|
309
|
+
blocks.push(entry);
|
|
310
|
+
}
|
|
311
|
+
flush();
|
|
312
|
+
return blocks;
|
|
313
|
+
}
|
|
314
|
+
var framesNoun = (count, word) => `${count.toLocaleString()} ${word} ${count === 1 ? "frame" : "frames"}`;
|
|
315
|
+
/** What a collapsed group says it holds. */
|
|
316
|
+
function describeFrameGroup(frames) {
|
|
317
|
+
const count = frames.length;
|
|
318
|
+
const dependency = frames.filter((frame) => frame.kind === "dependency").length;
|
|
319
|
+
if (dependency === count) return framesNoun(count, "dependency");
|
|
320
|
+
if (dependency === 0) return framesNoun(count, "runtime");
|
|
321
|
+
return `${count.toLocaleString()} dependency and runtime frames`;
|
|
322
|
+
}
|
|
323
|
+
/** `file:line:col`, with whichever parts the frame has. */
|
|
324
|
+
function frameLocation(frame) {
|
|
325
|
+
if (frame.file === void 0) return void 0;
|
|
326
|
+
const column = frame.column === void 0 ? "" : `:${frame.column}`;
|
|
327
|
+
const line = frame.line === void 0 ? "" : `:${frame.line}`;
|
|
328
|
+
return `${frame.file}${line}${line ? column : ""}`;
|
|
329
|
+
}
|
|
330
|
+
var LEADING_SPACE = /^[ \t]*/;
|
|
331
|
+
/** Remove the indentation every non-blank line shares, so a source snippet sits flush. */
|
|
332
|
+
function dedentLines(lines) {
|
|
333
|
+
let indent = Infinity;
|
|
334
|
+
for (const line of lines) if (line.trim() !== "") indent = Math.min(indent, LEADING_SPACE.exec(line)[0].length);
|
|
335
|
+
if (indent === Infinity) return [...lines];
|
|
336
|
+
return lines.map((line) => line.slice(Math.min(indent, LEADING_SPACE.exec(line)[0].length)));
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* The first lines of `lines`, up to `maxLines` of them and `maxChars` characters
|
|
340
|
+
* between them, with what was left out counted rather than dropped silently. It
|
|
341
|
+
* visits the shown lines and adds up the length of the rest, so the cost does not
|
|
342
|
+
* depend on how much text there is to omit.
|
|
343
|
+
*/
|
|
344
|
+
function boundLines(lines, maxLines, maxChars) {
|
|
345
|
+
const shown = [];
|
|
346
|
+
let chars = 0;
|
|
347
|
+
let index = 0;
|
|
348
|
+
let partial = 0;
|
|
349
|
+
while (index < lines.length && shown.length < maxLines) {
|
|
350
|
+
const line = lines[index];
|
|
351
|
+
const room = maxChars - chars;
|
|
352
|
+
if (line.length <= room) {
|
|
353
|
+
shown.push(line);
|
|
354
|
+
chars += line.length;
|
|
355
|
+
index += 1;
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
if (room > 0) {
|
|
359
|
+
shown.push(line.slice(0, room));
|
|
360
|
+
partial = line.length - room;
|
|
361
|
+
index += 1;
|
|
362
|
+
}
|
|
363
|
+
break;
|
|
364
|
+
}
|
|
365
|
+
let omittedChars = partial;
|
|
366
|
+
for (let rest = index; rest < lines.length; rest += 1) omittedChars += lines[rest].length;
|
|
367
|
+
return {
|
|
368
|
+
lines: shown,
|
|
369
|
+
omittedLines: lines.length - index,
|
|
370
|
+
omittedChars
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
//#endregion
|
|
374
|
+
export { STACK_MAX_LINES, boundLines, classifyFrame, dedentLines, describeFrameGroup, frameLocation, groupStackEntries, parseStackTrace, splitLocation };
|
|
375
|
+
|
|
376
|
+
//# sourceMappingURL=parse-stack-trace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-stack-trace.js","names":[],"sources":["../../../../src/components/composites/stack-trace/parse-stack-trace.ts"],"sourcesContent":["/**\n * Stack traces, read without being trusted or trimmed.\n *\n * A trace is text a runtime wrote about itself, and every language writes it\n * differently. This parses the three a coding agent meets most — V8/Node\n * (`at fn (file:line:col)`), Python (`File \"x\", line N, in fn`) and Rust panic\n * backtraces (` 0: symbol` then `at file:line:col`) — into frames, and does\n * three things a formatter would not:\n *\n * - **It never hides a line.** Every input line ends up in `entries`, as a frame\n * or as text, in order. A line the parser does not recognise is text, and a\n * trace it recognises nothing in has `format: 'unknown'` and `frames: []`, so a\n * caller falls back to showing the raw string. The header (error type and\n * message) is lifted out of the entries only when it is unambiguous.\n * - **It makes no claim about whose code a frame is without evidence.** A frame\n * is a dependency when its path says so (`node_modules`, `site-packages`,\n * `.cargo/registry`), internal when it belongs to the runtime (`node:` URLs,\n * Python's frozen modules, Rust's `std`), and first-party otherwise. A host that\n * knows better passes `classify`.\n * - **It is bounded.** Lines over 4 000 characters are never run through a\n * pattern, and input past 10 000 lines is kept as one trailing text entry. Every\n * pattern is anchored and linear, so a hostile trace cannot make parsing slow.\n *\n * Parsing is line-oriented and each line is classified on its own, so a trace\n * that mixes formats (a Node process that shells out to Python) keeps both.\n */\n\nexport type StackFrameKind = 'first-party' | 'dependency' | 'internal'\nexport type StackTraceFormat = 'v8' | 'python' | 'rust' | 'unknown'\n\nexport type StackFrame = Readonly<{\n /** The line exactly as written, minus its line ending. */\n raw: string\n function?: string\n /** The path or URL as written. Undefined for `<anonymous>`, `native` and the like. */\n file?: string\n line?: number\n column?: number\n kind: StackFrameKind\n async?: true\n /** Lines the runtime printed beneath the frame, such as Python's source line. */\n detail?: readonly string[]\n}>\n\nexport type StackEntry =\n | Readonly<{ type: 'frame'; frame: StackFrame }>\n | Readonly<{ type: 'text'; text: string }>\n\nexport type StackTraceHeader = Readonly<{\n /** `TypeError`, `ValueError`, `thread 'main' panicked`. */\n type?: string\n message: string\n /** Where a Rust panic says it happened. */\n location?: string\n}>\n\nexport type ParsedStackTrace = Readonly<{\n format: StackTraceFormat\n header?: StackTraceHeader\n /** Everything that is not the header, in order. */\n entries: readonly StackEntry[]\n frames: readonly StackFrame[]\n}>\n\nexport type ParseStackTraceOptions = {\n /** Override the built-in first-party/dependency/internal guess for a frame. */\n classify?: (frame: StackFrame) => StackFrameKind | undefined\n}\n\nexport const STACK_MAX_LINES = 10_000\nconst LINE_PATTERN_LIMIT = 4000\n\ntype Draft = {\n raw: string\n function?: string\n file?: string\n line?: number\n column?: number\n async?: true\n detail?: string[]\n format: 'v8' | 'python' | 'rust'\n}\n\nfunction trailingNumber(value: string): { value: number; rest: string } | undefined {\n let i = value.length\n while (i > 0 && value.charCodeAt(i - 1) >= 48 && value.charCodeAt(i - 1) <= 57) i -= 1\n if (i === value.length || i === 0 || value[i - 1] !== ':' || value.length - i > 9)\n return undefined\n return { value: Number(value.slice(i)), rest: value.slice(0, i - 1) }\n}\n\n/** Split `path:line:col` from the right, so a Windows drive or a URL port stays in the path. */\nexport function splitLocation(location: string): { file: string; line?: number; column?: number } {\n const last = trailingNumber(location)\n if (!last || last.rest === '') return { file: location }\n const before = trailingNumber(last.rest)\n if (before && before.rest !== '') {\n return { file: before.rest, line: before.value, column: last.value }\n }\n return { file: last.rest, line: last.value }\n}\n\nconst FILE_LIKE = /[\\\\/]|\\.[A-Za-z0-9]{1,6}$/\nconst URL_LIKE = /^node:/i\n\n/** Whether a V8 location is a place in a file rather than a runtime annotation. */\nfunction v8Location(location: string): Partial<Draft> | undefined {\n if (location === '<anonymous>' || location === 'native' || /^index \\d+$/.test(location)) {\n return {}\n }\n if (location.startsWith('eval at ')) return {}\n const split = splitLocation(location)\n if (split.line !== undefined || FILE_LIKE.test(split.file) || URL_LIKE.test(split.file)) {\n return { file: split.file, line: split.line, column: split.column }\n }\n return undefined\n}\n\nfunction parseV8(trimmed: string): Draft | undefined {\n if (!trimmed.startsWith('at ')) return undefined\n const rest = trimmed.slice(3)\n if (rest === '') return undefined\n\n let fn: string | undefined\n let location: string\n if (rest.endsWith(')') && rest.includes(' (')) {\n const open = rest.indexOf(' (')\n fn = rest.slice(0, open)\n location = rest.slice(open + 2, -1)\n } else {\n location = rest\n }\n const parsed = v8Location(location)\n if (!parsed) return undefined\n // Without parentheses the whole remainder was the location, and it must carry\n // a line or a path — otherwise \"at the end of the day\" would be a frame.\n if (\n fn === undefined &&\n parsed.file === undefined &&\n location !== '<anonymous>' &&\n location !== 'native'\n ) {\n return undefined\n }\n\n const draft: Draft = { raw: trimmed, format: 'v8', ...parsed }\n if (fn !== undefined) {\n if (fn.startsWith('async ')) {\n draft.async = true\n fn = fn.slice(6)\n }\n if (fn !== '') draft.function = fn\n }\n return draft\n}\n\nconst PYTHON_FRAME = /^File \"(.*)\", line (\\d+)(?:, in (.*))?$/\n\nfunction parsePython(trimmed: string): Draft | undefined {\n const match = PYTHON_FRAME.exec(trimmed)\n if (!match) return undefined\n const draft: Draft = { raw: trimmed, format: 'python', file: match[1], line: Number(match[2]) }\n if (match[3]) draft.function = match[3]\n return draft\n}\n\nconst RUST_FRAME = /^(\\d+):\\s+(?:0x[0-9a-fA-F]+ - )?(\\S.*)$/\nconst RUST_LOCATION = /^at\\s+(\\S.*)$/\n\nfunction parseRustFrame(trimmed: string, rustContext: boolean): Draft | undefined {\n const match = RUST_FRAME.exec(trimmed)\n if (!match) return undefined\n const symbol = match[2]!\n if (!rustContext && !symbol.includes('::')) return undefined\n return { raw: trimmed, format: 'rust', function: symbol }\n}\n\nconst INTERNAL_RUST_SYMBOLS =\n /^(?:std|core|alloc)::|^<?(?:\\w+ as )?(?:std|core|alloc)::|^(?:rust_begin_unwind|rust_panic|__rust_|_start$|__libc_|_main$)/\n\n/** The built-in guess at whose code a frame is. See the module comment. */\nexport function classifyFrame(\n frame: Omit<StackFrame, 'kind'>,\n format: StackTraceFormat\n): StackFrameKind {\n const file = frame.file?.replaceAll('\\\\', '/')\n if (format === 'rust') {\n if (file !== undefined) {\n if (file.startsWith('/rustc/') || /\\/library\\/(?:std|core|alloc)\\//.test(file))\n return 'internal'\n if (/\\/\\.cargo\\/(?:registry|git)\\/|\\/registry\\/src\\//.test(file)) return 'dependency'\n return 'first-party'\n }\n return frame.function !== undefined && INTERNAL_RUST_SYMBOLS.test(frame.function)\n ? 'internal'\n : 'first-party'\n }\n if (file === undefined) return 'internal'\n if (format === 'python') {\n if (/\\/(?:site|dist)-packages\\//.test(file)) return 'dependency'\n if (\n file.startsWith('<') ||\n /\\/lib\\/python\\d/i.test(file) ||\n /\\/python\\d[\\d.]*\\/lib\\//i.test(file)\n ) {\n return 'internal'\n }\n return 'first-party'\n }\n if (file.startsWith('node:') || file.startsWith('internal/') || file.startsWith('wasm://')) {\n return 'internal'\n }\n if (file.includes('/node_modules/') || file.startsWith('node_modules/')) return 'dependency'\n return 'first-party'\n}\n\nfunction finishFrame(draft: Draft, options: ParseStackTraceOptions | undefined): StackFrame {\n const { format, detail, ...base } = draft\n const shape: Omit<StackFrame, 'kind'> = detail && detail.length > 0 ? { ...base, detail } : base\n // Classified by the frame's own format, so a mixed trace keeps both languages' rules.\n const guess = classifyFrame(shape, format)\n const override = options?.classify?.({ ...shape, kind: guess })\n return { ...shape, kind: override ?? guess }\n}\n\nconst TYPE_AND_MESSAGE = /^([A-Za-z_$][\\w$.]*)(?::\\s?([\\s\\S]*))?$/\n\nfunction splitTypeAndMessage(lines: readonly string[]): StackTraceHeader {\n const first = lines[0] ?? ''\n const match = TYPE_AND_MESSAGE.exec(first)\n const tail = lines.slice(1)\n if (!match) return { message: lines.join('\\n') }\n const message = [match[2] ?? '', ...tail].join('\\n').replace(/^\\n+/, '')\n return { type: match[1], message }\n}\n\n/** Parse a stack trace. Never throws, and every input line appears in the result. */\nexport function parseStackTrace(text: string, options?: ParseStackTraceOptions): ParsedStackTrace {\n const rawLines = text.split('\\n')\n const overflow = rawLines.length > STACK_MAX_LINES ? rawLines.splice(STACK_MAX_LINES) : []\n const rustContext = /panicked at|stack backtrace|RUST_BACKTRACE/.test(text.slice(0, 200_000))\n\n type Item = { type: 'text'; text: string } | { type: 'frame'; draft: Draft }\n const items: Item[] = []\n let python: Draft | undefined\n let rust: Draft | undefined\n\n for (const original of rawLines) {\n const line = original.endsWith('\\r') ? original.slice(0, -1) : original\n const trimmed = line.trim()\n\n if (line.length > LINE_PATTERN_LIMIT || trimmed === '') {\n python = rust = undefined\n items.push({ type: 'text', text: line })\n continue\n }\n\n // Python prints the offending source line, indented, under its frame.\n if (python && /^\\s/.test(line) && !trimmed.startsWith('File \"')) {\n ;(python.detail ??= []).push(line)\n continue\n }\n\n if (rust && rust.file === undefined && RUST_LOCATION.test(trimmed)) {\n const split = splitLocation(RUST_LOCATION.exec(trimmed)![1]!)\n rust.file = split.file\n rust.line = split.line\n rust.column = split.column\n rust.raw = `${rust.raw}\\n${line}`\n continue\n }\n\n const draft = parsePython(trimmed) ?? parseRustFrame(trimmed, rustContext) ?? parseV8(trimmed)\n python = draft?.format === 'python' ? draft : undefined\n rust = draft?.format === 'rust' ? draft : undefined\n if (draft) items.push({ type: 'frame', draft })\n else items.push({ type: 'text', text: line })\n }\n if (overflow.length > 0) items.push({ type: 'text', text: overflow.join('\\n') })\n\n const counts = { v8: 0, python: 0, rust: 0 }\n for (const item of items) if (item.type === 'frame') counts[item.draft.format] += 1\n const total = counts.v8 + counts.python + counts.rust\n const format: StackTraceFormat =\n total === 0\n ? 'unknown'\n : counts.python >= counts.v8 && counts.python >= counts.rust\n ? 'python'\n : counts.rust >= counts.v8\n ? 'rust'\n : 'v8'\n\n const entries: StackEntry[] = items.map((item) =>\n item.type === 'text' ? item : { type: 'frame', frame: finishFrame(item.draft, options) }\n )\n\n if (format === 'unknown') return { format, entries, frames: [] }\n\n const header = liftHeader(entries, format)\n const frames = entries.flatMap((entry) => (entry.type === 'frame' ? [entry.frame] : []))\n return { format, ...(header && { header }), entries, frames }\n}\n\n/**\n * Take the header out of the entries it came from. V8 and Rust print it before\n * the frames; Python prints it after. The lifted lines are removed so they are\n * drawn once, as the header, and nothing else is touched.\n */\nfunction liftHeader(entries: StackEntry[], format: StackTraceFormat): StackTraceHeader | undefined {\n const firstFrame = entries.findIndex((entry) => entry.type === 'frame')\n\n if (format === 'python') {\n let last = entries.length - 1\n while (last >= 0 && (entries[last]!.type !== 'text' || isBlank(entries[last]!))) last -= 1\n let lastFrame = entries.length - 1\n while (lastFrame >= 0 && entries[lastFrame]!.type !== 'frame') lastFrame -= 1\n const entry = entries[last]\n // Only a line shaped like `Type: message` is taken as the header; anything\n // else after the last frame (`[Previous line repeated …]`) stays where it is.\n if (\n !entry ||\n entry.type !== 'text' ||\n last < lastFrame ||\n /^\\s/.test(entry.text) ||\n !TYPE_AND_MESSAGE.test(entry.text.trim())\n ) {\n return undefined\n }\n entries.splice(last, 1)\n return splitTypeAndMessage([entry.text.trim()])\n }\n\n if (format === 'rust') {\n const panicAt = entries.findIndex(\n (entry, index) =>\n index < firstFrame && entry.type === 'text' && /panicked at/.test(entry.text)\n )\n if (panicAt < 0) return undefined\n const first = (entries[panicAt] as { text: string }).text.trim()\n const at = first.indexOf(' at ')\n if (at < 0) return undefined\n const type = first.slice(0, at).trim()\n const after = first.slice(at + 4)\n const old = /^'(.*)', (\\S.*)$/.exec(after)\n let consumed = 1\n let message: string\n let location: string | undefined\n if (old) {\n message = old[1]!\n location = old[2]\n } else {\n location = after.replace(/:$/, '')\n const body: string[] = []\n for (let i = panicAt + 1; i < firstFrame; i += 1) {\n const entry = entries[i]!\n if (\n entry.type !== 'text' ||\n isBlank(entry) ||\n /^(?:note:|stack backtrace:)/.test(entry.text.trim())\n )\n break\n body.push(entry.text)\n consumed += 1\n }\n message = body.join('\\n')\n }\n entries.splice(panicAt, consumed)\n return { type, message, ...(location && { location }) }\n }\n\n // V8: the block of non-blank lines directly above the first frame. Anything\n // above a blank line — Node prints the source line that threw — stays as text.\n if (firstFrame <= 0) return undefined\n let start = firstFrame\n while (start > 0 && entries[start - 1]!.type === 'text' && !isBlank(entries[start - 1]!))\n start -= 1\n if (start === firstFrame) return undefined\n const lines = entries.slice(start, firstFrame).map((entry) => (entry as { text: string }).text)\n entries.splice(start, firstFrame - start)\n return splitTypeAndMessage(lines)\n}\n\nfunction isBlank(entry: StackEntry): boolean {\n return entry.type === 'text' && entry.text.trim() === ''\n}\n\n// ---------------------------------------------------------------------------\n// Grouping\n// ---------------------------------------------------------------------------\n\nexport type StackBlock =\n | Readonly<{ type: 'frame'; frame: StackFrame }>\n | Readonly<{ type: 'text'; text: string }>\n | Readonly<{ type: 'group'; frames: readonly StackFrame[] }>\n\n/**\n * Fold runs of dependency and runtime frames into groups, so a trace reads as\n * the code the reader owns with the framework's frames one click away.\n *\n * A run of one stays a frame — a disclosure around a single line costs more than\n * it saves. When there is no first-party frame at all nothing is grouped:\n * collapsing everything would hide the entire trace behind a button, which is the\n * opposite of what a reader who owns none of the frames needs.\n */\nexport function groupStackEntries(\n entries: readonly StackEntry[],\n collapse = true\n): readonly StackBlock[] {\n const hasFirstParty = entries.some(\n (entry) => entry.type === 'frame' && entry.frame.kind === 'first-party'\n )\n if (!collapse || !hasFirstParty) return entries\n\n const blocks: StackBlock[] = []\n let run: StackFrame[] = []\n const flush = () => {\n if (run.length >= 2) blocks.push({ type: 'group', frames: run })\n else for (const frame of run) blocks.push({ type: 'frame', frame })\n run = []\n }\n for (const entry of entries) {\n if (entry.type === 'frame' && entry.frame.kind !== 'first-party') {\n run.push(entry.frame)\n continue\n }\n flush()\n blocks.push(entry)\n }\n flush()\n return blocks\n}\n\nconst framesNoun = (count: number, word: string) =>\n `${count.toLocaleString()} ${word} ${count === 1 ? 'frame' : 'frames'}`\n\n/** What a collapsed group says it holds. */\nexport function describeFrameGroup(frames: readonly StackFrame[]): string {\n const count = frames.length\n const dependency = frames.filter((frame) => frame.kind === 'dependency').length\n if (dependency === count) return framesNoun(count, 'dependency')\n if (dependency === 0) return framesNoun(count, 'runtime')\n return `${count.toLocaleString()} dependency and runtime frames`\n}\n\n/** `file:line:col`, with whichever parts the frame has. */\nexport function frameLocation(frame: StackFrame): string | undefined {\n if (frame.file === undefined) return undefined\n const column = frame.column === undefined ? '' : `:${frame.column}`\n const line = frame.line === undefined ? '' : `:${frame.line}`\n return `${frame.file}${line}${line ? column : ''}`\n}\n\nconst LEADING_SPACE = /^[ \\t]*/\n\n/** Remove the indentation every non-blank line shares, so a source snippet sits flush. */\nexport function dedentLines(lines: readonly string[]): string[] {\n let indent = Infinity\n for (const line of lines) {\n if (line.trim() !== '') indent = Math.min(indent, LEADING_SPACE.exec(line)![0].length)\n }\n if (indent === Infinity) return [...lines]\n return lines.map((line) => line.slice(Math.min(indent, LEADING_SPACE.exec(line)![0].length)))\n}\n\nexport type BoundedLines = Readonly<{\n lines: string[]\n /** Lines beyond the bound that are not in `lines` at all. */\n omittedLines: number\n /** Characters beyond the bound, in omitted lines and in the cut end of the last shown line. */\n omittedChars: number\n}>\n\n/**\n * The first lines of `lines`, up to `maxLines` of them and `maxChars` characters\n * between them, with what was left out counted rather than dropped silently. It\n * visits the shown lines and adds up the length of the rest, so the cost does not\n * depend on how much text there is to omit.\n */\nexport function boundLines(\n lines: readonly string[],\n maxLines: number,\n maxChars: number\n): BoundedLines {\n const shown: string[] = []\n let chars = 0\n let index = 0\n let partial = 0\n while (index < lines.length && shown.length < maxLines) {\n const line = lines[index]!\n const room = maxChars - chars\n if (line.length <= room) {\n shown.push(line)\n chars += line.length\n index += 1\n continue\n }\n if (room > 0) {\n shown.push(line.slice(0, room))\n partial = line.length - room\n index += 1\n }\n break\n }\n let omittedChars = partial\n for (let rest = index; rest < lines.length; rest += 1) omittedChars += lines[rest]!.length\n return { lines: shown, omittedLines: lines.length - index, omittedChars }\n}\n"],"mappings":"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"}
|