trantor 0.18.82 → 0.18.85

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.
@@ -0,0 +1,81 @@
1
+ // CLI-owned records let read-only turns and their sub-agents prove liveness (#10497).
2
+ import { spawnSync } from "node:child_process";
3
+ import { readFileSync, readdirSync, realpathSync, statSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { createHash } from "node:crypto";
6
+
7
+ const canonical = p => { try { return realpathSync(p); } catch { return p; } };
8
+ const sql = s => `'${String(s).replaceAll("'", "''")}'`;
9
+ const entries = p => { try { return readdirSync(p, { withFileTypes: true }); } catch { return []; } };
10
+ const mtime = p => { try { return statSync(p).mtimeMs; } catch { return 0; } };
11
+ function logTime(dir, budget = { left: 20000 }) {
12
+ let best = 0;
13
+ for (const e of entries(dir)) {
14
+ if (--budget.left < 0) break;
15
+ const path = join(dir, e.name);
16
+ if (e.isDirectory()) best = Math.max(best, logTime(path, budget));
17
+ else if (e.name.endsWith(".jsonl")) best = Math.max(best, mtime(path));
18
+ }
19
+ return best;
20
+ }
21
+ function query(db, statement) {
22
+ try {
23
+ const r = spawnSync("sqlite3", ["-readonly", db, statement], {
24
+ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 2000,
25
+ });
26
+ return r.status === 0 ? r.stdout.trim() : "";
27
+ } catch { return ""; }
28
+ }
29
+
30
+ // Pin the root once discovered. A fresh root must have been created during this turn;
31
+ // a resumed root is supplied by the runner. Never use global DB/WAL mtimes.
32
+ export function sessionActivityReader({ kind, sid = "", db, workDir, home, startedAt, transcriptDir }) {
33
+ let root = sid, logDir = "";
34
+ const cwd = canonical(workDir);
35
+ return () => {
36
+ if (kind === "opencode") {
37
+ if (!root) root = query(db, `SELECT id FROM session WHERE directory IN (${sql(workDir)},${sql(cwd)})`
38
+ + ` AND parent_id IS NULL AND time_created>=${Math.floor(startedAt)} ORDER BY time_created DESC LIMIT 1;`);
39
+ if (!/^ses_[A-Za-z0-9]+$/.test(root)) return 0;
40
+ const value = query(db, `WITH RECURSIVE own(id) AS (SELECT id FROM session WHERE id=${sql(root)}`
41
+ + ` UNION SELECT s.id FROM session s JOIN own ON s.parent_id=own.id)`
42
+ + ` SELECT MAX(t) FROM (SELECT MAX(time_created,time_updated) t FROM message WHERE session_id IN (SELECT id FROM own)`
43
+ + ` UNION ALL SELECT MAX(time_created,time_updated) t FROM part WHERE session_id IN (SELECT id FROM own));`);
44
+ return Number(value) || 0;
45
+ }
46
+ if (kind === "claude") {
47
+ if (!root) {
48
+ const newest = entries(transcriptDir).filter(e => e.isFile() && e.name.endsWith(".jsonl"))
49
+ .map(e => ({ name: e.name, ts: mtime(join(transcriptDir, e.name)) }))
50
+ .filter(e => e.ts >= startedAt).sort((a, b) => b.ts - a.ts)[0];
51
+ if (newest) root = newest.name.slice(0, -6);
52
+ }
53
+ if (!root || root.includes("/")) return 0;
54
+ return Math.max(mtime(join(transcriptDir, `${root}.jsonl`)), logTime(join(transcriptDir, root)));
55
+ }
56
+ if (kind !== "kimi") return 0;
57
+ if (!logDir) {
58
+ // kimi-code indexes the actual workdir and session directory; avoid guessing its hash.
59
+ try {
60
+ const rows = readFileSync(join(home, ".kimi-code", "session_index.jsonl"), "utf8").trim().split("\n");
61
+ for (const line of rows.reverse()) {
62
+ let row; try { row = JSON.parse(line); } catch { continue; }
63
+ if (canonical(row.workDir || "") !== cwd || !row.sessionDir || (root && row.sessionId !== root)) continue;
64
+ if (!root && mtime(row.sessionDir) < startedAt) continue;
65
+ root = row.sessionId; logDir = row.sessionDir; break;
66
+ }
67
+ } catch {}
68
+ // Python kimi-cli uses md5(canonical cwd)/session-id.
69
+ if (!logDir) {
70
+ const parent = join(home, ".kimi", "sessions", createHash("md5").update(cwd).digest("hex"));
71
+ if (root && !root.includes("/")) logDir = join(parent, root);
72
+ else {
73
+ const newest = entries(parent).filter(e => e.isDirectory()).map(e => ({ name: e.name, ts: mtime(join(parent, e.name)) }))
74
+ .filter(e => e.ts >= startedAt).sort((a, b) => b.ts - a.ts)[0];
75
+ if (newest) { root = newest.name; logDir = join(parent, root); }
76
+ }
77
+ }
78
+ }
79
+ return logDir ? logTime(logDir) : 0;
80
+ };
81
+ }
package/lib/store-pg.mjs CHANGED
@@ -154,6 +154,7 @@ function kvFromState(state) {
154
154
  proposals: state.proposals || [],
155
155
  contractReap: state.contractReap || {},
156
156
  meta: {
157
+ overseerState: state.overseerState || {},
157
158
  taskSeq: Number(state.taskSeq || 0),
158
159
  verifyGateSeq: Number(state.verifyGateSeq || 0),
159
160
  proposalSeq: Number(state.proposalSeq || 0),
@@ -731,6 +732,7 @@ export class PgStore {
731
732
  inviteTokens: meta.inviteTokens && typeof meta.inviteTokens === "object" ? meta.inviteTokens : {},
732
733
  instances: meta.instances && typeof meta.instances === "object" ? meta.instances : {},
733
734
  focus: kv.focus && typeof kv.focus === "object" ? kv.focus : {},
735
+ overseerState: meta.overseerState || {},
734
736
  orgPolicy: kv.orgPolicy && typeof kv.orgPolicy === "object" ? kv.orgPolicy : {},
735
737
  contractReap: kv.contractReap && typeof kv.contractReap === "object" ? kv.contractReap : {},
736
738
  eventSeq: Math.max(Number(eventMaxRow?.rows?.[0]?.max_id || 0), Number(meta.eventSeq || 0)),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trantor",
3
- "version": "0.18.82",
3
+ "version": "0.18.85",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "trantor": "bin/cli.mjs"