@co0ontty/wand 4.38.0 → 4.39.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/dist/build-info.json +3 -3
- package/dist/cli.js +6 -0
- package/dist/process-manager.d.ts +12 -4
- package/dist/process-manager.js +314 -258
- package/dist/server-session-routes.js +9 -9
- package/dist/server.d.ts +2 -0
- package/dist/server.js +10 -6
- package/dist/session-transport.d.ts +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +31 -6
- package/dist/terminal-daemon-client.d.ts +29 -0
- package/dist/terminal-daemon-client.js +406 -0
- package/dist/terminal-daemon-protocol.d.ts +45 -0
- package/dist/terminal-daemon-protocol.js +31 -0
- package/dist/terminal-daemon-server.d.ts +2 -0
- package/dist/terminal-daemon-server.js +349 -0
- package/dist/terminal-host.d.ts +79 -0
- package/dist/terminal-host.js +123 -0
- package/dist/tui/commands.js +220 -33
- package/dist/types.d.ts +4 -0
- package/dist/web-ui/content/scripts.js +65 -65
- package/dist/web-ui/content/styles.css +1 -1
- package/dist/web-ui/embedded-assets.d.ts +1 -1
- package/dist/web-ui/embedded-assets.js +3 -3
- package/package.json +1 -1
|
@@ -367,7 +367,7 @@ function isPtyProviderCommand(provider, command) {
|
|
|
367
367
|
const executable = provider === "qoder" ? "qodercli" : provider;
|
|
368
368
|
return new RegExp(`^${executable}\\b`, "i").test(command.trim());
|
|
369
369
|
}
|
|
370
|
-
function startResumedPtySession(processes, existingSession, sessionId, defaultMode, body, initialInput) {
|
|
370
|
+
async function startResumedPtySession(processes, existingSession, sessionId, defaultMode, body, initialInput) {
|
|
371
371
|
if ((existingSession.sessionKind ?? "pty") !== "pty") {
|
|
372
372
|
throw new Error("结构化会话不支持 PTY resume。");
|
|
373
373
|
}
|
|
@@ -1066,7 +1066,7 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
1066
1066
|
const slice = enrichStructuredMessages(truncateMessagesForTransport(all.slice(offset, end), config.cardDefaults ?? {}));
|
|
1067
1067
|
res.json({ wandProtocolVersion: WAND_PROTOCOL_VERSION, messages: slice, offset, total });
|
|
1068
1068
|
});
|
|
1069
|
-
app.post("/api/sessions/:id/resume", (req, res) => {
|
|
1069
|
+
app.post("/api/sessions/:id/resume", asyncRoute(async (req, res) => {
|
|
1070
1070
|
const sessionId = req.params.id;
|
|
1071
1071
|
const body = req.body;
|
|
1072
1072
|
try {
|
|
@@ -1079,14 +1079,14 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
1079
1079
|
res.status(400).json({ error: "结构化会话不支持 PTY resume。" });
|
|
1080
1080
|
return;
|
|
1081
1081
|
}
|
|
1082
|
-
const newSnapshot = startResumedPtySession(processes, existingSession, sessionId, defaultMode, body);
|
|
1082
|
+
const newSnapshot = await startResumedPtySession(processes, existingSession, sessionId, defaultMode, body);
|
|
1083
1083
|
res.status(201).json(newSnapshot);
|
|
1084
1084
|
}
|
|
1085
1085
|
catch (error) {
|
|
1086
1086
|
res.status(400).json({ error: getErrorMessage(error, "无法恢复会话。") });
|
|
1087
1087
|
}
|
|
1088
|
-
});
|
|
1089
|
-
app.post("/api/claude-sessions/:claudeSessionId/resume", (req, res) => {
|
|
1088
|
+
}));
|
|
1089
|
+
app.post("/api/claude-sessions/:claudeSessionId/resume", asyncRoute(async (req, res) => {
|
|
1090
1090
|
const claudeSessionId = String(req.params.claudeSessionId || "").trim();
|
|
1091
1091
|
const body = req.body;
|
|
1092
1092
|
try {
|
|
@@ -1122,7 +1122,7 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
1122
1122
|
const resumeCommand = `claude --resume ${claudeSessionId}`;
|
|
1123
1123
|
const reqCols = typeof body.cols === "number" && Number.isFinite(body.cols) ? body.cols : undefined;
|
|
1124
1124
|
const reqRows = typeof body.rows === "number" && Number.isFinite(body.rows) ? body.rows : undefined;
|
|
1125
|
-
const newSnapshot = processes.start(resumeCommand, existingSession.cwd, newMode, undefined, {
|
|
1125
|
+
const newSnapshot = await processes.start(resumeCommand, existingSession.cwd, newMode, undefined, {
|
|
1126
1126
|
reuseId: existingSession.id,
|
|
1127
1127
|
cols: reqCols,
|
|
1128
1128
|
rows: reqRows,
|
|
@@ -1140,7 +1140,7 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
1140
1140
|
const resumeCommand = `claude --resume ${claudeSessionId}`;
|
|
1141
1141
|
const reqCols = typeof body.cols === "number" && Number.isFinite(body.cols) ? body.cols : undefined;
|
|
1142
1142
|
const reqRows = typeof body.rows === "number" && Number.isFinite(body.rows) ? body.rows : undefined;
|
|
1143
|
-
const newSnapshot = processes.start(resumeCommand, cwd, newMode, undefined, {
|
|
1143
|
+
const newSnapshot = await processes.start(resumeCommand, cwd, newMode, undefined, {
|
|
1144
1144
|
cols: reqCols,
|
|
1145
1145
|
rows: reqRows,
|
|
1146
1146
|
...(requestedOrigin ?? {}),
|
|
@@ -1151,7 +1151,7 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
1151
1151
|
catch (error) {
|
|
1152
1152
|
res.status(400).json({ error: getErrorMessage(error, "无法按 Claude 会话 ID 恢复会话。") });
|
|
1153
1153
|
}
|
|
1154
|
-
});
|
|
1154
|
+
}));
|
|
1155
1155
|
app.post("/api/sessions/:id/input", asyncRoute(async (req, res) => {
|
|
1156
1156
|
const body = req.body;
|
|
1157
1157
|
const sessionId = req.params.id;
|
|
@@ -1187,7 +1187,7 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
1187
1187
|
const existingSession = processes.get(sessionId) || storage.getSession(sessionId);
|
|
1188
1188
|
const autoResumeInput = getAutoResumeInitialInput(existingSession, input, view, shortcutKey);
|
|
1189
1189
|
if (autoResumeInput !== null && canAutoResumePtyForInput(existingSession, autoResumeInput)) {
|
|
1190
|
-
const snapshot = startResumedPtySession(processes, existingSession, sessionId, defaultMode, {}, autoResumeInput);
|
|
1190
|
+
const snapshot = await startResumedPtySession(processes, existingSession, sessionId, defaultMode, {}, autoResumeInput);
|
|
1191
1191
|
res.json(sessionResponseDTO(snapshot));
|
|
1192
1192
|
return;
|
|
1193
1193
|
}
|
package/dist/server.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { type ModelRefreshOptions } from "./models.js";
|
|
|
3
3
|
import { ProcessManager } from "./process-manager.js";
|
|
4
4
|
import { StructuredSessionManager } from "./structured-session-manager.js";
|
|
5
5
|
import { type PathRepairResult } from "./path-repair.js";
|
|
6
|
+
import type { TerminalHost } from "./terminal-host.js";
|
|
6
7
|
import { WandConfig } from "./types.js";
|
|
7
8
|
export interface ServerUrl {
|
|
8
9
|
url: string;
|
|
@@ -31,4 +32,5 @@ export declare class PortInUseError extends Error {
|
|
|
31
32
|
export declare function isPortInUseError(error: unknown): error is PortInUseError;
|
|
32
33
|
export declare function startServer(config: WandConfig, configPath: string, options?: {
|
|
33
34
|
modelRefreshOptions?: () => Partial<ModelRefreshOptions>;
|
|
35
|
+
terminalHost?: TerminalHost;
|
|
34
36
|
}): Promise<ServerHandle>;
|
package/dist/server.js
CHANGED
|
@@ -45,6 +45,7 @@ import { isLogBusActive, wandTuiLog } from "./tui/log-bus.js";
|
|
|
45
45
|
import { EMBEDDED_WEB_ASSETS } from "./web-ui/embedded-assets.js";
|
|
46
46
|
import { renderApp } from "./web-ui/index.js";
|
|
47
47
|
import { WsBroadcastManager } from "./ws-broadcast.js";
|
|
48
|
+
import { createTerminalHost } from "./terminal-daemon-client.js";
|
|
48
49
|
import { checkRateLimit, recordFailedLogin, resetRateLimit } from "./middleware/rate-limit.js";
|
|
49
50
|
import { updateProviderClis, verifyProviderCliUpdateResults, } from "./provider-cli-updater.js";
|
|
50
51
|
const SERVER_MODULE_DIR = path.dirname(new URL(import.meta.url).pathname);
|
|
@@ -499,7 +500,8 @@ export async function startServer(config, configPath, options = {}) {
|
|
|
499
500
|
config,
|
|
500
501
|
repositoryUrl: PKG_REPO_URL,
|
|
501
502
|
});
|
|
502
|
-
const
|
|
503
|
+
const terminalHost = options.terminalHost ?? await createTerminalHost(configPath);
|
|
504
|
+
const processes = new ProcessManager(config, storage, configDir, terminalHost);
|
|
503
505
|
const structuredLogger = new SessionLogger(configDir, config.shortcutLogMaxBytes);
|
|
504
506
|
const structuredSessions = new StructuredSessionManager(storage, config, structuredLogger);
|
|
505
507
|
const sessionRegistry = new SessionRegistry(processes, structuredSessions, storage);
|
|
@@ -977,7 +979,7 @@ export async function startServer(config, configPath, options = {}) {
|
|
|
977
979
|
}));
|
|
978
980
|
registerFileRoutes(app, { storage, defaultCwd: config.defaultCwd });
|
|
979
981
|
// ── Session control ──
|
|
980
|
-
app.post("/api/commands", (req, res) => {
|
|
982
|
+
app.post("/api/commands", asyncRoute(async (req, res) => {
|
|
981
983
|
const body = req.body;
|
|
982
984
|
const interactiveShell = body.shell === true;
|
|
983
985
|
if (!interactiveShell && !body.command?.trim()) {
|
|
@@ -1016,7 +1018,7 @@ export async function startServer(config, configPath, options = {}) {
|
|
|
1016
1018
|
: undefined;
|
|
1017
1019
|
const reqCols = typeof body.cols === "number" && Number.isFinite(body.cols) ? body.cols : undefined;
|
|
1018
1020
|
const reqRows = typeof body.rows === "number" && Number.isFinite(body.rows) ? body.rows : undefined;
|
|
1019
|
-
const snapshot = interactiveShell
|
|
1021
|
+
const snapshot = await (interactiveShell
|
|
1020
1022
|
? processes.startShell(body.cwd, body.mode ?? "default", {
|
|
1021
1023
|
worktreeEnabled: body.worktreeEnabled === true,
|
|
1022
1024
|
cols: reqCols,
|
|
@@ -1031,14 +1033,14 @@ export async function startServer(config, configPath, options = {}) {
|
|
|
1031
1033
|
rows: reqRows,
|
|
1032
1034
|
thinkingEffort: body.thinkingEffort ?? config.defaultThinkingEffort,
|
|
1033
1035
|
...origin,
|
|
1034
|
-
});
|
|
1036
|
+
}));
|
|
1035
1037
|
recordRecentPath(storage, snapshot.cwd);
|
|
1036
1038
|
res.status(201).json(snapshot);
|
|
1037
1039
|
}
|
|
1038
1040
|
catch (error) {
|
|
1039
1041
|
res.status(400).json({ error: getErrorMessage(error, "无法启动命令。请检查命令是否安装。") });
|
|
1040
1042
|
}
|
|
1041
|
-
});
|
|
1043
|
+
}));
|
|
1042
1044
|
// ── WebSocket broadcast layer ──
|
|
1043
1045
|
let activeSslCertPath = null;
|
|
1044
1046
|
const server = useHttps
|
|
@@ -1231,7 +1233,9 @@ export async function startServer(config, configPath, options = {}) {
|
|
|
1231
1233
|
const updateChecksEnabled = !testMode && process.env.WAND_DISABLE_UPDATE_CHECK !== "1";
|
|
1232
1234
|
// Start configured background sessions after the server is already reachable.
|
|
1233
1235
|
if (!testMode) {
|
|
1234
|
-
processes.runStartupCommands()
|
|
1236
|
+
void processes.runStartupCommands().catch((error) => {
|
|
1237
|
+
console.error("[wand] Failed to start configured startup commands:", getErrorMessage(error));
|
|
1238
|
+
});
|
|
1235
1239
|
}
|
|
1236
1240
|
// Model discovery runs exclusively in the server. Its first result is
|
|
1237
1241
|
// persisted; later checks only write when catalog content changes.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ConversationTurn, SessionSnapshot } from "./types.js";
|
|
2
2
|
export declare const SESSION_TRANSPORT_OUTPUT_LIMIT = 200000;
|
|
3
|
-
export type SessionBaseDTO = Omit<SessionSnapshot, "output" | "messages" | "title"> & {
|
|
3
|
+
export type SessionBaseDTO = Omit<SessionSnapshot, "output" | "messages" | "title" | "ptyOutputSeq" | "ptyLaunchMarkerToken"> & {
|
|
4
4
|
/** Canonical server-resolved title. Clients must not invent their own fallback. */
|
|
5
5
|
title: string;
|
|
6
6
|
};
|
package/dist/storage.d.ts
CHANGED
|
@@ -85,12 +85,12 @@ export declare class WandStorage {
|
|
|
85
85
|
/** Compatibility alias for older callers; intentionally excludes output/messages. */
|
|
86
86
|
saveSessionMetadata(snapshot: SessionSnapshot): void;
|
|
87
87
|
/** Checkpoint only the PTY/structured text output window. */
|
|
88
|
-
checkpointSessionOutput(id: string, output: string): void;
|
|
88
|
+
checkpointSessionOutput(id: string, output: string, ptyOutputSeq?: number): void;
|
|
89
89
|
/**
|
|
90
90
|
* Checkpoint the conversation payload once, optionally folding the matching
|
|
91
91
|
* structured state/output into the same statement.
|
|
92
92
|
*/
|
|
93
|
-
checkpointSessionMessages(id: string, messages: ConversationTurn[], structuredState?: StructuredSessionState | null, output?: string): void;
|
|
93
|
+
checkpointSessionMessages(id: string, messages: ConversationTurn[], structuredState?: StructuredSessionState | null, output?: string, ptyOutputSeq?: number): void;
|
|
94
94
|
getSession(id: string): SessionSnapshot | null;
|
|
95
95
|
getLatestSessionByClaudeSessionId(claudeSessionId: string): SessionSnapshot | null;
|
|
96
96
|
loadSessions(): SessionSnapshot[];
|
package/dist/storage.js
CHANGED
|
@@ -108,6 +108,9 @@ function serializeSessionOptions(snapshot) {
|
|
|
108
108
|
thinkingEffort: snapshot.thinkingEffort,
|
|
109
109
|
ptyCols: snapshot.ptyCols,
|
|
110
110
|
ptyRows: snapshot.ptyRows,
|
|
111
|
+
ptyLaunchMarkerToken: snapshot.ptyLaunchMarkerToken,
|
|
112
|
+
providerCliActive: snapshot.providerCliActive,
|
|
113
|
+
providerCliExitCode: snapshot.providerCliExitCode,
|
|
111
114
|
currentTaskTitle: snapshot.currentTaskTitle,
|
|
112
115
|
summary: snapshot.summary,
|
|
113
116
|
};
|
|
@@ -159,6 +162,14 @@ function parseSessionOptions(raw) {
|
|
|
159
162
|
if (Number.isSafeInteger(parsed.ptyRows) && parsed.ptyRows > 0) {
|
|
160
163
|
options.ptyRows = parsed.ptyRows;
|
|
161
164
|
}
|
|
165
|
+
if (parsed.ptyLaunchMarkerToken === null || typeof parsed.ptyLaunchMarkerToken === "string") {
|
|
166
|
+
options.ptyLaunchMarkerToken = parsed.ptyLaunchMarkerToken;
|
|
167
|
+
}
|
|
168
|
+
if (typeof parsed.providerCliActive === "boolean")
|
|
169
|
+
options.providerCliActive = parsed.providerCliActive;
|
|
170
|
+
if (parsed.providerCliExitCode === null || Number.isSafeInteger(parsed.providerCliExitCode)) {
|
|
171
|
+
options.providerCliExitCode = parsed.providerCliExitCode;
|
|
172
|
+
}
|
|
162
173
|
if (typeof parsed.currentTaskTitle === "string")
|
|
163
174
|
options.currentTaskTitle = parsed.currentTaskTitle;
|
|
164
175
|
if (typeof parsed.summary === "string")
|
|
@@ -243,11 +254,11 @@ function mapWorktreeMergeFields(row) {
|
|
|
243
254
|
};
|
|
244
255
|
}
|
|
245
256
|
function sessionSelectFields() {
|
|
246
|
-
return `id, session_source, automation_id, provider, session_kind, runner, command, cwd, mode, status, exit_code, started_at, ended_at, output, archived, archived_at, claude_session_id, messages, queued_messages, queued_message_skills, structured_state
|
|
257
|
+
return `id, session_source, automation_id, provider, session_kind, runner, command, cwd, mode, status, exit_code, started_at, ended_at, output, pty_output_seq, archived, archived_at, claude_session_id, messages, queued_messages, queued_message_skills, structured_state
|
|
247
258
|
, resumed_from_session_id, auto_recovered, worktree_enabled, worktree_info, worktree_merge_status, worktree_merge_info, title, description, session_options`;
|
|
248
259
|
}
|
|
249
260
|
function sessionPersistFields() {
|
|
250
|
-
return `id, session_source, automation_id, command, cwd, mode, status, exit_code, started_at, ended_at, output
|
|
261
|
+
return `id, session_source, automation_id, command, cwd, mode, status, exit_code, started_at, ended_at, output, pty_output_seq
|
|
251
262
|
, archived, archived_at, claude_session_id, provider, session_kind, runner, messages, queued_messages, queued_message_skills, structured_state
|
|
252
263
|
, resumed_from_session_id, auto_recovered, worktree_enabled, worktree_info, worktree_merge_status, worktree_merge_info, title, description, session_options`;
|
|
253
264
|
}
|
|
@@ -262,6 +273,7 @@ function sessionPersistAssignments() {
|
|
|
262
273
|
started_at = excluded.started_at,
|
|
263
274
|
ended_at = excluded.ended_at,
|
|
264
275
|
output = excluded.output,
|
|
276
|
+
pty_output_seq = excluded.pty_output_seq,
|
|
265
277
|
archived = excluded.archived,
|
|
266
278
|
archived_at = excluded.archived_at,
|
|
267
279
|
claude_session_id = excluded.claude_session_id,
|
|
@@ -305,6 +317,7 @@ function sessionPersistValues(snapshot) {
|
|
|
305
317
|
snapshot.startedAt,
|
|
306
318
|
snapshot.endedAt,
|
|
307
319
|
snapshot.output,
|
|
320
|
+
snapshot.ptyOutputSeq ?? 0,
|
|
308
321
|
snapshot.archived ? 1 : 0,
|
|
309
322
|
snapshot.archivedAt,
|
|
310
323
|
snapshot.claudeSessionId,
|
|
@@ -377,6 +390,7 @@ function mapSessionCore(row) {
|
|
|
377
390
|
startedAt: row.started_at,
|
|
378
391
|
endedAt: row.ended_at,
|
|
379
392
|
output: row.output,
|
|
393
|
+
ptyOutputSeq: row.pty_output_seq,
|
|
380
394
|
archived: Boolean(row.archived),
|
|
381
395
|
archivedAt: row.archived_at,
|
|
382
396
|
claudeSessionId: row.claude_session_id,
|
|
@@ -424,6 +438,7 @@ const INIT_SQL = `
|
|
|
424
438
|
started_at TEXT NOT NULL,
|
|
425
439
|
ended_at TEXT,
|
|
426
440
|
output TEXT NOT NULL,
|
|
441
|
+
pty_output_seq INTEGER NOT NULL DEFAULT 0,
|
|
427
442
|
archived INTEGER NOT NULL DEFAULT 0,
|
|
428
443
|
archived_at TEXT,
|
|
429
444
|
claude_session_id TEXT,
|
|
@@ -939,7 +954,7 @@ export class WandStorage {
|
|
|
939
954
|
this.db
|
|
940
955
|
.prepare(`INSERT INTO command_sessions (
|
|
941
956
|
${sessionPersistFields()}
|
|
942
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
957
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
943
958
|
ON CONFLICT(id) DO UPDATE SET
|
|
944
959
|
${sessionPersistAssignments()}`)
|
|
945
960
|
.run(...sessionPersistValues(snapshot));
|
|
@@ -957,14 +972,19 @@ export class WandStorage {
|
|
|
957
972
|
this.updateSessionRuntimeMetadata(snapshot);
|
|
958
973
|
}
|
|
959
974
|
/** Checkpoint only the PTY/structured text output window. */
|
|
960
|
-
checkpointSessionOutput(id, output) {
|
|
961
|
-
|
|
975
|
+
checkpointSessionOutput(id, output, ptyOutputSeq) {
|
|
976
|
+
if (ptyOutputSeq === undefined) {
|
|
977
|
+
this.db.prepare("UPDATE command_sessions SET output = ? WHERE id = ?").run(output, id);
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
this.db.prepare("UPDATE command_sessions SET output = ?, pty_output_seq = ? WHERE id = ?")
|
|
981
|
+
.run(output, ptyOutputSeq, id);
|
|
962
982
|
}
|
|
963
983
|
/**
|
|
964
984
|
* Checkpoint the conversation payload once, optionally folding the matching
|
|
965
985
|
* structured state/output into the same statement.
|
|
966
986
|
*/
|
|
967
|
-
checkpointSessionMessages(id, messages, structuredState, output) {
|
|
987
|
+
checkpointSessionMessages(id, messages, structuredState, output, ptyOutputSeq) {
|
|
968
988
|
const assignments = ["messages = ?"];
|
|
969
989
|
const values = [JSON.stringify(messages)];
|
|
970
990
|
if (structuredState !== undefined) {
|
|
@@ -975,6 +995,10 @@ export class WandStorage {
|
|
|
975
995
|
assignments.push("output = ?");
|
|
976
996
|
values.push(output);
|
|
977
997
|
}
|
|
998
|
+
if (ptyOutputSeq !== undefined) {
|
|
999
|
+
assignments.push("pty_output_seq = ?");
|
|
1000
|
+
values.push(ptyOutputSeq);
|
|
1001
|
+
}
|
|
978
1002
|
this.db
|
|
979
1003
|
.prepare(`UPDATE command_sessions SET ${assignments.join(", ")} WHERE id = ?`)
|
|
980
1004
|
.run(...values, id);
|
|
@@ -1122,6 +1146,7 @@ const SCHEMA_MIGRATIONS = [
|
|
|
1122
1146
|
["worktree_merge_info", "ALTER TABLE command_sessions ADD COLUMN worktree_merge_info TEXT"],
|
|
1123
1147
|
["title", "ALTER TABLE command_sessions ADD COLUMN title TEXT"],
|
|
1124
1148
|
["description", "ALTER TABLE command_sessions ADD COLUMN description TEXT"],
|
|
1149
|
+
["pty_output_seq", "ALTER TABLE command_sessions ADD COLUMN pty_output_seq INTEGER NOT NULL DEFAULT 0"],
|
|
1125
1150
|
["session_options", `ALTER TABLE command_sessions ADD COLUMN session_options TEXT NOT NULL DEFAULT '{"schemaVersion":1}'`],
|
|
1126
1151
|
];
|
|
1127
1152
|
const AUTH_SESSION_MIGRATIONS = [
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type TerminalDaemonRequest } from "./terminal-daemon-protocol.js";
|
|
2
|
+
import { type TerminalAttachResult, type TerminalHost, type TerminalSpawnRequest } from "./terminal-host.js";
|
|
3
|
+
export declare class TerminalDaemonClient implements TerminalHost {
|
|
4
|
+
private readonly socketPath;
|
|
5
|
+
private readonly token;
|
|
6
|
+
readonly persistent = true;
|
|
7
|
+
private socket;
|
|
8
|
+
private buffer;
|
|
9
|
+
private nextRequestId;
|
|
10
|
+
private readonly pending;
|
|
11
|
+
private readonly inventory;
|
|
12
|
+
private readonly handles;
|
|
13
|
+
private readonly pendingEvents;
|
|
14
|
+
constructor(socketPath: string, token: string);
|
|
15
|
+
connect(): Promise<void>;
|
|
16
|
+
attach(sessionId: string, afterSeq?: number): TerminalAttachResult | null;
|
|
17
|
+
createOrAttach(request: TerminalSpawnRequest, afterSeq?: number): Promise<TerminalAttachResult>;
|
|
18
|
+
forget(sessionId: string): void;
|
|
19
|
+
disconnect(): void;
|
|
20
|
+
request(method: TerminalDaemonRequest["method"], params?: Record<string, unknown>): Promise<unknown>;
|
|
21
|
+
reportOperationError(sessionId: string, error: unknown): void;
|
|
22
|
+
private resultFromState;
|
|
23
|
+
private consume;
|
|
24
|
+
private routeEvent;
|
|
25
|
+
private rejectPending;
|
|
26
|
+
}
|
|
27
|
+
export declare function createTerminalHost(configPath: string): Promise<TerminalHost>;
|
|
28
|
+
/** Connect to an already-running terminal daemon without starting a replacement. */
|
|
29
|
+
export declare function connectExistingTerminalHost(configPath: string): Promise<TerminalDaemonClient | null>;
|