sessionpipe-core 0.11.0 → 0.13.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/control.js +26 -11
- package/dist/control.js.map +3 -3
- package/dist/index.js +357 -116
- package/dist/index.js.map +4 -4
- package/dist/schema/v1.d.ts +77 -1
- package/dist/schema/v1.d.ts.map +1 -1
- package/dist/schema.js +83 -11
- package/dist/schema.js.map +2 -2
- package/dist/service.js +1 -1
- package/dist/src/adapters/acp-control.d.ts.map +1 -1
- package/dist/src/adapters/claude-code-control.d.ts +136 -6
- package/dist/src/adapters/claude-code-control.d.ts.map +1 -1
- package/dist/src/adapters/claude-code.d.ts +6 -0
- package/dist/src/adapters/claude-code.d.ts.map +1 -1
- package/dist/src/adapters/codex-control.d.ts.map +1 -1
- package/dist/src/adapters/gemini-cli.d.ts +3 -2
- package/dist/src/adapters/gemini-cli.d.ts.map +1 -1
- package/dist/src/adapters/headless.d.ts +26 -1
- package/dist/src/adapters/headless.d.ts.map +1 -1
- package/dist/src/adapters/types.d.ts +6 -0
- package/dist/src/adapters/types.d.ts.map +1 -1
- package/dist/src/control/verify.d.ts +3 -0
- package/dist/src/control/verify.d.ts.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/launched-by.d.ts +20 -3
- package/dist/src/launched-by.d.ts.map +1 -1
- package/dist/src/privacy/filter.d.ts.map +1 -1
- package/dist/src/readers/transcripts.d.ts +11 -1
- package/dist/src/readers/transcripts.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// sessionpipe-core 0.
|
|
1
|
+
// sessionpipe-core 0.13.0 · Apache-2.0 · https://sessionpipe.org
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __export = (target, all) => {
|
|
4
4
|
for (var name in all)
|
|
@@ -211,7 +211,14 @@ ${m.text}`;
|
|
|
211
211
|
continue;
|
|
212
212
|
}
|
|
213
213
|
if (cur) turns.push(cur);
|
|
214
|
-
cur = {
|
|
214
|
+
cur = {
|
|
215
|
+
user: m.text,
|
|
216
|
+
assistant: "",
|
|
217
|
+
at: m.at,
|
|
218
|
+
startLine: m.line,
|
|
219
|
+
endLine: m.line,
|
|
220
|
+
...m.injected ? { injected: true } : {}
|
|
221
|
+
};
|
|
215
222
|
} else {
|
|
216
223
|
if (!cur) cur = { user: "", assistant: "", at: m.at, startLine: m.line, endLine: m.line };
|
|
217
224
|
cur.assistant += (cur.assistant ? "\n\n" : "") + m.text;
|
|
@@ -221,10 +228,17 @@ ${m.text}`;
|
|
|
221
228
|
if (cur?.assistant) turns.push(cur);
|
|
222
229
|
const line = cur && !cur.assistant ? cur.startLine : endLine;
|
|
223
230
|
const out = {
|
|
224
|
-
turns: turns.map((t) => ({
|
|
231
|
+
turns: turns.map((t) => ({
|
|
232
|
+
user: t.user,
|
|
233
|
+
assistant: t.assistant,
|
|
234
|
+
at: t.at,
|
|
235
|
+
endLine: t.endLine,
|
|
236
|
+
...t.injected ? { injected: true } : {}
|
|
237
|
+
})),
|
|
225
238
|
line
|
|
226
239
|
};
|
|
227
|
-
if (cur && !cur.assistant && cur.user)
|
|
240
|
+
if (cur && !cur.assistant && cur.user)
|
|
241
|
+
out.open = { user: cur.user, at: cur.at, ...cur.injected ? { injected: true } : {} };
|
|
228
242
|
return out;
|
|
229
243
|
}
|
|
230
244
|
var isInjected = (text) => /^<[a-z_-]+(?:\s[^>]*)?>/i.test(text) && /<\/[a-z_-]+>\s*$/i.test(text) || /^<!--\s/.test(text) || /^<command-/.test(text);
|
|
@@ -247,27 +261,51 @@ var textParts = (c, kinds) => {
|
|
|
247
261
|
(b) => b && typeof b === "object" && kinds.includes(b.type ?? "") && typeof b.text === "string"
|
|
248
262
|
).map((b) => b.text).join("\n");
|
|
249
263
|
};
|
|
264
|
+
var SPOKEN = /* @__PURE__ */ new Set(["human", "peer"]);
|
|
265
|
+
var PEER_INTRO = /sent a message[^\n]*:$/;
|
|
266
|
+
var PEER_OUTRO = "\n\nThis came from another ";
|
|
267
|
+
var ENVELOPE = /^<cross-session-message\b[^>]*>\n([\s\S]*)\n<\/cross-session-message>$/;
|
|
268
|
+
function peerAsk(origin, text) {
|
|
269
|
+
const body = origin?.body;
|
|
270
|
+
let t = typeof body === "string" && body.trim() ? body : text;
|
|
271
|
+
if (t !== body) {
|
|
272
|
+
const nl = t.indexOf("\n");
|
|
273
|
+
if (nl > 0 && PEER_INTRO.test(t.slice(0, nl))) t = t.slice(nl + 1);
|
|
274
|
+
const outro = t.indexOf(PEER_OUTRO);
|
|
275
|
+
if (outro > 0) t = t.slice(0, outro);
|
|
276
|
+
}
|
|
277
|
+
return (ENVELOPE.exec(t.trim())?.[1] ?? t).trim();
|
|
278
|
+
}
|
|
250
279
|
var queuedPrompt = (a) => {
|
|
251
280
|
if (!a || typeof a !== "object") return "";
|
|
252
281
|
const q = a;
|
|
253
282
|
if (q.type !== "queued_command" || (q.commandMode ?? "prompt") !== "prompt") return "";
|
|
254
|
-
|
|
255
|
-
|
|
283
|
+
const kind = q.origin?.kind ?? "human";
|
|
284
|
+
if (!SPOKEN.has(kind)) return "";
|
|
285
|
+
const text = textParts(q.prompt, ["text"]).trim();
|
|
286
|
+
return kind === "peer" ? peerAsk(q.origin, text) : text;
|
|
256
287
|
};
|
|
288
|
+
var channelText = (text) => /^<channel\b[^>]*>([\s\S]*)<\/channel>$/.exec(text)?.[1]?.trim() ?? "";
|
|
257
289
|
function readClaude(lines, from) {
|
|
258
290
|
const msgs = [];
|
|
259
291
|
for (let i = from; i < lines.length; i++) {
|
|
260
292
|
const j = lines[i] ? parse(lines[i]) : null;
|
|
261
293
|
if (!j || j.isSidechain) continue;
|
|
262
294
|
const origin = j.origin;
|
|
263
|
-
|
|
264
|
-
|
|
295
|
+
const channel = j.type === "user" && origin?.kind === "channel";
|
|
296
|
+
const peer = origin?.kind === "peer";
|
|
297
|
+
if (j.type === "user" && (j.isCompactSummary || j.repeatsCompactSummary)) continue;
|
|
298
|
+
if (j.type === "user" && !channel && !peer && (j.isMeta || origin?.kind && origin.kind !== "human")) continue;
|
|
265
299
|
const at = Date.parse(String(j.timestamp ?? "")) || Date.now();
|
|
266
300
|
const c = j.message?.content;
|
|
267
|
-
if (
|
|
268
|
-
const text = textParts(c, ["text"]).trim();
|
|
301
|
+
if (channel) {
|
|
302
|
+
const text = channelText(textParts(c, ["text"]).trim());
|
|
303
|
+
if (text) msgs.push({ role: "user", text, at, line: i, injected: true });
|
|
304
|
+
} else if (j.type === "user") {
|
|
305
|
+
const raw = textParts(c, ["text"]).trim();
|
|
306
|
+
const text = peer ? peerAsk(origin, raw) : raw;
|
|
269
307
|
if (!text || isInjected(text)) continue;
|
|
270
|
-
msgs.push({ role: "user", text, at, line: i });
|
|
308
|
+
msgs.push({ role: "user", text, at, line: i, ...peer ? { injected: true } : {} });
|
|
271
309
|
} else if (j.type === "assistant" && Array.isArray(c)) {
|
|
272
310
|
const text = textParts(c, ["text"]).trim();
|
|
273
311
|
if (text) msgs.push({ role: "assistant", text, at, line: i });
|
|
@@ -645,13 +683,7 @@ var claudeCode = {
|
|
|
645
683
|
);
|
|
646
684
|
break;
|
|
647
685
|
case "Stop":
|
|
648
|
-
events.push(
|
|
649
|
-
ev("turn.ended", {
|
|
650
|
-
turn_id,
|
|
651
|
-
reason: "stop",
|
|
652
|
-
background: Array.isArray(s.background_tasks) ? s.background_tasks.length : void 0
|
|
653
|
-
})
|
|
654
|
-
);
|
|
686
|
+
events.push(ev("turn.ended", { turn_id, reason: "stop", background: backgroundCount(s.background_tasks) }));
|
|
655
687
|
break;
|
|
656
688
|
case "StopFailure":
|
|
657
689
|
events.push(
|
|
@@ -674,7 +706,8 @@ var claudeCode = {
|
|
|
674
706
|
events.push(
|
|
675
707
|
ev("subagent.ended", {
|
|
676
708
|
agent_id: String(s.agent_id ?? ""),
|
|
677
|
-
agent_type: typeof s.agent_type === "string" ? s.agent_type : void 0
|
|
709
|
+
agent_type: typeof s.agent_type === "string" ? s.agent_type : void 0,
|
|
710
|
+
background: backgroundCount(s.background_tasks, String(s.agent_id ?? ""))
|
|
678
711
|
})
|
|
679
712
|
);
|
|
680
713
|
break;
|
|
@@ -749,6 +782,15 @@ var claudeCode = {
|
|
|
749
782
|
return rows2;
|
|
750
783
|
}
|
|
751
784
|
};
|
|
785
|
+
var WAITER_RE = /(?:^|[\s"'`/\\])sessionpipe(?:\.\w+)?["']?\s+wait(?:\s|$)/;
|
|
786
|
+
function backgroundCount(tasks, ending) {
|
|
787
|
+
if (!Array.isArray(tasks)) return void 0;
|
|
788
|
+
return tasks.filter((t) => {
|
|
789
|
+
const task = t;
|
|
790
|
+
if (ending !== void 0 && task?.id === ending) return false;
|
|
791
|
+
return !(typeof task?.command === "string" && WAITER_RE.test(task.command));
|
|
792
|
+
}).length;
|
|
793
|
+
}
|
|
752
794
|
var LINE_REFRESH_S = 60;
|
|
753
795
|
function statusLine(file, want, cmd) {
|
|
754
796
|
const f = readJsonFile(file);
|
|
@@ -1629,8 +1671,43 @@ import path7 from "node:path";
|
|
|
1629
1671
|
|
|
1630
1672
|
// src/adapters/headless.ts
|
|
1631
1673
|
import { spawn } from "node:child_process";
|
|
1632
|
-
import { accessSync, constants, statSync as statSync3 } from "node:fs";
|
|
1674
|
+
import { accessSync, constants, readFileSync as readFileSync4, statSync as statSync3 } from "node:fs";
|
|
1633
1675
|
import path6 from "node:path";
|
|
1676
|
+
|
|
1677
|
+
// src/launched-by.ts
|
|
1678
|
+
var LAUNCHED_BY_ENV = "SESSIONPIPE_LAUNCHED_BY";
|
|
1679
|
+
var DELEGATED_BY_ENV = "SESSIONPIPE_ASKED_BY";
|
|
1680
|
+
var ASK_CHAIN_ENV = "SESSIONPIPE_ASK_CHAIN";
|
|
1681
|
+
var LINEAGE_ENV = [LAUNCHED_BY_ENV, DELEGATED_BY_ENV, ASK_CHAIN_ENV];
|
|
1682
|
+
var SESSION_REF = /^[a-z][a-z0-9-]{0,39}:[A-Za-z0-9._:-]{1,128}$/;
|
|
1683
|
+
function withoutLineage(env) {
|
|
1684
|
+
const e = { ...env };
|
|
1685
|
+
for (const k of LINEAGE_ENV) delete e[k];
|
|
1686
|
+
return e;
|
|
1687
|
+
}
|
|
1688
|
+
function refIn(env, name) {
|
|
1689
|
+
const v = env[name]?.trim();
|
|
1690
|
+
return v && SESSION_REF.test(v) ? v : void 0;
|
|
1691
|
+
}
|
|
1692
|
+
function launchedBy(env) {
|
|
1693
|
+
return refIn(env, LAUNCHED_BY_ENV);
|
|
1694
|
+
}
|
|
1695
|
+
function delegatedBy(env) {
|
|
1696
|
+
return refIn(env, DELEGATED_BY_ENV);
|
|
1697
|
+
}
|
|
1698
|
+
function readHook(adapter, input) {
|
|
1699
|
+
const r = adapter.fromHook(input);
|
|
1700
|
+
if (r && !r.session.parent_id) {
|
|
1701
|
+
const self = `${adapter.name}:${r.session.id}`;
|
|
1702
|
+
const launcher = launchedBy(input.env);
|
|
1703
|
+
if (launcher && launcher !== self) r.session.launched_by = launcher;
|
|
1704
|
+
const asker = delegatedBy(input.env);
|
|
1705
|
+
if (asker && asker !== self) r.session.delegated_by = asker;
|
|
1706
|
+
}
|
|
1707
|
+
return r;
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
// src/adapters/headless.ts
|
|
1634
1711
|
var JOB_TIMEOUT_MS = 30 * 6e4;
|
|
1635
1712
|
var OUT_CAP = 1024 * 1024;
|
|
1636
1713
|
function isExe(p) {
|
|
@@ -1651,8 +1728,34 @@ function findBinary(o) {
|
|
|
1651
1728
|
for (const d of o.dirs) for (const n of o.names) if (isExe(path6.join(d, n))) return path6.join(d, n);
|
|
1652
1729
|
return null;
|
|
1653
1730
|
}
|
|
1731
|
+
function shimTarget(shim) {
|
|
1732
|
+
let text = "";
|
|
1733
|
+
try {
|
|
1734
|
+
text = readFileSync4(shim, "utf8");
|
|
1735
|
+
} catch {
|
|
1736
|
+
return null;
|
|
1737
|
+
}
|
|
1738
|
+
const m = /"%(?:~dp0|dp0%)\\([^"]+)"\s+%\*/.exec(text);
|
|
1739
|
+
if (!m) return null;
|
|
1740
|
+
const target = path6.resolve(path6.dirname(shim), m[1].split("\\").join(path6.sep));
|
|
1741
|
+
try {
|
|
1742
|
+
return statSync3(target).isFile() ? target : null;
|
|
1743
|
+
} catch {
|
|
1744
|
+
return null;
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
function spawnable(bin, args) {
|
|
1748
|
+
if (!/\.(cmd|bat)$/i.test(bin)) return { file: bin, args };
|
|
1749
|
+
const target = shimTarget(bin);
|
|
1750
|
+
return target ? { file: process.execPath, args: [target, ...args] } : null;
|
|
1751
|
+
}
|
|
1752
|
+
var shimNote = (bin) => `${path6.basename(bin)} is a launcher script that names no program to run; point the harness's override (SESSIONPIPE_CLAUDE, SESSIONPIPE_CODEX, \u2026) at the program itself`;
|
|
1753
|
+
function probe(bin, args) {
|
|
1754
|
+
const s = spawnable(bin, args);
|
|
1755
|
+
return s ? { ...s, shell: false } : { file: [`"${bin}"`, ...args].join(" "), args: [], shell: true };
|
|
1756
|
+
}
|
|
1654
1757
|
function jobEnv(env = process.env) {
|
|
1655
|
-
return { ...env, SESSIONPIPE_CONTROL_JOB: "1" };
|
|
1758
|
+
return { ...withoutLineage(env), SESSIONPIPE_CONTROL_JOB: "1" };
|
|
1656
1759
|
}
|
|
1657
1760
|
function runHeadless(bin, args, o) {
|
|
1658
1761
|
return new Promise((resolve) => {
|
|
@@ -1663,8 +1766,13 @@ function runHeadless(bin, args, o) {
|
|
|
1663
1766
|
let timedOut = false;
|
|
1664
1767
|
let settled = false;
|
|
1665
1768
|
let child;
|
|
1769
|
+
const c = spawnable(bin, args);
|
|
1770
|
+
if (!c) {
|
|
1771
|
+
resolve({ error: shimNote(bin) });
|
|
1772
|
+
return;
|
|
1773
|
+
}
|
|
1666
1774
|
try {
|
|
1667
|
-
child = spawn(
|
|
1775
|
+
child = spawn(c.file, c.args, {
|
|
1668
1776
|
cwd: o.cwd,
|
|
1669
1777
|
env: o.env,
|
|
1670
1778
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -1864,10 +1972,14 @@ function startAcp(o) {
|
|
|
1864
1972
|
});
|
|
1865
1973
|
const label = o.label;
|
|
1866
1974
|
let child;
|
|
1975
|
+
const c = spawnable(o.bin, o.args);
|
|
1976
|
+
if (!c) return Promise.resolve({ failed: `couldn't start ${label}: ${shimNote(o.bin)}` });
|
|
1867
1977
|
try {
|
|
1868
|
-
child = spawn2(
|
|
1978
|
+
child = spawn2(c.file, c.args, {
|
|
1869
1979
|
cwd: o.cwd,
|
|
1870
|
-
env
|
|
1980
|
+
// The caller's env as given (the daemon's is jobEnv's already, with the ask's
|
|
1981
|
+
// lineage on top), marked as a control job.
|
|
1982
|
+
env: { ...o.env, SESSIONPIPE_CONTROL_JOB: "1" },
|
|
1871
1983
|
stdio: ["pipe", "pipe", "pipe"],
|
|
1872
1984
|
detached: process.platform !== "win32",
|
|
1873
1985
|
windowsHide: true
|
|
@@ -1926,15 +2038,15 @@ function startAcp(o) {
|
|
|
1926
2038
|
return;
|
|
1927
2039
|
}
|
|
1928
2040
|
if (kind !== "agent_message_chunk" || !turn) return;
|
|
1929
|
-
const
|
|
1930
|
-
if (
|
|
2041
|
+
const c2 = obj(u.content);
|
|
2042
|
+
if (c2?.type !== "text" || !str(c2.text)) return;
|
|
1931
2043
|
const mid = str(u.messageId) || null;
|
|
1932
2044
|
if (turn.message !== void 0 && mid !== turn.message && turn.text.trim())
|
|
1933
2045
|
turn.text = `${turn.text.trimEnd()}
|
|
1934
2046
|
|
|
1935
2047
|
`;
|
|
1936
2048
|
turn.message = mid;
|
|
1937
|
-
turn.text += str(
|
|
2049
|
+
turn.text += str(c2.text);
|
|
1938
2050
|
o.onText?.(turn.text);
|
|
1939
2051
|
};
|
|
1940
2052
|
const onRequest = (id, method, params) => {
|
|
@@ -2130,7 +2242,7 @@ import {
|
|
|
2130
2242
|
existsSync as existsSync3,
|
|
2131
2243
|
mkdirSync as mkdirSync2,
|
|
2132
2244
|
readdirSync as readdirSync3,
|
|
2133
|
-
readFileSync as
|
|
2245
|
+
readFileSync as readFileSync5,
|
|
2134
2246
|
realpathSync,
|
|
2135
2247
|
statSync as statSync4,
|
|
2136
2248
|
unlinkSync as unlinkSync2,
|
|
@@ -2259,7 +2371,7 @@ var antigravity = {
|
|
|
2259
2371
|
readTranscript(file, fromLine) {
|
|
2260
2372
|
let text = "";
|
|
2261
2373
|
try {
|
|
2262
|
-
text =
|
|
2374
|
+
text = readFileSync5(file, "utf8");
|
|
2263
2375
|
} catch {
|
|
2264
2376
|
return { turns: [], line: fromLine };
|
|
2265
2377
|
}
|
|
@@ -2338,7 +2450,7 @@ function agProjects(dir) {
|
|
|
2338
2450
|
if (!ID_RE2.test(id)) continue;
|
|
2339
2451
|
let j;
|
|
2340
2452
|
try {
|
|
2341
|
-
j = JSON.parse(
|
|
2453
|
+
j = JSON.parse(readFileSync5(path8.join(dir, n), "utf8"));
|
|
2342
2454
|
} catch {
|
|
2343
2455
|
continue;
|
|
2344
2456
|
}
|
|
@@ -2375,7 +2487,7 @@ function antigravityRemoteUrl(transcript, opts) {
|
|
|
2375
2487
|
for (const d of dirs) {
|
|
2376
2488
|
try {
|
|
2377
2489
|
const m = /installation_uuid:\s*"([0-9a-f-]{36})"/i.exec(
|
|
2378
|
-
|
|
2490
|
+
readFileSync5(path8.join(d, "antigravity_state.pbtxt"), "utf8")
|
|
2379
2491
|
);
|
|
2380
2492
|
if (!m) continue;
|
|
2381
2493
|
const base = `https://antigravity.google.com/r/${m[1]}-v2`;
|
|
@@ -2554,7 +2666,10 @@ var reading = () => new AgyReading();
|
|
|
2554
2666
|
// src/adapters/claude-code-control.ts
|
|
2555
2667
|
var claude_code_control_exports = {};
|
|
2556
2668
|
__export(claude_code_control_exports, {
|
|
2669
|
+
CLAUDE_MODES: () => CLAUDE_MODES,
|
|
2557
2670
|
JOB_TIMEOUT_MS: () => JOB_TIMEOUT_MS,
|
|
2671
|
+
MODE_RANK: () => MODE_RANK,
|
|
2672
|
+
NO_HOME_SETTINGS: () => NO_HOME_SETTINGS,
|
|
2558
2673
|
ceilingLevel: () => ceilingLevel,
|
|
2559
2674
|
claudeArgs: () => claudeArgs,
|
|
2560
2675
|
claudeEnv: () => claudeEnv,
|
|
@@ -2564,22 +2679,31 @@ __export(claude_code_control_exports, {
|
|
|
2564
2679
|
detectCaps: () => detectCaps,
|
|
2565
2680
|
findClaude: () => findClaude,
|
|
2566
2681
|
findTranscript: () => findTranscript,
|
|
2682
|
+
findTranscripts: () => findTranscripts,
|
|
2683
|
+
homeSettings: () => homeSettings,
|
|
2684
|
+
hookMode: () => hookMode,
|
|
2567
2685
|
isUuid: () => isUuid,
|
|
2568
2686
|
liveProcess: () => liveProcess,
|
|
2687
|
+
liveRecord: () => liveRecord,
|
|
2688
|
+
liveRecords: () => liveRecords,
|
|
2569
2689
|
loginCommand: () => loginCommand,
|
|
2570
2690
|
loginHint: () => loginHint,
|
|
2571
2691
|
modeFlags: () => modeFlags,
|
|
2692
|
+
modeRank: () => modeRank,
|
|
2572
2693
|
offeredLevels: () => offeredLevels2,
|
|
2573
2694
|
outputArgs: () => outputArgs,
|
|
2574
2695
|
parseAuthStatus: () => parseAuthStatus,
|
|
2575
2696
|
parseCaps: () => parseCaps,
|
|
2576
2697
|
parseResult: () => parseResult,
|
|
2698
|
+
peerClass: () => peerClass,
|
|
2577
2699
|
recentlyWritten: () => recentlyWritten,
|
|
2700
|
+
relaunchMode: () => relaunchMode,
|
|
2701
|
+
resolveHome: () => resolveHome,
|
|
2578
2702
|
runClaude: () => runClaude,
|
|
2579
2703
|
sessionFolder: () => sessionFolder
|
|
2580
2704
|
});
|
|
2581
2705
|
import { execFile, execFileSync as execFileSync3 } from "node:child_process";
|
|
2582
|
-
import { closeSync as closeSync2, openSync as openSync2, readdirSync as readdirSync4, readFileSync as
|
|
2706
|
+
import { closeSync as closeSync2, openSync as openSync2, readdirSync as readdirSync4, readFileSync as readFileSync6, readSync as readSync2, statSync as statSync5 } from "node:fs";
|
|
2583
2707
|
import os5 from "node:os";
|
|
2584
2708
|
import path10 from "node:path";
|
|
2585
2709
|
|
|
@@ -2593,10 +2717,10 @@ var MODEL_RE = /^[A-Za-z0-9][A-Za-z0-9._:/@[\]-]*$/;
|
|
|
2593
2717
|
var START_PERMISSIONS = ["read", "safe", "edits", "auto"];
|
|
2594
2718
|
var levelRank = (l) => START_PERMISSIONS.indexOf(l);
|
|
2595
2719
|
var FIELDS = {
|
|
2596
|
-
prompt: ["text", "files"],
|
|
2720
|
+
prompt: ["text", "files", "reply_to"],
|
|
2597
2721
|
"permission.answer": ["for", "decision"],
|
|
2598
2722
|
cancel: [],
|
|
2599
|
-
start: ["text", "cwd", "files", "permission", "model"],
|
|
2723
|
+
start: ["text", "cwd", "files", "permission", "model", "reply_to"],
|
|
2600
2724
|
"key.add": ["key", "name"],
|
|
2601
2725
|
pool: ["pool_action", "pool_account", "pool_order", "pool_code"]
|
|
2602
2726
|
};
|
|
@@ -2668,6 +2792,8 @@ var LEVEL_MODE = {
|
|
|
2668
2792
|
};
|
|
2669
2793
|
function modeFlags(level, caps) {
|
|
2670
2794
|
if (level === "inherit") return { args: [] };
|
|
2795
|
+
if (caps.unread)
|
|
2796
|
+
return { error: `this machine couldn't read its Claude Code's options (${caps.unread}); try again in a minute` };
|
|
2671
2797
|
if (level === "auto" && !caps.modes.includes("auto"))
|
|
2672
2798
|
return { error: "this machine is in auto mode, but its Claude Code has no auto permission mode" };
|
|
2673
2799
|
if (level !== "safe") {
|
|
@@ -2687,6 +2813,7 @@ function modeFlags(level, caps) {
|
|
|
2687
2813
|
}
|
|
2688
2814
|
var ceilingLevel = (mode) => mode === "inherit" ? "safe" : mode;
|
|
2689
2815
|
function offeredLevels2(mode, caps) {
|
|
2816
|
+
if (caps.unread) return [];
|
|
2690
2817
|
return START_PERMISSIONS.filter(
|
|
2691
2818
|
(l) => levelRank(l) <= levelRank(ceilingLevel(mode)) && (l === "safe" || caps.modes.includes(LEVEL_MODE[l]))
|
|
2692
2819
|
);
|
|
@@ -2712,7 +2839,7 @@ function claudeArgs(o) {
|
|
|
2712
2839
|
};
|
|
2713
2840
|
}
|
|
2714
2841
|
function claudeEnv(configDir, env = process.env) {
|
|
2715
|
-
const e =
|
|
2842
|
+
const e = withoutLineage(env);
|
|
2716
2843
|
for (const k of [
|
|
2717
2844
|
"CLAUDECODE",
|
|
2718
2845
|
"CLAUDE_CODE_SESSION_ID",
|
|
@@ -2746,11 +2873,12 @@ function parseAuthStatus(stdout) {
|
|
|
2746
2873
|
}
|
|
2747
2874
|
}
|
|
2748
2875
|
function claudeLogin2(bin, configDir, env = process.env) {
|
|
2876
|
+
const c = probe(bin, ["auth", "status", "--json"]);
|
|
2749
2877
|
return new Promise((resolve) => {
|
|
2750
2878
|
execFile(
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
{ encoding: "utf8", timeout: 2e4, env: claudeEnv(configDir, env), maxBuffer: 256 * 1024 },
|
|
2879
|
+
c.file,
|
|
2880
|
+
c.args,
|
|
2881
|
+
{ encoding: "utf8", timeout: 2e4, env: claudeEnv(configDir, env), maxBuffer: 256 * 1024, shell: c.shell },
|
|
2754
2882
|
// `auth status` may exit non-zero when signed out; its JSON still says so.
|
|
2755
2883
|
(_err, stdout) => resolve(parseAuthStatus(stdout))
|
|
2756
2884
|
);
|
|
@@ -2768,41 +2896,73 @@ function loginHint(configDir, platform = process.platform) {
|
|
|
2768
2896
|
return `Claude Code (${shown}) isn't signed in as this machine's background service sees it. On a Mac its login lives in the login keychain, which a background service can read only while someone is logged in at the screen: log in at the Mac, or run ${login} there.`;
|
|
2769
2897
|
return `Claude Code (${shown}) isn't signed in on this machine: run ${login} there.`;
|
|
2770
2898
|
}
|
|
2771
|
-
function detectCaps(bin) {
|
|
2772
|
-
|
|
2899
|
+
function detectCaps(bin, timeoutMs = 3e4) {
|
|
2900
|
+
const c = probe(bin, ["--help"]);
|
|
2773
2901
|
try {
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2902
|
+
return parseCaps(
|
|
2903
|
+
execFileSync3(c.file, c.args, {
|
|
2904
|
+
encoding: "utf8",
|
|
2905
|
+
timeout: timeoutMs,
|
|
2906
|
+
env: claudeEnv(),
|
|
2907
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
2908
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
2909
|
+
shell: c.shell
|
|
2910
|
+
})
|
|
2911
|
+
);
|
|
2781
2912
|
} catch (e) {
|
|
2782
|
-
|
|
2913
|
+
const err = e;
|
|
2914
|
+
const caps = parseCaps(String(err?.stdout || ""));
|
|
2915
|
+
if (caps.hasMode) return caps;
|
|
2916
|
+
const why = err?.code === "ETIMEDOUT" ? `timed out after ${timeoutMs / 1e3} s` : "failed";
|
|
2917
|
+
return { ...caps, unread: `\`${path10.basename(bin)} --help\` ${why}` };
|
|
2783
2918
|
}
|
|
2784
|
-
return parseCaps(help);
|
|
2785
2919
|
}
|
|
2786
|
-
function
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2920
|
+
function transcriptIn(session, dir) {
|
|
2921
|
+
let projects = [];
|
|
2922
|
+
try {
|
|
2923
|
+
projects = readdirSync4(path10.join(dir, "projects"), { withFileTypes: true });
|
|
2924
|
+
} catch {
|
|
2925
|
+
return null;
|
|
2926
|
+
}
|
|
2927
|
+
for (const p of projects) {
|
|
2928
|
+
if (!p.isDirectory()) continue;
|
|
2929
|
+
const file = path10.join(dir, "projects", p.name, `${session}.jsonl`);
|
|
2790
2930
|
try {
|
|
2791
|
-
|
|
2931
|
+
if (statSync5(file).isFile()) return { file, configDir: dir, project: p.name };
|
|
2792
2932
|
} catch {
|
|
2793
|
-
continue;
|
|
2794
|
-
}
|
|
2795
|
-
for (const p of projects) {
|
|
2796
|
-
if (!p.isDirectory()) continue;
|
|
2797
|
-
const file = path10.join(dir, "projects", p.name, `${session}.jsonl`);
|
|
2798
|
-
try {
|
|
2799
|
-
if (statSync5(file).isFile()) return { file, configDir: dir, project: p.name };
|
|
2800
|
-
} catch {
|
|
2801
|
-
}
|
|
2802
2933
|
}
|
|
2803
2934
|
}
|
|
2804
2935
|
return null;
|
|
2805
2936
|
}
|
|
2937
|
+
function findTranscript(session, dirs) {
|
|
2938
|
+
if (!UUID_RE2.test(session)) return null;
|
|
2939
|
+
for (const dir of dirs) {
|
|
2940
|
+
const t = transcriptIn(session, dir);
|
|
2941
|
+
if (t) return t;
|
|
2942
|
+
}
|
|
2943
|
+
return null;
|
|
2944
|
+
}
|
|
2945
|
+
function findTranscripts(session, dirs) {
|
|
2946
|
+
if (!UUID_RE2.test(session)) return [];
|
|
2947
|
+
const out = [];
|
|
2948
|
+
for (const dir of dirs) {
|
|
2949
|
+
const t = transcriptIn(session, dir);
|
|
2950
|
+
if (t) out.push(t);
|
|
2951
|
+
}
|
|
2952
|
+
return out;
|
|
2953
|
+
}
|
|
2954
|
+
var homeName = (t) => path10.basename(t.configDir);
|
|
2955
|
+
function resolveHome(session, dirs) {
|
|
2956
|
+
const all = findTranscripts(session, dirs);
|
|
2957
|
+
if (!all.length) return null;
|
|
2958
|
+
if (all.length === 1) return { transcript: all[0] };
|
|
2959
|
+
const live = all.filter((t) => liveRecords(session, t.configDir).length > 0);
|
|
2960
|
+
if (live.length === 1) return { transcript: live[0] };
|
|
2961
|
+
return {
|
|
2962
|
+
ambiguous: [...new Set(all.map(homeName))].sort(),
|
|
2963
|
+
live: [...new Set(live.map(homeName))].sort()
|
|
2964
|
+
};
|
|
2965
|
+
}
|
|
2806
2966
|
var projectName = (cwd) => cwd.replace(/[^a-zA-Z0-9]/g, "-");
|
|
2807
2967
|
function sessionFolder(t, cap2 = 8 * 1024 * 1024) {
|
|
2808
2968
|
let first = null;
|
|
@@ -2874,22 +3034,105 @@ function pidAlive(pid) {
|
|
|
2874
3034
|
return e.code === "EPERM";
|
|
2875
3035
|
}
|
|
2876
3036
|
}
|
|
2877
|
-
|
|
2878
|
-
|
|
3037
|
+
var registryRow = (file, configDir, j) => {
|
|
3038
|
+
const pid = Number(j.pid ?? path10.basename(file).slice(0, -5));
|
|
3039
|
+
const str2 = (v) => typeof v === "string" && v ? v : null;
|
|
3040
|
+
let keyFile = null;
|
|
2879
3041
|
try {
|
|
2880
|
-
|
|
3042
|
+
const want = new RegExp(`^${pid}\\.[0-9a-f]{64}\\.key$`);
|
|
3043
|
+
const hit = readdirSync4(path10.dirname(file)).find((n) => want.test(n));
|
|
3044
|
+
if (hit) keyFile = path10.join(path10.dirname(file), hit);
|
|
2881
3045
|
} catch {
|
|
2882
|
-
return false;
|
|
2883
3046
|
}
|
|
2884
|
-
|
|
3047
|
+
return {
|
|
3048
|
+
configDir,
|
|
3049
|
+
file,
|
|
3050
|
+
pid,
|
|
3051
|
+
socket: str2(j.messagingSocketPath),
|
|
3052
|
+
peerProtocol: typeof j.peerProtocol === "number" ? j.peerProtocol : null,
|
|
3053
|
+
procStart: str2(j.procStart),
|
|
3054
|
+
status: str2(j.status),
|
|
3055
|
+
kind: str2(j.kind),
|
|
3056
|
+
entrypoint: str2(j.entrypoint),
|
|
3057
|
+
keyFile
|
|
3058
|
+
};
|
|
3059
|
+
};
|
|
3060
|
+
function liveRecords(session, dirs) {
|
|
3061
|
+
const out = [];
|
|
3062
|
+
for (const dir of typeof dirs === "string" ? [dirs] : dirs) {
|
|
3063
|
+
let names = [];
|
|
2885
3064
|
try {
|
|
2886
|
-
|
|
2887
|
-
if (String(j.sessionId) !== session) continue;
|
|
2888
|
-
if (pidAlive(Number(j.pid ?? n.slice(0, -5)))) return true;
|
|
3065
|
+
names = readdirSync4(path10.join(dir, "sessions")).filter((n) => /^\d+\.json$/.test(n));
|
|
2889
3066
|
} catch {
|
|
3067
|
+
continue;
|
|
3068
|
+
}
|
|
3069
|
+
for (const n of names) {
|
|
3070
|
+
const file = path10.join(dir, "sessions", n);
|
|
3071
|
+
let j;
|
|
3072
|
+
try {
|
|
3073
|
+
j = JSON.parse(readFileSync6(file, "utf8"));
|
|
3074
|
+
} catch {
|
|
3075
|
+
continue;
|
|
3076
|
+
}
|
|
3077
|
+
if (String(j.sessionId) !== session) continue;
|
|
3078
|
+
const row = registryRow(file, dir, j);
|
|
3079
|
+
if (pidAlive(row.pid)) out.push(row);
|
|
2890
3080
|
}
|
|
2891
3081
|
}
|
|
2892
|
-
return
|
|
3082
|
+
return out;
|
|
3083
|
+
}
|
|
3084
|
+
function liveRecord(session, dirs) {
|
|
3085
|
+
const all = liveRecords(session, dirs);
|
|
3086
|
+
return all.length === 1 ? all[0] : null;
|
|
3087
|
+
}
|
|
3088
|
+
function liveProcess(session, configDir) {
|
|
3089
|
+
return liveRecords(session, configDir).length > 0;
|
|
3090
|
+
}
|
|
3091
|
+
var MODE_RANK = {
|
|
3092
|
+
plan: 0,
|
|
3093
|
+
default: 1,
|
|
3094
|
+
manual: 1,
|
|
3095
|
+
dontAsk: 1,
|
|
3096
|
+
acceptEdits: 2,
|
|
3097
|
+
auto: 3,
|
|
3098
|
+
bypassPermissions: 4
|
|
3099
|
+
};
|
|
3100
|
+
var CLAUDE_MODES = Object.keys(MODE_RANK);
|
|
3101
|
+
var modeRank = (m) => m && m in MODE_RANK ? MODE_RANK[m] : -1;
|
|
3102
|
+
function hookMode(payload) {
|
|
3103
|
+
if (!payload || typeof payload !== "object") return null;
|
|
3104
|
+
const p = payload;
|
|
3105
|
+
const v = typeof p.permission_mode === "string" ? p.permission_mode : p.permissionMode;
|
|
3106
|
+
return typeof v === "string" && CLAUDE_MODES.includes(v) ? v : null;
|
|
3107
|
+
}
|
|
3108
|
+
function peerClass(mode) {
|
|
3109
|
+
if (mode === "bypassPermissions") return "bypass";
|
|
3110
|
+
if (mode === "default" || mode === "manual" || mode === "dontAsk" || mode === "acceptEdits") return "prompting";
|
|
3111
|
+
return null;
|
|
3112
|
+
}
|
|
3113
|
+
var NO_HOME_SETTINGS = { defaultMode: null, disableAutoMode: false, disableBypass: false };
|
|
3114
|
+
function homeSettings(configDir, home = os5.homedir()) {
|
|
3115
|
+
const file = path10.join(configDir ?? path10.join(home, ".claude"), "settings.json");
|
|
3116
|
+
let j;
|
|
3117
|
+
try {
|
|
3118
|
+
j = JSON.parse(readFileSync6(file, "utf8"));
|
|
3119
|
+
} catch {
|
|
3120
|
+
return { ...NO_HOME_SETTINGS };
|
|
3121
|
+
}
|
|
3122
|
+
if (!j || typeof j !== "object" || Array.isArray(j)) return { ...NO_HOME_SETTINGS };
|
|
3123
|
+
const p = j.permissions && typeof j.permissions === "object" ? j.permissions : {};
|
|
3124
|
+
const off = (k) => j[k] === "disable" || p[k] === "disable";
|
|
3125
|
+
return {
|
|
3126
|
+
defaultMode: typeof p.defaultMode === "string" && CLAUDE_MODES.includes(p.defaultMode) ? p.defaultMode : null,
|
|
3127
|
+
disableAutoMode: off("disableAutoMode"),
|
|
3128
|
+
disableBypass: off("disableBypassPermissionsMode")
|
|
3129
|
+
};
|
|
3130
|
+
}
|
|
3131
|
+
function relaunchMode(recorded, home) {
|
|
3132
|
+
if (recorded === "plan") return recorded;
|
|
3133
|
+
if ((recorded === "dontAsk" || recorded === "acceptEdits") && modeRank(home.defaultMode) >= modeRank(recorded))
|
|
3134
|
+
return recorded;
|
|
3135
|
+
return null;
|
|
2893
3136
|
}
|
|
2894
3137
|
function recentlyWritten(file, ourLastEnd, now = Date.now()) {
|
|
2895
3138
|
let m;
|
|
@@ -2931,7 +3174,7 @@ function parseResult(stdout) {
|
|
|
2931
3174
|
var isUuid = (s) => typeof s === "string" && UUID_RE2.test(s);
|
|
2932
3175
|
|
|
2933
3176
|
// src/adapters/codex.ts
|
|
2934
|
-
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync5, readFileSync as
|
|
3177
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "node:fs";
|
|
2935
3178
|
import path11 from "node:path";
|
|
2936
3179
|
|
|
2937
3180
|
// src/adapters/codex-config.ts
|
|
@@ -3088,7 +3331,7 @@ function installNotify(cmd, env) {
|
|
|
3088
3331
|
const file = configFile2(env);
|
|
3089
3332
|
let text = "";
|
|
3090
3333
|
try {
|
|
3091
|
-
text =
|
|
3334
|
+
text = readFileSync7(file, "utf8");
|
|
3092
3335
|
} catch {
|
|
3093
3336
|
}
|
|
3094
3337
|
const argv = cmd([NAME3, "notify"]).argv;
|
|
@@ -3134,7 +3377,7 @@ function uninstallNotify(env) {
|
|
|
3134
3377
|
const file = configFile2(env);
|
|
3135
3378
|
let text;
|
|
3136
3379
|
try {
|
|
3137
|
-
text =
|
|
3380
|
+
text = readFileSync7(file, "utf8");
|
|
3138
3381
|
} catch {
|
|
3139
3382
|
return { file, changed: false };
|
|
3140
3383
|
}
|
|
@@ -3206,7 +3449,7 @@ var codex = {
|
|
|
3206
3449
|
];
|
|
3207
3450
|
let text = "";
|
|
3208
3451
|
try {
|
|
3209
|
-
text =
|
|
3452
|
+
text = readFileSync7(configFile2(env), "utf8");
|
|
3210
3453
|
} catch {
|
|
3211
3454
|
}
|
|
3212
3455
|
const n = readNotify(text);
|
|
@@ -3333,7 +3576,7 @@ var codex = {
|
|
|
3333
3576
|
readTranscript(file, fromLine) {
|
|
3334
3577
|
let text = "";
|
|
3335
3578
|
try {
|
|
3336
|
-
text =
|
|
3579
|
+
text = readFileSync7(file, "utf8");
|
|
3337
3580
|
} catch {
|
|
3338
3581
|
return { turns: [], line: fromLine };
|
|
3339
3582
|
}
|
|
@@ -3450,7 +3693,7 @@ __export(codex_control_exports, {
|
|
|
3450
3693
|
reading: () => reading2
|
|
3451
3694
|
});
|
|
3452
3695
|
import { execFile as execFile2 } from "node:child_process";
|
|
3453
|
-
import { readFileSync as
|
|
3696
|
+
import { readFileSync as readFileSync8 } from "node:fs";
|
|
3454
3697
|
import os6 from "node:os";
|
|
3455
3698
|
import path12 from "node:path";
|
|
3456
3699
|
var LABEL2 = "Codex";
|
|
@@ -3496,7 +3739,7 @@ function codexArgs(o) {
|
|
|
3496
3739
|
function codexModels(env = process.env, home = os6.homedir()) {
|
|
3497
3740
|
try {
|
|
3498
3741
|
const file = path12.join(env.CODEX_HOME || path12.join(home, ".codex"), "models_cache.json");
|
|
3499
|
-
const j = JSON.parse(
|
|
3742
|
+
const j = JSON.parse(readFileSync8(file, "utf8"));
|
|
3500
3743
|
if (!Array.isArray(j.models)) return [];
|
|
3501
3744
|
const out = [];
|
|
3502
3745
|
for (const m of j.models)
|
|
@@ -3512,11 +3755,12 @@ var codexEnv = (env = process.env) => jobEnv(env);
|
|
|
3512
3755
|
var LOGIN_HINT = "Codex isn't signed in on this machine: run `codex login --device-auth` there.";
|
|
3513
3756
|
function codexLogin(bin, env = process.env) {
|
|
3514
3757
|
if (env.CODEX_API_KEY) return Promise.resolve({ loggedIn: true, method: "api key" });
|
|
3758
|
+
const c = probe(bin, ["login", "status"]);
|
|
3515
3759
|
return new Promise((resolve) => {
|
|
3516
3760
|
execFile2(
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
{ encoding: "utf8", timeout: 2e4, env: codexEnv(env), maxBuffer: 256 * 1024 },
|
|
3761
|
+
c.file,
|
|
3762
|
+
c.args,
|
|
3763
|
+
{ encoding: "utf8", timeout: 2e4, env: codexEnv(env), maxBuffer: 256 * 1024, shell: c.shell },
|
|
3520
3764
|
(err) => {
|
|
3521
3765
|
if (!err) return resolve({ loggedIn: true });
|
|
3522
3766
|
const code = err.code;
|
|
@@ -4021,7 +4265,7 @@ function devinAccount(env = process.env) {
|
|
|
4021
4265
|
|
|
4022
4266
|
// src/adapters/gemini-cli.ts
|
|
4023
4267
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
4024
|
-
import { existsSync as existsSync7, readFileSync as
|
|
4268
|
+
import { existsSync as existsSync7, readFileSync as readFileSync9 } from "node:fs";
|
|
4025
4269
|
import path14 from "node:path";
|
|
4026
4270
|
var NAME5 = "gemini-cli";
|
|
4027
4271
|
var GEMINI_EVENTS = [
|
|
@@ -4043,14 +4287,14 @@ function geminiVersion(platform = process.platform, env = process.env) {
|
|
|
4043
4287
|
const win = platform === "win32";
|
|
4044
4288
|
const bin = win ? findBinary({ names: ["gemini.exe", "gemini.cmd"], dirs: [path14.dirname(process.execPath)], env }) : "gemini";
|
|
4045
4289
|
if (!bin) throw new Error("no gemini on PATH");
|
|
4046
|
-
const
|
|
4290
|
+
const c = probe(bin, ["--version"]);
|
|
4291
|
+
return execFileSync5(c.file, c.args, {
|
|
4047
4292
|
encoding: "utf8",
|
|
4048
4293
|
timeout: 4e3,
|
|
4049
4294
|
stdio: ["ignore", "pipe", "ignore"],
|
|
4050
|
-
env
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
return out.trim();
|
|
4295
|
+
env,
|
|
4296
|
+
shell: c.shell
|
|
4297
|
+
}).trim();
|
|
4054
4298
|
}
|
|
4055
4299
|
function geminiHooksActive(settingsFile) {
|
|
4056
4300
|
const tools = readJson(settingsFile).tools;
|
|
@@ -4175,7 +4419,7 @@ var geminiCli = {
|
|
|
4175
4419
|
readTranscript(file, fromLine) {
|
|
4176
4420
|
let text = "";
|
|
4177
4421
|
try {
|
|
4178
|
-
text =
|
|
4422
|
+
text = readFileSync9(file, "utf8");
|
|
4179
4423
|
} catch {
|
|
4180
4424
|
return { turns: [], line: fromLine };
|
|
4181
4425
|
}
|
|
@@ -4224,12 +4468,12 @@ function drivableHarnesses(env = process.env) {
|
|
|
4224
4468
|
}
|
|
4225
4469
|
|
|
4226
4470
|
// src/config.ts
|
|
4227
|
-
import { chmodSync, existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as
|
|
4471
|
+
import { chmodSync, existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as readFileSync10, writeFileSync as writeFileSync5 } from "node:fs";
|
|
4228
4472
|
import path15 from "node:path";
|
|
4229
4473
|
var DEFAULT_CONFIG = { sinks: [], harnesses: {}, update_check: true, keep_days: 30 };
|
|
4230
4474
|
function readConfig(file = configFile()) {
|
|
4231
4475
|
try {
|
|
4232
|
-
const j = JSON.parse(
|
|
4476
|
+
const j = JSON.parse(readFileSync10(file, "utf8"));
|
|
4233
4477
|
return {
|
|
4234
4478
|
...DEFAULT_CONFIG,
|
|
4235
4479
|
...j,
|
|
@@ -4306,22 +4550,6 @@ function makeEvent(a, ctx) {
|
|
|
4306
4550
|
};
|
|
4307
4551
|
}
|
|
4308
4552
|
|
|
4309
|
-
// src/launched-by.ts
|
|
4310
|
-
var LAUNCHED_BY_ENV = "SESSIONPIPE_LAUNCHED_BY";
|
|
4311
|
-
var LAUNCHED_BY = /^[a-z][a-z0-9-]{0,39}:[A-Za-z0-9._:-]{1,128}$/;
|
|
4312
|
-
function launchedBy(env) {
|
|
4313
|
-
const v = env[LAUNCHED_BY_ENV]?.trim();
|
|
4314
|
-
return v && LAUNCHED_BY.test(v) ? v : void 0;
|
|
4315
|
-
}
|
|
4316
|
-
function readHook(adapter, input) {
|
|
4317
|
-
const r = adapter.fromHook(input);
|
|
4318
|
-
if (r && !r.session.parent_id) {
|
|
4319
|
-
const launcher = launchedBy(input.env);
|
|
4320
|
-
if (launcher && launcher !== `${adapter.name}:${r.session.id}`) r.session.launched_by = launcher;
|
|
4321
|
-
}
|
|
4322
|
-
return r;
|
|
4323
|
-
}
|
|
4324
|
-
|
|
4325
4553
|
// src/outbox.ts
|
|
4326
4554
|
import {
|
|
4327
4555
|
appendFileSync,
|
|
@@ -4330,7 +4558,7 @@ import {
|
|
|
4330
4558
|
mkdirSync as mkdirSync5,
|
|
4331
4559
|
openSync as openSync3,
|
|
4332
4560
|
readdirSync as readdirSync6,
|
|
4333
|
-
readFileSync as
|
|
4561
|
+
readFileSync as readFileSync11,
|
|
4334
4562
|
readSync as readSync3,
|
|
4335
4563
|
renameSync,
|
|
4336
4564
|
statSync as statSync6,
|
|
@@ -4360,7 +4588,7 @@ var Outbox = class {
|
|
|
4360
4588
|
const f = this.seqFile(ref);
|
|
4361
4589
|
let n = -1;
|
|
4362
4590
|
try {
|
|
4363
|
-
const t =
|
|
4591
|
+
const t = readFileSync11(f, "utf8").trim();
|
|
4364
4592
|
if (/^\d+$/.test(t)) n = Number(t);
|
|
4365
4593
|
} catch {
|
|
4366
4594
|
}
|
|
@@ -4372,7 +4600,7 @@ var Outbox = class {
|
|
|
4372
4600
|
lastSeqInFile(ref) {
|
|
4373
4601
|
const f = this.file(ref);
|
|
4374
4602
|
if (!existsSync9(f)) return -1;
|
|
4375
|
-
const lines =
|
|
4603
|
+
const lines = readFileSync11(f, "utf8").trim().split("\n");
|
|
4376
4604
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
4377
4605
|
try {
|
|
4378
4606
|
const j = JSON.parse(lines[i]);
|
|
@@ -4495,7 +4723,7 @@ var Cursors = class {
|
|
|
4495
4723
|
}
|
|
4496
4724
|
read() {
|
|
4497
4725
|
try {
|
|
4498
|
-
return JSON.parse(
|
|
4726
|
+
return JSON.parse(readFileSync11(this.file(), "utf8"));
|
|
4499
4727
|
} catch {
|
|
4500
4728
|
return {};
|
|
4501
4729
|
}
|
|
@@ -4519,7 +4747,7 @@ function takeNamedLock(root, name, staleMs = 5 * 6e4) {
|
|
|
4519
4747
|
mkdirSync5(dir, { recursive: true, mode: 448 });
|
|
4520
4748
|
const f = path16.join(dir, `${name}.lock`);
|
|
4521
4749
|
try {
|
|
4522
|
-
if (Date.now() - statSync6(f).mtimeMs > staleMs || !processAlive(Number(
|
|
4750
|
+
if (Date.now() - statSync6(f).mtimeMs > staleMs || !processAlive(Number(readFileSync11(f, "utf8")))) unlinkSync3(f);
|
|
4523
4751
|
else return null;
|
|
4524
4752
|
} catch {
|
|
4525
4753
|
}
|
|
@@ -4760,6 +4988,8 @@ var TYPE_TIER = {
|
|
|
4760
4988
|
"subagent.ended": 1,
|
|
4761
4989
|
"context.compacted": 1,
|
|
4762
4990
|
"limits.observed": 1,
|
|
4991
|
+
"delegation.started": 0,
|
|
4992
|
+
"delegation.ended": 0,
|
|
4763
4993
|
native: 3
|
|
4764
4994
|
};
|
|
4765
4995
|
var DATA_ALLOW = {
|
|
@@ -4770,8 +5000,8 @@ var DATA_ALLOW = {
|
|
|
4770
5000
|
"session.forgotten": { 0: [] },
|
|
4771
5001
|
"turn.started": { 0: ["turn_id", "submitted_by", "injected"], 1: ["prompt_chars"] },
|
|
4772
5002
|
"turn.ended": { 0: ["turn_id", "reason", "ms", "background"], 1: ["error"] },
|
|
4773
|
-
"turn.transcript": { 2: ["turn", "user", "assistant", "at"] },
|
|
4774
|
-
"turn.progress": { 2: ["turn", "user", "assistant", "at"] },
|
|
5003
|
+
"turn.transcript": { 2: ["turn", "user", "assistant", "at", "injected"] },
|
|
5004
|
+
"turn.progress": { 2: ["turn", "user", "assistant", "at", "injected"] },
|
|
4775
5005
|
"tool.started": { 1: ["tool", "call_id", "turn_id", "agent_id"], 3: ["input"] },
|
|
4776
5006
|
"tool.ended": { 1: ["tool", "call_id", "turn_id", "agent_id", "ms", "ok", "error"], 3: ["input", "output"] },
|
|
4777
5007
|
"files.changed": { 1: ["paths"] },
|
|
@@ -4780,7 +5010,9 @@ var DATA_ALLOW = {
|
|
|
4780
5010
|
"subagent.started": { 1: ["agent_id", "agent_type"] },
|
|
4781
5011
|
"subagent.ended": { 1: ["agent_id", "agent_type"] },
|
|
4782
5012
|
"context.compacted": { 1: ["trigger"] },
|
|
4783
|
-
"limits.observed": { 1: ["windows", "plan", "account_id"] }
|
|
5013
|
+
"limits.observed": { 1: ["windows", "plan", "account_id"] },
|
|
5014
|
+
"delegation.started": { 0: ["ask_id", "via", "harness", "to"], 1: ["text"] },
|
|
5015
|
+
"delegation.ended": { 0: ["ask_id", "to", "ok", "ms", "error", "relayed"], 2: ["reply"] }
|
|
4784
5016
|
};
|
|
4785
5017
|
var SESSION_ALLOW = [
|
|
4786
5018
|
"id",
|
|
@@ -4796,7 +5028,8 @@ var SESSION_ALLOW = [
|
|
|
4796
5028
|
"account_id",
|
|
4797
5029
|
"attended",
|
|
4798
5030
|
"parent_id",
|
|
4799
|
-
"launched_by"
|
|
5031
|
+
"launched_by",
|
|
5032
|
+
"delegated_by"
|
|
4800
5033
|
];
|
|
4801
5034
|
var MAX_SIDE = 2e4;
|
|
4802
5035
|
var MAX_IO = 64 * 1024;
|
|
@@ -4835,6 +5068,8 @@ function filterEvent(event, tier, pii, opts = {}) {
|
|
|
4835
5068
|
if (data.input !== void 0) data.input = cap(data.input, MAX_IO);
|
|
4836
5069
|
if (data.output !== void 0) data.output = cap(data.output, MAX_IO);
|
|
4837
5070
|
if (typeof data.message === "string") data.message = cap(data.message, 200);
|
|
5071
|
+
if (event.type === "delegation.started" && typeof data.text === "string") data.text = cap(data.text, 200);
|
|
5072
|
+
if (event.type === "delegation.ended" && typeof data.reply === "string") data.reply = cap(data.reply, MAX_SIDE);
|
|
4838
5073
|
const rulesets = [];
|
|
4839
5074
|
let out = { ...event, tier, session, data, privacy: { rulesets, pii } };
|
|
4840
5075
|
if (tier > 0) {
|
|
@@ -4914,13 +5149,16 @@ var PROTOCOL_VERSION = 1;
|
|
|
4914
5149
|
export {
|
|
4915
5150
|
ADAPTERS,
|
|
4916
5151
|
AG_STALE_PRETOOL,
|
|
5152
|
+
ASK_CHAIN_ENV,
|
|
4917
5153
|
Cursors,
|
|
4918
5154
|
DEFAULT_CONFIG,
|
|
5155
|
+
DELEGATED_BY_ENV,
|
|
4919
5156
|
DEVIN_EVENTS,
|
|
4920
5157
|
FileSink,
|
|
4921
5158
|
HELLO_HARNESSES_MAX,
|
|
4922
5159
|
JOB_TIMEOUT_MS,
|
|
4923
5160
|
LAUNCHED_BY_ENV,
|
|
5161
|
+
LINEAGE_ENV,
|
|
4924
5162
|
Outbox,
|
|
4925
5163
|
PROTOCOL_VERSION,
|
|
4926
5164
|
REDACTED,
|
|
@@ -4942,6 +5180,7 @@ export {
|
|
|
4942
5180
|
codex,
|
|
4943
5181
|
codex_control_exports as codexControl,
|
|
4944
5182
|
configFile,
|
|
5183
|
+
delegatedBy,
|
|
4945
5184
|
deniedNote,
|
|
4946
5185
|
devin,
|
|
4947
5186
|
devinConfigDir,
|
|
@@ -4962,6 +5201,7 @@ export {
|
|
|
4962
5201
|
makeEvent,
|
|
4963
5202
|
notClaudeCode,
|
|
4964
5203
|
pairTurns,
|
|
5204
|
+
peerAsk,
|
|
4965
5205
|
processAlive,
|
|
4966
5206
|
readAntigravity,
|
|
4967
5207
|
readClaude,
|
|
@@ -4984,6 +5224,7 @@ export {
|
|
|
4984
5224
|
tilde,
|
|
4985
5225
|
ulid,
|
|
4986
5226
|
untilde,
|
|
5227
|
+
withoutLineage,
|
|
4987
5228
|
writeConfig
|
|
4988
5229
|
};
|
|
4989
5230
|
//# sourceMappingURL=index.js.map
|