@deepseek-harness-tui/dsh-tui 0.10.2 → 0.11.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 +175 -123
- package/bin/dsh-tui.js +748 -22
- package/cordis.patch.yml +42 -13
- package/cordis.yml +5 -2
- package/lib/types/activityPrefs.d.ts +24 -0
- package/lib/types/activityPrefs.d.ts.map +1 -1
- package/lib/types/activityPrefs.js +50 -1
- package/lib/types/adapter/channel/session-projection.d.ts.map +1 -1
- package/lib/types/adapter/channel/session-projection.js +2 -0
- package/lib/types/adapter/channel/state.d.ts.map +1 -1
- package/lib/types/adapter/channel/state.js +3 -1
- package/lib/types/adapter/channel/ui-policy.d.ts +4 -1
- package/lib/types/adapter/channel/ui-policy.d.ts.map +1 -1
- package/lib/types/adapter/channel/ui-policy.js +6 -2
- package/lib/types/adapter/kernel/host-facade.d.ts.map +1 -1
- package/lib/types/adapter/kernel/host-facade.js +1 -0
- package/lib/types/adapter/kernel/replay.d.ts.map +1 -1
- package/lib/types/adapter/kernel/replay.js +3 -0
- package/lib/types/adapter/kernel/runtime.d.ts.map +1 -1
- package/lib/types/adapter/kernel/runtime.js +2 -0
- package/lib/types/adapter/kernel/slices/workspace.d.ts.map +1 -1
- package/lib/types/adapter/kernel/slices/workspace.js +1 -0
- package/lib/types/adapter/ports/channel-ui.d.ts +29 -5
- package/lib/types/adapter/ports/channel-ui.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-view.d.ts +66 -12
- package/lib/types/adapter/ports/channel-view.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-workspace.d.ts +23 -0
- package/lib/types/adapter/ports/channel-workspace.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel.d.ts +4 -1
- package/lib/types/adapter/ports/channel.d.ts.map +1 -1
- package/lib/types/adapter/ports/workspace.d.ts +2 -0
- package/lib/types/adapter/ports/workspace.d.ts.map +1 -1
- package/lib/types/adapter/upstream/workspace-driver.d.ts.map +1 -1
- package/lib/types/adapter/upstream/workspace-driver.js +10 -2
- package/lib/types/commands.d.ts.map +1 -1
- package/lib/types/commands.js +1 -0
- package/lib/types/components/ActivityLine.d.ts +7 -2
- package/lib/types/components/ActivityLine.d.ts.map +1 -1
- package/lib/types/components/ActivityLine.js +0 -8
- package/lib/types/components/ContextBarView.d.ts +15 -7
- package/lib/types/components/ContextBarView.d.ts.map +1 -1
- package/lib/types/components/ContextBarView.js +26 -22
- package/lib/types/components/ImagePreviewOverlay.d.ts.map +1 -1
- package/lib/types/components/ImagePreviewOverlay.js +11 -5
- package/lib/types/components/Markdown.d.ts +11 -1
- package/lib/types/components/Markdown.d.ts.map +1 -1
- package/lib/types/components/Markdown.js +20 -2
- package/lib/types/components/MermaidDiagram.d.ts +13 -0
- package/lib/types/components/MermaidDiagram.d.ts.map +1 -0
- package/lib/types/components/MermaidDiagram.js +61 -0
- package/lib/types/components/MessageList.d.ts +26 -1
- package/lib/types/components/MessageList.d.ts.map +1 -1
- package/lib/types/components/MessageList.js +74 -8
- package/lib/types/components/PageMargin.d.ts +1 -1
- package/lib/types/components/PromptInput.d.ts +37 -1
- package/lib/types/components/PromptInput.d.ts.map +1 -1
- package/lib/types/components/PromptInput.js +291 -30
- package/lib/types/components/ScrollbarGutter.d.ts +20 -5
- package/lib/types/components/ScrollbarGutter.d.ts.map +1 -1
- package/lib/types/components/ScrollbarGutter.js +88 -10
- package/lib/types/components/SplitDiffView.d.ts.map +1 -1
- package/lib/types/components/SplitDiffView.js +2 -1
- package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
- package/lib/types/components/StreamingMarkdown.js +30 -28
- package/lib/types/components/SubagentCard.d.ts.map +1 -1
- package/lib/types/components/SubagentCard.js +12 -6
- package/lib/types/components/SubagentDetailScene.d.ts.map +1 -1
- package/lib/types/components/SubagentDetailScene.js +8 -3
- package/lib/types/components/Tooltip.d.ts.map +1 -1
- package/lib/types/components/Tooltip.js +45 -7
- package/lib/types/components/design-system/HintLine.d.ts +1 -2
- package/lib/types/components/design-system/HintLine.d.ts.map +1 -1
- package/lib/types/components/design-system/HintLine.js +1 -2
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts +2 -1
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantThinkingMessage.js +2 -1
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts +2 -2
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantToolUseMessage.js +30 -26
- package/lib/types/components/messages/UserPromptMessage.d.ts.map +1 -1
- package/lib/types/components/messages/UserPromptMessage.js +5 -7
- package/lib/types/components/messages/useImageInspection.d.ts.map +1 -1
- package/lib/types/components/messages/useImageInspection.js +19 -9
- package/lib/types/components/promptDraftCache.d.ts +102 -0
- package/lib/types/components/promptDraftCache.d.ts.map +1 -0
- package/lib/types/components/promptDraftCache.js +76 -0
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts +17 -1
- package/lib/types/components/questions/AskUserQuestionPanel.d.ts.map +1 -1
- package/lib/types/components/questions/AskUserQuestionPanel.js +40 -7
- package/lib/types/components/questions/QuestionMinimizedBar.d.ts +12 -0
- package/lib/types/components/questions/QuestionMinimizedBar.d.ts.map +1 -0
- package/lib/types/components/questions/QuestionMinimizedBar.js +43 -0
- package/lib/types/components/sessions/SessionListRow.d.ts +23 -1
- package/lib/types/components/sessions/SessionListRow.d.ts.map +1 -1
- package/lib/types/components/sessions/SessionListRow.js +52 -5
- package/lib/types/components/workspaces/HomeWorkspaceRow.d.ts +49 -0
- package/lib/types/components/workspaces/HomeWorkspaceRow.d.ts.map +1 -0
- package/lib/types/components/workspaces/HomeWorkspaceRow.js +50 -0
- package/lib/types/dsh-adapter/activity-store.d.ts +221 -0
- package/lib/types/dsh-adapter/activity-store.d.ts.map +1 -0
- package/lib/types/dsh-adapter/activity-store.js +359 -0
- package/lib/types/dsh-adapter/bundled-presets.d.ts +10 -0
- package/lib/types/dsh-adapter/bundled-presets.d.ts.map +1 -0
- package/lib/types/dsh-adapter/bundled-presets.js +80 -0
- package/lib/types/dsh-adapter/channel/action-readiness.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/action-readiness.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/action-readiness.js +3 -0
- package/lib/types/dsh-adapter/channel/agent-view-projection.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/agent-view-projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/agent-view-projection.js +19 -2
- package/lib/types/dsh-adapter/channel/background-action.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/background-action.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/background-action.js +53 -29
- package/lib/types/dsh-adapter/channel/binding-events.d.ts +8 -6
- package/lib/types/dsh-adapter/channel/binding-events.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/binding-events.js +5 -4
- package/lib/types/dsh-adapter/channel/binding.d.ts +19 -2
- package/lib/types/dsh-adapter/channel/binding.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/binding.js +78 -18
- package/lib/types/dsh-adapter/channel/compaction.d.ts +0 -1
- package/lib/types/dsh-adapter/channel/compaction.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/compaction.js +0 -2
- package/lib/types/dsh-adapter/channel/composer-images.d.ts +5 -0
- package/lib/types/dsh-adapter/channel/composer-images.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/composer-images.js +105 -6
- package/lib/types/dsh-adapter/channel/context-bookkeeping.d.ts +8 -0
- package/lib/types/dsh-adapter/channel/context-bookkeeping.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/context-bookkeeping.js +3 -2
- package/lib/types/dsh-adapter/channel/ide-selection.d.ts +58 -0
- package/lib/types/dsh-adapter/channel/ide-selection.d.ts.map +1 -0
- package/lib/types/dsh-adapter/channel/ide-selection.js +226 -0
- package/lib/types/dsh-adapter/channel/input-delivery.d.ts +6 -1
- package/lib/types/dsh-adapter/channel/input-delivery.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/input-delivery.js +9 -1
- package/lib/types/dsh-adapter/channel/local-actions.d.ts +3 -19
- package/lib/types/dsh-adapter/channel/local-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/local-actions.js +2 -1
- package/lib/types/dsh-adapter/channel/model-actions.d.ts +4 -1
- package/lib/types/dsh-adapter/channel/model-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/model-actions.js +82 -6
- package/lib/types/dsh-adapter/channel/model-switch.d.ts +1 -2
- package/lib/types/dsh-adapter/channel/model-switch.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/model-switch.js +49 -31
- package/lib/types/dsh-adapter/channel/projection.d.ts +4 -0
- package/lib/types/dsh-adapter/channel/projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/projection.js +29 -19
- package/lib/types/dsh-adapter/channel/reports.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/reports.js +4 -12
- package/lib/types/dsh-adapter/channel/session-adoption.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/session-adoption.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-adoption.js +1 -0
- package/lib/types/dsh-adapter/channel/session-fork.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-fork.js +26 -2
- package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts +4 -1
- package/lib/types/dsh-adapter/channel/session-live-adoption.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-live-adoption.js +2 -0
- package/lib/types/dsh-adapter/channel/session-metadata.d.ts +10 -0
- package/lib/types/dsh-adapter/channel/session-metadata.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-metadata.js +6 -4
- package/lib/types/dsh-adapter/channel/session-reset.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/session-reset.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-reset.js +0 -1
- package/lib/types/dsh-adapter/channel/session-resume.d.ts +12 -3
- package/lib/types/dsh-adapter/channel/session-resume.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-resume.js +292 -94
- package/lib/types/dsh-adapter/channel/session-rewind.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-rewind.js +34 -16
- package/lib/types/dsh-adapter/channel/session-tree-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/session-tree-actions.js +19 -3
- package/lib/types/dsh-adapter/channel/settings-host.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/settings-host.js +4 -3
- package/lib/types/dsh-adapter/channel/state.d.ts +6 -1
- package/lib/types/dsh-adapter/channel/state.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/state.js +3 -3
- package/lib/types/dsh-adapter/channel/subagent-projection.d.ts +21 -1
- package/lib/types/dsh-adapter/channel/subagent-projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/subagent-projection.js +173 -6
- package/lib/types/dsh-adapter/channel/transcript.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/transcript.js +6 -12
- package/lib/types/dsh-adapter/channel/types.d.ts +6 -1
- package/lib/types/dsh-adapter/channel/types.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/workspace-actions.d.ts +4 -1
- package/lib/types/dsh-adapter/channel/workspace-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/workspace-actions.js +41 -1
- package/lib/types/dsh-adapter/channel.d.ts +1 -1
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +82 -20
- package/lib/types/dsh-adapter/compat/index.d.ts +1 -1
- package/lib/types/dsh-adapter/compat/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/index.js +1 -1
- package/lib/types/dsh-adapter/compat/messages.d.ts +15 -0
- package/lib/types/dsh-adapter/compat/messages.d.ts.map +1 -0
- package/lib/types/dsh-adapter/compat/messages.js +15 -0
- package/lib/types/dsh-adapter/compat/sessionLog.d.ts +18 -0
- package/lib/types/dsh-adapter/compat/sessionLog.d.ts.map +1 -1
- package/lib/types/dsh-adapter/compat/sessionLog.js +18 -3
- package/lib/types/dsh-adapter/compat/settings.d.ts +35 -0
- package/lib/types/dsh-adapter/compat/settings.d.ts.map +1 -0
- package/lib/types/dsh-adapter/compat/settings.js +57 -0
- package/lib/types/dsh-adapter/compat/shell.d.ts +25 -0
- package/lib/types/dsh-adapter/compat/shell.d.ts.map +1 -0
- package/lib/types/dsh-adapter/compat/shell.js +11 -0
- package/lib/types/dsh-adapter/contract.d.ts +5 -4
- package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
- package/lib/types/dsh-adapter/contract.js +17 -6
- package/lib/types/dsh-adapter/ide-channel.d.ts +224 -0
- package/lib/types/dsh-adapter/ide-channel.d.ts.map +1 -0
- package/lib/types/dsh-adapter/ide-channel.js +556 -0
- package/lib/types/dsh-adapter/index.d.ts +18 -3
- package/lib/types/dsh-adapter/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/index.js +32 -5
- package/lib/types/dsh-adapter/plugin.d.ts +4 -1
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +197 -49
- package/lib/types/dsh-adapter/preset-resolution.d.ts +8 -0
- package/lib/types/dsh-adapter/preset-resolution.d.ts.map +1 -1
- package/lib/types/dsh-adapter/preset-resolution.js +10 -0
- package/lib/types/dsh-adapter/session-mount-heartbeat.d.ts +53 -0
- package/lib/types/dsh-adapter/session-mount-heartbeat.d.ts.map +1 -0
- package/lib/types/dsh-adapter/session-mount-heartbeat.js +100 -0
- package/lib/types/dsh-adapter/sessionTree.d.ts.map +1 -1
- package/lib/types/dsh-adapter/sessionTree.js +3 -2
- package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -1
- package/lib/types/dsh-adapter/settings-sections.js +7 -4
- package/lib/types/dsh-adapter/subagents.d.ts +16 -3
- package/lib/types/dsh-adapter/subagents.d.ts.map +1 -1
- package/lib/types/dsh-adapter/subagents.js +92 -29
- package/lib/types/dsh-adapter/workspaces.d.ts +46 -3
- package/lib/types/dsh-adapter/workspaces.d.ts.map +1 -1
- package/lib/types/dsh-adapter/workspaces.js +116 -0
- package/lib/types/effortPrefs.d.ts +15 -3
- package/lib/types/effortPrefs.d.ts.map +1 -1
- package/lib/types/effortPrefs.js +37 -3
- package/lib/types/history.d.ts +13 -1
- package/lib/types/history.d.ts.map +1 -1
- package/lib/types/history.js +15 -2
- package/lib/types/homePrefs.d.ts +15 -0
- package/lib/types/homePrefs.d.ts.map +1 -0
- package/lib/types/homePrefs.js +53 -0
- package/lib/types/i18n.d.ts +347 -297
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +133 -85
- package/lib/types/ink/colorize.d.ts +10 -0
- package/lib/types/ink/colorize.d.ts.map +1 -1
- package/lib/types/ink/colorize.js +21 -0
- package/lib/types/ink/components/ScrollBox.d.ts.map +1 -1
- package/lib/types/ink/components/ScrollBox.js +12 -1
- package/lib/types/ink/dom.d.ts +1 -0
- package/lib/types/ink/dom.d.ts.map +1 -1
- package/lib/types/ink/hooks/use-copy-on-select.d.ts +5 -1
- package/lib/types/ink/hooks/use-copy-on-select.d.ts.map +1 -1
- package/lib/types/ink/hooks/use-copy-on-select.js +15 -1
- package/lib/types/ink/ink.d.ts.map +1 -1
- package/lib/types/ink/ink.js +36 -1
- package/lib/types/ink/log-update.d.ts.map +1 -1
- package/lib/types/ink/log-update.js +19 -1
- package/lib/types/ink/output.d.ts +10 -1
- package/lib/types/ink/output.d.ts.map +1 -1
- package/lib/types/ink/output.js +109 -17
- package/lib/types/ink/render-border.d.ts +6 -1
- package/lib/types/ink/render-border.d.ts.map +1 -1
- package/lib/types/ink/render-border.js +25 -9
- package/lib/types/ink/render-node-to-output.d.ts.map +1 -1
- package/lib/types/ink/render-node-to-output.js +48 -6
- package/lib/types/ink/renderer.d.ts +6 -0
- package/lib/types/ink/renderer.d.ts.map +1 -1
- package/lib/types/ink/renderer.js +2 -1
- package/lib/types/ink/selection.d.ts +88 -0
- package/lib/types/ink/selection.d.ts.map +1 -1
- package/lib/types/ink/selection.js +164 -0
- package/lib/types/ink/sixel-graphics.d.ts +19 -1
- package/lib/types/ink/sixel-graphics.d.ts.map +1 -1
- package/lib/types/ink/sixel-graphics.js +124 -12
- package/lib/types/ink/terminal-image.d.ts +18 -1
- package/lib/types/ink/terminal-image.d.ts.map +1 -1
- package/lib/types/ink/terminal.d.ts +17 -0
- package/lib/types/ink/terminal.d.ts.map +1 -1
- package/lib/types/ink/terminal.js +20 -1
- package/lib/types/screens/Chat.d.ts +20 -1
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +296 -76
- package/lib/types/screens/SessionSupervisor.d.ts +84 -0
- package/lib/types/screens/SessionSupervisor.d.ts.map +1 -0
- package/lib/types/screens/SessionSupervisor.js +350 -0
- package/lib/types/screens/SessionTree.js +2 -2
- package/lib/types/screens/Settings.d.ts.map +1 -1
- package/lib/types/screens/Settings.js +32 -9
- package/lib/types/screens/StatusLine.d.ts +18 -1
- package/lib/types/screens/StatusLine.d.ts.map +1 -1
- package/lib/types/screens/StatusLine.js +38 -19
- package/lib/types/screens/StatusMetrics.d.ts +79 -22
- package/lib/types/screens/StatusMetrics.d.ts.map +1 -1
- package/lib/types/screens/StatusMetrics.js +153 -88
- package/lib/types/screens/sessionSupervisor/model.d.ts +83 -0
- package/lib/types/screens/sessionSupervisor/model.d.ts.map +1 -0
- package/lib/types/screens/sessionSupervisor/model.js +69 -0
- package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts +120 -0
- package/lib/types/screens/sessionSupervisor/useSessionSupervisor.d.ts.map +1 -0
- package/lib/types/screens/sessionSupervisor/useSessionSupervisor.js +593 -0
- package/lib/types/sessionMounts.d.ts +272 -0
- package/lib/types/sessionMounts.d.ts.map +1 -0
- package/lib/types/sessionMounts.js +706 -0
- package/lib/types/sessions/format.d.ts.map +1 -1
- package/lib/types/sessions/format.js +4 -1
- package/lib/types/sessions/resumeFailure.d.ts +38 -0
- package/lib/types/sessions/resumeFailure.d.ts.map +1 -0
- package/lib/types/sessions/resumeFailure.js +58 -0
- package/lib/types/terminal-utils/mermaid.d.ts +44 -0
- package/lib/types/terminal-utils/mermaid.d.ts.map +1 -0
- package/lib/types/terminal-utils/mermaid.js +83 -0
- package/lib/types/tips.d.ts.map +1 -1
- package/lib/types/tips.js +175 -19
- package/lib/types/tuiDisplayPrefs.d.ts +7 -9
- package/lib/types/tuiDisplayPrefs.d.ts.map +1 -1
- package/lib/types/tuiDisplayPrefs.js +31 -28
- package/lib/types/update.d.ts +61 -0
- package/lib/types/update.d.ts.map +1 -1
- package/lib/types/update.js +194 -0
- package/lib/types/utils/fold-long-lines.d.ts +1 -1
- package/lib/types/utils/fold-long-lines.js +1 -1
- package/lib/types/utils/imageResize.d.ts +90 -0
- package/lib/types/utils/imageResize.d.ts.map +1 -0
- package/lib/types/utils/imageResize.js +272 -0
- package/lib/types/utils/keymap.d.ts +5 -1
- package/lib/types/utils/keymap.d.ts.map +1 -1
- package/lib/types/utils/keymap.js +23 -0
- package/lib/types/working-activity.d.ts +10 -9
- package/lib/types/working-activity.d.ts.map +1 -1
- package/lib/types/working-activity.js +17 -10
- package/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/@deepseek-harness-tui/dsh-auth/package.json +10 -10
- package/package.json +126 -105
- package/presets/liangshen/.dsh-tui-managed.json +1 -1
- package/presets/liangshen/agent.cordis.yml +15 -0
- package/lib/types/components/design-system/KeyboardShortcutHint.d.ts +0 -19
- package/lib/types/components/design-system/KeyboardShortcutHint.d.ts.map +0 -1
- package/lib/types/components/design-system/KeyboardShortcutHint.js +0 -14
- package/lib/types/dsh-adapter/channel/activity.d.ts +0 -20
- package/lib/types/dsh-adapter/channel/activity.d.ts.map +0 -1
- package/lib/types/dsh-adapter/channel/activity.js +0 -113
- package/lib/types/screens/AgentView.d.ts +0 -23
- package/lib/types/screens/AgentView.d.ts.map +0 -1
- package/lib/types/screens/AgentView.js +0 -546
- package/lib/types/screens/SessionBrowser.d.ts +0 -42
- package/lib/types/screens/SessionBrowser.d.ts.map +0 -1
- package/lib/types/screens/SessionBrowser.js +0 -911
- package/lib/types/terminal-utils/terminal.d.ts +0 -18
- package/lib/types/terminal-utils/terminal.d.ts.map +0 -1
- package/lib/types/terminal-utils/terminal.js +0 -96
|
@@ -5,6 +5,8 @@ import { readModelPref } from '../../modelPrefs.js';
|
|
|
5
5
|
import { readPresetPref } from '../../presetPrefs.js';
|
|
6
6
|
import { clearResumeTarget, touchAgentViewSession, touchSession } from '../../sessionHistory.js';
|
|
7
7
|
import { t } from '../../i18n.js';
|
|
8
|
+
import { reserveMount } from '../../sessionMounts.js';
|
|
9
|
+
import { mountFailureText } from '../../sessions/resumeFailure.js';
|
|
8
10
|
import { composePreset } from '../presets.js';
|
|
9
11
|
import { attachSessionToWorkspace } from '../workspace.js';
|
|
10
12
|
import { resetSessionProjection } from './session-reset.js';
|
|
@@ -19,6 +21,13 @@ export function createBackgroundCurrentAction(ctx, state, options, deps) {
|
|
|
19
21
|
return { ok: false, reason: 'unavailable' };
|
|
20
22
|
}
|
|
21
23
|
const sessionId = SessionId(randomUUID());
|
|
24
|
+
// Reserve before the factory: from the moment `agents.create` returns this
|
|
25
|
+
// process holds the only write handle on a log the publisher has not named
|
|
26
|
+
// yet, and a peer listing sessions in that gap would be told it is free.
|
|
27
|
+
const reserved = await reserveMount(sessionId);
|
|
28
|
+
if (!reserved.ok && reserved.reason !== 'occupied')
|
|
29
|
+
deps.notify(mountFailureText(reserved), { color: 'warning', timeoutMs: 8000 });
|
|
30
|
+
const reservation = reserved.ok ? reserved.reservation : { settle: () => { }, abandon: () => { } };
|
|
22
31
|
try {
|
|
23
32
|
const composed = await composePreset(ctx, options.configuredPreset ?? readPresetPref());
|
|
24
33
|
const route = await validateModelRoute(ctx.get('llm'), resolveModelRoute({ provider: options.configuredProvider, model: options.configuredModel }, readModelPref(), { provider: options.provider, model: options.model }), { provider: options.provider, model: options.model });
|
|
@@ -30,6 +39,7 @@ export function createBackgroundCurrentAction(ctx, state, options, deps) {
|
|
|
30
39
|
}));
|
|
31
40
|
if (!deps.binding.isCurrent(adoption)) {
|
|
32
41
|
await deps.binding.abandon(handle);
|
|
42
|
+
reservation.abandon();
|
|
33
43
|
return { ok: false, reason: 'failed', error: 'Channel lifetime ended' };
|
|
34
44
|
}
|
|
35
45
|
try {
|
|
@@ -45,39 +55,53 @@ export function createBackgroundCurrentAction(ctx, state, options, deps) {
|
|
|
45
55
|
// agent; the prepared candidate is abandoned instead.
|
|
46
56
|
if (!deps.binding.isCurrent(adoption)) {
|
|
47
57
|
await deps.binding.abandon(handle);
|
|
58
|
+
reservation.abandon();
|
|
48
59
|
return { ok: false, reason: 'failed', error: 'Channel lifetime ended' };
|
|
49
60
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
61
|
+
let committed = false;
|
|
62
|
+
try {
|
|
63
|
+
const result = deps.binding.adopt(handle, adoption, (previous, disposePrevious) => {
|
|
64
|
+
const previousSessionId = String(previous.agent.session.id);
|
|
65
|
+
if (previous.handle !== undefined) {
|
|
66
|
+
deps.backgroundHandles.set(previousSessionId, previous.handle);
|
|
67
|
+
disposePrevious('park');
|
|
68
|
+
}
|
|
69
|
+
resetSessionProjection(state, deps.rowIds, deps.resetProjector, deps.resetSubagents, deps.resetJobs);
|
|
70
|
+
state.status = handle.agent.status;
|
|
71
|
+
state.agentId = handle.agent.id;
|
|
72
|
+
state.sessionId = handle.agent.session.id;
|
|
73
|
+
state.loadedContext = undefined;
|
|
74
|
+
state.contextWindow = undefined;
|
|
75
|
+
state.effortLevels = undefined;
|
|
76
|
+
state.reasoningEffort = undefined;
|
|
77
|
+
deps.refreshEffortLevels();
|
|
78
|
+
// Reset the input FIFO and pending-decision indicators BEFORE the first
|
|
79
|
+
// emit (main's bind → clear → refresh order).
|
|
80
|
+
deps.clearStagedImages();
|
|
81
|
+
deps.bindAgent();
|
|
82
|
+
deps.refreshCommands();
|
|
83
|
+
void deps.refreshLoadedContext();
|
|
84
|
+
void deps.refreshSkillCommands();
|
|
85
|
+
clearResumeTarget();
|
|
86
|
+
touchSession(handle.agent.id);
|
|
87
|
+
touchAgentViewSession(previousSessionId);
|
|
88
|
+
touchAgentViewSession(String(handle.agent.id));
|
|
89
|
+
deps.notifySessionSwitched('background', String(handle.agent.id), previousSessionId);
|
|
90
|
+
deps.notifyAgentView();
|
|
91
|
+
return { ok: true, backgroundedSessionId: previousSessionId };
|
|
92
|
+
});
|
|
93
|
+
committed = true;
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
if (committed)
|
|
98
|
+
reservation.settle();
|
|
99
|
+
else
|
|
100
|
+
reservation.abandon();
|
|
101
|
+
}
|
|
79
102
|
}
|
|
80
103
|
catch (error) {
|
|
104
|
+
reservation.abandon();
|
|
81
105
|
const message = error instanceof Error ? error.message : String(error);
|
|
82
106
|
deps.notify(t('agentview-dispatch-failed', { err: message }), { color: 'error', timeoutMs: 8000 });
|
|
83
107
|
return { ok: false, reason: 'failed', error: message };
|
|
@@ -16,12 +16,12 @@ export declare function createBindingEvents(ctx: Context, deps: {
|
|
|
16
16
|
owner: ChannelOwner;
|
|
17
17
|
binding: ChannelBinding;
|
|
18
18
|
state: ChannelState;
|
|
19
|
-
activity
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
/** Read the activity projection's current value for a freshly bound session.
|
|
20
|
+
* A projection value only arrives when it changes, so a resumed or
|
|
21
|
+
* reattached session needs this read to show its line before the next event.
|
|
22
|
+
* The line's semantics live in the working-activity plugin: this app folds
|
|
23
|
+
* nothing itself and forwards no events. */
|
|
24
|
+
seedActivity?(session: unknown): void;
|
|
25
25
|
inputConvergence: InputConvergence;
|
|
26
26
|
selection: ModelSelectionRef;
|
|
27
27
|
modelActions: {
|
|
@@ -36,6 +36,7 @@ export declare function createBindingEvents(ctx: Context, deps: {
|
|
|
36
36
|
subagents: {
|
|
37
37
|
onSessionEvent(session: unknown, event: unknown): boolean;
|
|
38
38
|
onStreamFrame?(agent: unknown, frame: AssistantStreamFrame): boolean;
|
|
39
|
+
onParentEvent?(event: unknown): void;
|
|
39
40
|
onStart(info: {
|
|
40
41
|
id: string;
|
|
41
42
|
runId?: string;
|
|
@@ -44,6 +45,7 @@ export declare function createBindingEvents(ctx: Context, deps: {
|
|
|
44
45
|
}): void;
|
|
45
46
|
onEnd(info: {
|
|
46
47
|
id: string;
|
|
48
|
+
runId?: string;
|
|
47
49
|
stopReason: string;
|
|
48
50
|
lastAssistantMessage?: unknown[];
|
|
49
51
|
}): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"binding-events.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/binding-events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AACrF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE;IACtD,KAAK,EAAE,YAAY,CAAA;IACnB,OAAO,EAAE,cAAc,CAAA;IACvB,KAAK,EAAE,YAAY,CAAA;IACnB
|
|
1
|
+
{"version":3,"file":"binding-events.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/binding-events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AACrF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE;IACtD,KAAK,EAAE,YAAY,CAAA;IACnB,OAAO,EAAE,cAAc,CAAA;IACvB,KAAK,EAAE,YAAY,CAAA;IACnB;;;;iDAI6C;IAC7C,YAAY,CAAC,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IACrC,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,SAAS,EAAE,iBAAiB,CAAA;IAC5B,YAAY,EAAE;QAAE,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;QAAC,SAAS,EAAE,iBAAiB,CAAA;KAAE,CAAA;IACrF,WAAW,EAAE;QAAE,WAAW,IAAI,IAAI,CAAC;QAAC,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAA;KAAE,CAAA;IAC5F,SAAS,EAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAA;IACrD,SAAS,EAAE;QAAE,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;QAAC,aAAa,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC;QAAC,aAAa,CAAC,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;QAAC,OAAO,CAAC,IAAI,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,OAAO,CAAA;SAAE,GAAG,IAAI,CAAC;QAAC,KAAK,CAAC,IAAI,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAC;YAAC,oBAAoB,CAAC,EAAE,OAAO,EAAE,CAAA;SAAE,GAAG,IAAI,CAAA;KAAE,CAAA;IACrX,SAAS,EAAE;QAAE,QAAQ,IAAI,IAAI,CAAA;KAAE,CAAA;IAC/B,eAAe,CAAC,EAAE;QAAE,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAA;KAAE,CAAA;IACrE;;;sCAGkC;IAClC,gBAAgB,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3C;gBAYkB,IAAI;EAiItB"}
|
|
@@ -22,7 +22,7 @@ export function createBindingEvents(ctx, deps) {
|
|
|
22
22
|
deps.state.agentBindingGeneration = deps.binding.bind();
|
|
23
23
|
deps.inputConvergence.cancelInFlight = false;
|
|
24
24
|
deps.inputConvergence.interruptSeq += 1;
|
|
25
|
-
deps.
|
|
25
|
+
deps.seedActivity?.(deps.binding.agent.session);
|
|
26
26
|
deps.modelActions.selection.current = undefined;
|
|
27
27
|
deps.modelActions.selection.assembled = undefined;
|
|
28
28
|
if (deps.binding.agent.options?.model === undefined && deps.state.provider !== '' && deps.state.model !== '') {
|
|
@@ -80,7 +80,6 @@ export function createBindingEvents(ctx, deps) {
|
|
|
80
80
|
if (!current() || subject !== capture.agent)
|
|
81
81
|
return;
|
|
82
82
|
deps.state.status = status;
|
|
83
|
-
deps.activity.onAgentStatus(status);
|
|
84
83
|
if (status === 'idle')
|
|
85
84
|
reconcileRetiredProjection('idle');
|
|
86
85
|
deps.state.emit();
|
|
@@ -89,7 +88,6 @@ export function createBindingEvents(ctx, deps) {
|
|
|
89
88
|
if (!current() || subject !== capture.agent)
|
|
90
89
|
return;
|
|
91
90
|
deps.state.status = 'disposed';
|
|
92
|
-
deps.activity.stop();
|
|
93
91
|
reconcileRetiredProjection('disposed');
|
|
94
92
|
deps.state.emit();
|
|
95
93
|
});
|
|
@@ -125,7 +123,10 @@ export function createBindingEvents(ctx, deps) {
|
|
|
125
123
|
if (!isMainSession)
|
|
126
124
|
return;
|
|
127
125
|
deps.messageObserver?.publish(subject, event);
|
|
128
|
-
|
|
126
|
+
// Parent-log discovery events (`subagent/catalog`, workflow member
|
|
127
|
+
// edges) reach the dashboard through the same firehose; they are not
|
|
128
|
+
// transcript rows and render below remains untouched by them.
|
|
129
|
+
deps.subagents.onParentEvent?.(event);
|
|
129
130
|
deps.modeActions.onSessionEvent(subject, event);
|
|
130
131
|
deps.projector.renderEvent(event);
|
|
131
132
|
if (event.type === 'assistant/chunk')
|
|
@@ -24,10 +24,27 @@ export declare function createChannelBinding(initial: Agent, handle: AgentHandle
|
|
|
24
24
|
readonly generation: number;
|
|
25
25
|
capture(): BindingCapture;
|
|
26
26
|
isCurrent(capture: BindingCapture): boolean;
|
|
27
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Create a candidate without giving it authority over the live binding.
|
|
29
|
+
*
|
|
30
|
+
* When the capture went stale the candidate is closed and the rejection
|
|
31
|
+
* WAITS for that close. The caller's `abandon(handle)` can no longer see the
|
|
32
|
+
* handle — it was never in `pending` — so waiting here is the only way the
|
|
33
|
+
* handle is known to have stopped writing before the caller gives its
|
|
34
|
+
* ledger reservation back.
|
|
35
|
+
*/
|
|
28
36
|
prepare(capture: BindingCapture, create: () => Promise<AgentHandle>): Promise<AgentHandle>;
|
|
29
|
-
/**
|
|
37
|
+
/**
|
|
38
|
+
* Dispose an uncommitted candidate exactly once and WAIT for the close.
|
|
39
|
+
*
|
|
40
|
+
* Waiting is the point: callers use this on the path where they are about
|
|
41
|
+
* to give a cross-process ledger reservation back, and that reservation may
|
|
42
|
+
* only be released once the handle has actually stopped writing. A live
|
|
43
|
+
* handle that this cell never owned is inert here.
|
|
44
|
+
*/
|
|
30
45
|
abandon(candidate: AgentHandle): Promise<void>;
|
|
46
|
+
/** A registry may retain an agent while its async handle close drains. */
|
|
47
|
+
waitForDisposal(sessionId: string): Promise<void>;
|
|
31
48
|
/** Perform one explicit synchronous prepared-handle adoption transaction. */
|
|
32
49
|
adopt: <T>(candidate: AgentHandle, capture: BindingCapture, tail: (previous: BindingCommit, disposition: (next: PreviousDisposition) => void) => T) => T;
|
|
33
50
|
/** Perform one explicit synchronous already-live-agent adoption transaction. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"binding.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/binding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAAA;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AAED,KAAK,mBAAmB,GAAG,SAAS,GAAG,MAAM,CAAA;AAE7C;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,GAAG,SAAS,EAAE,KAAK,EAAE,YAAY;;;;
|
|
1
|
+
{"version":3,"file":"binding.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/binding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAAA;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AAED,KAAK,mBAAmB,GAAG,SAAS,GAAG,MAAM,CAAA;AAE7C;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,GAAG,SAAS,EAAE,KAAK,EAAE,YAAY;;;;eAsM1F,cAAc;uBACN,cAAc;IAEjC;;;;;;;;OAQG;qBACoB,cAAc,UAAU,MAAM,OAAO,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;IAkBhG;;;;;;;OAOG;uBACsB,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpD,0EAA0E;+BACzC,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvD,6EAA6E;YA7JhE,CAAC,aACH,WAAW,WACb,cAAc,QACjB,CAAC,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,KAAK,CAAC,KACrF,CAAC;IA2JF,gFAAgF;eAlGhE,CAAC,SACV,KAAK,cACA,WAAW,GAAG,SAAS,QAC7B,CAAC,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,KAAK,CAAC,KACrF,CAAC;;uBA4GiB,MAAM,IAAI;qCAvNS,MAAM,IAAI,KAAG,OAAO;EA0N7D;AAED,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAA"}
|
|
@@ -14,17 +14,46 @@ export function createChannelBinding(initial, handle, owner) {
|
|
|
14
14
|
let subscriptions = [];
|
|
15
15
|
let handoff;
|
|
16
16
|
const pending = new Map();
|
|
17
|
-
|
|
17
|
+
/**
|
|
18
|
+
* The in-flight (or finished) close of a handle this cell owns, keyed by the
|
|
19
|
+
* handle. A Promise rather than a "has it started" flag, because the callers
|
|
20
|
+
* that matter need to know when the handle has actually STOPPED writing: a
|
|
21
|
+
* ledger reservation is only safe to give back after that, and a second
|
|
22
|
+
* `dispose()` must not start a parallel close.
|
|
23
|
+
*/
|
|
24
|
+
const closing = new WeakMap();
|
|
25
|
+
const closingSessions = new Map();
|
|
26
|
+
/** Close `candidate` exactly once; the result resolves however it ends. */
|
|
18
27
|
const dispose = (candidate) => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
28
|
+
const started = closing.get(candidate);
|
|
29
|
+
if (started !== undefined)
|
|
30
|
+
return started;
|
|
31
|
+
// Kicked off SYNCHRONOUSLY: revocation is part of a synchronous transaction
|
|
32
|
+
// boundary, and a caller that abandons a candidate may check it right away.
|
|
33
|
+
// Only the waiting is deferred, never the call.
|
|
34
|
+
let close;
|
|
35
|
+
try {
|
|
36
|
+
close = Promise.resolve(candidate.dispose()).catch(() => undefined);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
close = Promise.resolve();
|
|
40
|
+
}
|
|
41
|
+
closing.set(candidate, close);
|
|
42
|
+
const id = String(candidate.agent.session.id);
|
|
43
|
+
closingSessions.set(id, close);
|
|
44
|
+
void close.then(() => {
|
|
45
|
+
if (closingSessions.get(id) === close)
|
|
46
|
+
closingSessions.delete(id);
|
|
47
|
+
});
|
|
48
|
+
return close;
|
|
23
49
|
};
|
|
24
50
|
const disposePending = (candidate) => {
|
|
25
|
-
if (
|
|
26
|
-
return;
|
|
27
|
-
|
|
51
|
+
if (pending.delete(candidate))
|
|
52
|
+
return dispose(candidate);
|
|
53
|
+
// Already un-pended (a revocation path took it out from under the caller):
|
|
54
|
+
// hand back the close that is already running, so a caller that HAS to
|
|
55
|
+
// wait — one about to give a ledger reservation back — still can.
|
|
56
|
+
return closing.get(candidate);
|
|
28
57
|
};
|
|
29
58
|
const clearSubscriptions = (afterEach) => {
|
|
30
59
|
const active = subscriptions.splice(0);
|
|
@@ -49,23 +78,33 @@ export function createChannelBinding(initial, handle, owner) {
|
|
|
49
78
|
return failure;
|
|
50
79
|
};
|
|
51
80
|
const isCaptureCurrent = (capture) => owner.current() && capture.agent === currentAgent && capture.generation === generation;
|
|
81
|
+
/**
|
|
82
|
+
* Start a close without waiting for it. The callers below are synchronous
|
|
83
|
+
* transaction boundaries — they must not turn into awaits — but the close
|
|
84
|
+
* itself stays observable through {@link dispose}, so a caller that DOES have
|
|
85
|
+
* to wait (an `abandon` handing a ledger reservation back) still can.
|
|
86
|
+
*/
|
|
87
|
+
const startClose = (close) => {
|
|
88
|
+
void close;
|
|
89
|
+
};
|
|
52
90
|
const assertPrepared = (candidate, capture) => {
|
|
53
91
|
if (pending.get(candidate) !== capture || !isCaptureCurrent(capture)) {
|
|
54
|
-
disposePending(candidate);
|
|
92
|
+
startClose(disposePending(candidate));
|
|
55
93
|
throw new Error('dsh-tui: Channel binding changed before adoption');
|
|
56
94
|
}
|
|
57
95
|
};
|
|
58
96
|
const settlePrevious = (previous, disposition) => {
|
|
59
97
|
// Parking deliberately transfers ownership to the caller's background
|
|
60
98
|
// ledger. Disposal is centralised here so no adoption tail can double-call
|
|
61
|
-
// an old handle while its transaction is being revoked.
|
|
99
|
+
// an old handle while its transaction is being revoked. Neither path waits:
|
|
100
|
+
// an ordinary session switch must not block on the handle it just left.
|
|
62
101
|
if (disposition === 'dispose' && previous.handle !== undefined && previous.handle !== currentHandle) {
|
|
63
|
-
dispose(previous.handle);
|
|
102
|
+
startClose(dispose(previous.handle));
|
|
64
103
|
}
|
|
65
104
|
};
|
|
66
105
|
owner.own(clearSubscriptions);
|
|
67
106
|
owner.own(() => { for (const candidate of [...pending.keys()])
|
|
68
|
-
disposePending(candidate); });
|
|
107
|
+
startClose(disposePending(candidate)); });
|
|
69
108
|
const adopt = (candidate, capture, tail) => {
|
|
70
109
|
if (handoff !== undefined) {
|
|
71
110
|
// Mark the outer transaction superseded as well as rejecting this one;
|
|
@@ -120,7 +159,7 @@ export function createChannelBinding(initial, handle, owner) {
|
|
|
120
159
|
if (currentHandle === candidate) {
|
|
121
160
|
currentHandle = undefined;
|
|
122
161
|
}
|
|
123
|
-
dispose(candidate);
|
|
162
|
+
startClose(dispose(candidate));
|
|
124
163
|
owner.dispose();
|
|
125
164
|
throw error;
|
|
126
165
|
}
|
|
@@ -185,27 +224,48 @@ export function createChannelBinding(initial, handle, owner) {
|
|
|
185
224
|
get generation() { return generation; },
|
|
186
225
|
capture() { return { agent: currentAgent, generation }; },
|
|
187
226
|
isCurrent(capture) { return isCaptureCurrent(capture); },
|
|
188
|
-
/**
|
|
227
|
+
/**
|
|
228
|
+
* Create a candidate without giving it authority over the live binding.
|
|
229
|
+
*
|
|
230
|
+
* When the capture went stale the candidate is closed and the rejection
|
|
231
|
+
* WAITS for that close. The caller's `abandon(handle)` can no longer see the
|
|
232
|
+
* handle — it was never in `pending` — so waiting here is the only way the
|
|
233
|
+
* handle is known to have stopped writing before the caller gives its
|
|
234
|
+
* ledger reservation back.
|
|
235
|
+
*/
|
|
189
236
|
async prepare(capture, create) {
|
|
190
237
|
owner.assertActive();
|
|
191
238
|
if (!isCaptureCurrent(capture))
|
|
192
239
|
throw new Error('dsh-tui: Channel binding changed before preparation');
|
|
193
240
|
const candidate = await create();
|
|
194
241
|
if (!isCaptureCurrent(capture)) {
|
|
195
|
-
dispose(candidate);
|
|
242
|
+
await dispose(candidate);
|
|
196
243
|
throw new Error('dsh-tui: Channel binding changed during preparation');
|
|
197
244
|
}
|
|
198
245
|
pending.set(candidate, capture);
|
|
199
246
|
// Owner disposal may synchronously occur through embedding hooks while
|
|
200
247
|
// ownership is registered; verify the pending entry itself as well.
|
|
201
248
|
if (!isCaptureCurrent(capture) || pending.get(candidate) !== capture) {
|
|
202
|
-
disposePending(candidate);
|
|
249
|
+
await disposePending(candidate);
|
|
203
250
|
throw new Error('dsh-tui: Channel binding changed during preparation');
|
|
204
251
|
}
|
|
205
252
|
return candidate;
|
|
206
253
|
},
|
|
207
|
-
/**
|
|
208
|
-
|
|
254
|
+
/**
|
|
255
|
+
* Dispose an uncommitted candidate exactly once and WAIT for the close.
|
|
256
|
+
*
|
|
257
|
+
* Waiting is the point: callers use this on the path where they are about
|
|
258
|
+
* to give a cross-process ledger reservation back, and that reservation may
|
|
259
|
+
* only be released once the handle has actually stopped writing. A live
|
|
260
|
+
* handle that this cell never owned is inert here.
|
|
261
|
+
*/
|
|
262
|
+
async abandon(candidate) {
|
|
263
|
+
await disposePending(candidate);
|
|
264
|
+
},
|
|
265
|
+
/** A registry may retain an agent while its async handle close drains. */
|
|
266
|
+
async waitForDisposal(sessionId) {
|
|
267
|
+
await closingSessions.get(sessionId);
|
|
268
|
+
},
|
|
209
269
|
/** Perform one explicit synchronous prepared-handle adoption transaction. */
|
|
210
270
|
adopt,
|
|
211
271
|
/** Perform one explicit synchronous already-live-agent adoption transaction. */
|
|
@@ -10,7 +10,6 @@ export declare function createManualCompaction(ctx: Context, state: CompactionSt
|
|
|
10
10
|
agent(): Agent;
|
|
11
11
|
withDecisionPending<T>(name: string, pending: Promise<T>): Promise<T>;
|
|
12
12
|
notify: Notify;
|
|
13
|
-
onComplete(): void;
|
|
14
13
|
}): {
|
|
15
14
|
compact: () => void;
|
|
16
15
|
settle: () => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/compaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAIlD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAO9C,KAAK,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,KAAK,GAAG,SAAS,CAAC,CAAA;AACxE,KAAK,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAA;AAEpC,mFAAmF;AACnF,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE;IACJ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,QAAQ,GAAG,KAAK,CAAC,CAAA;IACvD,KAAK,IAAI,KAAK,CAAA;IACd,mBAAmB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IACrE,MAAM,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/compaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAIlD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAO9C,KAAK,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,KAAK,GAAG,SAAS,CAAC,CAAA;AACxE,KAAK,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAA;AAEpC,mFAAmF;AACnF,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE;IACJ,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,QAAQ,GAAG,KAAK,CAAC,CAAA;IACvD,KAAK,IAAI,KAAK,CAAA;IACd,mBAAmB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IACrE,MAAM,EAAE,MAAM,CAAA;CACf;mBAuBmB,IAAI;kBAlBC,OAAO,CAAC,IAAI,CAAC;EAuGvC"}
|
|
@@ -78,8 +78,6 @@ export function createManualCompaction(ctx, state, deps) {
|
|
|
78
78
|
if (!isCurrent())
|
|
79
79
|
return;
|
|
80
80
|
deps.notify(result ? t('compact-done') : t('compact-nothing'));
|
|
81
|
-
if (result)
|
|
82
|
-
deps.onComplete();
|
|
83
81
|
}
|
|
84
82
|
catch (error) {
|
|
85
83
|
if (!isCurrent() || cancelled.has(controller))
|
|
@@ -19,6 +19,11 @@ export declare function firstStaleComposerToken(text: string, ordered: ReadonlyM
|
|
|
19
19
|
export interface ComposerImageLimits {
|
|
20
20
|
readonly maxImageBytes: number;
|
|
21
21
|
readonly maxImagesPerMessage: number;
|
|
22
|
+
/** Per-side intrinsic pixel cap mirrored from the upstream store so the
|
|
23
|
+
* ingress gate can resample before staging (issue #938). */
|
|
24
|
+
readonly maxImageDimension: number;
|
|
25
|
+
/** Total-pixel cap ditto. */
|
|
26
|
+
readonly maxImagePixels: number;
|
|
22
27
|
}
|
|
23
28
|
/** The composer's staged-image capability store plus its draft-binding rules. */
|
|
24
29
|
export interface ComposerImages {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"composer-images.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/composer-images.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"composer-images.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/composer-images.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAMlD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAEhB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EAChB,MAAM,YAAY,CAAA;AAEnB,iEAAiE;AACjE,eAAO,MAAM,oBAAoB,QAAqB,CAAA;AAEtD;6EAC6E;AAC7E,eAAO,MAAM,0BAA0B,QAAsB,CAAA;AAE7D,eAAO,MAAM,sBAAsB,GAAI,WAAW,MAAM,KAAG,MACe,CAAA;AAE1E;;;2EAG2E;AAC3E,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,SAAS,gBAAgB,EAAE,EACjC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,GAC7B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAehB;AAED;;4EAE4E;AAC5E,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GACpC,MAAM,GAAG,SAAS,CAKpB;AAOD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAA;IACpC;iEAC6D;IAC7D,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;IAClC,6BAA6B;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;CAChC;AAED,iFAAiF;AACjF,MAAM,WAAW,cAAc;IAC7B;sEACkE;IAClE,qBAAqB,IAAI,MAAM,CAAA;IAC/B;yEACqE;IACrE,UAAU,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACpD;iFAC6E;IAC7E,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAA;IAC3F,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAA;IACxC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACzC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAAA;IACzD,iBAAiB,IAAI,mBAAmB,GAAG,SAAS,CAAA;IACpD;0EACsE;IACtE,iBAAiB,IAAI,IAAI,CAAA;IACzB,6EAA6E;IAC7E,QAAQ,IAAI,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC,CAAA;IAChE;4DACwD;IACxD,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,gBAAgB,EAAE,GAAG,SAAS,gBAAgB,EAAE,CAAA;IACtG,wEAAwE;IACxE,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,gBAAgB,EAAE,GAAG,SAAS,gBAAgB,EAAE,CAAA;CACnG;AA0BD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,YAAY,EACnB,IAAI,EAAE;IAAE,UAAU,IAAI,MAAM,CAAA;CAAE,GAC7B,cAAc,CAyPhB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { rememberImagePath, transcriptImageFromAttachment } from '../transcript-images.js';
|
|
3
|
+
import { probeImageSize, adaptImageForAdmission, withinDimensionLimits } from '../../utils/imageResize.js';
|
|
3
4
|
import { mentionAttachments } from './mentions.js';
|
|
4
5
|
/** Every visible composer placeholder token, in source order. */
|
|
5
6
|
export const COMPOSER_IMAGE_TOKEN = /\[Image #\d+\]/gu;
|
|
@@ -45,6 +46,24 @@ export function firstStaleComposerToken(text, ordered) {
|
|
|
45
46
|
* content-addressed and durable; this map only connects editable
|
|
46
47
|
* placeholders to them. */
|
|
47
48
|
const STAGED_IMAGE_LIMIT = 128;
|
|
49
|
+
/** Failure text for a refusal the ingress gate can state before the store:
|
|
50
|
+
* every reason except a missing sharp describes an image the deployment
|
|
51
|
+
* would reject anyway, so the paste is refused with the cause named. */
|
|
52
|
+
function admissionFailure(outcome, context) {
|
|
53
|
+
switch (outcome.reason) {
|
|
54
|
+
case 'sharp-missing':
|
|
55
|
+
return context.probe !== null
|
|
56
|
+
? `image is ${context.probe.width}×${context.probe.height} (over ${context.limits.maxImageDimension}px) and sharp is unavailable to resample it`
|
|
57
|
+
: `${context.mediaType} is not accepted by this profile and sharp is unavailable to convert it`;
|
|
58
|
+
case 'animated-unsupported':
|
|
59
|
+
return `resizing or converting this animated image cannot keep its frames (${outcome.detail})`;
|
|
60
|
+
default:
|
|
61
|
+
return `image could not be decoded to resize or convert it (${outcome.detail})`;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/** A store-reported pixel dimension, or the gate's own value when the store
|
|
65
|
+
* reported none (lean attachment fakes in the verify scripts). */
|
|
66
|
+
const positiveOr = (value, fallback) => typeof value === 'number' && value > 0 ? value : fallback;
|
|
48
67
|
/**
|
|
49
68
|
* Owns the editable-composer image capabilities: the session epoch, the
|
|
50
69
|
* capability map, its preview facades and the `[Image #N]` compatibility
|
|
@@ -121,16 +140,78 @@ export function createComposerImages(ctx, owner, deps) {
|
|
|
121
140
|
if (generation !== stagedImageEpoch) {
|
|
122
141
|
throw new Error('the session changed while the image was being staged');
|
|
123
142
|
}
|
|
124
|
-
if (!attachments.imageLimits.mediaTypes.includes(input.mediaType)) {
|
|
125
|
-
throw new Error(`${input.mediaType} images are not accepted by this profile`);
|
|
126
|
-
}
|
|
127
143
|
if (input.data.byteLength > attachments.imageLimits.maxImageBytes) {
|
|
128
144
|
throw new Error(`image exceeds this profile's per-image size limit`);
|
|
129
145
|
}
|
|
146
|
+
// Ingress adaptation (issue #938): the store admits by media type, byte
|
|
147
|
+
// budget and the per-side / total pixel caps, and refuses on all of them
|
|
148
|
+
// when the bytes reach it. Measure and re-encode HERE instead, while the
|
|
149
|
+
// paste can still be explained to the user. Admission is judged against
|
|
150
|
+
// the pair this gate HANDS OVER (the store may normalize further on its
|
|
151
|
+
// own — that step is outside this feature), and both triggers are
|
|
152
|
+
// size-independent:
|
|
153
|
+
// * a source media type the profile does not accept is converted, so a
|
|
154
|
+
// small PNG is never refused while a large one succeeds;
|
|
155
|
+
// * a probe-recognized image inside the caps skips sharp entirely;
|
|
156
|
+
// * an unrecognized format is decoded for measurement (never trusted by
|
|
157
|
+
// byte budget alone — the #432 gap);
|
|
158
|
+
// * with sharp absent the image goes to the store unchanged ONLY while
|
|
159
|
+
// it is still admissible as-is — an accepted format whose size the
|
|
160
|
+
// probe could not prove fits (upstream stays the backstop); a measured
|
|
161
|
+
// oversize, a decode failure, an unaccepted format or a multi-frame
|
|
162
|
+
// image this gate would have to re-encode is reported now instead of
|
|
163
|
+
// becoming a token that dies at save time.
|
|
164
|
+
// The runtime guards keep older attachment fakes (whose imageLimits
|
|
165
|
+
// predate the dimension fields) on the legacy synchronous path.
|
|
166
|
+
const dimensionCap = attachments.imageLimits.maxImageDimension;
|
|
167
|
+
const pixelCap = attachments.imageLimits.maxImagePixels;
|
|
168
|
+
let mediaType = input.mediaType;
|
|
169
|
+
let data = input.data;
|
|
170
|
+
let adapted;
|
|
171
|
+
if (typeof dimensionCap === 'number' && typeof pixelCap === 'number'
|
|
172
|
+
&& Number.isFinite(dimensionCap) && Number.isFinite(pixelCap)) {
|
|
173
|
+
const dimensionLimits = { maxImageDimension: dimensionCap, maxImagePixels: pixelCap };
|
|
174
|
+
const probe = probeImageSize(data);
|
|
175
|
+
const sourceAccepted = attachments.imageLimits.mediaTypes.includes(mediaType);
|
|
176
|
+
// Only a probe-measured oversize is *known* to be refused by the store;
|
|
177
|
+
// an unmeasurable image may well be admissible, which is what keeps the
|
|
178
|
+
// sharp-less degradation a degradation rather than a guess.
|
|
179
|
+
const knownOversize = probe !== null && !withinDimensionLimits(probe, dimensionLimits);
|
|
180
|
+
if (!sourceAccepted || probe === null || knownOversize) {
|
|
181
|
+
const outcome = await adaptImageForAdmission(data, mediaType, dimensionLimits, attachments.imageLimits.mediaTypes);
|
|
182
|
+
if (outcome.kind === 'adapted') {
|
|
183
|
+
// outcome.mediaType comes from the accepted list inside the gate, so
|
|
184
|
+
// it is one of the profile's media types at runtime — narrowing,
|
|
185
|
+
// not trusting.
|
|
186
|
+
mediaType = outcome.mediaType;
|
|
187
|
+
data = outcome.data;
|
|
188
|
+
adapted = outcome;
|
|
189
|
+
if (data.byteLength > attachments.imageLimits.maxImageBytes) {
|
|
190
|
+
throw new Error(`image still exceeds this profile's per-image size limit after resampling`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
else if (outcome.kind === 'unavailable') {
|
|
194
|
+
// Degrade ONLY when the paste is still admissible as-is: an accepted
|
|
195
|
+
// format whose size the probe could not prove fits. Everything else
|
|
196
|
+
// (measured oversize, unaccepted format, decode failure, animation
|
|
197
|
+
// that cannot survive) is a refusal we can state now.
|
|
198
|
+
const degraded = outcome.reason === 'sharp-missing' && sourceAccepted && !knownOversize;
|
|
199
|
+
if (!degraded)
|
|
200
|
+
throw new Error(admissionFailure(outcome, { probe, mediaType, limits: dimensionLimits }));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// What the store will actually see: an accepted media type, inside the
|
|
205
|
+
// byte cap. A media type can still be unaccepted here only when the
|
|
206
|
+
// adaptation did not run (legacy limits) or could not produce one.
|
|
207
|
+
if (!attachments.imageLimits.mediaTypes.includes(mediaType)) {
|
|
208
|
+
throw new Error(`${mediaType} images are not accepted by this profile`);
|
|
209
|
+
}
|
|
130
210
|
// The source path is TUI-side display metadata; the store only sees the
|
|
131
|
-
// fields its contract names.
|
|
211
|
+
// fields its contract names. mediaType/data may be the adapted pair from
|
|
212
|
+
// the ingress gate above.
|
|
132
213
|
const { path, ...stored } = input;
|
|
133
|
-
const attachment = await attachments.saveImage(stored);
|
|
214
|
+
const attachment = await attachments.saveImage({ ...stored, mediaType, data });
|
|
134
215
|
// A session change (/new, resume, rewind, model switch, background)
|
|
135
216
|
// cleared the maps while the save was in flight: the durable object is
|
|
136
217
|
// harmless, but the OLD session's capability must not reach the new one.
|
|
@@ -151,7 +232,23 @@ export function createComposerImages(ctx, owner, deps) {
|
|
|
151
232
|
break;
|
|
152
233
|
deleteStagedImage(oldest);
|
|
153
234
|
}
|
|
154
|
-
|
|
235
|
+
// The adjustment travels with the capability so the composer can say what
|
|
236
|
+
// happened instead of letting a rewritten image reach the store silently.
|
|
237
|
+
// Its numbers come from the STORE's own report, not from what this gate
|
|
238
|
+
// handed over: the store normalizes further (dimensions, and the media type
|
|
239
|
+
// too), and a notice quoting the gate's numbers would contradict the
|
|
240
|
+
// preview card the user is looking at.
|
|
241
|
+
const adjustment = adapted === undefined ? undefined : {
|
|
242
|
+
sourceMediaType: input.mediaType,
|
|
243
|
+
mediaType: attachment.mediaType,
|
|
244
|
+
width: positiveOr(attachment.width, adapted.width),
|
|
245
|
+
height: positiveOr(attachment.height, adapted.height),
|
|
246
|
+
resized: adapted.resized
|
|
247
|
+
|| positiveOr(attachment.width, adapted.width) !== adapted.width
|
|
248
|
+
|| positiveOr(attachment.height, adapted.height) !== adapted.height,
|
|
249
|
+
flattened: adapted.flattened,
|
|
250
|
+
};
|
|
251
|
+
return adjustment === undefined ? { stageId } : { stageId, adjustment };
|
|
155
252
|
};
|
|
156
253
|
return {
|
|
157
254
|
stagedImageGeneration() {
|
|
@@ -195,6 +292,8 @@ export function createComposerImages(ctx, owner, deps) {
|
|
|
195
292
|
return {
|
|
196
293
|
maxImageBytes: limits.maxImageBytes,
|
|
197
294
|
maxImagesPerMessage: limits.maxImagesPerMessage,
|
|
295
|
+
maxImageDimension: limits.maxImageDimension,
|
|
296
|
+
maxImagePixels: limits.maxImagePixels,
|
|
198
297
|
};
|
|
199
298
|
},
|
|
200
299
|
clearStagedImages() {
|
|
@@ -5,6 +5,14 @@ export declare function createContextBookkeeping(state: () => {
|
|
|
5
5
|
tokens: {
|
|
6
6
|
input: number;
|
|
7
7
|
};
|
|
8
|
+
/** Last turn's billed token shape; the honest numerator for the
|
|
9
|
+
* context-low warning (input alone misses cached reads/writes, which
|
|
10
|
+
* resumed sessions replay back at full size). */
|
|
11
|
+
lastUsage: {
|
|
12
|
+
input: number;
|
|
13
|
+
cacheRead: number;
|
|
14
|
+
cacheWrite: number;
|
|
15
|
+
} | undefined;
|
|
8
16
|
pending: PendingMessage[];
|
|
9
17
|
emit(): void;
|
|
10
18
|
}, notify: (text: string, options: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-bookkeeping.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/context-bookkeeping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAElE,+EAA+E;AAC/E,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM;IACX,aAAa,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACzB,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,IAAI,IAAI,IAAI,CAAA;CACb,EACD,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,KAAK,OAAO,EACnF,cAAc,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,EAC3C,mBAAmB,EAAE,MAAM;;;;+
|
|
1
|
+
{"version":3,"file":"context-bookkeeping.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/channel/context-bookkeeping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAElE,+EAA+E;AAC/E,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM;IACX,aAAa,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACzB;;qDAEiD;IACjD,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAA;IAC/E,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,IAAI,IAAI,IAAI,CAAA;CACb,EACD,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,KAAK,OAAO,EACnF,cAAc,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,EAC3C,mBAAmB,EAAE,MAAM;;;;+BAyBK,IAAI;+BAtBJ,IAAI;4BAWL;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAA;KAAE,aAAa,cAAc,CAAC,WAAW,CAAC,KAAG,IAAI;gCAK7G,MAAM,KAAG,IAAI;EAQjD"}
|
|
@@ -3,9 +3,10 @@ export function createContextBookkeeping(state, notify, lowContextText, warningB
|
|
|
3
3
|
const warning = { value: false };
|
|
4
4
|
const checkContextWarning = () => {
|
|
5
5
|
const channel = state();
|
|
6
|
-
if (warning.value || channel.contextWindow === undefined)
|
|
6
|
+
if (warning.value || channel.contextWindow === undefined || channel.lastUsage === undefined)
|
|
7
7
|
return;
|
|
8
|
-
const
|
|
8
|
+
const used = channel.lastUsage.input + channel.lastUsage.cacheRead + channel.lastUsage.cacheWrite;
|
|
9
|
+
const remaining = channel.contextWindow - used;
|
|
9
10
|
if (remaining >= warningBufferTokens)
|
|
10
11
|
return;
|
|
11
12
|
warning.value = true;
|