sessionpipe-conformance 0.6.0 → 0.7.0

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.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // sessionpipe-conformance 0.6.0 · Apache-2.0 · https://sessionpipe.org
2
+ // sessionpipe-conformance 0.7.0 · Apache-2.0 · https://sessionpipe.org
3
3
 
4
4
  // src/cli.ts
5
5
  import { readdirSync as readdirSync5, statSync as statSync4 } from "node:fs";
@@ -175,6 +175,9 @@ function readClaude(lines, from) {
175
175
  }
176
176
  return pairTurns(msgs, endOf(lines));
177
177
  }
178
+ function codexInjected(text) {
179
+ return /^<[a-z_-]+>/i.test(text) || /^# AGENTS\.md instructions\b/i.test(text);
180
+ }
178
181
  function readCodex(lines, from) {
179
182
  const msgs = [];
180
183
  for (let i = from; i < lines.length; i++) {
@@ -186,7 +189,7 @@ function readCodex(lines, from) {
186
189
  const text = textParts(p.content, ["input_text", "output_text"]).trim();
187
190
  if (!text) continue;
188
191
  if (p.role === "user") {
189
- if (/^<[a-z_-]+>/i.test(text)) continue;
192
+ if (codexInjected(text)) continue;
190
193
  msgs.push({ role: "user", text, at, line: i });
191
194
  } else if (p.role === "assistant") msgs.push({ role: "assistant", text, at, line: i });
192
195
  }
@@ -357,20 +360,19 @@ function installedClaudeShaped(file, harness, events, cmd, o) {
357
360
  // ../core/src/adapters/antigravity.ts
358
361
  var NAME = "antigravity";
359
362
  var HOOK_NAME = "sessionpipe";
360
- var AG_EVENTS = ["PreInvocation", "PostInvocation", "PreToolUse", "PostToolUse", "Stop"];
363
+ var AG_EVENTS = ["PreInvocation", "PostInvocation", "PostToolUse", "Stop"];
364
+ var AG_STALE_PRETOOL = '{"decision":"ask","reason":"sessionpipe: an outdated PreToolUse hook is still loaded. Restart this conversation (or run sessionpipe install) to drop it."}\n';
365
+ var antigravityAnswer = (event) => event === "PreToolUse" ? AG_STALE_PRETOOL : "{}\n";
361
366
  var gemini = (env) => env.GEMINI_CLI_HOME || path3.join(HOME, ".gemini");
362
367
  var hooksFile = (env) => path3.join(gemini(env), "config", "hooks.json");
363
368
  var projectsDir = (env) => path3.join(gemini(env), "config", "projects");
364
369
  var dataDirs = (env) => ["antigravity", "antigravity-cli", "antigravity-ide"].map((d) => path3.join(gemini(env), d));
365
370
  var ID_RE = /^[A-Za-z0-9_-]{1,128}$/;
366
371
  var validTool = (n) => typeof n === "string" && /^[A-Za-z0-9_.:-]{1,120}$/.test(n);
367
- function entry(cmd, lean) {
372
+ function entry(cmd) {
368
373
  const handler = (e) => ({ type: "command", command: cmd([NAME, e]).command, timeout: 5 });
369
374
  const out = { enabled: true };
370
- for (const e of AG_EVENTS) {
371
- if (lean && e === "PreToolUse") continue;
372
- out[e] = /Tool/.test(e) ? [{ matcher: "*", hooks: [handler(e)] }] : [handler(e)];
373
- }
375
+ for (const e of AG_EVENTS) out[e] = /Tool/.test(e) ? [{ matcher: "*", hooks: [handler(e)] }] : [handler(e)];
374
376
  return out;
375
377
  }
376
378
  var antigravity = {
@@ -378,12 +380,12 @@ var antigravity = {
378
380
  events: AG_EVENTS,
379
381
  detect: (env = process.env) => existsSync2(path3.join(gemini(env), "config")) || dataDirs(env).some((d) => existsSync2(d)),
380
382
  configFiles: (env = process.env) => [hooksFile(env)],
381
- install(cmd, env = process.env, opts = {}) {
383
+ install(cmd, env = process.env) {
382
384
  const file = hooksFile(env);
383
385
  const f = readJsonFile(file);
384
386
  if (!f.ok) return [{ file, changed: false, skipped: true, note: `${f.reason}; not touched` }];
385
387
  const hooks = f.value;
386
- const e = entry(cmd, opts.lean);
388
+ const e = entry(cmd);
387
389
  if (JSON.stringify(hooks[HOOK_NAME]) === JSON.stringify(e)) return [{ file, changed: false }];
388
390
  hooks[HOOK_NAME] = e;
389
391
  mkdirSync2(path3.dirname(file), { recursive: true });
@@ -412,14 +414,14 @@ var antigravity = {
412
414
  writeFileSync2(file, formatJson(hooks, f));
413
415
  return [{ file, changed: true }];
414
416
  },
415
- installed(cmd, env = process.env, opts = {}) {
417
+ installed(cmd, env = process.env) {
416
418
  const file = hooksFile(env);
417
419
  const f = readJsonFile(file);
418
420
  const have = f.ok ? f.value[HOOK_NAME] : void 0;
419
421
  return [
420
422
  {
421
423
  file,
422
- state: !have ? "missing" : JSON.stringify(have) === JSON.stringify(entry(cmd, opts.lean)) ? "current" : "stale"
424
+ state: !have ? "missing" : JSON.stringify(have) === JSON.stringify(entry(cmd)) ? "current" : "stale"
423
425
  }
424
426
  ];
425
427
  },
@@ -431,7 +433,8 @@ var antigravity = {
431
433
  } catch {
432
434
  }
433
435
  const id = s.conversationId ?? s.session_id ?? s.sessionId;
434
- if (!id) return { session: { id: "" }, events: [], stdout: "{}\n" };
436
+ const stdout = antigravityAnswer(event);
437
+ if (!id) return { session: { id: "" }, events: [], stdout };
435
438
  const workspaces = agWorkspaces(s.workspacePaths);
436
439
  const session = { id: String(id), cwd: workspaces[0] ?? input.cwd };
437
440
  if (typeof s.modelName === "string" && s.modelName !== "auto") session.model = s.modelName;
@@ -452,7 +455,8 @@ var antigravity = {
452
455
  if (tool) events.push(ev("tool.started", { tool, input: toolCall?.args }));
453
456
  break;
454
457
  case "PostToolUse":
455
- if (tool)
458
+ if (!tool) events.push(ev("session.heartbeat", {}));
459
+ else
456
460
  events.push(
457
461
  ev("tool.ended", {
458
462
  tool,
@@ -466,9 +470,9 @@ var antigravity = {
466
470
  events.push(ev("turn.ended", { reason: s.error ? "error" : "stop" }));
467
471
  break;
468
472
  default:
469
- return { session, events: [], stdout: "{}\n" };
473
+ return { session, events: [], stdout };
470
474
  }
471
- const r2 = { session, events, stdout: "{}\n", hints: { workspaces } };
475
+ const r2 = { session, events, stdout, hints: { workspaces } };
472
476
  if (typeof s.transcriptPath === "string") r2.transcript = s.transcriptPath;
473
477
  return r2;
474
478
  },
@@ -1423,7 +1427,8 @@ function uninstallNotify(env) {
1423
1427
  }
1424
1428
  return { file, changed: false };
1425
1429
  }
1426
- function findRollout(threadId, env) {
1430
+ function findRollout(threadId, env = process.env) {
1431
+ if (!/^[A-Za-z0-9-]{8,128}$/.test(threadId)) return null;
1427
1432
  let best = null;
1428
1433
  const walk2 = (dir, depth) => {
1429
1434
  let names = [];
@@ -1434,7 +1439,7 @@ function findRollout(threadId, env) {
1434
1439
  }
1435
1440
  for (const n of names.sort().reverse()) {
1436
1441
  const p = path5.join(dir, n);
1437
- if (n.endsWith(".jsonl") && n.includes(threadId)) {
1442
+ if (n.endsWith(`-${threadId}.jsonl`)) {
1438
1443
  best = p;
1439
1444
  return;
1440
1445
  }
@@ -1639,7 +1644,7 @@ function codexFacts(file) {
1639
1644
  const p = j.payload;
1640
1645
  if (j.type !== "response_item" || !p || p.type !== "message" || p.role !== "user") continue;
1641
1646
  const text = (p.content ?? []).filter((b) => b && b.type === "input_text" && typeof b.text === "string").map((b) => b.text).join("\n").trim();
1642
- if (!text || /^<[a-z_-]+>/i.test(text)) continue;
1647
+ if (!text || codexInjected(text)) continue;
1643
1648
  const line = text.split("\n").find((l) => l.trim()) ?? "";
1644
1649
  out.title = line.length > 80 ? `${line.slice(0, 80).replace(/\s+\S*$/, "")}\u2026` : line;
1645
1650
  out.title_source = "first-ask";