dsh-code 0.4.0 → 0.6.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 +217 -0
- package/README.md +216 -67
- package/bin/deepseek.mjs +70 -0
- package/cordis.patch.yml +62 -6
- package/lib/devtools-CdTl3MNy.mjs +3643 -0
- package/lib/index.mjs +27467 -673
- package/lib/rolldown-runtime-CMFfr-1z.mjs +26 -0
- package/lib/startup.mjs +34 -17
- package/lib/types/app.d.ts +29 -1
- package/lib/types/commands.d.ts +2 -0
- package/lib/types/history.d.ts +79 -0
- package/lib/types/index.d.ts +5 -5
- package/lib/types/internals.d.ts +2 -0
- package/lib/types/kernel-panels.d.ts +48 -0
- package/lib/types/plugin-inventory.d.ts +11 -0
- package/lib/types/presets.d.ts +32 -0
- package/lib/types/render/animations.d.ts +10 -1
- package/lib/types/render/inspector.d.ts +6 -0
- package/lib/types/render/projection.d.ts +21 -1
- package/lib/types/render/status.d.ts +131 -14
- package/lib/types/render/text.d.ts +9 -0
- package/lib/types/session-directory.d.ts +54 -0
- package/lib/types/session-switch.d.ts +17 -0
- package/lib/types/skills.d.ts +2 -0
- package/lib/types/startup.d.ts +11 -1
- package/package.json +117 -112
- package/src/app.ts +2543 -1969
- package/src/commands.ts +15 -1
- package/src/history.ts +136 -0
- package/src/index.ts +550 -155
- package/src/internals.ts +5 -0
- package/src/kernel-panels.ts +419 -0
- package/src/plugin-inventory.ts +47 -0
- package/src/presets.ts +64 -0
- package/src/render/animations.ts +14 -1
- package/src/render/export.ts +4 -0
- package/src/render/inspector.ts +23 -5
- package/src/render/lines.ts +21 -10
- package/src/render/markdown.ts +15 -1
- package/src/render/projection.ts +71 -8
- package/src/render/status.ts +522 -65
- package/src/render/text.ts +34 -6
- package/src/session-directory.ts +102 -0
- package/src/session-switch.ts +58 -0
- package/src/skills.ts +20 -7
- package/src/startup.ts +38 -20
- package/src/whale-glyph.ts +23 -23
- package/README.zh.md +0 -65
- package/src/pictures/1.png +0 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
12
|
+
key = keys[i];
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
14
|
+
get: ((k) => from[k]).bind(null, key),
|
|
15
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
21
|
+
value: mod,
|
|
22
|
+
enumerable: true
|
|
23
|
+
}) : target, mod));
|
|
24
|
+
var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
|
|
25
|
+
//#endregion
|
|
26
|
+
export { __require as n, __toESM as r, __commonJSMin as t };
|
package/lib/startup.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { parseCmdline } from "@deepseek-ai/dsh-cmdline";
|
|
|
3
3
|
//#region src/startup.ts
|
|
4
4
|
/**
|
|
5
5
|
* The interactive terminal app's command-line provider: parses `--resume`,
|
|
6
|
-
* `--continue`, `--session`, and `--help`, then publishes
|
|
6
|
+
* `--continue`, `--session`, `--mode`, and `--help`, then publishes
|
|
7
7
|
* {@link TUI_STARTUP_SERVICE} for the runner to consume lazily. Follows the
|
|
8
8
|
* headless bundle's startup shape (a commander action publishing a service
|
|
9
9
|
* through {@link parseCmdline}).
|
|
@@ -26,17 +26,41 @@ const name = "tui-startup";
|
|
|
26
26
|
const inject = ["cmdlineArgs"];
|
|
27
27
|
/** Service provided by this plugin and injected by the terminal runner. */
|
|
28
28
|
const TUI_STARTUP_SERVICE = "tuiStartup";
|
|
29
|
+
/** Pure option policy shared by Commander and tests. */
|
|
30
|
+
function resolveTuiStartup(options) {
|
|
31
|
+
if ([
|
|
32
|
+
options.resume !== void 0,
|
|
33
|
+
options.continue === true,
|
|
34
|
+
options.session !== void 0
|
|
35
|
+
].filter(Boolean).length > 1) throw new Error("--resume, --continue, and --session are mutually exclusive");
|
|
36
|
+
if (options.session === "") throw new Error("--session needs an id");
|
|
37
|
+
if (options.resume === "") throw new Error("--resume needs a session id or id prefix");
|
|
38
|
+
if (options.mode === "") throw new Error("--mode needs a preset id");
|
|
39
|
+
if (options.mode !== void 0 && (options.resume !== void 0 || options.continue === true)) throw new Error("--mode applies only to a new session; it cannot be combined with --resume or --continue");
|
|
40
|
+
return options.resume !== void 0 ? {
|
|
41
|
+
kind: "resume",
|
|
42
|
+
sessionId: options.resume
|
|
43
|
+
} : options.continue === true ? { kind: "latest" } : options.session !== void 0 ? {
|
|
44
|
+
kind: "named",
|
|
45
|
+
sessionId: options.session,
|
|
46
|
+
...options.mode === void 0 ? {} : { mode: options.mode }
|
|
47
|
+
} : {
|
|
48
|
+
kind: "fresh",
|
|
49
|
+
...options.mode === void 0 ? {} : { mode: options.mode }
|
|
50
|
+
};
|
|
51
|
+
}
|
|
29
52
|
/**
|
|
30
53
|
* This app's command: the launcher's flags this app owns, its description,
|
|
31
54
|
* and its help text.
|
|
32
55
|
* @returns a fresh program, so one process can parse more than once (tests).
|
|
33
56
|
*/
|
|
34
57
|
function tuiCommand() {
|
|
35
|
-
return new Command().name("dsh --profile cli").description("Claude-Code-style interactive terminal for DeepSeek Harness.").helpOption("-h, --help", "show this help").option("-r, --resume <session>", "resume the persisted session with this id (or unique id prefix)").option("-c, --continue", "resume the most recent persisted session for this working directory").option("--session <id>", "create a new session under this explicit id").addHelpText("after", `
|
|
58
|
+
return new Command().name("dsh --profile cli").description("Claude-Code-style interactive terminal for DeepSeek Harness.").helpOption("-h, --help", "show this help").option("-r, --resume <session>", "resume the persisted session with this id (or unique id prefix)").option("-c, --continue", "resume the most recent persisted session for this working directory").option("--session <id>", "create a new session under this explicit id").option("--mode <preset>", "agent preset for a newly created session").addHelpText("after", `
|
|
36
59
|
Examples:
|
|
37
60
|
dsh --profile cli fresh session, minted id
|
|
38
61
|
dsh --profile cli --resume abc123 resume session by id prefix
|
|
39
62
|
dsh --profile cli --continue resume the latest local session
|
|
63
|
+
dsh --profile cli --mode minimal fresh session using the minimal preset
|
|
40
64
|
`);
|
|
41
65
|
}
|
|
42
66
|
/**
|
|
@@ -48,23 +72,16 @@ function apply(ctx) {
|
|
|
48
72
|
const program = tuiCommand();
|
|
49
73
|
program.action(() => {
|
|
50
74
|
const options = program.opts();
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (
|
|
58
|
-
const startup = options.resume !== void 0 ? {
|
|
59
|
-
kind: "resume",
|
|
60
|
-
sessionId: options.resume
|
|
61
|
-
} : options.continue === true ? { kind: "latest" } : options.session !== void 0 ? {
|
|
62
|
-
kind: "named",
|
|
63
|
-
sessionId: options.session
|
|
64
|
-
} : { kind: "fresh" };
|
|
75
|
+
let startup;
|
|
76
|
+
try {
|
|
77
|
+
startup = resolveTuiStartup(options);
|
|
78
|
+
} catch (error) {
|
|
79
|
+
program.error(`error: ${error instanceof Error ? error.message : String(error)}`);
|
|
80
|
+
}
|
|
81
|
+
if (startup === void 0) return;
|
|
65
82
|
ctx.provide(TUI_STARTUP_SERVICE, { startup });
|
|
66
83
|
});
|
|
67
84
|
parseCmdline(ctx, program);
|
|
68
85
|
}
|
|
69
86
|
//#endregion
|
|
70
|
-
export { TUI_STARTUP_SERVICE, apply, inject, name };
|
|
87
|
+
export { TUI_STARTUP_SERVICE, apply, inject, name, resolveTuiStartup };
|
package/lib/types/app.d.ts
CHANGED
|
@@ -21,6 +21,11 @@ import type { ModelDirectory, ModelRow } from './models.ts';
|
|
|
21
21
|
import type { QuestionStore } from './questions.ts';
|
|
22
22
|
import type { SkillsView } from './skills.ts';
|
|
23
23
|
import type { MentionCandidate } from './mentions.ts';
|
|
24
|
+
import type { PresetRow } from './presets.ts';
|
|
25
|
+
import type { PluginRow } from './plugin-inventory.ts';
|
|
26
|
+
import type { SessionDirectoryOptions, SessionRow } from './session-directory.ts';
|
|
27
|
+
/** Visual priority for one bounded local notice. */
|
|
28
|
+
export type NoticeTone = 'info' | 'warning' | 'error';
|
|
24
29
|
/** Props the runner hands the app; callbacks stay owned by the runner. */
|
|
25
30
|
export interface AppProps {
|
|
26
31
|
/** Event-fed transcript store for the live session. */
|
|
@@ -37,12 +42,16 @@ export interface AppProps {
|
|
|
37
42
|
model: string;
|
|
38
43
|
/** Working-directory basename the session serves. */
|
|
39
44
|
cwd: string;
|
|
45
|
+
/** Absolute working directory used by session filters and references. */
|
|
46
|
+
workspaceRoot: string;
|
|
40
47
|
/** Git branch name, empty outside a repository. */
|
|
41
48
|
branch: string;
|
|
42
49
|
/** Short session identifier. */
|
|
43
50
|
sessionId: string;
|
|
44
51
|
/** Whether this session was resumed from persistence. */
|
|
45
52
|
resumed: boolean;
|
|
53
|
+
/** Agent preset currently composing the session. */
|
|
54
|
+
mode: string;
|
|
46
55
|
/** Submit one line: slash commands to the registry, other text to the agent. */
|
|
47
56
|
dispatch(text: string): void;
|
|
48
57
|
/** Submit steering: consumed at the running turn's next step boundary. */
|
|
@@ -63,10 +72,29 @@ export interface AppProps {
|
|
|
63
72
|
exportTranscript(argument: string): Promise<void>;
|
|
64
73
|
/** Rename the session (/title <text>); returns the outcome line for the notice. */
|
|
65
74
|
renameTitle(argument: string): string;
|
|
75
|
+
/** Preset/session/plugin kernel operations. */
|
|
76
|
+
loadPresets(): Promise<readonly PresetRow[]>;
|
|
77
|
+
switchMode(id: string): Promise<string>;
|
|
78
|
+
createSession(mode?: string): void;
|
|
79
|
+
loadSessions(options: SessionDirectoryOptions, signal?: AbortSignal): Promise<readonly SessionRow[]>;
|
|
80
|
+
loadSessionTranscript(id: string, signal?: AbortSignal): Promise<string>;
|
|
81
|
+
switchSession(row: SessionRow): void;
|
|
82
|
+
cancelSessionSwitch(): boolean;
|
|
83
|
+
loadPlugins(): readonly PluginRow[];
|
|
66
84
|
/** Registers the app's notice channel with the runner (called once on mount). */
|
|
67
85
|
onBridgeReady(bridge: {
|
|
68
|
-
notify(text: string): void;
|
|
86
|
+
notify(text: string, tone?: NoticeTone): void;
|
|
69
87
|
}): void;
|
|
88
|
+
/** Ordered enabled status items (/statusline config); the runner owns persistence. */
|
|
89
|
+
statusline: readonly string[];
|
|
90
|
+
/** Persist a new statusline item set; the runner surfaces IO failures as notices. */
|
|
91
|
+
saveStatusline(items: readonly string[]): void;
|
|
92
|
+
/** Persistent cross-session input history (oldest first); the runner owns the file. */
|
|
93
|
+
history: readonly string[];
|
|
94
|
+
/** Persist one submitted prompt to the global history file. */
|
|
95
|
+
recordHistory(text: string): void;
|
|
96
|
+
/** Cancel one queued inbox message by identity (Delete on the empty composer). */
|
|
97
|
+
cancelQueued(messageId: string): void;
|
|
70
98
|
}
|
|
71
99
|
/** The whole terminal app; state arrives via the store, output via Ink. */
|
|
72
100
|
export declare function App(props: AppProps): ReactElement;
|
package/lib/types/commands.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ import type { CommandDescriptor } from '@deepseek-ai/dsh-commands';
|
|
|
14
14
|
export interface CommandsView {
|
|
15
15
|
/** Name-sorted descriptors after scoped shadowing. */
|
|
16
16
|
readonly descriptors: readonly CommandDescriptor[];
|
|
17
|
+
/** Latest descriptor-read failure; the help panel exposes it in place. */
|
|
18
|
+
readonly error?: string;
|
|
17
19
|
/** Subscribe to list changes (`commands/change`); returns the unsubscribe function. */
|
|
18
20
|
subscribe(listener: () => void): () => void;
|
|
19
21
|
/** Retarget the agent whose scoped view the list is read through. */
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global input recall: persistent cross-session entries plus this process's
|
|
3
|
+
* submissions, with Codex `ChatComposerHistory` semantics — empty submissions
|
|
4
|
+
* are ignored, adjacent duplicates collapse, the recall space skips
|
|
5
|
+
* persistent entries that duplicate a local one (local wins), and Up/Down
|
|
6
|
+
* navigation is gated so interior cursor movement never hijacks the draft.
|
|
7
|
+
*
|
|
8
|
+
* @module @deepseek-ai/dsh-tui/history
|
|
9
|
+
*/
|
|
10
|
+
/** Maximum entries retained in the persistent history file. */
|
|
11
|
+
export declare const HISTORY_MAX_ENTRIES = 500;
|
|
12
|
+
/** Encode one entry for the history file (JSON keeps multi-line drafts intact). */
|
|
13
|
+
export declare function serializeHistoryEntry(text: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Parse a persisted history file (one JSON entry per line): invalid lines
|
|
16
|
+
* drop out, empty entries are ignored, adjacent duplicates collapse, and the
|
|
17
|
+
* result keeps only the newest `max` entries.
|
|
18
|
+
* @param raw - file content, empty for a missing file.
|
|
19
|
+
* @param max - entry cap.
|
|
20
|
+
* @returns persistent entries, oldest first.
|
|
21
|
+
*/
|
|
22
|
+
export declare function parseHistoryFile(raw: string, max?: number): readonly string[];
|
|
23
|
+
/**
|
|
24
|
+
* Append one entry to the persistent file content: JSON line, capped to the
|
|
25
|
+
* newest `max` entries with a trailing newline.
|
|
26
|
+
* @param current - existing file content.
|
|
27
|
+
* @param text - submission to persist.
|
|
28
|
+
* @param max - entry cap.
|
|
29
|
+
* @returns the new file content.
|
|
30
|
+
*/
|
|
31
|
+
export declare function appendHistoryContent(current: string, text: string, max?: number): string;
|
|
32
|
+
/**
|
|
33
|
+
* Record one in-session submission: empty text is ignored and an adjacent
|
|
34
|
+
* duplicate collapses (Codex `record_local_submission` semantics).
|
|
35
|
+
* @param local - current in-session entries, oldest first.
|
|
36
|
+
* @param text - the submitted prompt.
|
|
37
|
+
* @returns the updated local list.
|
|
38
|
+
*/
|
|
39
|
+
export declare function recordLocalEntry(local: readonly string[], text: string): readonly string[];
|
|
40
|
+
/**
|
|
41
|
+
* Build the recall space, newest first: local entries, then persistent
|
|
42
|
+
* entries whose text is not duplicated locally (the local copy wins and the
|
|
43
|
+
* persistent twin is skipped — Codex's replay-seed dedup, applied to the
|
|
44
|
+
* whole local set).
|
|
45
|
+
* @param persistent - cross-session entries, oldest first.
|
|
46
|
+
* @param local - this process's submissions, oldest first.
|
|
47
|
+
* @returns recall entries, newest first.
|
|
48
|
+
*/
|
|
49
|
+
export declare function recallEntries(persistent: readonly string[], local: readonly string[]): readonly string[];
|
|
50
|
+
/** Shell-style recall navigation over a fixed recall space. */
|
|
51
|
+
export interface RecallState {
|
|
52
|
+
/** Recall entries, newest first (frozen at navigation start). */
|
|
53
|
+
entries: readonly string[];
|
|
54
|
+
/** Current recall index; null when not browsing. */
|
|
55
|
+
index: number | null;
|
|
56
|
+
/** Draft saved when browsing started; restored on Down past the newest. */
|
|
57
|
+
savedDraft: string;
|
|
58
|
+
/** The recalled text currently in the composer (the boundary gate's anchor). */
|
|
59
|
+
lastRecalled: string | null;
|
|
60
|
+
}
|
|
61
|
+
/** Fresh navigation state over one recall space. */
|
|
62
|
+
export declare function beginRecall(entries: readonly string[], draft: string): RecallState;
|
|
63
|
+
/** The outcome of one recall step. */
|
|
64
|
+
export interface RecallStep {
|
|
65
|
+
state: RecallState;
|
|
66
|
+
/** The text to place in the composer; undefined means "no movement". */
|
|
67
|
+
entry: string | undefined;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Move one entry older (Up, toward index +1 in the newest-first space). The
|
|
71
|
+
* first Up saves the current draft so Down past the newest can restore it
|
|
72
|
+
* (Claude-Code shell recall — the draft is never lost); the oldest entry
|
|
73
|
+
* stays put.
|
|
74
|
+
* @param state - current navigation state.
|
|
75
|
+
* @param draft - the composer text to preserve when browsing starts.
|
|
76
|
+
*/
|
|
77
|
+
export declare function recallOlder(state: RecallState, draft: string): RecallStep;
|
|
78
|
+
/** Move one entry newer (Down, toward index 0); past the newest, browsing ends and the saved draft returns. */
|
|
79
|
+
export declare function recallNewer(state: RecallState): RecallStep;
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @deepseek-ai/dsh-code — the interactive terminal driver. The bundle patch
|
|
3
3
|
* rides over dsh-base without Host, HTTP, or browser plugins; this runner
|
|
4
|
-
* creates
|
|
5
|
-
*
|
|
6
|
-
* durable session, answers approval asks with a y/n bar,
|
|
7
|
-
*
|
|
8
|
-
* process exit.
|
|
4
|
+
* creates or resumes preset-composed Agents through the core registry, keeps
|
|
5
|
+
* one Ink owner while the active session changes, folds submitted prompts
|
|
6
|
+
* into the selected durable session, answers approval asks with a y/n bar,
|
|
7
|
+
* dispatches slash commands, and on quit flushes and requests process exit.
|
|
9
8
|
*
|
|
10
9
|
* @module @deepseek-ai/dsh-code
|
|
11
10
|
*/
|
|
@@ -21,6 +20,7 @@ export interface Config {
|
|
|
21
20
|
startup: {
|
|
22
21
|
kind: string;
|
|
23
22
|
sessionId?: string;
|
|
23
|
+
mode?: string;
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
export declare const Config: z<Config>;
|
package/lib/types/internals.d.ts
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
import type { ReactElement } from 'react';
|
|
9
9
|
/** A mounted terminal app instance; the runner owns unmount ordering. */
|
|
10
10
|
export interface TuiMount {
|
|
11
|
+
/** Replace the root element while preserving Ink's single terminal owner. */
|
|
12
|
+
rerender(element: ReactElement): void;
|
|
11
13
|
/** Tear the terminal app down before flush and exit. */
|
|
12
14
|
unmount(): void;
|
|
13
15
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** Bounded, composer-safe panels for preset, session, and plugin kernel views. */
|
|
2
|
+
import { type ReactElement } from 'react';
|
|
3
|
+
import type { PresetRow } from './presets.ts';
|
|
4
|
+
import type { PluginRow } from './plugin-inventory.ts';
|
|
5
|
+
import type { SessionDirectoryOptions, SessionRow } from './session-directory.ts';
|
|
6
|
+
import { type StatusItemId } from './render/status.ts';
|
|
7
|
+
export declare function ModePanel({ current, load, select, close }: {
|
|
8
|
+
current: string;
|
|
9
|
+
load(): Promise<readonly PresetRow[]>;
|
|
10
|
+
select(id: string): void;
|
|
11
|
+
close(): void;
|
|
12
|
+
}): ReactElement;
|
|
13
|
+
export declare function PluginPanel({ load, close, initialQuery }: {
|
|
14
|
+
load(): readonly PluginRow[];
|
|
15
|
+
close(): void;
|
|
16
|
+
initialQuery?: string;
|
|
17
|
+
}): ReactElement;
|
|
18
|
+
export declare function ResumePanel({ currentCwd, load, readTranscript, select, close }: {
|
|
19
|
+
currentCwd: string;
|
|
20
|
+
load(options: SessionDirectoryOptions, signal?: AbortSignal): Promise<readonly SessionRow[]>;
|
|
21
|
+
readTranscript(id: string, signal?: AbortSignal): Promise<string>;
|
|
22
|
+
select(row: SessionRow): void;
|
|
23
|
+
close(): void;
|
|
24
|
+
}): ReactElement;
|
|
25
|
+
/**
|
|
26
|
+
* The /history recall panel (Codex composer-history search, bounded): one
|
|
27
|
+
* query line over the newest-first recall space, filtered by substring, with
|
|
28
|
+
* arrow selection and enter to fill the composer. Editing the query restarts
|
|
29
|
+
* from the newest match; Esc closes without touching the draft.
|
|
30
|
+
*/
|
|
31
|
+
export declare function HistoryPanel({ entries, fill, close }: {
|
|
32
|
+
/** Newest-first recall entries (persistent + in-session, deduped). */
|
|
33
|
+
entries: readonly string[];
|
|
34
|
+
/** Accept one entry: its text plus its recall-space index (browsing resumes there). */
|
|
35
|
+
fill(text: string, index: number): void;
|
|
36
|
+
close(): void;
|
|
37
|
+
}): ReactElement;
|
|
38
|
+
/**
|
|
39
|
+
* The /statusline picker (the Codex setup-view contract): one bounded list
|
|
40
|
+
* of every status item with its enabled mark, arrow reordering, and a
|
|
41
|
+
* live preview — the real status line under the composer updates as you
|
|
42
|
+
* edit, so the panel itself carries no duplicate preview row.
|
|
43
|
+
*/
|
|
44
|
+
export declare function StatuslinePanel({ enabled, change, close }: {
|
|
45
|
+
enabled: readonly StatusItemId[];
|
|
46
|
+
change(items: readonly StatusItemId[]): void;
|
|
47
|
+
close(): void;
|
|
48
|
+
}): ReactElement;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Read-only projection of Cordis Loader entries for /plugin. */
|
|
2
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
3
|
+
export type PluginPhase = 'pending' | 'loading' | 'active' | 'failed' | 'unloading' | null;
|
|
4
|
+
export interface PluginRow {
|
|
5
|
+
readonly entryId: string;
|
|
6
|
+
readonly moduleName: string;
|
|
7
|
+
readonly enabled: boolean;
|
|
8
|
+
readonly phase: PluginPhase;
|
|
9
|
+
}
|
|
10
|
+
/** Snapshot the live Loader; group-only rows are composition containers, not plugins. */
|
|
11
|
+
export declare function listPluginRows(ctx: Context): PluginRow[];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Agent-preset policy kept independent from the Ink surface. */
|
|
2
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
3
|
+
import type { Agent, AgentHandle } from '@deepseek-ai/dsh-agent';
|
|
4
|
+
import type { Session, SessionEvent } from '@deepseek-ai/dsh-session';
|
|
5
|
+
/** One discoverable agent composition. */
|
|
6
|
+
export interface PresetRow {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly trust: 'system' | 'user';
|
|
9
|
+
readonly name?: string;
|
|
10
|
+
readonly description?: string;
|
|
11
|
+
readonly order?: number;
|
|
12
|
+
readonly broken?: string;
|
|
13
|
+
}
|
|
14
|
+
/** Structural boundary for the optional upstream AgentPresets service. */
|
|
15
|
+
export interface AgentPresetsService {
|
|
16
|
+
readonly defaultId: string;
|
|
17
|
+
list(): Promise<PresetRow[]>;
|
|
18
|
+
resolve(id?: string): Promise<PresetRow>;
|
|
19
|
+
mount(agentCtx: Context, id?: string): Promise<PresetRow>;
|
|
20
|
+
recompose(agentCtx: Context, id: string): Promise<PresetRow>;
|
|
21
|
+
composedPreset(agentCtx: Context): string | undefined;
|
|
22
|
+
}
|
|
23
|
+
/** Read an optional Cordis service without requiring its package at build time. */
|
|
24
|
+
export declare function agentPresetsFrom(ctx: Context): AgentPresetsService | undefined;
|
|
25
|
+
/** A preset may change only before the first durable turn begins. */
|
|
26
|
+
export declare function isBlankSession(events: readonly SessionEvent[]): boolean;
|
|
27
|
+
/** Latest logged selection wins; legacy sessions deliberately fall back to standard. */
|
|
28
|
+
export declare function resolvePreset(session: Pick<Session, 'header' | 'events'>): string;
|
|
29
|
+
/** Recompose atomically from the caller's perspective, logging only success. */
|
|
30
|
+
export declare function switchPreset(service: AgentPresetsService, agent: Agent, presetId: string): Promise<PresetRow>;
|
|
31
|
+
/** Minimal handle shape used by lifecycle tests without exposing Agent internals. */
|
|
32
|
+
export type OwnedAgent = Pick<AgentHandle, 'agent' | 'dispose'>;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Terminal animation frame tables derived from the web design language:
|
|
3
3
|
* the StateDot "ongoing" pixel chase (3×3 ring, 125ms flat-hold brightness
|
|
4
|
-
* steps, 1s cycle) becomes the single-cell stepped pulse below
|
|
4
|
+
* steps, 1s cycle) becomes the single-cell stepped pulse below and the
|
|
5
|
+
* full-ring clockwise braille chase in {@link BUSY_CHASE_FRAMES}, and the
|
|
5
6
|
* streaming caret blink is the Claude-Code convention. Pure functions only —
|
|
6
7
|
* the Ink layer owns timers and colors.
|
|
7
8
|
*
|
|
@@ -11,5 +12,13 @@
|
|
|
11
12
|
export declare const PULSE_FRAMES: readonly ["█", "█", "▆", "▃", "▁", "▃", "▆", "█"];
|
|
12
13
|
/** Pulse frame for a monotonic tick. */
|
|
13
14
|
export declare function pulseFrame(tick: number): string;
|
|
15
|
+
/**
|
|
16
|
+
* The web StateDot "ongoing" chase in terminal form: three cells of the 3×3
|
|
17
|
+
* ring trail clockwise around the eight outer positions, one braille glyph
|
|
18
|
+
* per step — 8 frames × 125ms = the web's 1s cycle.
|
|
19
|
+
*/
|
|
20
|
+
export declare const BUSY_CHASE_FRAMES: readonly ["⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"];
|
|
21
|
+
/** Chase frame for a monotonic tick (the busy composer/Deep-diving marker). */
|
|
22
|
+
export declare function busyChaseFrame(tick: number): string;
|
|
14
23
|
/** Caret visibility: half the ticks on, half off (530ms blink). */
|
|
15
24
|
export declare function caretVisible(tick: number): boolean;
|
|
@@ -5,11 +5,17 @@ export interface InspectorViewport {
|
|
|
5
5
|
maxHeight: number;
|
|
6
6
|
/** Rows available to the selected entry after border, title, and footer. */
|
|
7
7
|
bodyRows: number;
|
|
8
|
+
/** Optional blank rows separating title/body/footer on roomy terminals. */
|
|
9
|
+
gapRows: 0 | 2;
|
|
8
10
|
/** Columns available inside the horizontal border and padding. */
|
|
9
11
|
contentColumns: number;
|
|
12
|
+
/** Safe outer width for a bordered dynamic panel; never writes column N. */
|
|
13
|
+
outerColumns: number;
|
|
10
14
|
/** Tiny terminals use a borderless one-line close hint. */
|
|
11
15
|
compact: boolean;
|
|
12
16
|
}
|
|
17
|
+
/** One transcript-to-composer gutter, collapsed on short terminals. */
|
|
18
|
+
export declare function layoutGutterRows(rows: number): 0 | 1;
|
|
13
19
|
/**
|
|
14
20
|
* Keep the inspector plus its persistent status/composer chrome below
|
|
15
21
|
* `stdout.rows`: at equality Ink clears the terminal and rewrites all
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module @deepseek-ai/dsh-tui/render/projection
|
|
8
8
|
*/
|
|
9
|
+
import { type MessageId } from '@deepseek-ai/dsh-llm';
|
|
9
10
|
import type { SessionEvent, TodoItem } from '@deepseek-ai/dsh-session';
|
|
10
11
|
import { type ToolDetail } from './tool-detail.ts';
|
|
11
12
|
/** One user prompt line. */
|
|
@@ -17,6 +18,16 @@ export interface UserEntry {
|
|
|
17
18
|
* the renderer marks with a dim ↳ instead of the user ❯ prompt. */
|
|
18
19
|
notice: boolean;
|
|
19
20
|
}
|
|
21
|
+
/** One user message waiting in the agent inbox (the web's queued-message row). */
|
|
22
|
+
export interface PendingEntry {
|
|
23
|
+
kind: 'pending';
|
|
24
|
+
/** Stable message identity shared with the durable `user/message` that retires it. */
|
|
25
|
+
messageId: MessageId;
|
|
26
|
+
/** Which inbox list holds the message: steering is consumed at the next step boundary. */
|
|
27
|
+
target: 'next-turn' | 'next-step';
|
|
28
|
+
/** Full message text — Codex PendingSteer renders queued prompts exactly like user rows. */
|
|
29
|
+
text: string;
|
|
30
|
+
}
|
|
20
31
|
/** One assembled assistant reply. */
|
|
21
32
|
export interface AssistantEntry {
|
|
22
33
|
kind: 'assistant';
|
|
@@ -105,7 +116,7 @@ export interface FilesEntry {
|
|
|
105
116
|
paths: readonly string[];
|
|
106
117
|
}
|
|
107
118
|
/** Ordered transcript items the renderer draws. */
|
|
108
|
-
export type TranscriptEntry = UserEntry | AssistantEntry | ToolEntry | CommandEntry | ErrorEntry | TurnMarkerEntry | CompactionEntry | RetryEntry | FilesEntry;
|
|
119
|
+
export type TranscriptEntry = UserEntry | PendingEntry | AssistantEntry | ToolEntry | CommandEntry | ErrorEntry | TurnMarkerEntry | CompactionEntry | RetryEntry | FilesEntry;
|
|
109
120
|
/** The live goal the status line badges, folded from `goal/change`. */
|
|
110
121
|
export interface GoalFold {
|
|
111
122
|
/** Human-requested completion objective. */
|
|
@@ -185,6 +196,15 @@ export interface TranscriptView {
|
|
|
185
196
|
sandbox: string;
|
|
186
197
|
/** Current long-running goal folded from the last `goal/change`, undefined when cleared. */
|
|
187
198
|
goal: GoalFold | undefined;
|
|
199
|
+
/**
|
|
200
|
+
* Ordered live message ids per inbox target, mirrored from
|
|
201
|
+
* `agent/inbox/spliced` exactly like the upstream Inbox projection — the
|
|
202
|
+
* coordinates later removals resolve against.
|
|
203
|
+
*/
|
|
204
|
+
pending: {
|
|
205
|
+
'next-turn': readonly string[];
|
|
206
|
+
'next-step': readonly string[];
|
|
207
|
+
};
|
|
188
208
|
/**
|
|
189
209
|
* Fold-internal timing anchors, never rendered: open step and tool-call
|
|
190
210
|
* start timestamps the next `assistant/message` / `tool/result` resolves
|