dsh-code 0.5.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.
@@ -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 };
@@ -85,6 +85,16 @@ export interface AppProps {
85
85
  onBridgeReady(bridge: {
86
86
  notify(text: string, tone?: NoticeTone): void;
87
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;
88
98
  }
89
99
  /** The whole terminal app; state arrives via the store, output via Ink. */
90
100
  export declare function App(props: AppProps): ReactElement;
@@ -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;
@@ -3,6 +3,7 @@ import { type ReactElement } from 'react';
3
3
  import type { PresetRow } from './presets.ts';
4
4
  import type { PluginRow } from './plugin-inventory.ts';
5
5
  import type { SessionDirectoryOptions, SessionRow } from './session-directory.ts';
6
+ import { type StatusItemId } from './render/status.ts';
6
7
  export declare function ModePanel({ current, load, select, close }: {
7
8
  current: string;
8
9
  load(): Promise<readonly PresetRow[]>;
@@ -21,3 +22,27 @@ export declare function ResumePanel({ currentCwd, load, readTranscript, select,
21
22
  select(row: SessionRow): void;
22
23
  close(): void;
23
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;
@@ -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, and the
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;
@@ -9,6 +9,8 @@ export interface InspectorViewport {
9
9
  gapRows: 0 | 2;
10
10
  /** Columns available inside the horizontal border and padding. */
11
11
  contentColumns: number;
12
+ /** Safe outer width for a bordered dynamic panel; never writes column N. */
13
+ outerColumns: number;
12
14
  /** Tiny terminals use a borderless one-line close hint. */
13
15
  compact: boolean;
14
16
  }
@@ -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
@@ -1,9 +1,11 @@
1
1
  /**
2
- * Status-line composition for the TUI footer: pipe-separated groups blending
3
- * the Claude-Code-style identity facts (model, working directory, git branch,
4
- * session) with the web StatsLine's session figures (turns/steps, model and
5
- * tool wall time, cache hit, token totals). Pure functions only the footer
6
- * renders exactly what {@link buildStatusGroups} returns.
2
+ * Status-bar composition for the TUI footer. Codex/Claude-Code-style split
3
+ * line: identity facts and session figures flow from the left, while the
4
+ * permission badge (the Codex "autonomous selection" anchor, with its
5
+ * shift+tab cycle hint) pins to the right edge. Every segment carries a tone
6
+ * the footer maps to a theme color, and layoutStatusBar degrades the line
7
+ * item by item so it always fits one physical row — truncation with an
8
+ * ellipsis happens only after every lesser group has already dropped out.
7
9
  *
8
10
  * @module @deepseek-ai/dsh-tui/render/status
9
11
  */
@@ -34,9 +36,101 @@ export declare function formatRate(n: number): string;
34
36
  * @returns rounded integer percent, or null when no input was billed.
35
37
  */
36
38
  export declare function cacheHitPercent(usage: TranscriptStats['usage']): number | null;
39
+ /**
40
+ * Presentation tones for status spans; the footer maps each to a theme color
41
+ * (Codex status-line accents: model/path/branch/state/usage categories).
42
+ */
43
+ export type StatusTone = 'model' | 'live' | 'path' | 'branch' | 'value' | 'label' | 'meta' | 'accent' | 'success' | 'warn' | 'error';
44
+ /** One colored run inside the status bar. */
45
+ export interface StatusSpan {
46
+ text: string;
47
+ tone: StatusTone;
48
+ }
49
+ /**
50
+ * One pipe-separated cluster on the leading side of the bar. Spans are the
51
+ * full visual sequence: junction separators ride along as their own dim
52
+ * 'label'-tone spans, so joining is a flat concat with no implicit glue.
53
+ */
54
+ export interface StatusGroup {
55
+ spans: readonly StatusSpan[];
56
+ }
57
+ /** One physical row of the footer: leading clusters and trailing badges. */
58
+ export interface StatusRow {
59
+ /** Leading clusters, pipe-separated in display order; index 0 is identity. */
60
+ left: readonly StatusGroup[];
61
+ /** Trailing spans pinned to the right edge, dot-separated in display order. */
62
+ right: readonly StatusSpan[];
63
+ /** Whether the shift+tab cycle hint rides after the permission badge. */
64
+ hint: boolean;
65
+ }
66
+ /**
67
+ * The footer layout: two stacked physical rows. Row 1 is the identity/state
68
+ * row (busy dot, model, cwd, branch, plan, turns, tokens, title; goal,
69
+ * sandbox, and permission badges). Row 2 is the run-meters row (mode, the
70
+ * context progress bar, cache, and duration figures) and degrades to empty
71
+ * before any row-1 content is touched.
72
+ */
73
+ export interface StatusLayout {
74
+ row1: StatusRow;
75
+ row2: StatusRow;
76
+ }
77
+ /** Separator between leading clusters. */
78
+ export declare const STATUS_GROUP_SEPARATOR = " | ";
79
+ /** Separator between trailing state spans. */
80
+ export declare const STATUS_ITEM_SEPARATOR = " \u00B7 ";
81
+ /** The Codex-style mode cycle hint appended to the permission badge. */
82
+ export declare const STATUS_CYCLE_HINT = " (shift+tab to cycle)";
83
+ /** Cells in the context-occupancy progress bar (block glyphs count two columns in the budget). */
84
+ export declare const CONTEXT_BAR_CELLS = 10;
85
+ /** Occupancy at which the bar switches from brand blue to a single amber warning. */
86
+ export declare const CONTEXT_WARN_PERCENT = 90;
87
+ /**
88
+ * Render a context-occupancy percent as a bracketed fixed-width progress bar
89
+ * plus the percentage: `[▰▰▰▱▱▱▱▱▱▱] 25%`. Filled cells and the percent read
90
+ * in brand blue (accent), empty cells and the brackets read dim (label), and
91
+ * the whole meter flips to one amber warning once occupancy reaches the
92
+ * warning threshold. The bar fill clamps to 100 while the printed percent
93
+ * keeps the raw value so an over-budget session reads as such.
94
+ * @param percent - occupancy percent (may exceed 100).
95
+ * @returns tone-split spans for the footer to paint.
96
+ */
97
+ export declare function contextBar(percent: number): readonly StatusSpan[];
98
+ /**
99
+ * One customizable status item (the Codex /statusline picker contract).
100
+ * 'left' items render as pipe-separated clusters after the identity dot;
101
+ * 'right' items pin to the right edge as dot-separated state badges.
102
+ */
103
+ export type StatusItemId = 'model' | 'cwd' | 'branch' | 'plan' | 'mode' | 'turns' | 'durations' | 'cache' | 'context' | 'tokens' | 'title' | 'goal' | 'sandbox' | 'permission';
104
+ /** Picker-facing metadata for one customizable item. */
105
+ export interface StatusItemInfo {
106
+ id: StatusItemId;
107
+ /** Short picker label. */
108
+ label: string;
109
+ /** One-line picker description of what the item shows. */
110
+ description: string;
111
+ /** Which side of the split row the item renders on. */
112
+ side: 'left' | 'right';
113
+ }
114
+ /** The full item catalog in canonical order (the /statusline default). */
115
+ export declare const STATUS_ITEMS: readonly StatusItemInfo[];
116
+ /**
117
+ * Default order: the whole catalog (matches the pre-customization bar).
118
+ * The busy dot is not an item — it always leads the identity cluster.
119
+ */
120
+ export declare const DEFAULT_STATUSLINE_ITEMS: readonly StatusItemId[];
121
+ /**
122
+ * Parse a persisted statusline item list. The stored value is the ordered
123
+ * set of ENABLED items (the Codex /statusline contract): unknown ids and
124
+ * duplicates drop out, and a non-array value (missing or corrupt file)
125
+ * falls back to the full default set. An explicitly empty array is valid —
126
+ * the bar degrades to its busy dot alone.
127
+ * @param value - the raw parsed JSON value (expected string[]).
128
+ * @returns the normalized ordered item list.
129
+ */
130
+ export declare function parseStatuslineItems(value: unknown): readonly StatusItemId[];
37
131
  /** Identity facts the runner resolves once at mount; empty strings drop out. */
38
132
  export interface StatusFacts {
39
- /** `provider/model` selection serving this session. */
133
+ /** 'provider/model' selection serving this session. */
40
134
  model: string;
41
135
  /** Agent preset composing this session. */
42
136
  mode?: string;
@@ -46,25 +140,46 @@ export interface StatusFacts {
46
140
  branch: string;
47
141
  /** Short session identifier (last dash-separated segment or tail). */
48
142
  sessionId: string;
49
- /** Latest session title (folded from `session/title`); shown in place of the id. */
143
+ /** Latest session title (folded from 'session/title'); shown in place of the id. */
50
144
  title: string;
51
- /** Sandbox-mode override (folded from `sandbox/mode`), empty when never switched. */
145
+ /** Sandbox-mode override (folded from 'sandbox/mode'), empty when never switched. */
52
146
  sandbox: string;
53
- /** Live goal summary (folded from `goal/change`), undefined when none. */
147
+ /** Live goal summary (folded from 'goal/change'), undefined when none. */
54
148
  goal: {
55
149
  phase: string;
56
150
  rounds: number;
57
151
  max: number;
58
152
  } | undefined;
59
- /** Whether plan mode is active (folded from `plan/mode`). */
153
+ /** Whether plan mode is active (folded from 'plan/mode'). */
60
154
  plan: boolean;
61
- /** Active permission preset (folded from `permission/preset`), empty when unknown. */
155
+ /** Active permission preset (folded from 'permission/preset'), empty when unknown. */
62
156
  permission: string;
63
157
  }
64
158
  /**
65
- * Build the footer's display groups; a group with no data drops out whole.
159
+ * Traffic-light tone for a permission preset: read-only stays success green,
160
+ * full access reads error red, and every workspace-scoped middle ground
161
+ * (including unknown presets) reads warning amber.
162
+ * @param permission - active permission preset label.
163
+ * @returns tone for the badge span.
164
+ */
165
+ export declare function permissionTone(permission: string): StatusTone;
166
+ /**
167
+ * Compose the two-row footer layout under a column budget. Row 1 (identity
168
+ * and state badges) degrades in a fixed order — cycle hint, then title, token
169
+ * figures, turn/step counts, goal, divergent sandbox, permission badge — and
170
+ * only then ellipsizes the identity cluster, so the row never wraps. Row 2
171
+ * (mode, context bar, cache, duration figures) fits its own budget and
172
+ * degrades to empty before any row-1 content is touched.
66
173
  * @param facts - identity facts resolved by the runner.
67
174
  * @param stats - session figures folded from the durable log.
68
- * @returns one string per pipe-separated group, in display order.
175
+ * @param columns - usable columns for each row (before their left padding).
176
+ * @param options - 'busy' hides the cycle hint while a turn runs (Codex
177
+ * keeps mode hints idle-only); 'items' is the ordered enabled-item config
178
+ * from /statusline (defaults to the full catalog). Display order follows the
179
+ * config per side while the drop ladder keeps its fixed ranks.
180
+ * @returns the two rows to render; row1.left is never empty.
69
181
  */
70
- export declare function buildStatusGroups(facts: StatusFacts, stats: TranscriptStats): string[];
182
+ export declare function layoutStatusBar(facts: StatusFacts, stats: TranscriptStats, columns: number, options?: {
183
+ busy?: boolean;
184
+ items?: readonly string[];
185
+ }): StatusLayout;
package/package.json CHANGED
@@ -1,117 +1,117 @@
1
- {
2
- "name": "dsh-code",
3
- "description": "Claude-Code-style interactive TUI bundle for DeepSeek Harness (dsh): DeepSeek-blue whale banner, live session transcript, and a blended status line",
4
- "version": "0.5.0",
5
- "type": "module",
6
- "bin": {
7
- "deepseek": "./bin/deepseek.mjs",
8
- "dsh-code": "./bin/deepseek.mjs"
9
- },
10
- "main": "lib/index.mjs",
11
- "types": "lib/types/index.d.ts",
12
- "exports": {
13
- ".": {
14
- "types": "./lib/types/index.d.ts",
15
- "default": "./lib/index.mjs"
16
- },
17
- "./startup": {
18
- "types": "./lib/types/startup.d.ts",
19
- "default": "./lib/startup.mjs"
20
- },
21
- "./invariant": {
22
- "types": "./lib/types/invariant.d.ts",
23
- "default": "./lib/invariant.mjs"
24
- },
25
- "./cordis.patch.yml": "./cordis.patch.yml",
26
- "./src/*": "./src/*",
27
- "./package.json": "./package.json"
28
- },
29
- "files": [
30
- "lib",
31
- "cordis.patch.yml",
32
- "src"
33
- ],
34
- "license": "MIT",
35
- "keywords": [
36
- "deepseek",
37
- "dsh",
38
- "deepseek-harness",
39
- "tui",
40
- "terminal",
41
- "claude-code",
42
- "agent",
43
- "ink"
44
- ],
45
- "repository": {
46
- "type": "git",
47
- "url": "git+https://github.com/unlinearity/dsh-code.git"
48
- },
49
- "dsh": {
50
- "bundle": {
51
- "patch": "./cordis.patch.yml"
52
- }
53
- },
54
- "scripts": {
55
- "build": "tsdown && tsc -p tsconfig.json",
56
- "test": "vitest run",
57
- "typecheck": "tsc -p tsconfig.json --noEmit",
58
- "gen:whale": "tsx scripts/gen-whale-glyph.ts",
59
- "prepare": "pnpm build",
60
- "prepublishOnly": "pnpm typecheck && pnpm test && pnpm build"
61
- },
62
- "engines": {
63
- "node": "^22.19 || >=24"
64
- },
65
- "dependencies": {
66
- "@deepseek-ai/schemastery": "^3.18.1",
67
- "chalk": "^5.6.2",
68
- "commander": "^14.0.2",
69
- "ink": "^5.2.1",
70
- "react": "^18.3.1"
71
- },
72
- "peerDependencies": {
73
- "@deepseek-ai/cordis": "^4.0.1",
74
- "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5",
75
- "@deepseek-ai/dsh-agent": "^0.1.0-rc.6",
76
- "@deepseek-ai/dsh-agent-default-model": "^0.1.0-rc.6",
77
- "@deepseek-ai/dsh-cmdline": "^0.1.0-rc.6",
78
- "@deepseek-ai/dsh-code-runtime-worker-thread": "^0.1.0-rc.6",
79
- "@deepseek-ai/dsh-commands": "^0.1.0-rc.6",
80
- "@deepseek-ai/dsh-compaction": "^0.1.0-rc.6",
81
- "@deepseek-ai/dsh-goal": "^0.1.0-rc.6",
82
- "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6",
83
- "@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
84
- "@deepseek-ai/dsh-llm-retry": "^0.1.0-rc.6",
85
- "@deepseek-ai/dsh-permission-presets": "^0.1.0-rc.6",
86
- "@deepseek-ai/dsh-plan-mode": "^0.1.0-rc.6",
87
- "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.6",
88
- "@deepseek-ai/dsh-session": "^0.1.0-rc.6",
89
- "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.6",
90
- "@deepseek-ai/dsh-session-reference": "^0.1.0-rc.6",
91
- "@deepseek-ai/dsh-session-title": "^0.1.0-rc.6",
92
- "@deepseek-ai/dsh-skill": "^0.1.0-rc.6",
93
- "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.6",
94
- "@deepseek-ai/dsh-user-questions": "^0.1.0-rc.6"
95
- },
96
- "devDependencies": {
97
- "@deepseek-ai/dsh-compaction": "^0.1.0-rc.6",
98
- "@deepseek-ai/dsh-commands": "^0.1.0-rc.6",
99
- "@deepseek-ai/dsh-goal": "^0.1.0-rc.6",
100
- "@deepseek-ai/dsh-llm-retry": "^0.1.0-rc.6",
101
- "@deepseek-ai/dsh-permission-presets": "^0.1.0-rc.6",
102
- "@deepseek-ai/dsh-plan-mode": "^0.1.0-rc.6",
103
- "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.6",
104
- "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.6",
105
- "@deepseek-ai/dsh-session-reference": "^0.1.0-rc.6",
106
- "@deepseek-ai/dsh-session-title": "^0.1.0-rc.6",
107
- "@deepseek-ai/dsh-skill": "^0.1.0-rc.6",
108
- "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.6",
109
- "@deepseek-ai/dsh-user-questions": "^0.1.0-rc.6",
110
- "@types/node": "^24.0.0",
111
- "@types/react": "~18.3.1",
112
- "tsdown": "^0.22.2",
113
- "tsx": "^4.22.4",
114
- "typescript": "^5.9.0",
115
- "vitest": "^3.0.0"
116
- }
117
- }
1
+ {
2
+ "name": "dsh-code",
3
+ "description": "Claude-Code-style interactive TUI bundle for DeepSeek Harness (dsh): DeepSeek-blue whale banner, live session transcript, and a blended status line",
4
+ "version": "0.6.0",
5
+ "type": "module",
6
+ "bin": {
7
+ "deepseek": "./bin/deepseek.mjs",
8
+ "dsh-code": "./bin/deepseek.mjs"
9
+ },
10
+ "main": "lib/index.mjs",
11
+ "types": "lib/types/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./lib/types/index.d.ts",
15
+ "default": "./lib/index.mjs"
16
+ },
17
+ "./startup": {
18
+ "types": "./lib/types/startup.d.ts",
19
+ "default": "./lib/startup.mjs"
20
+ },
21
+ "./invariant": {
22
+ "types": "./lib/types/invariant.d.ts",
23
+ "default": "./lib/invariant.mjs"
24
+ },
25
+ "./cordis.patch.yml": "./cordis.patch.yml",
26
+ "./src/*": "./src/*",
27
+ "./package.json": "./package.json"
28
+ },
29
+ "files": [
30
+ "lib",
31
+ "cordis.patch.yml",
32
+ "src"
33
+ ],
34
+ "license": "MIT",
35
+ "keywords": [
36
+ "deepseek",
37
+ "dsh",
38
+ "deepseek-harness",
39
+ "tui",
40
+ "terminal",
41
+ "claude-code",
42
+ "agent",
43
+ "ink"
44
+ ],
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "git+https://github.com/unlinearity/dsh-code.git"
48
+ },
49
+ "dsh": {
50
+ "bundle": {
51
+ "patch": "./cordis.patch.yml"
52
+ }
53
+ },
54
+ "scripts": {
55
+ "build": "tsdown && tsc -p tsconfig.json",
56
+ "test": "vitest run",
57
+ "typecheck": "tsc -p tsconfig.json --noEmit",
58
+ "gen:whale": "tsx scripts/gen-whale-glyph.ts",
59
+ "prepare": "pnpm build",
60
+ "prepublishOnly": "pnpm typecheck && pnpm test && pnpm build"
61
+ },
62
+ "engines": {
63
+ "node": "^22.19 || >=24"
64
+ },
65
+ "dependencies": {
66
+ "@deepseek-ai/schemastery": "^3.18.1",
67
+ "chalk": "^5.6.2",
68
+ "commander": "^14.0.2",
69
+ "ink": "^5.2.1",
70
+ "react": "^18.3.1"
71
+ },
72
+ "peerDependencies": {
73
+ "@deepseek-ai/cordis": "^4.0.1",
74
+ "@deepseek-ai/cordis-plugin-loader": "^1.0.0-rc.5",
75
+ "@deepseek-ai/dsh-agent": "^0.1.0-rc.6",
76
+ "@deepseek-ai/dsh-agent-default-model": "^0.1.0-rc.6",
77
+ "@deepseek-ai/dsh-cmdline": "^0.1.0-rc.6",
78
+ "@deepseek-ai/dsh-code-runtime-worker-thread": "^0.1.0-rc.6",
79
+ "@deepseek-ai/dsh-commands": "^0.1.0-rc.6",
80
+ "@deepseek-ai/dsh-compaction": "^0.1.0-rc.6",
81
+ "@deepseek-ai/dsh-goal": "^0.1.0-rc.6",
82
+ "@deepseek-ai/dsh-invariants": "^0.1.0-rc.6",
83
+ "@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
84
+ "@deepseek-ai/dsh-llm-retry": "^0.1.0-rc.6",
85
+ "@deepseek-ai/dsh-permission-presets": "^0.1.0-rc.6",
86
+ "@deepseek-ai/dsh-plan-mode": "^0.1.0-rc.6",
87
+ "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.6",
88
+ "@deepseek-ai/dsh-session": "^0.1.0-rc.6",
89
+ "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.6",
90
+ "@deepseek-ai/dsh-session-reference": "^0.1.0-rc.6",
91
+ "@deepseek-ai/dsh-session-title": "^0.1.0-rc.6",
92
+ "@deepseek-ai/dsh-skill": "^0.1.0-rc.6",
93
+ "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.6",
94
+ "@deepseek-ai/dsh-user-questions": "^0.1.0-rc.6"
95
+ },
96
+ "devDependencies": {
97
+ "@deepseek-ai/dsh-compaction": "^0.1.0-rc.6",
98
+ "@deepseek-ai/dsh-commands": "^0.1.0-rc.6",
99
+ "@deepseek-ai/dsh-goal": "^0.1.0-rc.6",
100
+ "@deepseek-ai/dsh-llm-retry": "^0.1.0-rc.6",
101
+ "@deepseek-ai/dsh-permission-presets": "^0.1.0-rc.6",
102
+ "@deepseek-ai/dsh-plan-mode": "^0.1.0-rc.6",
103
+ "@deepseek-ai/dsh-sandbox-policy": "^0.1.0-rc.6",
104
+ "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.6",
105
+ "@deepseek-ai/dsh-session-reference": "^0.1.0-rc.6",
106
+ "@deepseek-ai/dsh-session-title": "^0.1.0-rc.6",
107
+ "@deepseek-ai/dsh-skill": "^0.1.0-rc.6",
108
+ "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.6",
109
+ "@deepseek-ai/dsh-user-questions": "^0.1.0-rc.6",
110
+ "@types/node": "^24.0.0",
111
+ "@types/react": "~18.3.1",
112
+ "tsdown": "^0.22.2",
113
+ "tsx": "^4.22.4",
114
+ "typescript": "^5.9.0",
115
+ "vitest": "^3.0.0"
116
+ }
117
+ }