dsh-code 1.3.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 +6980 -5942
- package/lib/session-query.mjs +18 -1
- package/lib/types/app.d.ts +38 -65
- 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 +20 -8
- package/lib/types/{authorization-panel.d.ts → panels/authorization-panel.d.ts} +6 -1
- package/lib/types/panels/completion-panel.d.ts +13 -0
- package/lib/types/panels/interaction-bars.d.ts +38 -0
- package/lib/types/{kernel-panels.d.ts → panels/kernel-panels.d.ts} +16 -37
- package/lib/types/{language-panel.d.ts → panels/language-panel.d.ts} +1 -1
- package/lib/types/panels/model-panels.d.ts +86 -0
- package/lib/types/{theme-panel.d.ts → panels/theme-panel.d.ts} +1 -1
- package/lib/types/{update-panel.d.ts → panels/update-panel.d.ts} +1 -1
- package/lib/types/provider-settings.d.ts +11 -0
- package/lib/types/render/inspector.d.ts +16 -0
- package/lib/types/render/projection-events.d.ts +33 -0
- package/lib/types/render/text.d.ts +4 -0
- package/lib/types/render/transcript-viewport.d.ts +32 -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 +57 -0
- package/lib/types/runner/session-target.d.ts +42 -0
- package/lib/types/runner/startup-config.d.ts +33 -0
- package/lib/types/runner/submissions.d.ts +87 -0
- package/lib/types/session/attach.d.ts +39 -0
- package/lib/types/{store.d.ts → session/store.d.ts} +1 -1
- package/lib/types/{subagents.d.ts → session/subagents.d.ts} +8 -1
- package/lib/types/session-query.d.ts +11 -0
- package/lib/types/settings-file.d.ts +10 -0
- package/lib/types/{panel-accent.d.ts → ui/panel-accent.d.ts} +1 -1
- package/lib/types/ui/panel-gap.d.ts +6 -0
- package/lib/types/ui/query-editor.d.ts +10 -0
- package/lib/types/ui/styled-rows.d.ts +8 -0
- package/lib/types/{terminal-title.d.ts → ui/terminal-title.d.ts} +1 -1
- package/lib/types/ui/ui-contract.d.ts +12 -0
- package/lib/types/ui/use-frames.d.ts +6 -0
- package/lib/types/ui/use-stable-input.d.ts +7 -0
- package/package.json +3 -2
- package/src/app.ts +802 -4162
- package/src/completion.ts +117 -0
- package/src/composer.ts +1956 -0
- package/src/git-workflow.ts +18 -0
- package/src/index.ts +113 -633
- package/src/internals.ts +1 -1
- package/src/locales/en.ts +20 -8
- package/src/locales/zh.ts +20 -8
- package/src/{authorization-panel.ts → panels/authorization-panel.ts} +25 -6
- package/src/panels/completion-panel.ts +79 -0
- package/src/panels/interaction-bars.ts +567 -0
- package/src/{kernel-panels.ts → panels/kernel-panels.ts} +84 -65
- package/src/{language-panel.ts → panels/language-panel.ts} +4 -4
- package/src/panels/model-panels.ts +1021 -0
- package/src/{theme-panel.ts → panels/theme-panel.ts} +5 -5
- package/src/{update-panel.ts → panels/update-panel.ts} +6 -6
- package/src/provider-settings.ts +38 -0
- package/src/render/inspector.ts +35 -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/text.ts +8 -0
- 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/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 +245 -0
- package/src/runner/session-target.ts +81 -0
- package/src/runner/startup-config.ts +54 -0
- package/src/runner/submissions.ts +157 -0
- package/src/session/attach.ts +87 -0
- package/src/{session-directory.ts → session/session-directory.ts} +1 -1
- package/src/{store.ts → session/store.ts} +1 -1
- package/src/{subagents.ts → session/subagents.ts} +12 -1
- package/src/session-query.ts +22 -0
- package/src/settings-file.ts +19 -1
- package/src/{panel-accent.ts → ui/panel-accent.ts} +1 -1
- package/src/ui/panel-gap.ts +9 -0
- package/src/ui/query-editor.ts +16 -0
- package/src/ui/styled-rows.ts +124 -0
- package/src/{terminal-title.ts → ui/terminal-title.ts} +1 -1
- package/src/ui/ui-contract.ts +10 -0
- package/src/ui/use-frames.ts +23 -0
- package/src/ui/use-stable-input.ts +17 -0
- /package/lib/types/{fork.d.ts → session/fork.d.ts} +0 -0
- /package/lib/types/{history.d.ts → session/history.d.ts} +0 -0
- /package/lib/types/{session-directory.d.ts → session/session-directory.d.ts} +0 -0
- /package/lib/types/{session-switch.d.ts → session/session-switch.d.ts} +0 -0
- /package/src/{fork.ts → session/fork.ts} +0 -0
- /package/src/{history.ts → session/history.ts} +0 -0
- /package/src/{session-switch.ts → session/session-switch.ts} +0 -0
|
@@ -86,8 +86,15 @@ export declare const en: {
|
|
|
86
86
|
readonly 'schedule.titlePlural': "/schedule · {count} active reminders";
|
|
87
87
|
readonly 'schedule.empty': "no active reminders — the model creates them with schedule_create";
|
|
88
88
|
readonly 'document.loading': "loading transcript…";
|
|
89
|
+
readonly 'attach.bar': "observing · {label} · r reload · esc/ctrl+d back";
|
|
90
|
+
readonly 'attach.loading': "loading {label}'s conversation…";
|
|
91
|
+
readonly 'attach.status': "subagent {label} · {id} · {turns} turns";
|
|
92
|
+
readonly 'notice.attachUnavailable': "subagent attachment is unavailable in this profile";
|
|
89
93
|
readonly 'document.compact': "transcript · esc close";
|
|
90
|
-
readonly 'document.
|
|
94
|
+
readonly 'document.expanded': "expanded";
|
|
95
|
+
readonly 'document.refreshHint': "r refresh";
|
|
96
|
+
readonly 'document.footerExpanded': "lines {from}-{to}/{total} · ↑↓/pg/g/G{refresh} · esc/ctrl+d back";
|
|
97
|
+
readonly 'document.footer': "lines {from}-{to}/{total} · ↑↓/pg/g/G · enter/f expand · t/esc close";
|
|
91
98
|
readonly 'review.picker.title': "/review · choose a target";
|
|
92
99
|
readonly 'review.picker.uncommitted': "Review uncommitted changes (staged / unstaged / new files)";
|
|
93
100
|
readonly 'review.picker.branch': "Compare against a base branch (lists local branches)";
|
|
@@ -132,7 +139,7 @@ export declare const en: {
|
|
|
132
139
|
readonly 'cmd.theme': "switch the color theme";
|
|
133
140
|
readonly 'cmd.language': "switch the interface language (/language [en|zh])";
|
|
134
141
|
readonly 'cmd.rainbow': "reroll or pin the rainbow palette (/rainbow [seed])";
|
|
135
|
-
readonly 'cmd.animation': "toggle
|
|
142
|
+
readonly 'cmd.animation': "toggle decorative animations; shimmer and activity stay live (/animation [on|off])";
|
|
136
143
|
readonly 'cmd.history': "search and recall past prompts";
|
|
137
144
|
readonly 'cmd.queue': "manage messages queued for the next turn";
|
|
138
145
|
readonly 'cmd.usage': "show this session token usage";
|
|
@@ -268,12 +275,12 @@ export declare const en: {
|
|
|
268
275
|
readonly 'notice.imageCancelled': "image submission cancelled";
|
|
269
276
|
readonly 'notice.themeConfigUnreadable': "theme config unreadable, using dark: {message}";
|
|
270
277
|
readonly 'notice.languageConfigUnreadable': "language config unreadable, using english: {message}";
|
|
271
|
-
readonly 'notice.animationsConfigUnreadable': "
|
|
278
|
+
readonly 'notice.animationsConfigUnreadable': "decorative animation config unreadable, effects stay on: {message}";
|
|
272
279
|
readonly 'notice.statuslineConfigUnreadable': "statusline config unreadable, using defaults: {message}";
|
|
273
280
|
readonly 'notice.sessionSearchUnavailable': "session search is unavailable in this deployment";
|
|
274
281
|
readonly 'notice.subagentsReadOnly': "subagent conversations are read-only";
|
|
275
282
|
readonly 'notice.statuslineSaveFailed': "statusline save failed: {message}";
|
|
276
|
-
readonly 'notice.animationsSaveFailed': "
|
|
283
|
+
readonly 'notice.animationsSaveFailed': "decorative animation save failed: {message}";
|
|
277
284
|
readonly 'notice.commandRegistryMissing': "no command registry is mounted in this composition";
|
|
278
285
|
readonly 'notice.commandFallbackFailed': "command fallback failed: {message}";
|
|
279
286
|
readonly 'notice.commandFailed': "command failed: {message}";
|
|
@@ -324,7 +331,7 @@ export declare const en: {
|
|
|
324
331
|
readonly 'notice.commandAttachments': "commands cannot carry attachments; the line will be sent to the model as a prompt";
|
|
325
332
|
readonly 'notice.copyFailed': "copy failed: {message}";
|
|
326
333
|
readonly 'notice.vscodeKeysFailed': "vscode-keys failed: {message}";
|
|
327
|
-
readonly 'notice.animationState': "animations {state}";
|
|
334
|
+
readonly 'notice.animationState': "decorative animations {state}; activity indicators stay live";
|
|
328
335
|
readonly 'notice.deleteFailed': "delete failed: {message}";
|
|
329
336
|
readonly 'notice.modelChangedPlaceholder': "model → {model} · image history will be sent as text placeholders";
|
|
330
337
|
readonly 'notice.modelNextStep': "model → next step uses {model}";
|
|
@@ -417,7 +424,6 @@ export declare const en: {
|
|
|
417
424
|
readonly 'panel.provider.notConfiguredDivider': "── not configured ──";
|
|
418
425
|
readonly 'panel.provider.title': "/model — providers";
|
|
419
426
|
readonly 'panel.provider.titleCount': "/model — providers · {index}/{total}";
|
|
420
|
-
readonly 'panel.provider.state': "{route} · {value}";
|
|
421
427
|
readonly 'panel.provider.key': "key {value}";
|
|
422
428
|
readonly 'panel.provider.authConfigured': "provider auth";
|
|
423
429
|
readonly 'panel.provider.noKey': "key missing";
|
|
@@ -432,7 +438,7 @@ export declare const en: {
|
|
|
432
438
|
readonly 'panel.provider.readOnlyLogin': "this login record is read-only";
|
|
433
439
|
readonly 'panel.provider.notManaged': "this provider is not managed by Harness settings";
|
|
434
440
|
readonly 'panel.providers.compact': "/model providers · enter configure · d remove key · esc back";
|
|
435
|
-
readonly 'panel.providers.footer': "↑↓ move · enter configure ·
|
|
441
|
+
readonly 'panel.providers.footer': "↑↓ move · enter configure · d remove key · x remove provider · r retry · esc back";
|
|
436
442
|
readonly 'panel.update.compact': "/update · {summary}";
|
|
437
443
|
readonly 'panel.update.checking': "checking…";
|
|
438
444
|
readonly 'panel.update.probeFailed': "probe failed";
|
|
@@ -460,8 +466,14 @@ export declare const en: {
|
|
|
460
466
|
readonly 'panel.setup.copyInto': "copy verbatim into {id}";
|
|
461
467
|
readonly 'panel.setup.copyTitle': "/model — copy efforts";
|
|
462
468
|
readonly 'panel.setup.copyFooter': "↑↓ move · enter copy · esc back";
|
|
469
|
+
readonly 'panel.setup.mode.subscribe': "Subscription";
|
|
470
|
+
readonly 'panel.setup.mode.key': "Key";
|
|
471
|
+
readonly 'panel.setup.mode.login.plan': "signed in · plan";
|
|
472
|
+
readonly 'panel.setup.mode.login.none': "not signed in";
|
|
473
|
+
readonly 'panel.setup.mode.login.running': "signing in…";
|
|
474
|
+
readonly 'panel.setup.mode.overridden': "⚠ the settings key overrides the plan sign-in";
|
|
463
475
|
readonly 'panel.setup.title': "/model — configure {provider}";
|
|
464
|
-
readonly 'panel.setup.footer': "↑↓ move · ←→ in/out · space remove · e efforts · c copy efforts · tab discover · enter save · esc back";
|
|
476
|
+
readonly 'panel.setup.footer': "↑↓ move · ←→ in/out · space remove · e efforts · c copy efforts · tab per channel (subscription = web sign-in, key = discover) · enter save · esc back";
|
|
465
477
|
readonly 'panel.discovery.compact': "model discovery · terminal too small · esc back";
|
|
466
478
|
readonly 'panel.discovery.loading': "discovering models…";
|
|
467
479
|
readonly 'panel.discovery.empty': "the endpoint advertised no models; add ids by hand on the setup page";
|
|
@@ -2,9 +2,14 @@
|
|
|
2
2
|
import { type ReactElement } from 'react';
|
|
3
3
|
import { type AuthorizationInteraction, type AuthorizationStatus } from '@deepseek-ai/dsh-authorization';
|
|
4
4
|
import type { CredentialKey } from '@deepseek-ai/dsh-credentials';
|
|
5
|
-
import type { ProviderAuthorizationRow } from '
|
|
5
|
+
import type { ProviderAuthorizationRow } from '../authorization.ts';
|
|
6
6
|
export interface ProviderAuthorizationPanelProps {
|
|
7
7
|
readonly row: ProviderAuthorizationRow;
|
|
8
|
+
/**
|
|
9
|
+
* Start this method immediately instead of showing the picker: a
|
|
10
|
+
* single-method provider signs in with no extra step.
|
|
11
|
+
*/
|
|
12
|
+
readonly autoStartMethod?: string;
|
|
8
13
|
begin(row: ProviderAuthorizationRow, method: string, interaction: AuthorizationInteraction, signal: AbortSignal): Promise<AuthorizationStatus>;
|
|
9
14
|
cancel(key: CredentialKey): void;
|
|
10
15
|
openUrl(url: string): boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Bounded slash-command and mention completion menu. */
|
|
2
|
+
import { type ReactElement } from 'react';
|
|
3
|
+
import type { CompletionCandidate } from '../completion.ts';
|
|
4
|
+
/** Total physical rows occupied by the completion menu at this terminal height. */
|
|
5
|
+
export declare function completionMenuRowCount(terminalRows: number, rowCount: number): number;
|
|
6
|
+
/** Completion view anchored directly above the composer band. */
|
|
7
|
+
export declare function CompletionMenu({ active, mention, index, rows, error }: {
|
|
8
|
+
active: boolean;
|
|
9
|
+
mention: boolean;
|
|
10
|
+
index: number;
|
|
11
|
+
rows: readonly CompletionCandidate[];
|
|
12
|
+
error?: string;
|
|
13
|
+
}): ReactElement | undefined;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Approval and structured-question keyboard-owned terminal surfaces. */
|
|
2
|
+
import { type ReactElement } from 'react';
|
|
3
|
+
import type { ApprovalSnapshot } from '../approval.ts';
|
|
4
|
+
import type { QuestionSnapshot, QuestionStore } from '../questions.ts';
|
|
5
|
+
import type { NoticeTone } from '../ui/ui-contract.ts';
|
|
6
|
+
/**
|
|
7
|
+
* The approval dialog (Codex ApprovalOverlay contract): a bold question
|
|
8
|
+
* header, the bounded command body with an explicit overflow marker, a
|
|
9
|
+
* numbered option list with a `›` cursor, single-key shortcuts, and digits
|
|
10
|
+
* for direct selection. Askers queue FIFO — the count rides the header.
|
|
11
|
+
* The upstream answerer vocabulary stays binary (`allowed-once` /
|
|
12
|
+
* `rejected`): "tell it what to do differently" rejects and hands the
|
|
13
|
+
* composer back with a hint notice, exactly Codex's decline-then-type flow.
|
|
14
|
+
*/
|
|
15
|
+
export declare function ApprovalBar({ snapshot, locked, notify, interrupt, summarize }: {
|
|
16
|
+
snapshot: ApprovalSnapshot;
|
|
17
|
+
locked: boolean;
|
|
18
|
+
notify: (text: string, tone?: NoticeTone) => void;
|
|
19
|
+
/** Cancel the running turn (Ctrl+C), matching the composer's busy branch. */
|
|
20
|
+
interrupt: () => boolean;
|
|
21
|
+
/** Render as the bounded one-line form even on tall terminals (another
|
|
22
|
+
* human-asked surface already owns the full panel budget). */
|
|
23
|
+
summarize?: boolean;
|
|
24
|
+
}): ReactElement | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* The ask_user_question bar: walks one request question by question,
|
|
27
|
+
* retaining an independent draft for every question. Options use Space/1-9
|
|
28
|
+
* to toggle a multi-select, Enter to confirm, and arrows/Ctrl+P/N to move
|
|
29
|
+
* between questions. Plan reviews arrive through the same service with a
|
|
30
|
+
* `plan-review` intent — the approve option gets a ✓ mark, the answer
|
|
31
|
+
* encoding stays identical.
|
|
32
|
+
*/
|
|
33
|
+
export declare function QuestionBar({ store, snapshot, locked }: {
|
|
34
|
+
store: QuestionStore;
|
|
35
|
+
snapshot: QuestionSnapshot;
|
|
36
|
+
locked: boolean;
|
|
37
|
+
}): ReactElement | undefined;
|
|
38
|
+
/** The /model panel: a scrolling list over the advisory model directory. */
|
|
@@ -1,24 +1,18 @@
|
|
|
1
1
|
/** Bounded, composer-safe panels for preset, session, and plugin kernel views. */
|
|
2
2
|
import { type ReactElement } from 'react';
|
|
3
|
-
import type { ModelDirectory, ModelRow } from '
|
|
4
|
-
import type { SubagentRow } from '
|
|
5
|
-
import type {
|
|
6
|
-
|
|
7
|
-
import type {
|
|
8
|
-
import type {
|
|
9
|
-
import type {
|
|
10
|
-
import type {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
* markers are stripped and control-laden chunks are ignored.
|
|
17
|
-
*/
|
|
18
|
-
export declare function editQuery(query: string, input: string, key: {
|
|
19
|
-
backspace?: boolean;
|
|
20
|
-
delete?: boolean;
|
|
21
|
-
}): string | undefined;
|
|
3
|
+
import type { ModelDirectory, ModelRow } from '../models.ts';
|
|
4
|
+
import type { SubagentRow } from '../session/subagents.ts';
|
|
5
|
+
import type { SearchRow } from '../runner/search-rows.ts';
|
|
6
|
+
export type { SearchRow } from '../runner/search-rows.ts';
|
|
7
|
+
import type { ScheduleRow } from '../render/projection.ts';
|
|
8
|
+
import type { PermissionRow } from '../permissions.ts';
|
|
9
|
+
import type { PresetRow } from '../presets.ts';
|
|
10
|
+
import type { PluginRow } from '../plugin-inventory.ts';
|
|
11
|
+
import type { SessionDirectoryOptions, SessionRow } from '../session/session-directory.ts';
|
|
12
|
+
import type { ReviewBranch, ReviewCommit, ReviewSelection } from '../git-workflow.ts';
|
|
13
|
+
import { type UsageView } from '../render/usage.ts';
|
|
14
|
+
import { type StatusItemId } from '../render/status.ts';
|
|
15
|
+
export { editQuery } from '../ui/query-editor.ts';
|
|
22
16
|
export declare function ModePanel({ current, load, select, close }: {
|
|
23
17
|
current: string;
|
|
24
18
|
load: () => Promise<readonly PresetRow[]>;
|
|
@@ -110,23 +104,6 @@ export declare function ReviewPickerPanel({ loadBranches, loadCommits, choose, c
|
|
|
110
104
|
choose: (selection: ReviewSelection) => void;
|
|
111
105
|
close: () => void;
|
|
112
106
|
}): ReactElement;
|
|
113
|
-
/** One cross-session full-text search hit mapped from the session-query engine. */
|
|
114
|
-
export interface SearchRow {
|
|
115
|
-
/** Session id (Enter resumes it through the switch machinery). */
|
|
116
|
-
readonly id: string;
|
|
117
|
-
/** Display label: session title or the short id form. */
|
|
118
|
-
readonly label: string;
|
|
119
|
-
/** Secondary facts line (workspace · preset markers). */
|
|
120
|
-
readonly detail: string;
|
|
121
|
-
/** Bounded plain-text excerpt around the strongest match. */
|
|
122
|
-
readonly snippet: string;
|
|
123
|
-
/** Match timestamp (relative labels derive from it). */
|
|
124
|
-
readonly updatedAt: number;
|
|
125
|
-
/** Whether the hit is a delegated subagent conversation (not resumable). */
|
|
126
|
-
readonly subagent: boolean;
|
|
127
|
-
/** Whether Enter may switch into it. */
|
|
128
|
-
readonly resumable: boolean;
|
|
129
|
-
}
|
|
130
107
|
/**
|
|
131
108
|
* The /search panel: full-text search over every persisted session through
|
|
132
109
|
* the in-process session-query engine (the same corpus the model's
|
|
@@ -182,13 +159,15 @@ export declare function EffortPanel({ row, current, select, back, onExit }: {
|
|
|
182
159
|
* Enter/t opening the child's full transcript in the shared read-only
|
|
183
160
|
* document view (the same projection the exporter uses).
|
|
184
161
|
*/
|
|
185
|
-
export declare function AgentsPanel({ live, load, readTranscript, close }: {
|
|
162
|
+
export declare function AgentsPanel({ live, load, readTranscript, attach, close }: {
|
|
186
163
|
/** Live feed rows (child sessions observed this process). */
|
|
187
164
|
live: readonly SubagentRow[];
|
|
188
165
|
/** Load this session's persisted child sessions by lineage. */
|
|
189
166
|
load: () => Promise<readonly SessionRow[]>;
|
|
190
167
|
/** Read one child session's full transcript as markdown. */
|
|
191
168
|
readTranscript: (id: string, signal?: AbortSignal) => Promise<string>;
|
|
169
|
+
/** Attach to one child as the whole view (the runner's live buses). */
|
|
170
|
+
attach: ((id: string, label: string) => void) | undefined;
|
|
192
171
|
close: () => void;
|
|
193
172
|
}): ReactElement;
|
|
194
173
|
/**
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* repainting the whole screen so Static-region text switches too).
|
|
5
5
|
*/
|
|
6
6
|
import { type ReactElement } from 'react';
|
|
7
|
-
import { type LanguageName } from '
|
|
7
|
+
import { type LanguageName } from '../i18n.ts';
|
|
8
8
|
export declare function LanguagePanel({ current, select, close }: {
|
|
9
9
|
current: LanguageName;
|
|
10
10
|
select: (name: LanguageName) => void;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/** Model selection and provider-management panels for the terminal app. */
|
|
2
|
+
import { type ReactElement } from 'react';
|
|
3
|
+
import type { ModelDirectory, ModelRow } from '../models.ts';
|
|
4
|
+
import { type DiscoveredModelView, type ProviderConfiguration, type ProviderSettingsDirectory, type ProviderTargetView } from '../provider-settings.ts';
|
|
5
|
+
import { type ProviderAuthorizationDirectory, type ProviderAuthorizationRow } from '../authorization.ts';
|
|
6
|
+
export declare function ModelPanel({ directory, error, current, onSelect, onProviders, onRetry, onClose }: {
|
|
7
|
+
directory: ModelDirectory | undefined;
|
|
8
|
+
error: string | undefined;
|
|
9
|
+
/** `provider/model` label of the applied model: the cursor lands on it once. */
|
|
10
|
+
current?: string;
|
|
11
|
+
onSelect: (row: ModelRow) => void;
|
|
12
|
+
onProviders?: () => void;
|
|
13
|
+
onRetry: () => void;
|
|
14
|
+
onClose: () => void;
|
|
15
|
+
}): ReactElement;
|
|
16
|
+
/** The provider-management stage reached from /model with `a`. */
|
|
17
|
+
export declare function ProviderPanel({ directory, error, authorizations, authorizationError, onConfigure, onUnset, onRemove, onRetry, onBack, onExit }: {
|
|
18
|
+
directory: ProviderSettingsDirectory | undefined;
|
|
19
|
+
error: string | undefined;
|
|
20
|
+
authorizations: ProviderAuthorizationDirectory | undefined;
|
|
21
|
+
authorizationError: string | undefined;
|
|
22
|
+
onConfigure: (target: ProviderTargetView) => void;
|
|
23
|
+
onUnset: (target: ProviderTargetView) => void;
|
|
24
|
+
onRemove: (target: ProviderTargetView) => void;
|
|
25
|
+
onRetry: () => void;
|
|
26
|
+
onBack: () => void;
|
|
27
|
+
/** Leave the whole /model flow (Ctrl+C), not just this stage. */
|
|
28
|
+
onExit: () => void;
|
|
29
|
+
}): ReactElement;
|
|
30
|
+
/** Provider configuration editor: only explicit models are written to settings. */
|
|
31
|
+
/**
|
|
32
|
+
* The unified provider setup page: API key, endpoint, and the explicit model
|
|
33
|
+
* list (with per-model context/output capacities) on ONE screen — the deep
|
|
34
|
+
* Tab menu and the separate key panel merged into a single discoverable
|
|
35
|
+
* surface. A saved key rides the same Enter as the endpoint and models; an
|
|
36
|
+
* empty endpoint keeps the provider's official default. Tab moves to the
|
|
37
|
+
* discovery page, which interrogates the real endpoint and returns checkable
|
|
38
|
+
* models for adoption; the last row also accepts hand-typed model ids.
|
|
39
|
+
*/
|
|
40
|
+
/** One declarable donor the setup page can copy reasoning efforts from verbatim. */
|
|
41
|
+
export interface EffortDonor {
|
|
42
|
+
/** Provider route the declaration lives on. */
|
|
43
|
+
readonly provider: string;
|
|
44
|
+
/** Model id the declaration belongs to. */
|
|
45
|
+
readonly id: string;
|
|
46
|
+
/** The stored display-level to wire-value map, copied verbatim. */
|
|
47
|
+
readonly efforts: Record<string, string | null>;
|
|
48
|
+
}
|
|
49
|
+
export declare function ProviderSetupPanel({ target, authorization, onSubscribe, save, saveCredential, discover, effortDonors, done, back, onExit }: {
|
|
50
|
+
target: ProviderTargetView;
|
|
51
|
+
/**
|
|
52
|
+
* The provider's sign-in flow, when it offers a web (OAuth) channel: its
|
|
53
|
+
* presence adds the subscription/key mode layer at the top of the page.
|
|
54
|
+
*/
|
|
55
|
+
authorization: ProviderAuthorizationRow | undefined;
|
|
56
|
+
/** Open the subscription channel: sign in when logged out, confirm sign-out when logged in. */
|
|
57
|
+
onSubscribe: (() => void) | undefined;
|
|
58
|
+
/** Models with declared efforts (settings first, catalog-advertised after) a model row can copy from. */
|
|
59
|
+
effortDonors: readonly EffortDonor[];
|
|
60
|
+
save: (target: ProviderTargetView, configuration: ProviderConfiguration) => Promise<void>;
|
|
61
|
+
saveCredential: ((target: ProviderTargetView, key: string) => Promise<void>) | undefined;
|
|
62
|
+
discover: (target: ProviderTargetView, request: {
|
|
63
|
+
readonly apiKey?: string;
|
|
64
|
+
readonly baseURL?: string;
|
|
65
|
+
}, signal?: AbortSignal) => Promise<readonly DiscoveredModelView[]>;
|
|
66
|
+
/** Report a successful save so the surface can notice the key rotation. */
|
|
67
|
+
done: (result: {
|
|
68
|
+
readonly key: boolean;
|
|
69
|
+
}) => void;
|
|
70
|
+
back: () => void;
|
|
71
|
+
/** Leave the whole /model flow (Ctrl+C), not just this page. */
|
|
72
|
+
onExit: () => void;
|
|
73
|
+
}): ReactElement;
|
|
74
|
+
/** Bounded destructive-action confirmation for credential or provider removal. */
|
|
75
|
+
export declare function ProviderConfirmPanel({ target, kind, confirm, done, back }: {
|
|
76
|
+
target: ProviderTargetView;
|
|
77
|
+
kind: 'credential' | 'provider';
|
|
78
|
+
confirm: (target: ProviderTargetView) => Promise<void>;
|
|
79
|
+
done: () => void;
|
|
80
|
+
back: () => void;
|
|
81
|
+
}): ReactElement;
|
|
82
|
+
/**
|
|
83
|
+
* The /help overlay: one scrolling card with the keyboard map, the TUI-local
|
|
84
|
+
* commands, the live registry commands, and the user-invocable skills — the
|
|
85
|
+
* real command surface, replacing the one-line notice.
|
|
86
|
+
*/
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @module @deepseek-ai/dsh-tui/theme-panel
|
|
8
8
|
*/
|
|
9
9
|
import { type ReactElement } from 'react';
|
|
10
|
-
import { type ThemeName } from '
|
|
10
|
+
import { type ThemeName } from '../theme.ts';
|
|
11
11
|
/**
|
|
12
12
|
* The /theme list: one row per theme, the current one marked with ●, the
|
|
13
13
|
* focused one with ›. Enter applies the focused theme (the runner persists
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* here.
|
|
10
10
|
*/
|
|
11
11
|
import { type ReactElement } from 'react';
|
|
12
|
-
import type { LauncherUpdatePlan, LauncherUpdateStatus } from '
|
|
12
|
+
import type { LauncherUpdatePlan, LauncherUpdateStatus } from '../update.ts';
|
|
13
13
|
/** Retained apply-progress lines (ring tail; npm output is ephemeral). */
|
|
14
14
|
export declare const UPDATE_OUTPUT_CAP = 800;
|
|
15
15
|
/** Keep the newest UPDATE_OUTPUT_CAP lines of streamed update output. */
|
|
@@ -197,6 +197,17 @@ export declare function loadProviderSettings(ctx: Context): Promise<ProviderSett
|
|
|
197
197
|
export declare function saveProviderCredential(ctx: Context, target: ProviderTargetView, rawKey: string): Promise<void>;
|
|
198
198
|
/** Save the endpoint and an explicit model allow-list without rebuilding the profile. */
|
|
199
199
|
export declare function saveProviderConfiguration(ctx: Context, target: ProviderTargetView, configuration: ProviderConfiguration): Promise<void>;
|
|
200
|
+
/**
|
|
201
|
+
* Switch one provider route to its subscription (plan sign-in) channel: the
|
|
202
|
+
* profile keeps neither a key reference nor an explicit model list, so the
|
|
203
|
+
* official catalog endpoint serves requests and the stored OAuth record — not
|
|
204
|
+
* a settings-named key override — authenticates them. Enabling a route that
|
|
205
|
+
* has no profile yet creates the empty profile that registers it.
|
|
206
|
+
* @param ctx - context carrying the `settings` service.
|
|
207
|
+
* @param target - provider row whose settings namespace owns the profile.
|
|
208
|
+
* @throws when the route is unmanaged or settings are read-only.
|
|
209
|
+
*/
|
|
210
|
+
export declare function enableProviderSubscription(ctx: Context, target: ProviderTargetView): Promise<void>;
|
|
200
211
|
/**
|
|
201
212
|
* Interrogate a provider endpoint for the models it really serves, through
|
|
202
213
|
* the model-discovery capability the provider's settings namespace
|
|
@@ -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. */
|
|
@@ -48,6 +56,14 @@ export declare function liveRegionBudget(chrome: LiveRegionChrome): number;
|
|
|
48
56
|
* accumulated `<Static>` output on every frame.
|
|
49
57
|
*/
|
|
50
58
|
export declare function panelViewport(columns: number, rows: number): InspectorViewport;
|
|
59
|
+
/**
|
|
60
|
+
* Viewport for an expanded (near-fullscreen) document overlay: the document
|
|
61
|
+
* replaces the transcript area entirely, so the half-screen overlay cap and
|
|
62
|
+
* the inter-section gaps drop away while the bottom live region (composer,
|
|
63
|
+
* status) and the Static-rewrite margin stay reserved. The result stays
|
|
64
|
+
* below terminal height, which is what keeps Ink off its full-rewrite path.
|
|
65
|
+
*/
|
|
66
|
+
export declare function expandedDocumentViewport(columns: number, rows: number): InspectorViewport;
|
|
51
67
|
/** Backward-compatible name for the Ctrl+O-specific caller and tests. */
|
|
52
68
|
export declare function inspectorViewport(columns: number, rows: number): InspectorViewport;
|
|
53
69
|
/** Clamp a first-visible row to the range representable by one viewport. */
|
|
@@ -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;
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
*
|
|
12
12
|
* @module @deepseek-ai/dsh-code/render/text
|
|
13
13
|
*/
|
|
14
|
+
import { stringWidth } from './width.ts';
|
|
15
|
+
export { stringWidth };
|
|
14
16
|
/**
|
|
15
17
|
* Compact token count: exact below 1K, then one-decimal-ish K/M.
|
|
16
18
|
* @param n - token count.
|
|
@@ -35,6 +37,8 @@ export declare function singleLineText(text: string): string;
|
|
|
35
37
|
* combining sequences never split mid-cluster.
|
|
36
38
|
*/
|
|
37
39
|
export declare function truncateColumns(text: string, columns: number): string;
|
|
40
|
+
/** Sanitize, clip, and right-pad one cell to an exact terminal-column width. */
|
|
41
|
+
export declare function padColumns(text: string, columns: number): string;
|
|
38
42
|
/** A display-safe suffix bounded by terminal rows and columns. */
|
|
39
43
|
export interface DisplayTail {
|
|
40
44
|
/** Sanitized suffix suitable for direct terminal rendering. */
|
|
@@ -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;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load-time DeepSeek Harness version gate.
|
|
3
|
+
*
|
|
4
|
+
* The terminal driver is validated against exactly one Harness snapshot, and
|
|
5
|
+
* the host resolves every bare `@deepseek-ai/*` import the plugin makes
|
|
6
|
+
* against ITS OWN installed copies (the profile's `HostResolvedRootInclude`
|
|
7
|
+
* redirects bare names to the installed-host base). No install-time or
|
|
8
|
+
* load-time check exists anywhere on that path, so a user who updates `dsh`
|
|
9
|
+
* would otherwise run this build against unvetted upstream code silently.
|
|
10
|
+
*
|
|
11
|
+
* This gate mirrors how the host itself reads its identity: the running CLI
|
|
12
|
+
* entry (`process.argv[1]`) sits inside the `@deepseek-ai/dsh` package, whose
|
|
13
|
+
* manifest version is released in lockstep with the Harness packages bundled
|
|
14
|
+
* beside it. When the probe can identify the host it compares the running
|
|
15
|
+
* versions against the one this build declares and fails fast with an
|
|
16
|
+
* actionable message; when it cannot identify the host it stays silent rather
|
|
17
|
+
* than brick a supported embedding on a false positive.
|
|
18
|
+
*
|
|
19
|
+
* @module @deepseek-ai/dsh-code/runner/harness-gate
|
|
20
|
+
*/
|
|
21
|
+
/** The one Harness release this build was validated against. */
|
|
22
|
+
export declare const EXPECTED_HARNESS_VERSION = "0.1.5-rc.2";
|
|
23
|
+
/** Host packages whose bundled copy the plugin binds to at runtime. */
|
|
24
|
+
export declare const HARNESS_GATE_PACKAGES: readonly ["@deepseek-ai/dsh-agent", "@deepseek-ai/dsh-session"];
|
|
25
|
+
/** Filesystem slice the probe needs; injectable so tests stay pure. */
|
|
26
|
+
export interface HarnessFs {
|
|
27
|
+
/** Resolve a symlinked entry to its real path. */
|
|
28
|
+
realpathSync(path: string): string;
|
|
29
|
+
/** Read and parse one package.json; undefined when absent or unreadable. */
|
|
30
|
+
readManifest(path: string): {
|
|
31
|
+
name?: unknown;
|
|
32
|
+
version?: unknown;
|
|
33
|
+
} | undefined;
|
|
34
|
+
}
|
|
35
|
+
/** What the probe learned about the running host. */
|
|
36
|
+
export interface HarnessProbe {
|
|
37
|
+
/** Installed-host package root, when identified. */
|
|
38
|
+
readonly hostRoot?: string;
|
|
39
|
+
/** Installed-host CLI version (`@deepseek-ai/dsh`). */
|
|
40
|
+
readonly hostVersion?: string;
|
|
41
|
+
/** Version of each gate package bundled beside the host, when present. */
|
|
42
|
+
readonly packages: Readonly<Record<string, string | undefined>>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Identify the running host and the Harness versions it provides.
|
|
46
|
+
* @param argv1 - `process.argv[1]`, the running CLI entry path.
|
|
47
|
+
* @param fs - filesystem slice; defaults to the real one.
|
|
48
|
+
* @returns the probe result; `packages` is empty when the host is unknown.
|
|
49
|
+
*/
|
|
50
|
+
export declare function probeRunningHarness(argv1: string | undefined, fs?: HarnessFs): HarnessProbe;
|
|
51
|
+
/** One host fact that disagrees with the version this build declares. */
|
|
52
|
+
export interface HarnessMismatch {
|
|
53
|
+
/** What was compared: the host CLI or one bundled package. */
|
|
54
|
+
readonly source: string;
|
|
55
|
+
/** The version this build was validated against. */
|
|
56
|
+
readonly expected: string;
|
|
57
|
+
/** The version the running host actually provides. */
|
|
58
|
+
readonly provided: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Compare one probe against the expected snapshot. Unknown facts never
|
|
62
|
+
* mismatch: the gate must stay silent when it cannot judge, not brick a
|
|
63
|
+
* supported embedding on missing evidence.
|
|
64
|
+
* @param expected - the Harness version this build declares.
|
|
65
|
+
* @param probe - the running host's identified versions.
|
|
66
|
+
* @returns every concrete disagreement, empty when compatible or unknown.
|
|
67
|
+
*/
|
|
68
|
+
export declare function harnessVersionMismatches(expected: string, probe: HarnessProbe): readonly HarnessMismatch[];
|
|
69
|
+
/**
|
|
70
|
+
* Render the gate failure the user sees on stderr.
|
|
71
|
+
* @param expected - the Harness version this build declares.
|
|
72
|
+
* @param mismatches - the disagreements to report.
|
|
73
|
+
* @param hostRoot - installed-host root, when identified, for the fix hint.
|
|
74
|
+
* @returns the multi-line diagnostic.
|
|
75
|
+
*/
|
|
76
|
+
export declare function harnessGateMessage(expected: string, mismatches: readonly HarnessMismatch[], hostRoot?: string): string;
|
|
77
|
+
/**
|
|
78
|
+
* Refuse to run against an identified-but-incompatible host.
|
|
79
|
+
* @param expected - the Harness version this build declares.
|
|
80
|
+
* @param probe - the running host's identified versions.
|
|
81
|
+
* @throws an Error carrying the gate diagnostic when a version disagrees.
|
|
82
|
+
*/
|
|
83
|
+
export declare function requireHarnessVersion(expected: string, probe: HarnessProbe): void;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Global input recall: the appended prompts and their durable JSONL file.
|
|
2
|
+
*
|
|
3
|
+
* One JSONL file under the DSH home. A missing file means an empty history and
|
|
4
|
+
* unreadable or corrupt content degrades to the valid lines it could parse,
|
|
5
|
+
* silently — recall is a convenience surface, never a gate.
|
|
6
|
+
*
|
|
7
|
+
* @module @deepseek-ai/dsh-code/input-history
|
|
8
|
+
*/
|
|
9
|
+
/** Live recall state plus its serialized durable writes. */
|
|
10
|
+
export interface InputHistoryStore {
|
|
11
|
+
/** The recall list, newest last; read live by the composer. */
|
|
12
|
+
readonly entries: () => readonly string[];
|
|
13
|
+
/** Append one submitted line and persist it; '' is ignored. */
|
|
14
|
+
readonly record: (text: string) => void;
|
|
15
|
+
/** Await the pending writes (the quit flush). */
|
|
16
|
+
readonly flush: () => Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Load the recall history and return its live store.
|
|
20
|
+
*
|
|
21
|
+
* Serialized history writes: each submission appends one JSON line at the end
|
|
22
|
+
* of the file, so concurrent terminals add entries after each other instead of
|
|
23
|
+
* overwriting snapshots they read at their own boot. A multi-line draft still
|
|
24
|
+
* occupies one physical line (JSON escapes the newline), and a regular-length
|
|
25
|
+
* line reaches the disk as one positioned write; an oversized paste may
|
|
26
|
+
* interleave mid-line, which the next parse simply drops.
|
|
27
|
+
*
|
|
28
|
+
* @param path - absolute path of the JSONL recall file.
|
|
29
|
+
* @param onFailure - receives the write failure message for a bounded notice.
|
|
30
|
+
*/
|
|
31
|
+
export declare function createInputHistory(path: string, onFailure: (message: string) => void): InputHistoryStore;
|