sessionpipe-conformance 0.13.0 → 0.13.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/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +135 -70
- package/dist/cli.js.map +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +119 -67
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAuBD,oGAAoG;AACpG,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EAAE,GACd,OAAO,CAAC;IAAE,OAAO,EAAE,aAAa,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAuBD,oGAAoG;AACpG,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EAAE,GACd,OAAO,CAAC;IAAE,OAAO,EAAE,aAAa,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAwDtE"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// sessionpipe-conformance 0.13.
|
|
1
|
+
// sessionpipe-conformance 0.13.2 · Apache-2.0 · https://sessionpipe.org
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { readFileSync as readFileSync7 } from "node:fs";
|
|
@@ -10,7 +10,7 @@ var homeDir = () => os.homedir();
|
|
|
10
10
|
// ../core/src/adapters/claude-code.ts
|
|
11
11
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
12
12
|
import { createHash } from "node:crypto";
|
|
13
|
-
import { existsSync as existsSync2, readdirSync as readdirSync2, readFileSync as readFileSync2, statSync as statSync2
|
|
13
|
+
import { existsSync as existsSync2, readdirSync as readdirSync2, readFileSync as readFileSync2, statSync as statSync2 } from "node:fs";
|
|
14
14
|
import { userInfo } from "node:os";
|
|
15
15
|
import path3 from "node:path";
|
|
16
16
|
|
|
@@ -368,6 +368,41 @@ function readJson(file) {
|
|
|
368
368
|
const f = readJsonFile(file);
|
|
369
369
|
return f.ok ? f.value : {};
|
|
370
370
|
}
|
|
371
|
+
function refused(file, e, what, existed) {
|
|
372
|
+
const { code, syscall } = e;
|
|
373
|
+
const why = `can't ${what} it (${code ?? String(e)})`;
|
|
374
|
+
if (what === "remove" || syscall === "open" || syscall === "mkdir")
|
|
375
|
+
return { file, changed: false, skipped: true, note: `${why}; not touched` };
|
|
376
|
+
return {
|
|
377
|
+
file,
|
|
378
|
+
changed: true,
|
|
379
|
+
skipped: true,
|
|
380
|
+
...existed ? {} : { created: true },
|
|
381
|
+
note: `${why} part way; check the file before the harness reads it`
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
function writeBack(file, text, existed = true) {
|
|
385
|
+
try {
|
|
386
|
+
mkdirSync(path2.dirname(file), { recursive: true });
|
|
387
|
+
writeFileSync(file, text);
|
|
388
|
+
return null;
|
|
389
|
+
} catch (e) {
|
|
390
|
+
return refused(file, e, "write", existed);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
function removeEmptied(file, empty) {
|
|
394
|
+
try {
|
|
395
|
+
unlinkSync(file);
|
|
396
|
+
return { file, changed: true, note: "removed (sessionpipe created it)" };
|
|
397
|
+
} catch (e) {
|
|
398
|
+
const bad = refused(file, e, "remove", true);
|
|
399
|
+
return writeBack(file, empty) ?? {
|
|
400
|
+
file,
|
|
401
|
+
changed: true,
|
|
402
|
+
note: `emptied; ${bad.note.replace(/; not touched$/, "")}, so the empty file stays`
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
}
|
|
371
406
|
function entryFor(event, harness, cmd, o) {
|
|
372
407
|
const matcher = o.matcherFor(event);
|
|
373
408
|
return {
|
|
@@ -409,8 +444,8 @@ function installClaudeShaped(file, harness, events, cmd, o) {
|
|
|
409
444
|
}
|
|
410
445
|
if (changed) {
|
|
411
446
|
settings2.hooks = hooks;
|
|
412
|
-
|
|
413
|
-
|
|
447
|
+
const bad = writeBack(file, formatJson(settings2, f), f.existed);
|
|
448
|
+
if (bad) return bad;
|
|
414
449
|
}
|
|
415
450
|
return { file, changed, created: !f.existed && changed };
|
|
416
451
|
}
|
|
@@ -433,12 +468,8 @@ function uninstallClaudeShaped(file, events, opts = {}) {
|
|
|
433
468
|
}
|
|
434
469
|
if (!changed) return { file, changed: false };
|
|
435
470
|
if (!Object.keys(hooks).length) delete settings2.hooks;
|
|
436
|
-
if (opts.created && !Object.keys(settings2).length)
|
|
437
|
-
|
|
438
|
-
return { file, changed: true, note: "removed (sessionpipe created it)" };
|
|
439
|
-
}
|
|
440
|
-
writeFileSync(file, formatJson(settings2, f));
|
|
441
|
-
return { file, changed: true };
|
|
471
|
+
if (opts.created && !Object.keys(settings2).length) return removeEmptied(file, formatJson(settings2, f));
|
|
472
|
+
return writeBack(file, formatJson(settings2, f)) ?? { file, changed: true };
|
|
442
473
|
}
|
|
443
474
|
function installedClaudeShaped(file, harness, events, cmd, o) {
|
|
444
475
|
const f = readJsonFile(file);
|
|
@@ -517,7 +548,7 @@ var claudeCode = {
|
|
|
517
548
|
configFiles: (env = process.env) => claudeDirs(env).map(settingsIn),
|
|
518
549
|
install: (cmd, env = process.env, opts = {}) => claudeDirs(env).flatMap((d) => {
|
|
519
550
|
const hooks = installClaudeShaped(settingsIn(d), NAME, eventsFor(opts.lean), cmd, OPTS);
|
|
520
|
-
const line = opts.statusLine === void 0 ? null : statusLine(settingsIn(d), opts.statusLine, cmd);
|
|
551
|
+
const line = opts.statusLine === void 0 || hooks.skipped ? null : statusLine(settingsIn(d), opts.statusLine, cmd);
|
|
521
552
|
return line ? [hooks, line] : [hooks];
|
|
522
553
|
}),
|
|
523
554
|
uninstall: (env = process.env, opts = {}) => claudeDirs(env).map((d) => {
|
|
@@ -525,7 +556,9 @@ var claudeCode = {
|
|
|
525
556
|
const hooks = uninstallClaudeShaped(settingsIn(d), CLAUDE_EVENTS, {
|
|
526
557
|
created: opts.created?.includes(settingsIn(d))
|
|
527
558
|
});
|
|
528
|
-
|
|
559
|
+
if (line?.changed && !line.skipped && hooks.skipped)
|
|
560
|
+
return { ...hooks, note: `status line removed, hooks not: ${hooks.note?.replace(/; not touched$/, "")}` };
|
|
561
|
+
return line && !hooks.changed && !hooks.skipped ? line : hooks;
|
|
529
562
|
}),
|
|
530
563
|
installed: (cmd, env = process.env, opts = {}) => claudeDirs(env).map((d) => ({
|
|
531
564
|
file: settingsIn(d),
|
|
@@ -620,7 +653,8 @@ var claudeCode = {
|
|
|
620
653
|
attention_id: call_id ?? permissionId(),
|
|
621
654
|
kind: "permission",
|
|
622
655
|
tool,
|
|
623
|
-
message: tool ? `${tool}${describe(s.tool_input)}` : void 0
|
|
656
|
+
message: tool ? `${tool}${describe(s.tool_input)}` : void 0,
|
|
657
|
+
agent_id
|
|
624
658
|
})
|
|
625
659
|
);
|
|
626
660
|
break;
|
|
@@ -629,7 +663,8 @@ var claudeCode = {
|
|
|
629
663
|
ev("attention.needed", {
|
|
630
664
|
attention_id: `notif-${Date.now()}`,
|
|
631
665
|
kind: notifKind(s.notification_type),
|
|
632
|
-
message: typeof s.message === "string" ? s.message.slice(0, 200) : void 0
|
|
666
|
+
message: typeof s.message === "string" ? s.message.slice(0, 200) : void 0,
|
|
667
|
+
agent_id
|
|
633
668
|
})
|
|
634
669
|
);
|
|
635
670
|
break;
|
|
@@ -754,8 +789,11 @@ function statusLine(file, want, cmd) {
|
|
|
754
789
|
if (want ? ours && cur?.command === command && cur?.refreshInterval === LINE_REFRESH_S : !ours) return null;
|
|
755
790
|
if (want) f.value.statusLine = { type: "command", command, refreshInterval: LINE_REFRESH_S };
|
|
756
791
|
else delete f.value.statusLine;
|
|
757
|
-
|
|
758
|
-
|
|
792
|
+
return writeBack(file, formatJson(f.value, f), f.existed) ?? {
|
|
793
|
+
file,
|
|
794
|
+
changed: true,
|
|
795
|
+
note: want ? "status line written (account limits)" : "status line removed"
|
|
796
|
+
};
|
|
759
797
|
}
|
|
760
798
|
var epochIso = (t) => typeof t === "number" && t > 0 && t < 1e11 ? new Date(t * 1e3).toISOString() : void 0;
|
|
761
799
|
var WINDOW_MINUTES = { five_hour: 300, seven_day: 10080 };
|
|
@@ -1247,16 +1285,7 @@ function probe(bin, args) {
|
|
|
1247
1285
|
}
|
|
1248
1286
|
|
|
1249
1287
|
// ../core/src/adapters/antigravity.ts
|
|
1250
|
-
import {
|
|
1251
|
-
existsSync as existsSync3,
|
|
1252
|
-
mkdirSync as mkdirSync2,
|
|
1253
|
-
readdirSync as readdirSync3,
|
|
1254
|
-
readFileSync as readFileSync4,
|
|
1255
|
-
realpathSync,
|
|
1256
|
-
statSync as statSync4,
|
|
1257
|
-
unlinkSync as unlinkSync2,
|
|
1258
|
-
writeFileSync as writeFileSync3
|
|
1259
|
-
} from "node:fs";
|
|
1288
|
+
import { existsSync as existsSync3, readdirSync as readdirSync3, readFileSync as readFileSync4, realpathSync, statSync as statSync4 } from "node:fs";
|
|
1260
1289
|
import path5 from "node:path";
|
|
1261
1290
|
var NAME2 = "antigravity";
|
|
1262
1291
|
var HOOK_NAME = "sessionpipe";
|
|
@@ -1288,10 +1317,8 @@ var antigravity = {
|
|
|
1288
1317
|
const e = entry(cmd);
|
|
1289
1318
|
if (JSON.stringify(hooks[HOOK_NAME]) === JSON.stringify(e)) return [{ file, changed: false }];
|
|
1290
1319
|
hooks[HOOK_NAME] = e;
|
|
1291
|
-
mkdirSync2(path5.dirname(file), { recursive: true });
|
|
1292
|
-
writeFileSync3(file, formatJson(hooks, f));
|
|
1293
1320
|
return [
|
|
1294
|
-
{
|
|
1321
|
+
writeBack(file, formatJson(hooks, f), f.existed) ?? {
|
|
1295
1322
|
file,
|
|
1296
1323
|
changed: true,
|
|
1297
1324
|
created: !f.existed,
|
|
@@ -1307,12 +1334,8 @@ var antigravity = {
|
|
|
1307
1334
|
const hooks = f.value;
|
|
1308
1335
|
if (!(HOOK_NAME in hooks)) return [{ file, changed: false }];
|
|
1309
1336
|
delete hooks[HOOK_NAME];
|
|
1310
|
-
if (opts.created?.includes(file) && !Object.keys(hooks).length)
|
|
1311
|
-
|
|
1312
|
-
return [{ file, changed: true, note: "removed (sessionpipe created it)" }];
|
|
1313
|
-
}
|
|
1314
|
-
writeFileSync3(file, formatJson(hooks, f));
|
|
1315
|
-
return [{ file, changed: true }];
|
|
1337
|
+
if (opts.created?.includes(file) && !Object.keys(hooks).length) return [removeEmptied(file, formatJson(hooks, f))];
|
|
1338
|
+
return [writeBack(file, formatJson(hooks, f)) ?? { file, changed: true }];
|
|
1316
1339
|
},
|
|
1317
1340
|
installed(cmd, env = process.env) {
|
|
1318
1341
|
const file = hooksFile(env);
|
|
@@ -1535,7 +1558,7 @@ function antigravityFacts(file, opts) {
|
|
|
1535
1558
|
}
|
|
1536
1559
|
|
|
1537
1560
|
// ../core/src/adapters/codex.ts
|
|
1538
|
-
import { existsSync as existsSync4,
|
|
1561
|
+
import { existsSync as existsSync4, readdirSync as readdirSync4, readFileSync as readFileSync5 } from "node:fs";
|
|
1539
1562
|
import path6 from "node:path";
|
|
1540
1563
|
|
|
1541
1564
|
// ../core/src/adapters/codex-config.ts
|
|
@@ -1688,29 +1711,30 @@ var configFile = (env) => path6.join(codexHome(env), "config.toml");
|
|
|
1688
1711
|
var sessionsDir = (env) => path6.join(codexHome(env), "sessions");
|
|
1689
1712
|
var validTool3 = (n) => typeof n === "string" && /^[A-Za-z0-9_.:-]{1,120}$/.test(n);
|
|
1690
1713
|
var endReason2 = (r) => r === "clear" || r === "logout" || r === "exit" ? r : "other";
|
|
1714
|
+
var UNTIL_APPROVED = "Codex will report nothing until you approve the hooks: start `codex` and accept the hook review";
|
|
1691
1715
|
function installNotify(cmd, env) {
|
|
1692
1716
|
const file = configFile(env);
|
|
1693
1717
|
let text = "";
|
|
1718
|
+
let existed = true;
|
|
1694
1719
|
try {
|
|
1695
1720
|
text = readFileSync5(file, "utf8");
|
|
1696
|
-
} catch {
|
|
1721
|
+
} catch (e) {
|
|
1722
|
+
existed = e.code !== "ENOENT";
|
|
1697
1723
|
}
|
|
1698
1724
|
const argv = cmd([NAME3, "notify"]).argv;
|
|
1699
1725
|
const line = `notify = ${JSON.stringify(argv)}`;
|
|
1700
1726
|
const n = readNotify(text);
|
|
1701
|
-
const write = (next) => {
|
|
1702
|
-
|
|
1703
|
-
|
|
1727
|
+
const write = (next, note) => {
|
|
1728
|
+
const bad = writeBack(file, next, existed);
|
|
1729
|
+
return bad ? { ...bad, note: `${bad.note}. ${UNTIL_APPROVED}` } : { file, changed: true, note };
|
|
1704
1730
|
};
|
|
1705
1731
|
if (n && !n.other) {
|
|
1706
1732
|
if (!n.misplaced && JSON.stringify(n.argv) === JSON.stringify(argv))
|
|
1707
1733
|
return { file, changed: false, note: "notify current" };
|
|
1708
|
-
write(
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
note: n.misplaced ? "notify moved to the top level (it sat inside a [table], where Codex never reads it)" : "notify updated"
|
|
1713
|
-
};
|
|
1734
|
+
return write(
|
|
1735
|
+
withNotify(text, line),
|
|
1736
|
+
n.misplaced ? "notify moved to the top level (it sat inside a [table], where Codex never reads it)" : "notify updated"
|
|
1737
|
+
);
|
|
1714
1738
|
}
|
|
1715
1739
|
if (n?.other) {
|
|
1716
1740
|
const prev = previousNotify(n.argv);
|
|
@@ -1719,20 +1743,20 @@ function installNotify(cmd, env) {
|
|
|
1719
1743
|
if (JSON.stringify(prev) === JSON.stringify(argv))
|
|
1720
1744
|
return { file, changed: false, note: "notify current (after Codex Computer Use)" };
|
|
1721
1745
|
}
|
|
1722
|
-
if (!prev || OURS2.test(JSON.stringify(prev)))
|
|
1723
|
-
write(
|
|
1724
|
-
|
|
1725
|
-
|
|
1746
|
+
if (!prev || OURS2.test(JSON.stringify(prev)))
|
|
1747
|
+
return write(
|
|
1748
|
+
replaceNotify(text, n, `notify = ${withPreviousRaw(n.raw, argv)}`),
|
|
1749
|
+
"chained after Codex Computer Use (--previous-notify)"
|
|
1750
|
+
);
|
|
1726
1751
|
}
|
|
1727
1752
|
return {
|
|
1728
1753
|
file,
|
|
1729
1754
|
changed: false,
|
|
1730
1755
|
skipped: true,
|
|
1731
|
-
note: `notify belongs to ${(n.argv?.[0] ?? n.raw).replace(/^.*\//, "").slice(0, 40)}; left alone.
|
|
1756
|
+
note: `notify belongs to ${(n.argv?.[0] ?? n.raw).replace(/^.*\//, "").slice(0, 40)}; left alone. ${UNTIL_APPROVED}`
|
|
1732
1757
|
};
|
|
1733
1758
|
}
|
|
1734
|
-
write(withNotify(text, line));
|
|
1735
|
-
return { file, changed: true, note: "notify set at the top level" };
|
|
1759
|
+
return write(withNotify(text, line), "notify set at the top level");
|
|
1736
1760
|
}
|
|
1737
1761
|
function uninstallNotify(env) {
|
|
1738
1762
|
const file = configFile(env);
|
|
@@ -1744,15 +1768,13 @@ function uninstallNotify(env) {
|
|
|
1744
1768
|
}
|
|
1745
1769
|
const n = readNotify(text);
|
|
1746
1770
|
if (!n) return { file, changed: false };
|
|
1747
|
-
if (!n.other) {
|
|
1748
|
-
writeFileSync4(file, withoutNotify(text));
|
|
1749
|
-
return { file, changed: true };
|
|
1750
|
-
}
|
|
1771
|
+
if (!n.other) return writeBack(file, withoutNotify(text)) ?? { file, changed: true };
|
|
1751
1772
|
const prev = previousNotify(n.argv);
|
|
1752
|
-
if (isComputerUse(n.argv) && prev && OURS2.test(JSON.stringify(prev)))
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1773
|
+
if (isComputerUse(n.argv) && prev && OURS2.test(JSON.stringify(prev)))
|
|
1774
|
+
return writeBack(file, replaceNotify(text, n, `notify = ${stripPreviousRaw(n.raw)}`)) ?? {
|
|
1775
|
+
file,
|
|
1776
|
+
changed: true
|
|
1777
|
+
};
|
|
1756
1778
|
return { file, changed: false };
|
|
1757
1779
|
}
|
|
1758
1780
|
function findRollout(threadId, env = process.env) {
|
|
@@ -1784,8 +1806,12 @@ function rolloutMeta(file) {
|
|
|
1784
1806
|
return scanLines(file, (line) => parseLines([line])[0] ?? {});
|
|
1785
1807
|
}
|
|
1786
1808
|
function ofAnotherThread(file, id) {
|
|
1809
|
+
const other = threadOf(file);
|
|
1810
|
+
return !!other && other !== id.toLowerCase();
|
|
1811
|
+
}
|
|
1812
|
+
function threadOf(file) {
|
|
1787
1813
|
const m = /-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl(?:\.zst)?$/i.exec(file);
|
|
1788
|
-
return
|
|
1814
|
+
return m?.[1] ? m[1].toLowerCase() : null;
|
|
1789
1815
|
}
|
|
1790
1816
|
var codex = {
|
|
1791
1817
|
name: NAME3,
|
|
@@ -1864,6 +1890,8 @@ var codex = {
|
|
|
1864
1890
|
const turn_id = typeof s.turn_id === "string" ? s.turn_id : void 0;
|
|
1865
1891
|
const tool = validTool3(s.tool_name) ? s.tool_name : void 0;
|
|
1866
1892
|
const call_id = typeof s.tool_use_id === "string" ? s.tool_use_id : void 0;
|
|
1893
|
+
const thread = typeof s.transcript_path === "string" ? threadOf(s.transcript_path) : null;
|
|
1894
|
+
const agent_id = typeof s.agent_id === "string" && s.agent_id ? s.agent_id : typeof s.subagent_id === "string" && s.subagent_id ? s.subagent_id : thread && thread !== String(id).toLowerCase() ? thread : void 0;
|
|
1867
1895
|
const ev = (type, data) => ({ type, data: prune3(data), harnessEvent: event });
|
|
1868
1896
|
const events = [];
|
|
1869
1897
|
switch (event) {
|
|
@@ -1883,17 +1911,30 @@ var codex = {
|
|
|
1883
1911
|
);
|
|
1884
1912
|
break;
|
|
1885
1913
|
case "PreToolUse":
|
|
1886
|
-
if (tool) events.push(ev("tool.started", { tool, call_id, turn_id, input: s.tool_input }));
|
|
1914
|
+
if (tool) events.push(ev("tool.started", { tool, call_id, turn_id, agent_id, input: s.tool_input }));
|
|
1887
1915
|
break;
|
|
1888
1916
|
case "PostToolUse":
|
|
1889
1917
|
if (tool)
|
|
1890
1918
|
events.push(
|
|
1891
|
-
ev("tool.ended", {
|
|
1919
|
+
ev("tool.ended", {
|
|
1920
|
+
tool,
|
|
1921
|
+
call_id,
|
|
1922
|
+
turn_id,
|
|
1923
|
+
agent_id,
|
|
1924
|
+
ok: true,
|
|
1925
|
+
input: s.tool_input,
|
|
1926
|
+
output: s.tool_response
|
|
1927
|
+
})
|
|
1892
1928
|
);
|
|
1893
1929
|
break;
|
|
1894
1930
|
case "PermissionRequest":
|
|
1895
1931
|
events.push(
|
|
1896
|
-
ev("attention.needed", {
|
|
1932
|
+
ev("attention.needed", {
|
|
1933
|
+
attention_id: call_id ?? `perm-${Date.now()}`,
|
|
1934
|
+
kind: "permission",
|
|
1935
|
+
tool,
|
|
1936
|
+
agent_id
|
|
1937
|
+
})
|
|
1897
1938
|
);
|
|
1898
1939
|
break;
|
|
1899
1940
|
case "Stop":
|
|
@@ -2383,7 +2424,7 @@ var CHAIN_LIMIT = 4e3;
|
|
|
2383
2424
|
var CHAIN_SQL = `WITH RECURSIVE chain(node_id, parent_node_id, chat_message, created_at) AS (
|
|
2384
2425
|
SELECT node_id, parent_node_id, chat_message, created_at FROM message_nodes
|
|
2385
2426
|
WHERE session_id = ? AND node_id = (SELECT main_chain_id FROM sessions WHERE id = ?)
|
|
2386
|
-
UNION
|
|
2427
|
+
UNION
|
|
2387
2428
|
SELECT m.node_id, m.parent_node_id, m.chat_message, m.created_at FROM message_nodes m
|
|
2388
2429
|
JOIN chain c ON m.node_id = c.parent_node_id AND m.session_id = ? AND m.node_id >= ?
|
|
2389
2430
|
)
|
|
@@ -2675,7 +2716,18 @@ function matches(expect, got, pathStr = "") {
|
|
|
2675
2716
|
async function runAdapterFixtures(files) {
|
|
2676
2717
|
const results = [];
|
|
2677
2718
|
for (const file of files) {
|
|
2678
|
-
|
|
2719
|
+
let fx;
|
|
2720
|
+
try {
|
|
2721
|
+
fx = JSON.parse(readFileSync7(file, "utf8"));
|
|
2722
|
+
} catch (e) {
|
|
2723
|
+
const code = e.code;
|
|
2724
|
+
results.push({ file, ok: false, why: code ? `not readable: ${code}` : `not JSON: ${e.message}` });
|
|
2725
|
+
continue;
|
|
2726
|
+
}
|
|
2727
|
+
if (typeof fx?.harness !== "string" || !fx.input || !Array.isArray(fx.expect)) {
|
|
2728
|
+
results.push({ file, ok: false, why: "not an adapter fixture: it needs harness, input and expect" });
|
|
2729
|
+
continue;
|
|
2730
|
+
}
|
|
2679
2731
|
const adapter = adapterByName(fx.harness);
|
|
2680
2732
|
if (!adapter) {
|
|
2681
2733
|
results.push({ file, ok: false, why: `no adapter ${fx.harness}` });
|