dsh-code 1.4.0 → 1.5.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 +10 -8
- package/README.md +10 -8
- package/lib/index.mjs +2001 -1688
- package/lib/session-query.mjs +18 -1
- package/lib/types/app.d.ts +21 -15
- package/lib/types/composer.d.ts +1 -1
- package/lib/types/locales/en.d.ts +4 -4
- package/lib/types/render/inspector.d.ts +8 -0
- package/lib/types/render/projection-events.d.ts +33 -0
- package/lib/types/render/transcript-viewport.d.ts +32 -0
- package/lib/types/runner/session-io.d.ts +11 -0
- package/lib/types/session-query.d.ts +11 -0
- package/package.json +3 -2
- package/src/app.ts +286 -123
- package/src/composer.ts +6 -6
- package/src/locales/en.ts +4 -4
- package/src/locales/zh.ts +4 -4
- package/src/render/inspector.ts +12 -0
- package/src/render/lines.ts +45 -18
- package/src/render/projection-events.ts +109 -0
- package/src/render/projection.ts +11 -2
- package/src/render/tool-preview.ts +35 -2
- package/src/render/transcript-viewport.ts +61 -0
- package/src/render/usage.ts +1 -2
- package/src/runner/session-io.ts +43 -4
- package/src/session-query.ts +22 -0
package/lib/session-query.mjs
CHANGED
|
@@ -139,6 +139,23 @@ async function observeStableWithSkip(engine, indexed, signal, readCold = readCol
|
|
|
139
139
|
}
|
|
140
140
|
throw new SessionQueryError("session-search persistence observation did not stabilize after one retry", "SESSION_QUERY_PERSISTENCE_FAILED");
|
|
141
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Assert the private override seam this compatibility engine relies on.
|
|
144
|
+
* Harness keeps `_observeStable` private, so TypeScript cannot protect this
|
|
145
|
+
* subclass when upstream renames the method or changes its call signature.
|
|
146
|
+
* The exact-version launcher gate prevents unsupported hosts; this import-time
|
|
147
|
+
* check additionally prevents a newly built bundle from silently mounting an
|
|
148
|
+
* override the installed base will never call.
|
|
149
|
+
*
|
|
150
|
+
* @internal Exported for the compatibility regression.
|
|
151
|
+
*/
|
|
152
|
+
function assertSessionQueryOverrideContract(candidate) {
|
|
153
|
+
if (typeof candidate !== "function") throw new TypeError("session-query sqlite engine must be a constructor");
|
|
154
|
+
const prototype = candidate.prototype;
|
|
155
|
+
const method = (prototype === void 0 ? void 0 : Object.getOwnPropertyDescriptor(prototype, "_observeStable"))?.value;
|
|
156
|
+
if (typeof method !== "function" || method.length !== 2) throw new Error("incompatible @deepseek-ai/dsh-session-query-sqlite: expected _observeStable(indexed, signal)");
|
|
157
|
+
}
|
|
158
|
+
assertSessionQueryOverrideContract(SqliteSessionQueryEngine);
|
|
142
159
|
const EngineBase = SqliteSessionQueryEngine;
|
|
143
160
|
/** The engine this bundle mounts in place of the base `session-query-sqlite` row. */
|
|
144
161
|
var SkipTolerantSessionQueryEngine = class extends EngineBase {
|
|
@@ -147,4 +164,4 @@ var SkipTolerantSessionQueryEngine = class extends EngineBase {
|
|
|
147
164
|
}
|
|
148
165
|
};
|
|
149
166
|
//#endregion
|
|
150
|
-
export { SkipTolerantSessionQueryEngine, SkipTolerantSessionQueryEngine as default, observeStableWithSkip };
|
|
167
|
+
export { SkipTolerantSessionQueryEngine, SkipTolerantSessionQueryEngine as default, assertSessionQueryOverrideContract, observeStableWithSkip };
|
package/lib/types/app.d.ts
CHANGED
|
@@ -42,6 +42,7 @@ import type { FilePathInspection, ImagePathInspection } from './attachments.ts';
|
|
|
42
42
|
export { completionCandidates, stepCompletionIndex } from './completion.ts';
|
|
43
43
|
import type { NoticeTone, QueueMutation } from './ui/ui-contract.ts';
|
|
44
44
|
export type { NoticeTone, QueueMutation } from './ui/ui-contract.ts';
|
|
45
|
+
import { type StyledLine } from './render/lines.ts';
|
|
45
46
|
/** Props the runner hands the app; callbacks stay owned by the runner. */
|
|
46
47
|
export interface AppProps {
|
|
47
48
|
/** Event-fed transcript store for the live session. */
|
|
@@ -216,8 +217,8 @@ export interface AppProps {
|
|
|
216
217
|
saveLanguage: (name: LanguageName) => void;
|
|
217
218
|
/** Apply and persist one /theme selection; the runner owns the theme.json file. */
|
|
218
219
|
saveTheme?: (name: ThemeName) => void;
|
|
219
|
-
/** Whether
|
|
220
|
-
*
|
|
220
|
+
/** Whether decorative animations run at startup (animations.json; on by
|
|
221
|
+
* default). Functional activity indicators remain live when disabled. */
|
|
221
222
|
animations?: boolean;
|
|
222
223
|
/** Apply and persist one /animation toggle; the runner owns the file. */
|
|
223
224
|
saveAnimations?: (enabled: boolean) => void;
|
|
@@ -248,16 +249,17 @@ export declare function streamTailBodyColumns(rowColumns: number, prefix: string
|
|
|
248
249
|
export declare function queuedInboxRows(entries: readonly TranscriptEntry[], ids: readonly string[]): readonly Extract<TranscriptEntry, {
|
|
249
250
|
kind: 'pending';
|
|
250
251
|
}>[];
|
|
252
|
+
interface SettledPhysicalRow {
|
|
253
|
+
/** Stable one-row Static element. */
|
|
254
|
+
readonly element: ReactElement;
|
|
255
|
+
/** The same row model reused by the mutable viewport tail. */
|
|
256
|
+
readonly line: StyledLine;
|
|
257
|
+
}
|
|
251
258
|
interface SettledRowRecord {
|
|
252
|
-
/**
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
|
|
256
|
-
/** The roomy-prompt spacer AFTER the row, or undefined. */
|
|
257
|
-
after: ReactElement | undefined;
|
|
258
|
-
/** Physical rows this record contributes (row body plus spacers) — the
|
|
259
|
-
* unit of the rendered-history cap. */
|
|
260
|
-
rows: number;
|
|
259
|
+
/** Physical rows for one settled entry, including roomy-prompt spacers. */
|
|
260
|
+
readonly physical: readonly SettledPhysicalRow[];
|
|
261
|
+
/** Physical rows this record contributes — the rendered-history-cap unit. */
|
|
262
|
+
readonly rows: number;
|
|
261
263
|
}
|
|
262
264
|
/** The incremental settled-history cache (see `computeSettledRows`). */
|
|
263
265
|
interface SettledRowsCache {
|
|
@@ -277,10 +279,13 @@ interface SettledRowsCache {
|
|
|
277
279
|
epoch: number;
|
|
278
280
|
/** The terminal width the rows were wrapped for; a change forces a rebuild. */
|
|
279
281
|
columns: number;
|
|
280
|
-
/**
|
|
282
|
+
/** Header/hint followed by one element per physical transcript row. */
|
|
281
283
|
flat: ReactElement[];
|
|
284
|
+
/** Physical transcript rows only (header/hint excluded). */
|
|
285
|
+
physical: SettledPhysicalRow[];
|
|
282
286
|
/** Settled entries dropped from the window's head (rendering only — the
|
|
283
|
-
* event log keeps everything;
|
|
287
|
+
* event log keeps everything; /export reads all of it and Ctrl+O reads its
|
|
288
|
+
* inspectable entries). */
|
|
284
289
|
droppedEntries: number;
|
|
285
290
|
/** Physical rows the window's entries contribute (excludes header/hint). */
|
|
286
291
|
totalRows: number;
|
|
@@ -310,8 +315,9 @@ interface SettledRowsResult {
|
|
|
310
315
|
*
|
|
311
316
|
* RENDERED-HISTORY CAP: the window holds at most `rowCap` physical rows of
|
|
312
317
|
* settled transcript (header and hint reserved on top). The cap exists only
|
|
313
|
-
* here — the event log, the store projection, /export,
|
|
314
|
-
*
|
|
318
|
+
* here — the event log, the store projection, /export, and /resume keep the
|
|
319
|
+
* full history; Ctrl+O keeps its inspectable subset. Ink 5's <Static> is a
|
|
320
|
+
* consumption counter
|
|
315
321
|
* (items.slice(index) keyed on length): deleting head items mid-stream while
|
|
316
322
|
* appending tail items can permanently swallow new rows, so the append branch
|
|
317
323
|
* NEVER drops the head — it only accounts rows and flags `needsTrim` once the
|
package/lib/types/composer.d.ts
CHANGED
|
@@ -116,7 +116,7 @@ export declare function Composer({ active, frozen, frozenHint, busy, descriptors
|
|
|
116
116
|
} | undefined;
|
|
117
117
|
/** Marks the accepted entry consumed (called after the fill is applied). */
|
|
118
118
|
historyConsumed: () => void;
|
|
119
|
-
/** Whether
|
|
119
|
+
/** Whether decorative animations run; caret and busy activity stay live. */
|
|
120
120
|
animations: boolean;
|
|
121
121
|
/** Apply and report one /animation toggle (App persists through the runner). */
|
|
122
122
|
applyAnimations: (enabled: boolean) => void;
|
|
@@ -139,7 +139,7 @@ export declare const en: {
|
|
|
139
139
|
readonly 'cmd.theme': "switch the color theme";
|
|
140
140
|
readonly 'cmd.language': "switch the interface language (/language [en|zh])";
|
|
141
141
|
readonly 'cmd.rainbow': "reroll or pin the rainbow palette (/rainbow [seed])";
|
|
142
|
-
readonly 'cmd.animation': "toggle
|
|
142
|
+
readonly 'cmd.animation': "toggle decorative animations; shimmer and activity stay live (/animation [on|off])";
|
|
143
143
|
readonly 'cmd.history': "search and recall past prompts";
|
|
144
144
|
readonly 'cmd.queue': "manage messages queued for the next turn";
|
|
145
145
|
readonly 'cmd.usage': "show this session token usage";
|
|
@@ -275,12 +275,12 @@ export declare const en: {
|
|
|
275
275
|
readonly 'notice.imageCancelled': "image submission cancelled";
|
|
276
276
|
readonly 'notice.themeConfigUnreadable': "theme config unreadable, using dark: {message}";
|
|
277
277
|
readonly 'notice.languageConfigUnreadable': "language config unreadable, using english: {message}";
|
|
278
|
-
readonly 'notice.animationsConfigUnreadable': "
|
|
278
|
+
readonly 'notice.animationsConfigUnreadable': "decorative animation config unreadable, effects stay on: {message}";
|
|
279
279
|
readonly 'notice.statuslineConfigUnreadable': "statusline config unreadable, using defaults: {message}";
|
|
280
280
|
readonly 'notice.sessionSearchUnavailable': "session search is unavailable in this deployment";
|
|
281
281
|
readonly 'notice.subagentsReadOnly': "subagent conversations are read-only";
|
|
282
282
|
readonly 'notice.statuslineSaveFailed': "statusline save failed: {message}";
|
|
283
|
-
readonly 'notice.animationsSaveFailed': "
|
|
283
|
+
readonly 'notice.animationsSaveFailed': "decorative animation save failed: {message}";
|
|
284
284
|
readonly 'notice.commandRegistryMissing': "no command registry is mounted in this composition";
|
|
285
285
|
readonly 'notice.commandFallbackFailed': "command fallback failed: {message}";
|
|
286
286
|
readonly 'notice.commandFailed': "command failed: {message}";
|
|
@@ -331,7 +331,7 @@ export declare const en: {
|
|
|
331
331
|
readonly 'notice.commandAttachments': "commands cannot carry attachments; the line will be sent to the model as a prompt";
|
|
332
332
|
readonly 'notice.copyFailed': "copy failed: {message}";
|
|
333
333
|
readonly 'notice.vscodeKeysFailed': "vscode-keys failed: {message}";
|
|
334
|
-
readonly 'notice.animationState': "animations {state}";
|
|
334
|
+
readonly 'notice.animationState': "decorative animations {state}; activity indicators stay live";
|
|
335
335
|
readonly 'notice.deleteFailed': "delete failed: {message}";
|
|
336
336
|
readonly 'notice.modelChangedPlaceholder': "model → {model} · image history will be sent as text placeholders";
|
|
337
337
|
readonly 'notice.modelNextStep': "model → next step uses {model}";
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
/** Pure viewport, selection, and scrolling rules for exclusive TUI panels. */
|
|
2
|
+
import type { TranscriptEntry } from './projection.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Remove assistant settlements that contain reasoning but no final response.
|
|
5
|
+
* They remain in the durable transcript and in the Ctrl/Alt+R fold; excluding
|
|
6
|
+
* them only from Ctrl+O navigation prevents short progress thoughts from
|
|
7
|
+
* appearing as a long run of misleading `reply` entries.
|
|
8
|
+
*/
|
|
9
|
+
export declare function inspectableTranscriptEntries(entries: readonly TranscriptEntry[]): readonly TranscriptEntry[];
|
|
2
10
|
/** Terminal-space allocation for the inspector's one dynamic screen. */
|
|
3
11
|
export interface InspectorViewport {
|
|
4
12
|
/** Maximum dynamic rows, kept strictly below the terminal height. */
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Explicit compatibility policy for durable session events entering the TUI.
|
|
3
|
+
*
|
|
4
|
+
* The Harness event map is merge-extensible, so a reducer default branch is
|
|
5
|
+
* unavoidable: deployments may mount plugins this bundle does not know. The
|
|
6
|
+
* default must not, however, let a NEW first-party event silently bypass
|
|
7
|
+
* review. Tests compare this policy with `KNOWN_SESSION_EVENT_TYPES`; every
|
|
8
|
+
* kernel event must be deliberately classified before a Harness-line bump.
|
|
9
|
+
*
|
|
10
|
+
* @module @deepseek-ai/dsh-tui/render/projection-events
|
|
11
|
+
*/
|
|
12
|
+
/** How one durable event relates to the terminal transcript projection. */
|
|
13
|
+
export type SessionEventDisposition = 'transcript' | 'other-surface' | 'ignored' | 'unknown';
|
|
14
|
+
/** Events folded directly into `TranscriptView`. */
|
|
15
|
+
export declare const TRANSCRIPT_SESSION_EVENT_TYPES: readonly ["agent/inbox/spliced", "assistant/attempt", "assistant/message", "command/done", "command/run", "compaction/end", "compaction/prune", "compaction/summary", "goal/change", "llm/retry", "llm/retry-started", "permission/preset", "plan/mode", "request/context", "request/header", "sandbox/mode", "schedule/change", "session/title", "step/start", "system/message", "todo/write", "tool-workflow/agent-end", "tool-workflow/agent-start", "tool-workflow/run-end", "tool-workflow/run-start", "tool/call", "tool/ptc-dispatch", "tool/ptc-dispatch-start", "tool/result", "turn/end", "turn/start", "user/message"];
|
|
16
|
+
/**
|
|
17
|
+
* Events consumed by another TUI adapter rather than the transcript fold.
|
|
18
|
+
* Keeping these separate documents that they are visible behavior, not
|
|
19
|
+
* accidental no-ops.
|
|
20
|
+
*/
|
|
21
|
+
export declare const OTHER_SURFACE_SESSION_EVENT_TYPES: readonly ["agent-preset/selected", "model/selection", "subagent/catalog"];
|
|
22
|
+
/**
|
|
23
|
+
* Kernel events deliberately omitted from terminal presentation. Their
|
|
24
|
+
* model-visible consequences arrive through projected message/tool/session
|
|
25
|
+
* events, while audit-only facts do not need a second transcript row.
|
|
26
|
+
*/
|
|
27
|
+
export declare const IGNORED_SESSION_EVENT_TYPES: readonly ["approval/asked", "approval/decided", "approval/policy", "compaction/start", "deliverables/presented", "feedback/message-delete", "feedback/message-put", "feedback/record", "hook/invoked", "hook/result", "session-log-deepseek/delivery-accepted", "session/end-seed", "session/title-llm-request", "step/end", "subagent/descriptor", "subagent/model-selection-policy", "team/member", "team/message/delivered", "team/message/queued", "team/task", "web/deepseek-search-llm-request"];
|
|
28
|
+
/**
|
|
29
|
+
* Classify a durable event without rejecting merge-extensible plugin events.
|
|
30
|
+
* `unknown` remains a runtime no-op for forward/plugin compatibility; the
|
|
31
|
+
* known-event coverage test is what makes a first-party addition fail CI.
|
|
32
|
+
*/
|
|
33
|
+
export declare function sessionEventDisposition(type: string): SessionEventDisposition;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Physical-row viewport state for native scrollback plus a bottom-anchored tail. */
|
|
2
|
+
export interface TranscriptViewportCursor {
|
|
3
|
+
readonly sessionKey: string;
|
|
4
|
+
readonly epoch: number;
|
|
5
|
+
readonly flushedRows: number;
|
|
6
|
+
}
|
|
7
|
+
export interface TranscriptViewportInput {
|
|
8
|
+
readonly sessionKey: string;
|
|
9
|
+
readonly epoch: number;
|
|
10
|
+
/** Physical durable transcript rows in the current rendered-history window. */
|
|
11
|
+
readonly totalRows: number;
|
|
12
|
+
/** Maximum durable rows retained outside Static for the live viewport. */
|
|
13
|
+
readonly retainedRows: number;
|
|
14
|
+
}
|
|
15
|
+
export interface TranscriptViewportStep {
|
|
16
|
+
readonly cursor: TranscriptViewportCursor;
|
|
17
|
+
/** Durable physical rows emitted through Static. */
|
|
18
|
+
readonly staticRows: number;
|
|
19
|
+
/** Durable physical rows still available to the live viewport. */
|
|
20
|
+
readonly liveRows: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Advance the monotonic physical-row flush cursor.
|
|
24
|
+
*
|
|
25
|
+
* Ordinary renders never pull a row back out of native scrollback. A source-
|
|
26
|
+
* backed replay (epoch change) flushes the complete durable window exactly
|
|
27
|
+
* once after the caller clears/remounts Static; subsequent durable rows start
|
|
28
|
+
* a fresh retained tail. Session/reset shrink starts from the new source.
|
|
29
|
+
*/
|
|
30
|
+
export declare function advanceTranscriptViewport(previous: TranscriptViewportCursor, input: TranscriptViewportInput): TranscriptViewportStep;
|
|
31
|
+
/** Real history rows that fit beside the currently painted stream/tool rows. */
|
|
32
|
+
export declare function visibleTranscriptRows(historyRows: number, occupiedRows: number, capacity: number): number;
|
|
@@ -38,6 +38,17 @@ export interface SessionIo {
|
|
|
38
38
|
/** Render one session's whole transcript as export Markdown. */
|
|
39
39
|
readonly loadSessionTranscript: (id: string, signal?: AbortSignal) => Promise<string>;
|
|
40
40
|
}
|
|
41
|
+
/** Maximum session artifact directories inspected at once by the picker. */
|
|
42
|
+
export declare const SESSION_ARTIFACT_READ_CONCURRENCY = 16;
|
|
43
|
+
/**
|
|
44
|
+
* Map a collection with a fixed worker count while preserving input order.
|
|
45
|
+
* The picker may own thousands of persisted sessions; an unbounded
|
|
46
|
+
* `Promise.all` turns those into one filesystem burst and can exhaust handles
|
|
47
|
+
* on Windows or remote filesystems.
|
|
48
|
+
*
|
|
49
|
+
* @internal Exported for the deterministic concurrency regression.
|
|
50
|
+
*/
|
|
51
|
+
export declare function mapConcurrent<T, R>(items: readonly T[], concurrency: number, mapper: (item: T, index: number) => Promise<R>): Promise<R[]>;
|
|
41
52
|
/**
|
|
42
53
|
* Bind the session IO to one runner's services.
|
|
43
54
|
* @param services - the query engine, persistence, and the live-session probe.
|
|
@@ -81,6 +81,17 @@ export declare function observeStableWithSkip(engine: EngineSurface, indexed: Re
|
|
|
81
81
|
persisted: Map<SessionId, ObservedPersistedSession>;
|
|
82
82
|
live: Map<SessionId, ObservedSession>;
|
|
83
83
|
}>;
|
|
84
|
+
/**
|
|
85
|
+
* Assert the private override seam this compatibility engine relies on.
|
|
86
|
+
* Harness keeps `_observeStable` private, so TypeScript cannot protect this
|
|
87
|
+
* subclass when upstream renames the method or changes its call signature.
|
|
88
|
+
* The exact-version launcher gate prevents unsupported hosts; this import-time
|
|
89
|
+
* check additionally prevents a newly built bundle from silently mounting an
|
|
90
|
+
* override the installed base will never call.
|
|
91
|
+
*
|
|
92
|
+
* @internal Exported for the compatibility regression.
|
|
93
|
+
*/
|
|
94
|
+
export declare function assertSessionQueryOverrideContract(candidate: unknown): void;
|
|
84
95
|
declare const EngineBase: abstract new (ctx: never, config: Config) => EngineSurface & object;
|
|
85
96
|
/** The engine this bundle mounts in place of the base `session-query-sqlite` row. */
|
|
86
97
|
export declare class SkipTolerantSessionQueryEngine extends EngineBase {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-code",
|
|
3
3
|
"description": "DeepSeek Harness CLI core bundle: interactive coding terminal, durable sessions, and model management for dsh --profile cli",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.5.0",
|
|
5
5
|
"packageManager": "pnpm@12.4.1",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -65,7 +65,8 @@
|
|
|
65
65
|
"typecheck:tests": "tsc -p tsconfig.test.json --noEmit",
|
|
66
66
|
"lint": "eslint . --max-warnings 0",
|
|
67
67
|
"lint:fix": "eslint . --fix --max-warnings 0",
|
|
68
|
-
"
|
|
68
|
+
"perf:check": "tsx scripts/check-performance.ts",
|
|
69
|
+
"verify": "pnpm lint && pnpm typecheck && pnpm typecheck:tests && pnpm test && pnpm perf:check",
|
|
69
70
|
"gen:whale": "tsx scripts/gen-whale-glyph.ts",
|
|
70
71
|
"prepare": "pnpm build",
|
|
71
72
|
"prepublishOnly": "pnpm audit:prod && pnpm exec tsx scripts/check-release.ts --package-version && pnpm verify && pnpm build"
|