@jmfederico/pi-web 1.202607.1 → 1.202607.2
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.md +8 -8
- package/dist/cli.js +17 -5
- package/dist/cli.js.map +1 -1
- package/dist/client/assets/{CodeViewer-uASb28Y1.js → CodeViewer-B4M13447.js} +1 -1
- package/dist/client/assets/{TerminalPanel-DfTmykFw.js → TerminalPanel-Bmvj-Ecn.js} +1 -1
- package/dist/client/assets/{UnifiedDiffViewer-laQN1x7P.js → UnifiedDiffViewer-C0hygwRo.js} +1 -1
- package/dist/client/assets/index-TvPsRyS1.js +3545 -0
- package/dist/client/index.html +1 -1
- package/dist/config.js +13 -0
- package/dist/config.js.map +1 -1
- package/dist/server/diagnostics/nodePtyNativeModule.js +36 -0
- package/dist/server/diagnostics/nodePtyNativeModule.js.map +1 -0
- package/dist/server/git/gitService.js +176 -5
- package/dist/server/git/gitService.js.map +1 -1
- package/dist/server/piWebStatus.js +6 -3
- package/dist/server/piWebStatus.js.map +1 -1
- package/dist/server/realtime/sessionEventHub.js +4 -0
- package/dist/server/realtime/sessionEventHub.js.map +1 -1
- package/dist/server/sessiond.js +47 -7
- package/dist/server/sessiond.js.map +1 -1
- package/dist/server/sessions/authService.js +58 -7
- package/dist/server/sessions/authService.js.map +1 -1
- package/dist/server/sessions/globalProviderPolicy.js +98 -0
- package/dist/server/sessions/globalProviderPolicy.js.map +1 -0
- package/dist/server/sessions/modelCatalogRefresher.js +184 -0
- package/dist/server/sessions/modelCatalogRefresher.js.map +1 -0
- package/dist/server/sessions/piSessionService.js +736 -100
- package/dist/server/sessions/piSessionService.js.map +1 -1
- package/dist/server/sessions/plainTextTheme.js +112 -0
- package/dist/server/sessions/plainTextTheme.js.map +1 -0
- package/dist/server/sessions/sessionCommandService.js +68 -9
- package/dist/server/sessions/sessionCommandService.js.map +1 -1
- package/dist/server/sessions/sessionNotificationStore.js +484 -0
- package/dist/server/sessions/sessionNotificationStore.js.map +1 -0
- package/dist/server/sessions/sessionRoutes.js +175 -0
- package/dist/server/sessions/sessionRoutes.js.map +1 -1
- package/dist/server/sessions/sessionTreeProjection.js +250 -0
- package/dist/server/sessions/sessionTreeProjection.js.map +1 -0
- package/dist/server/sessions/sessionUnreadStore.js +520 -0
- package/dist/server/sessions/sessionUnreadStore.js.map +1 -0
- package/dist/server/sessions/spawnSessionTool.js +2 -2
- package/dist/server/sessions/spawnSessionTool.js.map +1 -1
- package/dist/server/sessions/spawnSubsessionTool.js +10 -12
- package/dist/server/sessions/spawnSubsessionTool.js.map +1 -1
- package/dist/shared/apiTypes.d.ts +159 -2
- package/dist/shared/apiTypes.js +10 -0
- package/dist/shared/apiTypes.js.map +1 -1
- package/dist/shared/capabilities.js +6 -0
- package/dist/shared/capabilities.js.map +1 -1
- package/dist/shared/federatedRoutes.js +8 -0
- package/dist/shared/federatedRoutes.js.map +1 -1
- package/docs/config.md +32 -4
- package/docs/plugins.md +10 -6
- package/install.sh +1 -1
- package/package.json +8 -7
- package/dist/client/assets/index-Dhapi0oR.js +0 -3093
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { piWebDataDir } from "../../config.js";
|
|
5
|
+
import { SESSION_UNREAD_CATALOG_ID_MAX_LENGTH, SESSION_UNREAD_COMPLETED_AT_MAX_LENGTH, SESSION_UNREAD_CWD_MAX_LENGTH, SESSION_UNREAD_LIMIT, SESSION_UNREAD_SESSION_ID_MAX_LENGTH, } from "../../shared/apiTypes.js";
|
|
6
|
+
const SESSION_UNREAD_STATE_VERSION = 1;
|
|
7
|
+
const SESSION_UNREAD_FILE_MODE = 0o600;
|
|
8
|
+
/**
|
|
9
|
+
* Daemon-owned unread completion catalog.
|
|
10
|
+
*
|
|
11
|
+
* Completion orders are global and never reused within a catalog epoch. An
|
|
12
|
+
* acknowledgement must carry both the epoch and the observed completion order,
|
|
13
|
+
* so neither an old completion nor a client from reset state can clear newer
|
|
14
|
+
* work.
|
|
15
|
+
*/
|
|
16
|
+
export class SessionUnreadStore {
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
this.unreadByIdentity = new Map();
|
|
19
|
+
this.activeByIdentity = new Map();
|
|
20
|
+
this.excludedByIdentity = new Map();
|
|
21
|
+
this.catalogRevision = 0;
|
|
22
|
+
this.nextCompletionOrder = 0;
|
|
23
|
+
this.persistenceGeneration = 0;
|
|
24
|
+
this.durablePersistenceGeneration = 0;
|
|
25
|
+
this.now = options.now ?? (() => new Date());
|
|
26
|
+
this.persistence = options.persistence;
|
|
27
|
+
this.createCatalogId = options.createCatalogId ?? randomUUID;
|
|
28
|
+
this.onPersistenceError = options.onPersistenceError ?? (() => undefined);
|
|
29
|
+
this.loaded = this.persistence === undefined;
|
|
30
|
+
// A persisted store receives its epoch from disk or creates one during
|
|
31
|
+
// load; synchronous in-memory stores are ready immediately.
|
|
32
|
+
this.catalogId = this.loaded ? this.freshCatalogId() : "";
|
|
33
|
+
}
|
|
34
|
+
load() {
|
|
35
|
+
if (this.loaded)
|
|
36
|
+
return Promise.resolve();
|
|
37
|
+
if (this.loadPromise !== undefined)
|
|
38
|
+
return this.loadPromise;
|
|
39
|
+
const loadPromise = this.loadPersistedState();
|
|
40
|
+
this.loadPromise = loadPromise;
|
|
41
|
+
return loadPromise;
|
|
42
|
+
}
|
|
43
|
+
/** Current in-memory state. Transport boundaries should use `durableCatalogSnapshot`. */
|
|
44
|
+
catalogSnapshot() {
|
|
45
|
+
this.requireLoaded();
|
|
46
|
+
return {
|
|
47
|
+
catalogId: this.catalogId,
|
|
48
|
+
catalogRevision: this.catalogRevision,
|
|
49
|
+
sessions: [...this.unreadByIdentity.values()]
|
|
50
|
+
.sort((left, right) => right.completionOrder - left.completionOrder)
|
|
51
|
+
.map((summary) => ({ ...summary })),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
observeActivityState(sessionId, cwd, active) {
|
|
55
|
+
this.requireLoaded();
|
|
56
|
+
const identity = requireIdentity(sessionId, cwd);
|
|
57
|
+
const key = sessionIdentityKey(identity);
|
|
58
|
+
if (this.excludedByIdentity.has(key)) {
|
|
59
|
+
this.activeByIdentity.delete(key);
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
if (active) {
|
|
63
|
+
this.activeByIdentity.set(key, identity);
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
if (!this.activeByIdentity.has(key))
|
|
67
|
+
return [];
|
|
68
|
+
const completionOrder = incrementSafe(this.nextCompletionOrder, "Session unread completion order exhausted");
|
|
69
|
+
const willExceedLimit = !this.unreadByIdentity.has(key) && this.unreadByIdentity.size >= SESSION_UNREAD_LIMIT;
|
|
70
|
+
this.assertRevisionCapacity(willExceedLimit ? 2 : 1);
|
|
71
|
+
const completedAt = this.now().toISOString();
|
|
72
|
+
this.activeByIdentity.delete(key);
|
|
73
|
+
this.nextCompletionOrder = completionOrder;
|
|
74
|
+
const summary = {
|
|
75
|
+
sessionId,
|
|
76
|
+
cwd,
|
|
77
|
+
completionOrder,
|
|
78
|
+
completedAt,
|
|
79
|
+
};
|
|
80
|
+
// Reinsert existing identities so map order remains completion order.
|
|
81
|
+
this.unreadByIdentity.delete(key);
|
|
82
|
+
this.unreadByIdentity.set(key, summary);
|
|
83
|
+
const mutations = [this.mutation(identity, summary), ...this.trimToLimit()];
|
|
84
|
+
this.schedulePersist();
|
|
85
|
+
return mutations;
|
|
86
|
+
}
|
|
87
|
+
/** Clear only the transient active latch for a runtime that is closing or rebinding. */
|
|
88
|
+
forgetActivity(sessionId, cwd) {
|
|
89
|
+
this.requireLoaded();
|
|
90
|
+
const identity = requireIdentity(sessionId, cwd);
|
|
91
|
+
this.activeByIdentity.delete(sessionIdentityKey(identity));
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Suppress unread tracking until this identity is explicitly forgotten and
|
|
95
|
+
* remove state recorded before it was verified as a tracked sub-session.
|
|
96
|
+
*/
|
|
97
|
+
excludeSession(sessionId, cwd) {
|
|
98
|
+
this.requireLoaded();
|
|
99
|
+
const identity = requireIdentity(sessionId, cwd);
|
|
100
|
+
const key = sessionIdentityKey(identity);
|
|
101
|
+
const current = this.unreadByIdentity.get(key);
|
|
102
|
+
this.assertRevisionCapacity(current === undefined ? 0 : 1);
|
|
103
|
+
this.excludedByIdentity.set(key, identity);
|
|
104
|
+
this.activeByIdentity.delete(key);
|
|
105
|
+
if (current === undefined)
|
|
106
|
+
return [];
|
|
107
|
+
this.unreadByIdentity.delete(key);
|
|
108
|
+
const mutations = [this.mutation(identity, null)];
|
|
109
|
+
this.schedulePersist();
|
|
110
|
+
return mutations;
|
|
111
|
+
}
|
|
112
|
+
acknowledge(sessionId, request) {
|
|
113
|
+
this.requireLoaded();
|
|
114
|
+
const identity = requireIdentity(sessionId, request.cwd);
|
|
115
|
+
requireCatalogId(request.catalogId);
|
|
116
|
+
requirePositiveSafeInteger(request.throughCompletionOrder, "throughCompletionOrder");
|
|
117
|
+
if (request.catalogId !== this.catalogId)
|
|
118
|
+
return { mutations: [] };
|
|
119
|
+
const key = sessionIdentityKey(identity);
|
|
120
|
+
const current = this.unreadByIdentity.get(key);
|
|
121
|
+
if (current === undefined || current.completionOrder > request.throughCompletionOrder) {
|
|
122
|
+
return { mutations: [] };
|
|
123
|
+
}
|
|
124
|
+
this.assertRevisionCapacity(1);
|
|
125
|
+
this.unreadByIdentity.delete(key);
|
|
126
|
+
const mutations = [this.mutation(identity, null)];
|
|
127
|
+
this.schedulePersist();
|
|
128
|
+
return { mutations };
|
|
129
|
+
}
|
|
130
|
+
/** Remove durable unread and all transient lifecycle state for one identity. */
|
|
131
|
+
forgetSession(sessionId, cwd) {
|
|
132
|
+
this.requireLoaded();
|
|
133
|
+
const identity = requireIdentity(sessionId, cwd);
|
|
134
|
+
const key = sessionIdentityKey(identity);
|
|
135
|
+
const current = this.unreadByIdentity.get(key);
|
|
136
|
+
this.assertRevisionCapacity(current === undefined ? 0 : 1);
|
|
137
|
+
this.activeByIdentity.delete(key);
|
|
138
|
+
this.excludedByIdentity.delete(key);
|
|
139
|
+
if (current === undefined)
|
|
140
|
+
return [];
|
|
141
|
+
this.unreadByIdentity.delete(key);
|
|
142
|
+
const mutations = [this.mutation(identity, null)];
|
|
143
|
+
this.schedulePersist();
|
|
144
|
+
return mutations;
|
|
145
|
+
}
|
|
146
|
+
reconcileCwd(cwd, sessionIds) {
|
|
147
|
+
this.requireLoaded();
|
|
148
|
+
const boundedCwd = requireBoundedNonEmptyString(cwd, "cwd", SESSION_UNREAD_CWD_MAX_LENGTH);
|
|
149
|
+
const retained = new Set(sessionIds);
|
|
150
|
+
const removed = [...this.unreadByIdentity.entries()]
|
|
151
|
+
.filter(([, summary]) => summary.cwd === boundedCwd && !retained.has(summary.sessionId));
|
|
152
|
+
this.assertRevisionCapacity(removed.length);
|
|
153
|
+
for (const [key, identity] of this.activeByIdentity) {
|
|
154
|
+
if (identity.cwd === boundedCwd && !retained.has(identity.sessionId))
|
|
155
|
+
this.activeByIdentity.delete(key);
|
|
156
|
+
}
|
|
157
|
+
for (const [key, identity] of this.excludedByIdentity) {
|
|
158
|
+
if (identity.cwd === boundedCwd && !retained.has(identity.sessionId))
|
|
159
|
+
this.excludedByIdentity.delete(key);
|
|
160
|
+
}
|
|
161
|
+
const mutations = [];
|
|
162
|
+
for (const [key, summary] of removed) {
|
|
163
|
+
this.unreadByIdentity.delete(key);
|
|
164
|
+
mutations.push(this.mutation(summary, null));
|
|
165
|
+
}
|
|
166
|
+
if (mutations.length > 0)
|
|
167
|
+
this.schedulePersist();
|
|
168
|
+
return mutations;
|
|
169
|
+
}
|
|
170
|
+
/** Wait until all currently queued state is durably represented or throw. */
|
|
171
|
+
async flush() {
|
|
172
|
+
this.requireLoaded();
|
|
173
|
+
await this.waitForPersistenceWorker();
|
|
174
|
+
if (this.persistenceFailure === undefined
|
|
175
|
+
&& this.persistenceGeneration === this.durablePersistenceGeneration)
|
|
176
|
+
return;
|
|
177
|
+
// Retry the latest complete snapshot once. Failed/intermediate snapshots
|
|
178
|
+
// are coalesced because completion orders and revisions are cumulative.
|
|
179
|
+
this.ensurePersistenceWorker();
|
|
180
|
+
await this.waitForPersistenceWorker();
|
|
181
|
+
this.throwIfPersistenceFailed();
|
|
182
|
+
}
|
|
183
|
+
/** Snapshot safe to expose to a client that may subsequently acknowledge it. */
|
|
184
|
+
async durableCatalogSnapshot() {
|
|
185
|
+
let snapshot;
|
|
186
|
+
do {
|
|
187
|
+
await this.flush();
|
|
188
|
+
snapshot = this.catalogSnapshot();
|
|
189
|
+
} while (this.persistenceGeneration !== this.durablePersistenceGeneration);
|
|
190
|
+
return snapshot;
|
|
191
|
+
}
|
|
192
|
+
async loadPersistedState() {
|
|
193
|
+
const persistence = this.persistence;
|
|
194
|
+
if (persistence === undefined) {
|
|
195
|
+
this.loaded = true;
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
let value;
|
|
199
|
+
let resetState = false;
|
|
200
|
+
try {
|
|
201
|
+
value = await persistence.load();
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
this.reportPersistenceError("load", error);
|
|
205
|
+
if (!(error instanceof SessionUnreadPersistenceCorruptionError))
|
|
206
|
+
throw error;
|
|
207
|
+
resetState = true;
|
|
208
|
+
}
|
|
209
|
+
if (!resetState && value !== undefined) {
|
|
210
|
+
try {
|
|
211
|
+
this.installPersistedState(parsePersistedState(value));
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
this.reportPersistenceError("load", error);
|
|
215
|
+
resetState = true;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
else if (value === undefined) {
|
|
219
|
+
resetState = true;
|
|
220
|
+
}
|
|
221
|
+
if (resetState) {
|
|
222
|
+
this.resetInMemoryState();
|
|
223
|
+
// Persist even an empty epoch so the catalog identity itself survives a
|
|
224
|
+
// clean daemon restart and a corrupt file is repaired once.
|
|
225
|
+
this.schedulePersist();
|
|
226
|
+
await this.waitForPersistenceWorker();
|
|
227
|
+
try {
|
|
228
|
+
this.throwIfPersistenceFailed();
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
this.loaded = false;
|
|
232
|
+
throw error;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
this.loaded = true;
|
|
236
|
+
}
|
|
237
|
+
resetInMemoryState() {
|
|
238
|
+
this.catalogId = this.freshCatalogId();
|
|
239
|
+
this.catalogRevision = 0;
|
|
240
|
+
this.nextCompletionOrder = 0;
|
|
241
|
+
this.unreadByIdentity.clear();
|
|
242
|
+
this.activeByIdentity.clear();
|
|
243
|
+
this.excludedByIdentity.clear();
|
|
244
|
+
}
|
|
245
|
+
mutation(identity, unread) {
|
|
246
|
+
this.catalogRevision = incrementSafe(this.catalogRevision, "Session unread catalog revision exhausted");
|
|
247
|
+
return {
|
|
248
|
+
event: {
|
|
249
|
+
type: "sessions.unread",
|
|
250
|
+
catalogId: this.catalogId,
|
|
251
|
+
catalogRevision: this.catalogRevision,
|
|
252
|
+
sessionId: identity.sessionId,
|
|
253
|
+
cwd: identity.cwd,
|
|
254
|
+
unread: unread === null ? null : { ...unread },
|
|
255
|
+
},
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
trimToLimit() {
|
|
259
|
+
const mutations = [];
|
|
260
|
+
while (this.unreadByIdentity.size > SESSION_UNREAD_LIMIT) {
|
|
261
|
+
let oldestKey;
|
|
262
|
+
let oldest;
|
|
263
|
+
for (const [key, summary] of this.unreadByIdentity) {
|
|
264
|
+
if (oldest === undefined || summary.completionOrder < oldest.completionOrder) {
|
|
265
|
+
oldestKey = key;
|
|
266
|
+
oldest = summary;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (oldestKey === undefined || oldest === undefined)
|
|
270
|
+
break;
|
|
271
|
+
this.unreadByIdentity.delete(oldestKey);
|
|
272
|
+
mutations.push(this.mutation(oldest, null));
|
|
273
|
+
}
|
|
274
|
+
return mutations;
|
|
275
|
+
}
|
|
276
|
+
assertRevisionCapacity(count) {
|
|
277
|
+
if (!Number.isSafeInteger(this.catalogRevision + count)) {
|
|
278
|
+
throw new Error("Session unread catalog revision exhausted");
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
schedulePersist() {
|
|
282
|
+
if (this.persistence === undefined)
|
|
283
|
+
return;
|
|
284
|
+
const generation = incrementSafe(this.persistenceGeneration, "Session unread persistence generation exhausted");
|
|
285
|
+
this.persistenceGeneration = generation;
|
|
286
|
+
this.pendingPersistence = { generation, state: this.persistedState() };
|
|
287
|
+
// Once a save fails, mutations continue replacing the one pending snapshot
|
|
288
|
+
// but do not hammer storage; the service's backoff (or an explicit flush)
|
|
289
|
+
// owns the next retry attempt.
|
|
290
|
+
if (this.persistenceFailure === undefined)
|
|
291
|
+
this.ensurePersistenceWorker();
|
|
292
|
+
}
|
|
293
|
+
ensurePersistenceWorker() {
|
|
294
|
+
if (this.persistence === undefined || this.persistenceWorker !== undefined || this.pendingPersistence === undefined)
|
|
295
|
+
return;
|
|
296
|
+
const worker = this.runPersistenceWorker();
|
|
297
|
+
this.persistenceWorker = worker;
|
|
298
|
+
void worker.finally(() => {
|
|
299
|
+
if (this.persistenceWorker === worker)
|
|
300
|
+
this.persistenceWorker = undefined;
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
async runPersistenceWorker() {
|
|
304
|
+
const persistence = this.persistence;
|
|
305
|
+
if (persistence === undefined)
|
|
306
|
+
return;
|
|
307
|
+
while (this.pendingPersistence !== undefined) {
|
|
308
|
+
const pending = this.pendingPersistence;
|
|
309
|
+
this.pendingPersistence = undefined;
|
|
310
|
+
try {
|
|
311
|
+
await persistence.save(pending.state);
|
|
312
|
+
this.durablePersistenceGeneration = pending.generation;
|
|
313
|
+
this.persistenceFailure = undefined;
|
|
314
|
+
}
|
|
315
|
+
catch (error) {
|
|
316
|
+
// A newer pending snapshot subsumes this failed one. Otherwise retain
|
|
317
|
+
// this exact snapshot so a later flush can retry without a new mutation.
|
|
318
|
+
this.pendingPersistence ??= pending;
|
|
319
|
+
this.persistenceFailure = { error };
|
|
320
|
+
this.reportPersistenceError("save", error);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
async waitForPersistenceWorker() {
|
|
326
|
+
let worker = this.persistenceWorker;
|
|
327
|
+
while (worker !== undefined) {
|
|
328
|
+
await worker;
|
|
329
|
+
worker = this.persistenceWorker;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
throwIfPersistenceFailed() {
|
|
333
|
+
const failure = this.persistenceFailure;
|
|
334
|
+
if (failure !== undefined)
|
|
335
|
+
throw failure.error;
|
|
336
|
+
}
|
|
337
|
+
persistedState() {
|
|
338
|
+
return {
|
|
339
|
+
version: SESSION_UNREAD_STATE_VERSION,
|
|
340
|
+
catalogId: this.catalogId,
|
|
341
|
+
catalogRevision: this.catalogRevision,
|
|
342
|
+
nextCompletionOrder: this.nextCompletionOrder,
|
|
343
|
+
sessions: [...this.unreadByIdentity.values()].map((summary) => ({ ...summary })),
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
installPersistedState(state) {
|
|
347
|
+
this.catalogId = state.catalogId;
|
|
348
|
+
this.catalogRevision = state.catalogRevision;
|
|
349
|
+
this.nextCompletionOrder = state.nextCompletionOrder;
|
|
350
|
+
this.unreadByIdentity.clear();
|
|
351
|
+
for (const summary of [...state.sessions].sort((left, right) => left.completionOrder - right.completionOrder)) {
|
|
352
|
+
this.unreadByIdentity.set(sessionIdentityKey(summary), { ...summary });
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
freshCatalogId() {
|
|
356
|
+
return requireCatalogId(this.createCatalogId());
|
|
357
|
+
}
|
|
358
|
+
requireLoaded() {
|
|
359
|
+
if (!this.loaded)
|
|
360
|
+
throw new Error("Session unread store must be loaded before use");
|
|
361
|
+
}
|
|
362
|
+
reportPersistenceError(operation, error) {
|
|
363
|
+
try {
|
|
364
|
+
this.onPersistenceError(operation, error);
|
|
365
|
+
}
|
|
366
|
+
catch {
|
|
367
|
+
// Error reporting must not poison future serialized persistence work.
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
class SessionUnreadPersistenceCorruptionError extends Error {
|
|
372
|
+
constructor(cause) {
|
|
373
|
+
super("Session unread persistence contains invalid JSON", { cause });
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
export class FileSessionUnreadPersistence {
|
|
377
|
+
constructor(filePath = defaultSessionUnreadFilePath()) {
|
|
378
|
+
this.filePath = filePath;
|
|
379
|
+
}
|
|
380
|
+
async load() {
|
|
381
|
+
let source;
|
|
382
|
+
try {
|
|
383
|
+
source = await readFile(this.filePath, "utf8");
|
|
384
|
+
}
|
|
385
|
+
catch (error) {
|
|
386
|
+
if (isNodeError(error) && error.code === "ENOENT")
|
|
387
|
+
return undefined;
|
|
388
|
+
throw error;
|
|
389
|
+
}
|
|
390
|
+
try {
|
|
391
|
+
const value = JSON.parse(source);
|
|
392
|
+
return value;
|
|
393
|
+
}
|
|
394
|
+
catch (error) {
|
|
395
|
+
throw new SessionUnreadPersistenceCorruptionError(error);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
async save(state) {
|
|
399
|
+
await mkdir(dirname(this.filePath), { recursive: true });
|
|
400
|
+
const tempPath = `${this.filePath}.${process.pid.toString()}-${randomUUID()}.tmp`;
|
|
401
|
+
try {
|
|
402
|
+
await writeFile(tempPath, `${JSON.stringify(state, null, 2)}\n`, {
|
|
403
|
+
encoding: "utf8",
|
|
404
|
+
mode: SESSION_UNREAD_FILE_MODE,
|
|
405
|
+
flag: "wx",
|
|
406
|
+
});
|
|
407
|
+
await rename(tempPath, this.filePath);
|
|
408
|
+
}
|
|
409
|
+
finally {
|
|
410
|
+
await rm(tempPath, { force: true }).catch(() => undefined);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
export function defaultSessionUnreadFilePath(env = process.env, cwd = process.cwd()) {
|
|
415
|
+
return join(piWebDataDir(env, cwd), "session-unread.json");
|
|
416
|
+
}
|
|
417
|
+
function parsePersistedState(value) {
|
|
418
|
+
const record = requireRecord(value, "Session unread state must be an object");
|
|
419
|
+
if (record["version"] !== SESSION_UNREAD_STATE_VERSION)
|
|
420
|
+
throw new Error("Unsupported session unread state version");
|
|
421
|
+
const catalogId = requireCatalogId(record["catalogId"]);
|
|
422
|
+
const catalogRevision = requireNonNegativeSafeInteger(record["catalogRevision"], "catalogRevision");
|
|
423
|
+
const nextCompletionOrder = requireNonNegativeSafeInteger(record["nextCompletionOrder"], "nextCompletionOrder");
|
|
424
|
+
const rawSessions = record["sessions"];
|
|
425
|
+
if (!Array.isArray(rawSessions))
|
|
426
|
+
throw new Error("Session unread sessions must be an array");
|
|
427
|
+
if (rawSessions.length > SESSION_UNREAD_LIMIT)
|
|
428
|
+
throw new Error("Session unread state exceeds its session limit");
|
|
429
|
+
const sessions = rawSessions.map(parseSummary);
|
|
430
|
+
const identities = new Set();
|
|
431
|
+
const orders = new Set();
|
|
432
|
+
for (const summary of sessions) {
|
|
433
|
+
const key = sessionIdentityKey(summary);
|
|
434
|
+
if (identities.has(key))
|
|
435
|
+
throw new Error("Duplicate session unread identity");
|
|
436
|
+
if (orders.has(summary.completionOrder))
|
|
437
|
+
throw new Error("Duplicate session unread completion order");
|
|
438
|
+
identities.add(key);
|
|
439
|
+
orders.add(summary.completionOrder);
|
|
440
|
+
}
|
|
441
|
+
const maxOrder = sessions.reduce((maximum, summary) => Math.max(maximum, summary.completionOrder), 0);
|
|
442
|
+
if (nextCompletionOrder < maxOrder)
|
|
443
|
+
throw new Error("Session unread completion order is inconsistent");
|
|
444
|
+
if (catalogRevision < nextCompletionOrder)
|
|
445
|
+
throw new Error("Session unread catalog revision is inconsistent");
|
|
446
|
+
return {
|
|
447
|
+
version: SESSION_UNREAD_STATE_VERSION,
|
|
448
|
+
catalogId,
|
|
449
|
+
catalogRevision,
|
|
450
|
+
nextCompletionOrder,
|
|
451
|
+
sessions,
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
function parseSummary(value) {
|
|
455
|
+
const record = requireRecord(value, "Session unread summary must be an object");
|
|
456
|
+
const completedAt = requireBoundedNonEmptyString(record["completedAt"], "completedAt", SESSION_UNREAD_COMPLETED_AT_MAX_LENGTH);
|
|
457
|
+
const completedDate = new Date(completedAt);
|
|
458
|
+
if (!Number.isFinite(completedDate.getTime()) || completedDate.toISOString() !== completedAt) {
|
|
459
|
+
throw new Error("Session unread completedAt must be a canonical ISO timestamp");
|
|
460
|
+
}
|
|
461
|
+
return {
|
|
462
|
+
sessionId: requireBoundedNonEmptyString(record["sessionId"], "sessionId", SESSION_UNREAD_SESSION_ID_MAX_LENGTH),
|
|
463
|
+
cwd: requireBoundedNonEmptyString(record["cwd"], "cwd", SESSION_UNREAD_CWD_MAX_LENGTH),
|
|
464
|
+
completionOrder: requirePositiveSafeInteger(record["completionOrder"], "completionOrder"),
|
|
465
|
+
completedAt,
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
function requireRecord(value, message) {
|
|
469
|
+
if (!isRecord(value))
|
|
470
|
+
throw new Error(message);
|
|
471
|
+
return value;
|
|
472
|
+
}
|
|
473
|
+
function isRecord(value) {
|
|
474
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
475
|
+
}
|
|
476
|
+
function requireNonEmptyString(value, field) {
|
|
477
|
+
if (typeof value !== "string" || value === "")
|
|
478
|
+
throw new Error(`Session unread ${field} must be a non-empty string`);
|
|
479
|
+
return value;
|
|
480
|
+
}
|
|
481
|
+
function requireBoundedNonEmptyString(value, field, maxLength) {
|
|
482
|
+
const parsed = requireNonEmptyString(value, field);
|
|
483
|
+
if (parsed.length > maxLength)
|
|
484
|
+
throw new Error(`Session unread ${field} exceeds its length limit`);
|
|
485
|
+
return parsed;
|
|
486
|
+
}
|
|
487
|
+
function requireCatalogId(value) {
|
|
488
|
+
return requireBoundedNonEmptyString(value, "catalogId", SESSION_UNREAD_CATALOG_ID_MAX_LENGTH);
|
|
489
|
+
}
|
|
490
|
+
function requireNonNegativeSafeInteger(value, field) {
|
|
491
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
|
|
492
|
+
throw new Error(`Session unread ${field} must be a non-negative safe integer`);
|
|
493
|
+
}
|
|
494
|
+
return value;
|
|
495
|
+
}
|
|
496
|
+
function requirePositiveSafeInteger(value, field) {
|
|
497
|
+
const parsed = requireNonNegativeSafeInteger(value, field);
|
|
498
|
+
if (parsed === 0)
|
|
499
|
+
throw new Error(`Session unread ${field} must be positive`);
|
|
500
|
+
return parsed;
|
|
501
|
+
}
|
|
502
|
+
function requireIdentity(sessionId, cwd) {
|
|
503
|
+
return {
|
|
504
|
+
sessionId: requireBoundedNonEmptyString(sessionId, "sessionId", SESSION_UNREAD_SESSION_ID_MAX_LENGTH),
|
|
505
|
+
cwd: requireBoundedNonEmptyString(cwd, "cwd", SESSION_UNREAD_CWD_MAX_LENGTH),
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
function sessionIdentityKey(identity) {
|
|
509
|
+
return JSON.stringify([identity.sessionId, identity.cwd]);
|
|
510
|
+
}
|
|
511
|
+
function incrementSafe(value, message) {
|
|
512
|
+
const next = value + 1;
|
|
513
|
+
if (!Number.isSafeInteger(next))
|
|
514
|
+
throw new Error(message);
|
|
515
|
+
return next;
|
|
516
|
+
}
|
|
517
|
+
function isNodeError(error) {
|
|
518
|
+
return error instanceof Error && "code" in error;
|
|
519
|
+
}
|
|
520
|
+
//# sourceMappingURL=sessionUnreadStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionUnreadStore.js","sourceRoot":"","sources":["../../../src/server/sessions/sessionUnreadStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,8 +18,8 @@ export function createSpawnSessionToolDefinition(spawningCwd, deps) {
|
|
|
18
18
|
return defineTool({
|
|
19
19
|
name: "spawn_session",
|
|
20
20
|
label: "Spawn session",
|
|
21
|
-
description: "Start a
|
|
22
|
-
promptSnippet: "spawn_session:
|
|
21
|
+
description: "Start a fully independent session; its transcript and results are unavailable here. Use only when the user or active workflow explicitly requests a separate session.",
|
|
22
|
+
promptSnippet: "spawn_session: independent session; results unavailable here; explicit requests only",
|
|
23
23
|
parameters: SpawnSessionParams,
|
|
24
24
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
25
25
|
// Failures throw: the agent loop turns the thrown message into an error
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawnSessionTool.js","sourceRoot":"","sources":["../../../src/server/sessions/spawnSessionTool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAyB,MAAM,iCAAiC,CAAC;AAuBpF,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAAC;IACrC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;QAClB,WAAW,EAAE,gIAAgI;KAC9I,CAAC;IACF,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QAC7B,WAAW,EAAE,mKAAmK;KACjL,CAAC,CAAC;CACJ,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,UAAU,gCAAgC,CAAC,WAAmB,EAAE,IAA0B;IAC9F,OAAO,UAAU,CAAqD;QACpE,IAAI,EAAE,eAAe;QACrB,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"spawnSessionTool.js","sourceRoot":"","sources":["../../../src/server/sessions/spawnSessionTool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAyB,MAAM,iCAAiC,CAAC;AAuBpF,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAAC;IACrC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;QAClB,WAAW,EAAE,gIAAgI;KAC9I,CAAC;IACF,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QAC7B,WAAW,EAAE,mKAAmK;KACjL,CAAC,CAAC;CACJ,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,UAAU,gCAAgC,CAAC,WAAmB,EAAE,IAA0B;IAC9F,OAAO,UAAU,CAAqD;QACpE,IAAI,EAAE,eAAe;QACrB,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,uKAAuK;QACpL,aAAa,EAAE,sFAAsF;QACrG,UAAU,EAAE,kBAAkB;QAC9B,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG;YACxD,wEAAwE;YACxE,2EAA2E;YAC3E,sCAAsC;YACtC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC;gBAC9B,WAAW;gBACX,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,GAAG,EAAE,MAAM,CAAC,GAAG;gBACf,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;aACzD,CAAC,CAAC;YACH,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,+BAA+B,MAAM,CAAC,SAAS,OAAO,MAAM,CAAC,GAAG,GAAG,EAAE,CAAC;gBACtG,OAAO,EAAE,MAAM;aAChB,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -44,7 +44,7 @@ function statusLine(summary) {
|
|
|
44
44
|
return `- ${summary.sessionId} [${summary.status}] in ${summary.cwd}`;
|
|
45
45
|
}
|
|
46
46
|
function workingInspectionGuidance(sessionId) {
|
|
47
|
-
return `Subsession ${sessionId} is working; partial output is withheld. Continue
|
|
47
|
+
return `Subsession ${sessionId} is working; partial output is withheld. Continue other work, or call yield_to_subsessions alone and last at the join point. Completion notices wake you; do not poll.`;
|
|
48
48
|
}
|
|
49
49
|
function renderEntry(entry) {
|
|
50
50
|
const header = `#${String(entry.index)} ${entry.role}`;
|
|
@@ -96,18 +96,18 @@ function renderTranscript(result) {
|
|
|
96
96
|
* Tools that let an agent spawn *tracked* child sessions, inspect them, and
|
|
97
97
|
* explicitly yield at a join point.
|
|
98
98
|
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
99
|
+
* A subsession records its parent in its session header, the parent is notified
|
|
100
|
+
* when it stops working, and the parent may read its transcript/result. The
|
|
101
|
+
* tools are constructed per-session, carrying the spawning cwd for
|
|
102
|
+
* project-scope validation; the parent's identity is taken from the live
|
|
103
|
+
* extension context at call time.
|
|
104
104
|
*/
|
|
105
105
|
export function createSubsessionToolDefinitions(spawningCwd, deps) {
|
|
106
106
|
const spawnTool = defineTool({
|
|
107
107
|
name: "spawn_subsession",
|
|
108
108
|
label: "Spawn subsession",
|
|
109
|
-
description: "Start a tracked child
|
|
110
|
-
promptSnippet: "spawn_subsession: tracked
|
|
109
|
+
description: "Start a tracked child session to carry out part of the current task and return immediately. Its transcript and result are available here after it finishes.",
|
|
110
|
+
promptSnippet: "spawn_subsession: tracked child work for the current task; result available after completion",
|
|
111
111
|
parameters: SpawnSubsessionParams,
|
|
112
112
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
113
113
|
const parentSessionId = ctx.sessionManager.getSessionId();
|
|
@@ -121,7 +121,7 @@ export function createSubsessionToolDefinitions(spawningCwd, deps) {
|
|
|
121
121
|
...(ctx.model === undefined ? {} : { model: ctx.model }),
|
|
122
122
|
});
|
|
123
123
|
return {
|
|
124
|
-
content: [{ type: "text", text: `Started tracked subsession ${result.sessionId} in ${result.cwd}. Continue
|
|
124
|
+
content: [{ type: "text", text: `Started tracked subsession ${result.sessionId} in ${result.cwd}. Continue other work, then join with yield_to_subsessions; do not poll.` }],
|
|
125
125
|
details: result,
|
|
126
126
|
};
|
|
127
127
|
},
|
|
@@ -188,9 +188,7 @@ export function createSubsessionToolDefinitions(spawningCwd, deps) {
|
|
|
188
188
|
description: "At a join point, end this run while tracked children work; completion notices wake you. If none work, continue. Call alone and last; do not poll.",
|
|
189
189
|
promptSnippet: "yield_to_subsessions: end the run at a join point; call alone and last",
|
|
190
190
|
promptGuidelines: [
|
|
191
|
-
"After
|
|
192
|
-
"Call alone and last; a mixed tool batch may continue the run.",
|
|
193
|
-
"Completion notices wake you; do not poll inspection tools.",
|
|
191
|
+
"After calling spawn_subsession, you can continue with other work. At the join point, call yield_to_subsessions alone and last; completion notices wake you, so do not poll.",
|
|
194
192
|
],
|
|
195
193
|
parameters: YieldToSubsessionsParams,
|
|
196
194
|
async execute(_toolCallId, _params, _signal, _onUpdate, ctx) {
|