@deepseek-harness-tui/dsh-tui 0.9.0 → 0.9.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 +69 -256
- package/bin/dsh-tui.js +172 -5
- package/cordis.patch.yml +16 -4
- package/dsh-ecosystem-spec/protocols/profile-definitions.d.ts +13 -13
- package/dsh-ecosystem-spec/protocols/profile-definitions.js +59 -59
- package/dsh-ecosystem-spec/protocols/tui-channel-http.d.ts +15 -15
- package/dsh-ecosystem-spec/protocols/tui-channel-http.js +32 -32
- package/dsh-ecosystem-spec/protocols/tui-channel.d.ts +59 -59
- package/dsh-ecosystem-spec/protocols/tui-channel.js +166 -166
- package/dsh-ecosystem-spec/protocols/tui-contributions.d.ts +42 -42
- package/dsh-ecosystem-spec/protocols/tui-contributions.js +143 -143
- package/dsh-ecosystem-spec/registry/README.md +14 -14
- package/dsh-ecosystem-spec/registry/host-descriptor.tui.example.json +56 -56
- package/dsh-ecosystem-spec/registry/permissions-0.1.json +13 -13
- package/dsh-ecosystem-spec/registry/registry-0.15.json +149 -149
- package/lib/types/cc/hyperlink.d.ts +7 -1
- package/lib/types/cc/hyperlink.d.ts.map +1 -1
- package/lib/types/cc/hyperlink.js +3 -2
- package/lib/types/cc/markdown.d.ts.map +1 -1
- package/lib/types/cc/markdown.js +33 -3
- package/lib/types/cc/sessionColors.d.ts +27 -0
- package/lib/types/cc/sessionColors.d.ts.map +1 -0
- package/lib/types/cc/sessionColors.js +39 -0
- package/lib/types/commands.d.ts.map +1 -1
- package/lib/types/commands.js +6 -0
- package/lib/types/components/AutoRecapRow.d.ts +23 -0
- package/lib/types/components/AutoRecapRow.d.ts.map +1 -0
- package/lib/types/components/AutoRecapRow.js +23 -0
- package/lib/types/components/ColorPicker.d.ts +17 -0
- package/lib/types/components/ColorPicker.d.ts.map +1 -0
- package/lib/types/components/ColorPicker.js +20 -0
- package/lib/types/components/CommandSuggestions.d.ts +3 -1
- package/lib/types/components/CommandSuggestions.d.ts.map +1 -1
- package/lib/types/components/ContextBarView.d.ts +33 -0
- package/lib/types/components/ContextBarView.d.ts.map +1 -0
- package/lib/types/components/ContextBarView.js +46 -0
- package/lib/types/components/EffortInputBorder.d.ts +12 -1
- package/lib/types/components/EffortInputBorder.d.ts.map +1 -1
- package/lib/types/components/EffortInputBorder.js +22 -5
- package/lib/types/components/FileActionsPanel.d.ts +22 -0
- package/lib/types/components/FileActionsPanel.d.ts.map +1 -0
- package/lib/types/components/FileActionsPanel.js +28 -0
- package/lib/types/components/FileSuggestions.d.ts +3 -1
- package/lib/types/components/FileSuggestions.d.ts.map +1 -1
- package/lib/types/components/MessageList.d.ts +3 -1
- package/lib/types/components/MessageList.d.ts.map +1 -1
- package/lib/types/components/MessageList.js +13 -6
- package/lib/types/components/ModelPicker.d.ts +26 -4
- package/lib/types/components/ModelPicker.d.ts.map +1 -1
- package/lib/types/components/ModelPicker.js +26 -6
- package/lib/types/components/PromptInput.d.ts.map +1 -1
- package/lib/types/components/PromptInput.js +365 -57
- package/lib/types/components/RecapPanel.d.ts +25 -0
- package/lib/types/components/RecapPanel.d.ts.map +1 -0
- package/lib/types/components/RecapPanel.js +55 -0
- package/lib/types/components/ScrollbarGutter.d.ts.map +1 -1
- package/lib/types/components/ScrollbarGutter.js +55 -4
- package/lib/types/components/SubagentCard.d.ts.map +1 -1
- package/lib/types/components/SubagentCard.js +6 -4
- package/lib/types/components/SuggestionCard.d.ts +4 -2
- package/lib/types/components/SuggestionCard.d.ts.map +1 -1
- package/lib/types/components/TimelineRail.d.ts.map +1 -1
- package/lib/types/components/TimelineRail.js +9 -2
- package/lib/types/components/design-system/ThemeProvider.d.ts +7 -0
- package/lib/types/components/design-system/ThemeProvider.d.ts.map +1 -1
- package/lib/types/components/design-system/ThemeProvider.js +2 -1
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts +8 -1
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantToolUseMessage.js +36 -8
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts +7 -3
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
- package/lib/types/components/questions/AskUserQuestionPanel.js +41 -9
- package/lib/types/dsh-adapter/channel.d.ts +101 -2
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +969 -93
- package/lib/types/dsh-adapter/compat/index.d.ts +8 -6
- package/lib/types/dsh-adapter/compat/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/index.js +8 -6
- package/lib/types/dsh-adapter/compat/sessionLog.d.ts +150 -0
- package/lib/types/dsh-adapter/compat/sessionLog.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/sessionLog.js +518 -41
- package/lib/types/dsh-adapter/contract.d.ts +1 -1
- package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
- package/lib/types/dsh-adapter/contract.js +1 -0
- package/lib/types/dsh-adapter/extension-events.d.ts +1 -1
- package/lib/types/dsh-adapter/extension-events.d.ts.map +1 -1
- package/lib/types/dsh-adapter/index.d.ts +10 -0
- package/lib/types/dsh-adapter/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/index.js +5 -0
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +317 -8
- package/lib/types/dsh-adapter/presets.d.ts +18 -0
- package/lib/types/dsh-adapter/presets.d.ts.map +1 -1
- package/lib/types/dsh-adapter/presets.js +31 -0
- package/lib/types/dsh-adapter/providerWizard.d.ts +29 -1
- package/lib/types/dsh-adapter/providerWizard.d.ts.map +1 -1
- package/lib/types/dsh-adapter/providerWizard.js +89 -5
- package/lib/types/dsh-adapter/questions.d.ts +19 -2
- package/lib/types/dsh-adapter/questions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/questions.js +53 -10
- package/lib/types/dsh-adapter/recap.d.ts +49 -0
- package/lib/types/dsh-adapter/recap.d.ts.map +1 -0
- package/lib/types/dsh-adapter/recap.js +121 -0
- package/lib/types/dsh-adapter/sessionTree.d.ts +314 -0
- package/lib/types/dsh-adapter/sessionTree.d.ts.map +1 -0
- package/lib/types/dsh-adapter/sessionTree.js +954 -0
- package/lib/types/dsh-adapter/shortcuts.d.ts +15 -44
- package/lib/types/dsh-adapter/shortcuts.d.ts.map +1 -1
- package/lib/types/dsh-adapter/shortcuts.js +28 -165
- package/lib/types/dsh-adapter/types.d.ts +1 -1
- package/lib/types/dsh-adapter/types.d.ts.map +1 -1
- package/lib/types/herdr.js +1 -1
- package/lib/types/i18n.d.ts +604 -176
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +206 -72
- package/lib/types/ink/log-update.d.ts.map +1 -1
- package/lib/types/ink/log-update.js +21 -0
- package/lib/types/migrationPrefs.d.ts +60 -0
- package/lib/types/migrationPrefs.d.ts.map +1 -0
- package/lib/types/migrationPrefs.js +97 -0
- package/lib/types/modelGroups.d.ts +72 -0
- package/lib/types/modelGroups.d.ts.map +1 -0
- package/lib/types/modelGroups.js +97 -0
- package/lib/types/modelRecents.d.ts +39 -0
- package/lib/types/modelRecents.d.ts.map +1 -0
- package/lib/types/modelRecents.js +97 -0
- package/lib/types/native-ts/yoga-layout/index.d.ts +11 -0
- package/lib/types/native-ts/yoga-layout/index.d.ts.map +1 -1
- package/lib/types/native-ts/yoga-layout/index.js +31 -1
- package/lib/types/oauth.d.ts +15 -0
- package/lib/types/oauth.d.ts.map +1 -0
- package/lib/types/oauth.js +14 -0
- package/lib/types/plugin-spec/registry.d.ts +1 -1
- package/lib/types/plugin-spec/registry.js +1 -1
- package/lib/types/reload.d.ts +109 -0
- package/lib/types/reload.d.ts.map +1 -0
- package/lib/types/reload.js +118 -0
- package/lib/types/screens/Chat.d.ts +3 -1
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +588 -64
- package/lib/types/screens/SessionTree.d.ts +27 -0
- package/lib/types/screens/SessionTree.d.ts.map +1 -0
- package/lib/types/screens/SessionTree.js +555 -0
- package/lib/types/screens/StatusLine.d.ts +0 -9
- package/lib/types/screens/StatusLine.d.ts.map +1 -1
- package/lib/types/screens/StatusLine.js +215 -52
- package/lib/types/screens/StatusMetrics.d.ts +35 -3
- package/lib/types/screens/StatusMetrics.d.ts.map +1 -1
- package/lib/types/screens/StatusMetrics.js +63 -8
- package/lib/types/screens/chatOverlay.d.ts +17 -1
- package/lib/types/screens/chatOverlay.d.ts.map +1 -1
- package/lib/types/screens/chatOverlay.js +3 -1
- package/lib/types/tips.d.ts.map +1 -1
- package/lib/types/tips.js +22 -4
- package/lib/types/update.d.ts +159 -0
- package/lib/types/update.d.ts.map +1 -1
- package/lib/types/update.js +496 -30
- package/lib/types/utils/debug.d.ts +1 -1
- package/lib/types/utils/debug.js +3 -3
- package/lib/types/utils/fileTarget.d.ts +46 -0
- package/lib/types/utils/fileTarget.d.ts.map +1 -0
- package/lib/types/utils/fileTarget.js +178 -0
- package/lib/types/utils/keymap.d.ts +134 -0
- package/lib/types/utils/keymap.d.ts.map +1 -0
- package/lib/types/utils/keymap.js +311 -0
- package/lib/types/utils/mentions.d.ts +25 -2
- package/lib/types/utils/mentions.d.ts.map +1 -1
- package/lib/types/utils/mentions.js +69 -10
- package/lib/types/utils/openExternal.d.ts +50 -0
- package/lib/types/utils/openExternal.d.ts.map +1 -0
- package/lib/types/utils/openExternal.js +170 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/LICENSE +21 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/README.md +140 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/cordis.patch.yml +11 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/dsh-plugin.json +44 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/command.d.ts +14 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/command.js +67 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/credentials.d.ts +64 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/credentials.js +170 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/index.d.ts +79 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/index.js +196 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/interaction.d.ts +68 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/interaction.js +193 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/opener.d.ts +32 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/opener.js +101 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/profiles.d.ts +31 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/profiles.js +68 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/service.d.ts +69 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/service.js +129 -0
- package/node_modules/@deepseek-harness-tui/dsh-auth/package.json +70 -0
- package/node_modules/@dsh-std/command/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/command/LICENSE +21 -21
- package/node_modules/@dsh-std/command/README.md +26 -26
- package/node_modules/@dsh-std/command/README.zh.md +28 -28
- package/node_modules/@dsh-std/command/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/command/package.json +22 -22
- package/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/connection/LICENSE +21 -21
- package/node_modules/@dsh-std/connection/README.md +42 -42
- package/node_modules/@dsh-std/connection/README.zh.md +42 -42
- package/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
- package/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
- package/node_modules/@dsh-std/connection/package.json +20 -20
- package/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/core/LICENSE +21 -21
- package/node_modules/@dsh-std/core/README.md +13 -13
- package/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/core/package.json +21 -21
- package/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -9
- package/node_modules/@dsh-std/manifest/LICENSE +21 -21
- package/node_modules/@dsh-std/manifest/README.md +5 -5
- package/node_modules/@dsh-std/manifest/README.zh.md +5 -5
- package/node_modules/@dsh-std/manifest/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/manifest/package.json +20 -20
- package/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -144
- package/node_modules/@dsh-std/messages/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/messages/LICENSE +21 -21
- package/node_modules/@dsh-std/messages/README.md +5 -5
- package/node_modules/@dsh-std/messages/README.zh.md +7 -7
- package/node_modules/@dsh-std/messages/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/messages/package.json +20 -20
- package/node_modules/@dsh-std/messages/schema/message-observer-envelope-0.15.schema.json +54 -54
- package/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -9
- package/node_modules/@dsh-std/presentation/LICENSE +21 -21
- package/node_modules/@dsh-std/presentation/README.md +27 -27
- package/node_modules/@dsh-std/presentation/README.zh.md +29 -29
- package/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -1
- package/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/presentation/package.json +25 -25
- package/node_modules/@dsh-std/storage/CHANGELOG.md +8 -8
- package/node_modules/@dsh-std/storage/LICENSE +21 -21
- package/node_modules/@dsh-std/storage/README.md +5 -5
- package/node_modules/@dsh-std/storage/README.zh.md +7 -7
- package/node_modules/@dsh-std/storage/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/storage/package.json +20 -20
- package/node_modules/@dsh-std/storage/schema/local-storage-0.15.schema.json +56 -56
- package/package.json +17 -5
- package/presets/liangshen/.dsh-tui-managed.json +1 -1
- package/presets/liangshen/instruction-hint.mjs +8 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/LICENSE +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.md +42 -42
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.zh.md +42 -42
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/package.json +20 -20
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -9
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/LICENSE +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.md +5 -5
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.zh.md +5 -5
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/package.json +20 -20
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -144
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -9
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/LICENSE +21 -21
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.md +27 -27
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.zh.md +29 -29
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/package.json +25 -25
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/LICENSE +21 -21
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.md +42 -42
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.zh.md +42 -42
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/package.json +20 -20
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/package.json +21 -21
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/CHANGELOG.md +8 -8
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/LICENSE +21 -21
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.md +13 -13
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.zh.md +13 -13
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/package.json +21 -21
|
@@ -5,14 +5,31 @@
|
|
|
5
5
|
* or after whitespace) — `hello@world` never triggers. The token body is
|
|
6
6
|
* either a run of non-whitespace characters (`@src/a.ts`) or a double-quoted
|
|
7
7
|
* path (`@"my dir/a.ts"`, for paths containing spaces).
|
|
8
|
+
*
|
|
9
|
+
* A token may carry a trailing line-range suffix (issue #359, Claude Code
|
|
10
|
+
* parity): `@src/a.ts#L12` / `@src/a.ts#L12-14` (also after a quoted body:
|
|
11
|
+
* `@"my dir/a.ts"#L3-5`). The suffix must anchor at the token END and match
|
|
12
|
+
* `#L<digits>` / `#L<digits>-<digits>` exactly, so legal filenames that merely
|
|
13
|
+
* contain `#` (`report#L12.md`) never trip it; a range like `#L14-12` is
|
|
14
|
+
* rejected (kept as a literal path). Resolution order is strip-first: the
|
|
15
|
+
* suffix-stripped `path` is tried, and the caller may fall back to `literal`
|
|
16
|
+
* (the typed body, suffix intact) when that misses.
|
|
8
17
|
*/
|
|
9
18
|
export interface MentionToken {
|
|
10
19
|
/** Start index of the `@` in the source text. */
|
|
11
20
|
start: number;
|
|
12
|
-
/** End index (exclusive) of the whole token, quote included. */
|
|
21
|
+
/** End index (exclusive) of the whole token, quote and suffix included. */
|
|
13
22
|
end: number;
|
|
14
|
-
/** The referenced path as typed (unquoted, no leading
|
|
23
|
+
/** The referenced path as typed (unquoted, no leading `@`, suffix stripped). */
|
|
15
24
|
path: string;
|
|
25
|
+
/** Present only when a line suffix was stripped: the typed body verbatim
|
|
26
|
+
* (unquoted, suffix intact) — the literal fallback path for resolution. */
|
|
27
|
+
literal?: string;
|
|
28
|
+
/** Inclusive 1-based first line of the `#L` suffix, when present. */
|
|
29
|
+
startLine?: number;
|
|
30
|
+
/** Inclusive 1-based last line of the `#L` suffix; equals `startLine`
|
|
31
|
+
* for the single-line form. */
|
|
32
|
+
endLine?: number;
|
|
16
33
|
}
|
|
17
34
|
/** Extract every `@` mention in `text` (typed order, duplicates kept out). */
|
|
18
35
|
export declare function extractMentions(text: string): MentionToken[];
|
|
@@ -21,10 +38,16 @@ export declare function extractMentions(text: string): MentionToken[];
|
|
|
21
38
|
* that starts at or before the caret with the caret inside it. Used by the
|
|
22
39
|
* prompt's completion trigger so `@` works mid-message, not only at the
|
|
23
40
|
* start of the input.
|
|
41
|
+
*
|
|
42
|
+
* `query` is the PATH portion only (a `#L12-14` suffix never leaks into
|
|
43
|
+
* it) and `pathEnd` marks where that portion ends, so completing a token
|
|
44
|
+
* like `@src/a.ts#L12` matches on `src/a.ts` and replaces up to (not past)
|
|
45
|
+
* the `#` — the typed line range survives acceptance.
|
|
24
46
|
*/
|
|
25
47
|
export declare function mentionAtCaret(value: string, cursor: number): {
|
|
26
48
|
start: number;
|
|
27
49
|
end: number;
|
|
28
50
|
query: string;
|
|
51
|
+
pathEnd?: number;
|
|
29
52
|
} | undefined;
|
|
30
53
|
//# sourceMappingURL=mentions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mentions.d.ts","sourceRoot":"","sources":["../../../src/utils/mentions.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"mentions.d.ts","sourceRoot":"","sources":["../../../src/utils/mentions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAA;IACb,2EAA2E;IAC3E,GAAG,EAAE,MAAM,CAAA;IACX,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAA;IACZ;+EAC2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;mCAC+B;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAoCD,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,CA+C5D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAkB7E"}
|
|
@@ -5,11 +5,43 @@
|
|
|
5
5
|
* or after whitespace) — `hello@world` never triggers. The token body is
|
|
6
6
|
* either a run of non-whitespace characters (`@src/a.ts`) or a double-quoted
|
|
7
7
|
* path (`@"my dir/a.ts"`, for paths containing spaces).
|
|
8
|
+
*
|
|
9
|
+
* A token may carry a trailing line-range suffix (issue #359, Claude Code
|
|
10
|
+
* parity): `@src/a.ts#L12` / `@src/a.ts#L12-14` (also after a quoted body:
|
|
11
|
+
* `@"my dir/a.ts"#L3-5`). The suffix must anchor at the token END and match
|
|
12
|
+
* `#L<digits>` / `#L<digits>-<digits>` exactly, so legal filenames that merely
|
|
13
|
+
* contain `#` (`report#L12.md`) never trip it; a range like `#L14-12` is
|
|
14
|
+
* rejected (kept as a literal path). Resolution order is strip-first: the
|
|
15
|
+
* suffix-stripped `path` is tried, and the caller may fall back to `literal`
|
|
16
|
+
* (the typed body, suffix intact) when that misses.
|
|
8
17
|
*/
|
|
9
18
|
/** True when `ch` delimits a token (whitespace). Path separators and the
|
|
10
19
|
* quote char are ordinary token characters on every platform — Windows
|
|
11
20
|
* backslash paths must survive both caret tracking and submission. */
|
|
12
21
|
const isBoundary = (ch) => ch === undefined || /\s/.test(ch);
|
|
22
|
+
/** Line-suffix shape: `#L7` or `#L7-9`, anchored at the token end. */
|
|
23
|
+
const LINE_SUFFIX = /#L(\d+)(?:-(\d+))?$/;
|
|
24
|
+
/**
|
|
25
|
+
* Split a trailing `#L7` / `#L7-9` suffix off an unquoted token body.
|
|
26
|
+
* Returns undefined when there is no suffix or the suffix is malformed
|
|
27
|
+
* (`#L0`, `#L9-7`, bare `#L12` with an empty path) — the caller then treats
|
|
28
|
+
* the body as a plain literal path, exactly as before issue #359.
|
|
29
|
+
*/
|
|
30
|
+
function splitLineSuffix(raw) {
|
|
31
|
+
const match = LINE_SUFFIX.exec(raw);
|
|
32
|
+
if (match === null)
|
|
33
|
+
return undefined;
|
|
34
|
+
const path = raw.slice(0, match.index);
|
|
35
|
+
if (path === '')
|
|
36
|
+
return undefined;
|
|
37
|
+
const startLine = Number(match[1]);
|
|
38
|
+
const endLine = match[2] === undefined ? startLine : Number(match[2]);
|
|
39
|
+
if (!Number.isInteger(startLine) || !Number.isInteger(endLine))
|
|
40
|
+
return undefined;
|
|
41
|
+
if (startLine < 1 || endLine < startLine)
|
|
42
|
+
return undefined;
|
|
43
|
+
return { path, literal: raw, startLine, endLine };
|
|
44
|
+
}
|
|
13
45
|
/** Extract every `@` mention in `text` (typed order, duplicates kept out). */
|
|
14
46
|
export function extractMentions(text) {
|
|
15
47
|
const tokens = [];
|
|
@@ -26,22 +58,41 @@ export function extractMentions(text) {
|
|
|
26
58
|
const close = text.indexOf('"', at + 2);
|
|
27
59
|
if (close === -1)
|
|
28
60
|
continue; // unterminated quote — not a mention
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
61
|
+
const quoted = text.slice(at + 2, close);
|
|
62
|
+
// `#L` suffix may follow the closing quote and extends the token.
|
|
63
|
+
let end = close + 1;
|
|
64
|
+
let range;
|
|
65
|
+
if (quoted !== '' && text[close + 1] === '#') {
|
|
66
|
+
let suffixEnd = close + 1;
|
|
67
|
+
while (suffixEnd < text.length && !isBoundary(text[suffixEnd]))
|
|
68
|
+
suffixEnd++;
|
|
69
|
+
// splitLineSuffix expects `path + suffix`; feeding it the quoted body
|
|
70
|
+
// plus the tail yields path === quoted and the typed literal.
|
|
71
|
+
range = splitLineSuffix(quoted + text.slice(close + 1, suffixEnd));
|
|
72
|
+
if (range !== undefined)
|
|
73
|
+
end = suffixEnd;
|
|
33
74
|
}
|
|
34
|
-
|
|
75
|
+
const key = text.slice(at, end);
|
|
76
|
+
if (quoted !== '' && !seen.has(key)) {
|
|
77
|
+
seen.add(key);
|
|
78
|
+
tokens.push(range === undefined
|
|
79
|
+
? { start: at, end, path: quoted }
|
|
80
|
+
: { start: at, end, path: quoted, literal: `${quoted}${text.slice(close + 1, end)}`, startLine: range.startLine, endLine: range.endLine });
|
|
81
|
+
}
|
|
82
|
+
index = end;
|
|
35
83
|
continue;
|
|
36
84
|
}
|
|
37
85
|
let end = at + 1;
|
|
38
86
|
while (end < text.length && !isBoundary(text[end]))
|
|
39
87
|
end++;
|
|
40
|
-
const
|
|
88
|
+
const raw = text.slice(at + 1, end);
|
|
41
89
|
// A bare `@` or another trigger char (`@@`) carries no path.
|
|
42
|
-
if (
|
|
43
|
-
seen.add(
|
|
44
|
-
|
|
90
|
+
if (raw && !raw.startsWith('@') && !seen.has(raw)) {
|
|
91
|
+
seen.add(raw);
|
|
92
|
+
const range = splitLineSuffix(raw);
|
|
93
|
+
tokens.push(range === undefined
|
|
94
|
+
? { start: at, end, path: raw }
|
|
95
|
+
: { start: at, end, path: range.path, literal: range.literal, startLine: range.startLine, endLine: range.endLine });
|
|
45
96
|
}
|
|
46
97
|
}
|
|
47
98
|
return tokens;
|
|
@@ -51,6 +102,11 @@ export function extractMentions(text) {
|
|
|
51
102
|
* that starts at or before the caret with the caret inside it. Used by the
|
|
52
103
|
* prompt's completion trigger so `@` works mid-message, not only at the
|
|
53
104
|
* start of the input.
|
|
105
|
+
*
|
|
106
|
+
* `query` is the PATH portion only (a `#L12-14` suffix never leaks into
|
|
107
|
+
* it) and `pathEnd` marks where that portion ends, so completing a token
|
|
108
|
+
* like `@src/a.ts#L12` matches on `src/a.ts` and replaces up to (not past)
|
|
109
|
+
* the `#` — the typed line range survives acceptance.
|
|
54
110
|
*/
|
|
55
111
|
export function mentionAtCaret(value, cursor) {
|
|
56
112
|
// Token start: scan back from the caret to the previous boundary.
|
|
@@ -70,5 +126,8 @@ export function mentionAtCaret(value, cursor) {
|
|
|
70
126
|
let end = cursor;
|
|
71
127
|
while (end < value.length && !isBoundary(value[end]))
|
|
72
128
|
end++;
|
|
73
|
-
|
|
129
|
+
const queryEnd = Math.min(cursor, end);
|
|
130
|
+
const range = splitLineSuffix(value.slice(start + 1, end));
|
|
131
|
+
const pathEnd = range === undefined ? end : start + 1 + range.path.length;
|
|
132
|
+
return { start, end, query: value.slice(start + 1, Math.min(queryEnd, pathEnd)), pathEnd: range === undefined ? undefined : pathEnd };
|
|
74
133
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Windows `start` via cmd.exe: `start "" "<target>"` (the empty quoted
|
|
3
|
+
* title is mandatory — start would otherwise treat a quoted target as the
|
|
4
|
+
* window title). Exported for tests: assembly is pure.
|
|
5
|
+
*/
|
|
6
|
+
export declare function buildWin32StartSpawn(target: string): {
|
|
7
|
+
file: string;
|
|
8
|
+
args: string[];
|
|
9
|
+
verbatim: true;
|
|
10
|
+
detach: true;
|
|
11
|
+
};
|
|
12
|
+
/** Whether `target` exists on disk as a directory (decides the open
|
|
13
|
+
* channel: folders bypass the ShellExecute verb and go through the
|
|
14
|
+
* Shell.Application COM API). Never throws. */
|
|
15
|
+
export declare function isDirectory(target: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* The Windows spawn descriptor for opening `target` (pure, testable):
|
|
18
|
+
* directories go through `powershell (New-Object -ComObject
|
|
19
|
+
* Shell.Application).Open('<dir>')`, everything else (files, URLs) through
|
|
20
|
+
* `start`. Explorer's single-instance forwarding silently swallows
|
|
21
|
+
* "open folder" requests on many systems (diagnosed in the field: `start`,
|
|
22
|
+
* raw explorer, and `/select,` all dead while the COM API works), so the
|
|
23
|
+
* COM channel is the reliable folder opener; single quotes in the path are
|
|
24
|
+
* doubled for the PowerShell literal. The COM descriptor also carries
|
|
25
|
+
* `detach: false` — a DETACHED_PROCESS (console-less) PowerShell silently
|
|
26
|
+
* drops the Shell.Application Open call, so the channel only works with
|
|
27
|
+
* `windowsHide` (CREATE_NO_WINDOW) alone (field-diagnosed spawn matrix:
|
|
28
|
+
* detached+hide → dead, hide-only → works; start keeps working detached).
|
|
29
|
+
*/
|
|
30
|
+
export declare function buildWin32OpenSpawn(target: string): {
|
|
31
|
+
file: string;
|
|
32
|
+
args: string[];
|
|
33
|
+
verbatim: boolean;
|
|
34
|
+
detach: boolean;
|
|
35
|
+
};
|
|
36
|
+
/** Open a URL, file or directory with the platform's default handler. */
|
|
37
|
+
export declare function openExternal(target: string): void;
|
|
38
|
+
/** Open a file with its associated application (openExternal with a file). */
|
|
39
|
+
export declare function openFile(path: string): void;
|
|
40
|
+
/**
|
|
41
|
+
* Open the folder containing `filePath` in the platform file manager.
|
|
42
|
+
*
|
|
43
|
+
* Windows and Linux open the parent DIRECTORY through openExternal —
|
|
44
|
+
* Windows routes folders through the Shell.Application COM channel (see
|
|
45
|
+
* buildWin32OpenSpawn). macOS uses `open -R` to select the file, degrading
|
|
46
|
+
* to the folder when the file is gone. No-op when neither the file nor its
|
|
47
|
+
* parent exists (a stale/hallucinated path must not spawn error dialogs).
|
|
48
|
+
*/
|
|
49
|
+
export declare function revealInFileManager(filePath: string): void;
|
|
50
|
+
//# sourceMappingURL=openExternal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openExternal.d.ts","sourceRoot":"","sources":["../../../src/utils/openExternal.ts"],"names":[],"mappings":"AAgEA;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,IAAI,CAAA;CAAE,CAQnH;AAED;;gDAEgD;AAChD,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAMnD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAWxH;AAED,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAqBjD;AAED,8EAA8E;AAC9E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE3C;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAgB1D"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Open URLs, files and folders with the platform's default handler, fully
|
|
3
|
+
* detached from the TUI process (fire-and-forget: no stdio pipes, no wait,
|
|
4
|
+
* child unref'd so the TUI can exit without waiting for the handler).
|
|
5
|
+
*
|
|
6
|
+
* Launch strategy per platform:
|
|
7
|
+
* - Windows files/URLs: `start` is a cmd.exe builtin, so everything goes
|
|
8
|
+
* through `$comspec /d /s /c start "" "<target>"` using the vendored
|
|
9
|
+
* cross-spawn quoting (shellQuote.ts) with windowsVerbatimArguments —
|
|
10
|
+
* the same protocol externalEditor.ts uses for .cmd shims.
|
|
11
|
+
* - Windows DIRECTORIES: `powershell (New-Object -ComObject
|
|
12
|
+
* Shell.Application).Open('<dir>')`. Explorer's single-instance
|
|
13
|
+
* forwarding silently swallows "open folder" requests on many systems
|
|
14
|
+
* (field-diagnosed: `start`, raw explorer and `/select,` all dead while
|
|
15
|
+
* the COM API works), so folders bypass ShellExecute entirely. This
|
|
16
|
+
* powershell child must NOT be spawned detached: libuv maps
|
|
17
|
+
* `detached: true` to DETACHED_PROCESS (a console-less process) and in
|
|
18
|
+
* that state the Shell.Application Open call silently does nothing
|
|
19
|
+
* (field-diagnosed via spawn matrix: detached+hide dead, hide-only
|
|
20
|
+
* works) — `windowsHide` alone (CREATE_NO_WINDOW) keeps it invisible
|
|
21
|
+
* AND functional.
|
|
22
|
+
* - macOS: `open` (reveal adds `-R`).
|
|
23
|
+
* - Linux/other: `xdg-open`.
|
|
24
|
+
*/
|
|
25
|
+
import { spawn } from 'node:child_process';
|
|
26
|
+
import { dirname } from 'node:path';
|
|
27
|
+
import { existsSync, statSync } from 'node:fs';
|
|
28
|
+
import { cmdEscapeArgument } from './shellQuote.js';
|
|
29
|
+
import { logError } from './log.js';
|
|
30
|
+
/**
|
|
31
|
+
* Spawn a fire-and-forget child: no stdio pipes, no wait, unref'd so the
|
|
32
|
+
* TUI can exit without waiting for the handler. On Windows `detach`
|
|
33
|
+
* controls the DETACHED_PROCESS flag — it must stay false for the
|
|
34
|
+
* Shell.Application COM channel (console-less PowerShell swallows the
|
|
35
|
+
* Open call; see buildWin32OpenSpawn). Failures are logged, never
|
|
36
|
+
* thrown — an unopenable target (missing handler, sandboxed desktop)
|
|
37
|
+
* must not disturb the TUI. `onError` lets callers degrade (e.g.
|
|
38
|
+
* reveal → open parent folder).
|
|
39
|
+
*/
|
|
40
|
+
function spawnDetached(file, args, opts = {}) {
|
|
41
|
+
const { verbatim = false, detach = true, onError } = opts;
|
|
42
|
+
try {
|
|
43
|
+
const child = spawn(file, [...args], {
|
|
44
|
+
stdio: 'ignore',
|
|
45
|
+
detached: detach,
|
|
46
|
+
windowsHide: true,
|
|
47
|
+
windowsVerbatimArguments: verbatim,
|
|
48
|
+
});
|
|
49
|
+
child.on('error', error => {
|
|
50
|
+
logError(error);
|
|
51
|
+
onError?.();
|
|
52
|
+
});
|
|
53
|
+
child.unref();
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
logError(error);
|
|
57
|
+
onError?.();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Windows `start` via cmd.exe: `start "" "<target>"` (the empty quoted
|
|
62
|
+
* title is mandatory — start would otherwise treat a quoted target as the
|
|
63
|
+
* window title). Exported for tests: assembly is pure.
|
|
64
|
+
*/
|
|
65
|
+
export function buildWin32StartSpawn(target) {
|
|
66
|
+
const line = ['start', cmdEscapeArgument(''), cmdEscapeArgument(target)].join(' ');
|
|
67
|
+
return {
|
|
68
|
+
file: process.env.ComSpec || 'cmd.exe',
|
|
69
|
+
args: ['/d', '/s', '/c', `"${line}"`],
|
|
70
|
+
verbatim: true,
|
|
71
|
+
detach: true,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/** Whether `target` exists on disk as a directory (decides the open
|
|
75
|
+
* channel: folders bypass the ShellExecute verb and go through the
|
|
76
|
+
* Shell.Application COM API). Never throws. */
|
|
77
|
+
export function isDirectory(target) {
|
|
78
|
+
try {
|
|
79
|
+
return statSync(target).isDirectory();
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The Windows spawn descriptor for opening `target` (pure, testable):
|
|
87
|
+
* directories go through `powershell (New-Object -ComObject
|
|
88
|
+
* Shell.Application).Open('<dir>')`, everything else (files, URLs) through
|
|
89
|
+
* `start`. Explorer's single-instance forwarding silently swallows
|
|
90
|
+
* "open folder" requests on many systems (diagnosed in the field: `start`,
|
|
91
|
+
* raw explorer, and `/select,` all dead while the COM API works), so the
|
|
92
|
+
* COM channel is the reliable folder opener; single quotes in the path are
|
|
93
|
+
* doubled for the PowerShell literal. The COM descriptor also carries
|
|
94
|
+
* `detach: false` — a DETACHED_PROCESS (console-less) PowerShell silently
|
|
95
|
+
* drops the Shell.Application Open call, so the channel only works with
|
|
96
|
+
* `windowsHide` (CREATE_NO_WINDOW) alone (field-diagnosed spawn matrix:
|
|
97
|
+
* detached+hide → dead, hide-only → works; start keeps working detached).
|
|
98
|
+
*/
|
|
99
|
+
export function buildWin32OpenSpawn(target) {
|
|
100
|
+
if (isDirectory(target)) {
|
|
101
|
+
const literal = target.replace(/'/g, "''");
|
|
102
|
+
return {
|
|
103
|
+
file: 'powershell.exe',
|
|
104
|
+
args: ['-NoProfile', '-Command', `(New-Object -ComObject Shell.Application).Open('${literal}')`],
|
|
105
|
+
verbatim: false,
|
|
106
|
+
detach: false,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return buildWin32StartSpawn(target);
|
|
110
|
+
}
|
|
111
|
+
/** Open a URL, file or directory with the platform's default handler. */
|
|
112
|
+
export function openExternal(target) {
|
|
113
|
+
if (target === '')
|
|
114
|
+
return;
|
|
115
|
+
if (process.platform === 'win32') {
|
|
116
|
+
const cmd = buildWin32OpenSpawn(target);
|
|
117
|
+
// If the primary channel cannot even spawn (e.g. PowerShell missing on
|
|
118
|
+
// an exotic system), fall back to `start` — reliable on healthy boxes.
|
|
119
|
+
spawnDetached(cmd.file, cmd.args, {
|
|
120
|
+
verbatim: cmd.verbatim,
|
|
121
|
+
detach: cmd.detach,
|
|
122
|
+
onError: () => {
|
|
123
|
+
if (cmd.file !== (process.env.ComSpec || 'cmd.exe')) {
|
|
124
|
+
const fb = buildWin32StartSpawn(target);
|
|
125
|
+
spawnDetached(fb.file, fb.args, { verbatim: fb.verbatim });
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
else if (process.platform === 'darwin') {
|
|
131
|
+
spawnDetached('open', [target]);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
spawnDetached('xdg-open', [target]);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/** Open a file with its associated application (openExternal with a file). */
|
|
138
|
+
export function openFile(path) {
|
|
139
|
+
openExternal(path);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Open the folder containing `filePath` in the platform file manager.
|
|
143
|
+
*
|
|
144
|
+
* Windows and Linux open the parent DIRECTORY through openExternal —
|
|
145
|
+
* Windows routes folders through the Shell.Application COM channel (see
|
|
146
|
+
* buildWin32OpenSpawn). macOS uses `open -R` to select the file, degrading
|
|
147
|
+
* to the folder when the file is gone. No-op when neither the file nor its
|
|
148
|
+
* parent exists (a stale/hallucinated path must not spawn error dialogs).
|
|
149
|
+
*/
|
|
150
|
+
export function revealInFileManager(filePath) {
|
|
151
|
+
if (filePath === '')
|
|
152
|
+
return;
|
|
153
|
+
const dir = dirname(filePath);
|
|
154
|
+
if (process.platform === 'darwin') {
|
|
155
|
+
if (existsSync(filePath)) {
|
|
156
|
+
spawnDetached('open', ['-R', filePath], {
|
|
157
|
+
onError: () => {
|
|
158
|
+
if (existsSync(dir))
|
|
159
|
+
openExternal(dir);
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (existsSync(dir))
|
|
165
|
+
openExternal(dir);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (existsSync(dir))
|
|
169
|
+
openExternal(dir);
|
|
170
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ccch1mneyyy
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# @deepseek-harness-tui/dsh-auth
|
|
2
|
+
|
|
3
|
+
> Subscription OAuth sign-in for [dsh-TUI](https://github.com/ccch1mneyyy/dsh-TUI) and
|
|
4
|
+
> [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)
|
|
5
|
+
|
|
6
|
+
Use your **ChatGPT (Plus/Pro)**, **Claude (Pro/Max)** and **SuperGrok / X Premium**
|
|
7
|
+
subscriptions as model providers — sign in with the official account, no API
|
|
8
|
+
keys, and **no dsh source patch**. This plugin is developed alongside (and
|
|
9
|
+
bundled into) [dsh-TUI](https://github.com/ccch1mneyyy/dsh-TUI), the
|
|
10
|
+
Claude Code style terminal front door for DeepSeek Harness; it also installs
|
|
11
|
+
standalone into any dsh profile.
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
dsh-tui → /provider → 订阅账号登录(OAuth)→ sign in ← the TUI integration
|
|
15
|
+
/auth login openai-codex ← the plugin command
|
|
16
|
+
/model → OpenAI Codex → gpt-5.6-sol ← routes & models
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Status: experimental (M1).** The OAuth flows themselves are
|
|
20
|
+
[pi-ai](https://www.npmjs.com/package/@earendil-works/pi-ai)'s shipped
|
|
21
|
+
implementations (device-code and loopback callback included); this plugin
|
|
22
|
+
adds the hosting: credential storage, automatic token refresh, adapter
|
|
23
|
+
registration, and a login surface over the `userQuestions` seam that works in
|
|
24
|
+
the TUI, the web client, and refuses cleanly on headless hosts.
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
**With dsh-TUI** — nothing to do: dsh-auth ships inside the dsh-tui package
|
|
29
|
+
(bundled dependency). Update dsh-tui and the `/provider` wizard gains its
|
|
30
|
+
subscription sign-in branch automatically.
|
|
31
|
+
|
|
32
|
+
**Standalone, into any dsh profile:**
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
dsh plugin --profile <name> add @deepseek-harness-tui/dsh-auth
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Then restart the host; `/` lists `auth`, and every model picker gains the
|
|
39
|
+
signed-in providers' catalogs (credential-gated — see below).
|
|
40
|
+
|
|
41
|
+
## What it does
|
|
42
|
+
|
|
43
|
+
- Mounts the pi-ai catalog providers that ship OAuth flows as `llm` registry
|
|
44
|
+
routes: `openai-codex`, `anthropic`, `xai`. **Models appear in a picker
|
|
45
|
+
only after that provider is signed in** (credential-gated listing) — sign
|
|
46
|
+
in and the catalog appears, sign out and it disappears; model ids already
|
|
47
|
+
saved in sessions stay resolvable either way.
|
|
48
|
+
- `/auth login [provider]` runs the provider's OAuth flow interactively. The
|
|
49
|
+
waiting panel behaves the way pi's host does: the authorization URL is
|
|
50
|
+
**opened in your browser automatically** (never hand-copied — the URL is
|
|
51
|
+
hundreds of characters and wrap artifacts corrupt its `redirect_uri`),
|
|
52
|
+
and the panel offers *Copy authorization link* / *Open browser again* /
|
|
53
|
+
*Cancel sign-in*. Device-code flows open the verification page and make
|
|
54
|
+
the short code the copy target. OpenAI Codex also offers a device-code
|
|
55
|
+
login method — the most robust path on headless or locked-down machines
|
|
56
|
+
(no localhost:1455 callback needed).
|
|
57
|
+
- Stored access tokens refresh automatically before each request, serialized
|
|
58
|
+
per provider under the credential store's lock — concurrent requests never
|
|
59
|
+
double-refresh a rotated token.
|
|
60
|
+
- `/auth status` / `/auth logout <provider>`; the `ctx.dshAuth` service
|
|
61
|
+
exposes the same api for UIs (the dsh-tui `/provider` wizard and `/login`
|
|
62
|
+
ride it).
|
|
63
|
+
|
|
64
|
+
## Usage
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
/auth # status: which providers are signed in
|
|
68
|
+
/auth login # pick a provider interactively
|
|
69
|
+
/auth login openai-codex # ChatGPT (Plus/Pro)
|
|
70
|
+
/auth login anthropic # Claude (Pro/Max)
|
|
71
|
+
/auth login xai # SuperGrok / X Premium
|
|
72
|
+
/auth logout anthropic
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Model requests against a provider you have not signed in to fail loudly with
|
|
76
|
+
the `/auth login <provider>` hint — never silently.
|
|
77
|
+
|
|
78
|
+
## Configuration
|
|
79
|
+
|
|
80
|
+
```yaml
|
|
81
|
+
- id: dsh-auth
|
|
82
|
+
name: '@deepseek-harness-tui/dsh-auth'
|
|
83
|
+
config:
|
|
84
|
+
providers: [openai-codex, anthropic, xai] # any non-empty subset
|
|
85
|
+
# credentialsFile: /secure/path/credentials.json
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- `credentialsFile` defaults to `$DSH_HOME/dsh-auth/credentials.json`
|
|
89
|
+
(`~/.dsh/dsh-auth/credentials.json`), overridable with the
|
|
90
|
+
`DSH_AUTH_CREDENTIALS` environment variable. The directory is created
|
|
91
|
+
`0700`, the file `0600` (best-effort on Windows), and every write is
|
|
92
|
+
atomic (temp file + rename).
|
|
93
|
+
- A route another adapter family already owns — an `llm-pi-ai` settings
|
|
94
|
+
profile naming the same provider — is refused by the registry; the plugin
|
|
95
|
+
logs the refusal and mounts the remaining routes. Keep one provider on one
|
|
96
|
+
adapter.
|
|
97
|
+
|
|
98
|
+
## Security notes
|
|
99
|
+
|
|
100
|
+
- The credential file holds **long-lived refresh tokens**. It is never
|
|
101
|
+
logged, never echoed through status surfaces (`/auth status` shows expiry
|
|
102
|
+
metadata only), and a corrupt file fails loudly instead of being
|
|
103
|
+
overwritten.
|
|
104
|
+
- Secret prompts warn that terminal input is not masked on this surface.
|
|
105
|
+
- Login refuses to run where no interactive surface is registered (no
|
|
106
|
+
browser/GUI assumptions — remote and headless hosts get a clear error,
|
|
107
|
+
per the ecosystem spec's remote-determinism rule, TUI-RUN-001).
|
|
108
|
+
- Subscription authentication and API-key access are different products:
|
|
109
|
+
this plugin uses each provider's subscription backend only (ChatGPT Codex
|
|
110
|
+
backend for OpenAI, Claude Pro/Max for Anthropic) and does not turn a
|
|
111
|
+
subscription into a general-purpose API credential.
|
|
112
|
+
|
|
113
|
+
## Development
|
|
114
|
+
|
|
115
|
+
```sh
|
|
116
|
+
pnpm install
|
|
117
|
+
pnpm verify # build + headless smoke (credential store, refresh
|
|
118
|
+
# serialization, prompt bridging, gating, service api)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The smoke suite runs without cordis or a harness: the pure modules are
|
|
122
|
+
exercised directly. Real end-to-end login needs an interactive host
|
|
123
|
+
(dsh-tui) and is verified manually per release. The plugin is developed in
|
|
124
|
+
the [dsh-TUI repository](https://github.com/ccch1mneyyy/dsh-TUI) as the
|
|
125
|
+
`dsh-auth/` submodule and mirrors to this repository.
|
|
126
|
+
|
|
127
|
+
## Roadmap
|
|
128
|
+
|
|
129
|
+
- **M2** *(landed)* — dsh-tui integration: `/provider` OAuth branch, `/login`
|
|
130
|
+
account section, two-level `/model` picker with a pinned recently-used
|
|
131
|
+
group.
|
|
132
|
+
- **M3** — `dsh-ecosystem-spec` conformance (manifest validation, admission
|
|
133
|
+
fixtures) plus the remaining pi-ai OAuth providers (GitHub Copilot,
|
|
134
|
+
OpenRouter, Kimi); community list entry.
|
|
135
|
+
- **M4** — Gemini: a custom Google device-code flow (pi-ai ships none; this
|
|
136
|
+
is the one wheel this project plans to build itself).
|
|
137
|
+
|
|
138
|
+
## License
|
|
139
|
+
|
|
140
|
+
MIT
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# @deepseek-harness-tui/dsh-auth bundle patch: mounts the subscription OAuth
|
|
2
|
+
# provider routes and the /auth command as a profile layer
|
|
3
|
+
# (`dsh plugin --profile <name> add @deepseek-harness-tui/dsh-auth`).
|
|
4
|
+
#
|
|
5
|
+
# Entry-level inject — never a code-level one (see the plugin module's
|
|
6
|
+
# `inject` export): a stale patch must not deadlock a composition whose
|
|
7
|
+
# llm/commands services arrive later or are absent entirely.
|
|
8
|
+
- insert:
|
|
9
|
+
- id: dsh-auth
|
|
10
|
+
name: '@deepseek-harness-tui/dsh-auth'
|
|
11
|
+
inject: [llm, commands]
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://dsh.community/schemas/dsh-plugin-0.15.json",
|
|
3
|
+
"id": "com.dsh-tui.dsh-auth",
|
|
4
|
+
"name": "dsh-auth",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"manifestVersion": "0.15",
|
|
7
|
+
"description": "Subscription OAuth sign-in (ChatGPT/Codex, Claude Pro/Max, SuperGrok) as LLM provider routes for DeepSeek Harness. Registers llm adapter routes through the cordis llm registry; interactive login runs over the user-questions seam and degrades to a clear refusal when no interactive surface is present.",
|
|
8
|
+
"facets": {
|
|
9
|
+
"host": {
|
|
10
|
+
"entry": "lib/index.js",
|
|
11
|
+
"apiVersion": "v1alpha1"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"requires": {
|
|
15
|
+
"contracts": [
|
|
16
|
+
{
|
|
17
|
+
"apiVersion": "commands.dsh/v1alpha1",
|
|
18
|
+
"kind": "Command"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"apiVersion": "user-questions.dsh/v1alpha1",
|
|
22
|
+
"kind": "UserQuestions",
|
|
23
|
+
"optional": true,
|
|
24
|
+
"fallback": "login refuses with guidance instead of assuming a browser or GUI is present (TUI-RUN-001)"
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
"contributes": {
|
|
29
|
+
"commands": [
|
|
30
|
+
{
|
|
31
|
+
"id": "dsh.auth",
|
|
32
|
+
"title": "Sign in with a provider subscription (OAuth)"
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
"permissions": [
|
|
37
|
+
{
|
|
38
|
+
"name": "commands.invoke",
|
|
39
|
+
"scope": "dsh.auth",
|
|
40
|
+
"reason": "run /auth status|login|logout from any composed command surface"
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"license": "MIT"
|
|
44
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `/auth` command: a textual veneer over the {@link DshAuthApi} — status
|
|
3
|
+
* listing, login (optionally picking the provider interactively), logout.
|
|
4
|
+
*
|
|
5
|
+
* @module dsh-auth/command
|
|
6
|
+
*/
|
|
7
|
+
import type { CommandInvocation, CommandResult } from '@deepseek-ai/dsh-commands';
|
|
8
|
+
import type { DshAuthApi } from './service.js';
|
|
9
|
+
/**
|
|
10
|
+
* Build the `/auth` handler. Every failure returns a `CommandResult`, never a
|
|
11
|
+
* rejection the host would have to translate; unexpected throws still
|
|
12
|
+
* propagate for the host's own error surface.
|
|
13
|
+
*/
|
|
14
|
+
export declare function createAuthCommandHandler(api: DshAuthApi): (invocation: CommandInvocation) => Promise<CommandResult>;
|