@moxxy/core 0.5.3 → 0.5.4
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/run-turn.d.ts.map +1 -1
- package/dist/run-turn.js +4 -1
- package/dist/run-turn.js.map +1 -1
- package/dist/sessions/persistence.d.ts +19 -0
- package/dist/sessions/persistence.d.ts.map +1 -1
- package/dist/sessions/persistence.js +179 -15
- package/dist/sessions/persistence.js.map +1 -1
- package/package.json +2 -2
- package/src/run-turn.test.ts +46 -0
- package/src/run-turn.ts +4 -1
- package/src/sessions/persistence.test.ts +307 -0
- package/src/sessions/persistence.ts +182 -15
package/dist/run-turn.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-turn.d.ts","sourceRoot":"","sources":["../src/run-turn.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA0C,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACrG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAM3D,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,wBAAuB,OAAO,CAC5B,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,cAAmB,GACxB,aAAa,CAAC,UAAU,CAAC,
|
|
1
|
+
{"version":3,"file":"run-turn.d.ts","sourceRoot":"","sources":["../src/run-turn.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA0C,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACrG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAM3D,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,wBAAuB,OAAO,CAC5B,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,cAAmB,GACxB,aAAa,CAAC,UAAU,CAAC,CAyL3B;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAIpC"}
|
package/dist/run-turn.js
CHANGED
|
@@ -49,7 +49,10 @@ export async function* runTurn(session, prompt, opts = {}) {
|
|
|
49
49
|
let model;
|
|
50
50
|
try {
|
|
51
51
|
provider = session.providers.getActive();
|
|
52
|
-
|
|
52
|
+
// Sticky model: prefer the explicit per-turn model, then the session's
|
|
53
|
+
// last-resolved model (so a conversation keeps the model it was using
|
|
54
|
+
// across turns), then the active provider's default.
|
|
55
|
+
const resolvedModel = opts.model ?? session.lastResolvedModel ?? provider.models[0]?.id;
|
|
53
56
|
if (!resolvedModel) {
|
|
54
57
|
throw new Error(`Active provider '${provider.name}' has no models configured`);
|
|
55
58
|
}
|
package/dist/run-turn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-turn.js","sourceRoot":"","sources":["../src/run-turn.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAOvD,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,OAAO,CAC5B,OAAuB,EACvB,MAAc,EACd,OAAuB,EAAE;IAEzB,0EAA0E;IAC1E,wEAAwE;IACxE,yEAAyE;IACzE,yEAAyE;IACzE,oCAAoC;IACpC,6EAA6E;IAC7E,uEAAuE;IACvE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC;IAEzD,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAsB,EAAE,CAAC;IACtC,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,aAAa,GAAY,IAAI,CAAC;IAClC,yEAAyE;IACzE,sEAAsE;IACtE,IAAI,mBAAmB,GAAkB,IAAI,CAAC;IAE9C,MAAM,IAAI,GAAG,GAAS,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC;IAC7C,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE;QAClD,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM;YAAE,OAAO;QACpC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClB,IAAI,EAAE,CAAC;IACT,CAAC,CAAC,CAAC;IAEH,6EAA6E;IAC7E,4EAA4E;IAC5E,2EAA2E;IAC3E,8EAA8E;IAC9E,qBAAqB;IACrB,MAAM,cAAc,GAAG,IAAI,eAAe,EAAE,CAAC;IAC7C,IAAI,eAAe,GAAyB,IAAI,CAAC;IAEjD,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;YACvB,IAAI,EAAE,aAAa;YACnB,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,MAAM;YACN,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,MAAM;YACZ,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;gBACjD,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE;gBACnC,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,CAAC;QAEH,6DAA6D;QAC7D,qEAAqE;QACrE,2EAA2E;QAC3E,mDAAmD;QACnD,IAAI,QAAqB,CAAC;QAC1B,IAAI,KAAa,CAAC;QAClB,IAAI,CAAC;YACH,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC;YACzC,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"run-turn.js","sourceRoot":"","sources":["../src/run-turn.ts"],"names":[],"mappings":"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"}
|
|
@@ -246,6 +246,25 @@ export declare function readEventPage(sessionId: string, opts: {
|
|
|
246
246
|
* / append order); `before`/`limit` follow {@link readEventPage}.
|
|
247
247
|
*/
|
|
248
248
|
export declare function pageEvents(events: ReadonlyArray<MoxxyEvent>, before: number | null, limit: number): EventPage;
|
|
249
|
+
/**
|
|
250
|
+
* Seed a session's event log from an external event list IFF the session has no
|
|
251
|
+
* log on disk yet. This is the migration that makes the runner's authoritative
|
|
252
|
+
* log the home of a chat whose history previously lived ONLY in a thin client's
|
|
253
|
+
* own mirror (the desktop's NDJSON chat store) — after it runs, `loadHistory`
|
|
254
|
+
* serves that chat from the runner like any other.
|
|
255
|
+
*
|
|
256
|
+
* Idempotent and NON-destructive: if `<sessionId>.jsonl` already exists AND is
|
|
257
|
+
* NON-EMPTY this is a no-op returning `false`, so a session the runner already
|
|
258
|
+
* owns is NEVER overwritten. A 0-byte log IS seeded: `persistence.attach`
|
|
259
|
+
* creates an empty `<id>.jsonl` on every spawn (even a session with zero
|
|
260
|
+
* events), so an existence-only guard would skip exactly the legacy chats this
|
|
261
|
+
* migration targets — and an empty file holds no history, so seeding over it
|
|
262
|
+
* loses nothing. Events are re-sequenced to contiguous `seq` 0..n-1 (order + ids
|
|
263
|
+
* preserved) so the seeded log satisfies {@link EventLog}'s seq invariants when
|
|
264
|
+
* it is later restored. Written temp+rename so a crash mid-seed can't leave a
|
|
265
|
+
* half-written log. Returns `true` iff it wrote the log.
|
|
266
|
+
*/
|
|
267
|
+
export declare function seedSessionLog(sessionId: string, events: ReadonlyArray<MoxxyEvent>, dir?: string): Promise<boolean>;
|
|
249
268
|
/**
|
|
250
269
|
* Remove a session's log file and its sidecar. A leftover legacy `index.json`
|
|
251
270
|
* row, if any, is harmless — `readIndex` filters out sessions whose `.jsonl` is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../src/sessions/persistence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;
|
|
1
|
+
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../src/sessions/persistence.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,14 +15,13 @@
|
|
|
15
15
|
* a legacy `index.json`, if present, for back-compat). JSONL appends are
|
|
16
16
|
* best-effort (lose at most the last in-flight event on a crash).
|
|
17
17
|
*/
|
|
18
|
-
import { promises as fs } from 'node:fs';
|
|
19
|
-
import * as os from 'node:os';
|
|
18
|
+
import { constants as fsConstants, promises as fs } from 'node:fs';
|
|
20
19
|
import * as path from 'node:path';
|
|
21
20
|
import { createMutex } from '@moxxy/sdk';
|
|
22
|
-
import { writeFileAtomic } from '@moxxy/sdk/server';
|
|
21
|
+
import { moxxyPath, writeFileAtomic } from '@moxxy/sdk/server';
|
|
23
22
|
import { createLogger } from '../logger.js';
|
|
24
23
|
export function defaultSessionsDir() {
|
|
25
|
-
return
|
|
24
|
+
return moxxyPath('sessions');
|
|
26
25
|
}
|
|
27
26
|
/**
|
|
28
27
|
* Session ids are ULIDs internally, but `restoreEvents`/`readEventPage`/
|
|
@@ -201,6 +200,16 @@ export class SessionPersistence {
|
|
|
201
200
|
this.scheduleIndexWrite();
|
|
202
201
|
}
|
|
203
202
|
enqueueAppend(event) {
|
|
203
|
+
const ownedEvent = eventForSession(event, this.id);
|
|
204
|
+
if (!ownedEvent) {
|
|
205
|
+
this.logger.warn('session persistence ignored foreign-session event', {
|
|
206
|
+
path: this.logPath,
|
|
207
|
+
sessionId: this.id,
|
|
208
|
+
eventId: event.id,
|
|
209
|
+
eventSessionId: event.sessionId,
|
|
210
|
+
});
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
204
213
|
// Update in-memory meta synchronously so multiple events in the
|
|
205
214
|
// same tick share one debounced index write.
|
|
206
215
|
this.meta = {
|
|
@@ -208,10 +217,11 @@ export class SessionPersistence {
|
|
|
208
217
|
eventCount: this.meta.eventCount + 1,
|
|
209
218
|
lastActivity: new Date().toISOString(),
|
|
210
219
|
firstPrompt: this.meta.firstPrompt ??
|
|
211
|
-
(
|
|
220
|
+
(ownedEvent.type === 'user_prompt' ? firstPromptLabel(ownedEvent.text) : null),
|
|
221
|
+
...providerHeaderFromEvent(ownedEvent),
|
|
212
222
|
};
|
|
213
223
|
this.scheduleIndexWrite();
|
|
214
|
-
const line = JSON.stringify(
|
|
224
|
+
const line = JSON.stringify(ownedEvent) + '\n';
|
|
215
225
|
// Never propagate a write error into the listener chain — but never
|
|
216
226
|
// swallow it silently either: the JSONL is the session's source of
|
|
217
227
|
// truth, so a failing disk must at least be loud.
|
|
@@ -390,9 +400,72 @@ export async function readIndex(dir = defaultSessionsDir()) {
|
|
|
390
400
|
return false;
|
|
391
401
|
}
|
|
392
402
|
});
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
403
|
+
const present = metas.filter((_, index) => checks[index]);
|
|
404
|
+
const hydrated = await mapWithConcurrency(present, READ_INDEX_CONCURRENCY, (meta) => hydrateMetaFirstPrompt(meta, dir));
|
|
405
|
+
return hydrated.sort((a, b) => b.lastActivity.localeCompare(a.lastActivity));
|
|
406
|
+
}
|
|
407
|
+
async function hydrateMetaFirstPrompt(meta, dir) {
|
|
408
|
+
const stats = await matchingSessionStatsFromLog(meta.id, path.join(dir, `${meta.id}.jsonl`));
|
|
409
|
+
if (!stats)
|
|
410
|
+
return meta;
|
|
411
|
+
if (stats.parsedEvents === 0)
|
|
412
|
+
return meta;
|
|
413
|
+
return {
|
|
414
|
+
...meta,
|
|
415
|
+
eventCount: stats.eventCount,
|
|
416
|
+
firstPrompt: stats.firstPrompt,
|
|
417
|
+
provider: stats.provider ?? meta.provider,
|
|
418
|
+
model: stats.model ?? meta.model,
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
async function matchingSessionStatsFromLog(sessionId, logPath) {
|
|
422
|
+
let raw;
|
|
423
|
+
try {
|
|
424
|
+
raw = await fs.readFile(logPath, 'utf8');
|
|
425
|
+
}
|
|
426
|
+
catch {
|
|
427
|
+
return null;
|
|
428
|
+
}
|
|
429
|
+
let eventCount = 0;
|
|
430
|
+
let parsedEvents = 0;
|
|
431
|
+
let firstPrompt = null;
|
|
432
|
+
let provider = null;
|
|
433
|
+
let model = null;
|
|
434
|
+
for (const line of raw.split('\n')) {
|
|
435
|
+
if (!line.trim())
|
|
436
|
+
continue;
|
|
437
|
+
try {
|
|
438
|
+
const event = JSON.parse(line);
|
|
439
|
+
parsedEvents += 1;
|
|
440
|
+
if (!eventBelongsToSession(event, sessionId))
|
|
441
|
+
continue;
|
|
442
|
+
eventCount += 1;
|
|
443
|
+
if (firstPrompt === null && event.type === 'user_prompt') {
|
|
444
|
+
// Mirror the write-time label (SessionPersistence.enqueueAppend):
|
|
445
|
+
// code-point-aware slice + non-string coercion, so a hydrated index row
|
|
446
|
+
// matches the meta the live append wrote (no surrogate split, never null
|
|
447
|
+
// for a present prompt).
|
|
448
|
+
firstPrompt = firstPromptLabel(event.text);
|
|
449
|
+
}
|
|
450
|
+
const header = providerHeaderFromEvent(event);
|
|
451
|
+
if (header.provider !== undefined)
|
|
452
|
+
provider = header.provider;
|
|
453
|
+
if (header.model !== undefined)
|
|
454
|
+
model = header.model;
|
|
455
|
+
}
|
|
456
|
+
catch {
|
|
457
|
+
// A corrupt line should not hide a later valid prompt.
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
return { eventCount, firstPrompt, parsedEvents, provider, model };
|
|
461
|
+
}
|
|
462
|
+
function providerHeaderFromEvent(event) {
|
|
463
|
+
if (event.type !== 'provider_request' && event.type !== 'provider_response')
|
|
464
|
+
return {};
|
|
465
|
+
return {
|
|
466
|
+
provider: event.provider,
|
|
467
|
+
model: event.model,
|
|
468
|
+
};
|
|
396
469
|
}
|
|
397
470
|
/**
|
|
398
471
|
* Restore a previously-persisted session's events. Returns the full
|
|
@@ -430,11 +503,22 @@ export async function restoreEvents(sessionId, dir = defaultSessionsDir(), logge
|
|
|
430
503
|
}
|
|
431
504
|
const events = [];
|
|
432
505
|
let corruptLines = 0;
|
|
506
|
+
let foreignEvents = 0;
|
|
507
|
+
let normalizedSessionIds = 0;
|
|
433
508
|
for (const line of raw.split('\n')) {
|
|
434
509
|
if (!line.trim())
|
|
435
510
|
continue;
|
|
436
511
|
try {
|
|
437
|
-
|
|
512
|
+
const event = JSON.parse(line);
|
|
513
|
+
const ownedEvent = eventForSession(event, sessionId);
|
|
514
|
+
if (ownedEvent) {
|
|
515
|
+
if (ownedEvent !== event)
|
|
516
|
+
normalizedSessionIds += 1;
|
|
517
|
+
events.push(ownedEvent);
|
|
518
|
+
}
|
|
519
|
+
else {
|
|
520
|
+
foreignEvents += 1;
|
|
521
|
+
}
|
|
438
522
|
}
|
|
439
523
|
catch {
|
|
440
524
|
corruptLines += 1;
|
|
@@ -449,17 +533,37 @@ export async function restoreEvents(sessionId, dir = defaultSessionsDir(), logge
|
|
|
449
533
|
resequenced += 1;
|
|
450
534
|
}
|
|
451
535
|
}
|
|
452
|
-
if (corruptLines > 0 || resequenced > 0) {
|
|
453
|
-
|
|
536
|
+
if (corruptLines > 0 || resequenced > 0 || foreignEvents > 0 || normalizedSessionIds > 0) {
|
|
537
|
+
const message = foreignEvents > 0
|
|
538
|
+
? 'session log restored with foreign-session events removed — re-sequenced to keep full history replayable'
|
|
539
|
+
: 'session log restored with gaps — re-sequenced to keep full history replayable';
|
|
540
|
+
logger.warn(message, {
|
|
454
541
|
sessionId,
|
|
455
542
|
path: logPath,
|
|
456
543
|
corruptLines,
|
|
544
|
+
foreignEvents,
|
|
545
|
+
normalizedSessionIds,
|
|
457
546
|
resequencedEvents: resequenced,
|
|
458
547
|
restoredEvents: events.length,
|
|
459
548
|
});
|
|
549
|
+
let canRewrite = true;
|
|
550
|
+
if (foreignEvents > 0) {
|
|
551
|
+
try {
|
|
552
|
+
await backupForeignSessionLog(logPath);
|
|
553
|
+
}
|
|
554
|
+
catch (err) {
|
|
555
|
+
canRewrite = false;
|
|
556
|
+
logger.warn('failed to backup foreign-session log before repair', {
|
|
557
|
+
sessionId,
|
|
558
|
+
path: logPath,
|
|
559
|
+
error: err instanceof Error ? err.message : String(err),
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
}
|
|
460
563
|
try {
|
|
461
|
-
// Conflict guard: only rewrite if
|
|
462
|
-
//
|
|
564
|
+
// Conflict guard: only rewrite if (a) a foreign-session backup didn't
|
|
565
|
+
// fail (`canRewrite`) and (b) the on-disk content still matches what we
|
|
566
|
+
// read. Another process (a desktop runner already attached + a CLI
|
|
463
567
|
// `resume` of the SAME id) may have appended/repaired between our read and
|
|
464
568
|
// this write; its appends are a newer snapshot than our re-sequenced one,
|
|
465
569
|
// and a blind `writeFileAtomic` would clobber them (silent history loss).
|
|
@@ -468,7 +572,10 @@ export async function restoreEvents(sessionId, dir = defaultSessionsDir(), logge
|
|
|
468
572
|
// rewrite. Restore still succeeds either way — the in-memory log is
|
|
469
573
|
// already repaired; only the next clean resume would re-run the repair.
|
|
470
574
|
const current = await fs.readFile(logPath, 'utf8').catch(() => null);
|
|
471
|
-
if (
|
|
575
|
+
if (!canRewrite) {
|
|
576
|
+
/* foreign-session backup failed — skip the destructive rewrite */
|
|
577
|
+
}
|
|
578
|
+
else if (current !== raw) {
|
|
472
579
|
logger.warn('skipped repaired-log rewrite — file changed under us (another process attached?)', {
|
|
473
580
|
sessionId,
|
|
474
581
|
path: logPath,
|
|
@@ -591,6 +698,63 @@ export function pageEvents(events, before, limit) {
|
|
|
591
698
|
const prevCursor = start <= 0 ? null : page[0].seq;
|
|
592
699
|
return { events: page, prevCursor };
|
|
593
700
|
}
|
|
701
|
+
/**
|
|
702
|
+
* Seed a session's event log from an external event list IFF the session has no
|
|
703
|
+
* log on disk yet. This is the migration that makes the runner's authoritative
|
|
704
|
+
* log the home of a chat whose history previously lived ONLY in a thin client's
|
|
705
|
+
* own mirror (the desktop's NDJSON chat store) — after it runs, `loadHistory`
|
|
706
|
+
* serves that chat from the runner like any other.
|
|
707
|
+
*
|
|
708
|
+
* Idempotent and NON-destructive: if `<sessionId>.jsonl` already exists AND is
|
|
709
|
+
* NON-EMPTY this is a no-op returning `false`, so a session the runner already
|
|
710
|
+
* owns is NEVER overwritten. A 0-byte log IS seeded: `persistence.attach`
|
|
711
|
+
* creates an empty `<id>.jsonl` on every spawn (even a session with zero
|
|
712
|
+
* events), so an existence-only guard would skip exactly the legacy chats this
|
|
713
|
+
* migration targets — and an empty file holds no history, so seeding over it
|
|
714
|
+
* loses nothing. Events are re-sequenced to contiguous `seq` 0..n-1 (order + ids
|
|
715
|
+
* preserved) so the seeded log satisfies {@link EventLog}'s seq invariants when
|
|
716
|
+
* it is later restored. Written temp+rename so a crash mid-seed can't leave a
|
|
717
|
+
* half-written log. Returns `true` iff it wrote the log.
|
|
718
|
+
*/
|
|
719
|
+
export async function seedSessionLog(sessionId, events, dir = defaultSessionsDir()) {
|
|
720
|
+
if (events.length === 0)
|
|
721
|
+
return false;
|
|
722
|
+
const logPath = path.join(dir, `${sessionId}.jsonl`);
|
|
723
|
+
try {
|
|
724
|
+
// A non-empty log is a session the runner already owns → never overwrite.
|
|
725
|
+
// A 0-byte log is the empty file attach() left behind → seed over it.
|
|
726
|
+
if ((await fs.stat(logPath)).size > 0)
|
|
727
|
+
return false;
|
|
728
|
+
}
|
|
729
|
+
catch {
|
|
730
|
+
/* no log yet → seed below */
|
|
731
|
+
}
|
|
732
|
+
await fs.mkdir(dir, { recursive: true });
|
|
733
|
+
const reseq = events.map((e, i) => (e.seq === i ? e : { ...e, seq: i }));
|
|
734
|
+
await writeFileAtomic(logPath, reseq.map((e) => JSON.stringify(e) + '\n').join(''));
|
|
735
|
+
return true;
|
|
736
|
+
}
|
|
737
|
+
function eventBelongsToSession(event, sessionId) {
|
|
738
|
+
const eventSessionId = event.sessionId;
|
|
739
|
+
return eventSessionId == null || eventSessionId === sessionId;
|
|
740
|
+
}
|
|
741
|
+
function eventForSession(event, sessionId) {
|
|
742
|
+
if (!eventBelongsToSession(event, sessionId))
|
|
743
|
+
return null;
|
|
744
|
+
if (event.sessionId === sessionId)
|
|
745
|
+
return event;
|
|
746
|
+
return { ...event, sessionId: sessionId };
|
|
747
|
+
}
|
|
748
|
+
async function backupForeignSessionLog(logPath) {
|
|
749
|
+
try {
|
|
750
|
+
await fs.copyFile(logPath, `${logPath}.foreign-session.bak`, fsConstants.COPYFILE_EXCL);
|
|
751
|
+
}
|
|
752
|
+
catch (err) {
|
|
753
|
+
if (err.code === 'EEXIST')
|
|
754
|
+
return;
|
|
755
|
+
throw err;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
594
758
|
/**
|
|
595
759
|
* Remove a session's log file and its sidecar. A leftover legacy `index.json`
|
|
596
760
|
* row, if any, is harmless — `readIndex` filters out sessions whose `.jsonl` is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistence.js","sourceRoot":"","sources":["../../src/sessions/persistence.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"persistence.js","sourceRoot":"","sources":["../../src/sessions/persistence.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moxxy/core",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.4",
|
|
4
4
|
"description": "The moxxy runtime as a programmatic library: the agentic Session + runTurn loop, the event log, the plugin host, every block registry (providers, tools, modes, compactors, cache strategies, channels, …), session persistence, and the permission engine. Pair with @moxxy/sdk to build and embed moxxy agents in your own code.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"moxxy",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"jiti": "^2.4.2",
|
|
43
43
|
"ulid": "^2.3.0",
|
|
44
44
|
"zod": "^3.24.0",
|
|
45
|
-
"@moxxy/sdk": "0.16.
|
|
45
|
+
"@moxxy/sdk": "0.16.1"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/node": "^22.10.0",
|
package/src/run-turn.test.ts
CHANGED
|
@@ -59,6 +59,52 @@ function buildSession(): Session {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
describe('runTurn turnId filtering', () => {
|
|
62
|
+
it('continues the last resolved session model when no model override is supplied', async () => {
|
|
63
|
+
const models = [{ id: 'noop-default' }, { id: 'noop-sticky' }];
|
|
64
|
+
const session = new Session({ cwd: '/tmp', silent: true });
|
|
65
|
+
session.pluginHost.registerStatic(
|
|
66
|
+
definePlugin({
|
|
67
|
+
name: 'test-sticky-model',
|
|
68
|
+
version: '0.0.0',
|
|
69
|
+
providers: [
|
|
70
|
+
defineProvider({
|
|
71
|
+
name: 'noop',
|
|
72
|
+
models,
|
|
73
|
+
createClient: () => ({
|
|
74
|
+
name: 'noop',
|
|
75
|
+
models,
|
|
76
|
+
stream: async function* () {},
|
|
77
|
+
countTokens: async () => 0,
|
|
78
|
+
}),
|
|
79
|
+
}),
|
|
80
|
+
],
|
|
81
|
+
modes: [
|
|
82
|
+
defineMode({
|
|
83
|
+
name: 'model-echo',
|
|
84
|
+
run: async function* (ctx: ModeContext): AsyncIterable<MoxxyEvent> {
|
|
85
|
+
await ctx.emit({
|
|
86
|
+
type: 'assistant_message',
|
|
87
|
+
sessionId: ctx.sessionId,
|
|
88
|
+
turnId: ctx.turnId,
|
|
89
|
+
source: 'assistant',
|
|
90
|
+
text: ctx.model,
|
|
91
|
+
});
|
|
92
|
+
},
|
|
93
|
+
}),
|
|
94
|
+
],
|
|
95
|
+
}),
|
|
96
|
+
);
|
|
97
|
+
session.providers.setActive('noop');
|
|
98
|
+
session.modes.setActive('model-echo');
|
|
99
|
+
session.lastResolvedModel = 'noop-sticky';
|
|
100
|
+
|
|
101
|
+
const events = await collectTurn(session, 'continue');
|
|
102
|
+
|
|
103
|
+
expect(events.find((e) => e.type === 'assistant_message')).toMatchObject({
|
|
104
|
+
text: 'noop-sticky',
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
62
108
|
it('a single turn surfaces all of its own events', async () => {
|
|
63
109
|
const session = buildSession();
|
|
64
110
|
const events = await collectTurn(session, 'hi');
|
package/src/run-turn.ts
CHANGED
|
@@ -65,7 +65,10 @@ export async function* runTurn(
|
|
|
65
65
|
let model: string;
|
|
66
66
|
try {
|
|
67
67
|
provider = session.providers.getActive();
|
|
68
|
-
|
|
68
|
+
// Sticky model: prefer the explicit per-turn model, then the session's
|
|
69
|
+
// last-resolved model (so a conversation keeps the model it was using
|
|
70
|
+
// across turns), then the active provider's default.
|
|
71
|
+
const resolvedModel = opts.model ?? session.lastResolvedModel ?? provider.models[0]?.id;
|
|
69
72
|
if (!resolvedModel) {
|
|
70
73
|
throw new Error(
|
|
71
74
|
`Active provider '${provider.name}' has no models configured`,
|
|
@@ -6,6 +6,7 @@ import { EventLog } from '../events/log.js';
|
|
|
6
6
|
import type { Logger } from '../logger.js';
|
|
7
7
|
import {
|
|
8
8
|
SessionPersistence,
|
|
9
|
+
defaultSessionsDir,
|
|
9
10
|
deleteSession,
|
|
10
11
|
readEventPage,
|
|
11
12
|
readIndex,
|
|
@@ -57,6 +58,18 @@ function meta(id: string, eventCount = 0): SessionMeta {
|
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
describe('SessionPersistence', () => {
|
|
61
|
+
it('honors MOXXY_HOME for the default sessions directory', async () => {
|
|
62
|
+
const original = process.env.MOXXY_HOME;
|
|
63
|
+
const home = await makeTempDir();
|
|
64
|
+
process.env.MOXXY_HOME = home;
|
|
65
|
+
try {
|
|
66
|
+
expect(defaultSessionsDir()).toBe(path.join(home, 'sessions'));
|
|
67
|
+
} finally {
|
|
68
|
+
if (original === undefined) delete process.env.MOXXY_HOME;
|
|
69
|
+
else process.env.MOXXY_HOME = original;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
60
73
|
it('readIndex ignores rows whose event log file is missing', async () => {
|
|
61
74
|
const dir = await makeTempDir();
|
|
62
75
|
await fs.mkdir(dir, { recursive: true });
|
|
@@ -70,6 +83,172 @@ describe('SessionPersistence', () => {
|
|
|
70
83
|
await expect(readIndex(dir)).resolves.toEqual([meta('present')]);
|
|
71
84
|
});
|
|
72
85
|
|
|
86
|
+
it('readIndex recovers a missing firstPrompt from the event log', async () => {
|
|
87
|
+
const dir = await makeTempDir();
|
|
88
|
+
await fs.mkdir(dir, { recursive: true });
|
|
89
|
+
const id = '01HYDRATEPROMPT0000000000';
|
|
90
|
+
await fs.writeFile(
|
|
91
|
+
path.join(dir, `${id}.meta.json`),
|
|
92
|
+
JSON.stringify({ ...meta(id, 3), firstPrompt: null }, null, 2),
|
|
93
|
+
'utf8',
|
|
94
|
+
);
|
|
95
|
+
await fs.writeFile(
|
|
96
|
+
path.join(dir, `${id}.jsonl`),
|
|
97
|
+
JSON.stringify({
|
|
98
|
+
id: 'e1',
|
|
99
|
+
seq: 0,
|
|
100
|
+
ts: 1,
|
|
101
|
+
sessionId: id,
|
|
102
|
+
turnId: 't1',
|
|
103
|
+
source: 'user',
|
|
104
|
+
type: 'user_prompt',
|
|
105
|
+
text: 'restored from log',
|
|
106
|
+
}) + '\n',
|
|
107
|
+
'utf8',
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
const [restored] = await readIndex(dir);
|
|
111
|
+
|
|
112
|
+
expect(restored?.firstPrompt).toBe('restored from log');
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('readIndex refreshes provider and model from the latest provider event', async () => {
|
|
116
|
+
const dir = await makeTempDir();
|
|
117
|
+
await fs.mkdir(dir, { recursive: true });
|
|
118
|
+
const id = '01HYDRATEPROVIDER00000000';
|
|
119
|
+
await fs.writeFile(
|
|
120
|
+
path.join(dir, `${id}.meta.json`),
|
|
121
|
+
JSON.stringify({ ...meta(id, 2), provider: 'old-provider', model: 'old-model' }, null, 2),
|
|
122
|
+
'utf8',
|
|
123
|
+
);
|
|
124
|
+
await fs.writeFile(
|
|
125
|
+
path.join(dir, `${id}.jsonl`),
|
|
126
|
+
[
|
|
127
|
+
JSON.stringify({
|
|
128
|
+
id: 'e1',
|
|
129
|
+
seq: 0,
|
|
130
|
+
ts: 1,
|
|
131
|
+
sessionId: id,
|
|
132
|
+
turnId: 't1',
|
|
133
|
+
source: 'system',
|
|
134
|
+
type: 'provider_request',
|
|
135
|
+
provider: 'first-provider',
|
|
136
|
+
model: 'first-model',
|
|
137
|
+
}),
|
|
138
|
+
JSON.stringify({
|
|
139
|
+
id: 'e2',
|
|
140
|
+
seq: 1,
|
|
141
|
+
ts: 2,
|
|
142
|
+
sessionId: id,
|
|
143
|
+
turnId: 't1',
|
|
144
|
+
source: 'system',
|
|
145
|
+
type: 'provider_response',
|
|
146
|
+
provider: 'session-provider',
|
|
147
|
+
model: 'session-model',
|
|
148
|
+
inputTokens: 1,
|
|
149
|
+
outputTokens: 1,
|
|
150
|
+
}),
|
|
151
|
+
].join('\n') + '\n',
|
|
152
|
+
'utf8',
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
const [restored] = await readIndex(dir);
|
|
156
|
+
|
|
157
|
+
expect(restored).toMatchObject({
|
|
158
|
+
provider: 'session-provider',
|
|
159
|
+
model: 'session-model',
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('readIndex preserves a sidecar firstPrompt when the event log is still empty', async () => {
|
|
164
|
+
const dir = await makeTempDir();
|
|
165
|
+
await fs.mkdir(dir, { recursive: true });
|
|
166
|
+
const id = '01SIDECARPROMPT0000000000';
|
|
167
|
+
await fs.writeFile(
|
|
168
|
+
path.join(dir, `${id}.meta.json`),
|
|
169
|
+
JSON.stringify({ ...meta(id, 2), firstPrompt: 'sidecar title', eventCount: 2 }, null, 2),
|
|
170
|
+
'utf8',
|
|
171
|
+
);
|
|
172
|
+
await fs.writeFile(path.join(dir, `${id}.jsonl`), '', 'utf8');
|
|
173
|
+
|
|
174
|
+
const [restored] = await readIndex(dir);
|
|
175
|
+
|
|
176
|
+
expect(restored?.firstPrompt).toBe('sidecar title');
|
|
177
|
+
expect(restored?.eventCount).toBe(2);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('readIndex uses only matching-session prompts when hydrating titles', async () => {
|
|
181
|
+
const dir = await makeTempDir();
|
|
182
|
+
await fs.mkdir(dir, { recursive: true });
|
|
183
|
+
const id = '01MATCHPROMPT000000000000';
|
|
184
|
+
await fs.writeFile(
|
|
185
|
+
path.join(dir, `${id}.meta.json`),
|
|
186
|
+
JSON.stringify({ ...meta(id, 2), firstPrompt: 'foreign title', eventCount: 2 }, null, 2),
|
|
187
|
+
'utf8',
|
|
188
|
+
);
|
|
189
|
+
await fs.writeFile(
|
|
190
|
+
path.join(dir, `${id}.jsonl`),
|
|
191
|
+
[
|
|
192
|
+
{
|
|
193
|
+
id: 'foreign',
|
|
194
|
+
seq: 0,
|
|
195
|
+
ts: 1,
|
|
196
|
+
sessionId: 'other-session',
|
|
197
|
+
turnId: 't1',
|
|
198
|
+
source: 'user',
|
|
199
|
+
type: 'user_prompt',
|
|
200
|
+
text: 'foreign title',
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
id: 'matching',
|
|
204
|
+
seq: 1,
|
|
205
|
+
ts: 2,
|
|
206
|
+
sessionId: id,
|
|
207
|
+
turnId: 't2',
|
|
208
|
+
source: 'user',
|
|
209
|
+
type: 'user_prompt',
|
|
210
|
+
text: 'real matching title',
|
|
211
|
+
},
|
|
212
|
+
].map((event) => JSON.stringify(event)).join('\n') + '\n',
|
|
213
|
+
'utf8',
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
const [restored] = await readIndex(dir);
|
|
217
|
+
|
|
218
|
+
expect(restored?.firstPrompt).toBe('real matching title');
|
|
219
|
+
expect(restored?.eventCount).toBe(1);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('readIndex does not hydrate a visible title from a foreign-only log', async () => {
|
|
223
|
+
const dir = await makeTempDir();
|
|
224
|
+
await fs.mkdir(dir, { recursive: true });
|
|
225
|
+
const id = '01FOREIGNONLY00000000000';
|
|
226
|
+
await fs.writeFile(
|
|
227
|
+
path.join(dir, `${id}.meta.json`),
|
|
228
|
+
JSON.stringify({ ...meta(id, 1), firstPrompt: 'foreign prompt', eventCount: 1 }, null, 2),
|
|
229
|
+
'utf8',
|
|
230
|
+
);
|
|
231
|
+
await fs.writeFile(
|
|
232
|
+
path.join(dir, `${id}.jsonl`),
|
|
233
|
+
JSON.stringify({
|
|
234
|
+
id: 'foreign',
|
|
235
|
+
seq: 0,
|
|
236
|
+
ts: 1,
|
|
237
|
+
sessionId: 'other-session',
|
|
238
|
+
turnId: 't1',
|
|
239
|
+
source: 'user',
|
|
240
|
+
type: 'user_prompt',
|
|
241
|
+
text: 'foreign prompt',
|
|
242
|
+
}) + '\n',
|
|
243
|
+
'utf8',
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
const [restored] = await readIndex(dir);
|
|
247
|
+
|
|
248
|
+
expect(restored?.firstPrompt).toBeNull();
|
|
249
|
+
expect(restored?.eventCount).toBe(0);
|
|
250
|
+
});
|
|
251
|
+
|
|
73
252
|
it('creates a resumable empty event log when a session is indexed before any events', async () => {
|
|
74
253
|
const dir = await makeTempDir();
|
|
75
254
|
const id = '01EMPTYSESSION000000000000';
|
|
@@ -131,6 +310,66 @@ describe('SessionPersistence', () => {
|
|
|
131
310
|
detach();
|
|
132
311
|
});
|
|
133
312
|
|
|
313
|
+
it('does not persist foreign-session events into the current session log', async () => {
|
|
314
|
+
const dir = await makeTempDir();
|
|
315
|
+
const id = '01CURRENTSESSION0000000000';
|
|
316
|
+
const log = new EventLog();
|
|
317
|
+
const { logger, lines } = captureLogger();
|
|
318
|
+
const persistence = new SessionPersistence({
|
|
319
|
+
sessionId: id as never,
|
|
320
|
+
cwd: '/tmp/p',
|
|
321
|
+
dir,
|
|
322
|
+
logger,
|
|
323
|
+
});
|
|
324
|
+
const detach = persistence.attach(log);
|
|
325
|
+
|
|
326
|
+
await log.append({
|
|
327
|
+
type: 'user_prompt',
|
|
328
|
+
sessionId: 'other-session' as never,
|
|
329
|
+
turnId: 't1' as never,
|
|
330
|
+
source: 'user',
|
|
331
|
+
text: 'should not persist',
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
await waitForCondition(async () =>
|
|
335
|
+
lines.some((line) => line.level === 'warn' && line.msg.includes('foreign-session')),
|
|
336
|
+
);
|
|
337
|
+
await waitForCondition(async () => (await readIndex(dir))[0]?.id === id);
|
|
338
|
+
|
|
339
|
+
expect(await restoreEvents(id, dir)).toEqual([]);
|
|
340
|
+
expect((await readIndex(dir))[0]).toMatchObject({ eventCount: 0, firstPrompt: null });
|
|
341
|
+
|
|
342
|
+
detach();
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it('normalizes legacy in-memory events without sessionId to the current session before persisting', async () => {
|
|
346
|
+
const dir = await makeTempDir();
|
|
347
|
+
const id = '01LEGACYNOSESSION00000000';
|
|
348
|
+
const log = new EventLog();
|
|
349
|
+
const persistence = new SessionPersistence({ sessionId: id as never, cwd: '/tmp/p', dir });
|
|
350
|
+
const detach = persistence.attach(log);
|
|
351
|
+
|
|
352
|
+
await log.append({
|
|
353
|
+
type: 'user_prompt',
|
|
354
|
+
turnId: 't1' as never,
|
|
355
|
+
source: 'user',
|
|
356
|
+
text: 'legacy prompt without session id',
|
|
357
|
+
} as never);
|
|
358
|
+
|
|
359
|
+
await waitForCondition(async () => (await restoreEvents(id, dir)).length === 1);
|
|
360
|
+
const [event] = await restoreEvents(id, dir);
|
|
361
|
+
await waitForCondition(async () => (await readIndex(dir))[0]?.eventCount === 1);
|
|
362
|
+
|
|
363
|
+
expect(event?.sessionId).toBe(id);
|
|
364
|
+
expect((await readIndex(dir))[0]).toMatchObject({
|
|
365
|
+
id,
|
|
366
|
+
eventCount: 1,
|
|
367
|
+
firstPrompt: 'legacy prompt without session id',
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
detach();
|
|
371
|
+
});
|
|
372
|
+
|
|
134
373
|
it('warns once (not per event) on event-log write failure, recovers on success', async () => {
|
|
135
374
|
const dir = await makeTempDir();
|
|
136
375
|
const id = '01WRITEFAIL000000000000000';
|
|
@@ -233,6 +472,74 @@ describe('SessionPersistence', () => {
|
|
|
233
472
|
expect(again.lines).toHaveLength(0);
|
|
234
473
|
});
|
|
235
474
|
|
|
475
|
+
it('restore removes foreign-session events, creates a backup, and re-sequences survivors', async () => {
|
|
476
|
+
const dir = await makeTempDir();
|
|
477
|
+
const id = '01RESTOREFILTER000000000';
|
|
478
|
+
await fs.mkdir(dir, { recursive: true });
|
|
479
|
+
const logPath = path.join(dir, `${id}.jsonl`);
|
|
480
|
+
const events = [
|
|
481
|
+
{
|
|
482
|
+
id: 'foreign',
|
|
483
|
+
seq: 0,
|
|
484
|
+
ts: 1,
|
|
485
|
+
sessionId: 'other-session',
|
|
486
|
+
turnId: 't1',
|
|
487
|
+
source: 'user',
|
|
488
|
+
type: 'user_prompt',
|
|
489
|
+
text: 'foreign prompt',
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
id: 'matching',
|
|
493
|
+
seq: 5,
|
|
494
|
+
ts: 2,
|
|
495
|
+
sessionId: id,
|
|
496
|
+
turnId: 't2',
|
|
497
|
+
source: 'user',
|
|
498
|
+
type: 'user_prompt',
|
|
499
|
+
text: 'matching prompt',
|
|
500
|
+
},
|
|
501
|
+
];
|
|
502
|
+
await fs.writeFile(logPath, events.map((event) => JSON.stringify(event)).join('\n') + '\n', 'utf8');
|
|
503
|
+
|
|
504
|
+
const { logger, lines } = captureLogger();
|
|
505
|
+
const restored = await restoreEvents(id, dir, logger);
|
|
506
|
+
|
|
507
|
+
expect(restored.map((event) => event.id)).toEqual(['matching']);
|
|
508
|
+
expect(restored.map((event) => event.seq)).toEqual([0]);
|
|
509
|
+
expect(lines.some((line) => line.level === 'warn' && line.msg.includes('foreign-session'))).toBe(true);
|
|
510
|
+
await expect(fs.access(`${logPath}.foreign-session.bak`)).resolves.toBeUndefined();
|
|
511
|
+
const repaired = (await fs.readFile(logPath, 'utf8')).trim().split('\n').map((line) => JSON.parse(line));
|
|
512
|
+
expect(repaired.map((event) => event.id)).toEqual(['matching']);
|
|
513
|
+
expect(repaired.map((event) => event.seq)).toEqual([0]);
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
it('restore rewrites a foreign-only log to an empty session with a backup', async () => {
|
|
517
|
+
const dir = await makeTempDir();
|
|
518
|
+
const id = '01RESTOREEMPTY0000000000';
|
|
519
|
+
await fs.mkdir(dir, { recursive: true });
|
|
520
|
+
const logPath = path.join(dir, `${id}.jsonl`);
|
|
521
|
+
await fs.writeFile(
|
|
522
|
+
logPath,
|
|
523
|
+
JSON.stringify({
|
|
524
|
+
id: 'foreign',
|
|
525
|
+
seq: 0,
|
|
526
|
+
ts: 1,
|
|
527
|
+
sessionId: 'other-session',
|
|
528
|
+
turnId: 't1',
|
|
529
|
+
source: 'user',
|
|
530
|
+
type: 'user_prompt',
|
|
531
|
+
text: 'foreign prompt',
|
|
532
|
+
}) + '\n',
|
|
533
|
+
'utf8',
|
|
534
|
+
);
|
|
535
|
+
|
|
536
|
+
const restored = await restoreEvents(id, dir, captureLogger().logger);
|
|
537
|
+
|
|
538
|
+
expect(restored).toEqual([]);
|
|
539
|
+
expect(await fs.readFile(logPath, 'utf8')).toBe('');
|
|
540
|
+
await expect(fs.access(`${logPath}.foreign-session.bak`)).resolves.toBeUndefined();
|
|
541
|
+
});
|
|
542
|
+
|
|
236
543
|
it('rejects a path-traversal session id before touching the filesystem', async () => {
|
|
237
544
|
const dir = await makeTempDir();
|
|
238
545
|
// A secret file OUTSIDE the sessions dir that a traversal id would target.
|
|
@@ -16,11 +16,10 @@
|
|
|
16
16
|
* best-effort (lose at most the last in-flight event on a crash).
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import { promises as fs } from 'node:fs';
|
|
20
|
-
import * as os from 'node:os';
|
|
19
|
+
import { constants as fsConstants, promises as fs } from 'node:fs';
|
|
21
20
|
import * as path from 'node:path';
|
|
22
21
|
import { createMutex, type Mutex, type MoxxyEvent, type SessionId } from '@moxxy/sdk';
|
|
23
|
-
import { writeFileAtomic } from '@moxxy/sdk/server';
|
|
22
|
+
import { moxxyPath, writeFileAtomic } from '@moxxy/sdk/server';
|
|
24
23
|
import type { EventLog } from '../events/log.js';
|
|
25
24
|
import { createLogger, type Logger } from '../logger.js';
|
|
26
25
|
|
|
@@ -54,7 +53,7 @@ export interface SessionPersistenceOpts {
|
|
|
54
53
|
}
|
|
55
54
|
|
|
56
55
|
export function defaultSessionsDir(): string {
|
|
57
|
-
return
|
|
56
|
+
return moxxyPath('sessions');
|
|
58
57
|
}
|
|
59
58
|
|
|
60
59
|
/**
|
|
@@ -245,6 +244,16 @@ export class SessionPersistence {
|
|
|
245
244
|
}
|
|
246
245
|
|
|
247
246
|
private enqueueAppend(event: MoxxyEvent): void {
|
|
247
|
+
const ownedEvent = eventForSession(event, this.id);
|
|
248
|
+
if (!ownedEvent) {
|
|
249
|
+
this.logger.warn('session persistence ignored foreign-session event', {
|
|
250
|
+
path: this.logPath,
|
|
251
|
+
sessionId: this.id,
|
|
252
|
+
eventId: event.id,
|
|
253
|
+
eventSessionId: event.sessionId,
|
|
254
|
+
});
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
248
257
|
// Update in-memory meta synchronously so multiple events in the
|
|
249
258
|
// same tick share one debounced index write.
|
|
250
259
|
this.meta = {
|
|
@@ -253,10 +262,11 @@ export class SessionPersistence {
|
|
|
253
262
|
lastActivity: new Date().toISOString(),
|
|
254
263
|
firstPrompt:
|
|
255
264
|
this.meta.firstPrompt ??
|
|
256
|
-
(
|
|
265
|
+
(ownedEvent.type === 'user_prompt' ? firstPromptLabel(ownedEvent.text) : null),
|
|
266
|
+
...providerHeaderFromEvent(ownedEvent),
|
|
257
267
|
};
|
|
258
268
|
this.scheduleIndexWrite();
|
|
259
|
-
const line = JSON.stringify(
|
|
269
|
+
const line = JSON.stringify(ownedEvent) + '\n';
|
|
260
270
|
// Never propagate a write error into the listener chain — but never
|
|
261
271
|
// swallow it silently either: the JSONL is the session's source of
|
|
262
272
|
// truth, so a failing disk must at least be loud.
|
|
@@ -440,9 +450,77 @@ export async function readIndex(dir = defaultSessionsDir()): Promise<SessionMeta
|
|
|
440
450
|
return false;
|
|
441
451
|
}
|
|
442
452
|
});
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
453
|
+
const present = metas.filter((_, index) => checks[index]);
|
|
454
|
+
const hydrated = await mapWithConcurrency(present, READ_INDEX_CONCURRENCY, (meta) =>
|
|
455
|
+
hydrateMetaFirstPrompt(meta, dir),
|
|
456
|
+
);
|
|
457
|
+
return hydrated.sort((a, b) => b.lastActivity.localeCompare(a.lastActivity));
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
async function hydrateMetaFirstPrompt(meta: SessionMeta, dir: string): Promise<SessionMeta> {
|
|
461
|
+
const stats = await matchingSessionStatsFromLog(meta.id, path.join(dir, `${meta.id}.jsonl`));
|
|
462
|
+
if (!stats) return meta;
|
|
463
|
+
if (stats.parsedEvents === 0) return meta;
|
|
464
|
+
return {
|
|
465
|
+
...meta,
|
|
466
|
+
eventCount: stats.eventCount,
|
|
467
|
+
firstPrompt: stats.firstPrompt,
|
|
468
|
+
provider: stats.provider ?? meta.provider,
|
|
469
|
+
model: stats.model ?? meta.model,
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
async function matchingSessionStatsFromLog(
|
|
474
|
+
sessionId: string,
|
|
475
|
+
logPath: string,
|
|
476
|
+
): Promise<{
|
|
477
|
+
eventCount: number;
|
|
478
|
+
firstPrompt: string | null;
|
|
479
|
+
parsedEvents: number;
|
|
480
|
+
provider: string | null;
|
|
481
|
+
model: string | null;
|
|
482
|
+
} | null> {
|
|
483
|
+
let raw: string;
|
|
484
|
+
try {
|
|
485
|
+
raw = await fs.readFile(logPath, 'utf8');
|
|
486
|
+
} catch {
|
|
487
|
+
return null;
|
|
488
|
+
}
|
|
489
|
+
let eventCount = 0;
|
|
490
|
+
let parsedEvents = 0;
|
|
491
|
+
let firstPrompt: string | null = null;
|
|
492
|
+
let provider: string | null = null;
|
|
493
|
+
let model: string | null = null;
|
|
494
|
+
for (const line of raw.split('\n')) {
|
|
495
|
+
if (!line.trim()) continue;
|
|
496
|
+
try {
|
|
497
|
+
const event = JSON.parse(line) as MoxxyEvent;
|
|
498
|
+
parsedEvents += 1;
|
|
499
|
+
if (!eventBelongsToSession(event, sessionId)) continue;
|
|
500
|
+
eventCount += 1;
|
|
501
|
+
if (firstPrompt === null && event.type === 'user_prompt') {
|
|
502
|
+
// Mirror the write-time label (SessionPersistence.enqueueAppend):
|
|
503
|
+
// code-point-aware slice + non-string coercion, so a hydrated index row
|
|
504
|
+
// matches the meta the live append wrote (no surrogate split, never null
|
|
505
|
+
// for a present prompt).
|
|
506
|
+
firstPrompt = firstPromptLabel(event.text);
|
|
507
|
+
}
|
|
508
|
+
const header = providerHeaderFromEvent(event);
|
|
509
|
+
if (header.provider !== undefined) provider = header.provider;
|
|
510
|
+
if (header.model !== undefined) model = header.model;
|
|
511
|
+
} catch {
|
|
512
|
+
// A corrupt line should not hide a later valid prompt.
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return { eventCount, firstPrompt, parsedEvents, provider, model };
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
function providerHeaderFromEvent(event: MoxxyEvent): { provider?: string | null; model?: string | null } {
|
|
519
|
+
if (event.type !== 'provider_request' && event.type !== 'provider_response') return {};
|
|
520
|
+
return {
|
|
521
|
+
provider: event.provider,
|
|
522
|
+
model: event.model,
|
|
523
|
+
};
|
|
446
524
|
}
|
|
447
525
|
|
|
448
526
|
/**
|
|
@@ -484,10 +562,19 @@ export async function restoreEvents(
|
|
|
484
562
|
}
|
|
485
563
|
const events: MoxxyEvent[] = [];
|
|
486
564
|
let corruptLines = 0;
|
|
565
|
+
let foreignEvents = 0;
|
|
566
|
+
let normalizedSessionIds = 0;
|
|
487
567
|
for (const line of raw.split('\n')) {
|
|
488
568
|
if (!line.trim()) continue;
|
|
489
569
|
try {
|
|
490
|
-
|
|
570
|
+
const event = JSON.parse(line) as MoxxyEvent;
|
|
571
|
+
const ownedEvent = eventForSession(event, sessionId);
|
|
572
|
+
if (ownedEvent) {
|
|
573
|
+
if (ownedEvent !== event) normalizedSessionIds += 1;
|
|
574
|
+
events.push(ownedEvent);
|
|
575
|
+
} else {
|
|
576
|
+
foreignEvents += 1;
|
|
577
|
+
}
|
|
491
578
|
} catch {
|
|
492
579
|
corruptLines += 1;
|
|
493
580
|
}
|
|
@@ -503,17 +590,37 @@ export async function restoreEvents(
|
|
|
503
590
|
}
|
|
504
591
|
}
|
|
505
592
|
|
|
506
|
-
if (corruptLines > 0 || resequenced > 0) {
|
|
507
|
-
|
|
593
|
+
if (corruptLines > 0 || resequenced > 0 || foreignEvents > 0 || normalizedSessionIds > 0) {
|
|
594
|
+
const message =
|
|
595
|
+
foreignEvents > 0
|
|
596
|
+
? 'session log restored with foreign-session events removed — re-sequenced to keep full history replayable'
|
|
597
|
+
: 'session log restored with gaps — re-sequenced to keep full history replayable';
|
|
598
|
+
logger.warn(message, {
|
|
508
599
|
sessionId,
|
|
509
600
|
path: logPath,
|
|
510
601
|
corruptLines,
|
|
602
|
+
foreignEvents,
|
|
603
|
+
normalizedSessionIds,
|
|
511
604
|
resequencedEvents: resequenced,
|
|
512
605
|
restoredEvents: events.length,
|
|
513
606
|
});
|
|
607
|
+
let canRewrite = true;
|
|
608
|
+
if (foreignEvents > 0) {
|
|
609
|
+
try {
|
|
610
|
+
await backupForeignSessionLog(logPath);
|
|
611
|
+
} catch (err) {
|
|
612
|
+
canRewrite = false;
|
|
613
|
+
logger.warn('failed to backup foreign-session log before repair', {
|
|
614
|
+
sessionId,
|
|
615
|
+
path: logPath,
|
|
616
|
+
error: err instanceof Error ? err.message : String(err),
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
}
|
|
514
620
|
try {
|
|
515
|
-
// Conflict guard: only rewrite if
|
|
516
|
-
//
|
|
621
|
+
// Conflict guard: only rewrite if (a) a foreign-session backup didn't
|
|
622
|
+
// fail (`canRewrite`) and (b) the on-disk content still matches what we
|
|
623
|
+
// read. Another process (a desktop runner already attached + a CLI
|
|
517
624
|
// `resume` of the SAME id) may have appended/repaired between our read and
|
|
518
625
|
// this write; its appends are a newer snapshot than our re-sequenced one,
|
|
519
626
|
// and a blind `writeFileAtomic` would clobber them (silent history loss).
|
|
@@ -522,7 +629,9 @@ export async function restoreEvents(
|
|
|
522
629
|
// rewrite. Restore still succeeds either way — the in-memory log is
|
|
523
630
|
// already repaired; only the next clean resume would re-run the repair.
|
|
524
631
|
const current = await fs.readFile(logPath, 'utf8').catch(() => null);
|
|
525
|
-
if (
|
|
632
|
+
if (!canRewrite) {
|
|
633
|
+
/* foreign-session backup failed — skip the destructive rewrite */
|
|
634
|
+
} else if (current !== raw) {
|
|
526
635
|
logger.warn('skipped repaired-log rewrite — file changed under us (another process attached?)', {
|
|
527
636
|
sessionId,
|
|
528
637
|
path: logPath,
|
|
@@ -664,6 +773,64 @@ export function pageEvents(
|
|
|
664
773
|
return { events: page, prevCursor };
|
|
665
774
|
}
|
|
666
775
|
|
|
776
|
+
/**
|
|
777
|
+
* Seed a session's event log from an external event list IFF the session has no
|
|
778
|
+
* log on disk yet. This is the migration that makes the runner's authoritative
|
|
779
|
+
* log the home of a chat whose history previously lived ONLY in a thin client's
|
|
780
|
+
* own mirror (the desktop's NDJSON chat store) — after it runs, `loadHistory`
|
|
781
|
+
* serves that chat from the runner like any other.
|
|
782
|
+
*
|
|
783
|
+
* Idempotent and NON-destructive: if `<sessionId>.jsonl` already exists AND is
|
|
784
|
+
* NON-EMPTY this is a no-op returning `false`, so a session the runner already
|
|
785
|
+
* owns is NEVER overwritten. A 0-byte log IS seeded: `persistence.attach`
|
|
786
|
+
* creates an empty `<id>.jsonl` on every spawn (even a session with zero
|
|
787
|
+
* events), so an existence-only guard would skip exactly the legacy chats this
|
|
788
|
+
* migration targets — and an empty file holds no history, so seeding over it
|
|
789
|
+
* loses nothing. Events are re-sequenced to contiguous `seq` 0..n-1 (order + ids
|
|
790
|
+
* preserved) so the seeded log satisfies {@link EventLog}'s seq invariants when
|
|
791
|
+
* it is later restored. Written temp+rename so a crash mid-seed can't leave a
|
|
792
|
+
* half-written log. Returns `true` iff it wrote the log.
|
|
793
|
+
*/
|
|
794
|
+
export async function seedSessionLog(
|
|
795
|
+
sessionId: string,
|
|
796
|
+
events: ReadonlyArray<MoxxyEvent>,
|
|
797
|
+
dir = defaultSessionsDir(),
|
|
798
|
+
): Promise<boolean> {
|
|
799
|
+
if (events.length === 0) return false;
|
|
800
|
+
const logPath = path.join(dir, `${sessionId}.jsonl`);
|
|
801
|
+
try {
|
|
802
|
+
// A non-empty log is a session the runner already owns → never overwrite.
|
|
803
|
+
// A 0-byte log is the empty file attach() left behind → seed over it.
|
|
804
|
+
if ((await fs.stat(logPath)).size > 0) return false;
|
|
805
|
+
} catch {
|
|
806
|
+
/* no log yet → seed below */
|
|
807
|
+
}
|
|
808
|
+
await fs.mkdir(dir, { recursive: true });
|
|
809
|
+
const reseq = events.map((e, i) => (e.seq === i ? e : ({ ...e, seq: i } as MoxxyEvent)));
|
|
810
|
+
await writeFileAtomic(logPath, reseq.map((e) => JSON.stringify(e) + '\n').join(''));
|
|
811
|
+
return true;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
function eventBelongsToSession(event: MoxxyEvent, sessionId: string): boolean {
|
|
815
|
+
const eventSessionId = (event as { sessionId?: unknown }).sessionId;
|
|
816
|
+
return eventSessionId == null || eventSessionId === sessionId;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
function eventForSession(event: MoxxyEvent, sessionId: string): MoxxyEvent | null {
|
|
820
|
+
if (!eventBelongsToSession(event, sessionId)) return null;
|
|
821
|
+
if ((event as { sessionId?: unknown }).sessionId === sessionId) return event;
|
|
822
|
+
return { ...event, sessionId: sessionId as SessionId } as MoxxyEvent;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
async function backupForeignSessionLog(logPath: string): Promise<void> {
|
|
826
|
+
try {
|
|
827
|
+
await fs.copyFile(logPath, `${logPath}.foreign-session.bak`, fsConstants.COPYFILE_EXCL);
|
|
828
|
+
} catch (err) {
|
|
829
|
+
if ((err as NodeJS.ErrnoException).code === 'EEXIST') return;
|
|
830
|
+
throw err;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
|
|
667
834
|
/**
|
|
668
835
|
* Remove a session's log file and its sidecar. A leftover legacy `index.json`
|
|
669
836
|
* row, if any, is harmless — `readIndex` filters out sessions whose `.jsonl` is
|