@robota-sdk/agent-ui-terminal 3.0.0-beta.100
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/CHANGELOG.md +1204 -0
- package/LICENSE +661 -0
- package/README.md +50 -0
- package/dist/node/index.d.ts +1224 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +33 -0
- package/dist/node/index.js.map +1 -0
- package/package.json +88 -0
- package/src/App.tsx +157 -0
- package/src/AppPresentation.tsx +190 -0
- package/src/AppView.tsx +26 -0
- package/src/BackgroundTaskPanel.tsx +73 -0
- package/src/CjkTextInput.tsx +336 -0
- package/src/ConfirmPrompt.tsx +140 -0
- package/src/ContextWarningBanner.tsx +45 -0
- package/src/ExecutionWorkspaceDetailPane.tsx +85 -0
- package/src/ExecutionWorkspaceSwitcher.tsx +213 -0
- package/src/HistorySearchOverlay.tsx +150 -0
- package/src/InputArea.tsx +338 -0
- package/src/ListPicker.tsx +158 -0
- package/src/MenuSelect.tsx +159 -0
- package/src/MessageList.tsx +308 -0
- package/src/MultiSelectList.tsx +294 -0
- package/src/PendingActionPrompt.tsx +121 -0
- package/src/PermissionPrompt.tsx +236 -0
- package/src/PluginTUI.tsx +258 -0
- package/src/RoleLabel.tsx +72 -0
- package/src/SafeText.tsx +66 -0
- package/src/SessionEventNotices.tsx +27 -0
- package/src/SessionPicker.tsx +92 -0
- package/src/SessionStatusBar.tsx +80 -0
- package/src/SlashAutocomplete.tsx +154 -0
- package/src/StatusBar.tsx +308 -0
- package/src/StreamingIndicator.tsx +145 -0
- package/src/SupervisedSessionView.tsx +872 -0
- package/src/TextPrompt.tsx +112 -0
- package/src/ThemePicker.tsx +366 -0
- package/src/ToolCommandOutput.tsx +48 -0
- package/src/ToolDiffBlock.tsx +44 -0
- package/src/TransportTUI.tsx +166 -0
- package/src/TuiInteractionChannel.ts +530 -0
- package/src/UpdateNotice.tsx +18 -0
- package/src/UsageSummaryEntry.tsx +49 -0
- package/src/WaveText.tsx +70 -0
- package/src/__tests__/ListPicker.test.tsx +188 -0
- package/src/__tests__/MenuSelect.test.tsx +127 -0
- package/src/__tests__/PendingActionPrompt.test.tsx +193 -0
- package/src/__tests__/PluginTUI.test.tsx +167 -0
- package/src/__tests__/SlashAutocomplete.test.tsx +162 -0
- package/src/__tests__/SupervisedSessionView-render.test.tsx +52 -0
- package/src/__tests__/SupervisedSessionView.test.tsx +1112 -0
- package/src/__tests__/TextPrompt.test.tsx +112 -0
- package/src/__tests__/TransportTUI.test.tsx +124 -0
- package/src/__tests__/TuiInteractionChannel.askUser.test.ts +124 -0
- package/src/__tests__/TuiInteractionChannel.display-contract.test.ts +294 -0
- package/src/__tests__/TuiInteractionChannel.lifecycle.test.ts +650 -0
- package/src/__tests__/UpdateNotice.test.tsx +15 -0
- package/src/__tests__/__fixtures__/korean-text.json +17 -0
- package/src/__tests__/abort-after-permission.test.tsx +160 -0
- package/src/__tests__/abort-streaming-e2e.test.tsx +183 -0
- package/src/__tests__/attached-app-session-switch.test.tsx +317 -0
- package/src/__tests__/attention-bell-and-marks.test.ts +144 -0
- package/src/__tests__/autocomplete-editing-keys.test.tsx +127 -0
- package/src/__tests__/background-task-panel-countdown.test.tsx +75 -0
- package/src/__tests__/background-task-panel.test.tsx +98 -0
- package/src/__tests__/background-task-row-format.test.ts +152 -0
- package/src/__tests__/channel-factory-integration.test.ts +150 -0
- package/src/__tests__/checkpoint-store-per-channel.test.ts +81 -0
- package/src/__tests__/cjk-defer-submit.test.tsx +68 -0
- package/src/__tests__/cjk-fallback-render.test.tsx +89 -0
- package/src/__tests__/cjk-text-input-flow.test.ts +187 -0
- package/src/__tests__/cjk-text-input.test.ts +196 -0
- package/src/__tests__/command-handoff-pty-e2e.test.ts +107 -0
- package/src/__tests__/command-output-summary.test.ts +95 -0
- package/src/__tests__/command-result-handler.test.ts +171 -0
- package/src/__tests__/compact-event-bridge.test.ts +20 -0
- package/src/__tests__/confirm-permission-flow.test.ts +149 -0
- package/src/__tests__/confirm-prompt.test.tsx +103 -0
- package/src/__tests__/contextual-keybindings-input.test.tsx +158 -0
- package/src/__tests__/default-tui-cli-adapter-host-settings.test.ts +47 -0
- package/src/__tests__/effort-reaches-the-session.test.ts +41 -0
- package/src/__tests__/execution-workspace-switcher.test.tsx +147 -0
- package/src/__tests__/execution-workspace-view-model.test.ts +94 -0
- package/src/__tests__/external-prompt-notice.test.tsx +100 -0
- package/src/__tests__/fixtures/command-handoff-driver.tsx +114 -0
- package/src/__tests__/fixtures/fake-editor.sh +7 -0
- package/src/__tests__/fixtures/terminal-handoff-driver.tsx +90 -0
- package/src/__tests__/fork-attach.test.tsx +235 -0
- package/src/__tests__/grant-history-reaches-the-session.test.ts +31 -0
- package/src/__tests__/helpers/terminal-profiles.ts +152 -0
- package/src/__tests__/helpers/vt-cursor-interpreter.ts +175 -0
- package/src/__tests__/history-clear-broadcast.test.ts +66 -0
- package/src/__tests__/history-search-overlay.test.tsx +329 -0
- package/src/__tests__/humanize-tool-name.test.ts +30 -0
- package/src/__tests__/input-area-bottom-border.test.tsx +45 -0
- package/src/__tests__/input-area-flow.test.ts +199 -0
- package/src/__tests__/input-area-focus-handoff.test.tsx +77 -0
- package/src/__tests__/interaction-channel-charter.test.ts +13 -0
- package/src/__tests__/key-hint-consistency.test.tsx +249 -0
- package/src/__tests__/key-hint-footer.test.tsx +69 -0
- package/src/__tests__/live-trace-reaches-session.test.ts +14 -0
- package/src/__tests__/message-list-rendering.test.tsx +474 -0
- package/src/__tests__/numbered-selection-chunk.test.tsx +41 -0
- package/src/__tests__/org-policy-reaches-the-channel.test.ts +77 -0
- package/src/__tests__/output-style-reaches-session.test.ts +35 -0
- package/src/__tests__/palette-consistency.test.ts +329 -0
- package/src/__tests__/permission-prompt-arming.test.tsx +153 -0
- package/src/__tests__/permission-prompt-availability.test.tsx +23 -0
- package/src/__tests__/permission-prompt-peer.test.tsx +34 -0
- package/src/__tests__/permission-prompt-requester.test.tsx +34 -0
- package/src/__tests__/product-display-name.test.tsx +79 -0
- package/src/__tests__/prompt-queue.test.tsx +260 -0
- package/src/__tests__/provider-definitions-reach-the-session.test.ts +75 -0
- package/src/__tests__/pty/ask-user-question.ptytest.ts +72 -0
- package/src/__tests__/pty/background-work-switcher.ptytest.ts +53 -0
- package/src/__tests__/pty/behavior-2437-git.ptytest.ts +350 -0
- package/src/__tests__/pty/fixtures/ask-user-question.jsonl +3 -0
- package/src/__tests__/pty/fixtures/replay-conversation.jsonl +4 -0
- package/src/__tests__/pty/fixtures/screen-005-ask-shapes.jsonl +5 -0
- package/src/__tests__/pty/fixtures/screen-005-permission.jsonl +3 -0
- package/src/__tests__/pty/fixtures/screen-006-colors.jsonl +3 -0
- package/src/__tests__/pty/fixtures/screen-2002-themes.jsonl +5 -0
- package/src/__tests__/pty/flag-tui.ptytest.ts +56 -0
- package/src/__tests__/pty/flow-2006-deep-link.ptytest.ts +320 -0
- package/src/__tests__/pty/ime-cursor-tmux.ptytest.ts +211 -0
- package/src/__tests__/pty/ime-cursor.ptytest.ts +187 -0
- package/src/__tests__/pty/isolated-home.ts +97 -0
- package/src/__tests__/pty/org-policy.ptytest.ts +71 -0
- package/src/__tests__/pty/provider-setup.ptytest.ts +61 -0
- package/src/__tests__/pty/pty-driver.ts +155 -0
- package/src/__tests__/pty/replay-conversation.ptytest.ts +68 -0
- package/src/__tests__/pty/screen-005-prompt-footers.ptytest.ts +135 -0
- package/src/__tests__/pty/screen-006-no-color.ptytest.ts +140 -0
- package/src/__tests__/pty/screen-010-scrollback.ptytest.ts +123 -0
- package/src/__tests__/pty/screen-1993-scrollback.ptytest.ts +124 -0
- package/src/__tests__/pty/screen-2002-themes.ptytest.ts +292 -0
- package/src/__tests__/pty/screen-2670-prepark.ptytest.ts +228 -0
- package/src/__tests__/pty/screen-reader-mode.ptytest.ts +228 -0
- package/src/__tests__/pty/session-attach.ptytest.ts +182 -0
- package/src/__tests__/pty/settings-screen.ptytest.ts +49 -0
- package/src/__tests__/pty/spawn-pty.test.ts +120 -0
- package/src/__tests__/pty/spawn-pty.ts +229 -0
- package/src/__tests__/pty/terminal-handoff.ptytest.ts +79 -0
- package/src/__tests__/pty/trust-prompt.ptytest.ts +134 -0
- package/src/__tests__/pty/tui-pty.ptytest.ts +65 -0
- package/src/__tests__/pty-driver-dispose.test.ts +43 -0
- package/src/__tests__/real-cursor-positioning.test.tsx +264 -0
- package/src/__tests__/rename-broadcast-persistence.test.tsx +140 -0
- package/src/__tests__/render-channel-options.test.ts +201 -0
- package/src/__tests__/render-lifecycle.test.ts +36 -0
- package/src/__tests__/render-markdown.test.ts +164 -0
- package/src/__tests__/rendered-markdown-styling.test.tsx +98 -0
- package/src/__tests__/safe-text-boundary.test.tsx +75 -0
- package/src/__tests__/sandbox-reaches-the-session.test.ts +37 -0
- package/src/__tests__/screen-reader-input.test.tsx +106 -0
- package/src/__tests__/screen-reader-labels.test.ts +91 -0
- package/src/__tests__/screen-reader-menus.test.tsx +200 -0
- package/src/__tests__/screen-reader-pacing.test.ts +230 -0
- package/src/__tests__/screen-reader-prepark-echo.test.tsx +200 -0
- package/src/__tests__/screen-reader-render-options.test.ts +262 -0
- package/src/__tests__/screen-reader-stdout.test.ts +322 -0
- package/src/__tests__/screen-reader-turn-marks-port.test.tsx +85 -0
- package/src/__tests__/screen-reader-turn-signals.test.tsx +125 -0
- package/src/__tests__/sec-019-terminal-sanitizer.test.ts +276 -0
- package/src/__tests__/sec-019-tool-label-render.test.tsx +207 -0
- package/src/__tests__/selection-flow.test.ts +61 -0
- package/src/__tests__/session-event-notices.test.tsx +31 -0
- package/src/__tests__/session-init-poller.test.ts +102 -0
- package/src/__tests__/session-picker.test.tsx +93 -0
- package/src/__tests__/session-switch-channel.test.tsx +470 -0
- package/src/__tests__/shutdown-signal.test.ts +34 -0
- package/src/__tests__/status-activity.test.ts +71 -0
- package/src/__tests__/status-bar.test.tsx +290 -0
- package/src/__tests__/status-glyph.test.ts +30 -0
- package/src/__tests__/streaming-indicator.test.tsx +178 -0
- package/src/__tests__/terminal-capabilities.test.ts +153 -0
- package/src/__tests__/terminal-handoff-controller.test.ts +173 -0
- package/src/__tests__/terminal-handoff-pty-e2e.test.ts +77 -0
- package/src/__tests__/text-prompt-flow.test.ts +77 -0
- package/src/__tests__/theme-picker.test.tsx +345 -0
- package/src/__tests__/transport-boundary.test.ts +11 -0
- package/src/__tests__/tui-app-channel-port.test.ts +31 -0
- package/src/__tests__/tui-channel-init-failure.test.ts +70 -0
- package/src/__tests__/tui-channel-lifecycle-coordinator.test.ts +258 -0
- package/src/__tests__/tui-interaction-queues.test.ts +149 -0
- package/src/__tests__/tui-preset-capabilities.test.ts +33 -0
- package/src/__tests__/tui-state-manager.error-stall.test.ts +169 -0
- package/src/__tests__/tui-state-manager.test.ts +482 -0
- package/src/__tests__/ui-intent-rendering.test.tsx +291 -0
- package/src/__tests__/wave-text.test.tsx +133 -0
- package/src/__tests__/wire-tui-channel.test.ts +1457 -0
- package/src/__tests__/wire-tui-client-commands.test.ts +243 -0
- package/src/app-banner.tsx +42 -0
- package/src/app-static-items.ts +35 -0
- package/src/app-view-model.ts +140 -0
- package/src/attached-session-connection.ts +14 -0
- package/src/attention/__tests__/attention-coordinator.test.ts +166 -0
- package/src/attention/__tests__/attention-tracker.test.ts +103 -0
- package/src/attention/__tests__/countdown.test.ts +15 -0
- package/src/attention/__tests__/focus-input-filter.test.ts +93 -0
- package/src/attention/__tests__/interval-recap.test.ts +49 -0
- package/src/attention/attention-coordinator.ts +71 -0
- package/src/attention/attention-tracker.ts +124 -0
- package/src/attention/countdown.ts +24 -0
- package/src/attention/focus-input-filter.ts +131 -0
- package/src/attention/interval-recap.ts +148 -0
- package/src/attention/time-units.ts +6 -0
- package/src/attention-bell.ts +79 -0
- package/src/attributed-user-echo.ts +30 -0
- package/src/background-task-row-format.ts +99 -0
- package/src/command-interaction.ts +8 -0
- package/src/command-output-summary.ts +129 -0
- package/src/create-default-tui-cli-adapter.ts +45 -0
- package/src/execution-workspace-switcher-selection.ts +118 -0
- package/src/execution-workspace-view-model.ts +139 -0
- package/src/external-prompt-notice.tsx +38 -0
- package/src/flows/__tests__/background-focus-flow.test.ts +48 -0
- package/src/flows/__tests__/defer-submit.test.ts +88 -0
- package/src/flows/__tests__/real-cursor-flow.test.ts +139 -0
- package/src/flows/background-focus-flow.ts +44 -0
- package/src/flows/cjk-cursor-motion.ts +75 -0
- package/src/flows/cjk-text-deletion.ts +53 -0
- package/src/flows/cjk-text-input-flow.ts +248 -0
- package/src/flows/cjk-text-input-types.ts +24 -0
- package/src/flows/confirm-prompt-flow.ts +90 -0
- package/src/flows/defer-submit.ts +67 -0
- package/src/flows/fork-attach-flow.ts +62 -0
- package/src/flows/input-area-flow.ts +188 -0
- package/src/flows/permission-prompt-flow.ts +108 -0
- package/src/flows/real-cursor-flow.ts +83 -0
- package/src/flows/selection-flow.ts +205 -0
- package/src/flows/session-init-poller.ts +76 -0
- package/src/flows/text-prompt-flow.ts +93 -0
- package/src/history-search/__tests__/history-search-flow.test.ts +86 -0
- package/src/history-search/history-search-flow.ts +94 -0
- package/src/history-search/useHistorySearch.ts +336 -0
- package/src/hooks/__tests__/use-app-detach-key.test.tsx +72 -0
- package/src/hooks/__tests__/use-app-loop-escape.test.tsx +87 -0
- package/src/hooks/__tests__/use-plugin-callbacks.test.ts +18 -0
- package/src/hooks/__tests__/use-tui-channel-stability.test.tsx +100 -0
- package/src/hooks/__tests__/useAppThemeState.test.tsx +130 -0
- package/src/hooks/command-result-handler.ts +44 -0
- package/src/hooks/side-effects-types.ts +45 -0
- package/src/hooks/useAppController.ts +271 -0
- package/src/hooks/useAppInputBindings.ts +163 -0
- package/src/hooks/useAppInteractionState.ts +84 -0
- package/src/hooks/useAppLifecycleState.ts +81 -0
- package/src/hooks/useAppOverlays.ts +90 -0
- package/src/hooks/useAppScreenState.ts +81 -0
- package/src/hooks/useAppSubmissionState.ts +45 -0
- package/src/hooks/useAppThemeState.ts +157 -0
- package/src/hooks/useAppWorkspaceState.ts +149 -0
- package/src/hooks/useAppearanceSettings.ts +30 -0
- package/src/hooks/useAutocomplete.ts +101 -0
- package/src/hooks/useBackgroundPanel.ts +58 -0
- package/src/hooks/useCountdownTick.ts +24 -0
- package/src/hooks/useExecutionDetailPage.ts +69 -0
- package/src/hooks/useForkAttach.ts +60 -0
- package/src/hooks/useInputAreaHistorySearch.ts +72 -0
- package/src/hooks/useInputAreaKeys.ts +114 -0
- package/src/hooks/useNumberedSelection.ts +93 -0
- package/src/hooks/usePluginCallbacks.ts +38 -0
- package/src/hooks/usePluginScreenData.ts +85 -0
- package/src/hooks/useRealCursorPosition.ts +125 -0
- package/src/hooks/useRenderMarkdown.ts +38 -0
- package/src/hooks/useScreenReaderTurnSignals.ts +113 -0
- package/src/hooks/useSideEffects.ts +144 -0
- package/src/hooks/useStatusLineSettings.ts +50 -0
- package/src/hooks/useTerminalHandoffSuspension.ts +30 -0
- package/src/hooks/useTuiChannel.ts +141 -0
- package/src/humanize-tool-name.ts +51 -0
- package/src/index.ts +72 -0
- package/src/input-area-rules.tsx +71 -0
- package/src/json-value.ts +18 -0
- package/src/key-hint-footer.tsx +54 -0
- package/src/keybindings/__tests__/keybinding-registry.test.ts +228 -0
- package/src/keybindings/__tests__/node-keybindings-source.test.ts +118 -0
- package/src/keybindings/keybinding-catalogue.ts +171 -0
- package/src/keybindings/keybinding-registry.ts +303 -0
- package/src/keybindings/keybinding-syntax.ts +155 -0
- package/src/keybindings/keybindings-context.tsx +124 -0
- package/src/keybindings/node-keybindings-source.ts +189 -0
- package/src/numbered-list.tsx +113 -0
- package/src/plugin-tui-handlers.ts +163 -0
- package/src/product-display-name-context.tsx +30 -0
- package/src/render-markdown.ts +209 -0
- package/src/render.tsx +746 -0
- package/src/sanitize-terminal-text.ts +171 -0
- package/src/screen-reader-announcement.ts +52 -0
- package/src/screen-reader-context.tsx +32 -0
- package/src/screen-reader-labels.ts +64 -0
- package/src/screen-reader-pacing-context.tsx +47 -0
- package/src/screen-reader-pacing.ts +178 -0
- package/src/screen-reader-stdout.ts +328 -0
- package/src/short-session-id.ts +9 -0
- package/src/shutdown-signal.ts +34 -0
- package/src/slash-command-input.ts +11 -0
- package/src/status-activity.ts +70 -0
- package/src/status-glyph.ts +78 -0
- package/src/terminal-capabilities-context.tsx +27 -0
- package/src/terminal-capabilities.ts +77 -0
- package/src/terminal-focus-reporting.ts +50 -0
- package/src/terminal-handoff-controller.ts +98 -0
- package/src/terminal-marks.ts +63 -0
- package/src/theme/__tests__/built-in-themes.test.ts +117 -0
- package/src/theme/__tests__/color-vision.test.ts +82 -0
- package/src/theme/__tests__/theme-context.test.tsx +146 -0
- package/src/theme/__tests__/theme-document.test.ts +222 -0
- package/src/theme/__tests__/theme-registry.test.ts +138 -0
- package/src/theme/__tests__/theme-styles.test.ts +233 -0
- package/src/theme/built-in-themes.ts +342 -0
- package/src/theme/color-vision.ts +171 -0
- package/src/theme/index.ts +45 -0
- package/src/theme/theme-context.tsx +81 -0
- package/src/theme/theme-contracts.ts +139 -0
- package/src/theme/theme-document.ts +278 -0
- package/src/theme/theme-registry.ts +127 -0
- package/src/theme/theme-styles.ts +177 -0
- package/src/tool-summary-status.ts +59 -0
- package/src/tui-app-channel-port.ts +111 -0
- package/src/tui-channel-lifecycle-coordinator.ts +149 -0
- package/src/tui-channel-options.ts +184 -0
- package/src/tui-cli-adapter-context.tsx +13 -0
- package/src/tui-cli-adapter.ts +24 -0
- package/src/tui-interaction-queues.ts +171 -0
- package/src/tui-session-binding.ts +52 -0
- package/src/tui-session-event-projector.ts +149 -0
- package/src/tui-session-events.ts +89 -0
- package/src/tui-session-notice-store.ts +43 -0
- package/src/tui-session-options.ts +134 -0
- package/src/tui-state-manager.ts +347 -0
- package/src/types.ts +21 -0
- package/src/use-terminal-title.ts +29 -0
- package/src/utils/__tests__/edit-diff.test.ts +426 -0
- package/src/utils/__tests__/paste-detection.test.ts +116 -0
- package/src/utils/__tests__/paste-labels.test.ts +46 -0
- package/src/utils/__tests__/tool-call-extractor.test.ts +227 -0
- package/src/utils/__tests__/tool-diff-summary.test.ts +104 -0
- package/src/utils/edit-diff.ts +151 -0
- package/src/utils/input-top-border.ts +19 -0
- package/src/utils/paste-labels.ts +9 -0
- package/src/utils/tool-call-extractor.ts +92 -0
- package/src/utils/tool-diff-summary.ts +75 -0
- package/src/waiting-loop-stop-notice.ts +23 -0
- package/src/wire-history-sync.ts +159 -0
- package/src/wire-tui-channel.ts +963 -0
- package/src/wire-tui-client-commands.ts +142 -0
- package/src/wire-tui-projection.ts +136 -0
|
@@ -0,0 +1,1224 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { CommandRegistry, EditCheckpointStore, IAgentDefinition, IAutomaticMemoryConfig, IBackgroundTaskRunner, ICommandHostAdapters, ICommandHostTerminalHandoff, ICommandHostWorkspace, ICommandModule, IContributionSource, ICreateSessionOptions, ILivePromptTracePort, IMemoryStore, INodeHostSettingsSource, IOrgPolicy, IOutputStylePrompt, IPerTurnRecallConfig, IProjectSettingsPath, IPromptHistoryOptions, IProviderErrorGuidance, IRemoteCommandPolicy, ISkillRootDescriptor, IToolCallHandoffPolicy, InteractiveSession, TInteractiveSessionOptions, TSettingsSource, TShellExecFn, TSubagentRunnerFactory, TWorkspaceProjectAccess } from "@robota-sdk/agent-framework";
|
|
3
|
+
import { IAIProvider, IActionRequest, IContextWindowState, IHistoryEntry, IProviderDefinition, IToolWithEventService, TActionResponse, TModelEffortSelection, TPermissionMode, TProviderCredentialResolver, TSessionEndReason, TToolArgs, TUniversalValue } from "@robota-sdk/agent-core";
|
|
4
|
+
import { IBranchEvent, ICommandInfo, IContextFileRefreshedEvent, IExecutionResult, IInteractiveSession, IInteractiveSessionEvents, IInteractiveSessionStore, IPlanApprovalEvent, IPromptHistorySource, ISessionListingEntry, ITerminalHandoff, IToolState, TInteractiveEventName, TPermissionRequester, TPermissionResultValue } from "@robota-sdk/agent-interface-session";
|
|
5
|
+
import { TClientMessage, TServerMessage } from "@robota-sdk/agent-transport/client";
|
|
6
|
+
import { IExecutionDetailPage, IExecutionWorkspaceSnapshot } from "@robota-sdk/agent-interface-execution";
|
|
7
|
+
import { ICommand, ICommandResult, IThemeAppearanceState, IThemeCataloguePort, TAppearanceSettingsPatch, TReducedMotionOverride } from "@robota-sdk/agent-interface-command";
|
|
8
|
+
import { ITransportRegistryView } from "@robota-sdk/agent-interface-transport";
|
|
9
|
+
import { ITuiCommandInteraction, ITuiConfirmInteraction, ITuiPickerInteraction, ITuiPickerItem, TAnyTuiCommandInteraction, TOnMissingArgsAction } from "@robota-sdk/agent-interface-tui";
|
|
10
|
+
//#region src/screen-reader-pacing.d.ts
|
|
11
|
+
/** Raw timing choices supplied by the embedding host, with names for visible diagnostics. */
|
|
12
|
+
interface IScreenReaderPacingOverrides {
|
|
13
|
+
readonly startupQuiet?: {
|
|
14
|
+
readonly raw: string | undefined;
|
|
15
|
+
readonly label: string;
|
|
16
|
+
};
|
|
17
|
+
readonly prepark?: {
|
|
18
|
+
readonly raw: string | undefined;
|
|
19
|
+
readonly label: string;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/terminal-capabilities-context.d.ts
|
|
24
|
+
/** Host-selected overrides; absent values leave terminal detection in charge. */
|
|
25
|
+
interface ITerminalCapabilityOverrides {
|
|
26
|
+
readonly imeCursorPositioning?: boolean | undefined;
|
|
27
|
+
readonly turnMarks?: boolean | undefined;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/terminal-handoff-controller.d.ts
|
|
31
|
+
/** How the App suspends/resumes its rendering, registered into the controller on mount. */
|
|
32
|
+
interface ITuiSuspendHooks {
|
|
33
|
+
/** Render nothing (release Ink input/raw mode); resolves once that has committed. */
|
|
34
|
+
suspend(): Promise<void>;
|
|
35
|
+
/** Resume rendering and force a redraw. */
|
|
36
|
+
resume(): void;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* SCREEN-1992: terminal modes the TUI negotiated (focus reporting) are released before a child owns
|
|
40
|
+
* the terminal and re-negotiated once it is reclaimed, so the child never receives `CSI I`/`CSI O`
|
|
41
|
+
* and a child that reset the mode does not leave the TUI blind afterwards.
|
|
42
|
+
*/
|
|
43
|
+
interface ITerminalModeHooks {
|
|
44
|
+
/** May be async: SCREEN-2670 drains the parked screen-reader output before the child gets the TTY. */
|
|
45
|
+
preSuspend(): void | Promise<void>;
|
|
46
|
+
postResume(): void;
|
|
47
|
+
}
|
|
48
|
+
/** Minimal slice of the Ink render instance the controller needs. */
|
|
49
|
+
interface IInkClearable {
|
|
50
|
+
clear(): void;
|
|
51
|
+
}
|
|
52
|
+
declare class TerminalHandoffController implements ITerminalHandoff {
|
|
53
|
+
private hooks?;
|
|
54
|
+
private instance?;
|
|
55
|
+
private modeHooks?;
|
|
56
|
+
/**
|
|
57
|
+
* The App registers how to suspend/resume Ink. Returns an unregister function for cleanup on
|
|
58
|
+
* unmount. Only a mounted App provides these hooks, which gates `canHandoffTerminal`.
|
|
59
|
+
*/
|
|
60
|
+
registerSuspendHooks(hooks: ITuiSuspendHooks): () => void;
|
|
61
|
+
/** render.tsx registers the terminal-mode bracket (SCREEN-1992) before `render()`. */
|
|
62
|
+
setTerminalModeHooks(hooks: ITerminalModeHooks | undefined): void;
|
|
63
|
+
/** render.tsx supplies the Ink instance (for `clear()`) after `render()` returns. */
|
|
64
|
+
setInkInstance(instance: IInkClearable): void;
|
|
65
|
+
get canHandoffTerminal(): boolean;
|
|
66
|
+
runWithTerminal<T>(fn: () => Promise<T>): Promise<T>;
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/tui-session-events.d.ts
|
|
70
|
+
interface ITuiSessionEventNotice {
|
|
71
|
+
id: string;
|
|
72
|
+
event: 'plan_event' | 'context_file_refreshed' | 'branch_event' | 'delivery-error' |
|
|
73
|
+
/** SCREEN-1992: TUI-originated — the interval recap on return, not a session event. */
|
|
74
|
+
'attention-recap';
|
|
75
|
+
message: string;
|
|
76
|
+
}
|
|
77
|
+
type TTuiNoticeInput = {
|
|
78
|
+
event: 'plan_event';
|
|
79
|
+
payload: IPlanApprovalEvent;
|
|
80
|
+
} | {
|
|
81
|
+
event: 'context_file_refreshed';
|
|
82
|
+
payload: IContextFileRefreshedEvent;
|
|
83
|
+
} | {
|
|
84
|
+
event: 'branch_event';
|
|
85
|
+
payload: IBranchEvent;
|
|
86
|
+
};
|
|
87
|
+
//#endregion
|
|
88
|
+
//#region src/tui-state-manager.d.ts
|
|
89
|
+
/**
|
|
90
|
+
* TUI view of the core context-window state. The token fields are derived from the agent-core
|
|
91
|
+
* SSOT (`IContextWindowState`) via `Pick` so they stay structurally tied to it; `percentage` is an
|
|
92
|
+
* explicit display-facing mirror of `IContextWindowState.usedPercentage`.
|
|
93
|
+
*/
|
|
94
|
+
type TContextState = Pick<IContextWindowState, 'usedTokens' | 'maxTokens'> & {
|
|
95
|
+
/** Mirror of `IContextWindowState.usedPercentage`, named for the TUI display layer. */
|
|
96
|
+
percentage: number;
|
|
97
|
+
};
|
|
98
|
+
declare class TuiStateManager {
|
|
99
|
+
history: IHistoryEntry[];
|
|
100
|
+
/**
|
|
101
|
+
* Notices this terminal added itself (command results, init errors). They are not in the session's
|
|
102
|
+
* history, so each remembers how many session entries preceded it and is re-inserted there on sync.
|
|
103
|
+
*/
|
|
104
|
+
private localNotices;
|
|
105
|
+
streamingText: string;
|
|
106
|
+
activeTools: IToolState[];
|
|
107
|
+
isThinking: boolean;
|
|
108
|
+
isAborting: boolean;
|
|
109
|
+
pendingPrompt: string | null;
|
|
110
|
+
contextState: TContextState;
|
|
111
|
+
executionWorkspaceSnapshot: IExecutionWorkspaceSnapshot | null;
|
|
112
|
+
selectedExecutionEntryId: string | undefined;
|
|
113
|
+
/** ERR-001 G2: humanized message of the last failed turn; cleared when the next turn starts. */
|
|
114
|
+
lastErrorMessage: string | null;
|
|
115
|
+
/** ERR-001 G3: no stream/tool activity for STALL_HINT_MS while thinking. */
|
|
116
|
+
isStalled: boolean;
|
|
117
|
+
private readonly sessionNoticeStore;
|
|
118
|
+
/** Bounded render-only projection; never merged into canonical session history. */
|
|
119
|
+
readonly sessionEventNotices: ITuiSessionEventNotice[];
|
|
120
|
+
/** Called after any state change. React hook sets this to trigger re-render. */
|
|
121
|
+
onChange: (() => void) | null;
|
|
122
|
+
private streamBuf;
|
|
123
|
+
private debouncedStreamNotify;
|
|
124
|
+
private stallTimer;
|
|
125
|
+
/** (Re)start the dead-air timer — any provider activity proves the connection is alive. */
|
|
126
|
+
private armStallTimer;
|
|
127
|
+
private clearStallTimer;
|
|
128
|
+
private notify;
|
|
129
|
+
onTextDelta: (delta: string) => void;
|
|
130
|
+
onToolStart: (state: IToolState) => void;
|
|
131
|
+
onToolEnd: (state: IToolState) => void;
|
|
132
|
+
onThinking: (thinking: boolean) => void;
|
|
133
|
+
onComplete: (result: Pick<IExecutionResult, "contextState">) => void;
|
|
134
|
+
onInterrupted: () => void;
|
|
135
|
+
onError: (error?: Error) => void;
|
|
136
|
+
onContextUpdate: (state: IContextWindowState) => void;
|
|
137
|
+
/**
|
|
138
|
+
* Sync history from InteractiveSession — authoritative SSOT replace (SCREEN-010: no front-windowing).
|
|
139
|
+
* The session history grows monotonically during a session, so Ink `<Static>` (count-based) renders
|
|
140
|
+
* only the newly-appended tail; committed lines already in terminal scrollback are never re-printed.
|
|
141
|
+
*/
|
|
142
|
+
syncHistory(entries: IHistoryEntry[]): void;
|
|
143
|
+
/**
|
|
144
|
+
* A host's history as a terminal attached to it last read it, then the echoes of prompts the host
|
|
145
|
+
* has not recorded yet. Unlike `syncHistory`, an empty history is an answer: the host's session
|
|
146
|
+
* has no entries.
|
|
147
|
+
*/
|
|
148
|
+
syncHostHistory(entries: readonly IHistoryEntry[], echoes: readonly IHistoryEntry[]): void;
|
|
149
|
+
private withLocalNotices;
|
|
150
|
+
/** Add a notice this terminal owns; it survives the next session-history sync in place. */
|
|
151
|
+
addEntry(entry: IHistoryEntry): void;
|
|
152
|
+
/** Echo the user's prompt at once; the session's own user entry replaces it on the next sync. */
|
|
153
|
+
addUserEcho(entry: IHistoryEntry): void;
|
|
154
|
+
clearHistory(): void;
|
|
155
|
+
/** Update pending prompt state */
|
|
156
|
+
setPendingPrompt(prompt: string | null): void;
|
|
157
|
+
/** Set aborting flag */
|
|
158
|
+
setAborting(aborting: boolean): void;
|
|
159
|
+
/** Update context state */
|
|
160
|
+
setContextState(state: TContextState): void;
|
|
161
|
+
addSessionEventNotice(input: TTuiNoticeInput): void;
|
|
162
|
+
addAttentionRecap(line: string): void;
|
|
163
|
+
addSessionEventDeliveryError(error: Error, event: TInteractiveEventName): void;
|
|
164
|
+
syncExecutionWorkspaceSnapshot(snapshot: IExecutionWorkspaceSnapshot): void;
|
|
165
|
+
selectExecutionWorkspaceEntry(entryId: string): void;
|
|
166
|
+
/**
|
|
167
|
+
* RUNTIME-52: release every timer this manager owns and detach the render callback. Called by the
|
|
168
|
+
* channel's teardown (`stop()`); after dispose the manager must never fire `onChange` or trip the
|
|
169
|
+
* stall hint on a discarded session.
|
|
170
|
+
*/
|
|
171
|
+
dispose(): void;
|
|
172
|
+
}
|
|
173
|
+
//#endregion
|
|
174
|
+
//#region src/types.d.ts
|
|
175
|
+
/**
|
|
176
|
+
* Permission result: true (allow once), false (deny), 'allow-session' (remember for session),
|
|
177
|
+
* or 'allow-project' (persist through the host-selected project settings writer).
|
|
178
|
+
*/
|
|
179
|
+
type TPermissionResult = TPermissionResultValue;
|
|
180
|
+
interface IPendingPermissionRequest {
|
|
181
|
+
toolName: string;
|
|
182
|
+
toolArgs: TToolArgs;
|
|
183
|
+
canPersistProjectPermission?: boolean;
|
|
184
|
+
/** The peer session whose message this call serves, when a peer turn asked. */
|
|
185
|
+
requestedByPeer?: string;
|
|
186
|
+
/** Issue #3288 §1: a background agent's own request, forwarded to the person. */
|
|
187
|
+
requester?: TPermissionRequester;
|
|
188
|
+
resolve: (result: TPermissionResult) => void;
|
|
189
|
+
}
|
|
190
|
+
//#endregion
|
|
191
|
+
//#region src/tui-app-channel-port.d.ts
|
|
192
|
+
interface ITuiCommandQueryPort {
|
|
193
|
+
getCommands(filter?: string): ICommand[];
|
|
194
|
+
getSubcommands(commandName: string): ICommand[];
|
|
195
|
+
}
|
|
196
|
+
type TTuiSessionUiEventName = 'ui_intent' | 'session_renamed';
|
|
197
|
+
interface ITuiSessionUiEventPort {
|
|
198
|
+
on<E extends TTuiSessionUiEventName>(event: E, handler: IInteractiveSessionEvents[E]): void;
|
|
199
|
+
off<E extends TTuiSessionUiEventName>(event: E, handler: IInteractiveSessionEvents[E]): void;
|
|
200
|
+
}
|
|
201
|
+
interface ITuiRuntimeStatusSnapshot {
|
|
202
|
+
permissionMode: TPermissionMode;
|
|
203
|
+
sessionId: string;
|
|
204
|
+
activePresetId?: string;
|
|
205
|
+
effort?: TModelEffortSelection;
|
|
206
|
+
/** The model the session reports, when its host says; absent ⇒ the one this terminal was started with. */
|
|
207
|
+
modelId?: string;
|
|
208
|
+
}
|
|
209
|
+
interface ITuiChannelSnapshot {
|
|
210
|
+
history: readonly IHistoryEntry[];
|
|
211
|
+
streamingText: string;
|
|
212
|
+
activeTools: readonly IToolState[];
|
|
213
|
+
isThinking: boolean;
|
|
214
|
+
isAborting: boolean;
|
|
215
|
+
lastErrorMessage: string | null;
|
|
216
|
+
isStalled: boolean;
|
|
217
|
+
sessionEventNotices: readonly ITuiSessionEventNotice[];
|
|
218
|
+
isShuttingDown: boolean;
|
|
219
|
+
pendingPrompt: string | null;
|
|
220
|
+
pendingCount: number;
|
|
221
|
+
executionWorkspaceSnapshot: IExecutionWorkspaceSnapshot | null;
|
|
222
|
+
selectedExecutionEntryId?: string;
|
|
223
|
+
permissionRequest: IPendingPermissionRequest | null;
|
|
224
|
+
pendingUserAction: IActionRequest | null;
|
|
225
|
+
contextState: {
|
|
226
|
+
percentage: number;
|
|
227
|
+
usedTokens: number;
|
|
228
|
+
maxTokens: number;
|
|
229
|
+
};
|
|
230
|
+
/**
|
|
231
|
+
* The sessions the session picker offers, when the host keeps them (a terminal attached to a
|
|
232
|
+
* daemon). Absent ⇒ the picker lists this terminal's own session store. A host that keeps sessions
|
|
233
|
+
* live says which rows run now and how many clients are on each; the picker shows both.
|
|
234
|
+
*/
|
|
235
|
+
hostSessions?: readonly ISessionListingEntry[];
|
|
236
|
+
/**
|
|
237
|
+
* Changes when the transcript starts over for another session while the App keeps this channel.
|
|
238
|
+
* The terminal prints the transcript once and counts what it printed, so a new transcript is
|
|
239
|
+
* printed from its start. Absent ⇒ the transcript never starts over under this channel.
|
|
240
|
+
*/
|
|
241
|
+
transcriptGeneration?: number;
|
|
242
|
+
/**
|
|
243
|
+
* True while this terminal only observes the session: it sends nothing that changes it, and the
|
|
244
|
+
* App offers no key that would. Absent ⇒ the terminal drives the session.
|
|
245
|
+
*/
|
|
246
|
+
readOnly?: boolean;
|
|
247
|
+
/**
|
|
248
|
+
* True when this terminal is attached to a session a host runs: leaving only detaches it, and
|
|
249
|
+
* Ctrl-] leaves too. Absent ⇒ the terminal runs its own session, where Ctrl-] means nothing.
|
|
250
|
+
*/
|
|
251
|
+
attached?: boolean;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Complete channel surface visible below the top-level App composition shell.
|
|
255
|
+
*
|
|
256
|
+
* Deliberately excludes the concrete-session, concrete-registry and mutable-state-manager
|
|
257
|
+
* compatibility escapes retained by TuiInteractionChannel for non-React consumers.
|
|
258
|
+
*/
|
|
259
|
+
interface ITuiAppChannelPort {
|
|
260
|
+
readonly terminalHandoffController: TerminalHandoffController | undefined;
|
|
261
|
+
readonly sessionName: string | undefined;
|
|
262
|
+
start(): Promise<void>;
|
|
263
|
+
stop(): Promise<void>;
|
|
264
|
+
subscribe(onChange: () => void): () => void;
|
|
265
|
+
getSnapshot(): ITuiChannelSnapshot;
|
|
266
|
+
getCommandQueryPort(): ITuiCommandQueryPort;
|
|
267
|
+
getSessionUiEventPort(): ITuiSessionUiEventPort;
|
|
268
|
+
getRuntimeStatusSnapshot(fallbackPermissionMode: TPermissionMode): ITuiRuntimeStatusSnapshot;
|
|
269
|
+
addEntry(entry: IHistoryEntry): void;
|
|
270
|
+
handleInput(input: string): Promise<void>;
|
|
271
|
+
abort(): void;
|
|
272
|
+
cancelQueue(): void;
|
|
273
|
+
stopWaitingSelfPacedLoop(): Promise<void>;
|
|
274
|
+
shutdown(options?: {
|
|
275
|
+
reason?: TSessionEndReason;
|
|
276
|
+
timeoutMs?: number;
|
|
277
|
+
}): Promise<void>;
|
|
278
|
+
selectExecutionWorkspaceEntry(entryId: string): void;
|
|
279
|
+
readExecutionWorkspaceDetail(entryId: string): Promise<IExecutionDetailPage>;
|
|
280
|
+
sendAgentJob(taskId: string, input: string): Promise<void>;
|
|
281
|
+
resolveUserAction(request: IActionRequest, response: TActionResponse): void;
|
|
282
|
+
}
|
|
283
|
+
//#endregion
|
|
284
|
+
//#region src/attention/attention-tracker.d.ts
|
|
285
|
+
type TAttentionChangeKind = 'lost' | 'returned';
|
|
286
|
+
interface IAttentionChange {
|
|
287
|
+
readonly kind: TAttentionChangeKind;
|
|
288
|
+
/** ISO timestamp of the transition, from the injected clock. */
|
|
289
|
+
readonly at: string;
|
|
290
|
+
}
|
|
291
|
+
type TAttentionListener = (change: IAttentionChange) => void;
|
|
292
|
+
/** What a consumer of attention sees: the level, and every transition. */
|
|
293
|
+
interface IAttentionSource {
|
|
294
|
+
readonly attended: boolean;
|
|
295
|
+
/** Which source decides the level right now — recorded so a degraded run is never a silent default. */
|
|
296
|
+
readonly source: 'focus' | 'idle';
|
|
297
|
+
subscribe(listener: TAttentionListener): () => void;
|
|
298
|
+
}
|
|
299
|
+
//#endregion
|
|
300
|
+
//#region src/tui-channel-options.d.ts
|
|
301
|
+
/**
|
|
302
|
+
* The TUI channel's option surface.
|
|
303
|
+
*
|
|
304
|
+
* ARCH-013: this lived inside the 698-line channel class, beside the code that consumes it. The
|
|
305
|
+
* projection FROM it — `buildTuiSessionOptions` — already had its own module, so the surface and its
|
|
306
|
+
* one projection now sit together and neither is buried in an implementation file. That matters for
|
|
307
|
+
* this item specifically: a field added to the resolved preset has to be added here to reach the
|
|
308
|
+
* interactive surface at all, and a surface nobody can find is a surface people forget.
|
|
309
|
+
*/
|
|
310
|
+
interface ITuiInteractionChannelOptions {
|
|
311
|
+
livePromptTrace?: ILivePromptTracePort;
|
|
312
|
+
/**
|
|
313
|
+
* Provider definitions, forwarded to the session so `/provider switch` can construct the provider
|
|
314
|
+
* it switches TO.
|
|
315
|
+
*
|
|
316
|
+
* Not optional-by-accident: without it the session holds an empty list, and the hot-swap fails with
|
|
317
|
+
* "Unknown provider: <name>. Currently supported: " — an empty supported-list, which is both wrong
|
|
318
|
+
* and unactionable. The definitions live in the composition root; the session cannot discover them.
|
|
319
|
+
*/
|
|
320
|
+
providerDefinitions?: readonly IProviderDefinition[];
|
|
321
|
+
cwd: string;
|
|
322
|
+
provider: IAIProvider;
|
|
323
|
+
providerErrorGuidance?: IProviderErrorGuidance;
|
|
324
|
+
promptFileReferenceTag?: string;
|
|
325
|
+
modelCommandToolPrefix?: string;
|
|
326
|
+
subagentHookEnvironmentNames?: ICreateSessionOptions['subagentHookEnvironmentNames'];
|
|
327
|
+
observerFailureWarningCode?: ICreateSessionOptions['observerFailureWarningCode'];
|
|
328
|
+
commandHookShell?: string;
|
|
329
|
+
/** Skip instruction files and plugin discovery (`--safe-mode`). */
|
|
330
|
+
bare?: boolean;
|
|
331
|
+
/** Run no hook the settings layers declare (`--safe-mode`). */
|
|
332
|
+
skipConfiguredHooks?: boolean;
|
|
333
|
+
/** Resolved organization policy forwarded to the interactive session. */
|
|
334
|
+
orgPolicy?: IOrgPolicy;
|
|
335
|
+
projectAccess?: TWorkspaceProjectAccess;
|
|
336
|
+
projectSettingsPaths?: readonly IProjectSettingsPath[];
|
|
337
|
+
baselinePermissionAllow?: readonly string[];
|
|
338
|
+
/** Host-selected task-context root; absent means no framework task-directory scan. */
|
|
339
|
+
taskContext?: {
|
|
340
|
+
readonly enabled?: boolean;
|
|
341
|
+
readonly dir?: string;
|
|
342
|
+
};
|
|
343
|
+
contributionSources?: ICreateSessionOptions['contributionSources'];
|
|
344
|
+
skillRoots?: ICreateSessionOptions['skillRoots'];
|
|
345
|
+
userSettingsSources?: readonly INodeHostSettingsSource[];
|
|
346
|
+
environment?: Readonly<Record<string, string | undefined>>;
|
|
347
|
+
resolveProviderCredential?: import('@robota-sdk/agent-core').TProviderCredentialResolver;
|
|
348
|
+
/**
|
|
349
|
+
* Explicit authority- and permission-backed edit checkpoint capability for this channel's one
|
|
350
|
+
* session. Never shared with another channel's session: a store holds one turn in progress.
|
|
351
|
+
*/
|
|
352
|
+
editCheckpointStore?: EditCheckpointStore;
|
|
353
|
+
/** The host's way to build each external-event grant's verifier; absent, no grant opens. */
|
|
354
|
+
externalEventVerifierFactory?: TInteractiveSessionOptions['externalEventVerifierFactory'];
|
|
355
|
+
/** The run's grant history, shared by every session this TUI binds (#3189). */
|
|
356
|
+
externalEventGrantHistory?: TInteractiveSessionOptions['externalEventGrantHistory'];
|
|
357
|
+
/**
|
|
358
|
+
* CLI-076: the resolved model id (the same value the status line displays). Forwarded to the session so an
|
|
359
|
+
* explicit `--model` override reaches the provider chat call instead of being silently replaced by the
|
|
360
|
+
* session's default model.
|
|
361
|
+
*/
|
|
362
|
+
model?: string;
|
|
363
|
+
/** CLI-1988: resolved provider-neutral response style. */
|
|
364
|
+
outputStyle?: IOutputStylePrompt;
|
|
365
|
+
/** ARCH-013: resolved preset effort, threaded to the session's `effort` seam. */
|
|
366
|
+
effort?: ICreateSessionOptions['effort'];
|
|
367
|
+
temperature?: number;
|
|
368
|
+
maxOutputTokens?: number;
|
|
369
|
+
/** Preset prompt seed, distinct from the replacing `systemPrompt` option. */
|
|
370
|
+
presetSystemPrompt?: string;
|
|
371
|
+
responseFormat?: ICreateSessionOptions['responseFormat'];
|
|
372
|
+
permissionMode?: TPermissionMode;
|
|
373
|
+
maxTurns?: number;
|
|
374
|
+
sessionStore?: IInteractiveSessionStore;
|
|
375
|
+
disableSessionLoops?: boolean;
|
|
376
|
+
resolveDefaultLoopPrompt?: () => string;
|
|
377
|
+
resumeSessionId?: string;
|
|
378
|
+
forkSession?: boolean;
|
|
379
|
+
/** Issue #3081: this channel's session is the target of a `/cd` from this directory. */
|
|
380
|
+
workspaceMovedFrom?: string;
|
|
381
|
+
sessionName?: string;
|
|
382
|
+
backgroundTaskRunners?: IBackgroundTaskRunner[];
|
|
383
|
+
/** MCP-004: forwarded to `ICreateSessionOptions.toolCallHandoff`. */
|
|
384
|
+
toolCallHandoff?: IToolCallHandoffPolicy;
|
|
385
|
+
subagentRunnerFactory?: TSubagentRunnerFactory;
|
|
386
|
+
/** ARCH-005: composition-root-contributed subagent definitions (merged capability packs). */
|
|
387
|
+
agentDefinitions?: readonly IAgentDefinition[];
|
|
388
|
+
agentDefinitionRoots?: readonly string[];
|
|
389
|
+
pluginDirectories?: {
|
|
390
|
+
readonly user?: string;
|
|
391
|
+
readonly project?: string;
|
|
392
|
+
};
|
|
393
|
+
/**
|
|
394
|
+
* ARCH-006: tools contributed by the composition root (the capability packs `assembleProduct` merged)
|
|
395
|
+
* and, when the profile hands the packs the whole tool surface, the suppressed framework default tier
|
|
396
|
+
* (`defaultTools: []`). Forwarded to the session's tool-composition seam; absent ⇒ unchanged.
|
|
397
|
+
*/
|
|
398
|
+
additionalTools?: IToolWithEventService[];
|
|
399
|
+
defaultTools?: readonly IToolWithEventService[];
|
|
400
|
+
/** The sandbox the shell tools run under, so the session can let a confined command skip the prompt. */
|
|
401
|
+
sandboxClient?: ICreateSessionOptions['sandboxClient'];
|
|
402
|
+
toolExecutionPolicy?: ICreateSessionOptions['toolExecutionPolicy'];
|
|
403
|
+
commandModules?: readonly ICommandModule[];
|
|
404
|
+
commandHostAdapters?: ICommandHostAdapters;
|
|
405
|
+
shellExec?: TShellExecFn;
|
|
406
|
+
/** REMOTE-006: optional remote-command policy (allow-by-default; a transport-origin command runs as a local one). */
|
|
407
|
+
remoteCommandPolicy?: IRemoteCommandPolicy;
|
|
408
|
+
transportRegistry?: ITransportRegistryView;
|
|
409
|
+
/** Bind concrete transports to each newly constructed session before registry startup. */
|
|
410
|
+
bindTransports?: (session: IInteractiveSession) => void | Promise<void>;
|
|
411
|
+
language?: string;
|
|
412
|
+
reloadPluginCommandSource?: (registry: CommandRegistry) => void;
|
|
413
|
+
agentName?: string;
|
|
414
|
+
/** Active preset id selected at startup (PRESET-011 runtime state). Defaults to 'default'. */
|
|
415
|
+
activePresetId?: string;
|
|
416
|
+
/** Preset persona block composed as a `source: 'persona'` system-prompt section (priority 5). */
|
|
417
|
+
persona?: string;
|
|
418
|
+
systemPrompt?: string;
|
|
419
|
+
appendSystemPrompt?: string;
|
|
420
|
+
allowedTools?: readonly string[];
|
|
421
|
+
deniedTools?: readonly string[];
|
|
422
|
+
/** Preset execution capability: activate agent runtime + subagent/background dispatch. */
|
|
423
|
+
enableParallelSubagents?: boolean;
|
|
424
|
+
/** Preset execution capability: run a post-task self-verification step. */
|
|
425
|
+
selfVerification?: boolean;
|
|
426
|
+
/** TERM-002: process-shared terminal-handoff controller (the TUI implementation of ITerminalHandoff). */
|
|
427
|
+
terminalHandoff?: TerminalHandoffController;
|
|
428
|
+
/** SCREEN-1992: the terminal's attention level; absent ⇒ no interval recap. */
|
|
429
|
+
attention?: IAttentionSource;
|
|
430
|
+
/**
|
|
431
|
+
* SELFHOST-008 P6: optional durable-memory store injected by the surface (agent-cli). Forwarded into
|
|
432
|
+
* `buildRuntimeSession`; absent ⇒ memory OFF (today's behavior). Enablement/policy is surface-owned.
|
|
433
|
+
*/
|
|
434
|
+
memoryStore?: IMemoryStore;
|
|
435
|
+
/** SELFHOST-008 P6: optional automatic post-turn capture policy (absent ⇒ capture OFF). */
|
|
436
|
+
automaticMemory?: IAutomaticMemoryConfig;
|
|
437
|
+
/** SELFHOST-008 P6: optional per-turn recall policy (absent ⇒ recall OFF, startup-only injection). */
|
|
438
|
+
recallMemory?: IPerTurnRecallConfig;
|
|
439
|
+
/** Observe TUI-owned session-event rendering failures without failing the committed operation. */
|
|
440
|
+
onSessionEventDeliveryError?: (error: Error, event: TInteractiveEventName) => void;
|
|
441
|
+
/**
|
|
442
|
+
* CLI-2004: the resolved screen-reader mode. A PRESENTATION field — it changes nothing about the
|
|
443
|
+
* session and is deliberately NOT projected into `buildTuiSessionOptions`; it is carried here so
|
|
444
|
+
* the render-options → channel-options projection is complete and the ARCH-110 drop hazard is
|
|
445
|
+
* asserted rather than assumed. Absent ⇒ OFF.
|
|
446
|
+
*/
|
|
447
|
+
screenReader?: boolean;
|
|
448
|
+
/** SCREEN-1993: the session-side prompt-history writer and project key; absent ⇒ nothing recorded. */
|
|
449
|
+
promptHistory?: IPromptHistoryOptions | undefined;
|
|
450
|
+
}
|
|
451
|
+
//#endregion
|
|
452
|
+
//#region src/TuiInteractionChannel.d.ts
|
|
453
|
+
declare class TuiInteractionChannel implements ITuiAppChannelPort {
|
|
454
|
+
readonly stateManager: TuiStateManager;
|
|
455
|
+
private readonly interactiveSession;
|
|
456
|
+
private readonly registry;
|
|
457
|
+
private readonly opts;
|
|
458
|
+
private submitHandler;
|
|
459
|
+
private readonly userActions;
|
|
460
|
+
private readonly permissions;
|
|
461
|
+
private readonly eventProjector;
|
|
462
|
+
/** SCREEN-1992: joins the terminal's attention to this channel's recap; absent without a source. */
|
|
463
|
+
private readonly attention;
|
|
464
|
+
private readonly lifecycle;
|
|
465
|
+
availableCommands: ICommandInfo[];
|
|
466
|
+
sessionName: string | undefined;
|
|
467
|
+
private initPoller;
|
|
468
|
+
/** TERM-002: the App registers its Ink suspend/resume hooks into this controller. */
|
|
469
|
+
get terminalHandoffController(): TerminalHandoffController | undefined;
|
|
470
|
+
/** Set by React hook to trigger re-render on state change */
|
|
471
|
+
onChange: (() => void) | null;
|
|
472
|
+
constructor(opts: ITuiInteractionChannelOptions);
|
|
473
|
+
private startRuntime;
|
|
474
|
+
private stopTransports;
|
|
475
|
+
get permissionRequest(): IPendingPermissionRequest | null;
|
|
476
|
+
/** CMD-004: the action currently awaiting a user answer, or null. */
|
|
477
|
+
get pendingUserAction(): IActionRequest | null;
|
|
478
|
+
get isShuttingDown(): boolean;
|
|
479
|
+
get isActiveForPeerStatus(): boolean;
|
|
480
|
+
private createSession;
|
|
481
|
+
private createRegistry;
|
|
482
|
+
onSubmit(handler: (text: string) => Promise<void>): void;
|
|
483
|
+
setAvailableCommands(commands: ICommandInfo[]): void;
|
|
484
|
+
setBusy(busy: boolean): void;
|
|
485
|
+
start(): Promise<void>;
|
|
486
|
+
/**
|
|
487
|
+
* Full, idempotent channel teardown (CLI-075). Unwires every session listener, drains both
|
|
488
|
+
* request queues, stops the init poller, disposes the render-state manager, stops transports, and
|
|
489
|
+
* — unless a graceful `shutdown()` already ran — shuts the underlying session down so a discarded
|
|
490
|
+
* or switched-away channel releases its background tasks, subagent processes, and timers.
|
|
491
|
+
*/
|
|
492
|
+
stop(): Promise<void>;
|
|
493
|
+
getSession(): InteractiveSession;
|
|
494
|
+
getRegistry(): CommandRegistry;
|
|
495
|
+
subscribe(onChange: () => void): () => void;
|
|
496
|
+
getSnapshot(): ITuiChannelSnapshot;
|
|
497
|
+
getCommandQueryPort(): ITuiCommandQueryPort;
|
|
498
|
+
getSessionUiEventPort(): ITuiSessionUiEventPort;
|
|
499
|
+
getRuntimeStatusSnapshot(fallbackPermissionMode: TPermissionMode): ITuiRuntimeStatusSnapshot;
|
|
500
|
+
addEntry(entry: IHistoryEntry): void;
|
|
501
|
+
abort(): void;
|
|
502
|
+
cancelQueue(): void;
|
|
503
|
+
/** Esc on an idle prompt: the session decides which waiting loop, if any, stops. */
|
|
504
|
+
stopWaitingSelfPacedLoop(): Promise<void>;
|
|
505
|
+
shutdown(options?: {
|
|
506
|
+
reason?: TSessionEndReason;
|
|
507
|
+
timeoutMs?: number;
|
|
508
|
+
}): Promise<void>;
|
|
509
|
+
selectExecutionWorkspaceEntry(entryId: string): void;
|
|
510
|
+
readExecutionWorkspaceDetail(entryId: string): Promise<IExecutionDetailPage>;
|
|
511
|
+
sendAgentJob(taskId: string, input: string): Promise<void>;
|
|
512
|
+
setSessionName(name: string): void;
|
|
513
|
+
/**
|
|
514
|
+
* Queue an ask and resolve when the user answers. Reached via the `ask_request` event handler
|
|
515
|
+
* (which passes the framework prompt `id` for co-drive dismissal) and by any direct
|
|
516
|
+
* `IInteractionChannel.askUser` caller (no id).
|
|
517
|
+
*/
|
|
518
|
+
askUser(request: IActionRequest, id?: string): Promise<TActionResponse>;
|
|
519
|
+
/** Called by App's PendingActionPrompt when the user answers (or cancels) the pending action. */
|
|
520
|
+
resolveUserAction(request: IActionRequest, response: TActionResponse): void;
|
|
521
|
+
/** Resolve every queued/in-flight ask as cancelled (abort, shutdown). */
|
|
522
|
+
private cancelAllUserActions;
|
|
523
|
+
handleInput(input: string): Promise<void>;
|
|
524
|
+
private handleSlashCommand;
|
|
525
|
+
private handlePermissionRequest;
|
|
526
|
+
/**
|
|
527
|
+
* REMOTE-007 co-drive: another surface answered the prompt with this framework `id`, so dismiss the
|
|
528
|
+
* still-showing local dialog. Resolving the local entry (cancelled) is a no-op on the framework side
|
|
529
|
+
* — that id is already settled — but it clears the TUI's queue + render state.
|
|
530
|
+
*/
|
|
531
|
+
private dismissPromptById;
|
|
532
|
+
/**
|
|
533
|
+
* Resolve every queued/in-flight permission request as `false` (deny) — abort, cancelQueue,
|
|
534
|
+
* shutdown, stop. Symmetric to `cancelAllUserActions()`: tearing down must neither leave a tool's
|
|
535
|
+
* permission promise dangling (the tool would hang) nor silently grant it (CLI-075 RUNTIME-32).
|
|
536
|
+
*/
|
|
537
|
+
private cancelAllPermissions;
|
|
538
|
+
private syncRestoredHistory;
|
|
539
|
+
private startInitCheck;
|
|
540
|
+
/** Throws while the session is not ready; the init poller classifies the error. */
|
|
541
|
+
private runInitCheck;
|
|
542
|
+
/** SCREEN-1992: the recap lands in this channel's notice store; no source ⇒ no coordinator. */
|
|
543
|
+
private createAttention;
|
|
544
|
+
private onInitFailure;
|
|
545
|
+
private stopInitCheck;
|
|
546
|
+
private syncExecutionWorkspace;
|
|
547
|
+
}
|
|
548
|
+
//#endregion
|
|
549
|
+
//#region src/attached-session-connection.d.ts
|
|
550
|
+
/**
|
|
551
|
+
* A terminal's end of the session protocol to a session it is attached to. The terminal only sends
|
|
552
|
+
* and listens; closing the connection belongs to whoever opened it.
|
|
553
|
+
*/
|
|
554
|
+
interface IAttachedSessionConnection {
|
|
555
|
+
send(message: TClientMessage): void;
|
|
556
|
+
subscribe(listener: (message: TServerMessage) => void): () => void;
|
|
557
|
+
onClose(listener: () => void): () => void;
|
|
558
|
+
}
|
|
559
|
+
/** Why an attached terminal stopped showing the session: the user left, or the connection closed. */
|
|
560
|
+
type TAttachedSessionEnd = 'user' | 'closed';
|
|
561
|
+
//#endregion
|
|
562
|
+
//#region src/keybindings/keybinding-catalogue.d.ts
|
|
563
|
+
declare const KEYBINDING_ACTIONS: {
|
|
564
|
+
readonly app: readonly ["open-workspace-switcher"];
|
|
565
|
+
readonly thinking: readonly ["abort"];
|
|
566
|
+
readonly 'background-detail': readonly ["return-to-main"];
|
|
567
|
+
readonly recovery: readonly ["retry"];
|
|
568
|
+
readonly 'chat-input': readonly ["submit", "history-previous", "history-next", "history-search", "cursor-left", "cursor-right", "delete-backward", "delete-word", "delete-line"];
|
|
569
|
+
readonly 'text-input': readonly ["submit", "cursor-left", "cursor-right", "cursor-up", "cursor-down", "delete-backward", "delete-word", "delete-line"];
|
|
570
|
+
readonly 'autocomplete-menu': readonly ["previous", "next", "close", "accept", "execute"];
|
|
571
|
+
readonly 'queued-prompt': readonly ["cancel"];
|
|
572
|
+
readonly 'confirm-prompt': readonly ["previous", "next", "confirm", "choose-yes", "choose-no"];
|
|
573
|
+
readonly 'permission-prompt': readonly ["previous", "next", "confirm", "allow-once", "allow-session", "allow-project", "deny"];
|
|
574
|
+
readonly 'text-prompt': readonly ["submit", "cancel", "delete-backward"];
|
|
575
|
+
readonly 'list-picker': readonly ["previous", "next", "select", "cancel"];
|
|
576
|
+
readonly 'menu-select': readonly ["previous", "next", "select", "back"];
|
|
577
|
+
readonly 'multi-select': readonly ["previous", "next", "toggle", "confirm", "cancel"];
|
|
578
|
+
readonly 'workspace-switcher': readonly ["previous", "next", "select", "close", "attach"];
|
|
579
|
+
readonly 'background-list': readonly ["previous", "next", "open", "close"];
|
|
580
|
+
readonly 'transport-settings': readonly ["previous", "next", "toggle", "close"];
|
|
581
|
+
/** SCREEN-1993: the reverse prompt-history search overlay. */
|
|
582
|
+
readonly 'history-search': readonly ["previous", "next", "cycle-scope", "insert", "execute", "cancel"];
|
|
583
|
+
/**
|
|
584
|
+
* SCREEN-2002: the theme picker. Navigation PREVIEWS; only `select` applies. Printable keys are
|
|
585
|
+
* fine here because the picker takes no text.
|
|
586
|
+
*/
|
|
587
|
+
readonly 'theme-picker': readonly ["previous", "next", "select", "toggle-syntax", "toggle-motion", "cancel"];
|
|
588
|
+
};
|
|
589
|
+
type TKeybindingContext = keyof typeof KEYBINDING_ACTIONS;
|
|
590
|
+
type TKeybindingAction<TContext extends TKeybindingContext = TKeybindingContext> = (typeof KEYBINDING_ACTIONS)[TContext][number];
|
|
591
|
+
//#endregion
|
|
592
|
+
//#region src/keybindings/keybinding-registry.d.ts
|
|
593
|
+
interface IKeybindingWarning {
|
|
594
|
+
readonly code: 'multiplexer-conflict' | 'modifier-delivery';
|
|
595
|
+
readonly path: string;
|
|
596
|
+
readonly message: string;
|
|
597
|
+
}
|
|
598
|
+
interface IKeybindingDiagnostic {
|
|
599
|
+
readonly file: string;
|
|
600
|
+
readonly path: string;
|
|
601
|
+
readonly message: string;
|
|
602
|
+
}
|
|
603
|
+
interface IKeybindingSnapshot {
|
|
604
|
+
readonly generation: number;
|
|
605
|
+
readonly sourcePath: string;
|
|
606
|
+
readonly bindings: Readonly<Record<TKeybindingContext, Readonly<Record<string, readonly string[]>>>>;
|
|
607
|
+
readonly warnings: readonly IKeybindingWarning[];
|
|
608
|
+
readonly diagnostic?: IKeybindingDiagnostic;
|
|
609
|
+
}
|
|
610
|
+
//#endregion
|
|
611
|
+
//#region src/keybindings/node-keybindings-source.d.ts
|
|
612
|
+
interface IKeybindingsFilePort {
|
|
613
|
+
ensureFile(): Promise<string>;
|
|
614
|
+
}
|
|
615
|
+
interface IKeybindingsSource extends IKeybindingsFilePort {
|
|
616
|
+
readonly filePath: string;
|
|
617
|
+
start(): Promise<void>;
|
|
618
|
+
isStarted(): boolean;
|
|
619
|
+
getSnapshot(): IKeybindingSnapshot;
|
|
620
|
+
subscribe(listener: (snapshot: IKeybindingSnapshot) => void): () => void;
|
|
621
|
+
dispose(): void;
|
|
622
|
+
}
|
|
623
|
+
interface INodeKeybindingsSourceOptions {
|
|
624
|
+
readonly filePath: string;
|
|
625
|
+
readonly schemaUrl?: string;
|
|
626
|
+
readonly onDiagnostic?: (diagnostic: IKeybindingDiagnostic) => void;
|
|
627
|
+
}
|
|
628
|
+
declare function createNodeKeybindingsSource(options: INodeKeybindingsSourceOptions): IKeybindingsSource;
|
|
629
|
+
//#endregion
|
|
630
|
+
//#region src/screen-reader-announcement.d.ts
|
|
631
|
+
/**
|
|
632
|
+
* CLI-2004 — the first line the process prints.
|
|
633
|
+
*
|
|
634
|
+
* Two mutually exclusive lines, and never more than one:
|
|
635
|
+
* - the mode is ON → `[Screen reader mode: on via flag|env|settings]`. It is the only
|
|
636
|
+
* self-diagnostic in the design: when someone reports "I passed the flag and nothing changed",
|
|
637
|
+
* this line says whether the mode is on and which input turned it on.
|
|
638
|
+
* - the mode is OFF and the environment looks like a reader is present → one advisory line naming
|
|
639
|
+
* the flag. That is the whole of this project's answer to the auto-detection question: opt-in
|
|
640
|
+
* keeps determinism, and a false positive costs one line of text instead of reshaping a sighted
|
|
641
|
+
* user's interface.
|
|
642
|
+
*
|
|
643
|
+
* Printed before Ink's first frame and never during a turn, so it cannot interleave with output a
|
|
644
|
+
* reader is consuming.
|
|
645
|
+
*/
|
|
646
|
+
/** Which input turned the mode on. Mirrors the CLI resolver's channel. */
|
|
647
|
+
type TScreenReaderChannel = 'flag' | 'env' | 'settings';
|
|
648
|
+
//#endregion
|
|
649
|
+
//#region src/theme/theme-contracts.d.ts
|
|
650
|
+
/**
|
|
651
|
+
* SCREEN-2002 — the TUI's one theme token model.
|
|
652
|
+
*
|
|
653
|
+
* Before this, five things decided a colour: `PALETTE` (Ink names), `ANSI` (raw SGR for the markdown
|
|
654
|
+
* pipeline), `marked-terminal`'s own chalk defaults, `cli-highlight`'s `DEFAULT_THEME`, and a handful
|
|
655
|
+
* of `chalk.<name>` calls. A theme that rewrote only the first two would leave a daltonized run with
|
|
656
|
+
* red/green code blocks, because `cli-highlight` falls back PER KEY to its own theme. So the model
|
|
657
|
+
* carries every group a renderer reads, and the style builder derives every encoding from it through
|
|
658
|
+
* chalk — which is exactly what Ink's own `colorize` does, so no mapping layer is invented.
|
|
659
|
+
*
|
|
660
|
+
* Values use INK'S colour grammar verbatim (`<chalk name> | #rrggbb | ansi256(n) | rgb(r,g,b)`), so a
|
|
661
|
+
* theme file, a built-in and a component all speak one language and the grammar doubles as the
|
|
662
|
+
* injection floor: no raw escape sequence can enter through a theme.
|
|
663
|
+
*/
|
|
664
|
+
/** A colour in Ink's grammar. Validated at the boundary, never parsed twice. */
|
|
665
|
+
type TThemeColor = string;
|
|
666
|
+
/** Foreground and border roles every Ink component reads. */
|
|
667
|
+
interface IThemeColors {
|
|
668
|
+
readonly text: {
|
|
669
|
+
readonly accent: TThemeColor;
|
|
670
|
+
readonly emphasis: TThemeColor;
|
|
671
|
+
readonly success: TThemeColor;
|
|
672
|
+
readonly warning: TThemeColor;
|
|
673
|
+
readonly error: TThemeColor;
|
|
674
|
+
readonly session: TThemeColor;
|
|
675
|
+
readonly muted: TThemeColor;
|
|
676
|
+
readonly onAccent: TThemeColor;
|
|
677
|
+
};
|
|
678
|
+
readonly border: {
|
|
679
|
+
readonly attention: TThemeColor;
|
|
680
|
+
readonly focused: TThemeColor;
|
|
681
|
+
readonly active: TThemeColor;
|
|
682
|
+
readonly muted: TThemeColor;
|
|
683
|
+
readonly error: TThemeColor;
|
|
684
|
+
};
|
|
685
|
+
readonly status: {
|
|
686
|
+
readonly running: TThemeColor;
|
|
687
|
+
readonly success: TThemeColor;
|
|
688
|
+
readonly error: TThemeColor;
|
|
689
|
+
readonly denied: TThemeColor;
|
|
690
|
+
readonly waiting: TThemeColor;
|
|
691
|
+
readonly cancelled: TThemeColor;
|
|
692
|
+
readonly idle: TThemeColor;
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Every key `marked-terminal` colours by default, including `html` — a key left out would keep that
|
|
697
|
+
* dependency's own gray under every theme.
|
|
698
|
+
*
|
|
699
|
+
* Deliberately absent, because they carry no colour today and giving them one would change rendering
|
|
700
|
+
* rather than theme it: `strong` (`chalk.bold`), `em` (`chalk.italic`), `listitem` and `hr`
|
|
701
|
+
* (`chalk.reset`), and a diff's `diff `/`index ` metadata rows, which this package writes itself as
|
|
702
|
+
* dim over the inherited foreground.
|
|
703
|
+
*/
|
|
704
|
+
interface IThemeMarkdown {
|
|
705
|
+
readonly heading: TThemeColor;
|
|
706
|
+
readonly firstHeading: TThemeColor;
|
|
707
|
+
readonly code: TThemeColor;
|
|
708
|
+
readonly codespan: TThemeColor;
|
|
709
|
+
readonly link: TThemeColor;
|
|
710
|
+
readonly href: TThemeColor;
|
|
711
|
+
readonly blockquote: TThemeColor;
|
|
712
|
+
readonly del: TThemeColor;
|
|
713
|
+
readonly html: TThemeColor;
|
|
714
|
+
readonly diffAdded: TThemeColor;
|
|
715
|
+
readonly diffRemoved: TThemeColor;
|
|
716
|
+
readonly diffAddedBackground: TThemeColor;
|
|
717
|
+
readonly diffRemovedBackground: TThemeColor;
|
|
718
|
+
readonly diffHunk: TThemeColor;
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* `cli-highlight`'s seventeen coloured keys, ALL REQUIRED. Its `colorizeNode` reads
|
|
722
|
+
* `theme[token] || DEFAULT_THEME[token] || plain`, so one missing key restores that dependency's
|
|
723
|
+
* red/green pair — the exact thing a daltonized theme exists to remove.
|
|
724
|
+
*/
|
|
725
|
+
interface IThemeSyntax {
|
|
726
|
+
readonly keyword: TThemeColor;
|
|
727
|
+
readonly built_in: TThemeColor;
|
|
728
|
+
readonly type: TThemeColor;
|
|
729
|
+
readonly literal: TThemeColor;
|
|
730
|
+
readonly number: TThemeColor;
|
|
731
|
+
readonly regexp: TThemeColor;
|
|
732
|
+
readonly string: TThemeColor;
|
|
733
|
+
readonly class: TThemeColor;
|
|
734
|
+
readonly function: TThemeColor;
|
|
735
|
+
readonly comment: TThemeColor;
|
|
736
|
+
readonly doctag: TThemeColor;
|
|
737
|
+
readonly meta: TThemeColor;
|
|
738
|
+
readonly tag: TThemeColor;
|
|
739
|
+
readonly name: TThemeColor;
|
|
740
|
+
readonly attr: TThemeColor;
|
|
741
|
+
readonly addition: TThemeColor;
|
|
742
|
+
readonly deletion: TThemeColor;
|
|
743
|
+
}
|
|
744
|
+
/** The colour ramp of the package's one animation. Cadence is not themed. */
|
|
745
|
+
interface IThemeMotion {
|
|
746
|
+
readonly wave: readonly [TThemeColor, TThemeColor, TThemeColor, TThemeColor];
|
|
747
|
+
}
|
|
748
|
+
type TThemeAppearance = 'dark' | 'light';
|
|
749
|
+
type TThemeSource = 'built-in' | 'user' | 'plugin';
|
|
750
|
+
interface ITuiTheme {
|
|
751
|
+
/** `dark`, `light`, `dark-daltonized`, `light-daltonized`, `custom:<slug>`, `custom:<plugin>:<slug>`. */
|
|
752
|
+
readonly id: string;
|
|
753
|
+
readonly name: string;
|
|
754
|
+
readonly appearance: TThemeAppearance;
|
|
755
|
+
readonly source: TThemeSource;
|
|
756
|
+
readonly colors: IThemeColors;
|
|
757
|
+
readonly markdown: IThemeMarkdown;
|
|
758
|
+
readonly syntax: IThemeSyntax;
|
|
759
|
+
readonly motion: IThemeMotion;
|
|
760
|
+
}
|
|
761
|
+
//#endregion
|
|
762
|
+
//#region src/theme/built-in-themes.d.ts
|
|
763
|
+
/**
|
|
764
|
+
* The catalogue, as a function rather than the array itself. A caller outside `src/theme/` — the
|
|
765
|
+
* theme registry a picker reads — needs to ENUMERATE the built-ins, which is a different act from
|
|
766
|
+
* reaching into one of them for a colour; the floor refuses the second by refusing the DATA's names,
|
|
767
|
+
* so the first gets an accessor of its own instead of an exemption.
|
|
768
|
+
*/
|
|
769
|
+
declare function listBuiltInThemes(): readonly ITuiTheme[];
|
|
770
|
+
//#endregion
|
|
771
|
+
//#region src/theme/theme-registry.d.ts
|
|
772
|
+
/**
|
|
773
|
+
* A theme file that was found and refused. It is carried BESIDE the themes rather than among them,
|
|
774
|
+
* because a surface must be able to show the file without ever resolving to it — an id that can be
|
|
775
|
+
* listed and cannot be applied is the shape of the bug this avoids.
|
|
776
|
+
*/
|
|
777
|
+
interface IThemeSkip {
|
|
778
|
+
/**
|
|
779
|
+
* The id the file WOULD have had, so a `/theme <id>` that fails has a visible reason — or, when
|
|
780
|
+
* the file's own NAME is what made an id impossible, the quoted name in its place. It is a label,
|
|
781
|
+
* not a key: two files can carry the same one.
|
|
782
|
+
*/
|
|
783
|
+
readonly id: string;
|
|
784
|
+
readonly fileName: string;
|
|
785
|
+
/** The path-named diagnostic, verbatim from `parseThemeDocument`. */
|
|
786
|
+
readonly reason: string;
|
|
787
|
+
}
|
|
788
|
+
interface IThemeResolution {
|
|
789
|
+
readonly theme: ITuiTheme;
|
|
790
|
+
/** The id that was asked for and not found. Absent ⇒ the request was satisfied. */
|
|
791
|
+
readonly unknownId?: string;
|
|
792
|
+
}
|
|
793
|
+
interface IThemeRegistry {
|
|
794
|
+
list(): readonly ITuiTheme[];
|
|
795
|
+
get(id: string): ITuiTheme | undefined;
|
|
796
|
+
/** The theme for an id, falling back to the default and NAMING what it could not find. */
|
|
797
|
+
resolve(id: string | undefined): IThemeResolution;
|
|
798
|
+
/** The theme files that were found and refused, with the reason each was refused for. */
|
|
799
|
+
skipped(): readonly IThemeSkip[];
|
|
800
|
+
}
|
|
801
|
+
declare function createThemeRegistry(themes?: readonly ITuiTheme[], skipped?: readonly IThemeSkip[]): IThemeRegistry;
|
|
802
|
+
interface IThemeCataloguePortOptions {
|
|
803
|
+
readonly registry: IThemeRegistry;
|
|
804
|
+
/**
|
|
805
|
+
* Re-read on every call, not captured once: `/theme` reports what is PERSISTED, and the host
|
|
806
|
+
* applies a patch by writing the settings document. A snapshot would answer with the appearance
|
|
807
|
+
* the process started with, so the command would report the change it just made as not having
|
|
808
|
+
* happened.
|
|
809
|
+
*/
|
|
810
|
+
readonly readAppearance: () => IThemeAppearanceState['settings'];
|
|
811
|
+
/**
|
|
812
|
+
* The pin on reduced motion for this run, when something above the settings applied one — WHICH
|
|
813
|
+
* tier and WHAT it pinned, as one value. Two optional fields would let a caller supply the tier
|
|
814
|
+
* alone, and a default for the missing half is exactly the wrong answer this pair exists to stop:
|
|
815
|
+
* `--no-reduced-motion` is an override too and pins the opposite value.
|
|
816
|
+
*/
|
|
817
|
+
readonly reducedMotionPin?: {
|
|
818
|
+
readonly tier: TReducedMotionOverride;
|
|
819
|
+
readonly reducedMotion: boolean;
|
|
820
|
+
} | undefined;
|
|
821
|
+
}
|
|
822
|
+
declare function createThemeCataloguePort(options: IThemeCataloguePortOptions): IThemeCataloguePort;
|
|
823
|
+
//#endregion
|
|
824
|
+
//#region src/tui-cli-adapter.d.ts
|
|
825
|
+
/**
|
|
826
|
+
* CLI seam injected into the renderer.
|
|
827
|
+
*
|
|
828
|
+
* CMD-004 Phase 2 Stage C: READ-ONLY toward settings — the renderer re-reads the persisted
|
|
829
|
+
* settings document for display (statusline refresh-on-result) but never writes it. All settings
|
|
830
|
+
* mutations are host actions executed by the session layer via `ICommandHostAdapters`.
|
|
831
|
+
*/
|
|
832
|
+
interface ITuiCliAdapter {
|
|
833
|
+
getUserSettingsPath(): string;
|
|
834
|
+
readSettings(path: string): Record<string, TUniversalValue>;
|
|
835
|
+
reloadPluginCommandSource(registry: CommandRegistry): void;
|
|
836
|
+
applyActiveModelChange(cwd: string, modelId: string, options?: {
|
|
837
|
+
providerOverride?: string;
|
|
838
|
+
}): {
|
|
839
|
+
applied: boolean;
|
|
840
|
+
};
|
|
841
|
+
getGitBranch(cwd: string): string | undefined;
|
|
842
|
+
getProviderDisplayName(type: string): string;
|
|
843
|
+
/** Optional host-owned command shown when a completed fork can be reopened outside the TUI. */
|
|
844
|
+
formatResumeCommand?: (sessionId: string) => string;
|
|
845
|
+
}
|
|
846
|
+
//#endregion
|
|
847
|
+
//#region src/wire-tui-client-commands.d.ts
|
|
848
|
+
/** What a client-run command may use: this terminal's handoff and working directory. */
|
|
849
|
+
type TTuiClientCommandHost = ICommandHostTerminalHandoff & ICommandHostWorkspace;
|
|
850
|
+
/**
|
|
851
|
+
* A command this terminal runs itself. Declared here rather than imported: the command package's
|
|
852
|
+
* `createTerminalClientCommands` produces objects of this shape, and this package does not depend on
|
|
853
|
+
* the command package.
|
|
854
|
+
*/
|
|
855
|
+
interface ITuiClientCommand {
|
|
856
|
+
readonly name: string;
|
|
857
|
+
execute(host: TTuiClientCommandHost, args: string): ICommandResult | Promise<ICommandResult>;
|
|
858
|
+
}
|
|
859
|
+
/** The client-run commands, and how this terminal writes what they change. */
|
|
860
|
+
interface ITuiClientCommands {
|
|
861
|
+
readonly commands: readonly ITuiClientCommand[];
|
|
862
|
+
/** Writes the appearance keys of the user's settings; resolves when written. */
|
|
863
|
+
writeAppearanceSettings(patch: TAppearanceSettingsPatch): void | Promise<void>;
|
|
864
|
+
}
|
|
865
|
+
//#endregion
|
|
866
|
+
//#region src/render.d.ts
|
|
867
|
+
interface IRenderOptions {
|
|
868
|
+
cwd: string;
|
|
869
|
+
livePromptTrace?: ILivePromptTracePort;
|
|
870
|
+
/** Product identity for terminal labels, title, and host-facing copy. */
|
|
871
|
+
productDisplayName?: string;
|
|
872
|
+
modelCommandToolPrefix?: string;
|
|
873
|
+
subagentHookEnvironmentNames?: ICreateSessionOptions['subagentHookEnvironmentNames'];
|
|
874
|
+
observerFailureWarningCode?: ICreateSessionOptions['observerFailureWarningCode'];
|
|
875
|
+
commandHookShell?: string;
|
|
876
|
+
/** Skip instruction files and plugin discovery (`--safe-mode`). */
|
|
877
|
+
bare?: boolean;
|
|
878
|
+
/** Run no hook the settings layers declare (`--safe-mode`). */
|
|
879
|
+
skipConfiguredHooks?: boolean;
|
|
880
|
+
promptFileReferenceTag?: string;
|
|
881
|
+
provider: IAIProvider;
|
|
882
|
+
providerErrorGuidance?: IProviderErrorGuidance;
|
|
883
|
+
projectAccess?: TWorkspaceProjectAccess;
|
|
884
|
+
projectSettingsPaths?: readonly IProjectSettingsPath[];
|
|
885
|
+
baselinePermissionAllow?: readonly string[];
|
|
886
|
+
/** Host-selected task-context root; absent means no framework task-directory scan. */
|
|
887
|
+
taskContext?: {
|
|
888
|
+
readonly enabled?: boolean;
|
|
889
|
+
readonly dir?: string;
|
|
890
|
+
};
|
|
891
|
+
contributionSources?: readonly IContributionSource[];
|
|
892
|
+
skillRoots?: readonly ISkillRootDescriptor[];
|
|
893
|
+
userSettingsSources?: readonly INodeHostSettingsSource[];
|
|
894
|
+
environment?: Readonly<Record<string, string | undefined>>;
|
|
895
|
+
resolveProviderCredential?: TProviderCredentialResolver;
|
|
896
|
+
/**
|
|
897
|
+
* CLI-083 (issue #2287) — the org policy, forwarded to the session so `blockedCommands` is
|
|
898
|
+
* enforced on the direct CLI path as well as under `--serve`.
|
|
899
|
+
*
|
|
900
|
+
* DECLARED, not merely spread through. The shell forwards this with
|
|
901
|
+
* `...(orgPolicy === null ? {} : { orgPolicy })`, and a spread bypasses TypeScript's
|
|
902
|
+
* excess-property check — so before this field existed the value compiled, arrived, and was
|
|
903
|
+
* dropped by `toChannelOptions` below, which copies field by field. The idiom that looked safest
|
|
904
|
+
* is what disabled the one check that would have caught the missing declaration.
|
|
905
|
+
*/
|
|
906
|
+
orgPolicy?: IOrgPolicy | undefined;
|
|
907
|
+
/**
|
|
908
|
+
* Builds the authority- and permission-backed edit checkpoint store for one session; absent, no
|
|
909
|
+
* session keeps checkpoints. A factory, not a store: a session switch builds the next channel
|
|
910
|
+
* while the old session may still be finishing a turn, and a store holds one turn in progress.
|
|
911
|
+
*/
|
|
912
|
+
createEditCheckpointStore?: () => EditCheckpointStore;
|
|
913
|
+
/** The host's way to build each external-event grant's verifier; absent, no grant opens. */
|
|
914
|
+
externalEventVerifierFactory?: TInteractiveSessionOptions['externalEventVerifierFactory'];
|
|
915
|
+
/**
|
|
916
|
+
* #3189: the run's grant history, handed to every session this TUI builds so a switch replays no
|
|
917
|
+
* spent token and resets no rate. DECLARED for the reason `orgPolicy` above is.
|
|
918
|
+
*/
|
|
919
|
+
externalEventGrantHistory?: TInteractiveSessionOptions['externalEventGrantHistory'];
|
|
920
|
+
providerOverride?: string | undefined;
|
|
921
|
+
/**
|
|
922
|
+
* #1844: forwarded to the session so `/provider switch` can construct the provider it switches TO.
|
|
923
|
+
*
|
|
924
|
+
* The session cannot discover these — they are assembled at the composition root from the provider
|
|
925
|
+
* packages. Without them the hot-swap throws with an empty supported-list, which is the failure
|
|
926
|
+
* this option exists to prevent rather than a nicety.
|
|
927
|
+
*/
|
|
928
|
+
providerDefinitions?: readonly IProviderDefinition[];
|
|
929
|
+
providerType?: string | undefined;
|
|
930
|
+
modelId?: string;
|
|
931
|
+
/** CLI-1988: resolved provider-neutral response style. */
|
|
932
|
+
outputStyle?: IOutputStylePrompt;
|
|
933
|
+
/** ARCH-013: resolved preset effort, forwarded to the session's `effort` seam. */
|
|
934
|
+
effort?: ITuiInteractionChannelOptions['effort'];
|
|
935
|
+
temperature?: number;
|
|
936
|
+
maxOutputTokens?: number;
|
|
937
|
+
/** Preset prompt seed, distinct from the replacing `systemPrompt` option. */
|
|
938
|
+
presetSystemPrompt?: string;
|
|
939
|
+
/** CLI-sourced additive prompt text, composed before the TUI is rendered. */
|
|
940
|
+
appendSystemPrompt?: string;
|
|
941
|
+
responseFormat?: ITuiInteractionChannelOptions['responseFormat'];
|
|
942
|
+
language?: string;
|
|
943
|
+
permissionMode?: TPermissionMode;
|
|
944
|
+
maxTurns?: number;
|
|
945
|
+
allowedTools?: readonly string[];
|
|
946
|
+
deniedTools?: readonly string[];
|
|
947
|
+
version?: string;
|
|
948
|
+
sessionStore?: IInteractiveSessionStore;
|
|
949
|
+
disableSessionLoops?: boolean;
|
|
950
|
+
resolveDefaultLoopPrompt?: () => string;
|
|
951
|
+
resumeSessionId?: string;
|
|
952
|
+
showSessionPickerOnStart?: boolean;
|
|
953
|
+
/** FLOW-2006: text a deep link prefilled into the composer. Never submitted on its own. */
|
|
954
|
+
initialInput?: string;
|
|
955
|
+
/** Where that text came from; `external-link` renders the provenance notice. */
|
|
956
|
+
initialInputOrigin?: 'external-link';
|
|
957
|
+
forkSession?: boolean;
|
|
958
|
+
/** Issue #3081: the startup session is the target of a `/cd` from this directory. */
|
|
959
|
+
workspaceMovedFrom?: string;
|
|
960
|
+
sessionName?: string;
|
|
961
|
+
backgroundTaskRunners?: IBackgroundTaskRunner[];
|
|
962
|
+
/** MCP-004: the tool-call handoff policy the composition root computed for this runtime. */
|
|
963
|
+
toolCallHandoff?: IToolCallHandoffPolicy;
|
|
964
|
+
subagentRunnerFactory?: TSubagentRunnerFactory;
|
|
965
|
+
/**
|
|
966
|
+
* ARCH-005: subagent definitions contributed by the composition root (the capability packs
|
|
967
|
+
* `assembleProduct` merged). Forwarded to the session's `agentDefinitions` seam; absent ⇒ unchanged.
|
|
968
|
+
*/
|
|
969
|
+
agentDefinitions?: readonly IAgentDefinition[];
|
|
970
|
+
agentDefinitionRoots?: readonly string[];
|
|
971
|
+
pluginDirectories?: {
|
|
972
|
+
readonly user?: string;
|
|
973
|
+
readonly project?: string;
|
|
974
|
+
};
|
|
975
|
+
/**
|
|
976
|
+
* ARCH-006: tools contributed by the composition root (the capability packs `assembleProduct` merged)
|
|
977
|
+
* and, when the profile hands the packs the whole tool surface, the suppressed framework default tier
|
|
978
|
+
* (`defaultTools: []`). Forwarded to the session's tool-composition seam; absent ⇒ unchanged.
|
|
979
|
+
*/
|
|
980
|
+
additionalTools?: IToolWithEventService[];
|
|
981
|
+
defaultTools?: readonly IToolWithEventService[];
|
|
982
|
+
/** The sandbox the shell tools run under, so the session can let a confined command skip the prompt. */
|
|
983
|
+
sandboxClient?: ICreateSessionOptions['sandboxClient'];
|
|
984
|
+
toolExecutionPolicy?: ICreateSessionOptions['toolExecutionPolicy'];
|
|
985
|
+
commandModules?: readonly ICommandModule[];
|
|
986
|
+
commandHostAdapters?: ICommandHostAdapters;
|
|
987
|
+
shellExec?: TShellExecFn;
|
|
988
|
+
/** REMOTE-006: optional remote-command policy (allow-by-default; local == remote). */
|
|
989
|
+
remoteCommandPolicy?: IRemoteCommandPolicy;
|
|
990
|
+
startupUpdateNotice?: Promise<string | undefined>;
|
|
991
|
+
transportRegistry?: ITransportRegistryView;
|
|
992
|
+
bindTransports?: ITuiInteractionChannelOptions['bindTransports'];
|
|
993
|
+
cliAdapter: ITuiCliAdapter;
|
|
994
|
+
reloadPluginCommandSource?: (registry: CommandRegistry) => void;
|
|
995
|
+
agentName?: string;
|
|
996
|
+
/** Active preset id selected at startup (PRESET-011 runtime state). Defaults to 'default'. */
|
|
997
|
+
activePresetId?: string;
|
|
998
|
+
/** Preset persona block composed as a `source: 'persona'` system-prompt section (priority 5). */
|
|
999
|
+
persona?: string;
|
|
1000
|
+
/** Preset execution capability: activate agent runtime + subagent/background dispatch. */
|
|
1001
|
+
enableParallelSubagents?: boolean;
|
|
1002
|
+
/** Preset execution capability: run a post-task self-verification step. */
|
|
1003
|
+
selfVerification?: boolean;
|
|
1004
|
+
/**
|
|
1005
|
+
* Called with each live channel (including session-switch re-creations). Lets the embedding
|
|
1006
|
+
* product wire process-level concerns (ERR-001 G1: error routing into the live session).
|
|
1007
|
+
*/
|
|
1008
|
+
onChannelReady?: (channel: TuiInteractionChannel) => void;
|
|
1009
|
+
/**
|
|
1010
|
+
* SELFHOST-008 P6: optional durable-memory store injected by the surface (agent-cli). Forwarded to the
|
|
1011
|
+
* channel → `buildRuntimeSession`; absent ⇒ memory OFF (today's behavior). Enablement is surface-owned.
|
|
1012
|
+
*/
|
|
1013
|
+
memoryStore?: IMemoryStore;
|
|
1014
|
+
/** SELFHOST-008 P6: optional automatic post-turn capture policy (absent ⇒ capture OFF). */
|
|
1015
|
+
automaticMemory?: IAutomaticMemoryConfig;
|
|
1016
|
+
/** SELFHOST-008 P6: optional per-turn recall policy (absent ⇒ recall OFF, startup-only injection). */
|
|
1017
|
+
recallMemory?: IPerTurnRecallConfig;
|
|
1018
|
+
/**
|
|
1019
|
+
* CLI-2004: the resolved screen-reader mode. DECLARED, not spread through — `toChannelOptions`
|
|
1020
|
+
* below copies field by field, so an undeclared field compiles, arrives and is silently dropped
|
|
1021
|
+
* (the ARCH-110 containment hazard the `orgPolicy` comment above records). Absent ⇒ mode OFF and
|
|
1022
|
+
* today's byte stream is unchanged.
|
|
1023
|
+
*/
|
|
1024
|
+
screenReader?: boolean | undefined;
|
|
1025
|
+
/** Host-selected raw timing overrides; absent values use the renderer's defaults. */
|
|
1026
|
+
screenReaderPacing?: IScreenReaderPacingOverrides;
|
|
1027
|
+
/** Host-selected cursor and turn-mark overrides; absent values use terminal detection. */
|
|
1028
|
+
terminalCapabilities?: ITerminalCapabilityOverrides;
|
|
1029
|
+
/** CLI-2004: which input turned the mode on — printed in the confirmation line. */
|
|
1030
|
+
screenReaderChannel?: TScreenReaderChannel | undefined;
|
|
1031
|
+
/** CLI-2004: mode off, but the environment suggests a reader is running ⇒ one advisory line. */
|
|
1032
|
+
screenReaderHint?: boolean | undefined;
|
|
1033
|
+
/** BEHAVIOR-2003: one watched source shared with the optional `/keybindings` command. */
|
|
1034
|
+
keybindingsSource?: IKeybindingsSource;
|
|
1035
|
+
/**
|
|
1036
|
+
* SCREEN-2002: the theme catalogue this run renders from, shared with the optional `/theme`
|
|
1037
|
+
* command. DECLARED, not spread — see the `screenReader` note above. Absent ⇒ the built-ins.
|
|
1038
|
+
*/
|
|
1039
|
+
themeRegistry?: IThemeRegistry;
|
|
1040
|
+
/** SCREEN-2002: reduced motion as the product shell resolved it (settings ← env ← flag). */
|
|
1041
|
+
reducedMotion?: boolean | undefined;
|
|
1042
|
+
/** SCREEN-2002: which tier decided it, when that was not the settings. */
|
|
1043
|
+
reducedMotionOverride?: TReducedMotionOverride | undefined;
|
|
1044
|
+
/**
|
|
1045
|
+
* SCREEN-1992: the focus-reporting override the product shell resolved from its own environment.
|
|
1046
|
+
* `true` forces DECSET 1004 on, `false` is the kill switch, absent ⇒ on for an interactive TTY.
|
|
1047
|
+
*/
|
|
1048
|
+
focusReporting?: boolean | undefined;
|
|
1049
|
+
/**
|
|
1050
|
+
* SCREEN-1993: prompt history, resolved by the product shell. `promptHistory` is the session-side
|
|
1051
|
+
* writer (forwarded to the channel like `memoryStore`); `promptHistorySource` and
|
|
1052
|
+
* `promptHistoryProject` feed the input area's Ctrl+R search. DECLARED, not spread through — the
|
|
1053
|
+
* projection below copies field by field. Absent ⇒ nothing is written and `ctrl+r` is inert.
|
|
1054
|
+
*/
|
|
1055
|
+
promptHistory?: IPromptHistoryOptions;
|
|
1056
|
+
promptHistorySource?: IPromptHistorySource;
|
|
1057
|
+
promptHistoryProject?: string;
|
|
1058
|
+
}
|
|
1059
|
+
declare function renderApp(options: IRenderOptions): Promise<void>;
|
|
1060
|
+
/**
|
|
1061
|
+
* What the full TUI needs to attach to a session a host runs (a daemon) instead of building one.
|
|
1062
|
+
* Only presentation options: everything else belongs to the host's session.
|
|
1063
|
+
*/
|
|
1064
|
+
interface IRenderAttachedAppOptions extends Pick<IRenderOptions, 'cwd' | 'productDisplayName' | 'version' | 'cliAdapter' | 'screenReader' | 'screenReaderChannel' | 'screenReaderHint' | 'screenReaderPacing' | 'terminalCapabilities' | 'keybindingsSource' | 'themeRegistry' | 'reducedMotion' | 'reducedMotionOverride' | 'focusReporting' | 'promptHistorySource' | 'promptHistoryProject'> {
|
|
1065
|
+
/** The session protocol connection; closing it belongs to the caller. */
|
|
1066
|
+
readonly connection: IAttachedSessionConnection;
|
|
1067
|
+
/** Shown as the session's label until the session reports its own name. */
|
|
1068
|
+
readonly sessionLabel: string;
|
|
1069
|
+
/** This terminal's driver id, from the attach handshake. */
|
|
1070
|
+
readonly driverId: string;
|
|
1071
|
+
/** Commands this terminal runs itself (`/shell`, `/theme`, ...); the host never sees them. */
|
|
1072
|
+
readonly clientCommands?: ITuiClientCommands;
|
|
1073
|
+
/**
|
|
1074
|
+
* How this terminal is on the session: `'drive'` (the default) sends prompts and answers questions;
|
|
1075
|
+
* `'observe'` only watches, and the host refuses anything else from it.
|
|
1076
|
+
*/
|
|
1077
|
+
readonly mode?: 'drive' | 'observe';
|
|
1078
|
+
/** Print the screen-reader line; false when this process already printed it. Default true. */
|
|
1079
|
+
readonly announce?: boolean;
|
|
1080
|
+
}
|
|
1081
|
+
/**
|
|
1082
|
+
* Render the full TUI on a session the terminal is attached to over the session protocol. Leaving
|
|
1083
|
+
* only detaches: the session keeps running. Resolves `'user'` when the user leaves (`/exit`,
|
|
1084
|
+
* Ctrl-C) and `'closed'` when the connection closed.
|
|
1085
|
+
*/
|
|
1086
|
+
declare function renderAttachedApp(options: IRenderAttachedAppOptions): Promise<TAttachedSessionEnd>;
|
|
1087
|
+
//#endregion
|
|
1088
|
+
//#region src/SupervisedSessionView.d.ts
|
|
1089
|
+
interface ISupervisedViewRow {
|
|
1090
|
+
readonly id: string;
|
|
1091
|
+
readonly liveness: 'alive' | 'dead' | 'unknown';
|
|
1092
|
+
readonly control: 'available' | 'unavailable';
|
|
1093
|
+
readonly activity: 'working' | 'needs-input' | 'idle' | 'unknown';
|
|
1094
|
+
readonly nextLoopAt?: string;
|
|
1095
|
+
readonly name?: string;
|
|
1096
|
+
readonly cwd?: string;
|
|
1097
|
+
readonly pr?: {
|
|
1098
|
+
readonly url: string;
|
|
1099
|
+
readonly host: string;
|
|
1100
|
+
readonly number: number;
|
|
1101
|
+
readonly kind: 'pull' | 'merge-request';
|
|
1102
|
+
};
|
|
1103
|
+
readonly problem?: 'invalid-registration';
|
|
1104
|
+
/** The verified registration generation; a row without one never offers an action. Never rendered. */
|
|
1105
|
+
readonly generation?: string;
|
|
1106
|
+
}
|
|
1107
|
+
/** An attach the user confirmed in the view, bound to the process start the row showed. */
|
|
1108
|
+
interface ISupervisedAttachRequest {
|
|
1109
|
+
readonly id: string;
|
|
1110
|
+
readonly generation: string;
|
|
1111
|
+
readonly mode: 'drive' | 'observe';
|
|
1112
|
+
/** How the view was grouped, so it can reopen the same way after the attach. */
|
|
1113
|
+
readonly groupByDirectory: boolean;
|
|
1114
|
+
}
|
|
1115
|
+
/** How the view ended: closed, or handed to the host to attach and then come back. */
|
|
1116
|
+
type TSupervisedViewExit = {
|
|
1117
|
+
readonly kind: 'closed';
|
|
1118
|
+
} | ({
|
|
1119
|
+
readonly kind: 'attach';
|
|
1120
|
+
} & ISupervisedAttachRequest);
|
|
1121
|
+
/**
|
|
1122
|
+
* How a new session starts in a folder that is not trusted: trusted first (`trust` records the grant),
|
|
1123
|
+
* or `restricted`, without the project's own configuration. A person chose it in the view.
|
|
1124
|
+
*/
|
|
1125
|
+
type TSupervisedStartTrustChoice = 'trust' | 'restricted';
|
|
1126
|
+
/** What the person is asked about: the folder a new session would start in, and what trust loads. */
|
|
1127
|
+
interface ISupervisedStartTrustQuestion {
|
|
1128
|
+
readonly folder: string;
|
|
1129
|
+
/** What trusting it would load, one line each. */
|
|
1130
|
+
readonly loads: readonly string[];
|
|
1131
|
+
}
|
|
1132
|
+
interface ISupervisedSessionViewProps {
|
|
1133
|
+
readonly loadRows: (signal: AbortSignal) => Promise<readonly ISupervisedViewRow[]>;
|
|
1134
|
+
/** Called once the user confirmed; the view then closes so the host can attach this terminal. */
|
|
1135
|
+
readonly onAttach?: (request: ISupervisedAttachRequest) => void;
|
|
1136
|
+
/** Receives the generation the row displayed, so a session restarted under the same id is refused. */
|
|
1137
|
+
readonly onStop?: (id: string, generation: string) => Promise<void>;
|
|
1138
|
+
readonly onStart?: (choice?: TSupervisedStartTrustChoice) => Promise<string>;
|
|
1139
|
+
/** The question to ask when the folder a new session starts in is not trusted yet; none otherwise. */
|
|
1140
|
+
readonly startTrustQuestion?: () => Promise<ISupervisedStartTrustQuestion | undefined>;
|
|
1141
|
+
/** Product-owned command shown when a long trust question is shortened. */
|
|
1142
|
+
readonly trustStatusCommand?: string;
|
|
1143
|
+
readonly onOpenPr?: (id: string, url: string, generation: string) => Promise<void>;
|
|
1144
|
+
readonly filteredByCwd?: boolean;
|
|
1145
|
+
readonly filteredByName?: boolean;
|
|
1146
|
+
readonly filteredByPr?: boolean;
|
|
1147
|
+
readonly stateFilter?: TGroup;
|
|
1148
|
+
readonly refreshMs?: number;
|
|
1149
|
+
/** The row to select first, when it is still listed — the one an attach left from. */
|
|
1150
|
+
readonly initialSelectedId?: string;
|
|
1151
|
+
readonly initialGroupByDirectory?: boolean;
|
|
1152
|
+
}
|
|
1153
|
+
declare const GROUP_ORDER: readonly ["needs-input", "working", "idle", "unknown", "unverified", "dead"];
|
|
1154
|
+
type TGroup = (typeof GROUP_ORDER)[number];
|
|
1155
|
+
declare function renderSupervisedSessionView(options: ISupervisedSessionViewProps & {
|
|
1156
|
+
readonly screenReader: boolean;
|
|
1157
|
+
readonly screenReaderChannel?: TScreenReaderChannel;
|
|
1158
|
+
readonly screenReaderHint?: boolean;
|
|
1159
|
+
/** Print the screen-reader line; false when this process already printed it. */
|
|
1160
|
+
readonly announce?: boolean;
|
|
1161
|
+
}): Promise<TSupervisedViewExit>;
|
|
1162
|
+
//#endregion
|
|
1163
|
+
//#region src/create-default-tui-cli-adapter.d.ts
|
|
1164
|
+
interface IDefaultTuiCliAdapterOptions {
|
|
1165
|
+
providerDefinitions: readonly IProviderDefinition[];
|
|
1166
|
+
reloadPluginCommandSource: (registry: CommandRegistry) => void;
|
|
1167
|
+
userSettingsPath: string;
|
|
1168
|
+
settingsSources: readonly TSettingsSource[];
|
|
1169
|
+
formatResumeCommand?: (sessionId: string) => string;
|
|
1170
|
+
}
|
|
1171
|
+
declare function createDefaultTuiCliAdapter({ providerDefinitions, reloadPluginCommandSource, userSettingsPath, settingsSources, formatResumeCommand }: IDefaultTuiCliAdapterOptions): ITuiCliAdapter;
|
|
1172
|
+
//#endregion
|
|
1173
|
+
//#region src/theme/theme-document.d.ts
|
|
1174
|
+
interface IThemeDocumentInput {
|
|
1175
|
+
/** The namespaced id the caller minted — `custom:<slug>` or `custom:<plugin>:<slug>`. */
|
|
1176
|
+
readonly id: string;
|
|
1177
|
+
/** The file's own name, for the `Skipped theme "<file>": …` line. */
|
|
1178
|
+
readonly fileName: string;
|
|
1179
|
+
readonly source: TThemeSource;
|
|
1180
|
+
readonly text: string;
|
|
1181
|
+
}
|
|
1182
|
+
type TThemeDocumentResult = {
|
|
1183
|
+
readonly ok: true;
|
|
1184
|
+
readonly theme: ITuiTheme;
|
|
1185
|
+
} | {
|
|
1186
|
+
readonly ok: false;
|
|
1187
|
+
readonly error: string;
|
|
1188
|
+
};
|
|
1189
|
+
/**
|
|
1190
|
+
* Untrusted text on its way into a line a terminal will print — the one escaping policy, exported
|
|
1191
|
+
* so the surfaces that build their OWN diagnostics use it rather than re-deriving it.
|
|
1192
|
+
*
|
|
1193
|
+
* A diagnostic is the one part of a refused file that reaches the terminal, and it quotes what was
|
|
1194
|
+
* wrong — so without this the injection floor the grammar provides is defeated by the message that
|
|
1195
|
+
* reports a violation of it. Escaped rather than stripped, because an author has to SEE what their
|
|
1196
|
+
* file contains (`"\u001b[31m"`) instead of a value that looks fine.
|
|
1197
|
+
*
|
|
1198
|
+
* `JSON.stringify` alone is NOT enough, and that is the whole reason this is a function: it escapes
|
|
1199
|
+
* U+0000–U+001F and leaves U+007F and the C1 range literal — including U+009B and U+009D, the
|
|
1200
|
+
* single-byte spellings of CSI and OSC. A terminal accepts both spellings (`sanitize-terminal-text.ts`
|
|
1201
|
+
* says so and handles both), so quoting only the 7-bit one leaves the 8-bit one's parameters
|
|
1202
|
+
* standing as a live sequence.
|
|
1203
|
+
*/
|
|
1204
|
+
declare function quoteThemeText(value: string): string;
|
|
1205
|
+
/**
|
|
1206
|
+
* The same escaping WITHOUT the surrounding quotes, for a field a caller already quotes — so a
|
|
1207
|
+
* refused file does not print as `Skipped theme ""My Theme.json"": …`.
|
|
1208
|
+
*/
|
|
1209
|
+
declare function escapeThemeText(value: string): string;
|
|
1210
|
+
/**
|
|
1211
|
+
* Prose a surface did not write — a dependency's message, a path from the environment. Sanitized
|
|
1212
|
+
* rather than quoted, because it is a sentence; `sanitizeTerminalText` removes both spellings of
|
|
1213
|
+
* every sequence, and the tab/newline it keeps are flattened so one diagnostic stays one line.
|
|
1214
|
+
*/
|
|
1215
|
+
declare function sanitizeThemeProse(message: string): string;
|
|
1216
|
+
/**
|
|
1217
|
+
* Parse one theme file. The `id`, the `source` and the `appearance` are NOT the document's to
|
|
1218
|
+
* decide: the id is minted from where the file was found so nothing can shadow a built-in, the
|
|
1219
|
+
* source is where it was read from, and the appearance follows the base a theme chose to extend.
|
|
1220
|
+
*/
|
|
1221
|
+
declare function parseThemeDocument(input: IThemeDocumentInput): TThemeDocumentResult;
|
|
1222
|
+
//#endregion
|
|
1223
|
+
export { type IAttachedSessionConnection, type IDefaultTuiCliAdapterOptions, type IKeybindingDiagnostic, type IKeybindingSnapshot, type IKeybindingWarning, type IKeybindingsFilePort, type IKeybindingsSource, type INodeKeybindingsSourceOptions, type IRenderAttachedAppOptions, type IRenderOptions, type IScreenReaderPacingOverrides, type ISupervisedAttachRequest, type ISupervisedSessionViewProps, type ISupervisedStartTrustQuestion, type ISupervisedViewRow, type ITerminalCapabilityOverrides, type IThemeCataloguePortOptions, type IThemeDocumentInput, type IThemeRegistry, type IThemeResolution, type IThemeSkip, type ITuiCliAdapter, type ITuiClientCommand, type ITuiClientCommands, type ITuiCommandInteraction, type ITuiConfirmInteraction, type ITuiInteractionChannelOptions, type ITuiPickerInteraction, type ITuiPickerItem, type ITuiTheme, type TAnyTuiCommandInteraction, type TAttachedSessionEnd, type TKeybindingAction, type TKeybindingContext, type TOnMissingArgsAction, type TScreenReaderChannel, type TSupervisedStartTrustChoice, type TSupervisedViewExit, type TThemeDocumentResult, type TThemeSource, type TTuiClientCommandHost, TuiInteractionChannel, createDefaultTuiCliAdapter, createNodeKeybindingsSource, createThemeCataloguePort, createThemeRegistry, escapeThemeText, listBuiltInThemes, parseThemeDocument, quoteThemeText, renderApp, renderAttachedApp, renderSupervisedSessionView, sanitizeThemeProse };
|
|
1224
|
+
//# sourceMappingURL=index.d.ts.map
|