@deepseek-harness-tui/dsh-tui 0.7.3 → 0.8.1
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 +15 -7
- package/bin/dsh-tui.js +19 -3
- package/cordis.patch.yml +43 -11
- package/cordis.yml +20 -1
- package/ecosystem-spec/registry/contracts/decision-events-v1alpha1.json +13 -0
- package/ecosystem-spec/registry/host-descriptor.tui.example.json +56 -0
- package/ecosystem-spec/registry/permissions-0.1.json +13 -0
- package/ecosystem-spec/registry/registry-0.15.json +57 -0
- package/ecosystem-spec/schemas/conformance-claim.schema.json +15 -0
- package/ecosystem-spec/schemas/effect-ledger-record.schema.json +16 -0
- package/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/commands.d.ts.map +1 -1
- package/lib/types/commands.js +4 -1
- 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 -10
- package/lib/types/components/LoadedContextPanel.d.ts.map +1 -1
- package/lib/types/components/LoadedContextPanel.js +7 -18
- package/lib/types/components/LogoV2.d.ts.map +1 -1
- package/lib/types/components/LogoV2.js +1 -2
- 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 +29 -5
- package/lib/types/components/PluginSceneBoundary.d.ts +31 -0
- package/lib/types/components/PluginSceneBoundary.d.ts.map +1 -0
- package/lib/types/components/PluginSceneBoundary.js +29 -0
- 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/SkillsPicker.d.ts +18 -0
- package/lib/types/components/SkillsPicker.d.ts.map +1 -0
- package/lib/types/components/SkillsPicker.js +50 -0
- package/lib/types/components/SplitDiffView.d.ts +28 -0
- package/lib/types/components/SplitDiffView.d.ts.map +1 -0
- package/lib/types/components/SplitDiffView.js +417 -0
- 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/messages/AssistantToolUseMessage.d.ts +3 -1
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantToolUseMessage.js +17 -7
- package/lib/types/dsh-adapter/channel.d.ts +98 -7
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +623 -26
- 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/component-identity.d.ts +28 -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 +2 -2
- package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
- package/lib/types/dsh-adapter/contract.js +3 -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 +354 -0
- package/lib/types/dsh-adapter/dialogs.d.ts +146 -0
- package/lib/types/dsh-adapter/dialogs.d.ts.map +1 -0
- package/lib/types/dsh-adapter/dialogs.js +262 -0
- package/lib/types/dsh-adapter/effect-ledger.d.ts +99 -0
- package/lib/types/dsh-adapter/effect-ledger.d.ts.map +1 -0
- package/lib/types/dsh-adapter/effect-ledger.js +231 -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 +169 -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 +184 -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 +146 -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 +178 -0
- package/lib/types/dsh-adapter/message-observer.d.ts.map +1 -0
- package/lib/types/dsh-adapter/message-observer.js +509 -0
- package/lib/types/dsh-adapter/plugin-host.d.ts +103 -0
- package/lib/types/dsh-adapter/plugin-host.d.ts.map +1 -0
- package/lib/types/dsh-adapter/plugin-host.js +270 -0
- package/lib/types/dsh-adapter/plugin-storage.d.ts +113 -0
- package/lib/types/dsh-adapter/plugin-storage.d.ts.map +1 -0
- package/lib/types/dsh-adapter/plugin-storage.js +385 -0
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +106 -1
- 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 +10 -0
- package/lib/types/dsh-adapter/promptDebug.d.ts.map +1 -0
- package/lib/types/dsh-adapter/promptDebug.js +148 -0
- package/lib/types/dsh-adapter/renderers.d.ts +65 -0
- package/lib/types/dsh-adapter/renderers.d.ts.map +1 -0
- package/lib/types/dsh-adapter/renderers.js +138 -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 +81 -0
- package/lib/types/dsh-adapter/scenes.d.ts.map +1 -0
- package/lib/types/dsh-adapter/scenes.js +93 -0
- package/lib/types/dsh-adapter/settings-sections.d.ts +116 -0
- package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -0
- package/lib/types/dsh-adapter/settings-sections.js +63 -0
- package/lib/types/dsh-adapter/settingsEditor.d.ts +128 -0
- package/lib/types/dsh-adapter/settingsEditor.d.ts.map +1 -0
- package/lib/types/dsh-adapter/settingsEditor.js +244 -0
- package/lib/types/dsh-adapter/shortcuts.d.ts +109 -0
- package/lib/types/dsh-adapter/shortcuts.d.ts.map +1 -0
- package/lib/types/dsh-adapter/shortcuts.js +268 -0
- package/lib/types/dsh-adapter/status.d.ts +75 -0
- package/lib/types/dsh-adapter/status.d.ts.map +1 -0
- package/lib/types/dsh-adapter/status.js +168 -0
- package/lib/types/extensions.d.ts +8 -0
- package/lib/types/extensions.d.ts.map +1 -0
- package/lib/types/extensions.js +15 -0
- package/lib/types/i18n.d.ts +299 -26
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +89 -8
- package/lib/types/ink/ink.d.ts +11 -0
- package/lib/types/ink/ink.d.ts.map +1 -1
- package/lib/types/ink/ink.js +33 -0
- package/lib/types/ink/log-update.d.ts.map +1 -1
- package/lib/types/ink/log-update.js +101 -51
- package/lib/types/ink/output.d.ts +7 -0
- package/lib/types/ink/output.d.ts.map +1 -1
- package/lib/types/ink/output.js +125 -4
- 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/terminal.d.ts.map +1 -1
- package/lib/types/ink/terminal.js +18 -6
- package/lib/types/jsx-runtime.d.ts +2 -0
- package/lib/types/jsx-runtime.d.ts.map +1 -0
- package/lib/types/jsx-runtime.js +13 -0
- package/lib/types/modelRoute.d.ts +10 -2
- package/lib/types/modelRoute.d.ts.map +1 -1
- package/lib/types/modelRoute.js +33 -4
- package/lib/types/plugin-host.d.ts +13 -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 +157 -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 +77 -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 +119 -0
- package/lib/types/scenes.d.ts +3 -0
- package/lib/types/scenes.d.ts.map +1 -0
- package/lib/types/scenes.js +4 -0
- 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 +247 -48
- package/lib/types/screens/Settings.d.ts +20 -0
- package/lib/types/screens/Settings.d.ts.map +1 -0
- package/lib/types/screens/Settings.js +333 -0
- package/lib/types/screens/StatusLine.js +1 -1
- package/lib/types/settings-sections.d.ts +3 -0
- package/lib/types/settings-sections.d.ts.map +1 -0
- package/lib/types/settings-sections.js +4 -0
- package/lib/types/theme.d.ts +17 -0
- package/lib/types/theme.d.ts.map +1 -1
- package/lib/types/theme.js +51 -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/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/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/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 +257 -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/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/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/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/LICENSE +21 -0
- package/node_modules/@dsh-std/presentation/README.md +26 -0
- package/node_modules/@dsh-std/presentation/README.zh.md +28 -0
- package/node_modules/@dsh-std/presentation/lib/index.d.ts +219 -0
- package/node_modules/@dsh-std/presentation/lib/index.d.ts.map +1 -0
- package/node_modules/@dsh-std/presentation/lib/index.js +547 -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 +21 -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 +118 -67
- 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 +257 -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/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/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/LICENSE +21 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.md +26 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.zh.md +28 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.d.ts +219 -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 +547 -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 +21 -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/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/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/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 +257 -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/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/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,509 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* messages.observe contract surface (C-042,
|
|
3
|
+
* `messages.dsh/v1alpha1#MessageObserver`): the host event broker, mounted
|
|
4
|
+
* by the dsh-tui-plugin-host row as `ctx.tuiMessageObserver`.
|
|
5
|
+
*
|
|
6
|
+
* Mapping (deliberately narrow):
|
|
7
|
+
*
|
|
8
|
+
* - `user/message` → `message.received` (the user's prompt)
|
|
9
|
+
* - `assistant/message` → `message.sent` (the assembled step reply)
|
|
10
|
+
* - EVERYTHING ELSE (assistant/chunk streaming, tool/*, turn/*, mode
|
|
11
|
+
* events, …) produces NO envelope — observation starts conservative.
|
|
12
|
+
*
|
|
13
|
+
* Envelope rules (the pinned `@dsh-std/messages` v0.15 definition):
|
|
14
|
+
*
|
|
15
|
+
* - `scope` = `session:<sessionId>`; `sequence` = the session event's own
|
|
16
|
+
* `seq` (monotonic within scope, gaps allowed — unmapped events simply
|
|
17
|
+
* leave holes); `eventId` = `<sessionId>:<seq>` with schema-unsafe
|
|
18
|
+
* characters flattened to `_`.
|
|
19
|
+
* - privacyClass is ALWAYS `sensitive` for now (conservative and
|
|
20
|
+
* irreversible-safe; finer classification is a future, documented step).
|
|
21
|
+
* - Content carries the text/image subset (MCP ContentBlock): text runs
|
|
22
|
+
* join (a pure-text message keeps the single trimmed block); session
|
|
23
|
+
* image blocks are `{type:'image', attachment}` REFERENCES resolved via
|
|
24
|
+
* the attachments service into base64 `data` with a 192 KiB budget —
|
|
25
|
+
* an unreadable/oversize image is dropped and marks `truncated`.
|
|
26
|
+
* `summary` is the sanitized first 200 cells of the joined text;
|
|
27
|
+
* `truncated` marks summary, content, or image-drop truncation.
|
|
28
|
+
* - EVERY produced envelope passes the official pinned validator before delivery;
|
|
29
|
+
* a malformed envelope is dropped with a warning, never delivered.
|
|
30
|
+
*
|
|
31
|
+
* Scope isolation (C-042): `subscribe` requires an exact `scope` string
|
|
32
|
+
* and an envelope is delivered ONLY to subscriptions of the same scope —
|
|
33
|
+
* a plugin moving between sessions subscribes per scope and never
|
|
34
|
+
* receives another session's sensitive content.
|
|
35
|
+
*
|
|
36
|
+
* Grant gating (`messages.observe.read`, default deny):
|
|
37
|
+
*
|
|
38
|
+
* - SUBSCRIBE time: a denied plugin gets a no-op disposer + a warning
|
|
39
|
+
* naming plugin and grant (fast fail, as-if-unsubscribed).
|
|
40
|
+
* - DELIVER time: every publish re-checks each subscription; a revoked
|
|
41
|
+
* grant RELEASES the subscription (contract cleanup rule) with one
|
|
42
|
+
* warning.
|
|
43
|
+
*
|
|
44
|
+
* Delivery semantics: at-most-once, no replay; envelope builds serialize
|
|
45
|
+
* broker-wide (image reads are async — delivery order stays the publish
|
|
46
|
+
* order, so sequence stays monotonic); callbacks of ONE subscription run
|
|
47
|
+
* serially (per-subscription promise chain); a throwing listener is
|
|
48
|
+
* isolated (warn, name the plugin, keep delivering to the rest). The host
|
|
49
|
+
* MUST NOT persist payload through this contract — the broker keeps no
|
|
50
|
+
* history.
|
|
51
|
+
*
|
|
52
|
+
* privacyClass: sensitive — envelope content is never logged.
|
|
53
|
+
*/
|
|
54
|
+
import { Service } from '@deepseek-ai/cordis';
|
|
55
|
+
import { validateMessageEvent } from '@dsh-std/messages';
|
|
56
|
+
import { check } from '../plugin-spec/schema-check.js';
|
|
57
|
+
import { cleanScalarText } from './sanitize.js';
|
|
58
|
+
import { readGrantStore } from './grants.js';
|
|
59
|
+
import { declaresObserverScope, declaresPermission, requireComponentIdentity, } from './component-identity.js';
|
|
60
|
+
import { normalizePermissionScope, scopeCovers, SESSION_SCOPE_MAX_CHARS, } from '../plugin-spec/permission-scope.js';
|
|
61
|
+
/** Summary bound (cells; schema maxLength 1024 chars — 200 cells ≤ 1024). */
|
|
62
|
+
export const OBSERVE_SUMMARY_CELLS = 200;
|
|
63
|
+
/** Content text bound (chars; schema maxLength 262144). */
|
|
64
|
+
export const OBSERVE_CONTENT_MAX_CHARS = 262144;
|
|
65
|
+
/** Scope bound (schema maxLength 256). */
|
|
66
|
+
export const OBSERVE_SCOPE_MAX_CHARS = SESSION_SCOPE_MAX_CHARS;
|
|
67
|
+
/** messageId bound (schema maxLength 256). */
|
|
68
|
+
export const OBSERVE_ID_MAX_CHARS = 256;
|
|
69
|
+
/** Raw image byte budget per block (192 KiB → ≤262144 base64 chars). */
|
|
70
|
+
export const OBSERVE_IMAGE_MAX_BYTES = 192 * 1024;
|
|
71
|
+
/** Base64 length bound implied by OBSERVE_IMAGE_MAX_BYTES. */
|
|
72
|
+
export const OBSERVE_IMAGE_BASE64_MAX_CHARS = 262144;
|
|
73
|
+
/** Per-callback budget; timeout closes the subscription deterministically. */
|
|
74
|
+
export const OBSERVE_CALLBACK_TIMEOUT_MS = 1500;
|
|
75
|
+
/** Bound queued callbacks per subscription so a stalled listener cannot grow
|
|
76
|
+
* an unbounded Promise chain before its timeout closes the subscription. */
|
|
77
|
+
export const OBSERVE_CALLBACK_QUEUE_LIMIT = 32;
|
|
78
|
+
/** The envelope schema's mimeType pattern (image blocks). */
|
|
79
|
+
const OBSERVE_MIME_PATTERN = /^[A-Za-z0-9.+-]+\/[A-Za-z0-9.+-]+$/;
|
|
80
|
+
function deepFreeze(value) {
|
|
81
|
+
if (value === null || typeof value !== 'object' || Object.isFrozen(value))
|
|
82
|
+
return value;
|
|
83
|
+
Object.freeze(value);
|
|
84
|
+
for (const child of Object.values(value))
|
|
85
|
+
deepFreeze(child);
|
|
86
|
+
return value;
|
|
87
|
+
}
|
|
88
|
+
function freezeEnvelope(envelope) {
|
|
89
|
+
return deepFreeze(structuredClone(envelope));
|
|
90
|
+
}
|
|
91
|
+
/** Session events are untrusted at this boundary. Never coerce arbitrary
|
|
92
|
+
* objects through `String()` because a hostile `toString` can fabricate
|
|
93
|
+
* message text (or throw) before the envelope validator sees it. */
|
|
94
|
+
function sourceBlockType(value) {
|
|
95
|
+
if (value === null || typeof value !== 'object')
|
|
96
|
+
return undefined;
|
|
97
|
+
try {
|
|
98
|
+
const type = value.type;
|
|
99
|
+
return type === 'text' || type === 'image' ? type : undefined;
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function sourceText(value) {
|
|
106
|
+
try {
|
|
107
|
+
const text = value.text;
|
|
108
|
+
return typeof text === 'string' ? text : undefined;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async function runWithBudget(task, timeoutMs) {
|
|
115
|
+
let timer;
|
|
116
|
+
const work = Promise.resolve()
|
|
117
|
+
.then(task)
|
|
118
|
+
.then(() => ({ kind: 'fulfilled' }), error => ({ kind: 'rejected', error }));
|
|
119
|
+
const timeout = new Promise(resolve => {
|
|
120
|
+
timer = setTimeout(() => resolve({ kind: 'timeout' }), timeoutMs);
|
|
121
|
+
});
|
|
122
|
+
try {
|
|
123
|
+
return await Promise.race([work, timeout]);
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
if (timer !== undefined)
|
|
127
|
+
clearTimeout(timer);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/** Match a requested observer scope against the concrete scope of an
|
|
131
|
+
* envelope. `session:*` is an explicit, grantable parent scope; all other
|
|
132
|
+
* scopes remain exact. Keeping this relation in the broker means a wildcard
|
|
133
|
+
* declaration cannot accidentally become global unless both the manifest and
|
|
134
|
+
* the current grant cover it. */
|
|
135
|
+
function observerScopeCovers(subscriptionScope, envelopeScope) {
|
|
136
|
+
const declared = normalizePermissionScope('messages.observe.read', subscriptionScope, 'host');
|
|
137
|
+
const actual = normalizePermissionScope('messages.observe.read', envelopeScope, 'host');
|
|
138
|
+
return declared !== undefined && actual !== undefined && scopeCovers(declared, actual);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* `ctx.tuiMessageObserver` — the messages.observe broker. The channel
|
|
142
|
+
* publishes mapped session events; plugins subscribe with their own
|
|
143
|
+
* context. When the vendored envelope schema is unavailable (packaging
|
|
144
|
+
* accident) the broker fails CLOSED: subscriptions are accepted but nothing
|
|
145
|
+
* is ever delivered (a host that cannot self-check must not emit).
|
|
146
|
+
*/
|
|
147
|
+
export class TuiMessageObserverRuntime extends Service {
|
|
148
|
+
grantsOption;
|
|
149
|
+
fallbackGrants;
|
|
150
|
+
ledgerOption;
|
|
151
|
+
subscriptions = new Set();
|
|
152
|
+
validateEnvelope;
|
|
153
|
+
validatorUnavailable;
|
|
154
|
+
validatorWarned = false;
|
|
155
|
+
buildChain = Promise.resolve();
|
|
156
|
+
constructor(ctx, options = {}) {
|
|
157
|
+
super(ctx, 'tuiMessageObserver');
|
|
158
|
+
this.grantsOption = options.grants;
|
|
159
|
+
this.fallbackGrants = readGrantStore();
|
|
160
|
+
this.ledgerOption = options.ledger;
|
|
161
|
+
if (Object.hasOwn(options, 'validateEnvelope')) {
|
|
162
|
+
this.validatorUnavailable = options.validateEnvelope === undefined;
|
|
163
|
+
this.validateEnvelope = options.validateEnvelope ?? (() => { throw new Error('standard envelope validator unavailable'); });
|
|
164
|
+
}
|
|
165
|
+
else if (Object.hasOwn(options, 'envelopeSchema')) {
|
|
166
|
+
const schema = options.envelopeSchema;
|
|
167
|
+
this.validatorUnavailable = schema === undefined;
|
|
168
|
+
this.validateEnvelope = schema === undefined
|
|
169
|
+
? (() => { throw new Error('vendored envelope schema unavailable'); })
|
|
170
|
+
: (value) => check(value, schema, schema);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
this.validatorUnavailable = false;
|
|
174
|
+
this.validateEnvelope = (value) => { validateMessageEvent(value); };
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/** Grants: the plugin-host row's store when mounted, else a private read.
|
|
178
|
+
* Resolved PER CALL — sibling services mounted later by the same apply()
|
|
179
|
+
* are not visible to constructors (cordis), so a constructor-time probe
|
|
180
|
+
* would silently stick to the fallback. */
|
|
181
|
+
grants() {
|
|
182
|
+
return this.grantsOption ?? this.ctx.get('tuiPluginHost')?.grants ?? this.fallbackGrants;
|
|
183
|
+
}
|
|
184
|
+
/** Optional observability; a bare mount (tests) simply records nothing. */
|
|
185
|
+
ledger() {
|
|
186
|
+
return this.ledgerOption ?? this.ctx.get('tuiEffectLedger');
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Subscribe to observation envelopes for ONE scope. Identity = the verified
|
|
190
|
+
* Component bound to the PASSED activation (the same identity rule as
|
|
191
|
+
* storage); the scope
|
|
192
|
+
* is required and matched exactly — a plugin moving between sessions
|
|
193
|
+
* subscribes per scope and never receives another scope's sensitive
|
|
194
|
+
* content (C-042 isolation). A denied subscription fast-fails: no-op
|
|
195
|
+
* disposer + warning. The subscription releases when the caller's context
|
|
196
|
+
* unloads.
|
|
197
|
+
*/
|
|
198
|
+
subscribe(pluginCtx, listener, options) {
|
|
199
|
+
const identity = requireComponentIdentity(pluginCtx);
|
|
200
|
+
const plugin = identity.componentId;
|
|
201
|
+
const scope = typeof options?.scope === 'string' ? options.scope : '';
|
|
202
|
+
if (scope === '' || scope.length > OBSERVE_SCOPE_MAX_CHARS) {
|
|
203
|
+
this.ctx.logger.warn(`dsh-tui: messages.observe subscription from plugin "${plugin}" refused — options.scope must be a ` +
|
|
204
|
+
`non-empty string of at most ${OBSERVE_SCOPE_MAX_CHARS} characters (e.g. "session:<id>")`);
|
|
205
|
+
return () => false;
|
|
206
|
+
}
|
|
207
|
+
if (typeof listener !== 'function'
|
|
208
|
+
|| !declaresObserverScope(identity, scope)
|
|
209
|
+
|| !declaresPermission(identity, 'messages.observe.read', scope)
|
|
210
|
+
|| !this.grants().allows({ componentId: identity.componentId, activationId: identity.activationId }, 'messages.observe.read', scope)) {
|
|
211
|
+
this.ctx.logger.warn(`dsh-tui: messages.observe subscription from Component "${plugin}" denied — ` +
|
|
212
|
+
'the scope is not statically declared or the current grant does not cover it; the listener was NOT registered');
|
|
213
|
+
this.ledger()?.record({
|
|
214
|
+
operation: 'bind',
|
|
215
|
+
resource: { kind: 'permission', id: 'messages.observe.read' },
|
|
216
|
+
result: 'failed',
|
|
217
|
+
errorCode: 'PERMISSION_NOT_GRANTED',
|
|
218
|
+
}, pluginCtx);
|
|
219
|
+
return () => false;
|
|
220
|
+
}
|
|
221
|
+
const subscription = {
|
|
222
|
+
plugin,
|
|
223
|
+
identity,
|
|
224
|
+
ownerContext: pluginCtx,
|
|
225
|
+
scope,
|
|
226
|
+
listener,
|
|
227
|
+
chain: Promise.resolve(),
|
|
228
|
+
pendingCallbacks: 0,
|
|
229
|
+
closed: false,
|
|
230
|
+
};
|
|
231
|
+
this.subscriptions.add(subscription);
|
|
232
|
+
this.ledger()?.record({ operation: 'bind', resource: { kind: 'subscription', id: plugin }, result: 'applied' }, pluginCtx);
|
|
233
|
+
const release = () => {
|
|
234
|
+
if (subscription.closed)
|
|
235
|
+
return false;
|
|
236
|
+
this.drop(subscription);
|
|
237
|
+
return true;
|
|
238
|
+
};
|
|
239
|
+
subscription.stopGrantWatch = this.grants().onChange?.(() => {
|
|
240
|
+
if (!this.grants().allows({ componentId: identity.componentId, activationId: identity.activationId }, 'messages.observe.read', scope))
|
|
241
|
+
release();
|
|
242
|
+
});
|
|
243
|
+
try {
|
|
244
|
+
pluginCtx.effect(() => release);
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
// Degraded context: the subscription lives until process end.
|
|
248
|
+
}
|
|
249
|
+
return release;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Publish a session event (channel `session/event` arm). Non-mapped
|
|
253
|
+
* event types return immediately; everything else never throws into the
|
|
254
|
+
* caller — problems are warned, not raised.
|
|
255
|
+
*/
|
|
256
|
+
publish(session, event) {
|
|
257
|
+
try {
|
|
258
|
+
this.publishGuarded(session, event);
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
this.ctx.logger.warn(`dsh-tui: messages.observe publish failed (event dropped): ${error instanceof Error ? error.message : String(error)}`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
publishGuarded(session, event) {
|
|
265
|
+
if (this.subscriptions.size === 0)
|
|
266
|
+
return;
|
|
267
|
+
const record = event;
|
|
268
|
+
const kind = record.type === 'user/message'
|
|
269
|
+
? 'message.received'
|
|
270
|
+
: record.type === 'assistant/message'
|
|
271
|
+
? 'message.sent'
|
|
272
|
+
: undefined;
|
|
273
|
+
if (kind === undefined)
|
|
274
|
+
return;
|
|
275
|
+
if (typeof record.seq !== 'number' || !Number.isInteger(record.seq) || record.seq < 0)
|
|
276
|
+
return;
|
|
277
|
+
const sessionId = session?.id;
|
|
278
|
+
if (typeof sessionId !== 'string' || sessionId === '') {
|
|
279
|
+
this.ctx.logger.warn('dsh-tui: messages.observe publish skipped — the session carries no string id');
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
const data = (record.data ?? {});
|
|
283
|
+
const message = (kind === 'message.sent' ? data.message : data);
|
|
284
|
+
const scope = `session:${sessionId}`;
|
|
285
|
+
// Never truncate a session identity into the schema's scope bound: two
|
|
286
|
+
// distinct long ids can otherwise collapse into one subscription scope.
|
|
287
|
+
if (scope.length > OBSERVE_SCOPE_MAX_CHARS) {
|
|
288
|
+
this.ctx.logger.warn(`dsh-tui: messages.observe publish skipped — the session scope exceeds ${OBSERVE_SCOPE_MAX_CHARS} characters`);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
// C-042 isolation: match subscriptions BEFORE building anything — a
|
|
292
|
+
// subscription for another scope must never see this scope's content.
|
|
293
|
+
const matched = [...this.subscriptions].filter(subscription => !subscription.closed && observerScopeCovers(subscription.scope, scope));
|
|
294
|
+
if (matched.length === 0)
|
|
295
|
+
return;
|
|
296
|
+
// Builds serialize broker-wide so delivery order stays the publish
|
|
297
|
+
// order even though image reads are async (sequence stays monotonic).
|
|
298
|
+
this.buildChain = this.buildChain.then(() => this.buildAndDeliver(kind, sessionId, scope, record.seq, message, matched));
|
|
299
|
+
}
|
|
300
|
+
async buildAndDeliver(kind, sessionId, scope, sequence, message, matched) {
|
|
301
|
+
try {
|
|
302
|
+
const text = this.textOf(message?.content);
|
|
303
|
+
const { blocks, truncated: contentTruncated } = await this.contentOf(message?.content);
|
|
304
|
+
const summary = cleanScalarText(text, OBSERVE_SUMMARY_CELLS);
|
|
305
|
+
// Exact truncation detection: the capped clean differs from the
|
|
306
|
+
// uncapped clean (cells ≠ chars, so length comparison would lie).
|
|
307
|
+
const summaryTruncated = summary !== cleanScalarText(text, Number.MAX_SAFE_INTEGER);
|
|
308
|
+
const envelope = {
|
|
309
|
+
eventType: 'messages.observe',
|
|
310
|
+
eventVersion: '0.15',
|
|
311
|
+
eventId: `${sessionId}:${sequence}`.replace(/[^A-Za-z0-9._:-]/g, '_'),
|
|
312
|
+
scope,
|
|
313
|
+
sequence,
|
|
314
|
+
// Conservative-by-default: every envelope is sensitive until a
|
|
315
|
+
// documented finer classification exists.
|
|
316
|
+
privacyClass: 'sensitive',
|
|
317
|
+
summary,
|
|
318
|
+
payload: {
|
|
319
|
+
kind,
|
|
320
|
+
...(typeof message?.id === 'string' && message.id.length > 0 && message.id.length <= OBSERVE_ID_MAX_CHARS
|
|
321
|
+
? { messageId: message.id }
|
|
322
|
+
: {}),
|
|
323
|
+
author: kind === 'message.received' ? 'user' : 'assistant',
|
|
324
|
+
content: blocks,
|
|
325
|
+
...(summaryTruncated || contentTruncated ? { truncated: true } : {}),
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
// Self-check EVERY envelope with the pinned @dsh-std/messages validator.
|
|
329
|
+
if (this.validatorUnavailable) {
|
|
330
|
+
if (!this.validatorWarned) {
|
|
331
|
+
this.validatorWarned = true;
|
|
332
|
+
this.ctx.logger.warn('dsh-tui: standard message envelope validator unavailable — delivery is fail-closed');
|
|
333
|
+
}
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
try {
|
|
337
|
+
this.validateEnvelope(envelope);
|
|
338
|
+
}
|
|
339
|
+
catch (error) {
|
|
340
|
+
this.ctx.logger.warn(`dsh-tui: messages.observe envelope failed the standard validator and was dropped: ${error instanceof Error ? error.message : String(error)}`);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
for (const subscription of matched) {
|
|
344
|
+
if (subscription.closed)
|
|
345
|
+
continue;
|
|
346
|
+
// Deliver-time grant re-check: a revoked grant RELEASES the
|
|
347
|
+
// subscription (contract cleanup rule), with one warning.
|
|
348
|
+
if (!this.grants().allows({ componentId: subscription.identity.componentId, activationId: subscription.identity.activationId }, 'messages.observe.read', scope)) {
|
|
349
|
+
this.ctx.logger.warn(`dsh-tui: messages.observe subscription of plugin "${subscription.plugin}" released — the grant was revoked`);
|
|
350
|
+
this.drop(subscription);
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
if (subscription.pendingCallbacks >= OBSERVE_CALLBACK_QUEUE_LIMIT) {
|
|
354
|
+
this.ctx.logger.warn(`dsh-tui: messages.observe listener of Component "${subscription.plugin}" reached its ` +
|
|
355
|
+
`${OBSERVE_CALLBACK_QUEUE_LIMIT}-callback queue limit; this envelope was skipped`);
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
subscription.pendingCallbacks += 1;
|
|
359
|
+
const run = subscription.chain.then(async () => {
|
|
360
|
+
if (subscription.closed)
|
|
361
|
+
return;
|
|
362
|
+
const isolated = freezeEnvelope(envelope);
|
|
363
|
+
const result = await runWithBudget(() => subscription.listener(isolated), OBSERVE_CALLBACK_TIMEOUT_MS);
|
|
364
|
+
if (result.kind === 'timeout') {
|
|
365
|
+
this.ctx.logger.warn(`dsh-tui: messages.observe listener of Component "${subscription.plugin}" exceeded ` +
|
|
366
|
+
`${OBSERVE_CALLBACK_TIMEOUT_MS}ms and the subscription was closed`);
|
|
367
|
+
this.drop(subscription);
|
|
368
|
+
}
|
|
369
|
+
else if (result.kind === 'rejected') {
|
|
370
|
+
this.ctx.logger.warn(`dsh-tui: messages.observe listener of Component "${subscription.plugin}" failed; delivery continues: ` +
|
|
371
|
+
`${result.error instanceof Error ? result.error.message : String(result.error)}`);
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
subscription.chain = run.catch(error => {
|
|
375
|
+
this.ctx.logger.warn(`dsh-tui: messages.observe delivery failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
376
|
+
}).finally(() => { subscription.pendingCallbacks -= 1; });
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
catch (error) {
|
|
380
|
+
this.ctx.logger.warn(`dsh-tui: messages.observe publish failed (event dropped): ${error instanceof Error ? error.message : String(error)}`);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
/** Release a subscription exactly once (disposer, ctx unload, revoke). */
|
|
384
|
+
drop(subscription) {
|
|
385
|
+
if (subscription.closed)
|
|
386
|
+
return;
|
|
387
|
+
subscription.closed = true;
|
|
388
|
+
subscription.stopGrantWatch?.();
|
|
389
|
+
subscription.stopGrantWatch = undefined;
|
|
390
|
+
this.subscriptions.delete(subscription);
|
|
391
|
+
this.ledger()?.record({ operation: 'release', resource: { kind: 'subscription', id: subscription.plugin }, result: 'applied' }, subscription.ownerContext);
|
|
392
|
+
}
|
|
393
|
+
/** Join the text blocks of a session message's content (text-only view). */
|
|
394
|
+
textOf(content) {
|
|
395
|
+
if (!Array.isArray(content))
|
|
396
|
+
return '';
|
|
397
|
+
let text = '';
|
|
398
|
+
for (const block of content) {
|
|
399
|
+
if (sourceBlockType(block) !== 'text')
|
|
400
|
+
continue;
|
|
401
|
+
const value = sourceText(block);
|
|
402
|
+
if (value !== undefined)
|
|
403
|
+
text += value;
|
|
404
|
+
}
|
|
405
|
+
return text.trim();
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Map session content blocks to envelope blocks in order (text/image
|
|
409
|
+
* subset). Consecutive text runs join into one block (capped at
|
|
410
|
+
* OBSERVE_CONTENT_MAX_CHARS, pure-text messages keep the exact legacy
|
|
411
|
+
* shape: a single trimmed block); image blocks resolve through the
|
|
412
|
+
* attachments service (soft-probe) with a byte budget. A failed or
|
|
413
|
+
* oversize image becomes NO block plus the truncation mark; zero
|
|
414
|
+
* surviving blocks collapse to a single empty text block (schema
|
|
415
|
+
* minItems 1).
|
|
416
|
+
*/
|
|
417
|
+
async contentOf(content) {
|
|
418
|
+
const blocks = [];
|
|
419
|
+
let pendingText = '';
|
|
420
|
+
let truncated = false;
|
|
421
|
+
const appendText = (value) => {
|
|
422
|
+
const remaining = OBSERVE_CONTENT_MAX_CHARS - pendingText.length;
|
|
423
|
+
if (remaining <= 0) {
|
|
424
|
+
truncated = true;
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
if (value.length > remaining) {
|
|
428
|
+
pendingText += value.slice(0, remaining);
|
|
429
|
+
truncated = true;
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
pendingText += value;
|
|
433
|
+
};
|
|
434
|
+
const flushText = () => {
|
|
435
|
+
const run = pendingText.trim();
|
|
436
|
+
pendingText = '';
|
|
437
|
+
if (run === '')
|
|
438
|
+
return;
|
|
439
|
+
blocks.push({ type: 'text', text: run });
|
|
440
|
+
};
|
|
441
|
+
if (Array.isArray(content)) {
|
|
442
|
+
for (const raw of content) {
|
|
443
|
+
const type = sourceBlockType(raw);
|
|
444
|
+
if (type === 'text') {
|
|
445
|
+
const text = sourceText(raw);
|
|
446
|
+
if (text === undefined) {
|
|
447
|
+
// A declared text block with a non-string body is malformed source
|
|
448
|
+
// data, not the literal string "[object Object]".
|
|
449
|
+
truncated = true;
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
appendText(text);
|
|
453
|
+
continue;
|
|
454
|
+
}
|
|
455
|
+
if (type === 'image') {
|
|
456
|
+
const image = await this.imageBlockOf(raw);
|
|
457
|
+
if (image === undefined) {
|
|
458
|
+
truncated = true;
|
|
459
|
+
continue;
|
|
460
|
+
}
|
|
461
|
+
flushText();
|
|
462
|
+
blocks.push(image);
|
|
463
|
+
continue;
|
|
464
|
+
}
|
|
465
|
+
// Unknown block types are outside the text/image subset: dropped.
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
flushText();
|
|
469
|
+
if (blocks.length === 0)
|
|
470
|
+
blocks.push({ type: 'text', text: '' });
|
|
471
|
+
return { blocks, truncated };
|
|
472
|
+
}
|
|
473
|
+
/** Resolve a session image block (`{type:'image', attachment}` — a
|
|
474
|
+
* REFERENCE, never inline data) to an envelope image block; undefined =
|
|
475
|
+
* drop (unreadable, oversize, bad media type, no attachment store). */
|
|
476
|
+
async imageBlockOf(block) {
|
|
477
|
+
try {
|
|
478
|
+
if (block === null || typeof block !== 'object')
|
|
479
|
+
return undefined;
|
|
480
|
+
const attachment = block.attachment;
|
|
481
|
+
if (attachment === null || attachment === undefined || typeof attachment !== 'object')
|
|
482
|
+
return undefined;
|
|
483
|
+
const mediaType = attachment.mediaType;
|
|
484
|
+
if (typeof mediaType !== 'string' || !OBSERVE_MIME_PATTERN.test(mediaType))
|
|
485
|
+
return undefined;
|
|
486
|
+
const bytes = attachment.bytes;
|
|
487
|
+
if (typeof bytes !== 'number' || !Number.isFinite(bytes) || bytes < 0 || bytes > OBSERVE_IMAGE_MAX_BYTES)
|
|
488
|
+
return undefined;
|
|
489
|
+
const reader = this.ctx.get('attachments');
|
|
490
|
+
if (typeof reader?.readImage !== 'function')
|
|
491
|
+
return undefined;
|
|
492
|
+
// A failing read drops ONLY this image (the envelope survives with the
|
|
493
|
+
// truncation mark) — one corrupt attachment must not nuke the message.
|
|
494
|
+
const stored = await reader.readImage(attachment);
|
|
495
|
+
const data = stored?.data;
|
|
496
|
+
if (!(data instanceof Uint8Array) || data.byteLength > OBSERVE_IMAGE_MAX_BYTES)
|
|
497
|
+
return undefined;
|
|
498
|
+
const base64 = Buffer.from(data).toString('base64');
|
|
499
|
+
if (base64.length > OBSERVE_IMAGE_BASE64_MAX_CHARS)
|
|
500
|
+
return undefined;
|
|
501
|
+
return { type: 'image', data: base64, mimeType: mediaType };
|
|
502
|
+
}
|
|
503
|
+
catch {
|
|
504
|
+
// Source content and attachment service output are untrusted here.
|
|
505
|
+
// Drop only this block and let the enclosing envelope carry truncated.
|
|
506
|
+
return undefined;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The dsh-tui-plugin-host row: the plugin-interop anchor every later
|
|
3
|
+
* contract surface hangs off (storage.local, messages.observe, effect
|
|
4
|
+
* ledger — each lands as a sibling service mounted by THIS row's apply, so
|
|
5
|
+
* the patch surface changed exactly once for the whole v0.15 alignment).
|
|
6
|
+
*
|
|
7
|
+
* What it provides on `ctx.tuiPluginHost`:
|
|
8
|
+
*
|
|
9
|
+
* - `generationId` — the runtime generation id (C-050), a fresh UUID per
|
|
10
|
+
* row activation; ledger records and the Host Descriptor stamp it so
|
|
11
|
+
* effects from different process generations can never be confused.
|
|
12
|
+
* - `grants` — the unified 8-permission live GrantStore (./grants.js).
|
|
13
|
+
* - `hostDescriptor()` — the C-010 Host Descriptor (./host-descriptor.js),
|
|
14
|
+
* built lazily and cached; drifted contracts are dropped fail-closed.
|
|
15
|
+
* - `selfCheck()` — vendored registry + contract-profile violations
|
|
16
|
+
* (definition/profile drift, ten-point incompleteness, parity mismatches).
|
|
17
|
+
* - `registerCommand(pluginCtx, definition)` — the MEDIATED command
|
|
18
|
+
* registration surface (C-041 attribution): stamps each command with the
|
|
19
|
+
* verified Component identity so the invoke checkpoint can enforce per-owner
|
|
20
|
+
* denies (./command-attribution.js). Direct `ctx.get('commands')`
|
|
21
|
+
* registrations stay unattributed — the documented C-070 boundary.
|
|
22
|
+
*
|
|
23
|
+
* Discipline notes:
|
|
24
|
+
*
|
|
25
|
+
* - #183: consumers NEVER get this service via inject — always
|
|
26
|
+
* `ctx.get('tuiPluginHost', false)` soft probing, with the skew warning in
|
|
27
|
+
* plugin.ts covering profile launches on a stale patch.
|
|
28
|
+
* - The D-7 decision gate does NOT depend on this row: the extensions row
|
|
29
|
+
* and the channel each install it with their own GrantStore read, so a
|
|
30
|
+
* missing plugin-host row never relaxes interception gating.
|
|
31
|
+
* - Boot-time self-check failures are logged once here (fail closed happens
|
|
32
|
+
* per-contract at descriptor build time; boot must not die on drifted
|
|
33
|
+
* vendored data).
|
|
34
|
+
*/
|
|
35
|
+
import { Context, Service } from '@deepseek-ai/cordis';
|
|
36
|
+
import type { CommandDefinition } from '@deepseek-ai/dsh-commands';
|
|
37
|
+
import type { HostDescriptor } from '../plugin-spec/types.js';
|
|
38
|
+
import { type GrantStore } from './grants.js';
|
|
39
|
+
import { type HostDescriptorBuild } from './host-descriptor.js';
|
|
40
|
+
import { type DecisionRegistrationOptions } from './decision-guard.js';
|
|
41
|
+
import { type VerifiedComponentIdentity } from './component-identity.js';
|
|
42
|
+
declare module '@deepseek-ai/cordis' {
|
|
43
|
+
interface Context {
|
|
44
|
+
tuiPluginHost: TuiPluginHostRuntime;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** `ctx.tuiPluginHost` — plugin-interop anchor (generation, grants, descriptor). */
|
|
48
|
+
export declare class TuiPluginHostRuntime extends Service {
|
|
49
|
+
/** Runtime generation id (C-050): fresh per activation of this row. */
|
|
50
|
+
readonly generationId: `${string}-${string}-${string}-${string}-${string}`;
|
|
51
|
+
/** Live scoped grant store; every operation observes the current file. */
|
|
52
|
+
readonly grants: GrantStore;
|
|
53
|
+
private descriptorBuild;
|
|
54
|
+
private descriptorCommandsMounted;
|
|
55
|
+
constructor(ctx: Context);
|
|
56
|
+
/**
|
|
57
|
+
* The C-010 Host Descriptor, built lazily and cached while the
|
|
58
|
+
* runtime-dependent commands capability remains unchanged.
|
|
59
|
+
*/
|
|
60
|
+
hostDescriptor(): HostDescriptor;
|
|
61
|
+
/** The full build result (descriptor + dropped coordinates + warnings). */
|
|
62
|
+
describe(): HostDescriptorBuild;
|
|
63
|
+
private build;
|
|
64
|
+
/**
|
|
65
|
+
* Parse, project, validate, negotiate, and bind one activation's Component
|
|
66
|
+
* identity before any mediated runtime capability can be used.
|
|
67
|
+
*/
|
|
68
|
+
admit(pluginCtx: Context, source: string, options?: {
|
|
69
|
+
source?: string;
|
|
70
|
+
activationId?: string;
|
|
71
|
+
}): VerifiedComponentIdentity;
|
|
72
|
+
/**
|
|
73
|
+
* Host-mediated DecisionEvents activation surface. A plugin cannot use a
|
|
74
|
+
* raw `ctx.on` for these points: the verified Component identity, static
|
|
75
|
+
* requirement, scope and current grant are all checked before insertion in
|
|
76
|
+
* the registry. The returned disposer is idempotent and is also owned by
|
|
77
|
+
* the activation so deactivation cannot leave an effect behind.
|
|
78
|
+
*/
|
|
79
|
+
subscribeDecision(pluginCtx: Context, event: string, listener: (payload: Record<string, unknown>) => unknown, options?: DecisionRegistrationOptions): () => boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Mediated command registration (C-041 attribution): registers through
|
|
82
|
+
* the commands service and, on success, stamps the command's owner as
|
|
83
|
+
* the verified Component identity — so the channel's invoke checkpoint
|
|
84
|
+
* can enforce per-owner `commands.invoke` denies on the host-mediated
|
|
85
|
+
* path. Mirrors the honest-identity pattern of storage.open /
|
|
86
|
+
* messages.observe subscribe: there is no parameter to impersonate
|
|
87
|
+
* another plugin. The returned disposer unregisters AND lifts the stamp
|
|
88
|
+
* (idempotent). Duplicates throw the mapped DUPLICATE_CONTRIBUTION_ID
|
|
89
|
+
* error; a missing commands service fails loud (the descriptor's
|
|
90
|
+
* Command contract is excluded in that situation anyway).
|
|
91
|
+
*/
|
|
92
|
+
registerCommand(pluginCtx: Context, definition: CommandDefinition): () => void;
|
|
93
|
+
registerCommand(pluginCtx: Context, contributionId: string, definition: CommandDefinition): () => void;
|
|
94
|
+
/**
|
|
95
|
+
* Vendored registry + contract-profile self-check (C-020 definition/profile
|
|
96
|
+
* pins, C-040 ten-point completeness, coordinate/permission parity). Empty =
|
|
97
|
+
* clean; violations are strings, never thrown.
|
|
98
|
+
*/
|
|
99
|
+
selfCheck(): string[];
|
|
100
|
+
}
|
|
101
|
+
export declare const name = "dsh-tui-plugin-host";
|
|
102
|
+
export declare function apply(ctx: Context): void;
|
|
103
|
+
//# sourceMappingURL=plugin-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-host.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/plugin-host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAEtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAElE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAI7D,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7D,OAAO,EAAiD,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAM9G,OAAO,EAKL,KAAK,2BAA2B,EACjC,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAKL,KAAK,yBAAyB,EAC/B,MAAM,yBAAyB,CAAA;AAEhC,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,aAAa,EAAE,oBAAoB,CAAA;KACpC;CACF;AAED,oFAAoF;AACpF,qBAAa,oBAAqB,SAAQ,OAAO;IAC/C,uEAAuE;IACvE,QAAQ,CAAC,YAAY,sDAAe;IACpC,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;IAE3B,OAAO,CAAC,eAAe,CAAiC;IACxD,OAAO,CAAC,yBAAyB,CAAqB;gBAE1C,GAAG,EAAE,OAAO;IAexB;;;OAGG;IACH,cAAc,IAAI,cAAc;IAIhC,2EAA2E;IAC3E,QAAQ,IAAI,mBAAmB;IAI/B,OAAO,CAAC,KAAK;IAuBb;;;OAGG;IACH,KAAK,CACH,SAAS,EAAE,OAAO,EAClB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAO,GACvD,yBAAyB;IA4B5B;;;;;;OAMG;IACH,iBAAiB,CACf,SAAS,EAAE,OAAO,EAClB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,EACvD,OAAO,GAAE,2BAAgC,GACxC,MAAM,OAAO;IAgDhB;;;;;;;;;;;MAWE;IACF,eAAe,CAAC,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,iBAAiB,GAAG,MAAM,IAAI;IAC9E,eAAe,CAAC,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,GAAG,MAAM,IAAI;IAyFtG;;;;OAIG;IACH,SAAS,IAAI,MAAM,EAAE;CAKtB;AAED,eAAO,MAAM,IAAI,wBAAwB,CAAA;AAEzC,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAaxC"}
|