clay-server 4.3.0-beta.6 → 4.3.0-beta.7
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/lib/sessions.js +40 -22
- package/package.json +1 -1
package/lib/sessions.js
CHANGED
|
@@ -144,17 +144,32 @@ function createSessionManager(opts) {
|
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
function sessionFilePath(
|
|
148
|
-
return path.join(sessionsDir,
|
|
147
|
+
function sessionFilePath(recordId) {
|
|
148
|
+
return path.join(sessionsDir, recordId + ".jsonl");
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// A Clay record must exist before a provider assigns its resumable id.
|
|
152
|
+
// Existing records keep their filename; fresh provider-less sessions use
|
|
153
|
+
// the already durable origin id and later store cliSessionId as metadata.
|
|
154
|
+
function sessionRecordId(session) {
|
|
155
|
+
if (!session) return null;
|
|
156
|
+
return session._sessionRecordId || session.cliSessionId || session.sessionOriginId || null;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function existingSessionRecordId(session) {
|
|
160
|
+
if (!session) return null;
|
|
161
|
+
return session._sessionRecordId || session.cliSessionId || null;
|
|
149
162
|
}
|
|
150
163
|
|
|
151
164
|
function saveSessionFile(session) {
|
|
152
|
-
if (!session.cliSessionId) return false;
|
|
153
165
|
try {
|
|
166
|
+
var provenanceMeta = sessionProvenance.metadata(session);
|
|
167
|
+
var recordId = sessionRecordId(session);
|
|
168
|
+
if (!recordId) return false;
|
|
154
169
|
var metaObj = {
|
|
155
170
|
type: "meta",
|
|
156
171
|
localId: session.localId,
|
|
157
|
-
cliSessionId: session.cliSessionId,
|
|
172
|
+
cliSessionId: session.cliSessionId || null,
|
|
158
173
|
title: session.title,
|
|
159
174
|
titleProvisional: session.titleProvisional === true,
|
|
160
175
|
titleAutoGenerated: session.titleAutoGenerated === true,
|
|
@@ -204,7 +219,6 @@ function createSessionManager(opts) {
|
|
|
204
219
|
if (session.homeDebateInitialTopic) metaObj.homeDebateInitialTopic = session.homeDebateInitialTopic;
|
|
205
220
|
if (session.homeClayEntryRequestId) metaObj.homeClayEntryRequestId = session.homeClayEntryRequestId;
|
|
206
221
|
if (session.homeClayEntryMode) metaObj.homeClayEntryMode = session.homeClayEntryMode;
|
|
207
|
-
var provenanceMeta = sessionProvenance.metadata(session);
|
|
208
222
|
metaObj.sessionOriginId = provenanceMeta.sessionOriginId;
|
|
209
223
|
if (provenanceMeta.sessionProvenance) metaObj.sessionProvenance = provenanceMeta.sessionProvenance;
|
|
210
224
|
if (Array.isArray(session._workerGenerations)) metaObj.workerGenerations = session._workerGenerations;
|
|
@@ -213,7 +227,7 @@ function createSessionManager(opts) {
|
|
|
213
227
|
for (var i = 0; i < session.history.length; i++) {
|
|
214
228
|
lines.push(JSON.stringify(session.history[i]));
|
|
215
229
|
}
|
|
216
|
-
var sfPath = sessionFilePath(
|
|
230
|
+
var sfPath = sessionFilePath(recordId);
|
|
217
231
|
// Atomic write: write to temp file then rename, so a crash mid-write
|
|
218
232
|
// cannot leave a truncated/corrupted session file.
|
|
219
233
|
var tmpPath = sfPath + ".tmp." + process.pid;
|
|
@@ -222,6 +236,7 @@ function createSessionManager(opts) {
|
|
|
222
236
|
try { fs.chmodSync(tmpPath, 0o600); } catch (chmodErr) {}
|
|
223
237
|
}
|
|
224
238
|
fs.renameSync(tmpPath, sfPath);
|
|
239
|
+
session._sessionRecordId = recordId;
|
|
225
240
|
return true;
|
|
226
241
|
} catch(e) {
|
|
227
242
|
console.error("[session] Failed to save session file:", e.message);
|
|
@@ -230,10 +245,11 @@ function createSessionManager(opts) {
|
|
|
230
245
|
}
|
|
231
246
|
|
|
232
247
|
function appendToSessionFile(session, obj) {
|
|
233
|
-
|
|
248
|
+
var recordId = existingSessionRecordId(session);
|
|
249
|
+
if (!recordId) return true;
|
|
234
250
|
session.lastActivity = Date.now();
|
|
235
251
|
try {
|
|
236
|
-
var afPath = sessionFilePath(
|
|
252
|
+
var afPath = sessionFilePath(recordId);
|
|
237
253
|
fs.appendFileSync(afPath, JSON.stringify(obj) + "\n");
|
|
238
254
|
if (process.platform !== "win32") {
|
|
239
255
|
try { fs.chmodSync(afPath, 0o600); } catch (chmodErr) {}
|
|
@@ -276,7 +292,8 @@ function createSessionManager(opts) {
|
|
|
276
292
|
|
|
277
293
|
var meta;
|
|
278
294
|
try { meta = JSON.parse(lines[0]); } catch { continue; }
|
|
279
|
-
|
|
295
|
+
var pendingOrigin = typeof meta.sessionOriginId === "string" && meta.sessionOriginId.trim() && meta.sessionOriginId.length <= 128;
|
|
296
|
+
if (meta.type !== "meta" || (!meta.cliSessionId && !pendingOrigin)) continue;
|
|
280
297
|
|
|
281
298
|
var history = [];
|
|
282
299
|
for (var j = 1; j < lines.length; j++) {
|
|
@@ -285,7 +302,7 @@ function createSessionManager(opts) {
|
|
|
285
302
|
|
|
286
303
|
var fileMtime = 0;
|
|
287
304
|
try { fileMtime = fs.statSync(path.join(sessionsDir, files[i])).mtimeMs; } catch {}
|
|
288
|
-
loaded.push({ meta: meta, history: history, mtime: fileMtime });
|
|
305
|
+
loaded.push({ meta: meta, history: history, mtime: fileMtime, recordId: files[i].slice(0, -".jsonl".length) });
|
|
289
306
|
}
|
|
290
307
|
|
|
291
308
|
loaded.sort(function(a, b) { return a.meta.createdAt - b.meta.createdAt; });
|
|
@@ -310,6 +327,7 @@ function createSessionManager(opts) {
|
|
|
310
327
|
queryInstance: null,
|
|
311
328
|
messageQueue: null,
|
|
312
329
|
cliSessionId: m.cliSessionId,
|
|
330
|
+
_sessionRecordId: loaded[i].recordId,
|
|
313
331
|
blocks: {},
|
|
314
332
|
sentToolResults: {},
|
|
315
333
|
pendingPermissions: {},
|
|
@@ -388,7 +406,7 @@ function createSessionManager(opts) {
|
|
|
388
406
|
saveSessionFile(session);
|
|
389
407
|
try {
|
|
390
408
|
var preservedTime = new Date(activityTime);
|
|
391
|
-
fs.utimesSync(sessionFilePath(session
|
|
409
|
+
fs.utimesSync(sessionFilePath(sessionRecordId(session)), preservedTime, preservedTime);
|
|
392
410
|
} catch (e) {}
|
|
393
411
|
delete session._provenanceMigrationNeeded;
|
|
394
412
|
});
|
|
@@ -917,10 +935,9 @@ function createSessionManager(opts) {
|
|
|
917
935
|
session.worker = null;
|
|
918
936
|
}
|
|
919
937
|
|
|
920
|
-
if (session.cliSessionId)
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
}
|
|
938
|
+
if (session.cliSessionId) rememberDeletedCliSession(session.cliSessionId);
|
|
939
|
+
var recordId = existingSessionRecordId(session);
|
|
940
|
+
if (recordId) try { fs.unlinkSync(sessionFilePath(recordId)); } catch(e) {}
|
|
924
941
|
|
|
925
942
|
sessions.delete(localId);
|
|
926
943
|
try { onSessionDeleted(localId, session); } catch (e) {
|
|
@@ -964,10 +981,9 @@ function createSessionManager(opts) {
|
|
|
964
981
|
try { session.worker.kill(); } catch(e) {}
|
|
965
982
|
session.worker = null;
|
|
966
983
|
}
|
|
967
|
-
if (session.cliSessionId)
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
}
|
|
984
|
+
if (session.cliSessionId) rememberDeletedCliSession(session.cliSessionId);
|
|
985
|
+
var recordId = existingSessionRecordId(session);
|
|
986
|
+
if (recordId) try { fs.unlinkSync(sessionFilePath(recordId)); } catch(e) {}
|
|
971
987
|
sessions.delete(localId);
|
|
972
988
|
try { onSessionDeleted(localId, session); } catch (e) {
|
|
973
989
|
console.error("[session] Session deletion hook failed:", e.message || e);
|
|
@@ -1093,7 +1109,8 @@ function createSessionManager(opts) {
|
|
|
1093
1109
|
}
|
|
1094
1110
|
|
|
1095
1111
|
function sendAndRecordDurably(session, obj, clientObj) {
|
|
1096
|
-
|
|
1112
|
+
var recordId = existingSessionRecordId(session);
|
|
1113
|
+
if (!recordId || !fs.existsSync(sessionFilePath(recordId))) return false;
|
|
1097
1114
|
var saved;
|
|
1098
1115
|
try { saved = doSendAndRecord(session, obj, clientObj); }
|
|
1099
1116
|
catch (error) {
|
|
@@ -1107,9 +1124,10 @@ function createSessionManager(opts) {
|
|
|
1107
1124
|
}
|
|
1108
1125
|
|
|
1109
1126
|
function hasDurableSessionRecord(session, predicate) {
|
|
1110
|
-
|
|
1127
|
+
var recordId = existingSessionRecordId(session);
|
|
1128
|
+
if (!recordId || typeof predicate !== "function") return false;
|
|
1111
1129
|
try {
|
|
1112
|
-
var lines = fs.readFileSync(sessionFilePath(
|
|
1130
|
+
var lines = fs.readFileSync(sessionFilePath(recordId), "utf8").split("\n");
|
|
1113
1131
|
for (var i = lines.length - 1; i >= 0; i--) {
|
|
1114
1132
|
if (!lines[i]) continue;
|
|
1115
1133
|
try { if (predicate(JSON.parse(lines[i]))) return true; } catch (error) {}
|
package/package.json
CHANGED