sessionpipe-conformance 0.9.0 → 0.10.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 +69 -7
- package/dist/cli.js.map +3 -3
- package/dist/index.js +69 -7
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// sessionpipe-conformance 0.
|
|
1
|
+
// sessionpipe-conformance 0.10.0 · Apache-2.0 · https://sessionpipe.org
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { readFileSync as readFileSync6 } from "node:fs";
|
|
@@ -798,14 +798,28 @@ var claudeCode = {
|
|
|
798
798
|
case "SessionStart":
|
|
799
799
|
events.push(ev("session.started", { source: pickSource(s.source ?? s.trigger) }));
|
|
800
800
|
break;
|
|
801
|
-
case "UserPromptSubmit":
|
|
801
|
+
case "UserPromptSubmit": {
|
|
802
|
+
const prompt = typeof s.prompt === "string" ? s.prompt : void 0;
|
|
802
803
|
events.push(
|
|
803
804
|
ev("turn.started", {
|
|
804
805
|
turn_id,
|
|
805
|
-
prompt_chars:
|
|
806
|
+
prompt_chars: prompt === void 0 ? void 0 : [...prompt].length,
|
|
807
|
+
// Claude Code's hook schema documents `source`
|
|
808
|
+
// (user | sdk | system | loop_wakeup | schedule_wakeup | poll_event) and says a
|
|
809
|
+
// payload may omit it while the field rolls out; 2.1.304's payload has no such
|
|
810
|
+
// key at all. Forwarded verbatim, shape-guarded only: the list is the harness's
|
|
811
|
+
// to extend.
|
|
812
|
+
submitted_by: harnessWord(s.source),
|
|
813
|
+
// One of Claude Code's own prompt wrappers: the prompt is a block the harness
|
|
814
|
+
// wrote, so it is not the person's words. Absent is unknown, never "the person" —
|
|
815
|
+
// and `true` is never "no person caused this turn", because a Talk or
|
|
816
|
+
// `sessionpipe wait` delivery hands the person's own message over inside a
|
|
817
|
+
// <task-notification> (PROTOCOL.md §4).
|
|
818
|
+
injected: prompt !== void 0 && injectedBlock(prompt) ? true : void 0
|
|
806
819
|
})
|
|
807
820
|
);
|
|
808
821
|
break;
|
|
822
|
+
}
|
|
809
823
|
case "PreToolUse":
|
|
810
824
|
if (tool) events.push(ev("tool.started", { tool, call_id, turn_id, agent_id, input: s.tool_input }));
|
|
811
825
|
break;
|
|
@@ -860,7 +874,13 @@ var claudeCode = {
|
|
|
860
874
|
);
|
|
861
875
|
break;
|
|
862
876
|
case "Stop":
|
|
863
|
-
events.push(
|
|
877
|
+
events.push(
|
|
878
|
+
ev("turn.ended", {
|
|
879
|
+
turn_id,
|
|
880
|
+
reason: "stop",
|
|
881
|
+
background: Array.isArray(s.background_tasks) ? s.background_tasks.length : void 0
|
|
882
|
+
})
|
|
883
|
+
);
|
|
864
884
|
break;
|
|
865
885
|
case "StopFailure":
|
|
866
886
|
events.push(
|
|
@@ -903,6 +923,8 @@ var claudeCode = {
|
|
|
903
923
|
if (event === "UserPromptSubmit" && typeof s.prompt === "string") hints.prompt = s.prompt;
|
|
904
924
|
const host = input.env.CLAUDE_CODE_HOST_SESSION_ID;
|
|
905
925
|
if (host && DESKTOP_ID.test(host)) hints.desktop_id = host;
|
|
926
|
+
const attended = input.env.CLAUDE_CODE_SESSION_ATTENDED;
|
|
927
|
+
if (attended === "1" || attended === "0") hints.attended = attended === "1" || !!input.env.SESSIONPIPE_CONTROL_JOB;
|
|
906
928
|
if (event !== "PreToolUse" && event !== "PostToolUse") hints.claude_pid = claudePid(input.env);
|
|
907
929
|
const r = { session, events, hints };
|
|
908
930
|
if (typeof s.transcript_path === "string") r.transcript = s.transcript_path;
|
|
@@ -923,6 +945,7 @@ var claudeCode = {
|
|
|
923
945
|
const cwd = out.cwd ?? session.cwd;
|
|
924
946
|
Object.assign(out, gitFacts(cwd), out.branch ? { branch: out.branch } : {});
|
|
925
947
|
if (!out.url && typeof hints.desktop_id === "string") out.url = `claude://code/continue/${hints.desktop_id}`;
|
|
948
|
+
if (typeof hints.attended === "boolean") out.attended = hints.attended || !!out.url;
|
|
926
949
|
return out;
|
|
927
950
|
},
|
|
928
951
|
backfill(sinceMs, env = process.env) {
|
|
@@ -958,6 +981,9 @@ function notClaudeCode(id, s) {
|
|
|
958
981
|
function pickSource(v) {
|
|
959
982
|
return typeof v === "string" && ["startup", "resume", "clear", "compact", "fork"].includes(v) ? v : "unknown";
|
|
960
983
|
}
|
|
984
|
+
var harnessWord = (v) => typeof v === "string" && /^[A-Za-z0-9][A-Za-z0-9_.-]{0,39}$/.test(v) ? v : void 0;
|
|
985
|
+
var WRAPPER = /^<(?:task-notification|cross-session-message|system-reminder|local-command-stdout|command-[a-z-]+)[\s/>]/i;
|
|
986
|
+
var injectedBlock = (prompt) => WRAPPER.test(prompt.trim());
|
|
961
987
|
function errText(v) {
|
|
962
988
|
if (typeof v === "string") return v.slice(0, 2e3);
|
|
963
989
|
if (v && typeof v === "object") {
|
|
@@ -1074,7 +1100,27 @@ function claudeLogin(dir, home = homeDir()) {
|
|
|
1074
1100
|
} catch {
|
|
1075
1101
|
}
|
|
1076
1102
|
}
|
|
1077
|
-
return
|
|
1103
|
+
return apiAccount(dir);
|
|
1104
|
+
}
|
|
1105
|
+
var ANTHROPIC_HOST = /(^|\.)anthropic\.com$/i;
|
|
1106
|
+
function apiAccount(dir) {
|
|
1107
|
+
let base;
|
|
1108
|
+
try {
|
|
1109
|
+
base = JSON.parse(readFileSync3(settingsIn(dir), "utf8")).env?.ANTHROPIC_BASE_URL;
|
|
1110
|
+
} catch {
|
|
1111
|
+
return null;
|
|
1112
|
+
}
|
|
1113
|
+
if (typeof base !== "string") return null;
|
|
1114
|
+
let u;
|
|
1115
|
+
try {
|
|
1116
|
+
u = new URL(base.trim());
|
|
1117
|
+
} catch {
|
|
1118
|
+
return null;
|
|
1119
|
+
}
|
|
1120
|
+
if (u.protocol !== "https:" && u.protocol !== "http:" || !u.hostname || ANTHROPIC_HOST.test(u.hostname))
|
|
1121
|
+
return null;
|
|
1122
|
+
const origin = `${u.protocol}//${u.host}`;
|
|
1123
|
+
return { id: `api-${createHash("sha256").update(origin).digest("hex").slice(0, 16)}`, name: u.host };
|
|
1078
1124
|
}
|
|
1079
1125
|
var accountCache = /* @__PURE__ */ new Map();
|
|
1080
1126
|
function claudeAccount(dir) {
|
|
@@ -1555,7 +1601,7 @@ var codex = {
|
|
|
1555
1601
|
if (j && typeof j === "object" && !Array.isArray(j)) s = j;
|
|
1556
1602
|
} catch {
|
|
1557
1603
|
}
|
|
1558
|
-
const id = s.session_id;
|
|
1604
|
+
const id = s.session_id ?? s.thread_id ?? s.conversation_id ?? s["thread-id"] ?? s["session-id"];
|
|
1559
1605
|
if (!id) return null;
|
|
1560
1606
|
if (s.transcript_path === null) return null;
|
|
1561
1607
|
const session = { id: String(id), cwd: typeof s.cwd === "string" ? s.cwd : input.cwd };
|
|
@@ -2317,6 +2363,22 @@ function prune5(o) {
|
|
|
2317
2363
|
var ADAPTERS = [claudeCode, codex, geminiCli, antigravity, devin];
|
|
2318
2364
|
var adapterByName = (name) => ADAPTERS.find((a) => a.name === name);
|
|
2319
2365
|
|
|
2366
|
+
// ../core/src/launched-by.ts
|
|
2367
|
+
var LAUNCHED_BY_ENV = "SESSIONPIPE_LAUNCHED_BY";
|
|
2368
|
+
var LAUNCHED_BY = /^[a-z][a-z0-9-]{0,39}:[A-Za-z0-9._:-]{1,128}$/;
|
|
2369
|
+
function launchedBy(env) {
|
|
2370
|
+
const v = env[LAUNCHED_BY_ENV]?.trim();
|
|
2371
|
+
return v && LAUNCHED_BY.test(v) ? v : void 0;
|
|
2372
|
+
}
|
|
2373
|
+
function readHook(adapter, input) {
|
|
2374
|
+
const r = adapter.fromHook(input);
|
|
2375
|
+
if (r && !r.session.parent_id) {
|
|
2376
|
+
const launcher = launchedBy(input.env);
|
|
2377
|
+
if (launcher && launcher !== `${adapter.name}:${r.session.id}`) r.session.launched_by = launcher;
|
|
2378
|
+
}
|
|
2379
|
+
return r;
|
|
2380
|
+
}
|
|
2381
|
+
|
|
2320
2382
|
// src/index.ts
|
|
2321
2383
|
function matches(expect, got, pathStr = "") {
|
|
2322
2384
|
if (expect === "*") return null;
|
|
@@ -2347,7 +2409,7 @@ async function runAdapterFixtures(files) {
|
|
|
2347
2409
|
results.push({ file, ok: false, why: `no adapter ${fx.harness}` });
|
|
2348
2410
|
continue;
|
|
2349
2411
|
}
|
|
2350
|
-
const r = adapter
|
|
2412
|
+
const r = readHook(adapter, {
|
|
2351
2413
|
argv: fx.input.argv,
|
|
2352
2414
|
stdin: fx.input.stdin,
|
|
2353
2415
|
env: fx.input.env ?? {},
|