@deepseek-harness-tui/dsh-tui 0.8.0 → 0.8.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 +32 -15
- package/cordis.patch.yml +21 -2
- package/cordis.yml +12 -1
- package/dsh-ecosystem-spec/protocols/profile-definitions.d.ts +13 -0
- package/dsh-ecosystem-spec/protocols/profile-definitions.js +59 -0
- package/dsh-ecosystem-spec/protocols/tui-channel-http.d.ts +15 -0
- package/dsh-ecosystem-spec/protocols/tui-channel-http.js +32 -0
- package/dsh-ecosystem-spec/protocols/tui-channel.d.ts +59 -0
- package/dsh-ecosystem-spec/protocols/tui-channel.js +166 -0
- package/dsh-ecosystem-spec/protocols/tui-contributions.d.ts +42 -0
- package/dsh-ecosystem-spec/protocols/tui-contributions.js +143 -0
- package/dsh-ecosystem-spec/registry/README.md +14 -0
- package/dsh-ecosystem-spec/registry/contracts/decision-events-v1alpha1.json +13 -0
- package/dsh-ecosystem-spec/registry/contracts/scene-v1alpha1.json +13 -0
- package/dsh-ecosystem-spec/registry/contracts/settings-section-v1alpha1.json +13 -0
- package/dsh-ecosystem-spec/registry/contracts/tui-channel-v1alpha1.json +30 -0
- package/dsh-ecosystem-spec/registry/contracts/workspace-provider-v1alpha1.json +6 -0
- package/dsh-ecosystem-spec/registry/host-descriptor.tui.example.json +56 -0
- package/dsh-ecosystem-spec/registry/permissions-0.1.json +13 -0
- package/dsh-ecosystem-spec/registry/registry-0.15.json +149 -0
- package/dsh-ecosystem-spec/schemas/conformance-claim.schema.json +15 -0
- package/dsh-ecosystem-spec/schemas/effect-ledger-record.schema.json +16 -0
- package/dsh-ecosystem-spec/schemas/host-descriptor.schema.json +26 -0
- package/lib/types/cc/figures.d.ts +4 -0
- package/lib/types/cc/figures.d.ts.map +1 -1
- package/lib/types/cc/figures.js +4 -0
- package/lib/types/command-trees.d.ts +2 -1
- package/lib/types/command-trees.d.ts.map +1 -1
- package/lib/types/command-trees.js +1 -1
- package/lib/types/commands.d.ts.map +1 -1
- package/lib/types/commands.js +2 -0
- package/lib/types/components/ExtensionDialog.d.ts +40 -0
- package/lib/types/components/ExtensionDialog.d.ts.map +1 -0
- package/lib/types/components/ExtensionDialog.js +210 -0
- package/lib/types/components/HelpMenu.js +1 -1
- package/lib/types/components/LoadedContextPanel.d.ts +5 -5
- package/lib/types/components/LoadedContextPanel.js +6 -6
- package/lib/types/components/LogoV2.d.ts.map +1 -1
- package/lib/types/components/LogoV2.js +16 -8
- package/lib/types/components/Markdown.d.ts +13 -1
- package/lib/types/components/Markdown.d.ts.map +1 -1
- package/lib/types/components/Markdown.js +15 -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 +111 -6
- package/lib/types/components/PromptInput.d.ts.map +1 -1
- package/lib/types/components/PromptInput.js +26 -12
- package/lib/types/components/RewindPicker.d.ts +13 -1
- package/lib/types/components/RewindPicker.d.ts.map +1 -1
- package/lib/types/components/RewindPicker.js +26 -2
- package/lib/types/components/StreamingMarkdown.d.ts +2 -8
- package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
- package/lib/types/components/StreamingMarkdown.js +51 -9
- package/lib/types/components/ToolUseLoader.d.ts +8 -3
- package/lib/types/components/ToolUseLoader.d.ts.map +1 -1
- package/lib/types/components/ToolUseLoader.js +43 -9
- package/lib/types/components/activityFrames.d.ts +1 -1
- package/lib/types/components/activityFrames.d.ts.map +1 -1
- package/lib/types/components/activityFrames.js +4 -1
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts +5 -1
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantThinkingMessage.js +26 -3
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantToolUseMessage.js +13 -2
- package/lib/types/dsh-adapter/channel.d.ts +61 -11
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +767 -120
- package/lib/types/dsh-adapter/childStderr.d.ts.map +1 -1
- package/lib/types/dsh-adapter/childStderr.js +10 -0
- package/lib/types/dsh-adapter/command-attribution.d.ts +51 -0
- package/lib/types/dsh-adapter/command-attribution.d.ts.map +1 -0
- package/lib/types/dsh-adapter/command-attribution.js +93 -0
- package/lib/types/dsh-adapter/command-errors.d.ts +42 -0
- package/lib/types/dsh-adapter/command-errors.d.ts.map +1 -0
- package/lib/types/dsh-adapter/command-errors.js +63 -0
- package/lib/types/dsh-adapter/command-trees.d.ts +7 -1
- package/lib/types/dsh-adapter/command-trees.d.ts.map +1 -1
- package/lib/types/dsh-adapter/command-trees.js +70 -20
- package/lib/types/dsh-adapter/component-identity.d.ts +33 -0
- package/lib/types/dsh-adapter/component-identity.d.ts.map +1 -0
- package/lib/types/dsh-adapter/component-identity.js +108 -0
- package/lib/types/dsh-adapter/contract.d.ts +1 -1
- package/lib/types/dsh-adapter/contract.js +2 -2
- package/lib/types/dsh-adapter/decision-guard.d.ts +84 -0
- package/lib/types/dsh-adapter/decision-guard.d.ts.map +1 -0
- package/lib/types/dsh-adapter/decision-guard.js +348 -0
- package/lib/types/dsh-adapter/dialogs.d.ts +145 -0
- package/lib/types/dsh-adapter/dialogs.d.ts.map +1 -0
- package/lib/types/dsh-adapter/dialogs.js +316 -0
- package/lib/types/dsh-adapter/effect-ledger.d.ts +91 -0
- package/lib/types/dsh-adapter/effect-ledger.d.ts.map +1 -0
- package/lib/types/dsh-adapter/effect-ledger.js +251 -0
- package/lib/types/dsh-adapter/extension-events.d.ts +193 -0
- package/lib/types/dsh-adapter/extension-events.d.ts.map +1 -0
- package/lib/types/dsh-adapter/extension-events.js +207 -0
- package/lib/types/dsh-adapter/extensions.d.ts +32 -0
- package/lib/types/dsh-adapter/extensions.d.ts.map +1 -0
- package/lib/types/dsh-adapter/extensions.js +42 -0
- package/lib/types/dsh-adapter/grants.d.ts +25 -0
- package/lib/types/dsh-adapter/grants.d.ts.map +1 -0
- package/lib/types/dsh-adapter/grants.js +213 -0
- package/lib/types/dsh-adapter/host-access.d.ts +37 -0
- package/lib/types/dsh-adapter/host-access.d.ts.map +1 -0
- package/lib/types/dsh-adapter/host-access.js +652 -0
- package/lib/types/dsh-adapter/host-descriptor.d.ts +24 -0
- package/lib/types/dsh-adapter/host-descriptor.d.ts.map +1 -0
- package/lib/types/dsh-adapter/host-descriptor.js +169 -0
- package/lib/types/dsh-adapter/index.d.ts +4 -0
- package/lib/types/dsh-adapter/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/index.js +1 -0
- package/lib/types/dsh-adapter/message-observer.d.ts +173 -0
- package/lib/types/dsh-adapter/message-observer.d.ts.map +1 -0
- package/lib/types/dsh-adapter/message-observer.js +553 -0
- package/lib/types/dsh-adapter/plugin-host.d.ts +136 -0
- package/lib/types/dsh-adapter/plugin-host.d.ts.map +1 -0
- package/lib/types/dsh-adapter/plugin-host.js +365 -0
- package/lib/types/dsh-adapter/plugin-storage.d.ts +108 -0
- package/lib/types/dsh-adapter/plugin-storage.d.ts.map +1 -0
- package/lib/types/dsh-adapter/plugin-storage.js +397 -0
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +124 -14
- package/lib/types/dsh-adapter/plugins-info.d.ts +43 -0
- package/lib/types/dsh-adapter/plugins-info.d.ts.map +1 -0
- package/lib/types/dsh-adapter/plugins-info.js +276 -0
- package/lib/types/dsh-adapter/promptDebug.d.ts +0 -6
- package/lib/types/dsh-adapter/promptDebug.d.ts.map +1 -1
- package/lib/types/dsh-adapter/promptDebug.js +13 -4
- package/lib/types/dsh-adapter/renderers.d.ts +57 -0
- package/lib/types/dsh-adapter/renderers.d.ts.map +1 -0
- package/lib/types/dsh-adapter/renderers.js +173 -0
- package/lib/types/dsh-adapter/sanitize.d.ts +36 -0
- package/lib/types/dsh-adapter/sanitize.d.ts.map +1 -0
- package/lib/types/dsh-adapter/sanitize.js +65 -0
- package/lib/types/dsh-adapter/scenes.d.ts +15 -5
- package/lib/types/dsh-adapter/scenes.d.ts.map +1 -1
- package/lib/types/dsh-adapter/scenes.js +149 -35
- package/lib/types/dsh-adapter/settings-sections.d.ts +7 -3
- package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -1
- package/lib/types/dsh-adapter/settings-sections.js +106 -26
- package/lib/types/dsh-adapter/shortcuts.d.ts +107 -0
- package/lib/types/dsh-adapter/shortcuts.d.ts.map +1 -0
- package/lib/types/dsh-adapter/shortcuts.js +340 -0
- package/lib/types/dsh-adapter/status.d.ts +74 -0
- package/lib/types/dsh-adapter/status.d.ts.map +1 -0
- package/lib/types/dsh-adapter/status.js +234 -0
- package/lib/types/dsh-adapter/workspaces.d.ts +16 -5
- package/lib/types/dsh-adapter/workspaces.d.ts.map +1 -1
- package/lib/types/dsh-adapter/workspaces.js +287 -170
- package/lib/types/extensions.d.ts +13 -0
- package/lib/types/extensions.d.ts.map +1 -0
- package/lib/types/extensions.js +21 -0
- package/lib/types/force-production-react.d.ts +1 -0
- package/lib/types/force-production-react.d.ts.map +1 -0
- package/lib/types/force-production-react.js +12 -0
- package/lib/types/i18n.d.ts +174 -20
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +56 -6
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +1 -0
- package/lib/types/ink/components/App.d.ts +2 -0
- package/lib/types/ink/components/App.d.ts.map +1 -1
- package/lib/types/ink/components/App.js +4 -0
- package/lib/types/ink/ink.d.ts +31 -3
- package/lib/types/ink/ink.d.ts.map +1 -1
- package/lib/types/ink/ink.js +90 -5
- package/lib/types/ink/log-update.d.ts.map +1 -1
- package/lib/types/ink/log-update.js +225 -56
- package/lib/types/ink/output.d.ts +35 -2
- package/lib/types/ink/output.d.ts.map +1 -1
- package/lib/types/ink/output.js +281 -14
- package/lib/types/ink/render-node-to-output.d.ts.map +1 -1
- package/lib/types/ink/render-node-to-output.js +14 -6
- package/lib/types/ink/screen.d.ts +39 -0
- package/lib/types/ink/screen.d.ts.map +1 -1
- package/lib/types/ink/screen.js +117 -0
- package/lib/types/ink/terminal.d.ts.map +1 -1
- package/lib/types/ink/terminal.js +26 -6
- package/lib/types/ink/wrapAnsi.d.ts +1 -1
- package/lib/types/ink/wrapAnsi.d.ts.map +1 -1
- package/lib/types/ink/wrapAnsi.js +29 -2
- package/lib/types/plugin-host.d.ts +15 -0
- package/lib/types/plugin-host.d.ts.map +1 -0
- package/lib/types/plugin-host.js +17 -0
- package/lib/types/plugin-spec/negotiate.d.ts +11 -0
- package/lib/types/plugin-spec/negotiate.d.ts.map +1 -0
- package/lib/types/plugin-spec/negotiate.js +97 -0
- package/lib/types/plugin-spec/permission-scope.d.ts +32 -0
- package/lib/types/plugin-spec/permission-scope.d.ts.map +1 -0
- package/lib/types/plugin-spec/permission-scope.js +90 -0
- package/lib/types/plugin-spec/registry.d.ts +23 -0
- package/lib/types/plugin-spec/registry.d.ts.map +1 -0
- package/lib/types/plugin-spec/registry.js +252 -0
- package/lib/types/plugin-spec/schema-check.d.ts +17 -0
- package/lib/types/plugin-spec/schema-check.d.ts.map +1 -0
- package/lib/types/plugin-spec/schema-check.js +165 -0
- package/lib/types/plugin-spec/tui-extension.d.ts +16 -0
- package/lib/types/plugin-spec/tui-extension.d.ts.map +1 -0
- package/lib/types/plugin-spec/tui-extension.js +79 -0
- package/lib/types/plugin-spec/types.d.ts +114 -0
- package/lib/types/plugin-spec/types.d.ts.map +1 -0
- package/lib/types/plugin-spec/types.js +10 -0
- package/lib/types/plugin-spec/validate.d.ts +21 -0
- package/lib/types/plugin-spec/validate.d.ts.map +1 -0
- package/lib/types/plugin-spec/validate.js +138 -0
- package/lib/types/scenes.d.ts +2 -1
- package/lib/types/scenes.d.ts.map +1 -1
- package/lib/types/scenes.js +1 -1
- package/lib/types/screens/Chat.d.ts +14 -1
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +173 -49
- package/lib/types/screens/SessionBrowser.d.ts.map +1 -1
- package/lib/types/screens/SessionBrowser.js +10 -3
- package/lib/types/sessions/view.d.ts +3 -2
- package/lib/types/sessions/view.d.ts.map +1 -1
- package/lib/types/sessions/view.js +18 -0
- package/lib/types/settings-sections.d.ts +2 -1
- package/lib/types/settings-sections.d.ts.map +1 -1
- package/lib/types/settings-sections.js +1 -1
- package/lib/types/theme.d.ts +5 -0
- package/lib/types/theme.d.ts.map +1 -1
- package/lib/types/theme.js +15 -0
- package/lib/types/update.d.ts +20 -0
- package/lib/types/update.d.ts.map +1 -1
- package/lib/types/update.js +54 -7
- package/lib/types/utils/execFileNoThrow.d.ts.map +1 -1
- package/lib/types/utils/execFileNoThrow.js +3 -0
- package/lib/types/utils/loaded-context.d.ts +8 -3
- package/lib/types/utils/loaded-context.d.ts.map +1 -1
- package/lib/types/utils/loaded-context.js +39 -3
- package/lib/types/utils/modifiers.d.ts.map +1 -1
- package/lib/types/utils/modifiers.js +3 -2
- package/lib/types/working-activity.d.ts +12 -0
- package/lib/types/working-activity.d.ts.map +1 -1
- package/lib/types/working-activity.js +13 -0
- package/lib/types/workspaces.d.ts +2 -1
- package/lib/types/workspaces.d.ts.map +1 -1
- package/lib/types/workspaces.js +1 -1
- package/node_modules/@dsh-std/command/CHANGELOG.md +8 -0
- package/node_modules/@dsh-std/command/LICENSE +21 -0
- package/node_modules/@dsh-std/command/README.md +26 -0
- package/node_modules/@dsh-std/command/README.zh.md +28 -0
- package/node_modules/@dsh-std/command/lib/index.d.ts +144 -0
- package/node_modules/@dsh-std/command/lib/index.d.ts.map +1 -0
- package/node_modules/@dsh-std/command/lib/index.js +252 -0
- package/node_modules/@dsh-std/command/lib/index.js.map +1 -0
- package/node_modules/@dsh-std/command/package.json +22 -0
- package/node_modules/@dsh-std/connection/CHANGELOG.md +8 -0
- package/node_modules/@dsh-std/connection/LICENSE +21 -0
- package/node_modules/@dsh-std/connection/README.md +42 -0
- package/node_modules/@dsh-std/connection/README.zh.md +42 -0
- package/node_modules/@dsh-std/connection/lib/connection-CdGcSQnu.d.ts +125 -0
- package/node_modules/@dsh-std/connection/lib/connection-CdGcSQnu.d.ts.map +1 -0
- package/node_modules/@dsh-std/connection/lib/index.d.ts +89 -0
- package/node_modules/@dsh-std/connection/lib/index.d.ts.map +1 -0
- package/node_modules/@dsh-std/connection/lib/index.js +158 -0
- package/node_modules/@dsh-std/connection/lib/index.js.map +1 -0
- package/node_modules/@dsh-std/connection/lib/memory.d.ts +24 -0
- package/node_modules/@dsh-std/connection/lib/memory.d.ts.map +1 -0
- package/node_modules/@dsh-std/connection/lib/memory.js +258 -0
- package/node_modules/@dsh-std/connection/lib/memory.js.map +1 -0
- package/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js +226 -0
- package/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -0
- package/node_modules/@dsh-std/connection/package.json +20 -0
- package/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/node_modules/@dsh-std/core/LICENSE +21 -0
- package/node_modules/@dsh-std/core/README.md +13 -0
- package/node_modules/@dsh-std/core/README.zh.md +13 -0
- package/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
- package/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
- package/node_modules/@dsh-std/core/lib/index.js +424 -0
- package/node_modules/@dsh-std/core/lib/index.js.map +1 -0
- package/node_modules/@dsh-std/core/package.json +21 -0
- package/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -0
- package/node_modules/@dsh-std/manifest/LICENSE +21 -0
- package/node_modules/@dsh-std/manifest/README.md +5 -0
- package/node_modules/@dsh-std/manifest/README.zh.md +5 -0
- package/node_modules/@dsh-std/manifest/lib/index.d.ts +182 -0
- package/node_modules/@dsh-std/manifest/lib/index.d.ts.map +1 -0
- package/node_modules/@dsh-std/manifest/lib/index.js +625 -0
- package/node_modules/@dsh-std/manifest/lib/index.js.map +1 -0
- package/node_modules/@dsh-std/manifest/package.json +20 -0
- package/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -0
- package/node_modules/@dsh-std/messages/CHANGELOG.md +8 -0
- package/node_modules/@dsh-std/messages/LICENSE +21 -0
- package/node_modules/@dsh-std/messages/README.md +5 -0
- package/node_modules/@dsh-std/messages/README.zh.md +7 -0
- package/node_modules/@dsh-std/messages/lib/index.d.ts +50 -0
- package/node_modules/@dsh-std/messages/lib/index.d.ts.map +1 -0
- package/node_modules/@dsh-std/messages/lib/index.js +151 -0
- package/node_modules/@dsh-std/messages/lib/index.js.map +1 -0
- package/node_modules/@dsh-std/messages/package.json +20 -0
- package/node_modules/@dsh-std/messages/schema/message-observer-envelope-0.15.schema.json +54 -0
- package/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -0
- package/node_modules/@dsh-std/presentation/LICENSE +21 -0
- package/node_modules/@dsh-std/presentation/README.md +27 -0
- package/node_modules/@dsh-std/presentation/README.zh.md +29 -0
- package/node_modules/@dsh-std/presentation/lib/callback.d.ts +2 -0
- package/node_modules/@dsh-std/presentation/lib/callback.js +179 -0
- package/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -0
- package/node_modules/@dsh-std/presentation/lib/index.d.ts +262 -0
- package/node_modules/@dsh-std/presentation/lib/index.d.ts.map +1 -0
- package/node_modules/@dsh-std/presentation/lib/index.js +550 -0
- package/node_modules/@dsh-std/presentation/lib/index.js.map +1 -0
- package/node_modules/@dsh-std/presentation/lib/interaction.d.ts +2 -0
- package/node_modules/@dsh-std/presentation/lib/interaction.js +2 -0
- package/node_modules/@dsh-std/presentation/lib/operations.d.ts +2 -0
- package/node_modules/@dsh-std/presentation/lib/operations.js +2 -0
- package/node_modules/@dsh-std/presentation/package.json +25 -0
- package/node_modules/@dsh-std/storage/CHANGELOG.md +8 -0
- package/node_modules/@dsh-std/storage/LICENSE +21 -0
- package/node_modules/@dsh-std/storage/README.md +5 -0
- package/node_modules/@dsh-std/storage/README.zh.md +7 -0
- package/node_modules/@dsh-std/storage/lib/index.d.ts +48 -0
- package/node_modules/@dsh-std/storage/lib/index.d.ts.map +1 -0
- package/node_modules/@dsh-std/storage/lib/index.js +104 -0
- package/node_modules/@dsh-std/storage/lib/index.js.map +1 -0
- package/node_modules/@dsh-std/storage/package.json +20 -0
- package/node_modules/@dsh-std/storage/schema/local-storage-0.15.schema.json +56 -0
- package/package.json +110 -70
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/LICENSE +21 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.md +42 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/README.zh.md +42 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/connection-CdGcSQnu.d.ts +125 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/connection-CdGcSQnu.d.ts.map +1 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.d.ts +89 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.d.ts.map +1 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.js +158 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/index.js.map +1 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.d.ts +24 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.d.ts.map +1 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js +258 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js.map +1 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js +226 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/package.json +20 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/LICENSE +21 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.md +13 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/README.zh.md +13 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.js +424 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/lib/index.js.map +1 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/package.json +21 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/LICENSE +21 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.md +5 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/README.zh.md +5 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.d.ts +182 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.d.ts.map +1 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.js +625 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/lib/index.js.map +1 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/package.json +20 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/schema/dsh-plugin-0.15.schema.json +144 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/LICENSE +21 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.md +27 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.zh.md +29 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.d.ts +2 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.js +179 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.d.ts +262 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.d.ts.map +1 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js +550 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js.map +1 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/interaction.d.ts +2 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/interaction.js +2 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/operations.d.ts +2 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/operations.js +2 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/package.json +25 -0
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/LICENSE +21 -0
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.md +13 -0
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/README.zh.md +13 -0
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.js +424 -0
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/lib/index.js.map +1 -0
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/package.json +21 -0
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/LICENSE +21 -0
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.md +13 -0
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/README.zh.md +13 -0
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.js +424 -0
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/lib/index.js.map +1 -0
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/package.json +21 -0
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/LICENSE +21 -0
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.md +13 -0
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/README.zh.md +13 -0
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.js +424 -0
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/lib/index.js.map +1 -0
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/package.json +21 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/LICENSE +21 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.md +42 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/README.zh.md +42 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/connection-CdGcSQnu.d.ts +125 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/connection-CdGcSQnu.d.ts.map +1 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.d.ts +89 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.d.ts.map +1 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.js +158 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/index.js.map +1 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.d.ts +24 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.d.ts.map +1 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js +258 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js.map +1 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js +226 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/resolve-3X6ausgz.js.map +1 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/package.json +20 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/LICENSE +21 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.md +13 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/README.zh.md +13 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.js +424 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/lib/index.js.map +1 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/package.json +21 -0
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/LICENSE +21 -0
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.md +13 -0
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/README.zh.md +13 -0
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.d.ts +112 -0
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.d.ts.map +1 -0
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.js +424 -0
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/lib/index.js.map +1 -0
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/package.json +21 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Semantic validation layered on the official manifest parser/projection. */
|
|
2
|
+
import { createAdmissionCatalog } from './tui-extension.js';
|
|
3
|
+
import type { ContractCoordinate, ContractRegistry, HostDescriptor, PermissionRegistry, PluginManifest, RegistryEntry, SubscriptionRef } from './types.js';
|
|
4
|
+
export interface ContractIndex {
|
|
5
|
+
registry: ContractRegistry;
|
|
6
|
+
permissions: PermissionRegistry;
|
|
7
|
+
facetApiVersions: string[];
|
|
8
|
+
protocols: ReturnType<typeof createAdmissionCatalog>['protocols'];
|
|
9
|
+
manifests: ReturnType<typeof createAdmissionCatalog>['manifests'];
|
|
10
|
+
lookupContract(coordinate: ContractCoordinate): RegistryEntry | undefined;
|
|
11
|
+
resolveContractRef(ref: ContractCoordinate): {
|
|
12
|
+
entry: RegistryEntry | null;
|
|
13
|
+
unregisteredVersion: boolean;
|
|
14
|
+
};
|
|
15
|
+
resolveSubscription(sub: SubscriptionRef): RegistryEntry;
|
|
16
|
+
}
|
|
17
|
+
export declare const groupOf: (apiVersion: string) => string;
|
|
18
|
+
export declare function createContractIndex(registry: ContractRegistry, permissions: PermissionRegistry): ContractIndex;
|
|
19
|
+
export declare function validatePlugin(index: ContractIndex, manifest: PluginManifest): void;
|
|
20
|
+
export declare function validateHost(index: ContractIndex, host: HostDescriptor): void;
|
|
21
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/plugin-spec/validate.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAG9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAG3D,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,eAAe,EAChB,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,WAAW,EAAE,kBAAkB,CAAA;IAC/B,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,SAAS,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,WAAW,CAAC,CAAA;IACjE,SAAS,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,WAAW,CAAC,CAAA;IACjE,cAAc,CAAC,UAAU,EAAE,kBAAkB,GAAG,aAAa,GAAG,SAAS,CAAA;IACzE,kBAAkB,CAAC,GAAG,EAAE,kBAAkB,GAAG;QAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;QAAC,mBAAmB,EAAE,OAAO,CAAA;KAAE,CAAA;IAC1G,mBAAmB,CAAC,GAAG,EAAE,eAAe,GAAG,aAAa,CAAA;CACzD;AAGD,eAAO,MAAM,OAAO,GAAI,YAAY,MAAM,KAAG,MAAwC,CAAA;AAErF,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAAE,kBAAkB,GAAG,aAAa,CAsC9G;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,CA4DnF;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CA4B7E"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/** Semantic validation layered on the official manifest parser/projection. */
|
|
2
|
+
import { projectManifest } from '@dsh-std/manifest';
|
|
3
|
+
import { createAdmissionCatalog } from './tui-extension.js';
|
|
4
|
+
import { registryEntries } from './registry.js';
|
|
5
|
+
import { INTERCEPT_PERMISSIONS, normalizePermissionScope } from './permission-scope.js';
|
|
6
|
+
const coordinateKey = (coordinate) => `${coordinate.apiVersion}#${coordinate.kind}`;
|
|
7
|
+
export const groupOf = (apiVersion) => apiVersion.split('/')[0] ?? '';
|
|
8
|
+
export function createContractIndex(registry, permissions) {
|
|
9
|
+
const entries = registryEntries(registry);
|
|
10
|
+
const byCoordinate = new Map(entries.map(entry => [coordinateKey(entry.coordinates), entry]));
|
|
11
|
+
const byName = new Map(entries.map(entry => [entry.name, entry]));
|
|
12
|
+
const { protocols, manifests } = createAdmissionCatalog();
|
|
13
|
+
const resolveContractRef = (ref) => {
|
|
14
|
+
const exact = byCoordinate.get(coordinateKey(ref));
|
|
15
|
+
if (exact !== undefined)
|
|
16
|
+
return { entry: exact, unregisteredVersion: false };
|
|
17
|
+
const sameGroup = entries.filter(entry => groupOf(entry.coordinates.apiVersion) === groupOf(ref.apiVersion));
|
|
18
|
+
if (sameGroup.length === 0)
|
|
19
|
+
throw new Error(`unknown protocol group: ${groupOf(ref.apiVersion)}`);
|
|
20
|
+
if (!sameGroup.some(entry => entry.coordinates.kind === ref.kind)) {
|
|
21
|
+
throw new Error(`unknown protocol kind: ${coordinateKey(ref)}`);
|
|
22
|
+
}
|
|
23
|
+
return { entry: null, unregisteredVersion: true };
|
|
24
|
+
};
|
|
25
|
+
const resolveSubscription = (subscription) => {
|
|
26
|
+
const entry = typeof subscription === 'string'
|
|
27
|
+
? byName.get(subscription)
|
|
28
|
+
: byCoordinate.get(coordinateKey(subscription));
|
|
29
|
+
if (entry === undefined) {
|
|
30
|
+
throw new Error(`unknown subscription: ${typeof subscription === 'string' ? subscription : coordinateKey(subscription)}`);
|
|
31
|
+
}
|
|
32
|
+
if (entry.kind !== 'event')
|
|
33
|
+
throw new Error(`subscription must reference an event: ${entry.name}`);
|
|
34
|
+
return entry;
|
|
35
|
+
};
|
|
36
|
+
return {
|
|
37
|
+
registry,
|
|
38
|
+
permissions,
|
|
39
|
+
facetApiVersions: [...registry.facetApiVersions],
|
|
40
|
+
protocols,
|
|
41
|
+
manifests,
|
|
42
|
+
lookupContract: coordinate => byCoordinate.get(coordinateKey(coordinate)),
|
|
43
|
+
resolveContractRef,
|
|
44
|
+
resolveSubscription,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export function validatePlugin(index, manifest) {
|
|
48
|
+
if (!index.facetApiVersions.includes(manifest.facets.host.apiVersion)) {
|
|
49
|
+
throw new Error(`facet apiVersion is not admitted: ${manifest.facets.host.apiVersion}`);
|
|
50
|
+
}
|
|
51
|
+
for (const requirement of manifest.requires.contracts) {
|
|
52
|
+
index.resolveContractRef(requirement);
|
|
53
|
+
if (requirement.optional === true && !requirement.fallback) {
|
|
54
|
+
throw new Error(`optional protocol requires a TUI fallback: ${coordinateKey(requirement)}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
for (const subscription of manifest.subscriptions)
|
|
58
|
+
index.resolveSubscription(subscription);
|
|
59
|
+
const knownPermissions = new Set(index.permissions.permissions.map(permission => permission.name));
|
|
60
|
+
const commandIds = new Set(manifest.contributes.commands.map(command => command.id));
|
|
61
|
+
const requiresDecisionEvents = manifest.requires.contracts.some(requirement => requirement.kind === 'DecisionEvents'
|
|
62
|
+
&& groupOf(requirement.apiVersion) === groupOf('tui.dsh/v1alpha1'));
|
|
63
|
+
const capabilityForPermission = {
|
|
64
|
+
'commands.invoke': { apiVersion: 'commands.dsh/v1alpha1', kind: 'Command' },
|
|
65
|
+
'storage.local.read': { apiVersion: 'storage.dsh/v1alpha1', kind: 'LocalStorage' },
|
|
66
|
+
'storage.local.write': { apiVersion: 'storage.dsh/v1alpha1', kind: 'LocalStorage' },
|
|
67
|
+
'messages.observe.read': { apiVersion: 'messages.dsh/v1alpha1', kind: 'MessageObserver' },
|
|
68
|
+
'session.input.intercept': { apiVersion: 'tui.dsh/v1alpha1', kind: 'DecisionEvents' },
|
|
69
|
+
'session.rewind.intercept': { apiVersion: 'tui.dsh/v1alpha1', kind: 'DecisionEvents' },
|
|
70
|
+
'session.switch.intercept': { apiVersion: 'tui.dsh/v1alpha1', kind: 'DecisionEvents' },
|
|
71
|
+
'session.compact.intercept': { apiVersion: 'tui.dsh/v1alpha1', kind: 'DecisionEvents' },
|
|
72
|
+
};
|
|
73
|
+
for (const permission of manifest.permissions) {
|
|
74
|
+
if (!knownPermissions.has(permission.name)) {
|
|
75
|
+
throw new Error(`permission is not admitted by the TUI profile: ${permission.name}`);
|
|
76
|
+
}
|
|
77
|
+
if (normalizePermissionScope(permission.name, permission.scope, manifest.id) === undefined) {
|
|
78
|
+
throw new Error(`permission scope cannot be enforced: ${permission.name}@${permission.scope}`);
|
|
79
|
+
}
|
|
80
|
+
if (permission.name === 'commands.invoke' && !commandIds.has(permission.scope)) {
|
|
81
|
+
throw new Error(`commands.invoke scope is not a declared command: ${permission.scope}`);
|
|
82
|
+
}
|
|
83
|
+
if (INTERCEPT_PERMISSIONS.has(permission.name) && !requiresDecisionEvents) {
|
|
84
|
+
throw new Error(`${permission.name} requires tui.dsh/v1alpha1#DecisionEvents`);
|
|
85
|
+
}
|
|
86
|
+
const capability = capabilityForPermission[permission.name];
|
|
87
|
+
// An otherwise valid contract reference may use an unregistered version
|
|
88
|
+
// from the same protocol group. Keep that manifest structurally valid so
|
|
89
|
+
// negotiation can return UNKNOWN_PROTOCOL_VERSION rather than letting the
|
|
90
|
+
// permission/capability cross-check mask the version-drift decision.
|
|
91
|
+
if (capability !== undefined && !manifest.requires.contracts.some(requirement => requirement.kind === capability.kind && groupOf(requirement.apiVersion) === groupOf(capability.apiVersion))) {
|
|
92
|
+
throw new Error(`${permission.name} requires ${capability.apiVersion}#${capability.kind}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
for (const commandId of commandIds) {
|
|
96
|
+
if (!manifest.permissions.some(permission => permission.name === 'commands.invoke' && permission.scope === commandId)) {
|
|
97
|
+
throw new Error(`declared command is missing commands.invoke permission scope: ${commandId}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const projected = projectManifest(manifest);
|
|
101
|
+
const report = index.manifests.validate(projected, index.protocols);
|
|
102
|
+
const errors = report.issues.filter(issue => issue.severity === 'error');
|
|
103
|
+
if (errors.length > 0)
|
|
104
|
+
throw new Error(errors.map(issue => issue.message).join('; '));
|
|
105
|
+
}
|
|
106
|
+
export function validateHost(index, host) {
|
|
107
|
+
const seen = new Set();
|
|
108
|
+
const knownPermissions = new Set(index.permissions.permissions.map(permission => permission.name));
|
|
109
|
+
for (const contract of host.contracts) {
|
|
110
|
+
const key = coordinateKey(contract);
|
|
111
|
+
if (seen.has(key))
|
|
112
|
+
throw new Error(`host declares duplicate protocol: ${key}`);
|
|
113
|
+
seen.add(key);
|
|
114
|
+
const entry = index.lookupContract(contract);
|
|
115
|
+
const definition = index.protocols.resolve(contract);
|
|
116
|
+
if (entry === undefined || definition === undefined)
|
|
117
|
+
throw new Error(`host declares an unknown protocol: ${key}`);
|
|
118
|
+
definition.validateSupport(Object.hasOwn(contract, 'spec') ? contract.spec : undefined);
|
|
119
|
+
if ('package' in entry) {
|
|
120
|
+
if (contract.definition.source !== 'dsh-std' || contract.definition.package !== entry.package) {
|
|
121
|
+
throw new Error(`host dsh-std definition source mismatch: ${key}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else if (contract.definition.source !== 'tui-profile' || contract.definition.profileHash !== entry.profileHash) {
|
|
125
|
+
throw new Error(`host TUI profile definition hash mismatch: ${key}`);
|
|
126
|
+
}
|
|
127
|
+
const expectedPermissions = [...entry.permissions].sort();
|
|
128
|
+
const actualPermissions = [...contract.permissions].sort();
|
|
129
|
+
if (expectedPermissions.length !== actualPermissions.length
|
|
130
|
+
|| expectedPermissions.some((permission, index) => permission !== actualPermissions[index])) {
|
|
131
|
+
throw new Error(`host permission advertisement mismatch: ${key}`);
|
|
132
|
+
}
|
|
133
|
+
for (const permission of contract.permissions) {
|
|
134
|
+
if (!knownPermissions.has(permission))
|
|
135
|
+
throw new Error(`host declares unknown permission: ${permission}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
package/lib/types/scenes.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { name, TuiSceneRuntime } from './dsh-adapter/scenes.js';
|
|
2
|
+
export type { TuiSceneProps, TuiSceneDescriptor } from './dsh-adapter/scenes.js';
|
|
2
3
|
export { default } from './dsh-adapter/scenes.js';
|
|
3
4
|
//# sourceMappingURL=scenes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scenes.d.ts","sourceRoot":"","sources":["../../src/scenes.ts"],"names":[],"mappings":"AAEA,
|
|
1
|
+
{"version":3,"file":"scenes.d.ts","sourceRoot":"","sources":["../../src/scenes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAC/D,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAChF,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA"}
|
package/lib/types/scenes.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// Re-export shim: the Cordis-backed implementation lives behind the adapter
|
|
2
2
|
// boundary so UI consumers never import official @deepseek-ai/* packages.
|
|
3
|
-
export
|
|
3
|
+
export { name, TuiSceneRuntime } from './dsh-adapter/scenes.js';
|
|
4
4
|
export { default } from './dsh-adapter/scenes.js';
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { type Channel } from '../dsh-adapter/channel.js';
|
|
3
3
|
import type { QuestionStore } from '../dsh-adapter/questions.js';
|
|
4
|
+
import { TuiDialogStore } from '../dsh-adapter/dialogs.js';
|
|
5
|
+
import { TuiStatusStore } from '../dsh-adapter/status.js';
|
|
6
|
+
import type { TuiShortcutHost } from '../dsh-adapter/shortcuts.js';
|
|
4
7
|
import { ApprovalStore } from '../dsh-adapter/approvals.js';
|
|
5
|
-
export declare function Chat({ channel, questionStore, approvalStore, onExit, onUpdate, fullscreen, trajectorySeen: trajectorySeenProp, }: {
|
|
8
|
+
export declare function Chat({ channel, questionStore, approvalStore, extensionDialogs, extensionStatus, extensionShortcuts, onExit, onUpdate, fullscreen, trajectorySeen: trajectorySeenProp, }: {
|
|
6
9
|
channel: Channel;
|
|
7
10
|
questionStore: QuestionStore;
|
|
8
11
|
/**
|
|
@@ -11,6 +14,16 @@ export declare function Chat({ channel, questionStore, approvalStore, onExit, on
|
|
|
11
14
|
* simply never see an approval panel — the question panel keeps its seat.
|
|
12
15
|
*/
|
|
13
16
|
approvalStore?: ApprovalStore;
|
|
17
|
+
/**
|
|
18
|
+
* The managed plugin dialog queue (tuiDialogs service's store). Optional
|
|
19
|
+
* for the same hosts as approvalStore; absent, plugin dialog requests
|
|
20
|
+
* park unanswered (their `timeoutMs` is the plugin's guard).
|
|
21
|
+
*/
|
|
22
|
+
extensionDialogs?: TuiDialogStore;
|
|
23
|
+
/** Plugin status-line contributions (tuiStatus service's store). */
|
|
24
|
+
extensionStatus?: TuiStatusStore;
|
|
25
|
+
/** Host-only keyboard shortcut dispatch path. */
|
|
26
|
+
extensionShortcuts?: TuiShortcutHost;
|
|
14
27
|
onExit: () => void;
|
|
15
28
|
/** Update the installed package and restart the current TUI process. */
|
|
16
29
|
onUpdate?: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../../src/screens/Chat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AASzB,OAAO,EAAqB,KAAK,OAAO,EAAsE,MAAM,2BAA2B,CAAA;AAC/I,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../../src/screens/Chat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AASzB,OAAO,EAAqB,KAAK,OAAO,EAAsE,MAAM,2BAA2B,CAAA;AAC/I,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAGlE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAwI3D,wBAAgB,IAAI,CAAC,EACnB,OAAO,EACP,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,MAAM,EACN,QAAQ,EACR,UAAkB,EAClB,cAAc,EAAE,kBAAkB,GACnC,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,aAAa,EAAE,aAAa,CAAA;IAC5B;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,cAAc,CAAA;IACjC,oEAAoE;IACpE,eAAe,CAAC,EAAE,cAAc,CAAA;IAChC,iDAAiD;IACjD,kBAAkB,CAAC,EAAE,eAAe,CAAA;IACpC,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB,qBAwlEA"}
|
|
@@ -8,10 +8,13 @@ import { isMod, isPlainReturnInput, modLabel } from '../utils/modifiers.js';
|
|
|
8
8
|
import { formatTokens } from '../cc/format.js';
|
|
9
9
|
import { homeDir } from '../utils/paths.js';
|
|
10
10
|
import { sessionCwdMatches } from '../dsh-adapter/channel.js';
|
|
11
|
+
import { TuiDialogStore } from '../dsh-adapter/dialogs.js';
|
|
12
|
+
import { TuiStatusStore } from '../dsh-adapter/status.js';
|
|
11
13
|
import { runProviderWizard } from '../dsh-adapter/providerWizard.js';
|
|
12
14
|
import { ApprovalStore } from '../dsh-adapter/approvals.js';
|
|
13
15
|
import { AskUserQuestionPanel } from '../components/questions/AskUserQuestionPanel.js';
|
|
14
16
|
import { ApprovalPanel } from '../components/approvals/ApprovalPanel.js';
|
|
17
|
+
import { ExtensionDialog } from '../components/ExtensionDialog.js';
|
|
15
18
|
import { useSearchHighlight } from '../ink/hooks/use-search-highlight.js';
|
|
16
19
|
import { useTerminalTitle } from '../ink/hooks/use-terminal-title.js';
|
|
17
20
|
import { useTerminalFocus } from '../ink/hooks/use-terminal-focus.js';
|
|
@@ -53,6 +56,7 @@ import { readTrajectorySeen, writeTrajectorySeen } from '../trajectoryPrefs.js';
|
|
|
53
56
|
import { LoadingState } from '../components/design-system/LoadingState.js';
|
|
54
57
|
import { Pane } from '../components/design-system/Pane.js';
|
|
55
58
|
import { loadHistory } from '../history.js';
|
|
59
|
+
import { formatLoadedContextReport } from '../utils/loaded-context.js';
|
|
56
60
|
/** Shared empty snapshot for hosts whose channel has no event log. */
|
|
57
61
|
const NO_EVENTS = [];
|
|
58
62
|
/** Row kinds the message-selection cursor can land on. */
|
|
@@ -121,7 +125,15 @@ function searchableText(row) {
|
|
|
121
125
|
* snapshot stays null and the approval panel never mounts.
|
|
122
126
|
*/
|
|
123
127
|
let fallbackApprovalStore;
|
|
124
|
-
|
|
128
|
+
/**
|
|
129
|
+
* Shared inert extension stores for hosts that render Chat without the
|
|
130
|
+
* dsh-tui-extensions row (headless verify scripts, bare embeds). Never
|
|
131
|
+
* written, so the dialog panel and the plugin status line never mount and
|
|
132
|
+
* no shortcut ever matches.
|
|
133
|
+
*/
|
|
134
|
+
let fallbackDialogStore;
|
|
135
|
+
let fallbackStatusStore;
|
|
136
|
+
export function Chat({ channel, questionStore, approvalStore, extensionDialogs, extensionStatus, extensionShortcuts, onExit, onUpdate, fullscreen = false, trajectorySeen: trajectorySeenProp, }) {
|
|
125
137
|
// Re-render whenever the channel mutates; rows/status are read fresh below.
|
|
126
138
|
React.useSyncExternalStore(channel.subscribe, () => channel.version);
|
|
127
139
|
// Re-render on language switches so the whole UI hot-swaps its strings.
|
|
@@ -135,6 +147,27 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
|
|
|
135
147
|
// approvalStore share one inert instance that never holds an ask.
|
|
136
148
|
const approvals = approvalStore ?? (fallbackApprovalStore ??= new ApprovalStore());
|
|
137
149
|
const approvalSnapshot = React.useSyncExternalStore(listener => approvals.subscribe(listener), () => approvals.getSnapshot());
|
|
150
|
+
// The pending managed plugin dialog (tuiDialogs seam): a plugin's
|
|
151
|
+
// select/confirm/input request parks here until the panel settles it.
|
|
152
|
+
// Priority sits right below the approval panel (a gated tool outranks a
|
|
153
|
+
// plugin's question) and above the questionnaire. Hosts without the
|
|
154
|
+
// extensions row share one inert store that never holds a dialog.
|
|
155
|
+
const dialogs = extensionDialogs ?? (fallbackDialogStore ??= new TuiDialogStore());
|
|
156
|
+
const dialogSnapshot = React.useSyncExternalStore(listener => dialogs.subscribe(listener), () => dialogs.getSnapshot());
|
|
157
|
+
// Plugin status-line contributions (tuiStatus seam): keyed texts joined
|
|
158
|
+
// into one line above the prompt.
|
|
159
|
+
const statusContributions = extensionStatus ?? (fallbackStatusStore ??= new TuiStatusStore());
|
|
160
|
+
const statusEntries = React.useSyncExternalStore(listener => statusContributions.subscribe(listener), () => statusContributions.getSnapshot());
|
|
161
|
+
// Shortcut handler failures surface as toasts (the registry also logs
|
|
162
|
+
// them); the hook is re-pointed on every mount so a stale closure never
|
|
163
|
+
// outlives its channel.
|
|
164
|
+
React.useEffect(() => {
|
|
165
|
+
if (extensionShortcuts === undefined)
|
|
166
|
+
return;
|
|
167
|
+
return extensionShortcuts.setErrorHandler(combo => {
|
|
168
|
+
channel.notify(t('ext-shortcut-failed', { combo }), { color: 'error', timeoutMs: 4000 });
|
|
169
|
+
});
|
|
170
|
+
}, [extensionShortcuts, channel]);
|
|
138
171
|
// When a questionnaire batch completes, fold a Q&A summary into the
|
|
139
172
|
// transcript (the tool card itself is hidden from the message list).
|
|
140
173
|
const questionOpenRef = React.useRef(questionSnapshot !== null);
|
|
@@ -209,6 +242,17 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
|
|
|
209
242
|
const [rewindOpen, setRewindOpen] = React.useState(false);
|
|
210
243
|
const [rewindIndex, setRewindIndex] = React.useState(0);
|
|
211
244
|
const [rewindConfirm, setRewindConfirm] = React.useState(null);
|
|
245
|
+
/** Plugin rewind modes (tui/rewind-prompt seam): extra choices offered in
|
|
246
|
+
* the confirm pane; null = the plain conversation-only confirm. */
|
|
247
|
+
const [rewindModes, setRewindModes] = React.useState(null);
|
|
248
|
+
const [rewindModeIndex, setRewindModeIndex] = React.useState(0);
|
|
249
|
+
/** True while the tui/rewind-prompt decision is in flight (a plugin may be
|
|
250
|
+
* showing its own dialog); keys except Esc are swallowed meanwhile. */
|
|
251
|
+
const [rewindBusy, setRewindBusy] = React.useState(false);
|
|
252
|
+
/** Monotonic token: only the latest rewind decision may land (a slow
|
|
253
|
+
* plugin answering after the user moved on must not open a confirm for
|
|
254
|
+
* a row they are no longer looking at). */
|
|
255
|
+
const rewindRequestRef = React.useRef(0);
|
|
212
256
|
/** /btw side-question overlay (CC): pure UI state — the answer never
|
|
213
257
|
* enters the transcript or the session log. */
|
|
214
258
|
const [btw, setBtw] = React.useState(null);
|
|
@@ -230,15 +274,9 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
|
|
|
230
274
|
/**
|
|
231
275
|
* Close the scene.
|
|
232
276
|
*
|
|
233
|
-
* Leaving the alternate screen makes the terminal restore the main buffer
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
* round trip — the same, already-accepted cost as the Ctrl+X external-editor
|
|
237
|
-
* handoff, and bounded per OPEN rather than per keystroke. Making it zero
|
|
238
|
-
* needs the render core to save and restore the pre-alt front frame, which
|
|
239
|
-
* is a separate change to `setAltScreenActive` and deliberately not made
|
|
240
|
-
* here. `verify-trace-scene` pins the property that matters meanwhile:
|
|
241
|
-
* navigating inside the scene adds nothing at all.
|
|
277
|
+
* Leaving the alternate screen makes the terminal restore the main buffer;
|
|
278
|
+
* Ink restores the matching saved frame and diffs any conversation changes
|
|
279
|
+
* that happened while the scene was open.
|
|
242
280
|
*/
|
|
243
281
|
const closeScene = React.useCallback(() => {
|
|
244
282
|
setSceneOpen(false);
|
|
@@ -253,16 +291,10 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
|
|
|
253
291
|
});
|
|
254
292
|
setSceneOpen(true);
|
|
255
293
|
}, []);
|
|
256
|
-
/**
|
|
257
|
-
const [loadedContextOpen, setLoadedContextOpen] = React.useState(false);
|
|
258
|
-
/**
|
|
259
|
-
* Whether the startup context panel is on screen. Derived once and read by
|
|
260
|
-
* BOTH the Ctrl+T handler and the render below: the key's meaning depends on
|
|
261
|
-
* the panel being visible, so a second copy of this condition is a place for
|
|
262
|
-
* the two to disagree — which is how the key came to advertise one thing and
|
|
263
|
-
* do another in the first place.
|
|
264
|
-
*/
|
|
294
|
+
/** The startup summary gives way to transcript rows after the first local command or message. */
|
|
265
295
|
const loadedContextVisible = channel.rows.length === 0 && channel.loadedContext !== undefined;
|
|
296
|
+
/** Startup context panel: collapsed by default, toggled with Ctrl+P. */
|
|
297
|
+
const [loadedContextOpen, setLoadedContextOpen] = React.useState(false);
|
|
266
298
|
/** `/` transcript search (less-style incsearch, ported from CC's REPL). */
|
|
267
299
|
const [searchOpen, setSearchOpen] = React.useState(false);
|
|
268
300
|
const [searchQuery, setSearchQuery] = React.useState('');
|
|
@@ -542,7 +574,8 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
|
|
|
542
574
|
case 'lang': {
|
|
543
575
|
// `/lang` shows the current UI language, `/lang en|zh` switches
|
|
544
576
|
// (hot-swap, persisted to ~/.dsh-tui/lang.json). Precedence on next
|
|
545
|
-
// launch: DSH_TUI_LANG >
|
|
577
|
+
// launch: DSH_TUI_LANG > settings.yaml `dsh-tui.lang` > cordis.yml
|
|
578
|
+
// `lang` > the persisted choice.
|
|
546
579
|
const parts = rawInput.trim().split(/\s+/).filter(Boolean);
|
|
547
580
|
if (parts[0] === 'status') {
|
|
548
581
|
setHelpOpen(false);
|
|
@@ -558,6 +591,16 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
|
|
|
558
591
|
if (isLang(parts[0])) {
|
|
559
592
|
const ok = writeLangPref(parts[0]);
|
|
560
593
|
setLang(parts[0]);
|
|
594
|
+
// Mirror into the dsh-tui settings namespace when it is served,
|
|
595
|
+
// so /settings and the next boot see the same last-write-wins
|
|
596
|
+
// choice (best effort; lang.json stays the fallback).
|
|
597
|
+
const settingsHost = channel.settingsHost();
|
|
598
|
+
const tuiView = settingsHost?.listNamespaces().find(entry => entry.ns === 'dsh-tui');
|
|
599
|
+
if (settingsHost !== undefined && tuiView !== undefined) {
|
|
600
|
+
void settingsHost
|
|
601
|
+
.write('dsh-tui', [{ op: 'set', path: ['lang'], value: parts[0] }], tuiView.revision)
|
|
602
|
+
.catch(() => { });
|
|
603
|
+
}
|
|
561
604
|
channel.notify(ok ? t('lang-switched', { lang: parts[0] }) : t('lang-switch-failed', { lang: parts[0] }), { color: ok ? 'success' : 'error' });
|
|
562
605
|
}
|
|
563
606
|
else {
|
|
@@ -635,6 +678,16 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
|
|
|
635
678
|
setHelpOpen(false);
|
|
636
679
|
openScene();
|
|
637
680
|
return true;
|
|
681
|
+
case 'context': {
|
|
682
|
+
setHelpOpen(false);
|
|
683
|
+
const context = channel.loadedContext;
|
|
684
|
+
if (context === undefined) {
|
|
685
|
+
channel.notify(t('context-unavailable'), { color: 'warning' });
|
|
686
|
+
return true;
|
|
687
|
+
}
|
|
688
|
+
channel.pushLocal('/context', formatLoadedContextReport(context));
|
|
689
|
+
return true;
|
|
690
|
+
}
|
|
638
691
|
case 'help':
|
|
639
692
|
setHelpOpen(true);
|
|
640
693
|
return true;
|
|
@@ -841,6 +894,13 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
|
|
|
841
894
|
setHelpOpen(false);
|
|
842
895
|
channel.pushLocal('/doctor', channel.doctorInfo());
|
|
843
896
|
return true;
|
|
897
|
+
case 'plugins':
|
|
898
|
+
// Plugin diagnostics (C-070): trust banner first, then descriptor /
|
|
899
|
+
// grant matrix / ledger tail — or validate+negotiate for
|
|
900
|
+
// `/plugins check <path>` (rawInput carries the subcommand).
|
|
901
|
+
setHelpOpen(false);
|
|
902
|
+
channel.pushLocal('/plugins', channel.pluginsInfo(rawInput));
|
|
903
|
+
return true;
|
|
844
904
|
case 'export': {
|
|
845
905
|
const target = channel.exportSession();
|
|
846
906
|
channel.notify(target === null
|
|
@@ -1048,11 +1108,32 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
|
|
|
1048
1108
|
}
|
|
1049
1109
|
setRewindIndex(0);
|
|
1050
1110
|
setRewindConfirm(null);
|
|
1111
|
+
setRewindModes(null);
|
|
1112
|
+
setRewindBusy(false);
|
|
1113
|
+
rewindRequestRef.current += 1;
|
|
1051
1114
|
setRewindOpen(true);
|
|
1052
1115
|
};
|
|
1116
|
+
/**
|
|
1117
|
+
* Enter on a rewind candidate: ask the plugins first (tui/rewind-prompt).
|
|
1118
|
+
* A veto keeps the list open; offered modes turn the confirm pane into a
|
|
1119
|
+
* choice list; "no opinion" lands on the plain confirm as before.
|
|
1120
|
+
*/
|
|
1121
|
+
const requestRewindConfirm = async (row) => {
|
|
1122
|
+
const token = ++rewindRequestRef.current;
|
|
1123
|
+
setRewindBusy(true);
|
|
1124
|
+
const decision = await channel.promptRewind(row);
|
|
1125
|
+
if (token !== rewindRequestRef.current)
|
|
1126
|
+
return;
|
|
1127
|
+
setRewindBusy(false);
|
|
1128
|
+
if (decision === 'cancel')
|
|
1129
|
+
return;
|
|
1130
|
+
setRewindConfirm(row);
|
|
1131
|
+
setRewindModes(decision?.modes ?? null);
|
|
1132
|
+
setRewindModeIndex(0);
|
|
1133
|
+
};
|
|
1053
1134
|
/** Execute the confirmed rewind; the message comes back into the input. */
|
|
1054
|
-
const performRewind = async (row) => {
|
|
1055
|
-
const text = await channel.rewindTo(row);
|
|
1135
|
+
const performRewind = async (row, mode = null) => {
|
|
1136
|
+
const text = await channel.rewindTo(row, mode);
|
|
1056
1137
|
if (text !== null) {
|
|
1057
1138
|
// CC puts the restored message back in the prompt for re-editing.
|
|
1058
1139
|
setHistoryFill(text);
|
|
@@ -1241,10 +1322,11 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
|
|
|
1241
1322
|
// turn was in flight — closing the view and killing the turn in one key.
|
|
1242
1323
|
if (sceneOpen || channel.pluginScene !== undefined)
|
|
1243
1324
|
return;
|
|
1244
|
-
// The questionnaire / approval panel
|
|
1245
|
-
// pending (the panel's own useInput handles
|
|
1246
|
-
// the prompt input is unmounted, so nothing
|
|
1247
|
-
|
|
1325
|
+
// The questionnaire / approval panel / managed plugin dialog owns the
|
|
1326
|
+
// keyboard while one is pending (the panel's own useInput handles
|
|
1327
|
+
// ↑/↓/Space/Tab/Enter/Esc; the prompt input is unmounted, so nothing
|
|
1328
|
+
// else should see these keys).
|
|
1329
|
+
if (questionSnapshot !== null || approvalSnapshot !== null || dialogSnapshot !== null)
|
|
1248
1330
|
return;
|
|
1249
1331
|
const returnCandidate = isPlainReturnInput(input, key);
|
|
1250
1332
|
const returnNow = Date.now();
|
|
@@ -1662,7 +1744,40 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
|
|
|
1662
1744
|
return;
|
|
1663
1745
|
}
|
|
1664
1746
|
if (rewindOpen) {
|
|
1747
|
+
// While the plugin decision is in flight the picker is read-only;
|
|
1748
|
+
// Esc abandons the wait (the stale answer is dropped by the token).
|
|
1749
|
+
if (rewindBusy) {
|
|
1750
|
+
if (key.escape) {
|
|
1751
|
+
rewindRequestRef.current += 1;
|
|
1752
|
+
setRewindBusy(false);
|
|
1753
|
+
}
|
|
1754
|
+
return;
|
|
1755
|
+
}
|
|
1665
1756
|
if (rewindConfirm !== null) {
|
|
1757
|
+
if (rewindModes !== null) {
|
|
1758
|
+
// Plugin offered modes: the confirm pane is a choice list —
|
|
1759
|
+
// option 0 is always the built-in conversation-only rewind.
|
|
1760
|
+
const optionCount = rewindModes.length + 1;
|
|
1761
|
+
if (key.upArrow) {
|
|
1762
|
+
setRewindModeIndex(index => (index <= 0 ? optionCount - 1 : index - 1));
|
|
1763
|
+
}
|
|
1764
|
+
else if (key.downArrow) {
|
|
1765
|
+
setRewindModeIndex(index => (index >= optionCount - 1 ? 0 : index + 1));
|
|
1766
|
+
}
|
|
1767
|
+
else if (plainReturn) {
|
|
1768
|
+
const row = rewindConfirm;
|
|
1769
|
+
const mode = rewindModeIndex === 0 ? null : (rewindModes[rewindModeIndex - 1]?.id ?? null);
|
|
1770
|
+
setRewindOpen(false);
|
|
1771
|
+
setRewindConfirm(null);
|
|
1772
|
+
setRewindModes(null);
|
|
1773
|
+
void performRewind(row, mode);
|
|
1774
|
+
}
|
|
1775
|
+
else if (key.escape) {
|
|
1776
|
+
setRewindConfirm(null);
|
|
1777
|
+
setRewindModes(null);
|
|
1778
|
+
}
|
|
1779
|
+
return;
|
|
1780
|
+
}
|
|
1666
1781
|
// Confirmation state: Enter rewinds, Esc backs out to the list.
|
|
1667
1782
|
if (plainReturn) {
|
|
1668
1783
|
const row = rewindConfirm;
|
|
@@ -1684,37 +1799,27 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
|
|
|
1684
1799
|
const row = rewindRows[rewindIndex];
|
|
1685
1800
|
// oxlint-disable-next-line typescript/no-unnecessary-condition -- runtime guard: out-of-range index on an empty list
|
|
1686
1801
|
if (row)
|
|
1687
|
-
|
|
1802
|
+
void requestRewindConfirm(row);
|
|
1688
1803
|
}
|
|
1689
1804
|
else if (key.escape) {
|
|
1690
1805
|
setRewindOpen(false);
|
|
1691
1806
|
setRewindConfirm(null);
|
|
1807
|
+
setRewindModes(null);
|
|
1692
1808
|
}
|
|
1693
1809
|
return;
|
|
1694
1810
|
}
|
|
1695
1811
|
if (isMod(key) && input === 't') {
|
|
1696
|
-
// Ctrl+T
|
|
1697
|
-
// can expand never share the screen.
|
|
1698
|
-
//
|
|
1699
|
-
// The startup loaded-context panel renders only while the transcript is
|
|
1700
|
-
// empty (see the render below) — and that is exactly the window where
|
|
1701
|
-
// the trajectory has nothing in it yet, since the trajectory is folded
|
|
1702
|
-
// from the session's own events. So the panel wins while it is up, and
|
|
1703
|
-
// the scene takes over for the rest of the session.
|
|
1704
|
-
//
|
|
1705
|
-
// Claiming the key outright for the scene was wrong even though the
|
|
1706
|
-
// panel binding looked dead: the panel prints its own `(Ctrl+T 展开)`
|
|
1707
|
-
// hint, so the key still had a visible promise attached to it, and the
|
|
1708
|
-
// scene it opened instead was necessarily empty at that moment. That
|
|
1709
|
-
// left the panel reachable only by clicking its header, which is not a
|
|
1710
|
-
// keyboard path at all.
|
|
1711
|
-
if (loadedContextVisible) {
|
|
1712
|
-
setLoadedContextOpen(previous => !previous);
|
|
1713
|
-
return;
|
|
1714
|
-
}
|
|
1812
|
+
// Ctrl+T opens the trajectory scene at any point in the session.
|
|
1715
1813
|
openScene();
|
|
1716
1814
|
return;
|
|
1717
1815
|
}
|
|
1816
|
+
if (isMod(key) && input === 'p' && loadedContextVisible) {
|
|
1817
|
+
// Ctrl+P toggles the startup loaded-context panel while it is on
|
|
1818
|
+
// screen (transcript still empty); once rows take over and the
|
|
1819
|
+
// panel disappears the key has nothing left to do.
|
|
1820
|
+
setLoadedContextOpen(previous => !previous);
|
|
1821
|
+
return;
|
|
1822
|
+
}
|
|
1718
1823
|
if (isMod(key) && input === 'r' && !helpOpen) {
|
|
1719
1824
|
setHistoryQuery('');
|
|
1720
1825
|
setHistoryCursor(0);
|
|
@@ -1760,6 +1865,16 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
|
|
|
1760
1865
|
else if (isMod(key) && input === 'o') {
|
|
1761
1866
|
// Leaving transcript mode (Ctrl+O) — search was already handled above.
|
|
1762
1867
|
setExpanded(previous => !previous);
|
|
1868
|
+
// The toggle rewrites every thinking row's layout at once. The
|
|
1869
|
+
// ordinary scroll-based diff pushes rows into terminal scrollback on
|
|
1870
|
+
// each expand and nothing removes them on collapse — rapid toggling
|
|
1871
|
+
// drifts the virtual↔scrollback mapping until writes misland
|
|
1872
|
+
// (garbled transcript, duplicated rows). Re-anchor the next frame:
|
|
1873
|
+
// in-place viewport repaint, nothing added to scrollback. Lookup
|
|
1874
|
+
// falls back to the only live instance for embedders whose stdout
|
|
1875
|
+
// isn't process.stdout (test harnesses).
|
|
1876
|
+
const ink = instances.get(process.stdout) ?? instances.values().next().value;
|
|
1877
|
+
ink?.reanchorViewport();
|
|
1763
1878
|
}
|
|
1764
1879
|
else if (input === '/' && !key.ctrl && !key.meta && !key.super) {
|
|
1765
1880
|
// `/` in transcript mode (Ctrl+O expanded, CC's REPL semantics:
|
|
@@ -1803,6 +1918,15 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
|
|
|
1803
1918
|
else if (plainReturn && showPill) {
|
|
1804
1919
|
handle?.scrollToBottom();
|
|
1805
1920
|
}
|
|
1921
|
+
else if (extensionShortcuts !== undefined && extensionShortcuts.dispatch(input, key)) {
|
|
1922
|
+
// Plugin shortcut (tuiShortcuts seam): matched only after every
|
|
1923
|
+
// built-in global binding above declined — locals always win, and the
|
|
1924
|
+
// registry additionally refuses the prompt editor's own combos at
|
|
1925
|
+
// registration, so a plugin can never shadow anything. The handler
|
|
1926
|
+
// runs fire-and-forget; its errors arrive via the onError hook
|
|
1927
|
+
// (wired to the toast below).
|
|
1928
|
+
event.stopImmediatePropagation();
|
|
1929
|
+
}
|
|
1806
1930
|
});
|
|
1807
1931
|
// Working-activity line (spinner slot): context-pressure prefix shares the
|
|
1808
1932
|
// StatusLine thresholds (amber ≥ 80, red ≥ 95).
|
|
@@ -1883,7 +2007,7 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
|
|
|
1883
2007
|
seekRow(lastUser.id);
|
|
1884
2008
|
else
|
|
1885
2009
|
handle?.scrollToBottom();
|
|
1886
|
-
} })), _jsxs(ScrollBox, { ref: setHandle, flexDirection: "column", flexGrow: 1, flexShrink: 1, stickyScroll: true, children: [_jsx(LogoHeader, { model: channel.model, effort: channel.reasoningEffort, cwd: channel.displayCwd }), loadedContextVisible && (_jsx(LoadedContextPanel, { context: channel.loadedContext, open: loadedContextOpen, onToggle: () => { setLoadedContextOpen(previous => !previous); } })), _jsx(MessageList, { rows: channel.rows, failureHintRowId: failureHintRowId, failureHint: t('traj-hint-failure', { key: `${modLabel}t` }), expanded: expanded, expandedRows: expandedRows, selectedId: selectionActive ? selectedId : null, onToggleRow: toggleRowExpanded, model: channel.model, diffLayout: channel.diffLayout, showAll: showAllMessages, thinkingVisible: thinkingVisible, onToggleAll: () => { setShowAllMessages(previous => !previous); }, onLoadOlder: () => channel.loadOlder(), registerRowRef: registerRowRef, scrollHandle: handle, forceMountRowId: forceMountRowId, newSinceRowId: isSticky ? null : lastSeenRowIdRef.current, onUnseenCount: setUnseenCount })] }), _jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [showPill && (_jsx(NewMessagesPill, { count: unseenCount, onClick: () => handle?.scrollToBottom() })), channel.working &&
|
|
2010
|
+
} })), _jsxs(ScrollBox, { ref: setHandle, flexDirection: "column", flexGrow: 1, flexShrink: 1, stickyScroll: true, children: [_jsx(LogoHeader, { model: channel.model, effort: channel.reasoningEffort, cwd: channel.displayCwd }), loadedContextVisible && (_jsx(LoadedContextPanel, { context: channel.loadedContext, open: loadedContextOpen, onToggle: () => { setLoadedContextOpen(previous => !previous); } })), _jsx(MessageList, { rows: channel.rows, failureHintRowId: failureHintRowId, failureHint: t('traj-hint-failure', { key: `${modLabel}t` }), expanded: expanded, expandedRows: expandedRows, selectedId: selectionActive ? selectedId : null, onToggleRow: toggleRowExpanded, model: channel.model, diffLayout: channel.diffLayout, thinkingFold: channel.thinkingFold, showAll: showAllMessages, thinkingVisible: thinkingVisible, onToggleAll: () => { setShowAllMessages(previous => !previous); }, onLoadOlder: () => channel.loadOlder(), registerRowRef: registerRowRef, scrollHandle: handle, forceMountRowId: forceMountRowId, newSinceRowId: isSticky ? null : lastSeenRowIdRef.current, onUnseenCount: setUnseenCount })] }), _jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [showPill && (_jsx(NewMessagesPill, { count: unseenCount, onClick: () => handle?.scrollToBottom() })), channel.working &&
|
|
1887
2011
|
(channel.activityEnabled &&
|
|
1888
2012
|
channel.workingActivity !== undefined &&
|
|
1889
2013
|
channel.workingActivity.line !== '' &&
|
|
@@ -1892,7 +2016,7 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
|
|
|
1892
2016
|
// the animated chars/4 estimate, matching the classic
|
|
1893
2017
|
// spinner's counter (the suffix used raw chars before,
|
|
1894
2018
|
// inflating the reading next to a real upload number).
|
|
1895
|
-
suffix: `${lastUploadTokens > 0 ? ` · ↑ ${formatTokens(lastUploadTokens)}` : ''} · ↓ ${formatTokens(Math.round(channel.responseChars / 4))} tokens` }) })) : (_jsx(WorkingSpinner, { mode: channel.spinnerMode, hasActiveTools: channel.activeToolCount > 0, responseLengthRef: responseLengthRef, uploadTokensRef: uploadTokensRef, loadingStartTimeRef: loadingStartTimeRef, totalPausedMsRef: totalPausedMsRef, pauseStartTimeRef: pauseStartTimeRef, thinkingStatus: thinkingStatus }))), _jsx(GoalTodoPanel, { channel: channel }), approvalSnapshot !== null ? (_jsx(ApprovalPanel, { approval: approvalSnapshot, onDecide: outcome => approvals.decide(outcome) }, approvalSnapshot.key)) : btw !== null ? (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(BtwPanel, { question: btw.question, answer: btw.answer, error: btw.error, streaming: !btw.done, onClose: closeBtw, onCopy: () => {
|
|
2019
|
+
suffix: `${lastUploadTokens > 0 ? ` · ↑ ${formatTokens(lastUploadTokens)}` : ''} · ↓ ${formatTokens(Math.round(channel.responseChars / 4))} tokens` }) })) : (_jsx(WorkingSpinner, { mode: channel.spinnerMode, hasActiveTools: channel.activeToolCount > 0, responseLengthRef: responseLengthRef, uploadTokensRef: uploadTokensRef, loadingStartTimeRef: loadingStartTimeRef, totalPausedMsRef: totalPausedMsRef, pauseStartTimeRef: pauseStartTimeRef, thinkingStatus: thinkingStatus }))), _jsx(GoalTodoPanel, { channel: channel }), statusEntries.length > 0 && (_jsx(Text, { dimColor: true, wrap: "truncate", children: statusEntries.map(entry => entry.text).join(' · ') })), approvalSnapshot !== null ? (_jsx(ApprovalPanel, { approval: approvalSnapshot, onDecide: outcome => approvals.decide(outcome) }, approvalSnapshot.key)) : dialogSnapshot !== null ? (_jsx(ExtensionDialog, { dialog: dialogSnapshot, onDecide: value => dialogs.decide(dialogSnapshot.key, value), onCancel: () => dialogs.cancel(dialogSnapshot.key) }, dialogSnapshot.key)) : btw !== null ? (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(BtwPanel, { question: btw.question, answer: btw.answer, error: btw.error, streaming: !btw.done, onClose: closeBtw, onCopy: () => {
|
|
1896
2020
|
void setClipboard(btw.answer ?? '').then(raw => { if (raw)
|
|
1897
2021
|
process.stdout.write(raw); });
|
|
1898
2022
|
channel.notify(t('copied-chars', { n: (btw.answer ?? '').length }), { timeoutMs: 1500 });
|
|
@@ -1902,7 +2026,7 @@ export function Chat({ channel, questionStore, approvalStore, onExit, onUpdate,
|
|
|
1902
2026
|
band: wakeBand,
|
|
1903
2027
|
hint: trajectorySeen ? undefined : `${modLabel}t`,
|
|
1904
2028
|
tick: Math.floor(wakeTime / 120),
|
|
1905
|
-
} }), dialogOverlayOpen && (_jsxs(OverlayAbove, { maxHeight: Math.max(terminalRows - 8, 8), children: [thinkingOpen && (_jsx(ThinkingToggle, { currentValue: thinkingVisible, focusIndex: thinkingFocus, confirmationPending: thinkingConfirm })), workspacePickerOpen && workspaceTargets.length > 0 && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(WorkspacePicker, { targets: workspaceTargets, focusIndex: workspaceIndex, currentCwd: channel.cwd }) })), workspaceFlow !== null && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(WorkspaceFlowPicker, { title: workspaceFlow.title, choices: workspaceFlow.choices, focusIndex: workspaceFlowIndex, busy: workspaceFlowBusy, input: workspaceFlowInput }) })), modelPickerOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: models.length === 0 ? (_jsx(ModelPickerLoading, {})) : (_jsx(ModelPicker, { models: models, focusIndex: modelIndex, currentModel: `${channel.provider}/${channel.model}` })) })), skillsPickerOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: skillsList === null ? (_jsx(SkillsPickerLoading, {})) : (_jsx(SkillsPicker, { skills: skillsList, focusIndex: skillsIndex })) })), activityPickerOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(ActivityPicker, { focusIndex: activityIndex, currentPreset: channel.activityFrames }) })), effortSliderOpen && effortOptions.length > 1 && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(EffortSlider, { options: effortOptions, focusIndex: effortIndex, currentId: channel.reasoningEffort }) })), presetPickerOpen && presetOptions.length > 0 && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(PresetPicker, { presets: presetOptions, focusIndex: presetIndex, currentPreset: channel.agentPreset }) })), themePickerOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(ThemePicker, { focusIndex: themeIndex, currentTheme: themeName }) })), historyOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(HistorySearchDialog, { query: historyQuery, cursorOffset: historyCursor, matches: historyMatches, focusIndex: historyFocus }) })), rewindOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(RewindPicker, { rows: rewindRows, focusIndex: rewindIndex, confirmRow: rewindConfirm }) })), searchOpen && _jsx(TranscriptSearchBar, { query: searchQuery, cursorOffset: searchCursor, count: searchCount, current: searchCurrent })] }))] })] }));
|
|
2029
|
+
} }), dialogOverlayOpen && (_jsxs(OverlayAbove, { maxHeight: Math.max(terminalRows - 8, 8), children: [thinkingOpen && (_jsx(ThinkingToggle, { currentValue: thinkingVisible, focusIndex: thinkingFocus, confirmationPending: thinkingConfirm })), workspacePickerOpen && workspaceTargets.length > 0 && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(WorkspacePicker, { targets: workspaceTargets, focusIndex: workspaceIndex, currentCwd: channel.cwd }) })), workspaceFlow !== null && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(WorkspaceFlowPicker, { title: workspaceFlow.title, choices: workspaceFlow.choices, focusIndex: workspaceFlowIndex, busy: workspaceFlowBusy, input: workspaceFlowInput }) })), modelPickerOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: models.length === 0 ? (_jsx(ModelPickerLoading, {})) : (_jsx(ModelPicker, { models: models, focusIndex: modelIndex, currentModel: `${channel.provider}/${channel.model}` })) })), skillsPickerOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: skillsList === null ? (_jsx(SkillsPickerLoading, {})) : (_jsx(SkillsPicker, { skills: skillsList, focusIndex: skillsIndex })) })), activityPickerOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(ActivityPicker, { focusIndex: activityIndex, currentPreset: channel.activityFrames }) })), effortSliderOpen && effortOptions.length > 1 && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(EffortSlider, { options: effortOptions, focusIndex: effortIndex, currentId: channel.reasoningEffort }) })), presetPickerOpen && presetOptions.length > 0 && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(PresetPicker, { presets: presetOptions, focusIndex: presetIndex, currentPreset: channel.agentPreset }) })), themePickerOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(ThemePicker, { focusIndex: themeIndex, currentTheme: themeName }) })), historyOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(HistorySearchDialog, { query: historyQuery, cursorOffset: historyCursor, matches: historyMatches, focusIndex: historyFocus }) })), rewindOpen && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(RewindPicker, { rows: rewindRows, focusIndex: rewindIndex, confirmRow: rewindConfirm, modes: rewindModes, modeIndex: rewindModeIndex, busy: rewindBusy }) })), searchOpen && _jsx(TranscriptSearchBar, { query: searchQuery, cursorOffset: searchCursor, count: searchCount, current: searchCurrent })] }))] })] }));
|
|
1906
2030
|
}
|
|
1907
2031
|
/**
|
|
1908
2032
|
* The pinned prompt header shown above the ScrollBox while the user has
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionBrowser.d.ts","sourceRoot":"","sources":["../../../src/screens/SessionBrowser.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAsBzB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AAoDxD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,IAAI,EACJ,WAAW,EACX,OAAO,GACR,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAA;IACZ,4EAA4E;IAC5E,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAA;IAC9C,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,GAAG,KAAK,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"SessionBrowser.d.ts","sourceRoot":"","sources":["../../../src/screens/SessionBrowser.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAsBzB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AAoDxD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,IAAI,EACJ,WAAW,EACX,OAAO,GACR,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAA;IACZ,4EAA4E;IAC5E,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAA;IAC9C,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,GAAG,KAAK,CAAC,SAAS,CA4elB"}
|