@adhdev/daemon-core 0.9.82-rc.173 → 0.9.82-rc.174
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/index.js +68 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +68 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/providers/spec/native-history-executor.ts +86 -3
package/package.json
CHANGED
|
@@ -106,12 +106,21 @@ function executeJsonl(src: NativeHistoryJsonlSource, input: NativeHistoryInput):
|
|
|
106
106
|
sourcePath = newestRecentFileAcrossGlob(resolved, filePat, windowMs, sessionFloor);
|
|
107
107
|
} else {
|
|
108
108
|
let stat: fs.Stats | null = null;
|
|
109
|
-
try { stat = fs.statSync(resolved); } catch {
|
|
110
|
-
if (stat.isFile()) {
|
|
109
|
+
try { stat = fs.statSync(resolved); } catch { /* fall through to date-walk fallback */ }
|
|
110
|
+
if (stat && stat.isFile()) {
|
|
111
111
|
sourcePath = resolved;
|
|
112
|
-
} else if (stat.isDirectory()) {
|
|
112
|
+
} else if (stat && stat.isDirectory()) {
|
|
113
113
|
sourcePath = newestRecentFile(resolved, filePat, windowMs, sessionFloor);
|
|
114
114
|
}
|
|
115
|
+
// Date-templated directories (e.g. ~/.codex/sessions/{yyyy}/{mm}/{dd})
|
|
116
|
+
// expand to today's UTC dir. A session started before UTC midnight
|
|
117
|
+
// keeps appending to its previous-day file, so today's dir never
|
|
118
|
+
// contains the live transcript. When the templated dir is empty
|
|
119
|
+
// or doesn't exist yet, walk the last 3 UTC days at the same depth
|
|
120
|
+
// and pick the newest matching rollout across all of them.
|
|
121
|
+
if (!sourcePath && hasDateTemplateSegment(src.path)) {
|
|
122
|
+
sourcePath = newestRecentFileAcrossDateWindow(src.path, input, filePat, windowMs, sessionFloor);
|
|
123
|
+
}
|
|
115
124
|
}
|
|
116
125
|
if (!sourcePath) return null;
|
|
117
126
|
|
|
@@ -367,6 +376,80 @@ function newestRecentFileAcrossGlob(template: string, pattern: RegExp, windowMs:
|
|
|
367
376
|
return best ? best.p : null;
|
|
368
377
|
}
|
|
369
378
|
|
|
379
|
+
function hasDateTemplateSegment(template: string): boolean {
|
|
380
|
+
return /\{yyyy\}|\{mm\}|\{dd\}/.test(template);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Walk the last N UTC days of a date-templated path (e.g.
|
|
385
|
+
* `~/.codex/sessions/{yyyy}/{mm}/{dd}`) and return the newest matching
|
|
386
|
+
* file across all of them. Codex sessions started just before UTC
|
|
387
|
+
* midnight keep writing to their original day's file even after the
|
|
388
|
+
* date rolls over, so today's expanded dir alone misses the live
|
|
389
|
+
* transcript.
|
|
390
|
+
*/
|
|
391
|
+
function newestRecentFileAcrossDateWindow(
|
|
392
|
+
template: string,
|
|
393
|
+
input: NativeHistoryInput,
|
|
394
|
+
pattern: RegExp,
|
|
395
|
+
windowMs: number,
|
|
396
|
+
sessionFloorMs: number,
|
|
397
|
+
): string | null {
|
|
398
|
+
const cutoff = Math.max(Date.now() - windowMs, sessionFloorMs);
|
|
399
|
+
let best: { p: string; mtime: number } | null = null;
|
|
400
|
+
for (let dayOffset = 0; dayOffset < 3; dayOffset += 1) {
|
|
401
|
+
const dayMs = Date.now() - dayOffset * 24 * 60 * 60 * 1000;
|
|
402
|
+
const dayInput: NativeHistoryInput = { ...input, sessionStartedAtMs: sessionFloorMs };
|
|
403
|
+
const resolved = expandPathForDate(template, dayInput, new Date(dayMs));
|
|
404
|
+
if (!resolved) continue;
|
|
405
|
+
let entries: fs.Dirent[];
|
|
406
|
+
try { entries = fs.readdirSync(resolved, { withFileTypes: true }); } catch { continue; }
|
|
407
|
+
for (const e of entries) {
|
|
408
|
+
if (!e.isFile() || !pattern.test(e.name)) continue;
|
|
409
|
+
const p = path.join(resolved, e.name);
|
|
410
|
+
const mtime = safeMtimeMs(p);
|
|
411
|
+
if (mtime < cutoff) continue;
|
|
412
|
+
if (!best || mtime > best.mtime) best = { p, mtime };
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return best ? best.p : null;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function expandPathForDate(template: string, input: NativeHistoryInput, day: Date): string | null {
|
|
419
|
+
// Reuse expandPath logic but stamp {yyyy}/{mm}/{dd} from the given day.
|
|
420
|
+
if (!template) return null;
|
|
421
|
+
let out = template;
|
|
422
|
+
if (out.startsWith('~/') || out === '~') {
|
|
423
|
+
out = path.join(os.homedir(), out.slice(2));
|
|
424
|
+
}
|
|
425
|
+
out = out.replace(/\$\{([A-Z_][A-Z0-9_]*)(?::-(.*?))?\}/g, (_m, name, fallback) => {
|
|
426
|
+
const v = input.envOverrides?.[name] ?? process.env[name];
|
|
427
|
+
return v != null && v !== '' ? v : (fallback ?? '');
|
|
428
|
+
});
|
|
429
|
+
if (out.startsWith('~/')) out = path.join(os.homedir(), out.slice(2));
|
|
430
|
+
const workspaceRaw = input.workspace ?? '';
|
|
431
|
+
let workspaceResolved = workspaceRaw;
|
|
432
|
+
if (workspaceRaw) {
|
|
433
|
+
try { workspaceResolved = fs.realpathSync(workspaceRaw); } catch { /* keep raw */ }
|
|
434
|
+
}
|
|
435
|
+
const vars: Record<string, string> = {
|
|
436
|
+
cwd: workspaceResolved,
|
|
437
|
+
cwd_dashed: workspaceResolved.replace(/\//g, '-'),
|
|
438
|
+
session_id: input.providerSessionId || input.sessionId || input.historySessionId || '',
|
|
439
|
+
yyyy: String(day.getUTCFullYear()),
|
|
440
|
+
mm: String(day.getUTCMonth() + 1).padStart(2, '0'),
|
|
441
|
+
dd: String(day.getUTCDate()).padStart(2, '0'),
|
|
442
|
+
};
|
|
443
|
+
let missing = false;
|
|
444
|
+
out = out.replace(/\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g, (_m, name) => {
|
|
445
|
+
const v = vars[name] ?? '';
|
|
446
|
+
if (!v) missing = true;
|
|
447
|
+
return v;
|
|
448
|
+
});
|
|
449
|
+
if (missing) return null;
|
|
450
|
+
return out;
|
|
451
|
+
}
|
|
452
|
+
|
|
370
453
|
function newestRecentFile(dir: string, pattern: RegExp, windowMs: number, sessionFloorMs = 0): string | null {
|
|
371
454
|
let entries: fs.Dirent[];
|
|
372
455
|
try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { return null; }
|