@agent-native/toolkit 0.228.0-nightly-20261111212500 → 0.228.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/agent-native.eject.json +2 -0
- package/dist/app/agentkit/react/approval-card.d.ts.map +1 -1
- package/dist/app/agentkit/react/approval-card.js +5 -3
- package/dist/app/agentkit/react/approval-card.js.map +1 -1
- package/dist/app/agentkit/react/code-block.d.ts +32 -0
- package/dist/app/agentkit/react/code-block.d.ts.map +1 -0
- package/dist/app/agentkit/react/code-block.js +125 -0
- package/dist/app/agentkit/react/code-block.js.map +1 -0
- package/dist/app/agentkit/react/components.d.ts +33 -14
- package/dist/app/agentkit/react/components.d.ts.map +1 -1
- package/dist/app/agentkit/react/components.js +843 -168
- package/dist/app/agentkit/react/components.js.map +1 -1
- package/dist/app/agentkit/react/context-usage.d.ts +45 -0
- package/dist/app/agentkit/react/context-usage.d.ts.map +1 -0
- package/dist/app/agentkit/react/context-usage.js +93 -0
- package/dist/app/agentkit/react/context-usage.js.map +1 -0
- package/dist/app/agentkit/react/context.d.ts +42 -3
- package/dist/app/agentkit/react/context.d.ts.map +1 -1
- package/dist/app/agentkit/react/context.js +46 -1
- package/dist/app/agentkit/react/context.js.map +1 -1
- package/dist/app/agentkit/react/disclosure-content.d.ts +12 -0
- package/dist/app/agentkit/react/disclosure-content.d.ts.map +1 -0
- package/dist/app/agentkit/react/disclosure-content.js +33 -0
- package/dist/app/agentkit/react/disclosure-content.js.map +1 -0
- package/dist/app/agentkit/react/duration.d.ts +6 -0
- package/dist/app/agentkit/react/duration.d.ts.map +1 -0
- package/dist/app/agentkit/react/duration.js +21 -0
- package/dist/app/agentkit/react/duration.js.map +1 -0
- package/dist/app/agentkit/react/file-change.d.ts +33 -0
- package/dist/app/agentkit/react/file-change.d.ts.map +1 -0
- package/dist/app/agentkit/react/file-change.js +83 -0
- package/dist/app/agentkit/react/file-change.js.map +1 -0
- package/dist/app/agentkit/react/file-diff.d.ts +17 -0
- package/dist/app/agentkit/react/file-diff.d.ts.map +1 -0
- package/dist/app/agentkit/react/file-diff.js +94 -0
- package/dist/app/agentkit/react/file-diff.js.map +1 -0
- package/dist/app/agentkit/react/index.d.ts +7 -0
- package/dist/app/agentkit/react/index.d.ts.map +1 -1
- package/dist/app/agentkit/react/index.js +7 -0
- package/dist/app/agentkit/react/index.js.map +1 -1
- package/dist/app/agentkit/react/question-card.d.ts +67 -0
- package/dist/app/agentkit/react/question-card.d.ts.map +1 -0
- package/dist/app/agentkit/react/question-card.js +198 -0
- package/dist/app/agentkit/react/question-card.js.map +1 -0
- package/dist/app/agentkit/react/root.d.ts +3 -2
- package/dist/app/agentkit/react/root.d.ts.map +1 -1
- package/dist/app/agentkit/react/root.js +2 -2
- package/dist/app/agentkit/react/root.js.map +1 -1
- package/dist/app/agentkit/react/roving-focus.d.ts +4 -0
- package/dist/app/agentkit/react/roving-focus.d.ts.map +1 -0
- package/dist/app/agentkit/react/roving-focus.js +75 -0
- package/dist/app/agentkit/react/roving-focus.js.map +1 -0
- package/dist/app/agentkit/react/stack-trace.d.ts +34 -0
- package/dist/app/agentkit/react/stack-trace.d.ts.map +1 -0
- package/dist/app/agentkit/react/stack-trace.js +121 -0
- package/dist/app/agentkit/react/stack-trace.js.map +1 -0
- package/dist/app/agentkit/react/stop-button.d.ts.map +1 -1
- package/dist/app/agentkit/react/stop-button.js +22 -6
- package/dist/app/agentkit/react/stop-button.js.map +1 -1
- package/dist/app/agentkit/react/styles.css +1306 -395
- package/dist/app/agentkit/react/terminal.d.ts +28 -0
- package/dist/app/agentkit/react/terminal.d.ts.map +1 -0
- package/dist/app/agentkit/react/terminal.js +84 -0
- package/dist/app/agentkit/react/terminal.js.map +1 -0
- package/dist/app/agentkit/react/trace.d.ts +31 -0
- package/dist/app/agentkit/react/trace.d.ts.map +1 -0
- package/dist/app/agentkit/react/trace.js +73 -0
- package/dist/app/agentkit/react/trace.js.map +1 -0
- package/dist/app/blocks/library/HighlightedCode.d.ts +2 -1
- package/dist/app/blocks/library/HighlightedCode.d.ts.map +1 -1
- package/dist/app/blocks/library/HighlightedCode.js +8 -111
- package/dist/app/blocks/library/HighlightedCode.js.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.js +23 -245
- package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
- package/dist/app/chat/agentkit-chat/guided-questions.d.ts +15 -1
- package/dist/app/chat/agentkit-chat/guided-questions.d.ts.map +1 -1
- package/dist/app/chat/agentkit-chat/guided-questions.js +142 -2
- package/dist/app/chat/agentkit-chat/guided-questions.js.map +1 -1
- package/dist/app/chat/agentkit-chat/history.js +1 -1
- package/dist/app/chat/agentkit-chat/history.js.map +1 -1
- package/dist/app/chat/agentkit-chat/index.d.ts +1 -1
- package/dist/app/chat/agentkit-chat/index.d.ts.map +1 -1
- package/dist/app/chat/agentkit-chat/index.js +1 -1
- package/dist/app/chat/agentkit-chat/index.js.map +1 -1
- package/dist/app/chat/agentkit-chat/labels.d.ts +5 -0
- package/dist/app/chat/agentkit-chat/labels.d.ts.map +1 -0
- package/dist/app/chat/agentkit-chat/labels.js +245 -0
- package/dist/app/chat/agentkit-chat/labels.js.map +1 -0
- package/dist/app/chat/agentkit-chat/questions.d.ts +1 -1
- package/dist/app/chat/agentkit-chat/questions.d.ts.map +1 -1
- package/dist/app/chat/agentkit-chat/questions.js +1 -1
- package/dist/app/chat/agentkit-chat/questions.js.map +1 -1
- package/dist/app/chat/agentkit-chat/root.d.ts.map +1 -1
- package/dist/app/chat/agentkit-chat/root.js +5 -64
- package/dist/app/chat/agentkit-chat/root.js.map +1 -1
- package/dist/app/chat/agentkit-chat/work-step-labels.d.ts +2 -0
- package/dist/app/chat/agentkit-chat/work-step-labels.d.ts.map +1 -1
- package/dist/app/chat/agentkit-chat/work-step-labels.js +31 -0
- package/dist/app/chat/agentkit-chat/work-step-labels.js.map +1 -1
- package/dist/app/chat/chat/markdown-renderer.d.ts +2 -12
- package/dist/app/chat/chat/markdown-renderer.d.ts.map +1 -1
- package/dist/app/chat/chat/markdown-renderer.js +2 -41
- package/dist/app/chat/chat/markdown-renderer.js.map +1 -1
- package/dist/app/chat/chat/tool-call-display.d.ts.map +1 -1
- package/dist/app/chat/chat/tool-call-display.js +2 -2
- package/dist/app/chat/chat/tool-call-display.js.map +1 -1
- package/dist/app/chat/conversation/AgentConversation.d.ts.map +1 -1
- package/dist/app/chat/conversation/AgentConversation.js +2 -37
- package/dist/app/chat/conversation/AgentConversation.js.map +1 -1
- package/dist/app/chat/tool-cells/BashCell.d.ts +3 -1
- package/dist/app/chat/tool-cells/BashCell.d.ts.map +1 -1
- package/dist/app/chat/tool-cells/BashCell.js +4 -40
- package/dist/app/chat/tool-cells/BashCell.js.map +1 -1
- package/dist/app/chat/tool-cells/EditCell.d.ts.map +1 -1
- package/dist/app/chat/tool-cells/EditCell.js +5 -108
- package/dist/app/chat/tool-cells/EditCell.js.map +1 -1
- package/dist/app/chat/tool-cells/FilesChangedSummary.d.ts.map +1 -1
- package/dist/app/chat/tool-cells/FilesChangedSummary.js +23 -81
- package/dist/app/chat/tool-cells/FilesChangedSummary.js.map +1 -1
- package/dist/app/chat/tool-cells/WriteCell.d.ts.map +1 -1
- package/dist/app/chat/tool-cells/WriteCell.js +5 -24
- package/dist/app/chat/tool-cells/WriteCell.js.map +1 -1
- package/dist/app/code-highlighter.d.ts +11 -0
- package/dist/app/code-highlighter.d.ts.map +1 -0
- package/dist/app/code-highlighter.js +122 -0
- package/dist/app/code-highlighter.js.map +1 -0
- package/dist/app/context-xray/ThreadContextRing.js +3 -3
- package/dist/app/context-xray/ThreadContextRing.js.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.js +22 -0
- package/dist/app/i18n/catalogs/ar-SA.js.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.js +22 -0
- package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
- package/dist/app/i18n/catalogs/en-US.d.ts +22 -0
- package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/en-US.js +22 -0
- package/dist/app/i18n/catalogs/en-US.js.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.js +22 -0
- package/dist/app/i18n/catalogs/es-ES.js.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.js +22 -0
- package/dist/app/i18n/catalogs/fr-FR.js.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.js +22 -0
- package/dist/app/i18n/catalogs/hi-IN.js.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.js +22 -0
- package/dist/app/i18n/catalogs/ja-JP.js.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.js +22 -0
- package/dist/app/i18n/catalogs/ko-KR.js.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.js +22 -0
- package/dist/app/i18n/catalogs/pt-BR.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.js +22 -0
- package/dist/app/i18n/catalogs/zh-CN.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.js +22 -0
- package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
- package/dist/app/onboarding/first-run-first-paint.d.ts +10 -0
- package/dist/app/onboarding/first-run-first-paint.d.ts.map +1 -0
- package/dist/app/onboarding/first-run-first-paint.js +22 -0
- package/dist/app/onboarding/first-run-first-paint.js.map +1 -0
- package/dist/app/onboarding/first-run-startup-gate.d.ts +3 -1
- package/dist/app/onboarding/first-run-startup-gate.d.ts.map +1 -1
- package/dist/app/onboarding/first-run-startup-gate.js +30 -6
- package/dist/app/onboarding/first-run-startup-gate.js.map +1 -1
- package/dist/app/providers/AppProviders.d.ts.map +1 -1
- package/dist/app/providers/AppProviders.js +9 -2
- package/dist/app/providers/AppProviders.js.map +1 -1
- package/dist/app/providers/BuilderSignupActivation.d.ts +2 -1
- package/dist/app/providers/BuilderSignupActivation.d.ts.map +1 -1
- package/dist/app/providers/BuilderSignupActivation.js +6 -3
- package/dist/app/providers/BuilderSignupActivation.js.map +1 -1
- package/dist/app/shared/AppShellSkeleton.d.ts.map +1 -1
- package/dist/app/shared/AppShellSkeleton.js +11 -1
- package/dist/app/shared/AppShellSkeleton.js.map +1 -1
- package/dist/app/styles/agent-native.css +2 -2
- package/dist/app/styles/tokens/agent-kit.css +20 -3
- package/dist/composer/AgentSuggestionBar.d.ts.map +1 -1
- package/dist/composer/AgentSuggestionBar.js +2 -2
- package/dist/composer/AgentSuggestionBar.js.map +1 -1
- package/dist/composer/ComposerContextMenu.js +4 -4
- package/dist/composer/ComposerContextMenu.js.map +1 -1
- package/dist/composer/ComposerContextPicker.d.ts.map +1 -1
- package/dist/composer/ComposerContextPicker.js +2 -2
- package/dist/composer/ComposerContextPicker.js.map +1 -1
- package/dist/composer/ComposerContextPickerDialog.d.ts.map +1 -1
- package/dist/composer/ComposerContextPickerDialog.js +2 -2
- package/dist/composer/ComposerContextPickerDialog.js.map +1 -1
- package/dist/composer/ComposerModePicker.d.ts.map +1 -1
- package/dist/composer/ComposerModePicker.js +2 -1
- package/dist/composer/ComposerModePicker.js.map +1 -1
- package/dist/composer/ComposerPlusMenu.js +1 -1
- package/dist/composer/ComposerPlusMenu.js.map +1 -1
- package/dist/composer/MentionChip.js +1 -1
- package/dist/composer/MentionChip.js.map +1 -1
- package/dist/composer/MentionPopover.d.ts +3 -0
- package/dist/composer/MentionPopover.d.ts.map +1 -1
- package/dist/composer/MentionPopover.js +34 -15
- package/dist/composer/MentionPopover.js.map +1 -1
- package/dist/composer/MessageQueueDrawer.d.ts.map +1 -1
- package/dist/composer/MessageQueueDrawer.js +14 -9
- package/dist/composer/MessageQueueDrawer.js.map +1 -1
- package/dist/composer/PastedTextChip.d.ts.map +1 -1
- package/dist/composer/PastedTextChip.js +14 -18
- package/dist/composer/PastedTextChip.js.map +1 -1
- package/dist/composer/PromptBar.js +1 -1
- package/dist/composer/PromptBar.js.map +1 -1
- package/dist/composer/PromptComposer.d.ts.map +1 -1
- package/dist/composer/PromptComposer.js +11 -9
- package/dist/composer/PromptComposer.js.map +1 -1
- package/dist/composer/RealtimeVoiceMode.js +2 -2
- package/dist/composer/RealtimeVoiceMode.js.map +1 -1
- package/dist/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/composer/TiptapComposer.js +52 -89
- package/dist/composer/TiptapComposer.js.map +1 -1
- package/dist/composer/VoiceButton.d.ts +3 -1
- package/dist/composer/VoiceButton.d.ts.map +1 -1
- package/dist/composer/VoiceButton.js +10 -8
- package/dist/composer/VoiceButton.js.map +1 -1
- package/dist/composer/composer-notice.js +3 -3
- package/dist/composer/composer-notice.js.map +1 -1
- package/dist/composer/extensions/FileReference.js +1 -1
- package/dist/composer/extensions/FileReference.js.map +1 -1
- package/dist/composer/extensions/SkillReference.js +1 -1
- package/dist/composer/extensions/SkillReference.js.map +1 -1
- package/dist/composer/popover-surface.d.ts +1 -1
- package/dist/composer/popover-surface.d.ts.map +1 -1
- package/dist/composer/popover-surface.js +1 -1
- package/dist/composer/popover-surface.js.map +1 -1
- package/dist/context-ui/ContextUsageRing.d.ts +1 -45
- package/dist/context-ui/ContextUsageRing.d.ts.map +1 -1
- package/dist/context-ui/ContextUsageRing.js +2 -87
- package/dist/context-ui/ContextUsageRing.js.map +1 -1
- package/dist/context-ui/index.d.ts +2 -2
- package/dist/context-ui/index.d.ts.map +1 -1
- package/dist/context-ui/index.js +2 -2
- package/dist/context-ui/index.js.map +1 -1
- package/package.json +4 -4
- package/src/app/agentkit/react/approval-card.tsx +14 -2
- package/src/app/agentkit/react/code-block.spec.tsx +154 -0
- package/src/app/agentkit/react/code-block.tsx +317 -0
- package/src/app/agentkit/react/components.interaction.spec.tsx +7 -0
- package/src/app/agentkit/react/components.papercuts.spec.tsx +143 -2
- package/src/app/agentkit/react/components.spec.tsx +40 -47
- package/src/app/agentkit/react/components.tsx +1533 -413
- package/src/app/agentkit/react/composer-context.spec.tsx +35 -0
- package/src/app/agentkit/react/context-usage.tsx +353 -0
- package/src/app/agentkit/react/context.tsx +93 -1
- package/src/app/agentkit/react/disclosure-content.ts +42 -0
- package/src/app/agentkit/react/disclosures.spec.tsx +62 -4
- package/src/app/agentkit/react/duration.ts +22 -0
- package/src/app/agentkit/react/file-change.spec.tsx +124 -0
- package/src/app/agentkit/react/file-change.tsx +228 -0
- package/src/app/agentkit/react/file-diff.ts +110 -0
- package/src/app/agentkit/react/index.ts +7 -0
- package/src/app/agentkit/react/lifecycle.spec.tsx +565 -20
- package/src/app/agentkit/react/markdown.spec.tsx +18 -8
- package/src/app/agentkit/react/message-actions.spec.tsx +55 -1
- package/src/app/agentkit/react/notices.spec.tsx +4 -4
- package/src/app/agentkit/react/optimistic-send.spec.tsx +43 -0
- package/src/app/agentkit/react/question-card.spec.tsx +276 -0
- package/src/app/agentkit/react/question-card.tsx +533 -0
- package/src/app/agentkit/react/root.tsx +4 -0
- package/src/app/agentkit/react/roving-focus.spec.tsx +114 -0
- package/src/app/agentkit/react/roving-focus.ts +82 -0
- package/src/app/agentkit/react/stack-trace.spec.tsx +177 -0
- package/src/app/agentkit/react/stack-trace.tsx +281 -0
- package/src/app/agentkit/react/stop-button.spec.tsx +40 -0
- package/src/app/agentkit/react/stop-button.tsx +22 -5
- package/src/app/agentkit/react/styles.css +1306 -395
- package/src/app/agentkit/react/subagent-step.spec.tsx +554 -0
- package/src/app/agentkit/react/terminal.spec.tsx +228 -0
- package/src/app/agentkit/react/terminal.tsx +228 -0
- package/src/app/agentkit/react/trace.spec.tsx +120 -0
- package/src/app/agentkit/react/trace.tsx +239 -0
- package/src/app/blocks/library/HighlightedCode.tsx +14 -126
- package/src/app/chat/AgentKitAssistantChat.spec.tsx +28 -12
- package/src/app/chat/AgentKitAssistantChat.tsx +27 -253
- package/src/app/chat/agentkit-chat/approval-card.spec.tsx +1 -0
- package/src/app/chat/agentkit-chat/guided-questions.flow.spec.tsx +381 -0
- package/src/app/chat/agentkit-chat/guided-questions.tsx +236 -3
- package/src/app/chat/agentkit-chat/history.tsx +1 -1
- package/src/app/chat/agentkit-chat/index.ts +2 -0
- package/src/app/chat/agentkit-chat/labels.ts +259 -0
- package/src/app/chat/agentkit-chat/questions.ts +2 -0
- package/src/app/chat/agentkit-chat/root.spec.tsx +18 -0
- package/src/app/chat/agentkit-chat/root.tsx +5 -64
- package/src/app/chat/agentkit-chat/work-step-labels.ts +42 -0
- package/src/app/chat/chat/markdown-renderer.tsx +2 -59
- package/src/app/chat/chat/tool-call-display.spec.tsx +26 -14
- package/src/app/chat/chat/tool-call-display.tsx +2 -1
- package/src/app/chat/conversation/AgentConversation.tsx +2 -50
- package/src/app/chat/tool-cells/BashCell.tsx +14 -136
- package/src/app/chat/tool-cells/EditCell.tsx +11 -248
- package/src/app/chat/tool-cells/FilesChangedSummary.spec.tsx +62 -5
- package/src/app/chat/tool-cells/FilesChangedSummary.tsx +31 -162
- package/src/app/chat/tool-cells/WriteCell.tsx +11 -121
- package/src/app/code-highlighter.ts +131 -0
- package/src/app/context-xray/ThreadContextRing.tsx +7 -7
- package/src/app/i18n/catalogs/ar-SA.ts +22 -0
- package/src/app/i18n/catalogs/de-DE.ts +22 -0
- package/src/app/i18n/catalogs/en-US.ts +22 -0
- package/src/app/i18n/catalogs/es-ES.ts +22 -0
- package/src/app/i18n/catalogs/fr-FR.ts +22 -0
- package/src/app/i18n/catalogs/hi-IN.ts +22 -0
- package/src/app/i18n/catalogs/ja-JP.ts +22 -0
- package/src/app/i18n/catalogs/ko-KR.ts +22 -0
- package/src/app/i18n/catalogs/pt-BR.ts +22 -0
- package/src/app/i18n/catalogs/zh-CN.ts +22 -0
- package/src/app/i18n/catalogs/zh-TW.ts +22 -0
- package/src/app/onboarding/first-run-first-paint.spec.ts +39 -0
- package/src/app/onboarding/first-run-first-paint.ts +24 -0
- package/src/app/onboarding/first-run-startup-gate.spec.tsx +125 -13
- package/src/app/onboarding/first-run-startup-gate.tsx +48 -5
- package/src/app/providers/AppProviders.tsx +18 -0
- package/src/app/providers/BuilderSignupActivation.tsx +8 -2
- package/src/app/shared/AppShellSkeleton.spec.tsx +60 -1
- package/src/app/shared/AppShellSkeleton.tsx +31 -1
- package/src/app/styles/agent-native.css +2 -2
- package/src/app/styles/agent-native.spec.ts +2 -2
- package/src/app/styles/tokens/agent-kit.css +20 -3
- package/src/composer/AgentSuggestionBar.spec.tsx +3 -1
- package/src/composer/AgentSuggestionBar.tsx +5 -2
- package/src/composer/ComposerContextMenu.tsx +4 -4
- package/src/composer/ComposerContextPicker.tsx +8 -2
- package/src/composer/ComposerContextPickerDialog.tsx +5 -2
- package/src/composer/ComposerModePicker.tsx +2 -1
- package/src/composer/ComposerPlusMenu.tsx +1 -1
- package/src/composer/MentionChip.tsx +1 -1
- package/src/composer/MentionPopover.spec.tsx +108 -2
- package/src/composer/MentionPopover.tsx +93 -17
- package/src/composer/MessageQueueDrawer.spec.tsx +5 -5
- package/src/composer/MessageQueueDrawer.tsx +19 -12
- package/src/composer/PastedTextChip.spec.tsx +36 -0
- package/src/composer/PastedTextChip.tsx +52 -58
- package/src/composer/PromptBar.tsx +1 -1
- package/src/composer/PromptComposer.context.spec.tsx +2 -2
- package/src/composer/PromptComposer.submission.spec.tsx +27 -0
- package/src/composer/PromptComposer.tsx +17 -9
- package/src/composer/RealtimeVoiceMode.tsx +2 -2
- package/src/composer/TiptapComposer.model-picker.spec.tsx +23 -82
- package/src/composer/TiptapComposer.tsx +68 -145
- package/src/composer/VoiceButton.tsx +12 -7
- package/src/composer/composer-notice.tsx +3 -3
- package/src/composer/extensions/FileReference.tsx +1 -1
- package/src/composer/extensions/SkillReference.tsx +1 -1
- package/src/composer/popover-surface.ts +1 -1
- package/src/context-ui/ContextUsageRing.spec.tsx +33 -8
- package/src/context-ui/ContextUsageRing.tsx +13 -348
- package/src/context-ui/index.ts +7 -1
- package/dist/composer/ModelPickerParts.d.ts +0 -20
- package/dist/composer/ModelPickerParts.d.ts.map +0 -1
- package/dist/composer/ModelPickerParts.js +0 -77
- package/dist/composer/ModelPickerParts.js.map +0 -1
- package/src/composer/ModelPickerParts.tsx +0 -188
|
@@ -153,9 +153,14 @@ async function click(element: Element | null | undefined) {
|
|
|
153
153
|
|
|
154
154
|
function expectSharedSummary(trigger: HTMLElement | null) {
|
|
155
155
|
expect(trigger?.tagName).toBe("BUTTON");
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
// A trace line is `display: contents`: its parts are the summary's boxes.
|
|
157
|
+
const children = Array.from(trigger?.children ?? [])
|
|
158
|
+
.flatMap((child) =>
|
|
159
|
+
child.classList.contains("agentkit-trace-line")
|
|
160
|
+
? Array.from(child.children)
|
|
161
|
+
: [child],
|
|
162
|
+
)
|
|
163
|
+
.map((child) => child.classList[child.classList.length - 1]);
|
|
159
164
|
// Icon column first, then the label, then the chevron right after it.
|
|
160
165
|
expect(children).toEqual([
|
|
161
166
|
"agentkit-disclosure-icon-slot",
|
|
@@ -224,7 +229,10 @@ describe("AgentKit disclosures", () => {
|
|
|
224
229
|
);
|
|
225
230
|
expect(item.textContent).toContain("First file contents");
|
|
226
231
|
await click(itemTrigger);
|
|
227
|
-
|
|
232
|
+
// Closed, it stays in the DOM for find-in-page.
|
|
233
|
+
expect(
|
|
234
|
+
item.querySelector(".agentkit-activity-summary")?.getAttribute("hidden"),
|
|
235
|
+
).toBe("until-found");
|
|
228
236
|
|
|
229
237
|
// A row with nothing to expand is text, not a disabled button.
|
|
230
238
|
const plain = work.querySelectorAll<HTMLElement>(
|
|
@@ -1028,3 +1036,53 @@ describe("a turn that only answered", () => {
|
|
|
1028
1036
|
).toBe("Worked for 4s");
|
|
1029
1037
|
});
|
|
1030
1038
|
});
|
|
1039
|
+
|
|
1040
|
+
describe("Sources", () => {
|
|
1041
|
+
const cited = answer([
|
|
1042
|
+
{ type: "text", text: "The release shipped on Tuesday." },
|
|
1043
|
+
{ type: "citation", title: "Release notes", url: "https://example.com/r" },
|
|
1044
|
+
{ type: "citation", title: "Release notes", url: "https://example.com/r" },
|
|
1045
|
+
{ type: "citation", title: "", url: "https://docs.example.com/guide" },
|
|
1046
|
+
]);
|
|
1047
|
+
|
|
1048
|
+
it("collapses a message's citations into one deduped sources step", async () => {
|
|
1049
|
+
const view = await renderThread([user, cited], eventsOf([], cited));
|
|
1050
|
+
const sources = view.querySelector<HTMLElement>(".agentkit-sources");
|
|
1051
|
+
const trigger = sources?.querySelector<HTMLElement>(
|
|
1052
|
+
"button.agentkit-disclosure-summary",
|
|
1053
|
+
);
|
|
1054
|
+
expectSharedSummary(trigger ?? null);
|
|
1055
|
+
expect(trigger?.textContent).toBe("Used 2 sources");
|
|
1056
|
+
expect(trigger?.getAttribute("aria-expanded")).toBe("false");
|
|
1057
|
+
|
|
1058
|
+
// Closed sources stay findable in the page.
|
|
1059
|
+
const content = sources?.querySelector<HTMLElement>(
|
|
1060
|
+
'[data-slot="trace-collapsible-content"]',
|
|
1061
|
+
);
|
|
1062
|
+
expect(content?.getAttribute("hidden")).toBe("until-found");
|
|
1063
|
+
const links = Array.from(
|
|
1064
|
+
content?.querySelectorAll<HTMLAnchorElement>("a") ?? [],
|
|
1065
|
+
(link) => [link.textContent, link.getAttribute("href")],
|
|
1066
|
+
);
|
|
1067
|
+
expect(links).toEqual([
|
|
1068
|
+
["Release notes", "https://example.com/r"],
|
|
1069
|
+
["docs.example.com", "https://docs.example.com/guide"],
|
|
1070
|
+
]);
|
|
1071
|
+
|
|
1072
|
+
await click(trigger);
|
|
1073
|
+
expect(trigger?.getAttribute("aria-expanded")).toBe("true");
|
|
1074
|
+
expect(content?.hidden).toBe(false);
|
|
1075
|
+
});
|
|
1076
|
+
|
|
1077
|
+
it("names a single source in the singular", async () => {
|
|
1078
|
+
const one = answer([
|
|
1079
|
+
{ type: "text", text: "See the guide." },
|
|
1080
|
+
{ type: "citation", title: "Guide", url: "https://example.com/g" },
|
|
1081
|
+
]);
|
|
1082
|
+
const view = await renderThread([user, one], eventsOf([], one));
|
|
1083
|
+
expect(
|
|
1084
|
+
view.querySelector(".agentkit-sources .agentkit-disclosure-label")
|
|
1085
|
+
?.textContent,
|
|
1086
|
+
).toBe("Used 1 source");
|
|
1087
|
+
});
|
|
1088
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function formatAgentKitDuration(
|
|
2
|
+
ms: number,
|
|
3
|
+
units: { hour?: string; minute?: string; second?: string } = {},
|
|
4
|
+
): string {
|
|
5
|
+
const hour = units.hour ?? "h";
|
|
6
|
+
const minute = units.minute ?? "m";
|
|
7
|
+
const second = units.second ?? "s";
|
|
8
|
+
const totalSeconds = Math.max(0, Math.round(ms / 1_000));
|
|
9
|
+
if (totalSeconds < 60) return `${Math.max(1, totalSeconds)}${second}`;
|
|
10
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
11
|
+
const seconds = totalSeconds % 60;
|
|
12
|
+
if (minutes < 60) {
|
|
13
|
+
return seconds === 0
|
|
14
|
+
? `${minutes}${minute}`
|
|
15
|
+
: `${minutes}${minute} ${seconds}${second}`;
|
|
16
|
+
}
|
|
17
|
+
const hours = Math.floor(minutes / 60);
|
|
18
|
+
const remainingMinutes = minutes % 60;
|
|
19
|
+
return remainingMinutes === 0
|
|
20
|
+
? `${hours}${hour}`
|
|
21
|
+
: `${hours}${hour} ${remainingMinutes}${minute}`;
|
|
22
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
|
|
3
|
+
import { act, type ReactNode } from "react";
|
|
4
|
+
import { createRoot, type Root } from "react-dom/client";
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
6
|
+
|
|
7
|
+
import { FileChange } from "./file-change.js";
|
|
8
|
+
import { computeLineDiff } from "./file-diff.js";
|
|
9
|
+
|
|
10
|
+
let root: Root;
|
|
11
|
+
let container: HTMLDivElement;
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
|
|
15
|
+
container = document.createElement("div");
|
|
16
|
+
document.body.append(container);
|
|
17
|
+
root = createRoot(container);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
act(() => root.unmount());
|
|
22
|
+
container.remove();
|
|
23
|
+
vi.unstubAllGlobals();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
async function render(node: ReactNode) {
|
|
27
|
+
await act(async () => root.render(node));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const lines = (count: number) =>
|
|
31
|
+
Array.from({ length: count }, (_, index) => `line ${index + 1}`).join("\n");
|
|
32
|
+
|
|
33
|
+
describe("FileChange", () => {
|
|
34
|
+
it("shows an edit as a diff with markers instead of colors alone", async () => {
|
|
35
|
+
await render(
|
|
36
|
+
<FileChange
|
|
37
|
+
defaultOpen
|
|
38
|
+
change={{
|
|
39
|
+
kind: "edit",
|
|
40
|
+
filePath: "src/app.ts",
|
|
41
|
+
oldText: "const a = 1;\nexport { a };",
|
|
42
|
+
newText: "const a = 2;\nexport { a };",
|
|
43
|
+
}}
|
|
44
|
+
/>,
|
|
45
|
+
);
|
|
46
|
+
expect(
|
|
47
|
+
Array.from(
|
|
48
|
+
container.querySelectorAll<HTMLElement>(".agentkit-code-line"),
|
|
49
|
+
(line) => line.dataset.variant ?? "context",
|
|
50
|
+
),
|
|
51
|
+
).toEqual(["removed", "added", "context"]);
|
|
52
|
+
expect(container.querySelector("pre")?.textContent).toBe(
|
|
53
|
+
"Removed const a = 1;\nAdded const a = 2;\nexport { a };",
|
|
54
|
+
);
|
|
55
|
+
expect(
|
|
56
|
+
container.querySelector("[data-agent-file-change-stats]")?.textContent,
|
|
57
|
+
).toBe("+1−1");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("shows a new file with line numbers and its first 40 lines", async () => {
|
|
61
|
+
await render(
|
|
62
|
+
<FileChange
|
|
63
|
+
defaultOpen
|
|
64
|
+
change={{ kind: "write", filePath: "src/new.ts", content: lines(45) }}
|
|
65
|
+
/>,
|
|
66
|
+
);
|
|
67
|
+
const pre = () => container.querySelector("pre");
|
|
68
|
+
expect(pre()?.dataset.lineNumbers).toBe("true");
|
|
69
|
+
expect(pre()?.querySelector("code")?.dataset.language).toBe("ts");
|
|
70
|
+
expect(pre()?.textContent?.split("\n")).toHaveLength(40);
|
|
71
|
+
const more = container.querySelector<HTMLButtonElement>(
|
|
72
|
+
".agentkit-code-block-footer button",
|
|
73
|
+
);
|
|
74
|
+
expect(more?.textContent).toBe("Show 5 more lines");
|
|
75
|
+
await act(async () => more?.click());
|
|
76
|
+
expect(pre()?.textContent?.split("\n")).toHaveLength(45);
|
|
77
|
+
expect(
|
|
78
|
+
container.querySelector("[data-agent-file-change-stats]")?.textContent,
|
|
79
|
+
).toBe("+45");
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("marks a cut-short change and hides counts while it runs", async () => {
|
|
83
|
+
await render(
|
|
84
|
+
<FileChange
|
|
85
|
+
change={{
|
|
86
|
+
kind: "write",
|
|
87
|
+
filePath: "big.json",
|
|
88
|
+
lineCount: 9000,
|
|
89
|
+
truncated: true,
|
|
90
|
+
}}
|
|
91
|
+
/>,
|
|
92
|
+
);
|
|
93
|
+
// Nothing was kept, so there is nothing to open.
|
|
94
|
+
expect(container.querySelector("button")).toBeNull();
|
|
95
|
+
expect(
|
|
96
|
+
container.querySelector("[data-agent-file-change-stats]")?.textContent,
|
|
97
|
+
).toBe("+9000Partial");
|
|
98
|
+
|
|
99
|
+
await render(
|
|
100
|
+
<FileChange
|
|
101
|
+
running
|
|
102
|
+
change={{ kind: "edit", filePath: "a.ts", oldText: "a", newText: "b" }}
|
|
103
|
+
/>,
|
|
104
|
+
);
|
|
105
|
+
expect(
|
|
106
|
+
container.querySelector("[data-agent-file-change-stats]"),
|
|
107
|
+
).toBeNull();
|
|
108
|
+
expect(
|
|
109
|
+
container
|
|
110
|
+
.querySelector('[data-slot="trace-line"]')
|
|
111
|
+
?.getAttribute("data-trace-status"),
|
|
112
|
+
).toBe("running");
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe("computeLineDiff", () => {
|
|
117
|
+
it("keeps an unchanged line after an edit as context", () => {
|
|
118
|
+
expect(
|
|
119
|
+
computeLineDiff("a\nshared\nb", "A\nshared\nB").map(
|
|
120
|
+
(line) => `${line.kind[0]}${line.text}`,
|
|
121
|
+
),
|
|
122
|
+
).toEqual(["ra", "aA", "cshared", "rb", "aB"]);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { IconFileDiff, IconFilePlus } from "@tabler/icons-react";
|
|
2
|
+
import { useMemo, useState } from "react";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
CodeBlock,
|
|
6
|
+
CodeBlockContent,
|
|
7
|
+
CodeBlockFooter,
|
|
8
|
+
CodeBlockLine,
|
|
9
|
+
} from "./code-block.js";
|
|
10
|
+
import { useAgentKitLabels } from "./context.js";
|
|
11
|
+
import { cachedLineDiff, diffStats } from "./file-diff.js";
|
|
12
|
+
import {
|
|
13
|
+
TraceCollapsible,
|
|
14
|
+
TraceCollapsibleContent,
|
|
15
|
+
TraceCollapsibleTrigger,
|
|
16
|
+
TraceDescription,
|
|
17
|
+
TraceIcon,
|
|
18
|
+
TraceLine,
|
|
19
|
+
TraceTitle,
|
|
20
|
+
type TraceCollapsibleOpenProps,
|
|
21
|
+
} from "./trace.js";
|
|
22
|
+
|
|
23
|
+
const MAX_COLLAPSED_LINES = 40;
|
|
24
|
+
|
|
25
|
+
const EXTENSION_LANGUAGES: Record<string, string> = {
|
|
26
|
+
mjs: "javascript",
|
|
27
|
+
cjs: "javascript",
|
|
28
|
+
mts: "typescript",
|
|
29
|
+
cts: "typescript",
|
|
30
|
+
htm: "html",
|
|
31
|
+
zsh: "bash",
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export interface FileChangeData {
|
|
35
|
+
filePath: string;
|
|
36
|
+
/** `edit` uses `oldText` and `newText`; `write` uses `content`. */
|
|
37
|
+
kind: "edit" | "write";
|
|
38
|
+
oldText?: string | undefined;
|
|
39
|
+
newText?: string | undefined;
|
|
40
|
+
content?: string | undefined;
|
|
41
|
+
/** A write's line count when its content was not kept. */
|
|
42
|
+
lineCount?: number | undefined;
|
|
43
|
+
truncated?: boolean | undefined;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function fileChangeStats(change: FileChangeData): {
|
|
47
|
+
added: number;
|
|
48
|
+
removed: number;
|
|
49
|
+
} {
|
|
50
|
+
if (change.kind === "write") {
|
|
51
|
+
return {
|
|
52
|
+
added:
|
|
53
|
+
change.lineCount ??
|
|
54
|
+
(change.content ? change.content.split("\n").length : 0),
|
|
55
|
+
removed: 0,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (!change.oldText && !change.newText) return { added: 0, removed: 0 };
|
|
59
|
+
return diffStats(cachedLineDiff(change.oldText ?? "", change.newText ?? ""));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function fileLanguage(filePath: string): string | undefined {
|
|
63
|
+
const name = filePath.split(/[/\\]/).at(-1) ?? "";
|
|
64
|
+
const dot = name.lastIndexOf(".");
|
|
65
|
+
if (dot <= 0) return undefined;
|
|
66
|
+
const extension = name.slice(dot + 1).toLowerCase();
|
|
67
|
+
return EXTENSION_LANGUAGES[extension] ?? extension;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** A long directory truncates before the file name does. */
|
|
71
|
+
export function FilePath({ filePath }: { filePath: string }) {
|
|
72
|
+
const separator = filePath.lastIndexOf("/");
|
|
73
|
+
const directory = separator < 0 ? "" : filePath.slice(0, separator + 1);
|
|
74
|
+
const fileName = separator < 0 ? filePath : filePath.slice(separator + 1);
|
|
75
|
+
return (
|
|
76
|
+
<TraceTitle
|
|
77
|
+
className="agentkit-file-path"
|
|
78
|
+
title={filePath}
|
|
79
|
+
data-agent-file-change-path=""
|
|
80
|
+
>
|
|
81
|
+
{directory ? (
|
|
82
|
+
<span className="agentkit-file-path-directory">{directory}</span>
|
|
83
|
+
) : null}
|
|
84
|
+
<span className="agentkit-file-path-name">{fileName}</span>
|
|
85
|
+
</TraceTitle>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function FileChangeStats({ change }: { change: FileChangeData }) {
|
|
90
|
+
const labels = useAgentKitLabels();
|
|
91
|
+
const { added, removed } = fileChangeStats(change);
|
|
92
|
+
return (
|
|
93
|
+
<TraceDescription
|
|
94
|
+
className="agentkit-file-change-stats"
|
|
95
|
+
data-agent-file-change-stats=""
|
|
96
|
+
>
|
|
97
|
+
<span data-sign="added">+{added}</span>
|
|
98
|
+
{change.kind === "edit" ? (
|
|
99
|
+
<span data-sign="removed">−{removed}</span>
|
|
100
|
+
) : null}
|
|
101
|
+
{change.truncated ? <span>{labels.workStepFilePartial}</span> : null}
|
|
102
|
+
</TraceDescription>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function FileChangeBody({ change }: { change: FileChangeData }) {
|
|
107
|
+
const labels = useAgentKitLabels();
|
|
108
|
+
const [showAll, setShowAll] = useState(false);
|
|
109
|
+
const diff = useMemo(
|
|
110
|
+
() =>
|
|
111
|
+
change.kind === "edit" && (change.oldText || change.newText)
|
|
112
|
+
? cachedLineDiff(change.oldText ?? "", change.newText ?? "")
|
|
113
|
+
: undefined,
|
|
114
|
+
[change.kind, change.oldText, change.newText],
|
|
115
|
+
);
|
|
116
|
+
const lines = diff ?? (change.content ? change.content.split("\n") : []);
|
|
117
|
+
if (!lines.length) return null;
|
|
118
|
+
const hidden = showAll ? 0 : Math.max(0, lines.length - MAX_COLLAPSED_LINES);
|
|
119
|
+
const footer = hidden ? (
|
|
120
|
+
<CodeBlockFooter>
|
|
121
|
+
<button
|
|
122
|
+
type="button"
|
|
123
|
+
className="agentkit-terminal-earlier"
|
|
124
|
+
onClick={() => setShowAll(true)}
|
|
125
|
+
>
|
|
126
|
+
{labels.workStepFileMoreLines.replace("{{count}}", () => `${hidden}`)}
|
|
127
|
+
</button>
|
|
128
|
+
</CodeBlockFooter>
|
|
129
|
+
) : null;
|
|
130
|
+
if (diff) {
|
|
131
|
+
const visible = hidden ? diff.slice(0, MAX_COLLAPSED_LINES) : diff;
|
|
132
|
+
return (
|
|
133
|
+
<CodeBlock size="sm" className="agentkit-file-change-body">
|
|
134
|
+
<CodeBlockContent wrap>
|
|
135
|
+
{visible.map((line, index) => (
|
|
136
|
+
<CodeBlockLine
|
|
137
|
+
key={index}
|
|
138
|
+
variant={line.kind === "context" ? "default" : line.kind}
|
|
139
|
+
>
|
|
140
|
+
{line.text}
|
|
141
|
+
</CodeBlockLine>
|
|
142
|
+
))}
|
|
143
|
+
</CodeBlockContent>
|
|
144
|
+
{footer}
|
|
145
|
+
</CodeBlock>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
const content = change.content ?? "";
|
|
149
|
+
return (
|
|
150
|
+
<CodeBlock size="sm" className="agentkit-file-change-body">
|
|
151
|
+
<CodeBlockContent
|
|
152
|
+
wrap
|
|
153
|
+
lineNumbers
|
|
154
|
+
language={fileLanguage(change.filePath)}
|
|
155
|
+
>
|
|
156
|
+
{hidden
|
|
157
|
+
? content.split("\n").slice(0, MAX_COLLAPSED_LINES).join("\n")
|
|
158
|
+
: content}
|
|
159
|
+
</CodeBlockContent>
|
|
160
|
+
{footer}
|
|
161
|
+
</CodeBlock>
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function FileChange({
|
|
166
|
+
change,
|
|
167
|
+
running = false,
|
|
168
|
+
defaultOpen = false,
|
|
169
|
+
className,
|
|
170
|
+
...openProps
|
|
171
|
+
}: TraceCollapsibleOpenProps & {
|
|
172
|
+
change: FileChangeData;
|
|
173
|
+
running?: boolean;
|
|
174
|
+
defaultOpen?: boolean;
|
|
175
|
+
className?: string;
|
|
176
|
+
}) {
|
|
177
|
+
const labels = useAgentKitLabels();
|
|
178
|
+
const hasBody =
|
|
179
|
+
change.kind === "edit"
|
|
180
|
+
? Boolean(change.oldText || change.newText)
|
|
181
|
+
: Boolean(change.content);
|
|
182
|
+
const line = (
|
|
183
|
+
<TraceLine status={running ? "running" : undefined}>
|
|
184
|
+
<TraceIcon>
|
|
185
|
+
{change.kind === "edit" ? (
|
|
186
|
+
<IconFileDiff aria-hidden="true" className="agentkit-icon" />
|
|
187
|
+
) : (
|
|
188
|
+
<IconFilePlus aria-hidden="true" className="agentkit-icon" />
|
|
189
|
+
)}
|
|
190
|
+
</TraceIcon>
|
|
191
|
+
<FilePath filePath={change.filePath} />
|
|
192
|
+
{running ? (
|
|
193
|
+
<span className="agentkit-visually-hidden">
|
|
194
|
+
{labels.taskStatusRunning}
|
|
195
|
+
</span>
|
|
196
|
+
) : (
|
|
197
|
+
<FileChangeStats change={change} />
|
|
198
|
+
)}
|
|
199
|
+
</TraceLine>
|
|
200
|
+
);
|
|
201
|
+
const classes = className
|
|
202
|
+
? `agentkit-file-change ${className}`
|
|
203
|
+
: "agentkit-file-change";
|
|
204
|
+
if (!hasBody) {
|
|
205
|
+
return (
|
|
206
|
+
<div className={classes} data-kind={change.kind}>
|
|
207
|
+
<span className="agentkit-disclosure-summary" data-expandable="false">
|
|
208
|
+
{line}
|
|
209
|
+
</span>
|
|
210
|
+
</div>
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
return (
|
|
214
|
+
<TraceCollapsible
|
|
215
|
+
{...openProps}
|
|
216
|
+
defaultOpen={defaultOpen}
|
|
217
|
+
className={classes}
|
|
218
|
+
data-kind={change.kind}
|
|
219
|
+
>
|
|
220
|
+
<TraceCollapsibleTrigger data-agent-file-change-row="">
|
|
221
|
+
{line}
|
|
222
|
+
</TraceCollapsibleTrigger>
|
|
223
|
+
<TraceCollapsibleContent className="agentkit-file-change-content">
|
|
224
|
+
<FileChangeBody change={change} />
|
|
225
|
+
</TraceCollapsibleContent>
|
|
226
|
+
</TraceCollapsible>
|
|
227
|
+
);
|
|
228
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
export interface DiffLine {
|
|
2
|
+
kind: "context" | "added" | "removed";
|
|
3
|
+
text: string;
|
|
4
|
+
oldLineNo?: number;
|
|
5
|
+
newLineNo?: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function computeLineDiff(oldText: string, newText: string): DiffLine[] {
|
|
9
|
+
const oldLines = oldText.split("\n");
|
|
10
|
+
const newLines = newText.split("\n");
|
|
11
|
+
|
|
12
|
+
const MAX_LINES = 2000;
|
|
13
|
+
const a = oldLines.slice(0, MAX_LINES);
|
|
14
|
+
const b = newLines.slice(0, MAX_LINES);
|
|
15
|
+
|
|
16
|
+
const m = a.length;
|
|
17
|
+
const n = b.length;
|
|
18
|
+
|
|
19
|
+
// LCS of suffixes: cell(i, j) covers a[i..] against b[j..].
|
|
20
|
+
const width = n + 1;
|
|
21
|
+
const lengths = new Uint32Array((m + 1) * width);
|
|
22
|
+
const cell = (row: number, column: number) =>
|
|
23
|
+
lengths.at(row * width + column) ?? 0;
|
|
24
|
+
for (let i = m - 1; i >= 0; i--) {
|
|
25
|
+
for (let j = n - 1; j >= 0; j--) {
|
|
26
|
+
lengths[i * width + j] =
|
|
27
|
+
a.at(i) === b.at(j)
|
|
28
|
+
? cell(i + 1, j + 1) + 1
|
|
29
|
+
: Math.max(cell(i + 1, j), cell(i, j + 1));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const result: DiffLine[] = [];
|
|
34
|
+
let i = 0;
|
|
35
|
+
let j = 0;
|
|
36
|
+
let oldLineNo = 1;
|
|
37
|
+
let newLineNo = 1;
|
|
38
|
+
|
|
39
|
+
for (;;) {
|
|
40
|
+
const left = a.at(i);
|
|
41
|
+
const right = b.at(j);
|
|
42
|
+
if (left === undefined && right === undefined) break;
|
|
43
|
+
if (left !== undefined && left === right) {
|
|
44
|
+
result.push({
|
|
45
|
+
kind: "context",
|
|
46
|
+
text: left,
|
|
47
|
+
oldLineNo: oldLineNo++,
|
|
48
|
+
newLineNo: newLineNo++,
|
|
49
|
+
});
|
|
50
|
+
i++;
|
|
51
|
+
j++;
|
|
52
|
+
} else if (
|
|
53
|
+
left !== undefined &&
|
|
54
|
+
(right === undefined || cell(i + 1, j) >= cell(i, j + 1))
|
|
55
|
+
) {
|
|
56
|
+
// Ties remove first, so removals precede the additions replacing them.
|
|
57
|
+
result.push({ kind: "removed", text: left, oldLineNo: oldLineNo++ });
|
|
58
|
+
i++;
|
|
59
|
+
} else if (right !== undefined) {
|
|
60
|
+
result.push({ kind: "added", text: right, newLineNo: newLineNo++ });
|
|
61
|
+
j++;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
for (const text of oldLines.slice(MAX_LINES)) {
|
|
66
|
+
result.push({ kind: "removed", text, oldLineNo: oldLineNo++ });
|
|
67
|
+
}
|
|
68
|
+
for (const text of newLines.slice(MAX_LINES)) {
|
|
69
|
+
result.push({ kind: "added", text, newLineNo: newLineNo++ });
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function diffStats(lines: DiffLine[]): {
|
|
76
|
+
added: number;
|
|
77
|
+
removed: number;
|
|
78
|
+
} {
|
|
79
|
+
let added = 0;
|
|
80
|
+
let removed = 0;
|
|
81
|
+
for (const line of lines) {
|
|
82
|
+
if (line.kind === "added") added++;
|
|
83
|
+
else if (line.kind === "removed") removed++;
|
|
84
|
+
}
|
|
85
|
+
return { added, removed };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const CACHED_DIFFS = 32;
|
|
89
|
+
const cachedDiffs = new Map<string, DiffLine[]>();
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* `computeLineDiff`, cached by text: a row's stats and its body share one
|
|
93
|
+
* quadratic pass, and a re-render reuses it.
|
|
94
|
+
*/
|
|
95
|
+
export function cachedLineDiff(oldText: string, newText: string): DiffLine[] {
|
|
96
|
+
const key = `${oldText.length}:${oldText}\u0000${newText}`;
|
|
97
|
+
const cached = cachedDiffs.get(key);
|
|
98
|
+
if (cached) {
|
|
99
|
+
cachedDiffs.delete(key);
|
|
100
|
+
cachedDiffs.set(key, cached);
|
|
101
|
+
return cached;
|
|
102
|
+
}
|
|
103
|
+
const diff = computeLineDiff(oldText, newText);
|
|
104
|
+
cachedDiffs.set(key, diff);
|
|
105
|
+
if (cachedDiffs.size > CACHED_DIFFS) {
|
|
106
|
+
const oldest = cachedDiffs.keys().next();
|
|
107
|
+
if (!oldest.done) cachedDiffs.delete(oldest.value);
|
|
108
|
+
}
|
|
109
|
+
return diff;
|
|
110
|
+
}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
export * from "./approval-card.js";
|
|
2
|
+
export * from "./question-card.js";
|
|
2
3
|
export * from "./chat.js";
|
|
4
|
+
export * from "./code-block.js";
|
|
3
5
|
export * from "./components.js";
|
|
6
|
+
export * from "./context-usage.js";
|
|
4
7
|
export * from "./context.js";
|
|
5
8
|
export * from "./data-chart-layout.js";
|
|
9
|
+
export * from "./file-change.js";
|
|
6
10
|
export * from "./message-content-order.js";
|
|
7
11
|
export {
|
|
8
12
|
AGENTKIT_CLIENT_REQUEST_ID_METADATA_KEY,
|
|
@@ -12,6 +16,9 @@ export {
|
|
|
12
16
|
type AgentKitPendingSubmissionFile,
|
|
13
17
|
} from "./pending-submissions.js";
|
|
14
18
|
export * from "./root.js";
|
|
19
|
+
export * from "./stack-trace.js";
|
|
15
20
|
export * from "./streaming-text.js";
|
|
21
|
+
export * from "./terminal.js";
|
|
22
|
+
export * from "./trace.js";
|
|
16
23
|
export * from "./transcript-layout.js";
|
|
17
24
|
export * from "./work-steps.js";
|