dsh-ssh-tui 0.7.1 → 0.7.3
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 +92 -8
- package/README.md +64 -8
- package/cordis.patch.yml +15 -0
- package/docs/terminals.md +113 -0
- package/lib/approval-cache.js +12 -9
- package/lib/approval-cache.js.map +1 -1
- package/lib/color-depth.js +10 -4
- package/lib/color-depth.js.map +1 -1
- package/lib/diag.js +76 -17
- package/lib/diag.js.map +1 -1
- package/lib/dialogs.js.map +1 -1
- package/lib/display-sock.js +304 -29
- package/lib/display-sock.js.map +1 -1
- package/lib/doctor.js +71 -37
- package/lib/doctor.js.map +1 -1
- package/lib/dsh-compat.js +206 -88
- package/lib/dsh-compat.js.map +1 -1
- package/lib/footer.js +39 -9
- package/lib/footer.js.map +1 -1
- package/lib/gateway-protocol.js +202 -0
- package/lib/gateway-protocol.js.map +1 -0
- package/lib/i18n/en.js +79 -41
- package/lib/i18n/en.js.map +1 -1
- package/lib/i18n/index.js +13 -7
- package/lib/i18n/index.js.map +1 -1
- package/lib/i18n/zh.js +79 -41
- package/lib/i18n/zh.js.map +1 -1
- package/lib/index.js +132 -31
- package/lib/index.js.map +1 -1
- package/lib/job-label.js +99 -17
- package/lib/job-label.js.map +1 -1
- package/lib/paint.js +5 -2
- package/lib/paint.js.map +1 -1
- package/lib/picker.js +5 -3
- package/lib/picker.js.map +1 -1
- package/lib/plan.js +269 -17
- package/lib/plan.js.map +1 -1
- package/lib/platform.js +373 -0
- package/lib/platform.js.map +1 -0
- package/lib/preset-authoring.js +10 -14
- package/lib/preset-authoring.js.map +1 -1
- package/lib/preset-compat.js +100 -0
- package/lib/preset-compat.js.map +1 -0
- package/lib/preset-picker.js +5 -1
- package/lib/preset-picker.js.map +1 -1
- package/lib/preset-rows.js +83 -13
- package/lib/preset-rows.js.map +1 -1
- package/lib/provider-catalog.js +7 -4
- package/lib/provider-catalog.js.map +1 -1
- package/lib/route-memory.js +11 -4
- package/lib/route-memory.js.map +1 -1
- package/lib/session-index.js +5 -0
- package/lib/session-index.js.map +1 -1
- package/lib/session-list.js +18 -1
- package/lib/session-list.js.map +1 -1
- package/lib/session-lock.js +79 -24
- package/lib/session-lock.js.map +1 -1
- package/lib/session-route.js +334 -0
- package/lib/session-route.js.map +1 -0
- package/lib/settings-routes.js +10 -0
- package/lib/settings-routes.js.map +1 -0
- package/lib/settings-subagent.js +10 -0
- package/lib/settings-subagent.js.map +1 -0
- package/lib/subagent-model.js +84 -6
- package/lib/subagent-model.js.map +1 -1
- package/lib/supergrok-token.js +4 -0
- package/lib/supergrok-token.js.map +1 -1
- package/lib/term-text.js +7 -4
- package/lib/term-text.js.map +1 -1
- package/lib/terminal-caps.js +358 -0
- package/lib/terminal-caps.js.map +1 -0
- package/lib/tool-present.js +46 -14
- package/lib/tool-present.js.map +1 -1
- package/lib/tui.js +1949 -371
- package/lib/tui.js.map +1 -1
- package/lib/types/color-depth.d.ts +3 -3
- package/lib/types/diag.d.ts +18 -1
- package/lib/types/dialogs.d.ts +4 -0
- package/lib/types/display-sock.d.ts +94 -2
- package/lib/types/doctor.d.ts +8 -1
- package/lib/types/dsh-compat.d.ts +141 -44
- package/lib/types/footer.d.ts +21 -5
- package/lib/types/gateway-protocol.d.ts +88 -0
- package/lib/types/i18n/index.d.ts +18 -12
- package/lib/types/index.d.ts +45 -0
- package/lib/types/job-label.d.ts +38 -7
- package/lib/types/picker.d.ts +3 -0
- package/lib/types/plan.d.ts +94 -4
- package/lib/types/platform.d.ts +215 -0
- package/lib/types/preset-authoring.d.ts +8 -14
- package/lib/types/preset-compat.d.ts +58 -0
- package/lib/types/preset-picker.d.ts +1 -1
- package/lib/types/preset-rows.d.ts +51 -9
- package/lib/types/route-memory.d.ts +17 -22
- package/lib/types/session-list.d.ts +5 -0
- package/lib/types/session-lock.d.ts +9 -0
- package/lib/types/session-route.d.ts +191 -0
- package/lib/types/settings-routes.d.ts +16 -0
- package/lib/types/settings-subagent.d.ts +24 -0
- package/lib/types/subagent-model.d.ts +60 -7
- package/lib/types/term-text.d.ts +3 -2
- package/lib/types/terminal-caps.d.ts +105 -0
- package/lib/types/tool-present.d.ts +2 -17
- package/lib/types/transcript-types.d.ts +44 -1
- package/lib/types/tui.d.ts +333 -9
- package/package.json +82 -55
|
@@ -19,6 +19,9 @@
|
|
|
19
19
|
* must never lose the previous content or touch a row the user wrote.
|
|
20
20
|
* @module dsh-ssh-tui/preset-rows
|
|
21
21
|
*/
|
|
22
|
+
import type { SettingsGeneration } from './dsh-compat.js';
|
|
23
|
+
/** Which host line the profile being repaired boots on. */
|
|
24
|
+
export type HostGeneration = SettingsGeneration;
|
|
22
25
|
/** One host row the roster block mounts. */
|
|
23
26
|
export interface RosterRow {
|
|
24
27
|
id: string;
|
|
@@ -27,13 +30,35 @@ export interface RosterRow {
|
|
|
27
30
|
config?: readonly string[];
|
|
28
31
|
}
|
|
29
32
|
/**
|
|
30
|
-
* The rows
|
|
31
|
-
* the TypeScript runtime the PTC preset needs, and the host-owned
|
|
32
|
-
* delegation setting.
|
|
33
|
+
* The rows a 0.1.5 terminal profile has to mount itself: the roster `/mode`
|
|
34
|
+
* lists, the TypeScript runtime the PTC preset needs, and the host-owned
|
|
35
|
+
* subagent delegation setting.
|
|
33
36
|
*/
|
|
34
37
|
export declare const ROSTER_ROWS: readonly RosterRow[];
|
|
38
|
+
/**
|
|
39
|
+
* The rows a 0.1.7 terminal profile mounts for itself.
|
|
40
|
+
*
|
|
41
|
+
* 0.1.7 deleted the roster this plugin used to list and switch: presets became
|
|
42
|
+
* per-session declarations a surface mounts (`@deepseek-ai/dsh-agent-preset`
|
|
43
|
+
* rows over the `agent-preset-registry` service), and `dsh-base` keeps the
|
|
44
|
+
* agent-plane rows enabled for the TUI, which is single-session and composes
|
|
45
|
+
* its agent process-wide. What the base does *not* mount are the three rows the
|
|
46
|
+
* shipped standard preset owns beyond it — the persona prompt, and the
|
|
47
|
+
* `ask_user_question` / `present` tools — so those are what a TUI profile adds.
|
|
48
|
+
* Written verbatim as upstream's own `dsh-web-app/presets/standard.patch.yml`
|
|
49
|
+
* declares them, minus the rows the base already carries.
|
|
50
|
+
*/
|
|
51
|
+
export declare const FORMS_ROWS: readonly RosterRow[];
|
|
52
|
+
/** The rows one host line's profile has to mount. */
|
|
53
|
+
export declare function rosterRows(generation: HostGeneration): readonly RosterRow[];
|
|
54
|
+
/** Every row either line knows about, for name-to-row lookups. */
|
|
55
|
+
export declare const ALL_ROSTER_ROWS: readonly RosterRow[];
|
|
35
56
|
/** The comment header the block introduces itself with, in both writers. */
|
|
36
57
|
export declare const ROSTER_PATCH_HEADER = "# dsh-ssh-tui /mode: the agent-preset roster (standard / minimal / PTC /\n# cordis, plus every preset under $DSH_HOME/.agent-presets) and the two host\n# services the shipped presets need. dsh-base composes no roster in a terminal\n# profile, and a third-party bundle patch may not mount an @deepseek-ai row, so\n# the profile's user layer owns them.\n";
|
|
58
|
+
/** The same header on a host that composes its agent process-wide. */
|
|
59
|
+
export declare const FORMS_PATCH_HEADER = "# dsh-ssh-tui: the agent-plane rows a 0.1.7 terminal profile mounts for itself.\n# That line composes the agent process-wide (presets are a per-session Web\n# feature now), and dsh-base already carries every row the standard preset\n# needs except these three: the persona prompt and the ask_user_question /\n# present tools. The profile's user layer owns them.\n";
|
|
60
|
+
/** The header for one host line. */
|
|
61
|
+
export declare function rosterPatchHeader(generation: HostGeneration): string;
|
|
37
62
|
/** One top-level `- insert:` entry mounting exactly these rows. */
|
|
38
63
|
export declare function rosterInsertEntry(rows: readonly RosterRow[]): string;
|
|
39
64
|
/**
|
|
@@ -42,8 +67,23 @@ export declare function rosterInsertEntry(rows: readonly RosterRow[]): string;
|
|
|
42
67
|
* the same text; a test compares the two so they cannot drift.
|
|
43
68
|
*/
|
|
44
69
|
export declare const ROSTER_PATCH_BLOCK: string;
|
|
70
|
+
/** The 0.1.7 block, the same way. */
|
|
71
|
+
export declare const FORMS_PATCH_BLOCK: string;
|
|
72
|
+
/** The block for one host line. */
|
|
73
|
+
export declare function rosterPatchBlock(generation: HostGeneration): string;
|
|
45
74
|
/** The profile patch file the roster block belongs in. */
|
|
46
75
|
export declare function rosterPatchPath(home: string, profile: string): string;
|
|
76
|
+
/**
|
|
77
|
+
* Whether a profile patch already declares every 0.1.7 agent-plane row.
|
|
78
|
+
*
|
|
79
|
+
* Synchronous on purpose: the footer chip is rendered from the main loop and
|
|
80
|
+
* cannot await a read. The file is small and this runs at startup and after a
|
|
81
|
+
* repair, not per frame.
|
|
82
|
+
* @param home - the harness home carrying `profiles/`.
|
|
83
|
+
* @param profile - the profile to inspect.
|
|
84
|
+
* @returns whether all three rows are declared (or the row is unreachable).
|
|
85
|
+
*/
|
|
86
|
+
export declare function formsRowsDeclared(home: string, profile: string): boolean;
|
|
47
87
|
/** One row a patch file declares, with enough position to point at it. */
|
|
48
88
|
export interface PatchRowRef {
|
|
49
89
|
/** Insert id, or the target of an override/disable entry. */
|
|
@@ -88,7 +128,7 @@ export declare function duplicatePatchRows(rows: readonly PatchRowRef[]): PatchR
|
|
|
88
128
|
/** Whether a patch already declares one roster row, by id or by module name. */
|
|
89
129
|
export declare function patchNamesRow(rows: readonly PatchRowRef[], row: RosterRow): boolean;
|
|
90
130
|
/** The roster rows a patch does not declare yet. */
|
|
91
|
-
export declare function missingRosterRows(rows: readonly PatchRowRef[]): RosterRow[];
|
|
131
|
+
export declare function missingRosterRows(rows: readonly PatchRowRef[], candidates?: readonly RosterRow[]): RosterRow[];
|
|
92
132
|
export interface PatchRepair {
|
|
93
133
|
text: string;
|
|
94
134
|
/** Roster rows this repair adds, by id. */
|
|
@@ -108,10 +148,11 @@ export interface PatchRepair {
|
|
|
108
148
|
* (the profile template) is replaced; anything else keeps its content and gains
|
|
109
149
|
* a new `- insert:` entry after a blank line.
|
|
110
150
|
* @param existing - the patch file's current text.
|
|
111
|
-
* @param missing - the roster rows to mount; defaults to
|
|
151
|
+
* @param missing - the roster rows to mount; defaults to the 0.1.5 set.
|
|
152
|
+
* @param generation - which host line the profile boots on.
|
|
112
153
|
* @returns the new text, or `undefined` when nothing has to change.
|
|
113
154
|
*/
|
|
114
|
-
export declare function planRosterRepair(existing: string, missing?: readonly RosterRow[]): PatchRepair | undefined;
|
|
155
|
+
export declare function planRosterRepair(existing: string, missing?: readonly RosterRow[], generation?: HostGeneration): PatchRepair | undefined;
|
|
115
156
|
/**
|
|
116
157
|
* The patch text with every repeated insert removed, or `undefined` when the
|
|
117
158
|
* file has no duplicate.
|
|
@@ -132,10 +173,11 @@ export declare function planDuplicateRepair(existing: string): PatchRepair | und
|
|
|
132
173
|
* half-written patch would only be seen by the next launch.
|
|
133
174
|
* @param home - the harness home carrying `profiles/`.
|
|
134
175
|
* @param profile - the profile to patch.
|
|
135
|
-
* @param missing - the rows to mount; defaults to the
|
|
176
|
+
* @param missing - the rows to mount; defaults to the 0.1.5 set.
|
|
177
|
+
* @param generation - which host line the profile boots on.
|
|
136
178
|
* @returns `present` when the row already exists, else `written`.
|
|
137
179
|
*/
|
|
138
|
-
export declare function ensureRosterRows(home: string, profile: string, missing?: readonly RosterRow[]): Promise<'present' | 'written'>;
|
|
180
|
+
export declare function ensureRosterRows(home: string, profile: string, missing?: readonly RosterRow[], generation?: HostGeneration): Promise<'present' | 'written'>;
|
|
139
181
|
/**
|
|
140
182
|
* Write a repaired patch next to a copy of the previous content.
|
|
141
183
|
*
|
|
@@ -148,4 +190,4 @@ export declare function ensureRosterRows(home: string, profile: string, missing?
|
|
|
148
190
|
*/
|
|
149
191
|
export declare function writePatchWithBackup(path: string, text: string, stamp?: string): Promise<string | undefined>;
|
|
150
192
|
/** The patch text the roster block would produce on its own, for callers that report it. */
|
|
151
|
-
export declare function rosterPatchText(existing: string): string | undefined;
|
|
193
|
+
export declare function rosterPatchText(existing: string, generation?: HostGeneration): string | undefined;
|
|
@@ -5,28 +5,23 @@
|
|
|
5
5
|
import z from '@deepseek-ai/schemastery';
|
|
6
6
|
import type { Context } from '@deepseek-ai/cordis';
|
|
7
7
|
export declare const ROUTE_MEMORY_NAMESPACE: import("@deepseek-ai/dsh-settings").SettingsNamespace;
|
|
8
|
-
/**
|
|
9
|
-
export
|
|
10
|
-
providers:
|
|
11
|
-
model
|
|
12
|
-
reasoningEffort
|
|
13
|
-
updatedAt
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
model: z<string, string>;
|
|
26
|
-
reasoningEffort: z<string, string>;
|
|
27
|
-
updatedAt: z<number, number>;
|
|
28
|
-
}>, string>>;
|
|
29
|
-
}>>;
|
|
8
|
+
/** The shape `ssh-tui-routes` takes in `$DSH_HOME/settings.yaml`. */
|
|
9
|
+
export interface RouteMemorySettings {
|
|
10
|
+
providers: Record<string, {
|
|
11
|
+
model: string;
|
|
12
|
+
reasoningEffort: string;
|
|
13
|
+
updatedAt: number;
|
|
14
|
+
}>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Settings schema for `$DSH_HOME/settings.yaml` under ssh-tui-routes.
|
|
18
|
+
*
|
|
19
|
+
* The type argument is spelled out rather than inferred: `schemastery`'s
|
|
20
|
+
* builder names its own package internally, so an inferred schema makes `tsc`
|
|
21
|
+
* emit a declaration that references a path inside `node_modules` and fails
|
|
22
|
+
* with TS2742 on any layout that does not match this machine's.
|
|
23
|
+
*/
|
|
24
|
+
export declare const ROUTE_MEMORY_SCHEMA: z<RouteMemorySettings>;
|
|
30
25
|
export interface RememberedRoute {
|
|
31
26
|
model: string;
|
|
32
27
|
reasoningEffort?: string;
|
|
@@ -10,10 +10,15 @@ export declare function formatFooterCwd(cwd: string): string;
|
|
|
10
10
|
/**
|
|
11
11
|
* Switch the process into a persisted session working directory. Returns the
|
|
12
12
|
* directory actually used; missing/invalid paths stay put and are reported.
|
|
13
|
+
*
|
|
14
|
+
* The target must be an absolute directory. A regular file that happens to
|
|
15
|
+
* exist at the recorded path used to pass `existsSync` and then fail inside
|
|
16
|
+
* `chdir` with a platform errno; resume now refuses it before moving.
|
|
13
17
|
*/
|
|
14
18
|
export declare function enterSessionCwd(cwd: string | undefined, options?: {
|
|
15
19
|
current?: string;
|
|
16
20
|
exists?: (path: string) => boolean;
|
|
21
|
+
isDirectory?: (path: string) => boolean;
|
|
17
22
|
chdir?: (path: string) => void;
|
|
18
23
|
}): {
|
|
19
24
|
cwd: string;
|
|
@@ -21,6 +21,15 @@ export declare class SessionLockHeldError extends Error {
|
|
|
21
21
|
constructor(lock: SessionLockInfo, path: string);
|
|
22
22
|
}
|
|
23
23
|
export declare function sessionLockPath(sessionId: string, dshHome?: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Pre-digest lock path (`tui-locks/<safeId>.json`).
|
|
26
|
+
*
|
|
27
|
+
* 0.7.1 Hosts still write here. Lookup must find that file; a new Host must
|
|
28
|
+
* not bind a second lock beside a live one just because the filename changed.
|
|
29
|
+
*/
|
|
30
|
+
export declare function legacySessionLockPath(sessionId: string, dshHome?: string): string;
|
|
31
|
+
/** Digested lock first, then the 0.7.1 name when it is different. */
|
|
32
|
+
export declare function sessionLockLookupPaths(sessionId: string, dshHome?: string): string[];
|
|
24
33
|
export declare function parseSessionLock(raw: string): SessionLockInfo | undefined;
|
|
25
34
|
/** True when `pid` still exists on this machine (best-effort). */
|
|
26
35
|
export declare function processIsAlive(pid: number): boolean;
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-session provider/model memory.
|
|
3
|
+
*
|
|
4
|
+
* The parent route and the subagent route used to be one global choice: `/model`
|
|
5
|
+
* and `/submodel` wrote a default that every later session inherited. Once a
|
|
6
|
+
* child could run on a *different* supplier that stopped being enough — resuming
|
|
7
|
+
* an old conversation silently re-ran it on whatever the last conversation used,
|
|
8
|
+
* and there was no way to see which supplier had paid for the earlier one.
|
|
9
|
+
*
|
|
10
|
+
* Each session's effective route is recorded here, next to the TUI's other
|
|
11
|
+
* per-session state under `$DSH_HOME`, and applied when that session starts
|
|
12
|
+
* again. A new session still starts from the global default; the record only
|
|
13
|
+
* ever overrides it for the session it belongs to, and never for another one.
|
|
14
|
+
*
|
|
15
|
+
* The record is a cache of a decision, not a source of truth: every field is
|
|
16
|
+
* parsed defensively, and a route whose provider no longer exists is still
|
|
17
|
+
* applied (the launcher reports the failure the same way it would for a CLI
|
|
18
|
+
* flag).
|
|
19
|
+
*
|
|
20
|
+
* @module dsh-ssh-tui/session-route
|
|
21
|
+
*/
|
|
22
|
+
import { type SubagentSelectionRef } from './subagent-model.js';
|
|
23
|
+
/** Subagent route as this session ran it; no provider means "follows parent". */
|
|
24
|
+
export interface SessionSubagentRoute {
|
|
25
|
+
provider?: string;
|
|
26
|
+
model: string;
|
|
27
|
+
reasoningEffort?: string;
|
|
28
|
+
}
|
|
29
|
+
/** One session's route: what `/model`, `/provider`, `/submodel` settled on. */
|
|
30
|
+
export interface SessionRoute {
|
|
31
|
+
provider: string;
|
|
32
|
+
model: string;
|
|
33
|
+
reasoningEffort?: string;
|
|
34
|
+
subagent?: SessionSubagentRoute;
|
|
35
|
+
/** Epoch ms of the last write; the oldest records are pruned first. */
|
|
36
|
+
updatedAt: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* How many sessions keep a record. The file is a convenience cache, and a
|
|
40
|
+
* hundred-odd conversations is more history than a resume picker offers.
|
|
41
|
+
*/
|
|
42
|
+
export declare const SESSION_ROUTE_LIMIT = 200;
|
|
43
|
+
export declare function sessionRoutePath(dshHome?: string): string;
|
|
44
|
+
/** Parse one record; anything that cannot name a route is dropped. */
|
|
45
|
+
export declare function parseSessionRoute(raw: unknown): SessionRoute | undefined;
|
|
46
|
+
/** Parse the whole file; a file from another version reads as empty. */
|
|
47
|
+
export declare function parseSessionRoutes(raw: unknown): Map<string, SessionRoute>;
|
|
48
|
+
export declare function loadSessionRoutes(path?: string): Promise<Map<string, SessionRoute>>;
|
|
49
|
+
/** The record for one session, or undefined when it never had one. */
|
|
50
|
+
export declare function loadSessionRoute(sessionId: string, path?: string): Promise<SessionRoute | undefined>;
|
|
51
|
+
/** Keep the newest `limit` records, so the file cannot grow without bound. */
|
|
52
|
+
export declare function pruneSessionRoutes(entries: ReadonlyMap<string, SessionRoute>, limit?: number): Map<string, SessionRoute>;
|
|
53
|
+
export declare function saveSessionRoutes(path: string, entries: ReadonlyMap<string, SessionRoute>): Promise<boolean>;
|
|
54
|
+
/**
|
|
55
|
+
* Record one session's route, leaving every other session alone.
|
|
56
|
+
*
|
|
57
|
+
* Read-modify-write on purpose: two Hosts (two SSH windows) can be open at
|
|
58
|
+
* once, and neither may drop the other's entry.
|
|
59
|
+
*/
|
|
60
|
+
export declare function saveSessionRoute(sessionId: string, route: Omit<SessionRoute, 'updatedAt'>, path?: string): Promise<boolean>;
|
|
61
|
+
/** Whether two records describe the same route (the timestamp is ignored). */
|
|
62
|
+
export declare function sameSessionRoute(left: SessionRoute | undefined, right: Omit<SessionRoute, 'updatedAt'> | undefined): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Shape a live parent route plus the subagent selection into a record.
|
|
65
|
+
*
|
|
66
|
+
* Shared by the TUI (which reports what its refs hold) and the launcher (which
|
|
67
|
+
* writes it), so the two cannot disagree about what a session was running on.
|
|
68
|
+
* An empty provider or model yields nothing: a record that cannot name a route
|
|
69
|
+
* would come back as a lie.
|
|
70
|
+
*/
|
|
71
|
+
export declare function sessionRouteInput(input: {
|
|
72
|
+
provider: string;
|
|
73
|
+
model: string;
|
|
74
|
+
reasoningEffort?: string;
|
|
75
|
+
subagent?: {
|
|
76
|
+
provider?: string;
|
|
77
|
+
model: string;
|
|
78
|
+
reasoningEffort?: string;
|
|
79
|
+
};
|
|
80
|
+
}): Omit<SessionRoute, 'updatedAt'> | undefined;
|
|
81
|
+
/**
|
|
82
|
+
* Providers the harness ships with. They are routable in any install even when
|
|
83
|
+
* the adapter list is still warming up, so a record naming one is never treated
|
|
84
|
+
* as stale on that basis alone.
|
|
85
|
+
*/
|
|
86
|
+
export declare const BUILTIN_ROUTABLE_PROVIDERS: readonly ["deepseek-official", "xai", "opencode-go", "opencode"];
|
|
87
|
+
/**
|
|
88
|
+
* Whether this install can still route to a provider.
|
|
89
|
+
*
|
|
90
|
+
* Deliberately permissive: the cost of wrongly *keeping* a record is an error the
|
|
91
|
+
* harness already reports clearly (an unknown route, the same one a launch flag
|
|
92
|
+
* would hit), while wrongly *dropping* one silently loses the session's route —
|
|
93
|
+
* which is the whole feature. So a provider counts as routable when it is a
|
|
94
|
+
* built-in, appears in the adapter list, has a configured `llm-pi-ai` profile, or
|
|
95
|
+
* is listed by the adapter's own model catalog.
|
|
96
|
+
*/
|
|
97
|
+
export declare function providerIsRoutable(input: {
|
|
98
|
+
provider: string;
|
|
99
|
+
/** Ids from `llm.listProviders()`. */
|
|
100
|
+
listed?: readonly string[];
|
|
101
|
+
/** Ids with an `llm-pi-ai.providers.<id>` section. */
|
|
102
|
+
configured?: readonly string[];
|
|
103
|
+
}): boolean;
|
|
104
|
+
/** What a resumed session's record is worth in this install. */
|
|
105
|
+
export interface RouteAvailabilityPlan {
|
|
106
|
+
/** The parent route, when the provider it names can still be routed to. */
|
|
107
|
+
route?: SessionRoute;
|
|
108
|
+
/** The subagent route, when its own pin can be routed to as well. */
|
|
109
|
+
subagent?: SessionSubagentRoute;
|
|
110
|
+
/** Recorded parent provider that is gone; the caller says so on screen. */
|
|
111
|
+
droppedProvider?: string;
|
|
112
|
+
/** Recorded subagent pin that is gone; the app-level setting takes over. */
|
|
113
|
+
droppedSubagentProvider?: string;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Decide what of a recorded route still applies.
|
|
117
|
+
*
|
|
118
|
+
* A provider that no longer exists takes its whole record with it: the session
|
|
119
|
+
* was configured around that supplier (its model, its effort, and the children
|
|
120
|
+
* it pinned), so the honest answer is the app-level default for all of it rather
|
|
121
|
+
* than a half-restored route. A pinned *child* provider that is gone is narrower:
|
|
122
|
+
* the parent route is kept and the children fall back to the app-level subagent
|
|
123
|
+
* setting. An inherited child route has no pin to check — it follows the parent,
|
|
124
|
+
* which was just found routable.
|
|
125
|
+
*/
|
|
126
|
+
export declare function routeAvailabilityPlan(input: {
|
|
127
|
+
recorded?: SessionRoute;
|
|
128
|
+
routable: (provider: string) => boolean;
|
|
129
|
+
}): RouteAvailabilityPlan;
|
|
130
|
+
/**
|
|
131
|
+
* Apply a resumed session's record to the live selection.
|
|
132
|
+
*
|
|
133
|
+
* Returns what the record was worth (see `routeAvailabilityPlan`) so the
|
|
134
|
+
* launcher can say which route the session came back on — and, when a supplier
|
|
135
|
+
* has been removed since, which one it fell back from. A new session is left
|
|
136
|
+
* alone, and so is a resumed one that never had a record: both start from the
|
|
137
|
+
* app-level defaults, which is the behaviour before any of this existed.
|
|
138
|
+
*
|
|
139
|
+
* The subagent route is applied in memory only: it belongs to the conversation
|
|
140
|
+
* being resumed, and writing it back to the settings would make one session's
|
|
141
|
+
* pin the default for every later session.
|
|
142
|
+
*/
|
|
143
|
+
export declare function restoreSessionRoute(input: {
|
|
144
|
+
sessionId: string;
|
|
145
|
+
resume: boolean;
|
|
146
|
+
subagentSelection: SubagentSelectionRef;
|
|
147
|
+
path?: string;
|
|
148
|
+
/** Availability test; omitted means "everything is routable". */
|
|
149
|
+
routable?: (provider: string) => boolean;
|
|
150
|
+
}): Promise<RouteAvailabilityPlan>;
|
|
151
|
+
/** One remembered route as the launch waterfall sees it. */
|
|
152
|
+
export interface LaunchRouteSource {
|
|
153
|
+
provider: string;
|
|
154
|
+
model: string;
|
|
155
|
+
reasoningEffort?: string;
|
|
156
|
+
}
|
|
157
|
+
export interface LaunchRouteInput {
|
|
158
|
+
/** In-process change from `/model` or `/setup` earlier in this process. */
|
|
159
|
+
live?: LaunchRouteSource;
|
|
160
|
+
/** Launch flags (`--provider` / `--model`). */
|
|
161
|
+
cli?: {
|
|
162
|
+
provider?: string;
|
|
163
|
+
model?: string;
|
|
164
|
+
};
|
|
165
|
+
/** This session's own record, when the launch resumes it. */
|
|
166
|
+
session?: SessionRoute;
|
|
167
|
+
/** Global default (the settings file, or `agent-default-model`). */
|
|
168
|
+
saved?: LaunchRouteSource;
|
|
169
|
+
/** Last model per provider, used only when no user default section exists. */
|
|
170
|
+
remembered?: LaunchRouteSource;
|
|
171
|
+
}
|
|
172
|
+
export interface LaunchRoute {
|
|
173
|
+
provider: string;
|
|
174
|
+
model: string;
|
|
175
|
+
reasoningEffort?: string;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* The route a launch should run on, in one place.
|
|
179
|
+
*
|
|
180
|
+
* Precedence: an in-process change, then launch flags, then the session's own
|
|
181
|
+
* record, then the global default, then the last remembered route. A resumed
|
|
182
|
+
* conversation therefore comes back on the supplier it was actually using, while
|
|
183
|
+
* a new one still starts from the default — and an explicit flag still wins,
|
|
184
|
+
* because that is this launch's ask.
|
|
185
|
+
*
|
|
186
|
+
* The reasoning effort travels with the route it was chosen for: it is taken
|
|
187
|
+
* from whichever source supplied the provider/model, and only when the flags did
|
|
188
|
+
* not move the route away from it. A CLI that changes either half must not
|
|
189
|
+
* inherit the saved effort of a different model.
|
|
190
|
+
*/
|
|
191
|
+
export declare function resolveLaunchRoute(input: LaunchRouteInput): LaunchRoute;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loader row that carries the `/model` route memory as a settings form.
|
|
3
|
+
*
|
|
4
|
+
* On the 0.1.5 line `route-memory.ts` registers this namespace itself through
|
|
5
|
+
* `installSettingsSection`; from 0.1.7 a settings form is projected out of a
|
|
6
|
+
* loader entry's own `Config` schema, so the same schema is mounted as a row.
|
|
7
|
+
* The row id (`ssh-tui-routes`, see `cordis.patch.yml`) is the namespace every
|
|
8
|
+
* read goes through, and it is also the id the host's legacy `settings.yaml`
|
|
9
|
+
* import lands on, so an existing `ssh-tui-routes` section keeps its routes.
|
|
10
|
+
*/
|
|
11
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
12
|
+
export declare const name = "ssh-tui-settings-routes";
|
|
13
|
+
/** The route-memory section, as the 0.1.7 settings service wants to see it. */
|
|
14
|
+
export declare const Config: import("@deepseek-ai/schemastery").default<import("./route-memory.js").RouteMemorySettings>;
|
|
15
|
+
/** Nothing to mount: the TUI owns every read and write of this section. */
|
|
16
|
+
export declare function apply(_ctx: Context): void;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loader row that carries the subagent model selection as a settings form.
|
|
3
|
+
*
|
|
4
|
+
* On the 0.1.5 line `subagent-model.ts` registers this namespace itself through
|
|
5
|
+
* `installSettingsSection`; from 0.1.7 a settings form is projected out of a
|
|
6
|
+
* loader entry's own `Config` schema, so the same schema is mounted as a row.
|
|
7
|
+
* The row id (`ssh-tui-subagent`, see `cordis.patch.yml`) is the namespace
|
|
8
|
+
* every read and write goes through, and the id the host's legacy
|
|
9
|
+
* `settings.yaml` import lands on, so an existing `/submodel` pin survives.
|
|
10
|
+
*/
|
|
11
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
12
|
+
export declare const name = "ssh-tui-settings-subagent";
|
|
13
|
+
/** The subagent selection, as the 0.1.7 settings service wants to see it. */
|
|
14
|
+
export declare const Config: import("@deepseek-ai/schemastery").default<Schemastery.ObjectS<{
|
|
15
|
+
provider: import("@deepseek-ai/schemastery").default<string>;
|
|
16
|
+
model: import("@deepseek-ai/schemastery").default<string>;
|
|
17
|
+
reasoningEffort: import("@deepseek-ai/schemastery").default<string>;
|
|
18
|
+
}>, Schemastery.ObjectT<{
|
|
19
|
+
provider: import("@deepseek-ai/schemastery").default<string>;
|
|
20
|
+
model: import("@deepseek-ai/schemastery").default<string>;
|
|
21
|
+
reasoningEffort: import("@deepseek-ai/schemastery").default<string>;
|
|
22
|
+
}>>;
|
|
23
|
+
/** Nothing to mount: the TUI owns every read and write of this section. */
|
|
24
|
+
export declare function apply(_ctx: Context): void;
|
|
@@ -24,6 +24,33 @@ export declare const DEFAULT_XAI_SUBAGENT_MODEL = "grok-4.5";
|
|
|
24
24
|
* with flash-like ids ranked first.
|
|
25
25
|
*/
|
|
26
26
|
export declare function defaultSubagentModelForProvider(provider: string, listed?: readonly string[], parentModel?: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Canonical id of the supplier behind a route.
|
|
29
|
+
*
|
|
30
|
+
* The settings file can name the same supplier two ways — `xai` against
|
|
31
|
+
* `grok`, `deepseek-official` against `deepseek` — and a `/submodel` pin that
|
|
32
|
+
* spells the parent's own provider differently is still the parent's provider.
|
|
33
|
+
* Only those aliases collapse: an id the TUI cannot vouch for (`deepseek-eu`,
|
|
34
|
+
* `grok-mirror`, a relay) stays itself, because two routes it cannot prove
|
|
35
|
+
* share a bill are two providers.
|
|
36
|
+
*/
|
|
37
|
+
export declare function canonicalProviderId(provider: string | undefined): string;
|
|
38
|
+
/**
|
|
39
|
+
* True when `child` is a different supplier from `parent`.
|
|
40
|
+
*
|
|
41
|
+
* This is the one condition that earns a subagent an accent colour: a child
|
|
42
|
+
* that follows the parent — or that was pinned back onto the parent's own
|
|
43
|
+
* provider — is on the parent's route and must read as such.
|
|
44
|
+
*/
|
|
45
|
+
export declare function subagentProviderDiffers(parent: string | undefined, child: string | undefined): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Identity SGR for a subagent chip title. Same provider as the parent stays
|
|
48
|
+
* the violet used since the courtesy-name work; a different provider uses
|
|
49
|
+
* cyan so the foreign route is visible without a second color layer.
|
|
50
|
+
*/
|
|
51
|
+
export declare const SUBAGENT_IDENTITY_SGR = "38;5;141";
|
|
52
|
+
export declare const SUBAGENT_FOREIGN_SGR = "38;5;80";
|
|
53
|
+
export declare function subagentIdentitySgr(foreign: boolean): typeof SUBAGENT_IDENTITY_SGR | typeof SUBAGENT_FOREIGN_SGR;
|
|
27
54
|
/**
|
|
28
55
|
* True when the stored subagent model still belongs to the parent provider
|
|
29
56
|
* family. An explicit leftover DeepSeek flash id after switching to xAI is
|
|
@@ -75,16 +102,42 @@ export interface SubagentSelection {
|
|
|
75
102
|
/** Mutable selection handle shared by the settings watcher and the TUI. */
|
|
76
103
|
export interface SubagentSelectionRef {
|
|
77
104
|
current: SubagentSelection;
|
|
105
|
+
/**
|
|
106
|
+
* Where `current` came from.
|
|
107
|
+
*
|
|
108
|
+
* A route restored from a session's own record (`session`) outranks the
|
|
109
|
+
* settings watcher: the host fires `onChange` on writes to *any* section, so a
|
|
110
|
+
* `/model` or a `/doctor --fix` would otherwise put the app-level default back
|
|
111
|
+
* and silently drop the pin the conversation was resumed with. A user change
|
|
112
|
+
* through `/submodel` hands ownership back to the settings.
|
|
113
|
+
*/
|
|
114
|
+
source?: 'settings' | 'session';
|
|
78
115
|
}
|
|
79
|
-
/**
|
|
116
|
+
/**
|
|
117
|
+
* Adopt a session's own subagent route, outranking the settings watcher.
|
|
118
|
+
* @param ref - the shared selection handle.
|
|
119
|
+
* @param selection - the route the session's record names.
|
|
120
|
+
*/
|
|
121
|
+
export declare function adoptSessionSubagentSelection(ref: SubagentSelectionRef, selection: SubagentSelection): void;
|
|
122
|
+
/**
|
|
123
|
+
* Hand the ref back to the settings watcher.
|
|
124
|
+
*
|
|
125
|
+
* Called when a user change makes the settings the source again, and before a
|
|
126
|
+
* new session starts in this process — a session-scoped route must not leak into
|
|
127
|
+
* the next conversation. Only a readable section may replace the current value:
|
|
128
|
+
* resetting on a settings service that is not up yet would swap the route for
|
|
129
|
+
* the built-in default instead.
|
|
130
|
+
*/
|
|
131
|
+
export declare function releaseSessionSubagentSelection(ref: SubagentSelectionRef, settingsValue: unknown): void;
|
|
132
|
+
/** Settings schema for the subagent selection; every field is form-writable. */
|
|
80
133
|
export declare const SUBAGENT_SETTINGS_SCHEMA: z<Schemastery.ObjectS<{
|
|
81
|
-
provider: z<string
|
|
82
|
-
model: z<string
|
|
83
|
-
reasoningEffort: z<string
|
|
134
|
+
provider: z<string>;
|
|
135
|
+
model: z<string>;
|
|
136
|
+
reasoningEffort: z<string>;
|
|
84
137
|
}>, Schemastery.ObjectT<{
|
|
85
|
-
provider: z<string
|
|
86
|
-
model: z<string
|
|
87
|
-
reasoningEffort: z<string
|
|
138
|
+
provider: z<string>;
|
|
139
|
+
model: z<string>;
|
|
140
|
+
reasoningEffort: z<string>;
|
|
88
141
|
}>>;
|
|
89
142
|
/** Normalize a raw settings section into a live typed selection. */
|
|
90
143
|
export declare function normalizeSubagentSelection(value: unknown): SubagentSelection;
|
package/lib/types/term-text.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Isolated so the launch session picker can clip labels without loading
|
|
5
5
|
* the interactive TUI class.
|
|
6
6
|
*/
|
|
7
|
+
import { type ColorDepth } from './color-depth.js';
|
|
7
8
|
/**
|
|
8
9
|
* Codex-style compact elapsed: `0s`, `1m 05s`, `1h 01m 01s`.
|
|
9
10
|
* Used by the workspace wait card while the model has not streamed yet.
|
|
@@ -116,9 +117,9 @@ export declare function wrapTracked(text: string, width: number): {
|
|
|
116
117
|
end: number;
|
|
117
118
|
}[];
|
|
118
119
|
/** Paint one already-wrapped output line by the segments overlapping its range. */
|
|
119
|
-
export declare function paintSegmentedLine(line: string, start: number, end: number, segments: readonly TextSegment[]): string;
|
|
120
|
+
export declare function paintSegmentedLine(line: string, start: number, end: number, segments: readonly TextSegment[], depth?: ColorDepth): string;
|
|
120
121
|
/** Wrap `text` and color each output line by overlapping `segments`. */
|
|
121
|
-
export declare function wrapSegmented(text: string, width: number, segments: readonly TextSegment[]): string[];
|
|
122
|
+
export declare function wrapSegmented(text: string, width: number, segments: readonly TextSegment[], depth?: ColorDepth): string[];
|
|
122
123
|
export declare function truncate(text: string, maxLines: number): string;
|
|
123
124
|
/** One OSC-8 hyperlink span in a painted row, in display columns. */
|
|
124
125
|
export interface PaintedLinkHit {
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the terminal in front of us can actually do.
|
|
3
|
+
*
|
|
4
|
+
* `color-depth.ts` answers the palette question; this answers the rest of the
|
|
5
|
+
* ones that change what we may safely emit: mouse reporting, bracketed paste,
|
|
6
|
+
* the alternate screen, clipboard writes (OSC 52) and hyperlinks (OSC 8), plus
|
|
7
|
+
* which family of terminal we are talking to.
|
|
8
|
+
*
|
|
9
|
+
* Why it is a module and not a few `if`s: these decisions are made from
|
|
10
|
+
* environment variables that nobody on the team can test by hand for every
|
|
11
|
+
* desktop — GNOME Terminal, XFCE Terminal, Konsole, xterm, tmux, the Linux
|
|
12
|
+
* virtual console, Windows Terminal, a legacy Windows console. So the input is
|
|
13
|
+
* a parameter, the table is data, and `tests/terminal-caps.test.mjs` pins one
|
|
14
|
+
* fixture per family on any platform.
|
|
15
|
+
*
|
|
16
|
+
* The bias is **not** "assume the best". A capability we claim but the terminal
|
|
17
|
+
* lacks costs the user something real: `?1000h` on a console that cannot report
|
|
18
|
+
* SGR coordinates swallows its mouse; OSC 52 where nothing reads it makes
|
|
19
|
+
* `/copy` look like it worked; the alternate screen on a serial console loses
|
|
20
|
+
* the scrollback. Where a terminal is known to be marginal, the answer is no,
|
|
21
|
+
* and `DSH_TUI_TERM_CAPS` is the escape hatch for the user who knows better.
|
|
22
|
+
*
|
|
23
|
+
* @module dsh-ssh-tui/terminal-caps
|
|
24
|
+
*/
|
|
25
|
+
import { type ColorDepth } from './color-depth.js';
|
|
26
|
+
/** Which terminal implementation is on the other end. */
|
|
27
|
+
export type TerminalFamily = 'windows-terminal' | 'windows-console' | 'vte' | 'konsole' | 'xterm' | 'tmux' | 'screen' | 'linux-console' | 'dumb' | 'unknown';
|
|
28
|
+
/** One terminal's answer to every question this TUI asks of it. */
|
|
29
|
+
export interface TerminalCapabilities {
|
|
30
|
+
family: TerminalFamily;
|
|
31
|
+
/** A human name for diagnostics (`/diag`), e.g. `GNOME Terminal (VTE 7000)`. */
|
|
32
|
+
label: string;
|
|
33
|
+
colors: ColorDepth;
|
|
34
|
+
/** Report mouse events at all (`?1000h`). */
|
|
35
|
+
mouse: boolean;
|
|
36
|
+
/** Report them as SGR (`?1006h`) instead of the 32-column X10 encoding. */
|
|
37
|
+
mouseSgr: boolean;
|
|
38
|
+
/** Report motion while a button is held (`?1002h`), which a drag needs. */
|
|
39
|
+
mouseDrag: boolean;
|
|
40
|
+
/** `?2004h`: paste arrives wrapped, so a multi-line paste is one event. */
|
|
41
|
+
bracketedPaste: boolean;
|
|
42
|
+
/** `?1049h`: the TUI gets its own screen and restores the scrollback on exit. */
|
|
43
|
+
alternateScreen: boolean;
|
|
44
|
+
/** OSC 52 clipboard writes reach the user's own machine. */
|
|
45
|
+
osc52: boolean;
|
|
46
|
+
/** OSC 8 hyperlinks are clickable rather than noise. */
|
|
47
|
+
osc8: boolean;
|
|
48
|
+
/** OSC 0/2 window-title updates are honoured. */
|
|
49
|
+
title: boolean;
|
|
50
|
+
/** `DSH_TUI_TERM_CAPS` tokens that were rejected, for `/diag` to report. */
|
|
51
|
+
ignoredOverrides: readonly string[];
|
|
52
|
+
}
|
|
53
|
+
/** Everything the classifier reads. `platform` and `env` are injectable. */
|
|
54
|
+
export interface TerminalProbe {
|
|
55
|
+
env?: NodeJS.ProcessEnv;
|
|
56
|
+
platform?: NodeJS.Platform;
|
|
57
|
+
}
|
|
58
|
+
/** Capability names a user may force on or off through `DSH_TUI_TERM_CAPS`. */
|
|
59
|
+
declare const TOGGLEABLE: readonly ["mouse", "mouseSgr", "mouseDrag", "bracketedPaste", "alternateScreen", "osc52", "osc8", "title"];
|
|
60
|
+
/**
|
|
61
|
+
* Parse `DSH_TUI_TERM_CAPS`.
|
|
62
|
+
*
|
|
63
|
+
* `no-mouse`, `mouse`, `mouse=false` and `mouse = false` all mean what they
|
|
64
|
+
* look like: the `=` binds first, so the spaced spelling cannot silently invert
|
|
65
|
+
* into the opposite answer (it did, and `osc52 = false` then *re-enabled* the
|
|
66
|
+
* clipboard promise). A value outside the two vocabularies, an unknown name or a
|
|
67
|
+
* bare `no-` is rejected rather than guessed, and the rejects are returned so
|
|
68
|
+
* `/diag` can show them — this variable is the only feedback channel a user has
|
|
69
|
+
* when an override does not appear to work.
|
|
70
|
+
*/
|
|
71
|
+
export declare function parseCapsOverrideReport(raw: string): {
|
|
72
|
+
overrides: Partial<Record<(typeof TOGGLEABLE)[number], boolean>>;
|
|
73
|
+
ignored: string[];
|
|
74
|
+
};
|
|
75
|
+
/** The overrides alone, for callers that do not report. */
|
|
76
|
+
export declare function parseCapsOverride(raw: string): Partial<Record<(typeof TOGGLEABLE)[number], boolean>>;
|
|
77
|
+
/**
|
|
78
|
+
* Classify the terminal from the environment.
|
|
79
|
+
*
|
|
80
|
+
* Detection is by the markers terminals actually set: Windows Terminal exports
|
|
81
|
+
* `WT_SESSION`; the VTE family (GNOME Terminal, XFCE Terminal, MATE, Tilix,
|
|
82
|
+
* Terminator, Guake) exports `VTE_VERSION`; Konsole exports `KONSOLE_VERSION`;
|
|
83
|
+
* tmux and screen export `TMUX` / `STY` and set a `tmux*` / `screen*` TERM.
|
|
84
|
+
* Everything else falls back to the TERM name.
|
|
85
|
+
*/
|
|
86
|
+
export declare function detectTerminalFamily(probe?: TerminalProbe): {
|
|
87
|
+
family: TerminalFamily;
|
|
88
|
+
label: string;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Every capability for the terminal in front of us.
|
|
92
|
+
*
|
|
93
|
+
* `DSH_TUI_TERM_CAPS` overrides individual answers (`no-mouse`, `osc52=false`);
|
|
94
|
+
* `DSH_TUI_NO_ALT_SCREEN` and `DSH_TUI_OSC8` keep working because they came
|
|
95
|
+
* first and are documented.
|
|
96
|
+
*/
|
|
97
|
+
export declare function terminalCapabilities(probe?: TerminalProbe): TerminalCapabilities;
|
|
98
|
+
/** Mouse-tracking sequences to enable, in one write. Empty when unsupported. */
|
|
99
|
+
export declare function mouseEnableSequence(caps: TerminalCapabilities): string;
|
|
100
|
+
/** Mouse-tracking sequences to disable. Always safe to emit: `l` on a mode the
|
|
101
|
+
* terminal never enabled is ignored, and leaving a mode on is not. */
|
|
102
|
+
export declare function mouseDisableSequence(): string;
|
|
103
|
+
/** Bracketed-paste enable/disable, or empty when the terminal lacks it. */
|
|
104
|
+
export declare function bracketedPasteSequence(caps: TerminalCapabilities, on: boolean): string;
|
|
105
|
+
export {};
|