@co0ontty/wand 1.6.2 → 1.9.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/config.js +40 -0
- package/dist/git-worktree.d.ts +28 -0
- package/dist/git-worktree.js +287 -0
- package/dist/message-parser.d.ts +1 -1
- package/dist/message-parser.js +275 -1
- package/dist/process-manager.d.ts +6 -3
- package/dist/process-manager.js +135 -81
- package/dist/pty-text-utils.js +79 -29
- package/dist/server-session-routes.js +192 -7
- package/dist/server.js +38 -1
- package/dist/session-logger.d.ts +2 -0
- package/dist/session-logger.js +23 -0
- package/dist/storage.d.ts +1 -0
- package/dist/storage.js +258 -58
- package/dist/structured-session-manager.d.ts +5 -0
- package/dist/structured-session-manager.js +107 -43
- package/dist/types.d.ts +65 -0
- package/dist/web-ui/content/scripts.js +2251 -500
- package/dist/web-ui/content/styles.css +1154 -119
- package/package.json +1 -1
package/dist/storage.js
CHANGED
|
@@ -12,6 +12,18 @@ function parseStoredMessages(raw) {
|
|
|
12
12
|
return undefined;
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
+
function parseQueuedMessages(raw) {
|
|
16
|
+
if (!raw) {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
const parsed = JSON.parse(raw);
|
|
21
|
+
return Array.isArray(parsed) ? parsed.filter((item) => typeof item === "string") : undefined;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
15
27
|
function parseStructuredState(raw) {
|
|
16
28
|
if (!raw) {
|
|
17
29
|
return undefined;
|
|
@@ -23,6 +35,206 @@ function parseStructuredState(raw) {
|
|
|
23
35
|
return undefined;
|
|
24
36
|
}
|
|
25
37
|
}
|
|
38
|
+
function inferSessionProvider(row) {
|
|
39
|
+
if (row.provider === "claude" || row.provider === "codex") {
|
|
40
|
+
return row.provider;
|
|
41
|
+
}
|
|
42
|
+
if (row.runner === "claude-cli" || row.runner === "claude-cli-print") {
|
|
43
|
+
return "claude";
|
|
44
|
+
}
|
|
45
|
+
return /^claude\b/.test(row.command.trim()) ? "claude" : undefined;
|
|
46
|
+
}
|
|
47
|
+
function parseWorktreeInfo(raw) {
|
|
48
|
+
if (!raw) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const parsed = JSON.parse(raw);
|
|
53
|
+
if (parsed
|
|
54
|
+
&& typeof parsed === "object"
|
|
55
|
+
&& typeof parsed.branch === "string"
|
|
56
|
+
&& typeof parsed.path === "string") {
|
|
57
|
+
return parsed;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
function parseWorktreeMergeInfo(raw) {
|
|
66
|
+
if (!raw) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
const parsed = JSON.parse(raw);
|
|
71
|
+
if (parsed && typeof parsed === "object") {
|
|
72
|
+
return parsed;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
function serializeWorktreeMergeInfo(info) {
|
|
81
|
+
return info ? JSON.stringify(info) : null;
|
|
82
|
+
}
|
|
83
|
+
function serializeWorktreeInfo(info) {
|
|
84
|
+
return info ? JSON.stringify(info) : null;
|
|
85
|
+
}
|
|
86
|
+
function normalizeWorktreeMergeStatus(raw) {
|
|
87
|
+
if (raw === "ready" || raw === "checking" || raw === "merging" || raw === "merged" || raw === "failed") {
|
|
88
|
+
return raw;
|
|
89
|
+
}
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
function getWorktreeMergeStatusValue(snapshot) {
|
|
93
|
+
return snapshot.worktreeMergeStatus ?? null;
|
|
94
|
+
}
|
|
95
|
+
function getWorktreeMergeInfoValue(snapshot) {
|
|
96
|
+
return serializeWorktreeMergeInfo(snapshot.worktreeMergeInfo);
|
|
97
|
+
}
|
|
98
|
+
function getWorktreeInfoValue(snapshot) {
|
|
99
|
+
return serializeWorktreeInfo(snapshot.worktree);
|
|
100
|
+
}
|
|
101
|
+
function mapWorktreeMergeFields(row) {
|
|
102
|
+
return {
|
|
103
|
+
worktreeMergeStatus: normalizeWorktreeMergeStatus(row.worktree_merge_status),
|
|
104
|
+
worktreeMergeInfo: parseWorktreeMergeInfo(row.worktree_merge_info) ?? null,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function sessionSelectFields() {
|
|
108
|
+
return `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, structured_state
|
|
109
|
+
, resumed_from_session_id, resumed_to_session_id, auto_recovered, worktree_enabled, worktree_info, worktree_merge_status, worktree_merge_info`;
|
|
110
|
+
}
|
|
111
|
+
function sessionPersistFields() {
|
|
112
|
+
return `id, command, cwd, mode, status, exit_code, started_at, ended_at, output
|
|
113
|
+
, archived, archived_at, claude_session_id, provider, session_kind, runner, messages, queued_messages, structured_state
|
|
114
|
+
, resumed_from_session_id, resumed_to_session_id, auto_recovered, worktree_enabled, worktree_info, worktree_merge_status, worktree_merge_info`;
|
|
115
|
+
}
|
|
116
|
+
function sessionPersistAssignments() {
|
|
117
|
+
return `command = excluded.command,
|
|
118
|
+
cwd = excluded.cwd,
|
|
119
|
+
mode = excluded.mode,
|
|
120
|
+
status = excluded.status,
|
|
121
|
+
exit_code = excluded.exit_code,
|
|
122
|
+
started_at = excluded.started_at,
|
|
123
|
+
ended_at = excluded.ended_at,
|
|
124
|
+
output = excluded.output,
|
|
125
|
+
archived = excluded.archived,
|
|
126
|
+
archived_at = excluded.archived_at,
|
|
127
|
+
claude_session_id = excluded.claude_session_id,
|
|
128
|
+
provider = excluded.provider,
|
|
129
|
+
session_kind = excluded.session_kind,
|
|
130
|
+
runner = excluded.runner,
|
|
131
|
+
messages = excluded.messages,
|
|
132
|
+
queued_messages = excluded.queued_messages,
|
|
133
|
+
structured_state = excluded.structured_state,
|
|
134
|
+
resumed_from_session_id = excluded.resumed_from_session_id,
|
|
135
|
+
resumed_to_session_id = excluded.resumed_to_session_id,
|
|
136
|
+
auto_recovered = excluded.auto_recovered,
|
|
137
|
+
worktree_enabled = excluded.worktree_enabled,
|
|
138
|
+
worktree_info = excluded.worktree_info,
|
|
139
|
+
worktree_merge_status = excluded.worktree_merge_status,
|
|
140
|
+
worktree_merge_info = excluded.worktree_merge_info`;
|
|
141
|
+
}
|
|
142
|
+
function sessionMetadataAssignments() {
|
|
143
|
+
return `command = ?, cwd = ?, mode = ?, status = ?, exit_code = ?,
|
|
144
|
+
started_at = ?, ended_at = ?, output = ?,
|
|
145
|
+
archived = ?, archived_at = ?, claude_session_id = ?,
|
|
146
|
+
provider = ?, session_kind = ?, runner = ?, structured_state = ?,
|
|
147
|
+
resumed_from_session_id = ?, resumed_to_session_id = ?, auto_recovered = ?,
|
|
148
|
+
worktree_enabled = ?, worktree_info = ?, worktree_merge_status = ?, worktree_merge_info = ?`;
|
|
149
|
+
}
|
|
150
|
+
function sessionPersistValues(snapshot) {
|
|
151
|
+
return [
|
|
152
|
+
snapshot.id,
|
|
153
|
+
snapshot.command,
|
|
154
|
+
snapshot.cwd,
|
|
155
|
+
snapshot.mode,
|
|
156
|
+
snapshot.status,
|
|
157
|
+
snapshot.exitCode,
|
|
158
|
+
snapshot.startedAt,
|
|
159
|
+
snapshot.endedAt,
|
|
160
|
+
snapshot.output,
|
|
161
|
+
snapshot.archived ? 1 : 0,
|
|
162
|
+
snapshot.archivedAt,
|
|
163
|
+
snapshot.claudeSessionId,
|
|
164
|
+
snapshot.provider ?? null,
|
|
165
|
+
snapshot.sessionKind ?? "pty",
|
|
166
|
+
snapshot.runner ?? null,
|
|
167
|
+
snapshot.messages ? JSON.stringify(snapshot.messages) : null,
|
|
168
|
+
snapshot.queuedMessages ? JSON.stringify(snapshot.queuedMessages) : null,
|
|
169
|
+
snapshot.structuredState ? JSON.stringify(snapshot.structuredState) : null,
|
|
170
|
+
snapshot.resumedFromSessionId ?? null,
|
|
171
|
+
snapshot.resumedToSessionId ?? null,
|
|
172
|
+
snapshot.autoRecovered ? 1 : 0,
|
|
173
|
+
snapshot.worktreeEnabled ? 1 : 0,
|
|
174
|
+
getWorktreeInfoValue(snapshot),
|
|
175
|
+
getWorktreeMergeStatusValue(snapshot),
|
|
176
|
+
getWorktreeMergeInfoValue(snapshot),
|
|
177
|
+
];
|
|
178
|
+
}
|
|
179
|
+
function sessionMetadataValues(snapshot) {
|
|
180
|
+
return [
|
|
181
|
+
snapshot.command,
|
|
182
|
+
snapshot.cwd,
|
|
183
|
+
snapshot.mode,
|
|
184
|
+
snapshot.status,
|
|
185
|
+
snapshot.exitCode,
|
|
186
|
+
snapshot.startedAt,
|
|
187
|
+
snapshot.endedAt,
|
|
188
|
+
snapshot.output,
|
|
189
|
+
snapshot.archived ? 1 : 0,
|
|
190
|
+
snapshot.archivedAt,
|
|
191
|
+
snapshot.claudeSessionId,
|
|
192
|
+
snapshot.provider ?? null,
|
|
193
|
+
snapshot.sessionKind ?? "pty",
|
|
194
|
+
snapshot.runner ?? null,
|
|
195
|
+
snapshot.structuredState ? JSON.stringify(snapshot.structuredState) : null,
|
|
196
|
+
snapshot.resumedFromSessionId ?? null,
|
|
197
|
+
snapshot.resumedToSessionId ?? null,
|
|
198
|
+
snapshot.autoRecovered ? 1 : 0,
|
|
199
|
+
snapshot.worktreeEnabled ? 1 : 0,
|
|
200
|
+
getWorktreeInfoValue(snapshot),
|
|
201
|
+
getWorktreeMergeStatusValue(snapshot),
|
|
202
|
+
getWorktreeMergeInfoValue(snapshot),
|
|
203
|
+
snapshot.id,
|
|
204
|
+
];
|
|
205
|
+
}
|
|
206
|
+
function mapSessionCore(row) {
|
|
207
|
+
const provider = inferSessionProvider(row);
|
|
208
|
+
return {
|
|
209
|
+
id: row.id,
|
|
210
|
+
sessionKind: row.session_kind ?? "pty",
|
|
211
|
+
provider,
|
|
212
|
+
runner: row.runner ?? undefined,
|
|
213
|
+
command: row.command,
|
|
214
|
+
cwd: row.cwd,
|
|
215
|
+
mode: row.mode,
|
|
216
|
+
status: row.status,
|
|
217
|
+
exitCode: row.exit_code,
|
|
218
|
+
startedAt: row.started_at,
|
|
219
|
+
endedAt: row.ended_at,
|
|
220
|
+
output: row.output,
|
|
221
|
+
archived: Boolean(row.archived),
|
|
222
|
+
archivedAt: row.archived_at,
|
|
223
|
+
claudeSessionId: row.claude_session_id,
|
|
224
|
+
messages: parseStoredMessages(row.messages),
|
|
225
|
+
queuedMessages: parseQueuedMessages(row.queued_messages),
|
|
226
|
+
structuredState: parseStructuredState(row.structured_state),
|
|
227
|
+
resumedFromSessionId: row.resumed_from_session_id ?? undefined,
|
|
228
|
+
resumedToSessionId: row.resumed_to_session_id ?? undefined,
|
|
229
|
+
autoRecovered: Boolean(row.auto_recovered),
|
|
230
|
+
worktreeEnabled: Boolean(row.worktree_enabled),
|
|
231
|
+
worktree: parseWorktreeInfo(row.worktree_info) ?? null,
|
|
232
|
+
...mapWorktreeMergeFields(row),
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
function sessionRowQuery(base) {
|
|
236
|
+
return `${base} ${sessionSelectFields()}`;
|
|
237
|
+
}
|
|
26
238
|
export const DEFAULT_DB_FILE = "wand.db";
|
|
27
239
|
export function resolveDatabasePath(configPath) {
|
|
28
240
|
return path.resolve(path.dirname(configPath), DEFAULT_DB_FILE);
|
|
@@ -46,13 +258,19 @@ const INIT_SQL = `
|
|
|
46
258
|
archived INTEGER NOT NULL DEFAULT 0,
|
|
47
259
|
archived_at TEXT,
|
|
48
260
|
claude_session_id TEXT,
|
|
261
|
+
provider TEXT,
|
|
49
262
|
session_kind TEXT NOT NULL DEFAULT 'pty',
|
|
50
263
|
runner TEXT,
|
|
51
264
|
messages TEXT,
|
|
265
|
+
queued_messages TEXT,
|
|
52
266
|
structured_state TEXT,
|
|
53
267
|
resumed_from_session_id TEXT,
|
|
54
268
|
resumed_to_session_id TEXT,
|
|
55
|
-
auto_recovered INTEGER NOT NULL DEFAULT 0
|
|
269
|
+
auto_recovered INTEGER NOT NULL DEFAULT 0,
|
|
270
|
+
worktree_enabled INTEGER NOT NULL DEFAULT 0,
|
|
271
|
+
worktree_info TEXT,
|
|
272
|
+
worktree_merge_status TEXT,
|
|
273
|
+
worktree_merge_info TEXT
|
|
56
274
|
);
|
|
57
275
|
|
|
58
276
|
CREATE TABLE IF NOT EXISTS app_config (
|
|
@@ -142,30 +360,11 @@ export class WandStorage {
|
|
|
142
360
|
try {
|
|
143
361
|
this.db
|
|
144
362
|
.prepare(`INSERT INTO command_sessions (
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
, resumed_from_session_id, resumed_to_session_id, auto_recovered
|
|
148
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
363
|
+
${sessionPersistFields()}
|
|
364
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
149
365
|
ON CONFLICT(id) DO UPDATE SET
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
mode = excluded.mode,
|
|
153
|
-
status = excluded.status,
|
|
154
|
-
exit_code = excluded.exit_code,
|
|
155
|
-
started_at = excluded.started_at,
|
|
156
|
-
ended_at = excluded.ended_at,
|
|
157
|
-
output = excluded.output,
|
|
158
|
-
archived = excluded.archived,
|
|
159
|
-
archived_at = excluded.archived_at,
|
|
160
|
-
claude_session_id = excluded.claude_session_id,
|
|
161
|
-
session_kind = excluded.session_kind,
|
|
162
|
-
runner = excluded.runner,
|
|
163
|
-
messages = excluded.messages,
|
|
164
|
-
structured_state = excluded.structured_state,
|
|
165
|
-
resumed_from_session_id = excluded.resumed_from_session_id,
|
|
166
|
-
resumed_to_session_id = excluded.resumed_to_session_id,
|
|
167
|
-
auto_recovered = excluded.auto_recovered`)
|
|
168
|
-
.run(snapshot.id, snapshot.command, snapshot.cwd, snapshot.mode, snapshot.status, snapshot.exitCode, snapshot.startedAt, snapshot.endedAt, snapshot.output, snapshot.archived ? 1 : 0, snapshot.archivedAt, snapshot.claudeSessionId, snapshot.sessionKind ?? "pty", snapshot.runner ?? null, snapshot.messages ? JSON.stringify(snapshot.messages) : null, snapshot.structuredState ? JSON.stringify(snapshot.structuredState) : null, snapshot.resumedFromSessionId ?? null, snapshot.resumedToSessionId ?? null, snapshot.autoRecovered ? 1 : 0);
|
|
366
|
+
${sessionPersistAssignments()}`)
|
|
367
|
+
.run(...sessionPersistValues(snapshot));
|
|
169
368
|
this.db.exec("COMMIT");
|
|
170
369
|
}
|
|
171
370
|
catch (error) {
|
|
@@ -181,18 +380,13 @@ export class WandStorage {
|
|
|
181
380
|
saveSessionMetadata(snapshot) {
|
|
182
381
|
this.db
|
|
183
382
|
.prepare(`UPDATE command_sessions SET
|
|
184
|
-
|
|
185
|
-
started_at = ?, ended_at = ?, output = ?,
|
|
186
|
-
archived = ?, archived_at = ?, claude_session_id = ?,
|
|
187
|
-
session_kind = ?, runner = ?, structured_state = ?,
|
|
188
|
-
resumed_from_session_id = ?, resumed_to_session_id = ?, auto_recovered = ?
|
|
383
|
+
${sessionMetadataAssignments()}
|
|
189
384
|
WHERE id = ?`)
|
|
190
|
-
.run(
|
|
385
|
+
.run(...sessionMetadataValues(snapshot));
|
|
191
386
|
}
|
|
192
387
|
getSession(id) {
|
|
193
388
|
const row = this.db
|
|
194
|
-
.prepare(
|
|
195
|
-
, resumed_from_session_id, resumed_to_session_id, auto_recovered
|
|
389
|
+
.prepare(`${sessionRowQuery("SELECT")}
|
|
196
390
|
FROM command_sessions
|
|
197
391
|
WHERE id = ?`)
|
|
198
392
|
.get(id);
|
|
@@ -200,8 +394,7 @@ export class WandStorage {
|
|
|
200
394
|
}
|
|
201
395
|
getLatestSessionByClaudeSessionId(claudeSessionId) {
|
|
202
396
|
const row = this.db
|
|
203
|
-
.prepare(
|
|
204
|
-
, resumed_from_session_id, resumed_to_session_id, auto_recovered
|
|
397
|
+
.prepare(`${sessionRowQuery("SELECT")}
|
|
205
398
|
FROM command_sessions
|
|
206
399
|
WHERE claude_session_id = ?
|
|
207
400
|
ORDER BY started_at DESC
|
|
@@ -211,35 +404,27 @@ export class WandStorage {
|
|
|
211
404
|
}
|
|
212
405
|
loadSessions() {
|
|
213
406
|
const rows = this.db
|
|
214
|
-
.prepare(
|
|
215
|
-
, resumed_from_session_id, resumed_to_session_id, auto_recovered
|
|
407
|
+
.prepare(`${sessionRowQuery("SELECT")}
|
|
216
408
|
FROM command_sessions
|
|
217
409
|
ORDER BY started_at DESC`)
|
|
218
410
|
.all();
|
|
219
411
|
return rows.map((row) => this.mapSessionRow(row));
|
|
220
412
|
}
|
|
221
413
|
mapSessionRow(row) {
|
|
222
|
-
return
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
output: row.output,
|
|
234
|
-
archived: Boolean(row.archived),
|
|
235
|
-
archivedAt: row.archived_at,
|
|
236
|
-
claudeSessionId: row.claude_session_id,
|
|
237
|
-
messages: parseStoredMessages(row.messages),
|
|
238
|
-
structuredState: parseStructuredState(row.structured_state),
|
|
239
|
-
resumedFromSessionId: row.resumed_from_session_id ?? undefined,
|
|
240
|
-
resumedToSessionId: row.resumed_to_session_id ?? undefined,
|
|
241
|
-
autoRecovered: Boolean(row.auto_recovered)
|
|
414
|
+
return mapSessionCore(row);
|
|
415
|
+
}
|
|
416
|
+
updateSessionWorktreeMergeState(id, status, info) {
|
|
417
|
+
const current = this.getSession(id);
|
|
418
|
+
if (!current) {
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
const updated = {
|
|
422
|
+
...current,
|
|
423
|
+
worktreeMergeStatus: status,
|
|
424
|
+
worktreeMergeInfo: info,
|
|
242
425
|
};
|
|
426
|
+
this.saveSessionMetadata(updated);
|
|
427
|
+
return updated;
|
|
243
428
|
}
|
|
244
429
|
deleteSession(id) {
|
|
245
430
|
this.db.prepare("DELETE FROM command_sessions WHERE id = ?").run(id);
|
|
@@ -257,6 +442,9 @@ function ensureCommandSessionSchema(db) {
|
|
|
257
442
|
if (!names.has("claude_session_id")) {
|
|
258
443
|
db.exec("ALTER TABLE command_sessions ADD COLUMN claude_session_id TEXT");
|
|
259
444
|
}
|
|
445
|
+
if (!names.has("provider")) {
|
|
446
|
+
db.exec("ALTER TABLE command_sessions ADD COLUMN provider TEXT");
|
|
447
|
+
}
|
|
260
448
|
if (!names.has("session_kind")) {
|
|
261
449
|
db.exec("ALTER TABLE command_sessions ADD COLUMN session_kind TEXT NOT NULL DEFAULT 'pty'");
|
|
262
450
|
}
|
|
@@ -266,6 +454,9 @@ function ensureCommandSessionSchema(db) {
|
|
|
266
454
|
if (!names.has("messages")) {
|
|
267
455
|
db.exec("ALTER TABLE command_sessions ADD COLUMN messages TEXT");
|
|
268
456
|
}
|
|
457
|
+
if (!names.has("queued_messages")) {
|
|
458
|
+
db.exec("ALTER TABLE command_sessions ADD COLUMN queued_messages TEXT");
|
|
459
|
+
}
|
|
269
460
|
if (!names.has("structured_state")) {
|
|
270
461
|
db.exec("ALTER TABLE command_sessions ADD COLUMN structured_state TEXT");
|
|
271
462
|
}
|
|
@@ -275,7 +466,16 @@ function ensureCommandSessionSchema(db) {
|
|
|
275
466
|
if (!names.has("resumed_to_session_id")) {
|
|
276
467
|
db.exec("ALTER TABLE command_sessions ADD COLUMN resumed_to_session_id TEXT");
|
|
277
468
|
}
|
|
278
|
-
if (!names.has("
|
|
279
|
-
db.exec("ALTER TABLE command_sessions ADD COLUMN
|
|
469
|
+
if (!names.has("worktree_enabled")) {
|
|
470
|
+
db.exec("ALTER TABLE command_sessions ADD COLUMN worktree_enabled INTEGER NOT NULL DEFAULT 0");
|
|
471
|
+
}
|
|
472
|
+
if (!names.has("worktree_info")) {
|
|
473
|
+
db.exec("ALTER TABLE command_sessions ADD COLUMN worktree_info TEXT");
|
|
474
|
+
}
|
|
475
|
+
if (!names.has("worktree_merge_status")) {
|
|
476
|
+
db.exec("ALTER TABLE command_sessions ADD COLUMN worktree_merge_status TEXT");
|
|
477
|
+
}
|
|
478
|
+
if (!names.has("worktree_merge_info")) {
|
|
479
|
+
db.exec("ALTER TABLE command_sessions ADD COLUMN worktree_merge_info TEXT");
|
|
280
480
|
}
|
|
281
481
|
}
|
|
@@ -5,6 +5,7 @@ interface CreateStructuredSessionOptions {
|
|
|
5
5
|
mode: ExecutionMode;
|
|
6
6
|
prompt?: string;
|
|
7
7
|
runner?: SessionRunner;
|
|
8
|
+
worktreeEnabled?: boolean;
|
|
8
9
|
}
|
|
9
10
|
export declare class StructuredSessionManager {
|
|
10
11
|
private readonly storage;
|
|
@@ -29,6 +30,10 @@ export declare class StructuredSessionManager {
|
|
|
29
30
|
stop(id: string): SessionSnapshot;
|
|
30
31
|
delete(id: string): void;
|
|
31
32
|
private requireSession;
|
|
33
|
+
private buildQueuedPlaceholderTurns;
|
|
34
|
+
private buildRenderableMessages;
|
|
35
|
+
private emitStructuredSnapshot;
|
|
36
|
+
private flushNextQueuedMessage;
|
|
32
37
|
private emit;
|
|
33
38
|
private resolvePermission;
|
|
34
39
|
private incrementApprovalStats;
|