@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,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Managed plugin dialogs — the pi `ctx.ui.select/confirm/input` seam for
|
|
3
|
+
* dsh-TUI. Plugins hand the HOST a declarative request; the TUI renders the
|
|
4
|
+
* dialog in its own chrome (next to the approval panel), owns the keyboard,
|
|
5
|
+
* and settles the plugin's promise with the user's answer. Plugins never
|
|
6
|
+
* touch the TTY themselves.
|
|
7
|
+
*
|
|
8
|
+
* Split in two, mirroring QuestionStore/ApprovalStore:
|
|
9
|
+
*
|
|
10
|
+
* - {@link TuiDialogStore} — cordis-free queue + snapshot. The chat screen
|
|
11
|
+
* subscribes to it and renders the current dialog; tests can drive it
|
|
12
|
+
* without a cordis context.
|
|
13
|
+
* - {@link TuiDialogRuntime} — the cordis service (`ctx.tuiDialogs`)
|
|
14
|
+
* plugins call. Validation of untrusted request data lives here.
|
|
15
|
+
*
|
|
16
|
+
* Queue semantics mirror the approval store: parallel plugin calls park
|
|
17
|
+
* FIFO and surface one at a time. A request settles exactly once — user
|
|
18
|
+
* answer, Esc cancel, caller AbortSignal, caller timeout, or service
|
|
19
|
+
* teardown (`cancelled` outcomes map to `undefined`/`false` returns).
|
|
20
|
+
*/
|
|
21
|
+
import { Context, Service } from '@deepseek-ai/cordis';
|
|
22
|
+
import { cleanScalarText } from './sanitize.js';
|
|
23
|
+
import { activationContext, bindCallerEffect, compositionRoot, concreteService, requirePluginCaller } from './host-access.js';
|
|
24
|
+
/** Render-path strings are untrusted: sanitization (control-char stripping,
|
|
25
|
+
* cell-width caps, scalar-only coercion) lives in ./sanitize.js — the one
|
|
26
|
+
* implementation of the Track A contract. `clean` drops non-scalars to ''
|
|
27
|
+
* so callers take their refuse path instead of rendering "[object Object]". */
|
|
28
|
+
const clean = cleanScalarText;
|
|
29
|
+
const TITLE_CELLS = 120;
|
|
30
|
+
const LABEL_CELLS = 120;
|
|
31
|
+
const MESSAGE_CELLS = 400;
|
|
32
|
+
/** The documented bound of the resolved input text; the panel enforces it
|
|
33
|
+
* on every edit path (typing AND paste) so the promise never resolves with
|
|
34
|
+
* a larger value. */
|
|
35
|
+
export const INPUT_CELLS = 500;
|
|
36
|
+
const MAX_OPTIONS = 100;
|
|
37
|
+
/** Bound a request that omits both signal and timeout. */
|
|
38
|
+
export const DIALOG_DEFAULT_TIMEOUT_MS = 30_000;
|
|
39
|
+
let nextDialogId = 1;
|
|
40
|
+
/**
|
|
41
|
+
* Cordis-free dialog queue. `ask` parks a request; the UI drains one at a
|
|
42
|
+
* time via the snapshot and settles through {@link decide}/{@link cancel}.
|
|
43
|
+
*/
|
|
44
|
+
export class TuiDialogStore {
|
|
45
|
+
listeners = new Set();
|
|
46
|
+
queue = [];
|
|
47
|
+
active = null;
|
|
48
|
+
/** Park a request. The snapshot argument must already be sanitized. */
|
|
49
|
+
ask(snapshot, signal, timeoutMs, owner, bindOwnerEffect) {
|
|
50
|
+
if (signal?.aborted)
|
|
51
|
+
return Promise.resolve(undefined);
|
|
52
|
+
return new Promise((resolve) => {
|
|
53
|
+
let settled = false;
|
|
54
|
+
const pending = {
|
|
55
|
+
// The key is stable per dialog (the panel remounts fresh per
|
|
56
|
+
// request, like ApprovalSnapshot.key) and unique across the queue.
|
|
57
|
+
key: `dlg-${nextDialogId++}`,
|
|
58
|
+
snapshot: undefined,
|
|
59
|
+
settle: () => { },
|
|
60
|
+
onAbort: () => { },
|
|
61
|
+
timer: undefined,
|
|
62
|
+
ownerCleanup: undefined,
|
|
63
|
+
};
|
|
64
|
+
pending.snapshot = { ...snapshot, key: pending.key };
|
|
65
|
+
pending.settle = (value) => {
|
|
66
|
+
if (settled)
|
|
67
|
+
return;
|
|
68
|
+
settled = true;
|
|
69
|
+
if (pending.timer !== undefined)
|
|
70
|
+
clearTimeout(pending.timer);
|
|
71
|
+
signal?.removeEventListener('abort', pending.onAbort);
|
|
72
|
+
const ownerCleanup = pending.ownerCleanup;
|
|
73
|
+
pending.ownerCleanup = undefined;
|
|
74
|
+
ownerCleanup?.();
|
|
75
|
+
resolve(value);
|
|
76
|
+
};
|
|
77
|
+
pending.onAbort = () => {
|
|
78
|
+
// Normal completion also disposes the owner effect. The effect's
|
|
79
|
+
// cleanup must not re-enter the abort path and advance the queue a
|
|
80
|
+
// second time.
|
|
81
|
+
if (settled)
|
|
82
|
+
return;
|
|
83
|
+
// Aborted while queued: drop silently. Aborted while active: close
|
|
84
|
+
// the dialog and advance the queue.
|
|
85
|
+
const index = this.queue.indexOf(pending);
|
|
86
|
+
if (index !== -1)
|
|
87
|
+
this.queue.splice(index, 1);
|
|
88
|
+
if (this.active === pending)
|
|
89
|
+
this.active = null;
|
|
90
|
+
pending.settle(undefined);
|
|
91
|
+
// Must advance (not just emit): with the active dialog gone, the
|
|
92
|
+
// next queued request has to become active — otherwise its Promise
|
|
93
|
+
// parks forever and the UI shows no dialog until an unrelated ask
|
|
94
|
+
// happens to trigger advance.
|
|
95
|
+
this.advance();
|
|
96
|
+
};
|
|
97
|
+
signal?.addEventListener('abort', pending.onAbort, { once: true });
|
|
98
|
+
if (timeoutMs !== undefined && timeoutMs > 0) {
|
|
99
|
+
pending.timer = setTimeout(pending.onAbort, timeoutMs);
|
|
100
|
+
}
|
|
101
|
+
if (owner !== undefined) {
|
|
102
|
+
const bound = bindOwnerEffect?.(pending.onAbort, cleanup => { pending.ownerCleanup = cleanup; }) ?? false;
|
|
103
|
+
if (!bound) {
|
|
104
|
+
// An inactive or untrusted activation must never leave an orphan in
|
|
105
|
+
// the queue. The binder also rolls back partial owner state.
|
|
106
|
+
pending.onAbort();
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
this.queue.push(pending);
|
|
111
|
+
this.advance();
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
/** The dialog the UI should render right now, if any. */
|
|
115
|
+
getSnapshot() {
|
|
116
|
+
return this.active?.snapshot ?? null;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Settle the active dialog with the user's answer. The caller passes the
|
|
120
|
+
* key of the snapshot IT rendered; a mismatched key is a stale callback
|
|
121
|
+
* and ignored. This is not paranoia: ConPTY can deliver one Enter as a
|
|
122
|
+
* same-batch CR+LF pair, firing the old panel's handler twice before
|
|
123
|
+
* React unmounts it — an unkeyed decide would settle the active dialog
|
|
124
|
+
* AND the successor the first call just promoted (one Enter answering two
|
|
125
|
+
* consecutive dialogs).
|
|
126
|
+
*/
|
|
127
|
+
decide(key, value) {
|
|
128
|
+
const pending = this.active;
|
|
129
|
+
if (pending === null || pending.key !== key)
|
|
130
|
+
return;
|
|
131
|
+
this.active = null;
|
|
132
|
+
pending.settle(value);
|
|
133
|
+
this.advance();
|
|
134
|
+
}
|
|
135
|
+
/** Cancel the active dialog (Esc). Keyed like {@link decide}: a stale
|
|
136
|
+
* panel's Esc must not close the successor it never rendered. */
|
|
137
|
+
cancel(key) {
|
|
138
|
+
const pending = this.active;
|
|
139
|
+
if (pending === null || pending.key !== key)
|
|
140
|
+
return;
|
|
141
|
+
this.active = null;
|
|
142
|
+
pending.settle(undefined);
|
|
143
|
+
this.advance();
|
|
144
|
+
}
|
|
145
|
+
/** Settle everything queued + active (teardown): all resolve cancelled. */
|
|
146
|
+
settleAll() {
|
|
147
|
+
const pending = [...this.queue];
|
|
148
|
+
this.queue.length = 0;
|
|
149
|
+
if (this.active !== null)
|
|
150
|
+
pending.push(this.active);
|
|
151
|
+
this.active = null;
|
|
152
|
+
for (const item of pending)
|
|
153
|
+
item.settle(undefined);
|
|
154
|
+
this.emit();
|
|
155
|
+
}
|
|
156
|
+
subscribe(listener) {
|
|
157
|
+
this.listeners.add(listener);
|
|
158
|
+
return () => {
|
|
159
|
+
this.listeners.delete(listener);
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
advance() {
|
|
163
|
+
if (this.active === null && this.queue.length > 0) {
|
|
164
|
+
this.active = this.queue.shift() ?? null;
|
|
165
|
+
}
|
|
166
|
+
this.emit();
|
|
167
|
+
}
|
|
168
|
+
emit() {
|
|
169
|
+
for (const listener of this.listeners)
|
|
170
|
+
listener();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* `ctx.tuiDialogs` — plugin-facing managed dialogs. Every method validates
|
|
175
|
+
* its request (untrusted data on the render path) and resolves with the
|
|
176
|
+
* cancelled value (`undefined`/`false`) rather than throwing when the
|
|
177
|
+
* request is malformed — a dialog must never take the plugin or the TUI
|
|
178
|
+
* down; callers get a logger warning instead.
|
|
179
|
+
*/
|
|
180
|
+
export class TuiDialogRuntime extends Service {
|
|
181
|
+
constructor(ctx) {
|
|
182
|
+
super(ctx, 'tuiDialogs');
|
|
183
|
+
compositionRoot(ctx);
|
|
184
|
+
// Keep queue state off the service object. Cordis invokes public methods
|
|
185
|
+
// through a caller-bound proxy, so JS `#private` fields are unsuitable
|
|
186
|
+
// here; the module-local WeakMap preserves both encapsulation and proxy
|
|
187
|
+
// compatibility.
|
|
188
|
+
const store = new TuiDialogStore();
|
|
189
|
+
hostDialogStores.set(this, store);
|
|
190
|
+
ctx.effect(() => () => store.settleAll());
|
|
191
|
+
}
|
|
192
|
+
/** Cordis traceable services normally provide the caller through `this.ctx`;
|
|
193
|
+
* the explicit overloads below make ownership unambiguous for embedders and
|
|
194
|
+
* tests that retain the service instance directly. */
|
|
195
|
+
callContext(value) {
|
|
196
|
+
const caller = requirePluginCaller(this.ctx, 'tuiDialogs', this);
|
|
197
|
+
if (!Context.is(value))
|
|
198
|
+
return caller;
|
|
199
|
+
// An explicit owner is accepted only when it is the activation that made
|
|
200
|
+
// the service call. Otherwise a plugin could pass the root (or another
|
|
201
|
+
// plugin's context) and leave an orphaned dialog alive after deactivation.
|
|
202
|
+
const canonical = activationContext(value);
|
|
203
|
+
if (canonical === undefined || activationContext(caller) !== canonical) {
|
|
204
|
+
throw new Error('tuiDialogs owner context must be the calling activation');
|
|
205
|
+
}
|
|
206
|
+
return canonical;
|
|
207
|
+
}
|
|
208
|
+
timeoutOf(value) {
|
|
209
|
+
return typeof value === 'number' && Number.isFinite(value) && value > 0
|
|
210
|
+
? Math.min(Math.floor(value), 24 * 60 * 60 * 1000)
|
|
211
|
+
: DIALOG_DEFAULT_TIMEOUT_MS;
|
|
212
|
+
}
|
|
213
|
+
select(ownerOrRequest, explicitRequest) {
|
|
214
|
+
try {
|
|
215
|
+
const owner = this.callContext(ownerOrRequest);
|
|
216
|
+
const request = (explicitRequest ?? ownerOrRequest);
|
|
217
|
+
const title = clean(request?.title, TITLE_CELLS);
|
|
218
|
+
const rawOptions = Array.isArray(request?.options) ? request.options : [];
|
|
219
|
+
const options = [];
|
|
220
|
+
for (const raw of rawOptions.slice(0, MAX_OPTIONS)) {
|
|
221
|
+
// The id is NOT render-path data — it is the opaque token the promise
|
|
222
|
+
// resolves with, matched by the plugin against its own options. Sanitizing
|
|
223
|
+
// it (whitespace collapse, cell truncation) would hand back a DIFFERENT
|
|
224
|
+
// string the plugin cannot look up; validate and keep it verbatim.
|
|
225
|
+
const id = raw?.id;
|
|
226
|
+
const label = clean(raw?.label, LABEL_CELLS);
|
|
227
|
+
if (typeof id !== 'string' || id === '' || !label)
|
|
228
|
+
continue;
|
|
229
|
+
// '' (absent, blank, or a dropped non-scalar) means no description row.
|
|
230
|
+
const description = clean(raw?.description, MESSAGE_CELLS);
|
|
231
|
+
options.push({ id, label, ...(description === '' ? {} : { description }) });
|
|
232
|
+
}
|
|
233
|
+
if (!title || options.length === 0) {
|
|
234
|
+
this.ctx.logger.warn('dsh-tui: tuiDialogs.select called without a title or options; cancelled');
|
|
235
|
+
return Promise.resolve(undefined);
|
|
236
|
+
}
|
|
237
|
+
return dialogStoreFor(this)
|
|
238
|
+
.ask({ kind: 'select', title, options }, request.signal, this.timeoutOf(request.timeoutMs), owner, (disposer, onRegistered) => bindCallerEffect(owner, disposer, onRegistered))
|
|
239
|
+
.then(value => (typeof value === 'string' ? value : undefined));
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
this.ctx.logger.warn('dsh-tui: tuiDialogs.select received malformed data; cancelled');
|
|
243
|
+
return Promise.resolve(undefined);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
confirm(ownerOrRequest, explicitRequest) {
|
|
247
|
+
try {
|
|
248
|
+
const owner = this.callContext(ownerOrRequest);
|
|
249
|
+
const request = (explicitRequest ?? ownerOrRequest);
|
|
250
|
+
const title = clean(request?.title, TITLE_CELLS);
|
|
251
|
+
if (!title) {
|
|
252
|
+
this.ctx.logger.warn('dsh-tui: tuiDialogs.confirm called without a title; cancelled');
|
|
253
|
+
return Promise.resolve(false);
|
|
254
|
+
}
|
|
255
|
+
const message = clean(request?.message, MESSAGE_CELLS);
|
|
256
|
+
const confirmLabel = clean(request?.confirmLabel, LABEL_CELLS);
|
|
257
|
+
const cancelLabel = clean(request?.cancelLabel, LABEL_CELLS);
|
|
258
|
+
return dialogStoreFor(this)
|
|
259
|
+
.ask({
|
|
260
|
+
kind: 'confirm',
|
|
261
|
+
title,
|
|
262
|
+
...(message === '' ? {} : { message }),
|
|
263
|
+
confirmLabel,
|
|
264
|
+
cancelLabel,
|
|
265
|
+
}, request.signal, this.timeoutOf(request.timeoutMs), owner, (disposer, onRegistered) => bindCallerEffect(owner, disposer, onRegistered))
|
|
266
|
+
.then(value => value === true);
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
this.ctx.logger.warn('dsh-tui: tuiDialogs.confirm received malformed data; cancelled');
|
|
270
|
+
return Promise.resolve(false);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
input(ownerOrRequest, explicitRequest) {
|
|
274
|
+
try {
|
|
275
|
+
const owner = this.callContext(ownerOrRequest);
|
|
276
|
+
const request = (explicitRequest ?? ownerOrRequest);
|
|
277
|
+
const title = clean(request?.title, TITLE_CELLS);
|
|
278
|
+
if (!title) {
|
|
279
|
+
this.ctx.logger.warn('dsh-tui: tuiDialogs.input called without a title; cancelled');
|
|
280
|
+
return Promise.resolve(undefined);
|
|
281
|
+
}
|
|
282
|
+
const placeholder = clean(request?.placeholder, LABEL_CELLS);
|
|
283
|
+
const initial = clean(request?.initial, INPUT_CELLS);
|
|
284
|
+
return dialogStoreFor(this)
|
|
285
|
+
.ask({ kind: 'input', title, ...(placeholder === '' ? {} : { placeholder }), initial }, request.signal, this.timeoutOf(request.timeoutMs), owner, (disposer, onRegistered) => bindCallerEffect(owner, disposer, onRegistered))
|
|
286
|
+
.then(value => (typeof value === 'string' ? value : undefined));
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
this.ctx.logger.warn('dsh-tui: tuiDialogs.input received malformed data; cancelled');
|
|
290
|
+
return Promise.resolve(undefined);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Host-only queue accessor. This module is intentionally not a package
|
|
296
|
+
* export; plugins receive only the traceable `tuiDialogs` capability, whose
|
|
297
|
+
* public surface is select/confirm/input.
|
|
298
|
+
*/
|
|
299
|
+
const hostDialogStores = new WeakMap();
|
|
300
|
+
function dialogStoreFor(runtime) {
|
|
301
|
+
const store = hostDialogStores.get(concreteService(runtime));
|
|
302
|
+
if (store === undefined)
|
|
303
|
+
throw new Error('tuiDialogs host store is unavailable');
|
|
304
|
+
return store;
|
|
305
|
+
}
|
|
306
|
+
export function getHostDialogStore(runtime) {
|
|
307
|
+
if (runtime === undefined)
|
|
308
|
+
return undefined;
|
|
309
|
+
try {
|
|
310
|
+
return hostDialogStores.get(concreteService(runtime));
|
|
311
|
+
}
|
|
312
|
+
catch {
|
|
313
|
+
return undefined;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
export default TuiDialogRuntime;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Effect ledger (C-060): an append-only JSONL journal of plugin-visible
|
|
3
|
+
* effects at `~/.dsh-tui/effect-ledger.jsonl`, mounted by the
|
|
4
|
+
* dsh-tui-plugin-host row as `ctx.tuiEffectLedger`.
|
|
5
|
+
*
|
|
6
|
+
* Every record carries the lifecycle triple:
|
|
7
|
+
*
|
|
8
|
+
* - `pluginId` — derived from the verified Component identity bound to the
|
|
9
|
+
* PASSED activation. `'host'` is used for host/root records and
|
|
10
|
+
* `'undeclared'` for a plugin-facing call without a verified identity; a
|
|
11
|
+
* display fiber name is never trusted as authorization identity.
|
|
12
|
+
* - `activationInstance` — stable per cordis fiber for the lifetime of this
|
|
13
|
+
* process (first-seen assignment from a WeakMap), so a hot-reloaded plugin
|
|
14
|
+
* shows up as a NEW instance while all effects of one activation share one
|
|
15
|
+
* id.
|
|
16
|
+
* - `runtimeGenerationId` — the plugin-host row's generation (C-050), so
|
|
17
|
+
* records from different process generations can never be confused.
|
|
18
|
+
*
|
|
19
|
+
* Recording rules:
|
|
20
|
+
*
|
|
21
|
+
* - FAIL-CLOSED ON SCHEMA: every record is validated against the vendored
|
|
22
|
+
* `effect-ledger-record.schema.json` BEFORE it is appended; a record that
|
|
23
|
+
* fails is dropped with a warning, never written. A missing vendored
|
|
24
|
+
* schema suppresses ALL writes (warned once) — the same posture as the
|
|
25
|
+
* messages.observe envelope check. The schema's `additionalProperties:
|
|
26
|
+
* false` is what structurally bans secrets from the ledger: callers
|
|
27
|
+
* cannot smuggle payload fields through.
|
|
28
|
+
* - SEQUENCE: continues across restarts (max sequence in the existing file
|
|
29
|
+
* + 1); corrupt lines are skipped, never rewritten.
|
|
30
|
+
* - NEVER THROWS: recording is observability, not a gate — internal errors
|
|
31
|
+
* (including disk failures) are caught and warned, the caller's path is
|
|
32
|
+
* unaffected.
|
|
33
|
+
*
|
|
34
|
+
* privacyClass: operational — records hold identifiers and error codes,
|
|
35
|
+
* never message content, storage values, or grant-file contents.
|
|
36
|
+
*/
|
|
37
|
+
import { Context, Service } from '@deepseek-ai/cordis';
|
|
38
|
+
/** Default ledger file (JSONL, one record per line). */
|
|
39
|
+
export declare const EFFECT_LEDGER_FILE: string;
|
|
40
|
+
/** Resource kinds recorded by the host's wired emitters. */
|
|
41
|
+
export declare const LEDGER_RESOURCE_KINDS: readonly ["command", "scene", "shortcut", "status", "renderer", "storage-namespace", "subscription", "permission"];
|
|
42
|
+
export type LedgerOperation = 'create' | 'bind' | 'replace' | 'release' | 'cleanup-failed';
|
|
43
|
+
export type LedgerResult = 'applied' | 'pending' | 'failed';
|
|
44
|
+
/** Caller-facing record input; the runtime fills the lifecycle triple. */
|
|
45
|
+
export interface LedgerEntry {
|
|
46
|
+
operation: LedgerOperation;
|
|
47
|
+
resource: {
|
|
48
|
+
kind: string;
|
|
49
|
+
id: string;
|
|
50
|
+
};
|
|
51
|
+
result: LedgerResult;
|
|
52
|
+
/** Contract error code when result is 'failed' (e.g. PERMISSION_NOT_GRANTED). */
|
|
53
|
+
errorCode?: string;
|
|
54
|
+
/** What this record supersedes (operation 'replace'). */
|
|
55
|
+
replaces?: {
|
|
56
|
+
resourceId?: string;
|
|
57
|
+
activationInstance?: string;
|
|
58
|
+
};
|
|
59
|
+
/** `sha256:<64hex>` digest of an opaque value, when a record must reference one. */
|
|
60
|
+
valueDigest?: string;
|
|
61
|
+
}
|
|
62
|
+
declare module '@deepseek-ai/cordis' {
|
|
63
|
+
interface Context {
|
|
64
|
+
tuiEffectLedger: TuiEffectLedgerRuntime;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** `ctx.tuiEffectLedger` — append-only effect journal (C-060). */
|
|
68
|
+
export declare class TuiEffectLedgerRuntime extends Service {
|
|
69
|
+
constructor(ctx: Context, options?: {
|
|
70
|
+
file?: string;
|
|
71
|
+
generationId?: string;
|
|
72
|
+
ledgerSchema?: Record<string, unknown>;
|
|
73
|
+
});
|
|
74
|
+
/**
|
|
75
|
+
* Append one record. `identity` is the caller's own context (plugins pass
|
|
76
|
+
* their plugin ctx through the managed services' optional trailing
|
|
77
|
+
* parameter); omitting it records `undeclared`, never a guess.
|
|
78
|
+
*/
|
|
79
|
+
record(entry: LedgerEntry, identity?: Context): void;
|
|
80
|
+
/** Runtime generation (C-050): options override, else the plugin-host
|
|
81
|
+
* service's id — resolved on first record and cached (the host row mounts
|
|
82
|
+
* before any caller can record). */
|
|
83
|
+
private generation;
|
|
84
|
+
/** Continue numbering after the existing file's max sequence (restart-safe). */
|
|
85
|
+
private resumeSequence;
|
|
86
|
+
private fiberOf;
|
|
87
|
+
private pluginIdOf;
|
|
88
|
+
private activationOf;
|
|
89
|
+
}
|
|
90
|
+
export default TuiEffectLedgerRuntime;
|
|
91
|
+
//# sourceMappingURL=effect-ledger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effect-ledger.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/effect-ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAIH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAOtD,wDAAwD;AACxD,eAAO,MAAM,kBAAkB,QAAwC,CAAA;AAEvE,4DAA4D;AAC5D,eAAO,MAAM,qBAAqB,oHASxB,CAAA;AAEV,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,gBAAgB,CAAA;AAC1F,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAA;AAE3D,0EAA0E;AAC1E,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,eAAe,CAAA;IAC1B,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;IACtC,MAAM,EAAE,YAAY,CAAA;IACpB,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,yDAAyD;IACzD,QAAQ,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC/D,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,eAAe,EAAE,sBAAsB,CAAA;KACxC;CACF;AAWD,kEAAkE;AAClE,qBAAa,sBAAuB,SAAQ,OAAO;gBAE/C,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAO;IA0BhG;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI;IA6DpD;;yCAEqC;IACrC,OAAO,CAAC,UAAU;IAOlB,gFAAgF;IAChF,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,OAAO;IAUf,OAAO,CAAC,UAAU;IAgBlB,OAAO,CAAC,YAAY;CAarB;AA6CD,eAAe,sBAAsB,CAAA"}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Effect ledger (C-060): an append-only JSONL journal of plugin-visible
|
|
3
|
+
* effects at `~/.dsh-tui/effect-ledger.jsonl`, mounted by the
|
|
4
|
+
* dsh-tui-plugin-host row as `ctx.tuiEffectLedger`.
|
|
5
|
+
*
|
|
6
|
+
* Every record carries the lifecycle triple:
|
|
7
|
+
*
|
|
8
|
+
* - `pluginId` — derived from the verified Component identity bound to the
|
|
9
|
+
* PASSED activation. `'host'` is used for host/root records and
|
|
10
|
+
* `'undeclared'` for a plugin-facing call without a verified identity; a
|
|
11
|
+
* display fiber name is never trusted as authorization identity.
|
|
12
|
+
* - `activationInstance` — stable per cordis fiber for the lifetime of this
|
|
13
|
+
* process (first-seen assignment from a WeakMap), so a hot-reloaded plugin
|
|
14
|
+
* shows up as a NEW instance while all effects of one activation share one
|
|
15
|
+
* id.
|
|
16
|
+
* - `runtimeGenerationId` — the plugin-host row's generation (C-050), so
|
|
17
|
+
* records from different process generations can never be confused.
|
|
18
|
+
*
|
|
19
|
+
* Recording rules:
|
|
20
|
+
*
|
|
21
|
+
* - FAIL-CLOSED ON SCHEMA: every record is validated against the vendored
|
|
22
|
+
* `effect-ledger-record.schema.json` BEFORE it is appended; a record that
|
|
23
|
+
* fails is dropped with a warning, never written. A missing vendored
|
|
24
|
+
* schema suppresses ALL writes (warned once) — the same posture as the
|
|
25
|
+
* messages.observe envelope check. The schema's `additionalProperties:
|
|
26
|
+
* false` is what structurally bans secrets from the ledger: callers
|
|
27
|
+
* cannot smuggle payload fields through.
|
|
28
|
+
* - SEQUENCE: continues across restarts (max sequence in the existing file
|
|
29
|
+
* + 1); corrupt lines are skipped, never rewritten.
|
|
30
|
+
* - NEVER THROWS: recording is observability, not a gate — internal errors
|
|
31
|
+
* (including disk failures) are caught and warned, the caller's path is
|
|
32
|
+
* unaffected.
|
|
33
|
+
*
|
|
34
|
+
* privacyClass: operational — records hold identifiers and error codes,
|
|
35
|
+
* never message content, storage values, or grant-file contents.
|
|
36
|
+
*/
|
|
37
|
+
import { appendFileSync, mkdirSync, readFileSync } from 'node:fs';
|
|
38
|
+
import { dirname, join } from 'node:path';
|
|
39
|
+
import { Service } from '@deepseek-ai/cordis';
|
|
40
|
+
import { DATA_DIR } from '../utils/paths.js';
|
|
41
|
+
import { loadSpecData } from '../plugin-spec/registry.js';
|
|
42
|
+
import { check } from '../plugin-spec/schema-check.js';
|
|
43
|
+
import { componentIdentityOf } from './component-identity.js';
|
|
44
|
+
import { compositionRoot, concreteService } from './host-access.js';
|
|
45
|
+
/** Default ledger file (JSONL, one record per line). */
|
|
46
|
+
export const EFFECT_LEDGER_FILE = join(DATA_DIR, 'effect-ledger.jsonl');
|
|
47
|
+
/** Resource kinds recorded by the host's wired emitters. */
|
|
48
|
+
export const LEDGER_RESOURCE_KINDS = [
|
|
49
|
+
'command',
|
|
50
|
+
'scene',
|
|
51
|
+
'shortcut',
|
|
52
|
+
'status',
|
|
53
|
+
'renderer',
|
|
54
|
+
'storage-namespace',
|
|
55
|
+
'subscription',
|
|
56
|
+
'permission',
|
|
57
|
+
];
|
|
58
|
+
/** Strip control chars and cap length so a hostile id cannot break the JSONL
|
|
59
|
+
* line format or blow the schema bounds (JSON.stringify would keep the line
|
|
60
|
+
* intact, but downstream tooling reads these fields raw). */
|
|
61
|
+
function cleanField(value, max, fallback) {
|
|
62
|
+
if (typeof value !== 'string')
|
|
63
|
+
return fallback;
|
|
64
|
+
const cleaned = value.replace(/[\x00-\x1f\x7f-\x9f]/g, '').slice(0, max);
|
|
65
|
+
return cleaned === '' ? fallback : cleaned;
|
|
66
|
+
}
|
|
67
|
+
/** `ctx.tuiEffectLedger` — append-only effect journal (C-060). */
|
|
68
|
+
export class TuiEffectLedgerRuntime extends Service {
|
|
69
|
+
constructor(ctx, options = {}) {
|
|
70
|
+
super(ctx, 'tuiEffectLedger');
|
|
71
|
+
const file = options.file ?? EFFECT_LEDGER_FILE;
|
|
72
|
+
// The generation is resolved LAZILY (per first record): cordis does not
|
|
73
|
+
// make sibling services visible to constructors of plugins mounted later
|
|
74
|
+
// by the same apply(), so a constructor-time probe would always miss the
|
|
75
|
+
// plugin-host service and fall back to 'unknown-generation'.
|
|
76
|
+
const state = {
|
|
77
|
+
hostContext: compositionRoot(ctx),
|
|
78
|
+
file,
|
|
79
|
+
optionsGenerationId: options.generationId,
|
|
80
|
+
generationId: undefined,
|
|
81
|
+
activations: new WeakMap(),
|
|
82
|
+
nextActivation: 1,
|
|
83
|
+
sequence: 0,
|
|
84
|
+
schemaWarned: false,
|
|
85
|
+
ledgerSchema: undefined,
|
|
86
|
+
};
|
|
87
|
+
// `'ledgerSchema' in options` lets a caller force-undefined (fail-closed
|
|
88
|
+
// test seam), same contract as the message observer's envelopeSchema.
|
|
89
|
+
state.ledgerSchema = 'ledgerSchema' in options ? options.ledgerSchema : loadSpecData()?.schemas.ledger;
|
|
90
|
+
state.sequence = resumeSequence(file);
|
|
91
|
+
ledgerStates.set(this, state);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Append one record. `identity` is the caller's own context (plugins pass
|
|
95
|
+
* their plugin ctx through the managed services' optional trailing
|
|
96
|
+
* parameter); omitting it records `undeclared`, never a guess.
|
|
97
|
+
*/
|
|
98
|
+
record(entry, identity) {
|
|
99
|
+
let state;
|
|
100
|
+
try {
|
|
101
|
+
state = ledgerStateFor(this);
|
|
102
|
+
if (state.ledgerSchema === undefined) {
|
|
103
|
+
if (!state.schemaWarned) {
|
|
104
|
+
state.schemaWarned = true;
|
|
105
|
+
state.hostContext.logger.warn('dsh-tui: effect ledger schema unavailable — suppressing all ledger writes (fail-closed)');
|
|
106
|
+
}
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const fiber = this.fiberOf(identity);
|
|
110
|
+
const verified = identity === undefined ? undefined : componentIdentityOf(identity);
|
|
111
|
+
const pluginId = this.pluginIdOf(identity, fiber, verified?.componentId);
|
|
112
|
+
const record = {
|
|
113
|
+
ledgerVersion: '0.15',
|
|
114
|
+
sequence: state.sequence,
|
|
115
|
+
timestamp: new Date().toISOString(),
|
|
116
|
+
pluginId,
|
|
117
|
+
activationInstance: verified?.activationId ?? this.activationOf(fiber, pluginId),
|
|
118
|
+
runtimeGenerationId: this.generation(),
|
|
119
|
+
operation: entry.operation,
|
|
120
|
+
resource: {
|
|
121
|
+
kind: cleanField(entry.resource?.kind, 64, 'unknown'),
|
|
122
|
+
id: cleanField(entry.resource?.id, 128, 'unknown'),
|
|
123
|
+
},
|
|
124
|
+
result: entry.result,
|
|
125
|
+
...(entry.errorCode !== undefined ? { errorCode: cleanField(entry.errorCode, 64, 'UNKNOWN') } : {}),
|
|
126
|
+
...(entry.replaces !== undefined
|
|
127
|
+
? {
|
|
128
|
+
replaces: {
|
|
129
|
+
...(entry.replaces.resourceId !== undefined
|
|
130
|
+
? { resourceId: cleanField(entry.replaces.resourceId, 128, 'unknown') }
|
|
131
|
+
: {}),
|
|
132
|
+
...(entry.replaces.activationInstance !== undefined
|
|
133
|
+
? { activationInstance: cleanField(entry.replaces.activationInstance, 128, 'unknown') }
|
|
134
|
+
: {}),
|
|
135
|
+
},
|
|
136
|
+
}
|
|
137
|
+
: {}),
|
|
138
|
+
...(entry.valueDigest !== undefined ? { valueDigest: entry.valueDigest } : {}),
|
|
139
|
+
};
|
|
140
|
+
// Fail-closed self-check: a record that does not satisfy the vendored
|
|
141
|
+
// schema is DROPPED, not written (the schema's additionalProperties:
|
|
142
|
+
// false is the structural secret ban).
|
|
143
|
+
try {
|
|
144
|
+
check(record, state.ledgerSchema, state.ledgerSchema);
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
state.hostContext.logger.warn(`dsh-tui: effect ledger record dropped (schema: ${error instanceof Error ? error.message : String(error)})`);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
mkdirSync(dirname(state.file), { recursive: true, mode: 0o700 });
|
|
151
|
+
appendFileSync(state.file, `${JSON.stringify(record)}\n`, { mode: 0o600 });
|
|
152
|
+
state.sequence += 1;
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
;
|
|
156
|
+
(state?.hostContext ?? this.ctx).logger.warn('dsh-tui: effect ledger write failed');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/** Runtime generation (C-050): options override, else the plugin-host
|
|
160
|
+
* service's id — resolved on first record and cached (the host row mounts
|
|
161
|
+
* before any caller can record). */
|
|
162
|
+
generation() {
|
|
163
|
+
const state = ledgerStateFor(this);
|
|
164
|
+
if (state.optionsGenerationId !== undefined)
|
|
165
|
+
return state.optionsGenerationId;
|
|
166
|
+
state.generationId ??= state.hostContext.get('tuiPluginHost')?.generationId ?? 'unknown-generation';
|
|
167
|
+
return state.generationId;
|
|
168
|
+
}
|
|
169
|
+
/** Continue numbering after the existing file's max sequence (restart-safe). */
|
|
170
|
+
resumeSequence() {
|
|
171
|
+
return resumeSequence(ledgerStateFor(this).file);
|
|
172
|
+
}
|
|
173
|
+
fiberOf(identity) {
|
|
174
|
+
if (identity === undefined)
|
|
175
|
+
return undefined;
|
|
176
|
+
try {
|
|
177
|
+
const fiber = identity.fiber;
|
|
178
|
+
return typeof fiber === 'object' && fiber !== null ? fiber : undefined;
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
return undefined;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
pluginIdOf(identity, fiber, verifiedComponentId) {
|
|
185
|
+
if (identity === undefined)
|
|
186
|
+
return 'undeclared';
|
|
187
|
+
if (verifiedComponentId !== undefined)
|
|
188
|
+
return cleanField(verifiedComponentId, 128, 'undeclared');
|
|
189
|
+
let name = '';
|
|
190
|
+
try {
|
|
191
|
+
name = typeof identity.fiber?.name === 'string' ? identity.fiber.name : '';
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
name = '';
|
|
195
|
+
}
|
|
196
|
+
// A non-root fiber without a verified Component is intentionally not
|
|
197
|
+
// attributed by its Cordis export name. Names are display metadata and
|
|
198
|
+
// can differ from the manifest identity (or be impersonated).
|
|
199
|
+
if (fiber === undefined || name === '' || name === 'root')
|
|
200
|
+
return 'host';
|
|
201
|
+
return 'undeclared';
|
|
202
|
+
}
|
|
203
|
+
activationOf(fiber, pluginId) {
|
|
204
|
+
// 'host'/'undeclared' are single-tenant identities (one root fiber per
|
|
205
|
+
// process; 'undeclared' has no fiber at all) — the constant instance id
|
|
206
|
+
// is exact; per-fiber ids only matter for plugin fibers.
|
|
207
|
+
if (fiber === undefined || pluginId === 'host' || pluginId === 'undeclared')
|
|
208
|
+
return pluginId;
|
|
209
|
+
const state = ledgerStateFor(this);
|
|
210
|
+
let activation = state.activations.get(fiber);
|
|
211
|
+
if (activation === undefined) {
|
|
212
|
+
activation = `activation-${state.nextActivation++}`;
|
|
213
|
+
state.activations.set(fiber, activation);
|
|
214
|
+
}
|
|
215
|
+
return activation;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
const ledgerStates = new WeakMap();
|
|
219
|
+
function ledgerStateFor(runtime) {
|
|
220
|
+
const state = ledgerStates.get(concreteService(runtime));
|
|
221
|
+
if (state === undefined)
|
|
222
|
+
throw new Error('tuiEffectLedger host state is unavailable');
|
|
223
|
+
return state;
|
|
224
|
+
}
|
|
225
|
+
/** Continue numbering after the existing file's max sequence (restart-safe). */
|
|
226
|
+
function resumeSequence(file) {
|
|
227
|
+
let text;
|
|
228
|
+
try {
|
|
229
|
+
text = readFileSync(file, 'utf8');
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
return 0; // missing file = fresh ledger, not corruption
|
|
233
|
+
}
|
|
234
|
+
let max = -1;
|
|
235
|
+
for (const line of text.split('\n')) {
|
|
236
|
+
if (line.trim() === '')
|
|
237
|
+
continue;
|
|
238
|
+
try {
|
|
239
|
+
const parsed = JSON.parse(line);
|
|
240
|
+
const sequence = parsed.sequence;
|
|
241
|
+
if (typeof sequence === 'number' && Number.isInteger(sequence) && sequence > max)
|
|
242
|
+
max = sequence;
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
// Corrupt line: skip it (never rewritten — the bytes stay for manual
|
|
246
|
+
// recovery, same posture as plugin-storage).
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return max + 1;
|
|
250
|
+
}
|
|
251
|
+
export default TuiEffectLedgerRuntime;
|