@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,325 @@
|
|
|
1
|
+
//#region src/components/composites/file-tree/build-file-tree.ts
|
|
2
|
+
/** Deeper paths are rejected: no real repository nests this far, and a row's indent would be unusable. */
|
|
3
|
+
var FILE_TREE_MAX_DEPTH = 256;
|
|
4
|
+
var MAX_SEGMENT_LENGTH = 1024;
|
|
5
|
+
function hasForbiddenCharacter(value) {
|
|
6
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
7
|
+
const code = value.charCodeAt(i);
|
|
8
|
+
if (code < 32 || code >= 127 && code <= 159 || code >= 8234 && code <= 8238 || code >= 8294 && code <= 8297 || code === 8232 || code === 8233) return true;
|
|
9
|
+
}
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A path as its segments, or `null` when it is not acceptable. Both separators
|
|
14
|
+
* are accepted, empty and `.` segments are dropped (`a//b`, `./a`, trailing `/`),
|
|
15
|
+
* and a leading separator is dropped, so an absolute path becomes relative to
|
|
16
|
+
* the tree's root rather than escaping it.
|
|
17
|
+
*/
|
|
18
|
+
function normalizePath(path) {
|
|
19
|
+
if (typeof path !== "string" || hasForbiddenCharacter(path)) return null;
|
|
20
|
+
const segments = [];
|
|
21
|
+
let start = 0;
|
|
22
|
+
for (let i = 0; i <= path.length; i += 1) {
|
|
23
|
+
if (i !== path.length && path[i] !== "/" && path[i] !== "\\") continue;
|
|
24
|
+
const segment = path.slice(start, i);
|
|
25
|
+
start = i + 1;
|
|
26
|
+
if (segment === "" || segment === ".") continue;
|
|
27
|
+
if (segment === ".." || segment.length > MAX_SEGMENT_LENGTH) return null;
|
|
28
|
+
segments.push(segment);
|
|
29
|
+
if (segments.length > 256) return null;
|
|
30
|
+
}
|
|
31
|
+
return segments.length === 0 ? null : segments;
|
|
32
|
+
}
|
|
33
|
+
function newDraft(id, name) {
|
|
34
|
+
return {
|
|
35
|
+
id,
|
|
36
|
+
name,
|
|
37
|
+
children: /* @__PURE__ */ new Map(),
|
|
38
|
+
explicit: false
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function compareNodes(a, b) {
|
|
42
|
+
if (a.kind !== b.kind) return a.kind === "directory" ? -1 : 1;
|
|
43
|
+
const left = a.name.toLowerCase();
|
|
44
|
+
const right = b.name.toLowerCase();
|
|
45
|
+
if (left !== right) return left < right ? -1 : 1;
|
|
46
|
+
return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
|
|
47
|
+
}
|
|
48
|
+
function safeCount(value) {
|
|
49
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : void 0;
|
|
50
|
+
}
|
|
51
|
+
var CHANGE_KINDS = /* @__PURE__ */ new Set([
|
|
52
|
+
"added",
|
|
53
|
+
"modified",
|
|
54
|
+
"deleted",
|
|
55
|
+
"renamed"
|
|
56
|
+
]);
|
|
57
|
+
/**
|
|
58
|
+
* Build the tree. Folders sort before files, then by name without regard to
|
|
59
|
+
* case. A path that is both a file and the parent of another path is a folder
|
|
60
|
+
* that keeps the file entry's change (a file replaced by a directory is a real
|
|
61
|
+
* thing to report).
|
|
62
|
+
*/
|
|
63
|
+
function buildFileTree(paths, options = {}) {
|
|
64
|
+
const root = newDraft("", "");
|
|
65
|
+
const rejected = [];
|
|
66
|
+
let duplicates = 0;
|
|
67
|
+
for (const input of paths) {
|
|
68
|
+
const entry = typeof input === "string" ? { path: input } : input && typeof input === "object" ? input : void 0;
|
|
69
|
+
const segments = normalizePath(entry?.path);
|
|
70
|
+
if (!entry || !segments) {
|
|
71
|
+
rejected.push(typeof input === "string" ? input : String(input?.path ?? ""));
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
let node = root;
|
|
75
|
+
let id = "";
|
|
76
|
+
for (const segment of segments) {
|
|
77
|
+
id = id === "" ? segment : `${id}/${segment}`;
|
|
78
|
+
let child = node.children.get(segment);
|
|
79
|
+
if (!child) {
|
|
80
|
+
child = newDraft(id, segment);
|
|
81
|
+
node.children.set(segment, child);
|
|
82
|
+
}
|
|
83
|
+
node = child;
|
|
84
|
+
}
|
|
85
|
+
if (node.explicit) {
|
|
86
|
+
duplicates += 1;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
node.explicit = true;
|
|
90
|
+
if (entry.change && CHANGE_KINDS.has(entry.change)) node.change = entry.change;
|
|
91
|
+
if (typeof entry.renamedFrom === "string" && !hasForbiddenCharacter(entry.renamedFrom)) node.renamedFrom = entry.renamedFrom;
|
|
92
|
+
node.additions = safeCount(entry.additions);
|
|
93
|
+
node.deletions = safeCount(entry.deletions);
|
|
94
|
+
}
|
|
95
|
+
const order = [];
|
|
96
|
+
const parentOf = [];
|
|
97
|
+
const stack = [...root.children.values()].map((draft) => [draft, -1]);
|
|
98
|
+
while (stack.length > 0) {
|
|
99
|
+
const [draft, parent] = stack.pop();
|
|
100
|
+
const index = order.length;
|
|
101
|
+
order.push(draft);
|
|
102
|
+
parentOf.push(parent);
|
|
103
|
+
for (const child of draft.children.values()) stack.push([child, index]);
|
|
104
|
+
}
|
|
105
|
+
const built = order.map(() => []);
|
|
106
|
+
const roots = [];
|
|
107
|
+
const compact = options.compact !== false;
|
|
108
|
+
let fileCount = 0;
|
|
109
|
+
for (let index = order.length - 1; index >= 0; index -= 1) {
|
|
110
|
+
const draft = order[index];
|
|
111
|
+
const children = built[index].toSorted(compareNodes);
|
|
112
|
+
let node;
|
|
113
|
+
const only = children.length === 1 ? children[0] : void 0;
|
|
114
|
+
if (compact && only?.kind === "directory" && draft.change === void 0) node = {
|
|
115
|
+
...only,
|
|
116
|
+
name: `${draft.name}/${only.name}`
|
|
117
|
+
};
|
|
118
|
+
else if (children.length > 0) node = {
|
|
119
|
+
id: draft.id,
|
|
120
|
+
name: draft.name,
|
|
121
|
+
kind: "directory",
|
|
122
|
+
...draft.change && { change: draft.change },
|
|
123
|
+
...draft.renamedFrom !== void 0 && { renamedFrom: draft.renamedFrom },
|
|
124
|
+
children,
|
|
125
|
+
fileCount: children.reduce((sum, child) => sum + child.fileCount, 0)
|
|
126
|
+
};
|
|
127
|
+
else {
|
|
128
|
+
fileCount += 1;
|
|
129
|
+
node = {
|
|
130
|
+
id: draft.id,
|
|
131
|
+
name: draft.name,
|
|
132
|
+
kind: "file",
|
|
133
|
+
...draft.change && { change: draft.change },
|
|
134
|
+
...draft.renamedFrom !== void 0 && { renamedFrom: draft.renamedFrom },
|
|
135
|
+
...draft.additions !== void 0 && { additions: draft.additions },
|
|
136
|
+
...draft.deletions !== void 0 && { deletions: draft.deletions },
|
|
137
|
+
children: [],
|
|
138
|
+
fileCount: 1
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
const parent = parentOf[index];
|
|
142
|
+
if (parent === -1) roots.push(node);
|
|
143
|
+
else built[parent].push(node);
|
|
144
|
+
}
|
|
145
|
+
roots.sort(compareNodes);
|
|
146
|
+
return {
|
|
147
|
+
roots,
|
|
148
|
+
rejected,
|
|
149
|
+
duplicates,
|
|
150
|
+
fileCount
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* The rows that are on screen, in reading order. A collapsed folder's subtree
|
|
155
|
+
* is never visited, so toggling a folder in a 5 000-file tree costs the size of
|
|
156
|
+
* what is visible, not of what exists.
|
|
157
|
+
*/
|
|
158
|
+
function flattenFileTree(roots, expanded) {
|
|
159
|
+
const rows = [];
|
|
160
|
+
const stack = [];
|
|
161
|
+
for (let i = roots.length - 1; i >= 0; i -= 1) stack.push([
|
|
162
|
+
roots[i],
|
|
163
|
+
1,
|
|
164
|
+
null
|
|
165
|
+
]);
|
|
166
|
+
while (stack.length > 0) {
|
|
167
|
+
const [node, level, parentId] = stack.pop();
|
|
168
|
+
const open = node.kind === "directory" && expanded.has(node.id);
|
|
169
|
+
rows.push({
|
|
170
|
+
node,
|
|
171
|
+
level,
|
|
172
|
+
parentId,
|
|
173
|
+
expanded: open
|
|
174
|
+
});
|
|
175
|
+
if (open) for (let i = node.children.length - 1; i >= 0; i -= 1) stack.push([
|
|
176
|
+
node.children[i],
|
|
177
|
+
level + 1,
|
|
178
|
+
node.id
|
|
179
|
+
]);
|
|
180
|
+
}
|
|
181
|
+
return rows;
|
|
182
|
+
}
|
|
183
|
+
/** Every node by id, for turning a row id back into its node. */
|
|
184
|
+
function indexFileTree(roots) {
|
|
185
|
+
const index = /* @__PURE__ */ new Map();
|
|
186
|
+
const stack = [...roots];
|
|
187
|
+
while (stack.length > 0) {
|
|
188
|
+
const node = stack.pop();
|
|
189
|
+
index.set(node.id, node);
|
|
190
|
+
for (const child of node.children) stack.push(child);
|
|
191
|
+
}
|
|
192
|
+
return index;
|
|
193
|
+
}
|
|
194
|
+
/** Tree this small opens fully by default; a larger one opens only its top level. */
|
|
195
|
+
var FILE_TREE_AUTO_EXPAND_LIMIT = 100;
|
|
196
|
+
/**
|
|
197
|
+
* Which folders start open. `true` opens every folder, a number opens folders up
|
|
198
|
+
* to that depth (1 is the top level), a list opens exactly those ids, `false`
|
|
199
|
+
* none. Unset is "auto": everything for a small tree, the top level for a large
|
|
200
|
+
* one, because a tree that opens 5 000 rows is the freeze this exists to avoid.
|
|
201
|
+
*/
|
|
202
|
+
function initialExpanded(roots, spec, fileCount) {
|
|
203
|
+
const open = /* @__PURE__ */ new Set();
|
|
204
|
+
if (Array.isArray(spec)) {
|
|
205
|
+
for (const id of spec) open.add(id);
|
|
206
|
+
return open;
|
|
207
|
+
}
|
|
208
|
+
const depth = spec === true ? Infinity : spec === false ? 0 : typeof spec === "number" ? Math.max(0, Math.floor(spec)) : fileCount <= 100 ? Infinity : 1;
|
|
209
|
+
const stack = roots.map((node) => [node, 1]);
|
|
210
|
+
while (stack.length > 0) {
|
|
211
|
+
const [node, level] = stack.pop();
|
|
212
|
+
if (node.kind !== "directory" || level > depth) continue;
|
|
213
|
+
open.add(node.id);
|
|
214
|
+
for (const child of node.children) stack.push([child, level + 1]);
|
|
215
|
+
}
|
|
216
|
+
return open;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* A window clamped to what exists, and never narrower than one page when that
|
|
220
|
+
* many rows are there. Rows collapse and files are removed while a window is
|
|
221
|
+
* held, so every read goes through this.
|
|
222
|
+
*/
|
|
223
|
+
function clampWindow(window, total, page) {
|
|
224
|
+
if (total <= 0) return {
|
|
225
|
+
start: 0,
|
|
226
|
+
end: 0
|
|
227
|
+
};
|
|
228
|
+
const start = Math.min(Math.max(0, window.start), total - 1);
|
|
229
|
+
return {
|
|
230
|
+
start,
|
|
231
|
+
end: Math.min(total, Math.max(window.end, start + Math.max(1, page)))
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* The window after the keyboard (or typeahead) asks for a row. A row inside the
|
|
236
|
+
* window changes nothing. A row just outside it — an arrow key at the edge — grows
|
|
237
|
+
* the window by one page, so walking the tree costs a page at a time. Anything
|
|
238
|
+
* further is a jump (End, Home, a typed letter): the window moves to the page that
|
|
239
|
+
* holds the row instead of mounting every row between, which is what keeps End on
|
|
240
|
+
* a 5 000-row tree from being a multi-second freeze.
|
|
241
|
+
*/
|
|
242
|
+
function revealInWindow(window, index, total, page) {
|
|
243
|
+
const current = clampWindow(window, total, page);
|
|
244
|
+
if (index < 0 || index >= total) return current;
|
|
245
|
+
if (index >= current.start && index < current.end) return current;
|
|
246
|
+
if (index === current.start - 1) return {
|
|
247
|
+
start: Math.max(0, current.start - page),
|
|
248
|
+
end: current.end
|
|
249
|
+
};
|
|
250
|
+
if (index === current.end) return {
|
|
251
|
+
start: current.start,
|
|
252
|
+
end: Math.min(total, current.end + page)
|
|
253
|
+
};
|
|
254
|
+
const start = Math.floor(index / page) * page;
|
|
255
|
+
return {
|
|
256
|
+
start,
|
|
257
|
+
end: Math.min(total, start + page)
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
function countChanges(roots) {
|
|
261
|
+
const counts = {
|
|
262
|
+
total: 0,
|
|
263
|
+
added: 0,
|
|
264
|
+
modified: 0,
|
|
265
|
+
deleted: 0,
|
|
266
|
+
renamed: 0,
|
|
267
|
+
unspecified: 0
|
|
268
|
+
};
|
|
269
|
+
const stack = [...roots];
|
|
270
|
+
while (stack.length > 0) {
|
|
271
|
+
const node = stack.pop();
|
|
272
|
+
for (const child of node.children) stack.push(child);
|
|
273
|
+
if (node.kind !== "file") continue;
|
|
274
|
+
counts.total += 1;
|
|
275
|
+
if (node.change) counts[node.change] += 1;
|
|
276
|
+
else counts.unspecified += 1;
|
|
277
|
+
}
|
|
278
|
+
return counts;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* The summary in words: "12 files changed: 3 added, 8 modified, 1 deleted". Only
|
|
282
|
+
* kinds that occur are named, and files with no kind are not folded into any of
|
|
283
|
+
* them. Empty is empty, not "0 files changed".
|
|
284
|
+
*/
|
|
285
|
+
function describeChanges(counts) {
|
|
286
|
+
if (counts.total === 0) return "No changed files";
|
|
287
|
+
const parts = [];
|
|
288
|
+
for (const kind of [
|
|
289
|
+
"added",
|
|
290
|
+
"modified",
|
|
291
|
+
"deleted",
|
|
292
|
+
"renamed"
|
|
293
|
+
]) if (counts[kind] > 0) parts.push(`${counts[kind].toLocaleString()} ${kind}`);
|
|
294
|
+
const noun = counts.total === 1 ? "file" : "files";
|
|
295
|
+
const head = `${counts.total.toLocaleString()} ${noun} changed`;
|
|
296
|
+
return parts.length > 0 ? `${head}: ${parts.join(", ")}` : head;
|
|
297
|
+
}
|
|
298
|
+
/** The words for a change, which are drawn on the row and so also spoken. */
|
|
299
|
+
var FILE_CHANGE_LABELS = {
|
|
300
|
+
added: "Added",
|
|
301
|
+
modified: "Modified",
|
|
302
|
+
deleted: "Deleted",
|
|
303
|
+
renamed: "Renamed"
|
|
304
|
+
};
|
|
305
|
+
/**
|
|
306
|
+
* The row a typed prefix jumps to. One typed letter searches from the row after
|
|
307
|
+
* the active one, so pressing it again cycles; a longer string searches from the
|
|
308
|
+
* active row, so refining a match does not skip past it. Matching ignores case.
|
|
309
|
+
*/
|
|
310
|
+
function typeaheadIndex(labels, activeIndex, query) {
|
|
311
|
+
const needle = query.toLowerCase();
|
|
312
|
+
if (needle === "" || labels.length === 0) return -1;
|
|
313
|
+
const repeated = needle.length > 1 && [...needle].every((char) => char === needle[0]);
|
|
314
|
+
const prefix = repeated ? needle[0] : needle;
|
|
315
|
+
const first = needle.length === 1 || repeated ? activeIndex + 1 : Math.max(0, activeIndex);
|
|
316
|
+
for (let offset = 0; offset < labels.length; offset += 1) {
|
|
317
|
+
const index = (first + offset) % labels.length;
|
|
318
|
+
if (labels[index].toLowerCase().startsWith(prefix)) return index;
|
|
319
|
+
}
|
|
320
|
+
return -1;
|
|
321
|
+
}
|
|
322
|
+
//#endregion
|
|
323
|
+
export { FILE_CHANGE_LABELS, FILE_TREE_AUTO_EXPAND_LIMIT, FILE_TREE_MAX_DEPTH, buildFileTree, clampWindow, countChanges, describeChanges, flattenFileTree, indexFileTree, initialExpanded, normalizePath, revealInWindow, typeaheadIndex };
|
|
324
|
+
|
|
325
|
+
//# sourceMappingURL=build-file-tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-file-tree.js","names":[],"sources":["../../../../src/components/composites/file-tree/build-file-tree.ts"],"sourcesContent":["/**\n * The model behind the changed-files tree: paths in, a folder tree out, and the\n * small pure rules the view needs (what is visible, what to say about the\n * changes, what a typed letter jumps to).\n *\n * Paths come from an agent, which means from a model, which means they are\n * untrusted text. They are used here as labels and as ids, never as places to\n * read or write, and the builder is strict about what counts as a path at all:\n * a `..` segment, a control character or a bidirectional override rejects the\n * path rather than being cleaned up, because a cleaned-up path is a different\n * path and the tree would be making a claim the input did not. Rejected paths\n * are returned, not dropped silently, so the view can say how many it ignored.\n *\n * Everything is iterative. A path with ten thousand segments, or a tree five\n * thousand files wide, must not be able to overflow the stack or stall the page.\n */\n\nexport type FileChangeKind = 'added' | 'modified' | 'deleted' | 'renamed'\n\nexport type FileChangeInput = Readonly<{\n path: string\n /** Absent means the host did not say; the tree makes no statement about the file. */\n change?: FileChangeKind\n /** For a rename, where the file was. Shown as text only. */\n renamedFrom?: string\n additions?: number\n deletions?: number\n}>\n\nexport type FileTreeNode = Readonly<{\n /** The normalised path, `/`-separated. Unique within a tree. */\n id: string\n /** The label. For a compacted folder chain this is `a/b/c`. */\n name: string\n kind: 'file' | 'directory'\n change?: FileChangeKind\n renamedFrom?: string\n additions?: number\n deletions?: number\n children: readonly FileTreeNode[]\n /** Files at or below this node. A file counts itself. */\n fileCount: number\n}>\n\nexport type FileTreeBuild = Readonly<{\n roots: readonly FileTreeNode[]\n /** Inputs that were not accepted as paths, exactly as given. */\n rejected: readonly string[]\n /** Inputs that named a path already present. The first one wins. */\n duplicates: number\n fileCount: number\n}>\n\nexport type BuildFileTreeOptions = {\n /** Merge a folder with a single folder child into one row (`src/lib`). Default true. */\n compact?: boolean\n}\n\n/** Deeper paths are rejected: no real repository nests this far, and a row's indent would be unusable. */\nexport const FILE_TREE_MAX_DEPTH = 256\nconst MAX_SEGMENT_LENGTH = 1024\n\nfunction hasForbiddenCharacter(value: string): boolean {\n for (let i = 0; i < value.length; i += 1) {\n const code = value.charCodeAt(i)\n if (\n code < 0x20 ||\n (code >= 0x7f && code <= 0x9f) ||\n (code >= 0x202a && code <= 0x202e) ||\n (code >= 0x2066 && code <= 0x2069) ||\n code === 0x2028 ||\n code === 0x2029\n ) {\n return true\n }\n }\n return false\n}\n\n/**\n * A path as its segments, or `null` when it is not acceptable. Both separators\n * are accepted, empty and `.` segments are dropped (`a//b`, `./a`, trailing `/`),\n * and a leading separator is dropped, so an absolute path becomes relative to\n * the tree's root rather than escaping it.\n */\nexport function normalizePath(path: unknown): string[] | null {\n if (typeof path !== 'string' || hasForbiddenCharacter(path)) return null\n const segments: string[] = []\n let start = 0\n for (let i = 0; i <= path.length; i += 1) {\n if (i !== path.length && path[i] !== '/' && path[i] !== '\\\\') continue\n const segment = path.slice(start, i)\n start = i + 1\n if (segment === '' || segment === '.') continue\n if (segment === '..' || segment.length > MAX_SEGMENT_LENGTH) return null\n segments.push(segment)\n if (segments.length > FILE_TREE_MAX_DEPTH) return null\n }\n return segments.length === 0 ? null : segments\n}\n\ntype Draft = {\n id: string\n name: string\n children: Map<string, Draft>\n change?: FileChangeKind\n renamedFrom?: string\n additions?: number\n deletions?: number\n explicit: boolean\n}\n\nfunction newDraft(id: string, name: string): Draft {\n return { id, name, children: new Map(), explicit: false }\n}\n\nfunction compareNodes(a: FileTreeNode, b: FileTreeNode): number {\n if (a.kind !== b.kind) return a.kind === 'directory' ? -1 : 1\n const left = a.name.toLowerCase()\n const right = b.name.toLowerCase()\n if (left !== right) return left < right ? -1 : 1\n return a.name < b.name ? -1 : a.name > b.name ? 1 : 0\n}\n\nfunction safeCount(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) && value >= 0\n ? Math.floor(value)\n : undefined\n}\n\nconst CHANGE_KINDS: ReadonlySet<string> = new Set(['added', 'modified', 'deleted', 'renamed'])\n\n/**\n * Build the tree. Folders sort before files, then by name without regard to\n * case. A path that is both a file and the parent of another path is a folder\n * that keeps the file entry's change (a file replaced by a directory is a real\n * thing to report).\n */\nexport function buildFileTree(\n paths: readonly (string | FileChangeInput)[],\n options: BuildFileTreeOptions = {}\n): FileTreeBuild {\n const root = newDraft('', '')\n const rejected: string[] = []\n let duplicates = 0\n\n for (const input of paths) {\n const entry: FileChangeInput | undefined =\n typeof input === 'string'\n ? { path: input }\n : input && typeof input === 'object'\n ? input\n : undefined\n const segments = normalizePath(entry?.path)\n if (!entry || !segments) {\n rejected.push(\n typeof input === 'string' ? input : String((input as { path?: unknown })?.path ?? '')\n )\n continue\n }\n\n let node = root\n let id = ''\n for (const segment of segments) {\n id = id === '' ? segment : `${id}/${segment}`\n let child = node.children.get(segment)\n if (!child) {\n child = newDraft(id, segment)\n node.children.set(segment, child)\n }\n node = child\n }\n if (node.explicit) {\n duplicates += 1\n continue\n }\n node.explicit = true\n if (entry.change && CHANGE_KINDS.has(entry.change)) node.change = entry.change\n if (typeof entry.renamedFrom === 'string' && !hasForbiddenCharacter(entry.renamedFrom)) {\n node.renamedFrom = entry.renamedFrom\n }\n node.additions = safeCount(entry.additions)\n node.deletions = safeCount(entry.deletions)\n }\n\n // Pre-order flatten, then fold back in reverse: a child always has a larger\n // index than its parent, so one backwards pass builds every node after its\n // children without recursion.\n const order: Draft[] = []\n const parentOf: number[] = []\n const stack: [Draft, number][] = [...root.children.values()].map((draft) => [draft, -1])\n while (stack.length > 0) {\n const [draft, parent] = stack.pop()!\n const index = order.length\n order.push(draft)\n parentOf.push(parent)\n for (const child of draft.children.values()) stack.push([child, index])\n }\n\n const built: FileTreeNode[][] = order.map(() => [])\n const roots: FileTreeNode[] = []\n const compact = options.compact !== false\n let fileCount = 0\n\n for (let index = order.length - 1; index >= 0; index -= 1) {\n const draft = order[index]!\n const children = built[index]!.toSorted(compareNodes)\n let node: FileTreeNode\n const only = children.length === 1 ? children[0]! : undefined\n if (compact && only?.kind === 'directory' && draft.change === undefined) {\n // A folder holding only another folder reads as one row: `src/lib`, not two.\n node = { ...only, name: `${draft.name}/${only.name}` }\n } else if (children.length > 0) {\n node = {\n id: draft.id,\n name: draft.name,\n kind: 'directory',\n ...(draft.change && { change: draft.change }),\n ...(draft.renamedFrom !== undefined && { renamedFrom: draft.renamedFrom }),\n children,\n fileCount: children.reduce((sum, child) => sum + child.fileCount, 0),\n }\n } else {\n fileCount += 1\n node = {\n id: draft.id,\n name: draft.name,\n kind: 'file',\n ...(draft.change && { change: draft.change }),\n ...(draft.renamedFrom !== undefined && { renamedFrom: draft.renamedFrom }),\n ...(draft.additions !== undefined && { additions: draft.additions }),\n ...(draft.deletions !== undefined && { deletions: draft.deletions }),\n children: [],\n fileCount: 1,\n }\n }\n const parent = parentOf[index]!\n if (parent === -1) roots.push(node)\n else built[parent]!.push(node)\n }\n\n roots.sort(compareNodes)\n return { roots, rejected, duplicates, fileCount }\n}\n\n// ---------------------------------------------------------------------------\n// Projection\n// ---------------------------------------------------------------------------\n\nexport type FileTreeRow = Readonly<{\n node: FileTreeNode\n /** One-based depth. */\n level: number\n parentId: string | null\n expanded: boolean\n}>\n\n/**\n * The rows that are on screen, in reading order. A collapsed folder's subtree\n * is never visited, so toggling a folder in a 5 000-file tree costs the size of\n * what is visible, not of what exists.\n */\nexport function flattenFileTree(\n roots: readonly FileTreeNode[],\n expanded: ReadonlySet<string>\n): FileTreeRow[] {\n const rows: FileTreeRow[] = []\n const stack: [FileTreeNode, number, string | null][] = []\n for (let i = roots.length - 1; i >= 0; i -= 1) stack.push([roots[i]!, 1, null])\n while (stack.length > 0) {\n const [node, level, parentId] = stack.pop()!\n const open = node.kind === 'directory' && expanded.has(node.id)\n rows.push({ node, level, parentId, expanded: open })\n if (open) {\n for (let i = node.children.length - 1; i >= 0; i -= 1) {\n stack.push([node.children[i]!, level + 1, node.id])\n }\n }\n }\n return rows\n}\n\n/** Every node by id, for turning a row id back into its node. */\nexport function indexFileTree(roots: readonly FileTreeNode[]): Map<string, FileTreeNode> {\n const index = new Map<string, FileTreeNode>()\n const stack = [...roots]\n while (stack.length > 0) {\n const node = stack.pop()!\n index.set(node.id, node)\n for (const child of node.children) stack.push(child)\n }\n return index\n}\n\nexport type FileTreeExpansion = boolean | number | readonly string[] | undefined\n\n/** Tree this small opens fully by default; a larger one opens only its top level. */\nexport const FILE_TREE_AUTO_EXPAND_LIMIT = 100\n\n/**\n * Which folders start open. `true` opens every folder, a number opens folders up\n * to that depth (1 is the top level), a list opens exactly those ids, `false`\n * none. Unset is \"auto\": everything for a small tree, the top level for a large\n * one, because a tree that opens 5 000 rows is the freeze this exists to avoid.\n */\nexport function initialExpanded(\n roots: readonly FileTreeNode[],\n spec: FileTreeExpansion,\n fileCount: number\n): Set<string> {\n const open = new Set<string>()\n if (Array.isArray(spec)) {\n for (const id of spec) open.add(id)\n return open\n }\n const depth =\n spec === true\n ? Infinity\n : spec === false\n ? 0\n : typeof spec === 'number'\n ? Math.max(0, Math.floor(spec))\n : fileCount <= FILE_TREE_AUTO_EXPAND_LIMIT\n ? Infinity\n : 1\n const stack: [FileTreeNode, number][] = roots.map((node) => [node, 1])\n while (stack.length > 0) {\n const [node, level] = stack.pop()!\n if (node.kind !== 'directory' || level > depth) continue\n open.add(node.id)\n for (const child of node.children) stack.push([child, level + 1])\n }\n return open\n}\n\n// ---------------------------------------------------------------------------\n// Mounted window\n// ---------------------------------------------------------------------------\n\n/** The slice of visible rows that is mounted: `start` inclusive, `end` exclusive. */\nexport type RowWindow = Readonly<{ start: number; end: number }>\n\n/**\n * A window clamped to what exists, and never narrower than one page when that\n * many rows are there. Rows collapse and files are removed while a window is\n * held, so every read goes through this.\n */\nexport function clampWindow(window: RowWindow, total: number, page: number): RowWindow {\n if (total <= 0) return { start: 0, end: 0 }\n const start = Math.min(Math.max(0, window.start), total - 1)\n return { start, end: Math.min(total, Math.max(window.end, start + Math.max(1, page))) }\n}\n\n/**\n * The window after the keyboard (or typeahead) asks for a row. A row inside the\n * window changes nothing. A row just outside it — an arrow key at the edge — grows\n * the window by one page, so walking the tree costs a page at a time. Anything\n * further is a jump (End, Home, a typed letter): the window moves to the page that\n * holds the row instead of mounting every row between, which is what keeps End on\n * a 5 000-row tree from being a multi-second freeze.\n */\nexport function revealInWindow(\n window: RowWindow,\n index: number,\n total: number,\n page: number\n): RowWindow {\n const current = clampWindow(window, total, page)\n if (index < 0 || index >= total) return current\n if (index >= current.start && index < current.end) return current\n if (index === current.start - 1) {\n return { start: Math.max(0, current.start - page), end: current.end }\n }\n if (index === current.end)\n return { start: current.start, end: Math.min(total, current.end + page) }\n const start = Math.floor(index / page) * page\n return { start, end: Math.min(total, start + page) }\n}\n\n// ---------------------------------------------------------------------------\n// Words\n// ---------------------------------------------------------------------------\n\nexport type ChangeCounts = Readonly<{\n total: number\n added: number\n modified: number\n deleted: number\n renamed: number\n /** Files with no change kind supplied. */\n unspecified: number\n}>\n\nexport function countChanges(roots: readonly FileTreeNode[]): ChangeCounts {\n const counts = { total: 0, added: 0, modified: 0, deleted: 0, renamed: 0, unspecified: 0 }\n const stack = [...roots]\n while (stack.length > 0) {\n const node = stack.pop()!\n for (const child of node.children) stack.push(child)\n if (node.kind !== 'file') continue\n counts.total += 1\n if (node.change) counts[node.change] += 1\n else counts.unspecified += 1\n }\n return counts\n}\n\n/**\n * The summary in words: \"12 files changed: 3 added, 8 modified, 1 deleted\". Only\n * kinds that occur are named, and files with no kind are not folded into any of\n * them. Empty is empty, not \"0 files changed\".\n */\nexport function describeChanges(counts: ChangeCounts): string {\n if (counts.total === 0) return 'No changed files'\n const parts: string[] = []\n for (const kind of ['added', 'modified', 'deleted', 'renamed'] as const) {\n if (counts[kind] > 0) parts.push(`${counts[kind].toLocaleString()} ${kind}`)\n }\n const noun = counts.total === 1 ? 'file' : 'files'\n const head = `${counts.total.toLocaleString()} ${noun} changed`\n return parts.length > 0 ? `${head}: ${parts.join(', ')}` : head\n}\n\n/** The words for a change, which are drawn on the row and so also spoken. */\nexport const FILE_CHANGE_LABELS: Readonly<Record<FileChangeKind, string>> = {\n added: 'Added',\n modified: 'Modified',\n deleted: 'Deleted',\n renamed: 'Renamed',\n}\n\n// ---------------------------------------------------------------------------\n// Typeahead\n// ---------------------------------------------------------------------------\n\n/**\n * The row a typed prefix jumps to. One typed letter searches from the row after\n * the active one, so pressing it again cycles; a longer string searches from the\n * active row, so refining a match does not skip past it. Matching ignores case.\n */\nexport function typeaheadIndex(\n labels: readonly string[],\n activeIndex: number,\n query: string\n): number {\n const needle = query.toLowerCase()\n if (needle === '' || labels.length === 0) return -1\n const repeated = needle.length > 1 && [...needle].every((char) => char === needle[0])\n const prefix = repeated ? needle[0]! : needle\n const first = needle.length === 1 || repeated ? activeIndex + 1 : Math.max(0, activeIndex)\n for (let offset = 0; offset < labels.length; offset += 1) {\n const index = (first + offset) % labels.length\n if (labels[index]!.toLowerCase().startsWith(prefix)) return index\n }\n return -1\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { type ComponentProps } from 'solid-js';
|
|
2
|
+
import { type FileChangeInput, type FileTreeExpansion, type FileTreeNode } from './build-file-tree';
|
|
3
|
+
/**
|
|
4
|
+
* FileTree.
|
|
5
|
+
*
|
|
6
|
+
* The files an agent changed, as a folder tree. It is for a change set — dozens
|
|
7
|
+
* to thousands of paths with an optional change kind each — and not for browsing
|
|
8
|
+
* a workspace: it has no rename, drag, or filesystem action, and it never opens
|
|
9
|
+
* anything. Reach for `Trace` lines when the agent touched two or three files, and
|
|
10
|
+
* for the shared `Tree` directly when the host owns a real file explorer.
|
|
11
|
+
*
|
|
12
|
+
* ## Built on `Tree`, and why that fits
|
|
13
|
+
*
|
|
14
|
+
* `Tree` supplies the treeitem semantics and the WAI-ARIA keyboard model (arrows,
|
|
15
|
+
* Home/End, roving tab stop) and leaves the projection to the host. A changed-file
|
|
16
|
+
* tree is small enough that the whole projection can live in memory, and the
|
|
17
|
+
* `Tree` contract for a mounted window — a complete `visibleItems` list with only
|
|
18
|
+
* some rows rendered, `onRequestReveal` to mount a row the keyboard moved to — is
|
|
19
|
+
* exactly the seam a bounded render needs, so this adds no navigation code of
|
|
20
|
+
* its own. What it adds is typeahead, which `Tree` does not provide: a typed
|
|
21
|
+
* prefix jumps to the next row whose name starts with it.
|
|
22
|
+
*
|
|
23
|
+
* ## Large trees
|
|
24
|
+
*
|
|
25
|
+
* A collapsed folder's subtree is never visited or rendered, so a 5 000-file tree
|
|
26
|
+
* costs what is visible. A tree of more than 100 files starts with only its top
|
|
27
|
+
* level open (`defaultExpanded` overrides). Past `maxRows` visible rows only a
|
|
28
|
+
* window of them is mounted, with a control above and below to move it a page at
|
|
29
|
+
* a time. The full list is what keyboard navigation walks: an arrow key at the
|
|
30
|
+
* window's edge grows it by a page, and a jump (End, Home, a typed letter) moves
|
|
31
|
+
* it to the page holding the target instead of mounting every row between, so End
|
|
32
|
+
* on a tree of thousands of open rows stays one page of work.
|
|
33
|
+
*
|
|
34
|
+
* ## Changes are claims
|
|
35
|
+
*
|
|
36
|
+
* A change kind is drawn — as a word on the row, so it is also spoken — only for a
|
|
37
|
+
* file the host gave one. A file without one is listed and nothing more is said.
|
|
38
|
+
* The summary counts what was supplied, and is silent about files with no kind.
|
|
39
|
+
* Paths that are not acceptable (`..` segments, control characters) are not drawn;
|
|
40
|
+
* their number is stated, so the list is never quietly shorter than the input.
|
|
41
|
+
*
|
|
42
|
+
* ## Selection is the host's
|
|
43
|
+
*
|
|
44
|
+
* Rows select only when `onSelect` is supplied; without it no row is selectable
|
|
45
|
+
* and `aria-selected` is not set. Enter or a click on a folder expands it; on a
|
|
46
|
+
* file it selects. Space selects either. The tree never opens a file itself — the
|
|
47
|
+
* path is untrusted text, and what it means on this machine is the host's call.
|
|
48
|
+
*/
|
|
49
|
+
export type FileTreeProps = Omit<ComponentProps<'div'>, 'children' | 'onSelect'> & {
|
|
50
|
+
/** Paths, or paths with a change kind. Both `/` and `\` separate segments. */
|
|
51
|
+
files: readonly (string | FileChangeInput)[];
|
|
52
|
+
/** The tree's accessible name. Default "Changed files". */
|
|
53
|
+
label?: string;
|
|
54
|
+
/**
|
|
55
|
+
* Which folders start open: `true` all, `false` none, a number to that depth,
|
|
56
|
+
* or a list of ids. Unset opens a small tree fully and a large one at its top level.
|
|
57
|
+
*/
|
|
58
|
+
defaultExpanded?: FileTreeExpansion;
|
|
59
|
+
/** Merge a folder with a single folder child into one row. Default true. */
|
|
60
|
+
compact?: boolean;
|
|
61
|
+
/** The selected node's id. Meaningful only with `onSelect`. */
|
|
62
|
+
selected?: string;
|
|
63
|
+
/** Make rows selectable. Omit and nothing is selectable. */
|
|
64
|
+
onSelect?: (path: string, node: FileTreeNode) => void;
|
|
65
|
+
/** Height of the tree box, which scrolls past it. A number is pixels. Default `20rem`. */
|
|
66
|
+
maxHeight?: number | string;
|
|
67
|
+
/** Visible rows mounted at once; more are added a page at a time. Default 500. */
|
|
68
|
+
maxRows?: number;
|
|
69
|
+
/** Show the count of changes above the tree. Default true. */
|
|
70
|
+
showSummary?: boolean;
|
|
71
|
+
};
|
|
72
|
+
export declare const FILE_TREE_MAX_ROWS = 500;
|
|
73
|
+
export declare function FileTree(props: FileTreeProps): import("solid-js").JSX.Element;
|
|
74
|
+
//# sourceMappingURL=file-tree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-tree.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/file-tree/file-tree.tsx"],"names":[],"mappings":"AACA,OAAO,EASL,KAAK,cAAc,EACpB,MAAM,UAAU,CAAA;AAMjB,OAAO,EAYL,KAAK,eAAe,EAEpB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAElB,MAAM,mBAAmB,CAAA;AAE1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC,GAAG;IACjF,8EAA8E;IAC9E,KAAK,EAAE,SAAS,CAAC,MAAM,GAAG,eAAe,CAAC,EAAE,CAAA;IAC5C,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,eAAe,CAAC,EAAE,iBAAiB,CAAA;IACnC,4EAA4E;IAC5E,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAAA;IACrD,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC3B,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,CAAA;AAED,eAAO,MAAM,kBAAkB,MAAM,CAAA;AAuErC,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,kCAmO5C"}
|