@deepseek-harness-tui/dsh-tui 0.11.0 → 0.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -20
- package/assets/whale-girl/whale-girl-dark.png +0 -0
- package/assets/whale-girl/whale-girl-happy.png +0 -0
- package/assets/whale-girl/whale-girl.png +0 -0
- package/bin/dsh-tui.js +63 -3
- package/cordis.patch.yml +43 -20
- package/cordis.yml +6 -4
- package/lib/settings.json +1272 -0
- package/lib/types/activityPrefs.d.ts +24 -0
- package/lib/types/activityPrefs.d.ts.map +1 -1
- package/lib/types/activityPrefs.js +50 -1
- package/lib/types/adapter/channel/state.d.ts.map +1 -1
- package/lib/types/adapter/channel/state.js +3 -1
- package/lib/types/adapter/channel/ui-policy.d.ts +9 -2
- package/lib/types/adapter/channel/ui-policy.d.ts.map +1 -1
- package/lib/types/adapter/channel/ui-policy.js +14 -1
- package/lib/types/adapter/kernel/replay.d.ts.map +1 -1
- package/lib/types/adapter/kernel/replay.js +2 -0
- package/lib/types/adapter/ports/channel-display.d.ts +12 -0
- package/lib/types/adapter/ports/channel-display.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-session.d.ts +38 -0
- package/lib/types/adapter/ports/channel-session.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-settings.d.ts +12 -0
- package/lib/types/adapter/ports/channel-settings.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-ui.d.ts +53 -7
- package/lib/types/adapter/ports/channel-ui.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-view.d.ts +43 -12
- package/lib/types/adapter/ports/channel-view.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel.d.ts +4 -1
- package/lib/types/adapter/ports/channel.d.ts.map +1 -1
- package/lib/types/commands.d.ts.map +1 -1
- package/lib/types/commands.js +2 -0
- package/lib/types/components/ActivityLine.d.ts +7 -2
- package/lib/types/components/ActivityLine.d.ts.map +1 -1
- package/lib/types/components/ActivityLine.js +0 -8
- package/lib/types/components/BalanceReportRow.d.ts +10 -2
- package/lib/types/components/BalanceReportRow.d.ts.map +1 -1
- package/lib/types/components/BalanceReportRow.js +18 -4
- package/lib/types/components/CompactionStatusRow.d.ts +24 -0
- package/lib/types/components/CompactionStatusRow.d.ts.map +1 -0
- package/lib/types/components/CompactionStatusRow.js +72 -0
- package/lib/types/components/GoalTodoPanel.js +2 -2
- package/lib/types/components/HelpMenu.d.ts +2 -2
- package/lib/types/components/HelpMenu.d.ts.map +1 -1
- package/lib/types/components/HelpMenu.js +5 -4
- package/lib/types/components/InlineMathParagraph.d.ts +22 -0
- package/lib/types/components/InlineMathParagraph.d.ts.map +1 -0
- package/lib/types/components/InlineMathParagraph.js +178 -0
- package/lib/types/components/LogoV2.d.ts +41 -3
- package/lib/types/components/LogoV2.d.ts.map +1 -1
- package/lib/types/components/LogoV2.js +148 -24
- package/lib/types/components/Markdown.d.ts +10 -3
- package/lib/types/components/Markdown.d.ts.map +1 -1
- package/lib/types/components/Markdown.js +47 -14
- package/lib/types/components/MathBlock.d.ts +13 -0
- package/lib/types/components/MathBlock.d.ts.map +1 -0
- package/lib/types/components/MathBlock.js +136 -0
- package/lib/types/components/MessageList.d.ts +10 -1
- package/lib/types/components/MessageList.d.ts.map +1 -1
- package/lib/types/components/MessageList.js +15 -5
- package/lib/types/components/MigratePicker.d.ts +30 -0
- package/lib/types/components/MigratePicker.d.ts.map +1 -0
- package/lib/types/components/MigratePicker.js +38 -0
- package/lib/types/components/PromptInput.d.ts +17 -0
- package/lib/types/components/PromptInput.d.ts.map +1 -1
- package/lib/types/components/PromptInput.js +96 -9
- package/lib/types/components/SplitDiffView.d.ts.map +1 -1
- package/lib/types/components/SplitDiffView.js +3 -1
- package/lib/types/components/StarPrompt.d.ts +53 -0
- package/lib/types/components/StarPrompt.d.ts.map +1 -0
- package/lib/types/components/StarPrompt.js +281 -0
- package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
- package/lib/types/components/StreamingMarkdown.js +20 -3
- package/lib/types/components/SubagentCard.d.ts.map +1 -1
- package/lib/types/components/SubagentCard.js +12 -6
- package/lib/types/components/SubagentDetailScene.d.ts.map +1 -1
- package/lib/types/components/SubagentDetailScene.js +8 -3
- package/lib/types/components/TimelineRail.d.ts.map +1 -1
- package/lib/types/components/TimelineRail.js +9 -1
- package/lib/types/components/Whale.d.ts +17 -8
- package/lib/types/components/Whale.d.ts.map +1 -1
- package/lib/types/components/Whale.js +25 -15
- package/lib/types/components/WhaleGirl.d.ts +29 -0
- package/lib/types/components/WhaleGirl.d.ts.map +1 -0
- package/lib/types/components/WhaleGirl.js +32 -0
- package/lib/types/components/WorkingSpinner.d.ts +4 -1
- package/lib/types/components/WorkingSpinner.d.ts.map +1 -1
- package/lib/types/components/WorkingSpinner.js +2 -2
- package/lib/types/components/bigfont.d.ts +47 -18
- package/lib/types/components/bigfont.d.ts.map +1 -1
- package/lib/types/components/bigfont.js +55 -40
- package/lib/types/components/design-system/HintLine.d.ts +1 -2
- package/lib/types/components/design-system/HintLine.d.ts.map +1 -1
- package/lib/types/components/design-system/HintLine.js +1 -2
- package/lib/types/components/design-system/ThemeProvider.d.ts +6 -0
- package/lib/types/components/design-system/ThemeProvider.d.ts.map +1 -1
- package/lib/types/components/design-system/ThemeProvider.js +40 -1
- package/lib/types/components/maidPortrait.d.ts +44 -0
- package/lib/types/components/maidPortrait.d.ts.map +1 -0
- package/lib/types/components/maidPortrait.js +178 -0
- package/lib/types/components/mathPreview.d.ts +25 -0
- package/lib/types/components/mathPreview.d.ts.map +1 -0
- package/lib/types/components/mathPreview.js +48 -0
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts +2 -1
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantThinkingMessage.js +4 -2
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts +2 -2
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantToolUseMessage.js +31 -26
- package/lib/types/components/messages/TranscriptImages.d.ts.map +1 -1
- package/lib/types/components/messages/TranscriptImages.js +11 -1
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts +14 -2
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
- package/lib/types/components/questions/AskUserQuestionPanel.js +80 -38
- package/lib/types/components/questions/PlanReviewPanel.d.ts.map +1 -1
- package/lib/types/components/questions/PlanReviewPanel.js +3 -3
- package/lib/types/components/sessions/ForeignSessionRow.d.ts +34 -0
- package/lib/types/components/sessions/ForeignSessionRow.d.ts.map +1 -0
- package/lib/types/components/sessions/ForeignSessionRow.js +43 -0
- package/lib/types/components/sessions/SourceTabs.d.ts +52 -0
- package/lib/types/components/sessions/SourceTabs.d.ts.map +1 -0
- package/lib/types/components/sessions/SourceTabs.js +70 -0
- package/lib/types/components/splashEggs.d.ts +56 -0
- package/lib/types/components/splashEggs.d.ts.map +1 -0
- package/lib/types/components/splashEggs.js +67 -0
- package/lib/types/components/splashFonts.d.ts +119 -0
- package/lib/types/components/splashFonts.d.ts.map +1 -0
- package/lib/types/components/splashFonts.js +267 -0
- package/lib/types/components/splashLayout.d.ts +41 -0
- package/lib/types/components/splashLayout.d.ts.map +1 -0
- package/lib/types/components/splashLayout.js +40 -0
- package/lib/types/components/whaleGirlSprite.d.ts +17 -0
- package/lib/types/components/whaleGirlSprite.d.ts.map +1 -0
- package/lib/types/components/whaleGirlSprite.js +47 -0
- package/lib/types/deepseekPricing.d.ts +74 -0
- package/lib/types/deepseekPricing.d.ts.map +1 -1
- package/lib/types/deepseekPricing.js +110 -11
- package/lib/types/dsh-adapter/activity-store.d.ts +221 -0
- package/lib/types/dsh-adapter/activity-store.d.ts.map +1 -0
- package/lib/types/dsh-adapter/activity-store.js +359 -0
- package/lib/types/dsh-adapter/channel/action-readiness.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/action-readiness.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/action-readiness.js +6 -1
- package/lib/types/dsh-adapter/channel/background-action.d.ts +2 -1
- package/lib/types/dsh-adapter/channel/background-action.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/background-action.js +2 -0
- package/lib/types/dsh-adapter/channel/binding-events.d.ts +15 -14
- package/lib/types/dsh-adapter/channel/binding-events.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/binding-events.js +70 -21
- package/lib/types/dsh-adapter/channel/compaction.d.ts +2 -2
- package/lib/types/dsh-adapter/channel/compaction.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/compaction.js +35 -4
- package/lib/types/dsh-adapter/channel/local-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/local-actions.js +6 -1
- package/lib/types/dsh-adapter/channel/model-switch.d.ts +1 -2
- package/lib/types/dsh-adapter/channel/model-switch.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/model-switch.js +6 -2
- package/lib/types/dsh-adapter/channel/paths.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/paths.js +7 -1
- package/lib/types/dsh-adapter/channel/preferences.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/preferences.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/preferences.js +16 -0
- package/lib/types/dsh-adapter/channel/projection.d.ts +1 -2
- package/lib/types/dsh-adapter/channel/projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/projection.js +127 -17
- package/lib/types/dsh-adapter/channel/question-record.d.ts +76 -0
- package/lib/types/dsh-adapter/channel/question-record.d.ts.map +1 -0
- package/lib/types/dsh-adapter/channel/question-record.js +107 -0
- package/lib/types/dsh-adapter/channel/session-adoption.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/session-adoption.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-adoption.js +1 -0
- package/lib/types/dsh-adapter/channel/session-lineage.d.ts +42 -0
- package/lib/types/dsh-adapter/channel/session-lineage.d.ts.map +1 -0
- package/lib/types/dsh-adapter/channel/session-lineage.js +51 -0
- package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts +3 -1
- package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-live-adoption.js +10 -3
- package/lib/types/dsh-adapter/channel/session-metadata.d.ts +2 -1
- package/lib/types/dsh-adapter/channel/session-metadata.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-metadata.js +43 -9
- package/lib/types/dsh-adapter/channel/session-reset.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/session-reset.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-reset.js +7 -1
- package/lib/types/dsh-adapter/channel/session-resume.d.ts +2 -1
- package/lib/types/dsh-adapter/channel/session-resume.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-resume.js +5 -2
- package/lib/types/dsh-adapter/channel/settings-host.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/settings-host.js +8 -0
- package/lib/types/dsh-adapter/channel/state.d.ts +19 -1
- package/lib/types/dsh-adapter/channel/state.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/state.js +8 -3
- package/lib/types/dsh-adapter/channel/subagent-projection.d.ts +32 -17
- package/lib/types/dsh-adapter/channel/subagent-projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/subagent-projection.js +309 -8
- package/lib/types/dsh-adapter/channel/types.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/types.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.d.ts +1 -1
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +34 -18
- package/lib/types/dsh-adapter/compat/index.d.ts +1 -1
- package/lib/types/dsh-adapter/compat/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/index.js +1 -1
- package/lib/types/dsh-adapter/compat/messages.d.ts +6 -0
- package/lib/types/dsh-adapter/compat/messages.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/messages.js +9 -0
- package/lib/types/dsh-adapter/compat/sessionLog.d.ts +18 -0
- package/lib/types/dsh-adapter/compat/sessionLog.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/sessionLog.js +18 -3
- package/lib/types/dsh-adapter/compat/settings.d.ts +2 -0
- package/lib/types/dsh-adapter/compat/settings.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/settings.js +14 -0
- package/lib/types/dsh-adapter/contract.d.ts +5 -4
- package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
- package/lib/types/dsh-adapter/contract.js +9 -5
- package/lib/types/dsh-adapter/index.d.ts +36 -1
- package/lib/types/dsh-adapter/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/index.js +22 -6
- package/lib/types/dsh-adapter/migrate/adapters/claude-code.d.ts +3 -0
- package/lib/types/dsh-adapter/migrate/adapters/claude-code.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/claude-code.js +131 -0
- package/lib/types/dsh-adapter/migrate/adapters/claude-code.parse.d.ts +17 -0
- package/lib/types/dsh-adapter/migrate/adapters/claude-code.parse.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/claude-code.parse.js +329 -0
- package/lib/types/dsh-adapter/migrate/adapters/codex.d.ts +3 -0
- package/lib/types/dsh-adapter/migrate/adapters/codex.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/codex.js +102 -0
- package/lib/types/dsh-adapter/migrate/adapters/codex.parse.d.ts +16 -0
- package/lib/types/dsh-adapter/migrate/adapters/codex.parse.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/codex.parse.js +289 -0
- package/lib/types/dsh-adapter/migrate/adapters/grok-build.d.ts +3 -0
- package/lib/types/dsh-adapter/migrate/adapters/grok-build.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/grok-build.js +117 -0
- package/lib/types/dsh-adapter/migrate/adapters/grok-build.parse.d.ts +13 -0
- package/lib/types/dsh-adapter/migrate/adapters/grok-build.parse.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/grok-build.parse.js +178 -0
- package/lib/types/dsh-adapter/migrate/adapters/omp.d.ts +3 -0
- package/lib/types/dsh-adapter/migrate/adapters/omp.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/omp.js +133 -0
- package/lib/types/dsh-adapter/migrate/adapters/scan-fs.d.ts +60 -0
- package/lib/types/dsh-adapter/migrate/adapters/scan-fs.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/scan-fs.js +178 -0
- package/lib/types/dsh-adapter/migrate/adapters/scan.d.ts +8 -0
- package/lib/types/dsh-adapter/migrate/adapters/scan.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/scan.js +40 -0
- package/lib/types/dsh-adapter/migrate/adapters/zcode.d.ts +3 -0
- package/lib/types/dsh-adapter/migrate/adapters/zcode.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/zcode.js +93 -0
- package/lib/types/dsh-adapter/migrate/adapters/zcode.parse.d.ts +9 -0
- package/lib/types/dsh-adapter/migrate/adapters/zcode.parse.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/adapters/zcode.parse.js +89 -0
- package/lib/types/dsh-adapter/migrate/bin-path.d.ts +6 -0
- package/lib/types/dsh-adapter/migrate/bin-path.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/bin-path.js +30 -0
- package/lib/types/dsh-adapter/migrate/browse.d.ts +42 -0
- package/lib/types/dsh-adapter/migrate/browse.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/browse.js +90 -0
- package/lib/types/dsh-adapter/migrate/cli.d.ts +9 -0
- package/lib/types/dsh-adapter/migrate/cli.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/cli.js +106 -0
- package/lib/types/dsh-adapter/migrate/import-one.d.ts +89 -0
- package/lib/types/dsh-adapter/migrate/import-one.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/import-one.js +133 -0
- package/lib/types/dsh-adapter/migrate/index.d.ts +35 -0
- package/lib/types/dsh-adapter/migrate/index.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/index.js +107 -0
- package/lib/types/dsh-adapter/migrate/parse/injection.d.ts +40 -0
- package/lib/types/dsh-adapter/migrate/parse/injection.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/parse/injection.js +127 -0
- package/lib/types/dsh-adapter/migrate/parse/jsonl.d.ts +28 -0
- package/lib/types/dsh-adapter/migrate/parse/jsonl.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/parse/jsonl.js +40 -0
- package/lib/types/dsh-adapter/migrate/parse/role-turns.d.ts +28 -0
- package/lib/types/dsh-adapter/migrate/parse/role-turns.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/parse/role-turns.js +50 -0
- package/lib/types/dsh-adapter/migrate/parse/title.d.ts +18 -0
- package/lib/types/dsh-adapter/migrate/parse/title.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/parse/title.js +29 -0
- package/lib/types/dsh-adapter/migrate/parse/tools.d.ts +62 -0
- package/lib/types/dsh-adapter/migrate/parse/tools.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/parse/tools.js +110 -0
- package/lib/types/dsh-adapter/migrate/picker.d.ts +64 -0
- package/lib/types/dsh-adapter/migrate/picker.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/picker.js +86 -0
- package/lib/types/dsh-adapter/migrate/recent-agents.d.ts +40 -0
- package/lib/types/dsh-adapter/migrate/recent-agents.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/recent-agents.js +100 -0
- package/lib/types/dsh-adapter/migrate/sessionize.d.ts +39 -0
- package/lib/types/dsh-adapter/migrate/sessionize.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/sessionize.js +271 -0
- package/lib/types/dsh-adapter/migrate/types.d.ts +176 -0
- package/lib/types/dsh-adapter/migrate/types.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/types.js +11 -0
- package/lib/types/dsh-adapter/migrate/uuid.d.ts +7 -0
- package/lib/types/dsh-adapter/migrate/uuid.d.ts.map +1 -0
- package/lib/types/dsh-adapter/migrate/uuid.js +25 -0
- package/lib/types/dsh-adapter/plugin.d.ts +5 -3
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +168 -372
- package/lib/types/dsh-adapter/providerWizard.d.ts +17 -0
- package/lib/types/dsh-adapter/providerWizard.d.ts.map +1 -1
- package/lib/types/dsh-adapter/providerWizard.js +254 -66
- package/lib/types/dsh-adapter/questions.d.ts +22 -15
- package/lib/types/dsh-adapter/questions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/questions.js +47 -45
- package/lib/types/dsh-adapter/sessions/digest.d.ts +11 -6
- package/lib/types/dsh-adapter/sessions/digest.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessions/digest.js +20 -13
- package/lib/types/dsh-adapter/sessions/frames.d.ts +3 -1
- package/lib/types/dsh-adapter/sessions/frames.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessions/frames.js +5 -4
- package/lib/types/dsh-adapter/sessions/list.d.ts +6 -1
- package/lib/types/dsh-adapter/sessions/list.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessions/list.js +188 -164
- package/lib/types/dsh-adapter/sessions/recovery.d.ts +16 -0
- package/lib/types/dsh-adapter/sessions/recovery.d.ts.map +1 -0
- package/lib/types/dsh-adapter/sessions/recovery.js +108 -0
- package/lib/types/dsh-adapter/sessions/snapshot.d.ts +7 -0
- package/lib/types/dsh-adapter/sessions/snapshot.d.ts.map +1 -0
- package/lib/types/dsh-adapter/sessions/snapshot.js +90 -0
- package/lib/types/dsh-adapter/sessions/store.d.ts +10 -4
- package/lib/types/dsh-adapter/sessions/store.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessions/store.js +62 -25
- package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -1
- package/lib/types/dsh-adapter/settings-sections.js +7 -4
- package/lib/types/dsh-adapter/sideQuestion.d.ts +41 -2
- package/lib/types/dsh-adapter/sideQuestion.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sideQuestion.js +98 -2
- package/lib/types/dsh-adapter/subagents.d.ts +44 -6
- package/lib/types/dsh-adapter/subagents.d.ts.map +1 -1
- package/lib/types/dsh-adapter/subagents.js +163 -26
- package/lib/types/herdr.d.ts +2 -0
- package/lib/types/herdr.d.ts.map +1 -1
- package/lib/types/herdr.js +9 -3
- package/lib/types/history.d.ts +13 -1
- package/lib/types/history.d.ts.map +1 -1
- package/lib/types/history.js +15 -2
- package/lib/types/i18n.d.ts +512 -41
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +199 -20
- package/lib/types/ink/components/App.d.ts +2 -2
- package/lib/types/ink/components/App.d.ts.map +1 -1
- package/lib/types/ink/components/App.js +5 -1
- package/lib/types/ink/components/Image.d.ts +14 -1
- package/lib/types/ink/components/Image.d.ts.map +1 -1
- package/lib/types/ink/components/Image.js +2 -2
- package/lib/types/ink/events/input-event.js +3 -3
- package/lib/types/ink/hooks/use-terminal-images.d.ts +12 -0
- package/lib/types/ink/hooks/use-terminal-images.d.ts.map +1 -1
- package/lib/types/ink/hooks/use-terminal-images.js +13 -0
- package/lib/types/ink/ink.d.ts +6 -0
- package/lib/types/ink/ink.d.ts.map +1 -1
- package/lib/types/ink/ink.js +16 -1
- package/lib/types/ink/kitty-graphics.d.ts +44 -3
- package/lib/types/ink/kitty-graphics.d.ts.map +1 -1
- package/lib/types/ink/kitty-graphics.js +184 -23
- package/lib/types/ink/log-update.d.ts.map +1 -1
- package/lib/types/ink/log-update.js +19 -1
- package/lib/types/ink/output.d.ts +24 -2
- package/lib/types/ink/output.d.ts.map +1 -1
- package/lib/types/ink/output.js +83 -5
- package/lib/types/ink/parse-keypress.d.ts +26 -1
- package/lib/types/ink/parse-keypress.d.ts.map +1 -1
- package/lib/types/ink/parse-keypress.js +156 -13
- package/lib/types/ink/render-node-to-output.d.ts.map +1 -1
- package/lib/types/ink/render-node-to-output.js +8 -1
- package/lib/types/ink/screen.d.ts +24 -0
- package/lib/types/ink/screen.d.ts.map +1 -1
- package/lib/types/ink/screen.js +89 -0
- package/lib/types/ink/selection.d.ts +68 -18
- package/lib/types/ink/selection.d.ts.map +1 -1
- package/lib/types/ink/selection.js +178 -31
- package/lib/types/ink/sixel-codec.d.ts +12 -1
- package/lib/types/ink/sixel-codec.d.ts.map +1 -1
- package/lib/types/ink/sixel-codec.js +29 -5
- package/lib/types/ink/sixel-graphics.d.ts.map +1 -1
- package/lib/types/ink/sixel-graphics.js +5 -3
- package/lib/types/ink/styles.d.ts +9 -0
- package/lib/types/ink/styles.d.ts.map +1 -1
- package/lib/types/ink/terminal-image.d.ts +8 -0
- package/lib/types/ink/terminal-image.d.ts.map +1 -1
- package/lib/types/ink/terminal-querier.d.ts +7 -1
- package/lib/types/ink/terminal-querier.d.ts.map +1 -1
- package/lib/types/ink/terminal-querier.js +12 -2
- package/lib/types/ink/timeline-rail.d.ts +5 -0
- package/lib/types/ink/timeline-rail.d.ts.map +1 -1
- package/lib/types/math/inline-layout.d.ts +29 -0
- package/lib/types/math/inline-layout.d.ts.map +1 -0
- package/lib/types/math/inline-layout.js +106 -0
- package/lib/types/math/layout.d.ts +58 -0
- package/lib/types/math/layout.d.ts.map +1 -0
- package/lib/types/math/layout.js +59 -0
- package/lib/types/math/renderer.d.ts +64 -0
- package/lib/types/math/renderer.d.ts.map +1 -0
- package/lib/types/math/renderer.js +256 -0
- package/lib/types/screens/Chat.d.ts +17 -1
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +618 -57
- package/lib/types/screens/SessionSupervisor.d.ts +2 -1
- package/lib/types/screens/SessionSupervisor.d.ts.map +1 -1
- package/lib/types/screens/SessionSupervisor.js +156 -19
- package/lib/types/screens/Settings.d.ts.map +1 -1
- package/lib/types/screens/Settings.js +49 -11
- package/lib/types/screens/StatusLine.d.ts +5 -1
- package/lib/types/screens/StatusLine.d.ts.map +1 -1
- package/lib/types/screens/StatusLine.js +47 -17
- package/lib/types/screens/chatOverlay.d.ts +5 -0
- package/lib/types/screens/chatOverlay.d.ts.map +1 -1
- package/lib/types/screens/chatOverlay.js +1 -0
- package/lib/types/screens/sessionSupervisor/ForeignSessionPanes.d.ts +47 -0
- package/lib/types/screens/sessionSupervisor/ForeignSessionPanes.d.ts.map +1 -0
- package/lib/types/screens/sessionSupervisor/ForeignSessionPanes.js +65 -0
- package/lib/types/screens/sessionSupervisor/model.d.ts +12 -0
- package/lib/types/screens/sessionSupervisor/model.d.ts.map +1 -1
- package/lib/types/screens/sessionSupervisor/model.js +26 -0
- package/lib/types/screens/sessionSupervisor/useForeignSessions.d.ts +107 -0
- package/lib/types/screens/sessionSupervisor/useForeignSessions.d.ts.map +1 -0
- package/lib/types/screens/sessionSupervisor/useForeignSessions.js +312 -0
- package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts +4 -1
- package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts.map +1 -1
- package/lib/types/screens/sessionSupervisor/useSessionSupervisor.js +97 -14
- package/lib/types/sessionHistory.d.ts +2 -2
- package/lib/types/sessionHistory.d.ts.map +1 -1
- package/lib/types/sessionHistory.js +31 -5
- package/lib/types/settings/definitions.d.ts +681 -0
- package/lib/types/settings/definitions.d.ts.map +1 -0
- package/lib/types/settings/definitions.js +511 -0
- package/lib/types/starAction.d.ts +44 -0
- package/lib/types/starAction.d.ts.map +1 -0
- package/lib/types/starAction.js +52 -0
- package/lib/types/terminal-utils/latex.d.ts +10 -0
- package/lib/types/terminal-utils/latex.d.ts.map +1 -0
- package/lib/types/terminal-utils/latex.js +1417 -0
- package/lib/types/terminal-utils/markdown.d.ts +3 -1
- package/lib/types/terminal-utils/markdown.d.ts.map +1 -1
- package/lib/types/terminal-utils/markdown.js +26 -1
- package/lib/types/terminal-utils/math.d.ts +66 -0
- package/lib/types/terminal-utils/math.d.ts.map +1 -0
- package/lib/types/terminal-utils/math.js +337 -0
- package/lib/types/tips.d.ts.map +1 -1
- package/lib/types/tips.js +6 -0
- package/lib/types/tuiDisplayPrefs.d.ts +67 -0
- package/lib/types/tuiDisplayPrefs.d.ts.map +1 -1
- package/lib/types/tuiDisplayPrefs.js +59 -0
- package/lib/types/ui.d.ts +1 -1
- package/lib/types/ui.d.ts.map +1 -1
- package/lib/types/ui.js +1 -1
- package/lib/types/usageStats.d.ts +98 -0
- package/lib/types/usageStats.d.ts.map +1 -0
- package/lib/types/usageStats.js +169 -0
- package/lib/types/utils/bmp.d.ts +17 -0
- package/lib/types/utils/bmp.d.ts.map +1 -0
- package/lib/types/utils/bmp.js +154 -0
- package/lib/types/utils/clipboard.d.ts +14 -2
- package/lib/types/utils/clipboard.d.ts.map +1 -1
- package/lib/types/utils/clipboard.js +143 -8
- package/lib/types/utils/fold-long-lines.d.ts +1 -1
- package/lib/types/utils/fold-long-lines.d.ts.map +1 -1
- package/lib/types/utils/fold-long-lines.js +3 -2
- package/lib/types/utils/keymap.d.ts +4 -1
- package/lib/types/utils/keymap.d.ts.map +1 -1
- package/lib/types/utils/keymap.js +8 -0
- package/lib/types/utils/modifiers.d.ts +4 -3
- package/lib/types/utils/modifiers.d.ts.map +1 -1
- package/lib/types/utils/modifiers.js +4 -3
- package/lib/types/working-activity.d.ts +10 -9
- package/lib/types/working-activity.d.ts.map +1 -1
- package/lib/types/working-activity.js +17 -10
- package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/LICENSE +202 -0
- package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/NOTICE +20 -0
- package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/index.d.ts +16 -0
- package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/lib/bundled-packages.json +4 -0
- package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/lib/index.mjs +20 -0
- package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/lib/index.mjs.LEGAL.txt +35 -0
- package/node_modules/@dsh-tui-vendor/mathjax-tex-svg/package.json +29 -0
- package/package.json +117 -99
- package/lib/types/components/design-system/KeyboardShortcutHint.d.ts +0 -19
- package/lib/types/components/design-system/KeyboardShortcutHint.d.ts.map +0 -1
- package/lib/types/components/design-system/KeyboardShortcutHint.js +0 -14
- package/lib/types/dsh-adapter/channel/activity.d.ts +0 -20
- package/lib/types/dsh-adapter/channel/activity.d.ts.map +0 -1
- package/lib/types/dsh-adapter/channel/activity.js +0 -113
- package/lib/types/terminal-utils/terminal.d.ts +0 -18
- package/lib/types/terminal-utils/terminal.d.ts.map +0 -1
- package/lib/types/terminal-utils/terminal.js +0 -96
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-agent conversation migration: orchestration over the official
|
|
3
|
+
* persistence backend.
|
|
4
|
+
*
|
|
5
|
+
* Discovery is read-only against foreign stores (adapters never write their
|
|
6
|
+
* source). Import goes EXCLUSIVELY through `JsonlSessionPersistence` — the
|
|
7
|
+
* same plugin the retired-store migration (scripts/migrate-sessions-to-jsonl.mts)
|
|
8
|
+
* writes through — so physical encoding, `projectKey`/directory layout, zstd
|
|
9
|
+
* frames, atomic writes and Windows path handling are upstream's, not ours.
|
|
10
|
+
* Re-importing the same source conversation deterministically lands on the
|
|
11
|
+
* same session id and is skipped when already present: repeats neither stack
|
|
12
|
+
* duplicates nor rewrite existing logs.
|
|
13
|
+
*
|
|
14
|
+
* @module @deepseek-harness-tui/dsh-tui/migrate
|
|
15
|
+
*/
|
|
16
|
+
import { Context } from '@deepseek-ai/cordis';
|
|
17
|
+
import JsonlSessionPersistence from '@deepseek-ai/dsh-session-persistence-jsonl';
|
|
18
|
+
import { homedir } from 'node:os';
|
|
19
|
+
import { join } from 'node:path';
|
|
20
|
+
import { claudeCodeAdapter } from './adapters/claude-code.js';
|
|
21
|
+
import { codexAdapter } from './adapters/codex.js';
|
|
22
|
+
import { ompAdapter } from './adapters/omp.js';
|
|
23
|
+
import { grokBuildAdapter } from './adapters/grok-build.js';
|
|
24
|
+
import { zcodeAdapter } from './adapters/zcode.js';
|
|
25
|
+
import { foreignSessionId, writeImportedSession } from './import-one.js';
|
|
26
|
+
export const MIGRATION_ADAPTERS = [
|
|
27
|
+
claudeCodeAdapter,
|
|
28
|
+
codexAdapter,
|
|
29
|
+
ompAdapter,
|
|
30
|
+
zcodeAdapter,
|
|
31
|
+
grokBuildAdapter,
|
|
32
|
+
];
|
|
33
|
+
/**
|
|
34
|
+
* The default import target: the shared DSH session store, resolved exactly
|
|
35
|
+
* like the persistence backend's root (cordis.patch.yml): an explicit
|
|
36
|
+
* `DSH_TUI_SESSION_ROOT` first, then `$DSH_HOME/sessions`, then
|
|
37
|
+
* `~/.dsh/sessions`. Resolving it any other way would let the CLI import into
|
|
38
|
+
* a store the TUI (and the source tabs) never read.
|
|
39
|
+
*/
|
|
40
|
+
export function defaultSessionRoot() {
|
|
41
|
+
const override = process.env.DSH_TUI_SESSION_ROOT?.trim();
|
|
42
|
+
if (override)
|
|
43
|
+
return override;
|
|
44
|
+
const dshHome = process.env.DSH_HOME?.trim();
|
|
45
|
+
return join(dshHome ? dshHome : join(homedir(), '.dsh'), 'sessions');
|
|
46
|
+
}
|
|
47
|
+
/** Deterministic session id for one foreign conversation. */
|
|
48
|
+
export function migrationSessionId(adapter, session) {
|
|
49
|
+
return foreignSessionId(adapter.id, session.sourceId);
|
|
50
|
+
}
|
|
51
|
+
/** Wait until the plugin's service is published on the context. */
|
|
52
|
+
async function awaitPersistence(ctx) {
|
|
53
|
+
for (let i = 0; i < 200; i++) {
|
|
54
|
+
const service = ctx.get('sessionPersistence');
|
|
55
|
+
if (service !== undefined)
|
|
56
|
+
return service;
|
|
57
|
+
await new Promise(resolve => setTimeout(resolve, 25));
|
|
58
|
+
}
|
|
59
|
+
throw new Error('session persistence service did not become ready');
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Import every discovered conversation of one adapter into the DSH store.
|
|
63
|
+
*
|
|
64
|
+
* The persistence backend is mounted ONCE per run (one Context, one plugin
|
|
65
|
+
* lifecycle) and disposed after the loop; sessions already present (same
|
|
66
|
+
* deterministic id) are skipped, and a failed conversation never aborts the
|
|
67
|
+
* batch — both properties the retired-store migration established first.
|
|
68
|
+
*
|
|
69
|
+
* @param adapter - the foreign agent to import from.
|
|
70
|
+
* @param root - the DSH session root to write into.
|
|
71
|
+
* @param sessions - the conversations to import (usually adapter.discover()).
|
|
72
|
+
* @returns the per-run counters.
|
|
73
|
+
*/
|
|
74
|
+
export async function importSessions(adapter, root, sessions) {
|
|
75
|
+
const ctx = new Context();
|
|
76
|
+
const fiber = ctx.plugin(JsonlSessionPersistence, { root });
|
|
77
|
+
let imported = 0;
|
|
78
|
+
let existing = 0;
|
|
79
|
+
let failed = 0;
|
|
80
|
+
const failures = [];
|
|
81
|
+
try {
|
|
82
|
+
const persistence = await awaitPersistence(ctx);
|
|
83
|
+
const present = new Set((await persistence.list()).map(entry => entry.header.id));
|
|
84
|
+
for (const session of sessions) {
|
|
85
|
+
const id = migrationSessionId(adapter, session);
|
|
86
|
+
if (present.has(id)) {
|
|
87
|
+
existing += 1;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
await writeImportedSession(persistence, id, adapter.id, session);
|
|
92
|
+
present.add(id);
|
|
93
|
+
imported += 1;
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
failed += 1;
|
|
97
|
+
failures.push(`${session.sourceId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
// The mounted plugin fiber owns the backend's file handles; dispose it
|
|
103
|
+
// so a CLI process with nothing left to do can exit promptly.
|
|
104
|
+
await Promise.resolve(fiber.dispose()).catch(() => { });
|
|
105
|
+
}
|
|
106
|
+
return { imported, existing, failed, failures };
|
|
107
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness-injection recognition and user-text unwrapping.
|
|
3
|
+
*
|
|
4
|
+
* Every foreign agent writes machine text into its user role: environment
|
|
5
|
+
* blocks, instruction files, reminders, slash-command echoes. None of it is
|
|
6
|
+
* the human's words, so it must never open a turn or become a title. The
|
|
7
|
+
* other half is wrappers the harness puts AROUND real words (`<user_query>`,
|
|
8
|
+
* pasted-content envelopes, interrupt notices): those keep the words and
|
|
9
|
+
* drop the frame.
|
|
10
|
+
*
|
|
11
|
+
* Every scan here is linear: tag bodies are located with indexOf, never a
|
|
12
|
+
* lazy `[\s\S]*?` regex, whose per-unclosed-tag rescans a hostile single
|
|
13
|
+
* line can turn quadratic (deep-review m1 on the first claude adapter).
|
|
14
|
+
*
|
|
15
|
+
* @module @deepseek-harness-tui/dsh-tui/migrate/parse/injection
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Line-start markers of injected blocks, matched case-insensitively after
|
|
19
|
+
* trimming. A user text that STARTS with one of these is harness output.
|
|
20
|
+
*/
|
|
21
|
+
export declare const INJECTED_PREFIXES: readonly string[];
|
|
22
|
+
/** Whether a user text is harness injection rather than the human's words. */
|
|
23
|
+
export declare function isInjectedText(text: string): boolean;
|
|
24
|
+
/** Strip inline `<system-reminder>` blocks (Claude Code puts them anywhere). */
|
|
25
|
+
export declare function stripSystemReminders(text: string): string;
|
|
26
|
+
/** Whether a user text is an interrupt notice (the previous turn was cut short). */
|
|
27
|
+
export declare function isInterruptNotice(text: string): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Reduce a user text to the human's own words.
|
|
30
|
+
*
|
|
31
|
+
* - `<user_query>` wrappers keep only their bodies — this also covers the
|
|
32
|
+
* interrupt / "sent a message while you were working" notices, whose
|
|
33
|
+
* human part is always inside a `<user_query>`;
|
|
34
|
+
* - a notice without a `<user_query>` keeps what follows the notice line;
|
|
35
|
+
* - pasted-content envelopes lose their tags but keep the pasted text.
|
|
36
|
+
*
|
|
37
|
+
* @returns The unwrapped, trimmed text ('' when nothing human remains).
|
|
38
|
+
*/
|
|
39
|
+
export declare function unwrapUserText(text: string): string;
|
|
40
|
+
//# sourceMappingURL=injection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"injection.d.ts","sourceRoot":"","sources":["../../../../../src/dsh-adapter/migrate/parse/injection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS,MAAM,EAa9C,CAAA;AAID,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGpD;AAsBD,gFAAgF;AAChF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGzD;AAyBD,oFAAoF;AACpF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvD;AAQD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAYnD"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness-injection recognition and user-text unwrapping.
|
|
3
|
+
*
|
|
4
|
+
* Every foreign agent writes machine text into its user role: environment
|
|
5
|
+
* blocks, instruction files, reminders, slash-command echoes. None of it is
|
|
6
|
+
* the human's words, so it must never open a turn or become a title. The
|
|
7
|
+
* other half is wrappers the harness puts AROUND real words (`<user_query>`,
|
|
8
|
+
* pasted-content envelopes, interrupt notices): those keep the words and
|
|
9
|
+
* drop the frame.
|
|
10
|
+
*
|
|
11
|
+
* Every scan here is linear: tag bodies are located with indexOf, never a
|
|
12
|
+
* lazy `[\s\S]*?` regex, whose per-unclosed-tag rescans a hostile single
|
|
13
|
+
* line can turn quadratic (deep-review m1 on the first claude adapter).
|
|
14
|
+
*
|
|
15
|
+
* @module @deepseek-harness-tui/dsh-tui/migrate/parse/injection
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Line-start markers of injected blocks, matched case-insensitively after
|
|
19
|
+
* trimming. A user text that STARTS with one of these is harness output.
|
|
20
|
+
*/
|
|
21
|
+
export const INJECTED_PREFIXES = [
|
|
22
|
+
'<environment_context>',
|
|
23
|
+
'<system-reminder>',
|
|
24
|
+
'<user_instructions>',
|
|
25
|
+
'<local-command-caveat>',
|
|
26
|
+
'<local-command-stdout>',
|
|
27
|
+
'<command-name>',
|
|
28
|
+
'<command-message>',
|
|
29
|
+
'<task-notification>',
|
|
30
|
+
'<permissions>',
|
|
31
|
+
'<user_info>',
|
|
32
|
+
'# AGENTS.md instructions',
|
|
33
|
+
'# Context from my IDE setup:',
|
|
34
|
+
];
|
|
35
|
+
const LOWER_PREFIXES = INJECTED_PREFIXES.map(prefix => prefix.toLowerCase());
|
|
36
|
+
/** Whether a user text is harness injection rather than the human's words. */
|
|
37
|
+
export function isInjectedText(text) {
|
|
38
|
+
const head = text.trimStart().slice(0, 64).toLowerCase();
|
|
39
|
+
return LOWER_PREFIXES.some(prefix => head.startsWith(prefix));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Remove every `<tag>…</tag>` span. An opening tag with no closing tag
|
|
43
|
+
* swallows the rest of the text (the block was cut off, nothing after it is
|
|
44
|
+
* the user's).
|
|
45
|
+
*/
|
|
46
|
+
function removeTagSpans(text, tag) {
|
|
47
|
+
const open = `<${tag}>`;
|
|
48
|
+
const close = `</${tag}>`;
|
|
49
|
+
let out = '';
|
|
50
|
+
let from = 0;
|
|
51
|
+
for (;;) {
|
|
52
|
+
const start = text.indexOf(open, from);
|
|
53
|
+
if (start === -1)
|
|
54
|
+
return out + text.slice(from);
|
|
55
|
+
out += text.slice(from, start);
|
|
56
|
+
const end = text.indexOf(close, start + open.length);
|
|
57
|
+
if (end === -1)
|
|
58
|
+
return out;
|
|
59
|
+
from = end + close.length;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** Strip inline `<system-reminder>` blocks (Claude Code puts them anywhere). */
|
|
63
|
+
export function stripSystemReminders(text) {
|
|
64
|
+
if (!text.includes('<system-reminder>'))
|
|
65
|
+
return text.trim();
|
|
66
|
+
return removeTagSpans(text, 'system-reminder').trim();
|
|
67
|
+
}
|
|
68
|
+
/** Bodies of every `<user_query>` block; an unclosed tag runs to the end. */
|
|
69
|
+
function userQueryBodies(text) {
|
|
70
|
+
const open = '<user_query>';
|
|
71
|
+
const close = '</user_query>';
|
|
72
|
+
const bodies = [];
|
|
73
|
+
let from = 0;
|
|
74
|
+
for (;;) {
|
|
75
|
+
const start = text.indexOf(open, from);
|
|
76
|
+
if (start === -1)
|
|
77
|
+
return bodies;
|
|
78
|
+
const bodyStart = start + open.length;
|
|
79
|
+
const end = text.indexOf(close, bodyStart);
|
|
80
|
+
bodies.push(text.slice(bodyStart, end === -1 ? undefined : end).trim());
|
|
81
|
+
if (end === -1)
|
|
82
|
+
return bodies;
|
|
83
|
+
from = end + close.length;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/** Notices a harness prepends when the user speaks over a running turn. */
|
|
87
|
+
const INTERJECTION_PREFIXES = [
|
|
88
|
+
'The user interrupted the previous turn:',
|
|
89
|
+
'The user sent a message while you were working:',
|
|
90
|
+
];
|
|
91
|
+
/** Whether a user text is an interrupt notice (the previous turn was cut short). */
|
|
92
|
+
export function isInterruptNotice(text) {
|
|
93
|
+
return text.trimStart().startsWith(INTERJECTION_PREFIXES[0]);
|
|
94
|
+
}
|
|
95
|
+
/** Drop `<pasted_content …>` / `</pasted_content …>` tags, keeping the pasted body. */
|
|
96
|
+
function stripPastedTags(text) {
|
|
97
|
+
if (!text.includes('pasted_content'))
|
|
98
|
+
return text;
|
|
99
|
+
return text.replace(/<\/?pasted_content(?:\s[^<>]*)?>/gu, ' ').replace(/[ \t]{2,}/gu, ' ');
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Reduce a user text to the human's own words.
|
|
103
|
+
*
|
|
104
|
+
* - `<user_query>` wrappers keep only their bodies — this also covers the
|
|
105
|
+
* interrupt / "sent a message while you were working" notices, whose
|
|
106
|
+
* human part is always inside a `<user_query>`;
|
|
107
|
+
* - a notice without a `<user_query>` keeps what follows the notice line;
|
|
108
|
+
* - pasted-content envelopes lose their tags but keep the pasted text.
|
|
109
|
+
*
|
|
110
|
+
* @returns The unwrapped, trimmed text ('' when nothing human remains).
|
|
111
|
+
*/
|
|
112
|
+
export function unwrapUserText(text) {
|
|
113
|
+
const lead = text.trimStart();
|
|
114
|
+
if (!text.includes('<') && !lead.startsWith('The user '))
|
|
115
|
+
return text.trim();
|
|
116
|
+
let body = text;
|
|
117
|
+
const queries = userQueryBodies(body);
|
|
118
|
+
if (queries.length > 0) {
|
|
119
|
+
body = queries.join('\n\n');
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
const notice = INTERJECTION_PREFIXES.find(prefix => lead.startsWith(prefix));
|
|
123
|
+
if (notice !== undefined)
|
|
124
|
+
body = lead.slice(notice.length);
|
|
125
|
+
}
|
|
126
|
+
return stripPastedTags(body).trim();
|
|
127
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Line-delimited JSON reading shared by every migration source.
|
|
3
|
+
*
|
|
4
|
+
* Foreign stores are read defensively: a malformed line costs that line,
|
|
5
|
+
* never the file. Legal JSON that is not a record (`null`, scalars, arrays)
|
|
6
|
+
* is skipped silently — it is well-formed, just not a row — while text that
|
|
7
|
+
* fails to parse is COUNTED, so a truncated or corrupted source shows up in
|
|
8
|
+
* the import stats instead of vanishing quietly.
|
|
9
|
+
*
|
|
10
|
+
* @module @deepseek-harness-tui/dsh-tui/migrate/parse/jsonl
|
|
11
|
+
*/
|
|
12
|
+
/** A decoded JSON object row. */
|
|
13
|
+
export type JsonRecord = Record<string, unknown>;
|
|
14
|
+
/** Narrow an unknown JSON value to an object record (rejects `null` and arrays). */
|
|
15
|
+
export declare function isRecord(value: unknown): value is JsonRecord;
|
|
16
|
+
/** Parsed rows of one JSONL document. */
|
|
17
|
+
export interface JsonlRows {
|
|
18
|
+
readonly records: readonly JsonRecord[];
|
|
19
|
+
/** Non-empty lines that were not valid JSON. */
|
|
20
|
+
readonly badLines: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Split and decode a JSONL document.
|
|
24
|
+
* @param raw - Whole file text; `\n` and `\r\n` line ends are both accepted.
|
|
25
|
+
* @returns Every object row in file order plus the count of unparseable lines.
|
|
26
|
+
*/
|
|
27
|
+
export declare function parseJsonl(raw: string): JsonlRows;
|
|
28
|
+
//# sourceMappingURL=jsonl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonl.d.ts","sourceRoot":"","sources":["../../../../../src/dsh-adapter/migrate/parse/jsonl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,iCAAiC;AACjC,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEhD,oFAAoF;AACpF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAE5D;AAED,yCAAyC;AACzC,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,CAAA;IACvC,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAgBjD"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Line-delimited JSON reading shared by every migration source.
|
|
3
|
+
*
|
|
4
|
+
* Foreign stores are read defensively: a malformed line costs that line,
|
|
5
|
+
* never the file. Legal JSON that is not a record (`null`, scalars, arrays)
|
|
6
|
+
* is skipped silently — it is well-formed, just not a row — while text that
|
|
7
|
+
* fails to parse is COUNTED, so a truncated or corrupted source shows up in
|
|
8
|
+
* the import stats instead of vanishing quietly.
|
|
9
|
+
*
|
|
10
|
+
* @module @deepseek-harness-tui/dsh-tui/migrate/parse/jsonl
|
|
11
|
+
*/
|
|
12
|
+
/** Narrow an unknown JSON value to an object record (rejects `null` and arrays). */
|
|
13
|
+
export function isRecord(value) {
|
|
14
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Split and decode a JSONL document.
|
|
18
|
+
* @param raw - Whole file text; `\n` and `\r\n` line ends are both accepted.
|
|
19
|
+
* @returns Every object row in file order plus the count of unparseable lines.
|
|
20
|
+
*/
|
|
21
|
+
export function parseJsonl(raw) {
|
|
22
|
+
const records = [];
|
|
23
|
+
let badLines = 0;
|
|
24
|
+
for (const line of raw.split('\n')) {
|
|
25
|
+
const text = line.endsWith('\r') ? line.slice(0, -1) : line;
|
|
26
|
+
if (text.trim() === '')
|
|
27
|
+
continue;
|
|
28
|
+
let value;
|
|
29
|
+
try {
|
|
30
|
+
value = JSON.parse(text);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
badLines += 1;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (isRecord(value))
|
|
37
|
+
records.push(value);
|
|
38
|
+
}
|
|
39
|
+
return { records, badLines };
|
|
40
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flat role list → imported turns, plus the shared size measure.
|
|
3
|
+
*
|
|
4
|
+
* The first migration adapters normalized every source into an alternating
|
|
5
|
+
* user/assistant list. {@link fromRoleTurns} folds that list into the turn
|
|
6
|
+
* model mechanically — a user message opens a turn, every assistant message
|
|
7
|
+
* after it is one step — so an adapter that still produces the list imports
|
|
8
|
+
* exactly as it did before the turn model existed.
|
|
9
|
+
*
|
|
10
|
+
* @module @deepseek-harness-tui/dsh-tui/migrate/parse/role-turns
|
|
11
|
+
*/
|
|
12
|
+
import type { ImportStats, ImportTurn, MigrationSession, MigrationTurn } from '../types.js';
|
|
13
|
+
/** Counters for a source that reports nothing it left out. */
|
|
14
|
+
export declare function emptyStats(): ImportStats;
|
|
15
|
+
/**
|
|
16
|
+
* Fold a role list into turns.
|
|
17
|
+
*
|
|
18
|
+
* A list that starts with an assistant message opens a turn with no prompt
|
|
19
|
+
* (the source lost its head); a trailing user message is a step-less turn.
|
|
20
|
+
*/
|
|
21
|
+
export declare function fromRoleTurns(list: readonly MigrationTurn[]): ImportTurn[];
|
|
22
|
+
/**
|
|
23
|
+
* How many conversation messages an imported session carries: prompts,
|
|
24
|
+
* mid-turn inputs and assistant steps (tool results are not counted). For a
|
|
25
|
+
* role-list source this equals the list length.
|
|
26
|
+
*/
|
|
27
|
+
export declare function messageCount(session: Pick<MigrationSession, 'turns'>): number;
|
|
28
|
+
//# sourceMappingURL=role-turns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role-turns.d.ts","sourceRoot":"","sources":["../../../../../src/dsh-adapter/migrate/parse/role-turns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAe,WAAW,EAAE,UAAU,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAGxG,8DAA8D;AAC9D,wBAAgB,UAAU,IAAI,WAAW,CAExC;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,GAAG,UAAU,EAAE,CAqB1E;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,GAAG,MAAM,CAO7E"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { newStep } from './tools.js';
|
|
2
|
+
/** Counters for a source that reports nothing it left out. */
|
|
3
|
+
export function emptyStats() {
|
|
4
|
+
return { badLines: 0, droppedToolResults: 0, filtered: 0, meta: 0 };
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Fold a role list into turns.
|
|
8
|
+
*
|
|
9
|
+
* A list that starts with an assistant message opens a turn with no prompt
|
|
10
|
+
* (the source lost its head); a trailing user message is a step-less turn.
|
|
11
|
+
*/
|
|
12
|
+
export function fromRoleTurns(list) {
|
|
13
|
+
const turns = [];
|
|
14
|
+
let current;
|
|
15
|
+
for (const message of list) {
|
|
16
|
+
if (message.role === 'user') {
|
|
17
|
+
current = { prompt: message.text, steps: [] };
|
|
18
|
+
turns.push(current);
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (current === undefined) {
|
|
22
|
+
current = { prompt: '', steps: [] };
|
|
23
|
+
turns.push(current);
|
|
24
|
+
}
|
|
25
|
+
const step = newStep(message.model);
|
|
26
|
+
const blocks = [];
|
|
27
|
+
if (message.reasoning !== undefined && message.reasoning !== '')
|
|
28
|
+
blocks.push({ type: 'reasoning', text: message.reasoning });
|
|
29
|
+
if (message.text !== '')
|
|
30
|
+
blocks.push({ type: 'text', text: message.text });
|
|
31
|
+
step.blocks = blocks;
|
|
32
|
+
current.steps.push(step);
|
|
33
|
+
}
|
|
34
|
+
return turns;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* How many conversation messages an imported session carries: prompts,
|
|
38
|
+
* mid-turn inputs and assistant steps (tool results are not counted). For a
|
|
39
|
+
* role-list source this equals the list length.
|
|
40
|
+
*/
|
|
41
|
+
export function messageCount(session) {
|
|
42
|
+
let count = 0;
|
|
43
|
+
for (const turn of session.turns) {
|
|
44
|
+
if (turn.prompt !== '')
|
|
45
|
+
count += 1;
|
|
46
|
+
for (const step of turn.steps)
|
|
47
|
+
count += 1 + step.inputs.length;
|
|
48
|
+
}
|
|
49
|
+
return count;
|
|
50
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Title normalization shared by every migration source.
|
|
3
|
+
*
|
|
4
|
+
* One rule for all sources, so the same conversation shows the same title
|
|
5
|
+
* whichever entry imported it: trim, collapse inner whitespace (a title is
|
|
6
|
+
* one line), cap at {@link TITLE_MAX_CHARS} code points with a trailing `…`.
|
|
7
|
+
*
|
|
8
|
+
* @module @deepseek-harness-tui/dsh-tui/migrate/parse/title
|
|
9
|
+
*/
|
|
10
|
+
/** Longest normalized title, in code points (the ellipsis included). */
|
|
11
|
+
export declare const TITLE_MAX_CHARS = 80;
|
|
12
|
+
/**
|
|
13
|
+
* Normalize a candidate title.
|
|
14
|
+
* @param text - Raw title or first prompt.
|
|
15
|
+
* @returns The one-line title, or '' when the input is blank.
|
|
16
|
+
*/
|
|
17
|
+
export declare function normalizeTitle(text: string | undefined): string;
|
|
18
|
+
//# sourceMappingURL=title.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"title.d.ts","sourceRoot":"","sources":["../../../../../src/dsh-adapter/migrate/parse/title.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,wEAAwE;AACxE,eAAO,MAAM,eAAe,KAAK,CAAA;AAIjC;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAQ/D"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Title normalization shared by every migration source.
|
|
3
|
+
*
|
|
4
|
+
* One rule for all sources, so the same conversation shows the same title
|
|
5
|
+
* whichever entry imported it: trim, collapse inner whitespace (a title is
|
|
6
|
+
* one line), cap at {@link TITLE_MAX_CHARS} code points with a trailing `…`.
|
|
7
|
+
*
|
|
8
|
+
* @module @deepseek-harness-tui/dsh-tui/migrate/parse/title
|
|
9
|
+
*/
|
|
10
|
+
/** Longest normalized title, in code points (the ellipsis included). */
|
|
11
|
+
export const TITLE_MAX_CHARS = 80;
|
|
12
|
+
const ELLIPSIS = '…';
|
|
13
|
+
/**
|
|
14
|
+
* Normalize a candidate title.
|
|
15
|
+
* @param text - Raw title or first prompt.
|
|
16
|
+
* @returns The one-line title, or '' when the input is blank.
|
|
17
|
+
*/
|
|
18
|
+
export function normalizeTitle(text) {
|
|
19
|
+
if (text === undefined)
|
|
20
|
+
return '';
|
|
21
|
+
const flat = text.trim().replace(/\s+/gu, ' ');
|
|
22
|
+
if (flat === '')
|
|
23
|
+
return '';
|
|
24
|
+
// Code points, not UTF-16 units: a cut must never split a surrogate pair.
|
|
25
|
+
const points = Array.from(flat);
|
|
26
|
+
if (points.length <= TITLE_MAX_CHARS)
|
|
27
|
+
return flat;
|
|
28
|
+
return `${points.slice(0, TITLE_MAX_CHARS - ELLIPSIS.length).join('').trimEnd()}${ELLIPSIS}`;
|
|
29
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool-call pairing for imported conversations.
|
|
3
|
+
*
|
|
4
|
+
* The one hard rule for replaying tool traffic is wire legality: every tool
|
|
5
|
+
* call is answered by exactly one tool message before any later assistant
|
|
6
|
+
* message, and every tool message answers a call. Sources do not guarantee
|
|
7
|
+
* that — results arrive steps after their call (Claude batches them behind
|
|
8
|
+
* consecutive assistant rows), transcripts start mid-conversation, runs are
|
|
9
|
+
* interrupted before a result lands. This module restores the rule:
|
|
10
|
+
*
|
|
11
|
+
* - {@link CallIndex} attaches a late result to the STEP that made the call,
|
|
12
|
+
* never to whatever step is newest;
|
|
13
|
+
* - {@link closeToolPairs} orders each step's results by call order, drops
|
|
14
|
+
* orphans and duplicates (counted), and answers unanswered calls with an
|
|
15
|
+
* empty result.
|
|
16
|
+
*
|
|
17
|
+
* @module @deepseek-harness-tui/dsh-tui/migrate/parse/tools
|
|
18
|
+
*/
|
|
19
|
+
import type { ImportStep, ImportTurn } from '../types.js';
|
|
20
|
+
/** Largest tool-result text kept per result, in UTF-8 bytes. */
|
|
21
|
+
export declare const TOOL_RESULT_MAX_BYTES: number;
|
|
22
|
+
/** Placeholder written instead of image bytes (never base64 into the log). */
|
|
23
|
+
export declare const IMAGE_PLACEHOLDER = "[image]";
|
|
24
|
+
/** A fresh empty step. */
|
|
25
|
+
export declare function newStep(model?: string): ImportStep;
|
|
26
|
+
/**
|
|
27
|
+
* Clamp a tool-result text to {@link TOOL_RESULT_MAX_BYTES}, cutting on a
|
|
28
|
+
* character boundary and noting how much was dropped.
|
|
29
|
+
*/
|
|
30
|
+
export declare function clampToolText(text: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Session-wide call-id → step index. Register a step's calls when the step
|
|
33
|
+
* is built; attach results as they arrive, wherever they arrive.
|
|
34
|
+
*/
|
|
35
|
+
export declare class CallIndex {
|
|
36
|
+
private readonly stepOf;
|
|
37
|
+
/** Results whose call id was never registered. */
|
|
38
|
+
orphans: number;
|
|
39
|
+
/** Index every tool-call block currently in `step`. */
|
|
40
|
+
register(step: ImportStep): void;
|
|
41
|
+
/** Whether a call with this id has been registered. */
|
|
42
|
+
has(callId: string): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Attach one result to the step that made the call.
|
|
45
|
+
* @returns false (and counts an orphan) when no such call is known.
|
|
46
|
+
*/
|
|
47
|
+
attach(callId: string, text: string, isError: boolean): boolean;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Make every step wire-legal, in place.
|
|
51
|
+
*
|
|
52
|
+
* Per step: results follow call order; a result for a call not in the step,
|
|
53
|
+
* or a second result for one call, is dropped; a call without a result gets
|
|
54
|
+
* an empty one. Across the session, a call id reused by a later step (a
|
|
55
|
+
* source retry the source-specific cleanup did not collapse) is renamed
|
|
56
|
+
* `<id>#<n>` together with its result — the session log folds tool calls by
|
|
57
|
+
* id, and a duplicate id would swallow everything after it.
|
|
58
|
+
*
|
|
59
|
+
* @returns How many results were dropped.
|
|
60
|
+
*/
|
|
61
|
+
export declare function closeToolPairs(turns: readonly ImportTurn[]): number;
|
|
62
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../../../src/dsh-adapter/migrate/parse/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAEzD,gEAAgE;AAChE,eAAO,MAAM,qBAAqB,QAAY,CAAA;AAE9C,8EAA8E;AAC9E,eAAO,MAAM,iBAAiB,YAAY,CAAA;AAE1C,0BAA0B;AAC1B,wBAAgB,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,UAAU,CAElD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASlD;AAED;;;GAGG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgC;IACvD,kDAAkD;IAClD,OAAO,SAAI;IAEX,uDAAuD;IACvD,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAMhC,uDAAuD;IACvD,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAI5B;;;OAGG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO;CAShE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,MAAM,CAmCnE"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/** Largest tool-result text kept per result, in UTF-8 bytes. */
|
|
2
|
+
export const TOOL_RESULT_MAX_BYTES = 64 * 1024;
|
|
3
|
+
/** Placeholder written instead of image bytes (never base64 into the log). */
|
|
4
|
+
export const IMAGE_PLACEHOLDER = '[image]';
|
|
5
|
+
/** A fresh empty step. */
|
|
6
|
+
export function newStep(model) {
|
|
7
|
+
return model === undefined ? { inputs: [], blocks: [], results: [] } : { inputs: [], blocks: [], results: [], model };
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Clamp a tool-result text to {@link TOOL_RESULT_MAX_BYTES}, cutting on a
|
|
11
|
+
* character boundary and noting how much was dropped.
|
|
12
|
+
*/
|
|
13
|
+
export function clampToolText(text) {
|
|
14
|
+
// Cheap pre-check: UTF-8 needs at most 3 bytes per UTF-16 unit.
|
|
15
|
+
if (text.length * 3 <= TOOL_RESULT_MAX_BYTES)
|
|
16
|
+
return text;
|
|
17
|
+
const bytes = Buffer.from(text, 'utf8');
|
|
18
|
+
if (bytes.length <= TOOL_RESULT_MAX_BYTES)
|
|
19
|
+
return text;
|
|
20
|
+
let end = TOOL_RESULT_MAX_BYTES;
|
|
21
|
+
// Back off continuation bytes (10xxxxxx) so the cut never splits a character.
|
|
22
|
+
while (end > 0 && (bytes[end] & 0xc0) === 0x80)
|
|
23
|
+
end -= 1;
|
|
24
|
+
return `${bytes.subarray(0, end).toString('utf8')}…[truncated ${bytes.length - end} bytes]`;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Session-wide call-id → step index. Register a step's calls when the step
|
|
28
|
+
* is built; attach results as they arrive, wherever they arrive.
|
|
29
|
+
*/
|
|
30
|
+
export class CallIndex {
|
|
31
|
+
stepOf = new Map();
|
|
32
|
+
/** Results whose call id was never registered. */
|
|
33
|
+
orphans = 0;
|
|
34
|
+
/** Index every tool-call block currently in `step`. */
|
|
35
|
+
register(step) {
|
|
36
|
+
for (const block of step.blocks) {
|
|
37
|
+
if (block.type === 'tool-call')
|
|
38
|
+
this.stepOf.set(block.id, step);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** Whether a call with this id has been registered. */
|
|
42
|
+
has(callId) {
|
|
43
|
+
return this.stepOf.has(callId);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Attach one result to the step that made the call.
|
|
47
|
+
* @returns false (and counts an orphan) when no such call is known.
|
|
48
|
+
*/
|
|
49
|
+
attach(callId, text, isError) {
|
|
50
|
+
const step = this.stepOf.get(callId);
|
|
51
|
+
if (step === undefined) {
|
|
52
|
+
this.orphans += 1;
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
step.results.push({ callId, text: clampToolText(text), isError });
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Make every step wire-legal, in place.
|
|
61
|
+
*
|
|
62
|
+
* Per step: results follow call order; a result for a call not in the step,
|
|
63
|
+
* or a second result for one call, is dropped; a call without a result gets
|
|
64
|
+
* an empty one. Across the session, a call id reused by a later step (a
|
|
65
|
+
* source retry the source-specific cleanup did not collapse) is renamed
|
|
66
|
+
* `<id>#<n>` together with its result — the session log folds tool calls by
|
|
67
|
+
* id, and a duplicate id would swallow everything after it.
|
|
68
|
+
*
|
|
69
|
+
* @returns How many results were dropped.
|
|
70
|
+
*/
|
|
71
|
+
export function closeToolPairs(turns) {
|
|
72
|
+
let dropped = 0;
|
|
73
|
+
const seen = new Set();
|
|
74
|
+
for (const turn of turns) {
|
|
75
|
+
for (const step of turn.steps) {
|
|
76
|
+
const renamed = new Map();
|
|
77
|
+
step.blocks = step.blocks.map(block => {
|
|
78
|
+
if (block.type !== 'tool-call')
|
|
79
|
+
return block;
|
|
80
|
+
let id = block.id;
|
|
81
|
+
for (let n = 2; seen.has(id); n += 1)
|
|
82
|
+
id = `${block.id}#${n}`;
|
|
83
|
+
seen.add(id);
|
|
84
|
+
if (id === block.id)
|
|
85
|
+
return block;
|
|
86
|
+
renamed.set(block.id, id);
|
|
87
|
+
return { ...block, id };
|
|
88
|
+
});
|
|
89
|
+
const byCall = new Map();
|
|
90
|
+
for (const result of step.results) {
|
|
91
|
+
const callId = renamed.get(result.callId) ?? result.callId;
|
|
92
|
+
if (byCall.has(callId)) {
|
|
93
|
+
dropped += 1;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
byCall.set(callId, callId === result.callId ? result : { ...result, callId });
|
|
97
|
+
}
|
|
98
|
+
const ordered = [];
|
|
99
|
+
for (const block of step.blocks) {
|
|
100
|
+
if (block.type !== 'tool-call')
|
|
101
|
+
continue;
|
|
102
|
+
ordered.push(byCall.get(block.id) ?? { callId: block.id, text: '', isError: false });
|
|
103
|
+
byCall.delete(block.id);
|
|
104
|
+
}
|
|
105
|
+
dropped += byCall.size;
|
|
106
|
+
step.results = ordered;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return dropped;
|
|
110
|
+
}
|