dsh-code 1.2.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 +5 -5
- package/README.md +5 -5
- package/lib/index.mjs +6679 -5232
- package/lib/startup.mjs +1 -1
- package/lib/{theme-7u5Qo3dF.mjs → theme-B3orFUYz.mjs} +8 -0
- package/lib/types/app.d.ts +32 -45
- package/lib/types/attachments.d.ts +16 -7
- 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 +65 -5
- 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} +19 -38
- 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} +22 -1
- package/lib/types/provider-settings.d.ts +11 -0
- package/lib/types/render/inspector.d.ts +8 -0
- package/lib/types/render/status.d.ts +4 -1
- 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/{history.d.ts → session/history.d.ts} +10 -0
- package/lib/types/{session-directory.d.ts → session/session-directory.d.ts} +25 -1
- package/lib/types/{session-switch.d.ts → session/session-switch.d.ts} +8 -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/lib/types/version.d.ts +2 -0
- package/package.json +7 -5
- package/src/app.ts +707 -4108
- package/src/attachments.ts +65 -19
- package/src/completion.ts +117 -0
- package/src/composer.ts +1956 -0
- package/src/git-workflow.ts +18 -0
- package/src/index.ts +164 -645
- package/src/input-split.ts +24 -4
- package/src/internals.ts +1 -1
- package/src/locales/en.ts +66 -5
- package/src/locales/zh.ts +66 -5
- package/src/{authorization-panel.ts → panels/authorization-panel.ts} +30 -8
- 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} +142 -90
- 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} +117 -10
- package/src/provider-settings.ts +38 -0
- package/src/rainbow.ts +13 -3
- package/src/render/inspector.ts +23 -0
- package/src/render/status.ts +80 -29
- package/src/render/text.ts +10 -1
- 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/{fork.ts → session/fork.ts} +11 -7
- package/src/{history.ts → session/history.ts} +14 -0
- package/src/{session-directory.ts → session/session-directory.ts} +83 -4
- package/src/{session-switch.ts → session/session-switch.ts} +14 -0
- package/src/{store.ts → session/store.ts} +20 -2
- 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/src/version.ts +5 -0
- /package/lib/types/{fork.d.ts → session/fork.d.ts} +0 -0
package/lib/startup.mjs
CHANGED
|
@@ -538,6 +538,10 @@ function hueOf([r, g, b]) {
|
|
|
538
538
|
if (max === g) return (60 * (b - r) / span + 120) % 360;
|
|
539
539
|
return (60 * (r - g) / span + 240) % 360;
|
|
540
540
|
}
|
|
541
|
+
/** Strict RGB equality for the wrap-collision repair. */
|
|
542
|
+
function sameRgb(left, right) {
|
|
543
|
+
return left[0] === right[0] && left[1] === right[1] && left[2] === right[2];
|
|
544
|
+
}
|
|
541
545
|
/** A dark row tint for diff backgrounds: the hue at 22% strength over black. */
|
|
542
546
|
function darkTint(hue) {
|
|
543
547
|
return [
|
|
@@ -603,6 +607,10 @@ function rollRainbow(seed) {
|
|
|
603
607
|
TONE_ORDER.forEach((tone, index) => {
|
|
604
608
|
toneColors[tone] = pool[(offset + index) % pool.length];
|
|
605
609
|
});
|
|
610
|
+
if (sameRgb(toneColors.live, toneColors.error)) {
|
|
611
|
+
const replacement = pool.find((hue) => !sameRgb(hue, toneColors.live) && !sameRgb(hue, toneColors.warn));
|
|
612
|
+
if (replacement !== void 0) toneColors.error = replacement;
|
|
613
|
+
}
|
|
606
614
|
return {
|
|
607
615
|
seed,
|
|
608
616
|
palette,
|
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[];
|
|
@@ -234,32 +230,24 @@ export interface AppProps {
|
|
|
234
230
|
/** Apply the Ctrl+R terminal passthrough to the detected editor (/vscode-keys); resolves to a one-line summary. */
|
|
235
231
|
applyEditorKeys: () => Promise<string>;
|
|
236
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* The streaming buffer rendered with a hard size cap: the live region must
|
|
235
|
+
* ALWAYS fit the terminal, or Ink's erase/rewrite of a dynamic tree taller
|
|
236
|
+
* than the screen freezes (cursor-up past the top, garbage, no scroll). The
|
|
237
|
+
* cap counts explicit newlines and terminal wrapping, slicing from the END so
|
|
238
|
+
* the freshest tokens stay visible while a long reply streams; the complete
|
|
239
|
+
* text lands in the flushed scrollback once the turn assembles it.
|
|
240
|
+
*
|
|
241
|
+
* Body wrap width for a streaming tail. `rowColumns` is the same width
|
|
242
|
+
* passed to `transcriptEntryLines` (terminal minus the last-column safety);
|
|
243
|
+
* the hanging prefix then shrinks the body so streamed text and settled
|
|
244
|
+
* markdown wrap on the same column.
|
|
245
|
+
*/
|
|
246
|
+
export declare function streamTailBodyColumns(rowColumns: number, prefix: string, continuationPrefix?: string): number;
|
|
237
247
|
/** Rows in the exact next-turn inbox order, never transcript append order. */
|
|
238
248
|
export declare function queuedInboxRows(entries: readonly TranscriptEntry[], ids: readonly string[]): readonly Extract<TranscriptEntry, {
|
|
239
249
|
kind: 'pending';
|
|
240
250
|
}>[];
|
|
241
|
-
/** One completion candidate row. */
|
|
242
|
-
interface CompletionCandidate {
|
|
243
|
-
/** Insertion text for the command name (with leading slash). */
|
|
244
|
-
label: string;
|
|
245
|
-
/** Human-readable description shown beside the label. */
|
|
246
|
-
description: string;
|
|
247
|
-
/** Candidate origin; skills land the same literal text but route through the prompt. */
|
|
248
|
-
origin: 'command' | 'skill' | 'mention';
|
|
249
|
-
}
|
|
250
|
-
/**
|
|
251
|
-
* Resolve completion candidates for the current input: TUI-local commands,
|
|
252
|
-
* the live registry descriptors, and user-invocable skills, filtered by the
|
|
253
|
-
* typed prefix. Command names win collisions (the dispatch tries the
|
|
254
|
-
* registry first and only then falls through to the skill gesture), and a
|
|
255
|
-
* later duplicate name never renders twice.
|
|
256
|
-
*
|
|
257
|
-
* A bare `/` returns the FULL merged list — Codex's command popup shows every
|
|
258
|
-
* command inside a scroll window on an empty filter, and the menu's own
|
|
259
|
-
* selection window bounds the visible rows, so no slice cap is needed.
|
|
260
|
-
*/
|
|
261
|
-
export declare function completionCandidates(value: string, descriptors: readonly CommandDescriptor[], skills: readonly SkillRow[]): readonly CompletionCandidate[];
|
|
262
|
-
/** One cached settled row: the row Box plus its roomy-prompt spacers. */
|
|
263
251
|
interface SettledRowRecord {
|
|
264
252
|
/** The row Box element (keyed by the entry's settled index). */
|
|
265
253
|
box: ReactElement;
|
|
@@ -345,4 +333,3 @@ interface SettledRowsResult {
|
|
|
345
333
|
export declare function computeSettledRows(previous: SettledRowsCache | undefined, entries: readonly TranscriptEntry[], settled: number, showReasoning: boolean, resumed: boolean, epoch: number, columns?: number, rowCap?: number): SettledRowsResult;
|
|
346
334
|
/** The whole terminal app; state arrives via the store, output via Ink. */
|
|
347
335
|
export declare function App(props: AppProps): ReactElement;
|
|
348
|
-
export {};
|
|
@@ -26,17 +26,26 @@ export declare const MAX_FILES_PER_MESSAGE = 8;
|
|
|
26
26
|
export declare function detectImageMediaType(data: Uint8Array): ImageMediaType | undefined;
|
|
27
27
|
/** Whether a path-like token is worth probing as an image attachment. */
|
|
28
28
|
export declare function looksLikeImagePath(path: string): boolean;
|
|
29
|
+
/** Strip one layer of ASCII or Unicode quotes and shell-escaped spaces. */
|
|
30
|
+
export declare function unwrapDroppedPath(token: string): string;
|
|
31
|
+
/** Absolute/relative drop with a dotted leaf — including unquoted spaces. */
|
|
32
|
+
export declare function looksLikeFilesystemDrop(path: string): boolean;
|
|
29
33
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
* A composer draft that is a filesystem path, not a slash command.
|
|
35
|
+
* `/usage` stays a command; `/Users/foo.png` and `C:\temp\a.png` are drops.
|
|
36
|
+
*/
|
|
37
|
+
export declare function looksLikePathDraft(value: string): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Parse a paste or file-drop into image and file paths: image-suffixed
|
|
40
|
+
* tokens stay images, other path-shaped tokens ride as file attachments
|
|
41
|
+
* (0.1.5 file blocks), and anything that is neither leaves both empty —
|
|
42
|
+
* the caller then treats the paste as plain text.
|
|
34
43
|
*
|
|
35
44
|
* File tokens are held to an absolute-path-with-shape bar (drive/backslash
|
|
36
|
-
* or a
|
|
45
|
+
* or a dotted leaf after a separator): a dropped terminal path always
|
|
37
46
|
* carries one of those, while prose, slash commands, and option flags never
|
|
38
|
-
* do. A POSIX absolute path without
|
|
39
|
-
*
|
|
47
|
+
* do. A POSIX absolute path without a dotted leaf falls through as text —
|
|
48
|
+
* the @ mention route still attaches such files deliberately.
|
|
40
49
|
*/
|
|
41
50
|
export declare function parsePastedAttachmentPaths(input: string): {
|
|
42
51
|
readonly images: readonly string[];
|
|
@@ -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 {};
|