dsh-code 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +2 -2
- package/README.md +2 -2
- package/lib/index.mjs +5115 -4390
- package/lib/types/app.d.ts +18 -51
- package/lib/types/completion.d.ts +29 -0
- package/lib/types/composer.d.ts +150 -0
- package/lib/types/git-workflow.d.ts +6 -0
- package/lib/types/index.d.ts +6 -188
- package/lib/types/locales/en.d.ts +16 -4
- package/lib/types/{authorization-panel.d.ts → panels/authorization-panel.d.ts} +6 -1
- package/lib/types/panels/completion-panel.d.ts +13 -0
- package/lib/types/panels/interaction-bars.d.ts +38 -0
- package/lib/types/{kernel-panels.d.ts → panels/kernel-panels.d.ts} +16 -37
- package/lib/types/{language-panel.d.ts → panels/language-panel.d.ts} +1 -1
- package/lib/types/panels/model-panels.d.ts +86 -0
- package/lib/types/{theme-panel.d.ts → panels/theme-panel.d.ts} +1 -1
- package/lib/types/{update-panel.d.ts → panels/update-panel.d.ts} +1 -1
- package/lib/types/provider-settings.d.ts +11 -0
- package/lib/types/render/inspector.d.ts +8 -0
- package/lib/types/render/text.d.ts +4 -0
- package/lib/types/runner/harness-gate.d.ts +83 -0
- package/lib/types/runner/input-history.d.ts +31 -0
- package/lib/types/runner/mode-cycle.d.ts +44 -0
- package/lib/types/runner/preferences.d.ts +40 -0
- package/lib/types/runner/quit.d.ts +27 -0
- package/lib/types/runner/search-rows.d.ts +38 -0
- package/lib/types/runner/session-io.d.ts +46 -0
- package/lib/types/runner/session-target.d.ts +42 -0
- package/lib/types/runner/startup-config.d.ts +33 -0
- package/lib/types/runner/submissions.d.ts +87 -0
- package/lib/types/session/attach.d.ts +39 -0
- package/lib/types/{store.d.ts → session/store.d.ts} +1 -1
- package/lib/types/{subagents.d.ts → session/subagents.d.ts} +8 -1
- package/lib/types/settings-file.d.ts +10 -0
- package/lib/types/{panel-accent.d.ts → ui/panel-accent.d.ts} +1 -1
- package/lib/types/ui/panel-gap.d.ts +6 -0
- package/lib/types/ui/query-editor.d.ts +10 -0
- package/lib/types/ui/styled-rows.d.ts +8 -0
- package/lib/types/{terminal-title.d.ts → ui/terminal-title.d.ts} +1 -1
- package/lib/types/ui/ui-contract.d.ts +12 -0
- package/lib/types/ui/use-frames.d.ts +6 -0
- package/lib/types/ui/use-stable-input.d.ts +7 -0
- package/package.json +1 -1
- package/src/app.ts +543 -4066
- package/src/completion.ts +117 -0
- package/src/composer.ts +1956 -0
- package/src/git-workflow.ts +18 -0
- package/src/index.ts +113 -633
- package/src/internals.ts +1 -1
- package/src/locales/en.ts +16 -4
- package/src/locales/zh.ts +16 -4
- package/src/{authorization-panel.ts → panels/authorization-panel.ts} +25 -6
- package/src/panels/completion-panel.ts +79 -0
- package/src/panels/interaction-bars.ts +567 -0
- package/src/{kernel-panels.ts → panels/kernel-panels.ts} +84 -65
- package/src/{language-panel.ts → panels/language-panel.ts} +4 -4
- package/src/panels/model-panels.ts +1021 -0
- package/src/{theme-panel.ts → panels/theme-panel.ts} +5 -5
- package/src/{update-panel.ts → panels/update-panel.ts} +6 -6
- package/src/provider-settings.ts +38 -0
- package/src/render/inspector.ts +23 -0
- package/src/render/text.ts +8 -0
- package/src/runner/harness-gate.ts +168 -0
- package/src/runner/input-history.ts +77 -0
- package/src/runner/mode-cycle.ts +49 -0
- package/src/runner/preferences.ts +67 -0
- package/src/runner/quit.ts +53 -0
- package/src/runner/search-rows.ts +55 -0
- package/src/runner/session-io.ts +206 -0
- package/src/runner/session-target.ts +81 -0
- package/src/runner/startup-config.ts +54 -0
- package/src/runner/submissions.ts +157 -0
- package/src/session/attach.ts +87 -0
- package/src/{session-directory.ts → session/session-directory.ts} +1 -1
- package/src/{store.ts → session/store.ts} +1 -1
- package/src/{subagents.ts → session/subagents.ts} +12 -1
- package/src/settings-file.ts +19 -1
- package/src/{panel-accent.ts → ui/panel-accent.ts} +1 -1
- package/src/ui/panel-gap.ts +9 -0
- package/src/ui/query-editor.ts +16 -0
- package/src/ui/styled-rows.ts +124 -0
- package/src/{terminal-title.ts → ui/terminal-title.ts} +1 -1
- package/src/ui/ui-contract.ts +10 -0
- package/src/ui/use-frames.ts +23 -0
- package/src/ui/use-stable-input.ts +17 -0
- /package/lib/types/{fork.d.ts → session/fork.d.ts} +0 -0
- /package/lib/types/{history.d.ts → session/history.d.ts} +0 -0
- /package/lib/types/{session-directory.d.ts → session/session-directory.d.ts} +0 -0
- /package/lib/types/{session-switch.d.ts → session/session-switch.d.ts} +0 -0
- /package/src/{fork.ts → session/fork.ts} +0 -0
- /package/src/{history.ts → session/history.ts} +0 -0
- /package/src/{session-switch.ts → session/session-switch.ts} +0 -0
package/lib/types/app.d.ts
CHANGED
|
@@ -14,42 +14,34 @@
|
|
|
14
14
|
* @module @deepseek-ai/dsh-code/app
|
|
15
15
|
*/
|
|
16
16
|
import { type ReactElement } from 'react';
|
|
17
|
-
import type { CommandDescriptor } from '@deepseek-ai/dsh-commands';
|
|
18
17
|
import type { ContentBlock, FileBlock, ImageBlock } from '@deepseek-ai/dsh-llm';
|
|
19
18
|
import type { AuthorizationInteraction, AuthorizationStatus } from '@deepseek-ai/dsh-authorization';
|
|
20
19
|
import { type ThemeName } from './theme.ts';
|
|
21
20
|
import { type LanguageName } from './i18n.ts';
|
|
22
21
|
import type { LauncherUpdateStatus } from './update.ts';
|
|
23
|
-
import type { TranscriptStore } from './store.ts';
|
|
22
|
+
import type { TranscriptStore } from './session/store.ts';
|
|
24
23
|
import { type TranscriptEntry } from './render/projection.ts';
|
|
24
|
+
import { type SubagentAttachmentServices } from './session/attach.ts';
|
|
25
25
|
import type { ApprovalStore } from './approval.ts';
|
|
26
|
-
import {
|
|
26
|
+
import type { CommandsView } from './commands.ts';
|
|
27
27
|
import type { ModelDirectory, ModelRow } from './models.ts';
|
|
28
28
|
import { type DiscoveredModelView, type ProviderConfiguration, type ProviderSettingsDirectory, type ProviderTargetView } from './provider-settings.ts';
|
|
29
29
|
import type { QuestionStore } from './questions.ts';
|
|
30
|
-
import type { SkillsView
|
|
31
|
-
import {
|
|
32
|
-
import type { SubagentFeedView } from './subagents.ts';
|
|
30
|
+
import type { SkillsView } from './skills.ts';
|
|
31
|
+
import type { MentionCandidate } from './mentions.ts';
|
|
32
|
+
import type { SubagentFeedView } from './session/subagents.ts';
|
|
33
33
|
import type { UsageView } from './render/usage.ts';
|
|
34
|
-
import { type JobRow, type SearchRow } from './kernel-panels.ts';
|
|
34
|
+
import { type JobRow, type SearchRow } from './panels/kernel-panels.ts';
|
|
35
35
|
import type { PresetRow } from './presets.ts';
|
|
36
36
|
import type { PermissionRow } from './permissions.ts';
|
|
37
37
|
import type { PluginRow } from './plugin-inventory.ts';
|
|
38
|
-
import type { SessionDirectoryOptions, SessionRow } from './session-directory.ts';
|
|
39
|
-
import {
|
|
40
|
-
import {
|
|
41
|
-
import {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
export type QueueMutation = {
|
|
46
|
-
readonly kind: 'remove';
|
|
47
|
-
} | {
|
|
48
|
-
readonly kind: 'edit';
|
|
49
|
-
readonly text: string;
|
|
50
|
-
} | {
|
|
51
|
-
readonly kind: 'steer';
|
|
52
|
-
};
|
|
38
|
+
import type { SessionDirectoryOptions, SessionRow } from './session/session-directory.ts';
|
|
39
|
+
import type { GitDiffView, ReviewBranch, ReviewCommit, ReviewSelection } from './git-workflow.ts';
|
|
40
|
+
import type { ProviderAuthorizationDirectory, ProviderAuthorizationRow } from './authorization.ts';
|
|
41
|
+
import type { FilePathInspection, ImagePathInspection } from './attachments.ts';
|
|
42
|
+
export { completionCandidates, stepCompletionIndex } from './completion.ts';
|
|
43
|
+
import type { NoticeTone, QueueMutation } from './ui/ui-contract.ts';
|
|
44
|
+
export type { NoticeTone, QueueMutation } from './ui/ui-contract.ts';
|
|
53
45
|
/** Props the runner hands the app; callbacks stay owned by the runner. */
|
|
54
46
|
export interface AppProps {
|
|
55
47
|
/** Event-fed transcript store for the live session. */
|
|
@@ -132,6 +124,8 @@ export interface AppProps {
|
|
|
132
124
|
subscribeModelProviders?: (listener: () => void) => () => void;
|
|
133
125
|
/** Store or rotate one provider credential through the Harness credential service. */
|
|
134
126
|
saveModelProviderCredential?: (target: ProviderTargetView, key: string) => Promise<void>;
|
|
127
|
+
/** Switch a provider route to its subscription channel (drops the key reference). */
|
|
128
|
+
enableModelProviderSubscription?: (target: ProviderTargetView) => Promise<void>;
|
|
135
129
|
/** Remove one writable provider credential without removing its settings profile. */
|
|
136
130
|
unsetModelProviderCredential?: (target: ProviderTargetView) => Promise<void>;
|
|
137
131
|
/** Remove one user-owned provider profile and its page-managed credential. */
|
|
@@ -195,6 +189,8 @@ export interface AppProps {
|
|
|
195
189
|
searchSessions?: (query: string, signal?: AbortSignal) => Promise<readonly SearchRow[]>;
|
|
196
190
|
/** Load this session's subagent conversations (children by lineage). */
|
|
197
191
|
loadSubagents: () => Promise<readonly SessionRow[]>;
|
|
192
|
+
/** Live subagent attachment: seed + the two real-time buses, runner-wired. */
|
|
193
|
+
attachSubagent?: SubagentAttachmentServices;
|
|
198
194
|
switchSession: (row: SessionRow) => void;
|
|
199
195
|
cancelSessionSwitch: () => boolean;
|
|
200
196
|
loadPlugins: () => readonly PluginRow[];
|
|
@@ -252,34 +248,6 @@ export declare function streamTailBodyColumns(rowColumns: number, prefix: string
|
|
|
252
248
|
export declare function queuedInboxRows(entries: readonly TranscriptEntry[], ids: readonly string[]): readonly Extract<TranscriptEntry, {
|
|
253
249
|
kind: 'pending';
|
|
254
250
|
}>[];
|
|
255
|
-
/** One completion candidate row. */
|
|
256
|
-
interface CompletionCandidate {
|
|
257
|
-
/** Insertion text for the command name (with leading slash). */
|
|
258
|
-
label: string;
|
|
259
|
-
/** Human-readable description shown beside the label. */
|
|
260
|
-
description: string;
|
|
261
|
-
/** Candidate origin; skills land the same literal text but route through the prompt. */
|
|
262
|
-
origin: 'command' | 'skill' | 'mention';
|
|
263
|
-
}
|
|
264
|
-
/**
|
|
265
|
-
* Wrap one completion-menu cursor step. An empty menu keeps the index at 0:
|
|
266
|
-
* `% 0` is NaN, and a NaN index silently disables the highlight, the accept
|
|
267
|
-
* key, and any later Enter that runs through the menu.
|
|
268
|
-
*/
|
|
269
|
-
export declare function stepCompletionIndex(index: number, delta: number, count: number): number;
|
|
270
|
-
/**
|
|
271
|
-
* Resolve completion candidates for the current input: TUI-local commands,
|
|
272
|
-
* the live registry descriptors, and user-invocable skills, filtered by the
|
|
273
|
-
* typed prefix. Command names win collisions (the dispatch tries the
|
|
274
|
-
* registry first and only then falls through to the skill gesture), and a
|
|
275
|
-
* later duplicate name never renders twice.
|
|
276
|
-
*
|
|
277
|
-
* A bare `/` returns the FULL merged list — Codex's command popup shows every
|
|
278
|
-
* command inside a scroll window on an empty filter, and the menu's own
|
|
279
|
-
* selection window bounds the visible rows, so no slice cap is needed.
|
|
280
|
-
*/
|
|
281
|
-
export declare function completionCandidates(value: string, descriptors: readonly CommandDescriptor[], skills: readonly SkillRow[]): readonly CompletionCandidate[];
|
|
282
|
-
/** One cached settled row: the row Box plus its roomy-prompt spacers. */
|
|
283
251
|
interface SettledRowRecord {
|
|
284
252
|
/** The row Box element (keyed by the entry's settled index). */
|
|
285
253
|
box: ReactElement;
|
|
@@ -365,4 +333,3 @@ interface SettledRowsResult {
|
|
|
365
333
|
export declare function computeSettledRows(previous: SettledRowsCache | undefined, entries: readonly TranscriptEntry[], settled: number, showReasoning: boolean, resumed: boolean, epoch: number, columns?: number, rowCap?: number): SettledRowsResult;
|
|
366
334
|
/** The whole terminal app; state arrives via the store, output via Ink. */
|
|
367
335
|
export declare function App(props: AppProps): ReactElement;
|
|
368
|
-
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Slash-command parsing and completion candidates shared by the composer and help panel. */
|
|
2
|
+
import type { CommandDescriptor } from '@deepseek-ai/dsh-commands';
|
|
3
|
+
import { type MessageKey } from './i18n.ts';
|
|
4
|
+
import type { SkillRow } from './skills.ts';
|
|
5
|
+
/** One TUI-owned slash command: label plus its i18n description key. */
|
|
6
|
+
export interface LocalCommand {
|
|
7
|
+
readonly label: string;
|
|
8
|
+
readonly descriptionKey: MessageKey;
|
|
9
|
+
}
|
|
10
|
+
/** One source of truth for TUI-owned slash commands in completion and `/help`. */
|
|
11
|
+
export declare const LOCAL_COMMANDS: readonly LocalCommand[];
|
|
12
|
+
export declare const LOCAL_COMMAND_NAMES: ReadonlySet<string>;
|
|
13
|
+
/** TUI-local commands that reject trailing input instead of forwarding it as a prompt. */
|
|
14
|
+
export declare const BARE_LOCAL_COMMANDS: ReadonlySet<string>;
|
|
15
|
+
/** Split a slash line into the command name and any trailing input. */
|
|
16
|
+
export declare function slashNameAndArgs(text: string): {
|
|
17
|
+
readonly name: string;
|
|
18
|
+
readonly args: string;
|
|
19
|
+
} | undefined;
|
|
20
|
+
/** One completion candidate row. */
|
|
21
|
+
export interface CompletionCandidate {
|
|
22
|
+
readonly label: string;
|
|
23
|
+
readonly description: string;
|
|
24
|
+
readonly origin: 'command' | 'skill' | 'mention';
|
|
25
|
+
}
|
|
26
|
+
/** Wrap one completion-menu cursor step; an empty menu keeps the index at zero. */
|
|
27
|
+
export declare function stepCompletionIndex(index: number, delta: number, count: number): number;
|
|
28
|
+
/** Merge local commands, registry descriptors, and skills using dispatch shadowing order. */
|
|
29
|
+
export declare function completionCandidates(value: string, descriptors: readonly CommandDescriptor[], skills: readonly SkillRow[]): readonly CompletionCandidate[];
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/** Composer input, command routing, attachments, and one-shot composer animations. */
|
|
2
|
+
import { type ReactElement } from 'react';
|
|
3
|
+
import type { CommandDescriptor } from '@deepseek-ai/dsh-commands';
|
|
4
|
+
import type { ContentBlock, FileBlock, ImageBlock } from '@deepseek-ai/dsh-llm';
|
|
5
|
+
import { type FilePathInspection, type ImagePathInspection } from './attachments.ts';
|
|
6
|
+
import type { SkillRow } from './skills.ts';
|
|
7
|
+
import { type MentionCandidate } from './mentions.ts';
|
|
8
|
+
import { type ReviewSelection } from './git-workflow.ts';
|
|
9
|
+
import { type LanguageName } from './i18n.ts';
|
|
10
|
+
import { type DeepseekWaveStyle, type DeepseekWaveTier } from './render/animations.ts';
|
|
11
|
+
import type { TranscriptEntry } from './render/projection.ts';
|
|
12
|
+
import type { NoticeTone, QueueMutation } from './ui/ui-contract.ts';
|
|
13
|
+
/**
|
|
14
|
+
* The prompt box: TUI-local slash commands handled locally, other lines
|
|
15
|
+
* dispatched; input editing keeps a cursor with history and completion.
|
|
16
|
+
* While a modal (approval / question / model panel) owns the keys, the
|
|
17
|
+
* box passes every key through untouched.
|
|
18
|
+
*/
|
|
19
|
+
export declare function Composer({ active, frozen, frozenHint, busy, descriptors, skills, dispatch, steer, submitMode, cycleSubmitMode, interrupt, quit, openModel, openEffort, openHelp, openMode, openPermission, openResume, openSearch, openPlugin, openUpdate, openSchedule, openJobs, openStatusline, openTheme, openLanguage, saveLanguage, openHistory, openQueue, openAgents, openSubagent, openTodos, openUsage, openDelete, openDiff, openReviewPicker, reviewChanges, deleteConfirm, confirmDelete, cancelDelete, createSession, forkSession, cancelSessionSwitch, notify, applyEditorKeys, hasNotice, dismissNotice, toggleReasoning, openVerbose, clearView, refresh, loadMentions, inspectImages, prepareImages, inspectFiles, prepareFiles, cycleMode, exportTranscript, renameTitle, copyLastResponse, recallSpace, recordLocal, recordHistory, queued, updateQueued, historyFill, historyConsumed, animations, applyAnimations, applyRainbow, rainbowBurstId, waveTier, waveStyle, maxRows, anchorRowsBelow, tabTitle, onEditorRows, onMenuRows, sessionKey }: {
|
|
20
|
+
active: boolean;
|
|
21
|
+
frozen: boolean;
|
|
22
|
+
/** Frozen-band hint naming the surface that owns the keyboard; an empty
|
|
23
|
+
* draft otherwise advertises typing that the composer cannot accept. */
|
|
24
|
+
frozenHint?: string;
|
|
25
|
+
busy: boolean;
|
|
26
|
+
descriptors: readonly CommandDescriptor[];
|
|
27
|
+
skills: readonly SkillRow[];
|
|
28
|
+
dispatch: (text: string, attachments?: readonly ContentBlock[], origin?: string) => void;
|
|
29
|
+
/** Submit as steering into the running turn (see {@link AppProps.steer}). */
|
|
30
|
+
steer: (text: string, attachments?: readonly ContentBlock[], origin?: string) => void;
|
|
31
|
+
/** Delivery mode the next submission uses; Tab on an empty composer flips it. */
|
|
32
|
+
submitMode: 'queue' | 'steer';
|
|
33
|
+
/** Flip {@link submitMode} and report the new mode. */
|
|
34
|
+
cycleSubmitMode: () => void;
|
|
35
|
+
/** The full current session identity ('' while pending); the delivery origin. */
|
|
36
|
+
sessionKey: string;
|
|
37
|
+
interrupt: () => boolean;
|
|
38
|
+
quit: () => void;
|
|
39
|
+
openModel: () => void;
|
|
40
|
+
openEffort: () => void;
|
|
41
|
+
openHelp: () => void;
|
|
42
|
+
openMode: () => void;
|
|
43
|
+
openPermission: () => void;
|
|
44
|
+
openResume: () => void;
|
|
45
|
+
/** Open the /search panel with an optional seed query. */
|
|
46
|
+
openSearch: (query: string) => void;
|
|
47
|
+
openPlugin: (query?: string) => void;
|
|
48
|
+
/** Open the /update panel (aligned upgrade surface). */
|
|
49
|
+
openUpdate: () => void;
|
|
50
|
+
/** Open the /schedule reminder panel (read-only catalog). */
|
|
51
|
+
openSchedule: () => void;
|
|
52
|
+
openJobs: () => void;
|
|
53
|
+
openStatusline: () => void;
|
|
54
|
+
openTheme: () => void;
|
|
55
|
+
/** Open the /language picker (bare /language). */
|
|
56
|
+
openLanguage: () => void;
|
|
57
|
+
/** Apply and persist a language chosen by argument. */
|
|
58
|
+
saveLanguage: (name: LanguageName) => void;
|
|
59
|
+
openHistory: () => void;
|
|
60
|
+
openQueue: () => void;
|
|
61
|
+
/** Open the /agents panel (live subagent feed + transcript entry). */
|
|
62
|
+
openAgents: () => void;
|
|
63
|
+
/** Open the /subagent model panel. */
|
|
64
|
+
openSubagent: () => void;
|
|
65
|
+
/** Open the /todos subpage (full todo list in one bounded panel). */
|
|
66
|
+
openTodos: () => void;
|
|
67
|
+
openUsage: () => void;
|
|
68
|
+
/** Open the dedicated /delete picker, optionally pre-armed on one id. */
|
|
69
|
+
openDelete: (id?: string) => void;
|
|
70
|
+
openDiff: (argument: string) => void;
|
|
71
|
+
reviewChanges: (selection: ReviewSelection) => void;
|
|
72
|
+
/** Open the /review candidate picker (bare /review). */
|
|
73
|
+
openReviewPicker: () => void;
|
|
74
|
+
/** The row id awaiting y/n in this box, when a deletion is pending. */
|
|
75
|
+
deleteConfirm?: string;
|
|
76
|
+
/** Confirm the pending deletion (y in the box). */
|
|
77
|
+
confirmDelete: () => void;
|
|
78
|
+
/** Cancel the pending deletion (any other key in the box). */
|
|
79
|
+
cancelDelete: () => void;
|
|
80
|
+
createSession: (mode?: string) => void;
|
|
81
|
+
forkSession: (argument: string) => void;
|
|
82
|
+
cancelSessionSwitch: () => boolean;
|
|
83
|
+
notify: (text: string, tone?: NoticeTone) => void;
|
|
84
|
+
/** Apply the Ctrl+R passthrough to the detected editor (/vscode-keys); resolves to a one-line summary. */
|
|
85
|
+
applyEditorKeys: () => Promise<string>;
|
|
86
|
+
hasNotice: boolean;
|
|
87
|
+
dismissNotice: () => void;
|
|
88
|
+
toggleReasoning: () => void;
|
|
89
|
+
openVerbose: () => void;
|
|
90
|
+
clearView: () => void;
|
|
91
|
+
refresh: () => void;
|
|
92
|
+
loadMentions: (query: string, signal?: AbortSignal) => Promise<readonly MentionCandidate[]>;
|
|
93
|
+
inspectImages: (paths: readonly string[]) => Promise<readonly ImagePathInspection[]>;
|
|
94
|
+
prepareImages: (paths: readonly string[], signal?: AbortSignal) => Promise<readonly ImageBlock[]>;
|
|
95
|
+
inspectFiles: (paths: readonly string[]) => Promise<readonly FilePathInspection[]>;
|
|
96
|
+
prepareFiles: (paths: readonly string[], signal?: AbortSignal) => Promise<readonly FileBlock[]>;
|
|
97
|
+
cycleMode: () => string;
|
|
98
|
+
exportTranscript: (argument: string) => Promise<void>;
|
|
99
|
+
renameTitle: (argument: string) => string;
|
|
100
|
+
copyLastResponse: () => Promise<string>;
|
|
101
|
+
/** Newest-first recall space (persistent + in-session, deduped). */
|
|
102
|
+
recallSpace: readonly string[];
|
|
103
|
+
/** Record one in-session submission (deduped, local only). */
|
|
104
|
+
recordLocal: (text: string) => void;
|
|
105
|
+
/** Persist one submission to the global history file. */
|
|
106
|
+
recordHistory: (text: string) => void;
|
|
107
|
+
/** Next-turn inbox rows, ordered exactly as the durable inbox. */
|
|
108
|
+
queued: readonly Extract<TranscriptEntry, {
|
|
109
|
+
kind: 'pending';
|
|
110
|
+
}>[];
|
|
111
|
+
updateQueued?: (messageId: string, action: QueueMutation) => void;
|
|
112
|
+
/** Accepted /history entry waiting to be placed into the composer. */
|
|
113
|
+
historyFill: {
|
|
114
|
+
text: string;
|
|
115
|
+
index: number;
|
|
116
|
+
} | undefined;
|
|
117
|
+
/** Marks the accepted entry consumed (called after the fill is applied). */
|
|
118
|
+
historyConsumed: () => void;
|
|
119
|
+
/** Whether timed animations run (shimmer, chase, blink, wave). */
|
|
120
|
+
animations: boolean;
|
|
121
|
+
/** Apply and report one /animation toggle (App persists through the runner). */
|
|
122
|
+
applyAnimations: (enabled: boolean) => void;
|
|
123
|
+
/** Reroll or pin the rainbow palette (switches to rainbow if needed). */
|
|
124
|
+
applyRainbow: (seed?: number) => void;
|
|
125
|
+
/** Monotonic id of the in-flight /rainbow composer burst; 0 means none. */
|
|
126
|
+
rainbowBurstId: number;
|
|
127
|
+
/** DeepSeek easter-egg wave tier of the applied route (null otherwise):
|
|
128
|
+
* official DeepSeek models drive their flash/pro tiers, non-DeepSeek
|
|
129
|
+
* models running an effort above high drive the "Into the Unknown"
|
|
130
|
+
* variant. Drives the persistent prompt glyph/accent and the sparkle
|
|
131
|
+
* tier. */
|
|
132
|
+
waveTier: DeepseekWaveTier | null;
|
|
133
|
+
/** The ignition style running, if any: Wave / Aurora / Pulse. */
|
|
134
|
+
waveStyle: DeepseekWaveStyle | null;
|
|
135
|
+
/** Maximum physical editor rows the composer may occupy (see composerMaxRows). */
|
|
136
|
+
maxRows: number;
|
|
137
|
+
/** Terminal rows below the composer the editor does not own: the status
|
|
138
|
+
* footer and Ink's parked cursor row. The IME anchor adds these to the
|
|
139
|
+
* caret's in-band offset to reach that parked position. */
|
|
140
|
+
anchorRowsBelow: number;
|
|
141
|
+
/** The managed terminal tab label; re-asserted on terminal focus-in so a
|
|
142
|
+
* background process sharing the console cannot keep it overwritten. */
|
|
143
|
+
tabTitle: string;
|
|
144
|
+
/** Reports the editor's current physical row count so the live budget stays exact. */
|
|
145
|
+
onEditorRows: (rows: number) => void;
|
|
146
|
+
/** Reports the open completion menu's physical row count (0 when closed)
|
|
147
|
+
* for the same reason: the dynamic budget must reserve it, not overflow. */
|
|
148
|
+
onMenuRows: (rows: number) => void;
|
|
149
|
+
}): ReactElement;
|
|
150
|
+
/** One cached settled row: the row Box plus its roomy-prompt spacers. */
|
|
@@ -119,3 +119,9 @@ export declare function parseReviewConclusion(text: string): ReviewConclusion |
|
|
|
119
119
|
* priority plus the overall verdict, or a no-findings phrasing.
|
|
120
120
|
*/
|
|
121
121
|
export declare function reviewSummaryLine(conclusion: ReviewConclusion): string;
|
|
122
|
+
/**
|
|
123
|
+
* Resolve the working directory's git branch for the status line.
|
|
124
|
+
* @param cwd - the session's working directory.
|
|
125
|
+
* @returns the branch name, or '' outside a repository or on a detached HEAD.
|
|
126
|
+
*/
|
|
127
|
+
export declare function gitBranch(cwd: string): string;
|
package/lib/types/index.d.ts
CHANGED
|
@@ -10,13 +10,12 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { Context } from '@deepseek-ai/cordis';
|
|
12
12
|
import z from '@deepseek-ai/schemastery';
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
import type { SearchRow } from './kernel-panels.ts';
|
|
13
|
+
export { planCycleDecision, type ModeCycleDecision } from './runner/mode-cycle.ts';
|
|
14
|
+
export { runQuitSequence, type QuitCleanupStep } from './runner/quit.ts';
|
|
15
|
+
export { exportSessionIdSuffix, resolveTarget } from './runner/session-target.ts';
|
|
16
|
+
export { applyQueueMutation, cancelPreservingQueue, queueEditContent, StartupInputGate, submissionBelongsToSession, type QueuedSubmission, type QueueMutationOutcome, } from './runner/submissions.ts';
|
|
17
|
+
export { subagentCatalogSeed } from './session/subagents.ts';
|
|
18
|
+
export { searchHitToRow } from './runner/search-rows.ts';
|
|
20
19
|
/** Stable Cordis plugin name. */
|
|
21
20
|
export declare const name = "tui-runner";
|
|
22
21
|
/** Core services required before the interactive session can start. */
|
|
@@ -34,190 +33,9 @@ export interface Config {
|
|
|
34
33
|
};
|
|
35
34
|
}
|
|
36
35
|
export declare const Config: z<Config>;
|
|
37
|
-
/** The session identity this invocation will run, plus whether it is resumed. */
|
|
38
|
-
interface Target {
|
|
39
|
-
sessionId: string;
|
|
40
|
-
resume: boolean;
|
|
41
|
-
mode?: string;
|
|
42
|
-
cwd?: string;
|
|
43
|
-
seed?: readonly SessionEvent[];
|
|
44
|
-
parentSession?: SessionId;
|
|
45
|
-
/** Marks the session as a subagent conversation in the durable header. */
|
|
46
|
-
origin?: 'subagent';
|
|
47
|
-
seedLength?: number;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Reduce a session id to a filename-safe /export default-name suffix. Session
|
|
51
|
-
* ids are normally minted `session-<uuid>`, but `--session` accepts arbitrary
|
|
52
|
-
* user text: path separators must never leak into the default export filename
|
|
53
|
-
* (which would escape the session cwd).
|
|
54
|
-
* @param id - the session id.
|
|
55
|
-
* @returns at most the last 8 filename-safe characters.
|
|
56
|
-
*/
|
|
57
|
-
export declare function exportSessionIdSuffix(id: string): string;
|
|
58
|
-
/** One ordered step of the terminal quit cleanup. */
|
|
59
|
-
export interface QuitCleanupStep {
|
|
60
|
-
/** Step label used in diagnostics and tests. */
|
|
61
|
-
readonly name: string;
|
|
62
|
-
/** The step's async work; a rejection is contained by the sequence. */
|
|
63
|
-
readonly run: () => Promise<void>;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Run the ordered quit cleanup, then request exit. Every step rejection is
|
|
67
|
-
* contained (reported through `onError`) so a failed flush or dispose never
|
|
68
|
-
* skips the remaining cleanup; the exit request is always reached exactly
|
|
69
|
-
* once.
|
|
70
|
-
* @param steps - the cleanup steps in dependency order (settle the visible
|
|
71
|
-
* session, await the final in-flight composition, await durable recall).
|
|
72
|
-
* @param exit - the terminal exit request (code 0).
|
|
73
|
-
* @param onError - optional failure sink; called once per failing step and
|
|
74
|
-
* itself contained, so a throwing sink cannot abort the sequence.
|
|
75
|
-
* @returns the names of the steps that started, in order (for tests).
|
|
76
|
-
*/
|
|
77
|
-
export declare function runQuitSequence(steps: readonly QuitCleanupStep[], exit: (code: number) => void, onError?: (name: string, error: unknown) => void): Promise<readonly string[]>;
|
|
78
|
-
/** One composer submission waiting behind the startup delivery. */
|
|
79
|
-
export interface QueuedSubmission {
|
|
80
|
-
readonly text: string;
|
|
81
|
-
/** `steer` inserts into the running turn; `followup` waits for the next one. */
|
|
82
|
-
readonly mode: 'followup' | 'steer';
|
|
83
|
-
readonly images: readonly ContentBlock[];
|
|
84
|
-
}
|
|
85
|
-
/** What one requested queue mutation did; the runner maps it to one notice. */
|
|
86
|
-
export type QueueMutationOutcome = 'removed' | 'edited' | 'steered' | 'unavailable' | 'empty' | 'steerUnavailable';
|
|
87
|
-
/**
|
|
88
|
-
* Replace one queued message's text while keeping its attachments. A queue
|
|
89
|
-
* edit rewrites what the user typed, not what they attached: image and file
|
|
90
|
-
* blocks ride through in delivery order (text first, then attachments, the
|
|
91
|
-
* shape {@link deliverLine} submits). Dropping them here would silently strip
|
|
92
|
-
* an attachment the user already confirmed, so this is the edit's single
|
|
93
|
-
* definition and the panel's read-only marker only mirrors it.
|
|
94
|
-
*/
|
|
95
|
-
export declare function queueEditContent(content: readonly ContentBlock[], text: string): ContentBlock[];
|
|
96
|
-
/**
|
|
97
|
-
* Apply one terminal queue mutation to the live inbox. The decision and the
|
|
98
|
-
* inbox change are pure over the supplied handles so every branch is testable
|
|
99
|
-
* without an agent; steering itself is injected because it wakes the driver
|
|
100
|
-
* rather than mutating the inbox. The durable inbox splices remain the UI's
|
|
101
|
-
* single source of truth — this helper never reports a state the inbox did not
|
|
102
|
-
* actually reach.
|
|
103
|
-
* @param inbox - the live agent inbox (pending lists plus its mutators).
|
|
104
|
-
* @param status - the agent's lifecycle status; steering needs `running`.
|
|
105
|
-
* @param messageId - identity of the queued message to mutate.
|
|
106
|
-
* @param action - the requested mutation.
|
|
107
|
-
* @param steer - submits the removed message as next-step steering.
|
|
108
|
-
* @returns the outcome the caller reports.
|
|
109
|
-
*/
|
|
110
|
-
export declare function applyQueueMutation(inbox: Pick<Inbox, 'nextTurn' | 'append' | 'remove' | 'replace'>, status: AgentStatus, messageId: string, action: QueueMutation, steer: (message: UserMessage) => void): QueueMutationOutcome;
|
|
111
|
-
/**
|
|
112
|
-
* Cancel the active turn while keeping the next-turn queue, then wake the
|
|
113
|
-
* driver again so the preserved messages actually run. `cancel` clears
|
|
114
|
-
* pending work by default and never wakes the driver on its own, so the queue
|
|
115
|
-
* is captured first and re-submitted afterwards: a waking submission latches
|
|
116
|
-
* the wake while the aborted activity converges to idle, which is what turns
|
|
117
|
-
* "preserved" into "sent next" instead of "parked forever". Next-step
|
|
118
|
-
* steering is deliberately dropped — it belonged to the cancelled turn.
|
|
119
|
-
* @param agent - the live agent handle.
|
|
120
|
-
* @returns how many queued messages were preserved across the abort.
|
|
121
|
-
*/
|
|
122
|
-
export declare function cancelPreservingQueue(agent: Pick<Agent, 'inbox' | 'cancel' | 'followup'>): number;
|
|
123
|
-
/**
|
|
124
|
-
* Whether a tagged submission still belongs to the active session. Attachment
|
|
125
|
-
* prepares resolve on the microtask timeline, while a queued session switch
|
|
126
|
-
* remounts the app asynchronously — the composing instance's unmount cleanup
|
|
127
|
-
* runs too late to abort, so the delivery itself carries the composing
|
|
128
|
-
* session's full id and the runner drops it here when the world moved on.
|
|
129
|
-
* An untagged (synchronous) or pending-session ('') submission always passes.
|
|
130
|
-
*/
|
|
131
|
-
export declare function submissionBelongsToSession(origin: string | undefined, activeSessionId: string | undefined): boolean;
|
|
132
|
-
/**
|
|
133
|
-
* Root-log catalog facts a resumed session must replay into the subagent
|
|
134
|
-
* feed: constructor seeds never fire on the live bus, so without this the
|
|
135
|
-
* children of a resumed session vanish behind a restart. The empty-child
|
|
136
|
-
* placeholder row (childId '') is a placeholder, not a child, and stays out.
|
|
137
|
-
*/
|
|
138
|
-
export declare function subagentCatalogSeed(events: readonly SessionEvent[]): readonly SessionEvent<'subagent/catalog'>[];
|
|
139
|
-
/**
|
|
140
|
-
* Map one cross-session full-text hit onto the /search panel's row (pure).
|
|
141
|
-
* Labels fall back to the short id form — the engine's hit carries the
|
|
142
|
-
* strongest matching event, not the title observation.
|
|
143
|
-
*/
|
|
144
|
-
export declare function searchHitToRow(hit: {
|
|
145
|
-
header: SessionHeader;
|
|
146
|
-
bestMatch: {
|
|
147
|
-
snippet: string;
|
|
148
|
-
time: number;
|
|
149
|
-
};
|
|
150
|
-
}): SearchRow;
|
|
151
|
-
/** One Shift+Tab station decision for the mode cycle. */
|
|
152
|
-
export type ModeCycleDecision = {
|
|
153
|
-
readonly kind: 'permission';
|
|
154
|
-
readonly preset: string;
|
|
155
|
-
} | {
|
|
156
|
-
readonly kind: 'plan-on';
|
|
157
|
-
} | {
|
|
158
|
-
readonly kind: 'plan-off';
|
|
159
|
-
readonly preset: string;
|
|
160
|
-
};
|
|
161
|
-
/**
|
|
162
|
-
* Decide the next Shift+Tab station. The cycle keeps the preset table's
|
|
163
|
-
* own order (most restrictive first) and inserts ONE plan station between
|
|
164
|
-
* the most restrictive preset and the wrap target: with the shipped three
|
|
165
|
-
* presets the user sees workspace-write → danger-full-access → read-only
|
|
166
|
-
* → plan → workspace-write. Plan IS the most restrictive preset plus the
|
|
167
|
-
* plan prompt layer — entering it switches nothing (the cycle is already
|
|
168
|
-
* parked on read-only), and leaving it lands on the next preset after the
|
|
169
|
-
* most restrictive one. Without the /plan command the cycle is exactly the
|
|
170
|
-
* preset table.
|
|
171
|
-
*
|
|
172
|
-
* `planIntent` covers the committed fold's commit lag: upstream queues a
|
|
173
|
-
* plan switch during an open turn (and the command pipeline is async even
|
|
174
|
-
* idle), so the durable plan/mode event lands AFTER the press that chose
|
|
175
|
-
* it. While an intent from an earlier press is in flight it — not the
|
|
176
|
-
* stale committed fold — decides the station, so repeated presses advance
|
|
177
|
-
* the cycle instead of re-issuing the same plan transition (the stuck
|
|
178
|
-
* plan-on/plan-off toggle). Undefined falls back to the committed fold.
|
|
179
|
-
*/
|
|
180
|
-
export declare function planCycleDecision(input: {
|
|
181
|
-
readonly names: readonly string[];
|
|
182
|
-
readonly current: string;
|
|
183
|
-
readonly inPlan: boolean;
|
|
184
|
-
readonly planAvailable: boolean;
|
|
185
|
-
readonly planIntent?: boolean;
|
|
186
|
-
}): ModeCycleDecision | undefined;
|
|
187
|
-
/**
|
|
188
|
-
* Order-preserving gate for composer input while the startup prompt/images
|
|
189
|
-
* are still preparing. Anything submitted before the startup delivery settles
|
|
190
|
-
* queues and flushes afterwards in submit order, so the initial request can
|
|
191
|
-
* never be overtaken by typing that raced a slow image preparation. The flush
|
|
192
|
-
* also runs when the startup delivery fails: user input is never stranded.
|
|
193
|
-
*/
|
|
194
|
-
export declare class StartupInputGate {
|
|
195
|
-
private readonly deliver;
|
|
196
|
-
private readonly queued;
|
|
197
|
-
private pending;
|
|
198
|
-
constructor(deliver: (submission: QueuedSubmission) => void);
|
|
199
|
-
/** Submit one line: delivered now while idle, queued behind the startup delivery otherwise. */
|
|
200
|
-
submit(submission: QueuedSubmission): void;
|
|
201
|
-
/**
|
|
202
|
-
* Run the startup delivery — the callback receives the direct-delivery sink
|
|
203
|
-
* for the startup prompt itself — then flush everything that queued behind
|
|
204
|
-
* it, in order, even when the callback rejects.
|
|
205
|
-
*/
|
|
206
|
-
run(startup: (deliver: (submission: QueuedSubmission) => void) => Promise<void>): Promise<void>;
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* Resolve the invocation's target session against the persisted headers.
|
|
210
|
-
* @param startup - the parsed startup flags.
|
|
211
|
-
* @param persistence - the persistence service; required for resume/latest.
|
|
212
|
-
* @param cwd - the working directory `--continue` filters by.
|
|
213
|
-
* @returns the target identity.
|
|
214
|
-
* @throws with a user-facing message when the flags name nothing resolvable.
|
|
215
|
-
*/
|
|
216
|
-
export declare function resolveTarget(startup: TuiStartup, persistence: SessionPersistence | undefined, cwd: string): Promise<Target>;
|
|
217
36
|
/**
|
|
218
37
|
* Mount the interactive terminal driver.
|
|
219
38
|
* @param ctx - plugin context carrying core services and the launcher-provided exit request.
|
|
220
39
|
* @param config - validated startup config resolved from the tuiStartup provider.
|
|
221
40
|
*/
|
|
222
41
|
export declare function apply(ctx: Context, config: Config): void;
|
|
223
|
-
export {};
|
|
@@ -86,8 +86,15 @@ export declare const en: {
|
|
|
86
86
|
readonly 'schedule.titlePlural': "/schedule · {count} active reminders";
|
|
87
87
|
readonly 'schedule.empty': "no active reminders — the model creates them with schedule_create";
|
|
88
88
|
readonly 'document.loading': "loading transcript…";
|
|
89
|
+
readonly 'attach.bar': "observing · {label} · r reload · esc/ctrl+d back";
|
|
90
|
+
readonly 'attach.loading': "loading {label}'s conversation…";
|
|
91
|
+
readonly 'attach.status': "subagent {label} · {id} · {turns} turns";
|
|
92
|
+
readonly 'notice.attachUnavailable': "subagent attachment is unavailable in this profile";
|
|
89
93
|
readonly 'document.compact': "transcript · esc close";
|
|
90
|
-
readonly 'document.
|
|
94
|
+
readonly 'document.expanded': "expanded";
|
|
95
|
+
readonly 'document.refreshHint': "r refresh";
|
|
96
|
+
readonly 'document.footerExpanded': "lines {from}-{to}/{total} · ↑↓/pg/g/G{refresh} · esc/ctrl+d back";
|
|
97
|
+
readonly 'document.footer': "lines {from}-{to}/{total} · ↑↓/pg/g/G · enter/f expand · t/esc close";
|
|
91
98
|
readonly 'review.picker.title': "/review · choose a target";
|
|
92
99
|
readonly 'review.picker.uncommitted': "Review uncommitted changes (staged / unstaged / new files)";
|
|
93
100
|
readonly 'review.picker.branch': "Compare against a base branch (lists local branches)";
|
|
@@ -417,7 +424,6 @@ export declare const en: {
|
|
|
417
424
|
readonly 'panel.provider.notConfiguredDivider': "── not configured ──";
|
|
418
425
|
readonly 'panel.provider.title': "/model — providers";
|
|
419
426
|
readonly 'panel.provider.titleCount': "/model — providers · {index}/{total}";
|
|
420
|
-
readonly 'panel.provider.state': "{route} · {value}";
|
|
421
427
|
readonly 'panel.provider.key': "key {value}";
|
|
422
428
|
readonly 'panel.provider.authConfigured': "provider auth";
|
|
423
429
|
readonly 'panel.provider.noKey': "key missing";
|
|
@@ -432,7 +438,7 @@ export declare const en: {
|
|
|
432
438
|
readonly 'panel.provider.readOnlyLogin': "this login record is read-only";
|
|
433
439
|
readonly 'panel.provider.notManaged': "this provider is not managed by Harness settings";
|
|
434
440
|
readonly 'panel.providers.compact': "/model providers · enter configure · d remove key · esc back";
|
|
435
|
-
readonly 'panel.providers.footer': "↑↓ move · enter configure ·
|
|
441
|
+
readonly 'panel.providers.footer': "↑↓ move · enter configure · d remove key · x remove provider · r retry · esc back";
|
|
436
442
|
readonly 'panel.update.compact': "/update · {summary}";
|
|
437
443
|
readonly 'panel.update.checking': "checking…";
|
|
438
444
|
readonly 'panel.update.probeFailed': "probe failed";
|
|
@@ -460,8 +466,14 @@ export declare const en: {
|
|
|
460
466
|
readonly 'panel.setup.copyInto': "copy verbatim into {id}";
|
|
461
467
|
readonly 'panel.setup.copyTitle': "/model — copy efforts";
|
|
462
468
|
readonly 'panel.setup.copyFooter': "↑↓ move · enter copy · esc back";
|
|
469
|
+
readonly 'panel.setup.mode.subscribe': "Subscription";
|
|
470
|
+
readonly 'panel.setup.mode.key': "Key";
|
|
471
|
+
readonly 'panel.setup.mode.login.plan': "signed in · plan";
|
|
472
|
+
readonly 'panel.setup.mode.login.none': "not signed in";
|
|
473
|
+
readonly 'panel.setup.mode.login.running': "signing in…";
|
|
474
|
+
readonly 'panel.setup.mode.overridden': "⚠ the settings key overrides the plan sign-in";
|
|
463
475
|
readonly 'panel.setup.title': "/model — configure {provider}";
|
|
464
|
-
readonly 'panel.setup.footer': "↑↓ move · ←→ in/out · space remove · e efforts · c copy efforts · tab discover · enter save · esc back";
|
|
476
|
+
readonly 'panel.setup.footer': "↑↓ move · ←→ in/out · space remove · e efforts · c copy efforts · tab per channel (subscription = web sign-in, key = discover) · enter save · esc back";
|
|
465
477
|
readonly 'panel.discovery.compact': "model discovery · terminal too small · esc back";
|
|
466
478
|
readonly 'panel.discovery.loading': "discovering models…";
|
|
467
479
|
readonly 'panel.discovery.empty': "the endpoint advertised no models; add ids by hand on the setup page";
|
|
@@ -2,9 +2,14 @@
|
|
|
2
2
|
import { type ReactElement } from 'react';
|
|
3
3
|
import { type AuthorizationInteraction, type AuthorizationStatus } from '@deepseek-ai/dsh-authorization';
|
|
4
4
|
import type { CredentialKey } from '@deepseek-ai/dsh-credentials';
|
|
5
|
-
import type { ProviderAuthorizationRow } from '
|
|
5
|
+
import type { ProviderAuthorizationRow } from '../authorization.ts';
|
|
6
6
|
export interface ProviderAuthorizationPanelProps {
|
|
7
7
|
readonly row: ProviderAuthorizationRow;
|
|
8
|
+
/**
|
|
9
|
+
* Start this method immediately instead of showing the picker: a
|
|
10
|
+
* single-method provider signs in with no extra step.
|
|
11
|
+
*/
|
|
12
|
+
readonly autoStartMethod?: string;
|
|
8
13
|
begin(row: ProviderAuthorizationRow, method: string, interaction: AuthorizationInteraction, signal: AbortSignal): Promise<AuthorizationStatus>;
|
|
9
14
|
cancel(key: CredentialKey): void;
|
|
10
15
|
openUrl(url: string): boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Bounded slash-command and mention completion menu. */
|
|
2
|
+
import { type ReactElement } from 'react';
|
|
3
|
+
import type { CompletionCandidate } from '../completion.ts';
|
|
4
|
+
/** Total physical rows occupied by the completion menu at this terminal height. */
|
|
5
|
+
export declare function completionMenuRowCount(terminalRows: number, rowCount: number): number;
|
|
6
|
+
/** Completion view anchored directly above the composer band. */
|
|
7
|
+
export declare function CompletionMenu({ active, mention, index, rows, error }: {
|
|
8
|
+
active: boolean;
|
|
9
|
+
mention: boolean;
|
|
10
|
+
index: number;
|
|
11
|
+
rows: readonly CompletionCandidate[];
|
|
12
|
+
error?: string;
|
|
13
|
+
}): ReactElement | undefined;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Approval and structured-question keyboard-owned terminal surfaces. */
|
|
2
|
+
import { type ReactElement } from 'react';
|
|
3
|
+
import type { ApprovalSnapshot } from '../approval.ts';
|
|
4
|
+
import type { QuestionSnapshot, QuestionStore } from '../questions.ts';
|
|
5
|
+
import type { NoticeTone } from '../ui/ui-contract.ts';
|
|
6
|
+
/**
|
|
7
|
+
* The approval dialog (Codex ApprovalOverlay contract): a bold question
|
|
8
|
+
* header, the bounded command body with an explicit overflow marker, a
|
|
9
|
+
* numbered option list with a `›` cursor, single-key shortcuts, and digits
|
|
10
|
+
* for direct selection. Askers queue FIFO — the count rides the header.
|
|
11
|
+
* The upstream answerer vocabulary stays binary (`allowed-once` /
|
|
12
|
+
* `rejected`): "tell it what to do differently" rejects and hands the
|
|
13
|
+
* composer back with a hint notice, exactly Codex's decline-then-type flow.
|
|
14
|
+
*/
|
|
15
|
+
export declare function ApprovalBar({ snapshot, locked, notify, interrupt, summarize }: {
|
|
16
|
+
snapshot: ApprovalSnapshot;
|
|
17
|
+
locked: boolean;
|
|
18
|
+
notify: (text: string, tone?: NoticeTone) => void;
|
|
19
|
+
/** Cancel the running turn (Ctrl+C), matching the composer's busy branch. */
|
|
20
|
+
interrupt: () => boolean;
|
|
21
|
+
/** Render as the bounded one-line form even on tall terminals (another
|
|
22
|
+
* human-asked surface already owns the full panel budget). */
|
|
23
|
+
summarize?: boolean;
|
|
24
|
+
}): ReactElement | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* The ask_user_question bar: walks one request question by question,
|
|
27
|
+
* retaining an independent draft for every question. Options use Space/1-9
|
|
28
|
+
* to toggle a multi-select, Enter to confirm, and arrows/Ctrl+P/N to move
|
|
29
|
+
* between questions. Plan reviews arrive through the same service with a
|
|
30
|
+
* `plan-review` intent — the approve option gets a ✓ mark, the answer
|
|
31
|
+
* encoding stays identical.
|
|
32
|
+
*/
|
|
33
|
+
export declare function QuestionBar({ store, snapshot, locked }: {
|
|
34
|
+
store: QuestionStore;
|
|
35
|
+
snapshot: QuestionSnapshot;
|
|
36
|
+
locked: boolean;
|
|
37
|
+
}): ReactElement | undefined;
|
|
38
|
+
/** The /model panel: a scrolling list over the advisory model directory. */
|