sessionpipe 0.13.0 → 0.13.1

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/connect.d.ts CHANGED
@@ -16,7 +16,12 @@ export declare function connectFolders(o: {
16
16
  exists?: (dir: string) => boolean;
17
17
  max?: number;
18
18
  }): FolderChoice;
19
+ /** `--tier N` from the command line: digits, held to 0–3 (`--tier 9` is 3), or `fallback`
20
+ * when there is no --tier. A value left off or not written in digits (`--tier` last,
21
+ * `--tier one`, `--tier 1.5`, `--tier 0x2`, `--tier --name x`) is refused: stored, it
22
+ * became a tier no event can carry (`null`, or 1.5 where the schema takes an integer). */
23
+ export declare function tierArg(argv: readonly string[], fallback: 0 | 1 | 2 | 3): 0 | 1 | 2 | 3;
19
24
  /** The tier `connect` reports at: --tier when given; otherwise 2 (what a session board
20
25
  * needs: the asks and the answers, secrets removed), never lowering a sink set higher. */
21
- export declare function connectTier(flag: string | undefined, current: number | undefined): 0 | 1 | 2 | 3;
26
+ export declare function connectTier(flag: 0 | 1 | 2 | 3 | undefined, current: number | undefined): 0 | 1 | 2 | 3;
22
27
  //# sourceMappingURL=connect.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"AAMA,yFAAyF;AACzF,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAM1D;AAMD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;0DACsD;IACtD,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;CACzD;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,CAAC,EAAE;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,YAAY,CAiBf;AAED;2FAC2F;AAC3F,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAIhG"}
1
+ {"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"AAMA,yFAAyF;AACzF,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAM1D;AAMD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;0DACsD;IACtD,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;CACzD;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,CAAC,EAAE;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,YAAY,CAiBf;AAED;;;2FAG2F;AAC3F,wBAAgB,OAAO,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAOvF;AAED;2FAC2F;AAC3F,wBAAgB,WAAW,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAKvG"}
@@ -54,6 +54,7 @@ export declare function updateSummary(o: {
54
54
  off: string | null;
55
55
  paired: boolean;
56
56
  rec: UpdateRecord;
57
+ platform?: NodeJS.Platform;
57
58
  }): UpdateSummary;
58
59
  export declare function ago(iso: string, now: number): string;
59
60
  /** One line: whether it's automatic, when it last looked, what it found. */
@@ -1 +1 @@
1
- {"version":3,"file":"autoupdate.d.ts","sourceRoot":"","sources":["../../src/control/autoupdate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"autoupdate.d.ts","sourceRoot":"","sources":["../../src/control/autoupdate.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/control/cli.ts"],"names":[],"mappings":"AAKA,OAAO,EAWL,KAAK,IAAI,EAEV,MAAM,mBAAmB,CAAC;AA4B3B,eAAO,MAAM,YAAY,ulBAK2E,CAAC;AAuDrG;;yFAEyF;AACzF,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EAAE,EACjB,EAAE,EAAE,KAAK,GAAG,QAAQ,EACpB,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,SAAe,GAClB;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAkCvC;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqK3G;AAED,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GAAG,MAAM,EAAE,CAK3F;AAwKD;;kFAEkF;AAClF,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,GAAG,IAAI,CASlE;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CASvF;AAED;kDACkD;AAClD,eAAO,MAAM,SAAS;IACpB,KAAK,QAAM,MAAM,CAAC,cAAc;IAChC,KAAK,MAAM,MAAM,KAAG,IAAI;IACxB,GAAG,MAAM,MAAM,KAAG,IAAI;IACtB,IAAI,SAAS,MAAM,KAAG,IAAI;CAC3B,CAAC;AAEF;;wEAEwE;AACxE,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,EAAE,OAAO,SAAS,EACpB,MAAM,GAAE,MAAM,MAAM,EAAe,GAClC,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;oCAEoC;AACpC,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CASjH"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/control/cli.ts"],"names":[],"mappings":"AAKA,OAAO,EAYL,KAAK,IAAI,EAEV,MAAM,mBAAmB,CAAC;AA4B3B,eAAO,MAAM,YAAY,ulBAK2E,CAAC;AAuDrG;;yFAEyF;AACzF,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EAAE,EACjB,EAAE,EAAE,KAAK,GAAG,QAAQ,EACpB,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,SAAe,GAClB;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAkCvC;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuK3G;AAED,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,GAAG,MAAM,EAAE,CAK3F;AAwKD;;kFAEkF;AAClF,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,GAAG,IAAI,CASlE;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CASvF;AAED;kDACkD;AAClD,eAAO,MAAM,SAAS;IACpB,KAAK,QAAM,MAAM,CAAC,cAAc;IAChC,KAAK,MAAM,MAAM,KAAG,IAAI;IACxB,GAAG,MAAM,MAAM,KAAG,IAAI;IACtB,IAAI,SAAS,MAAM,KAAG,IAAI;CAC3B,CAAC;AAEF;;wEAEwE;AACxE,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,EAAE,OAAO,SAAS,EACpB,MAAM,GAAE,MAAM,MAAM,EAAe,GAClC,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;oCAEoC;AACpC,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CASjH"}
package/dist/fold.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ import { type Event, type SinkConfig } from "@sessionpipe/core";
2
+ export type ToolsMode = "all" | "main" | "beat";
3
+ export declare const TOOLS_MODES: readonly ToolsMode[];
4
+ /** One tool event per this window, per session, when a sink thins them. */
5
+ export declare const TOOL_FOLD_MS = 60000;
6
+ export declare function isToolsMode(v: unknown): v is ToolsMode;
7
+ /** What a sink is sent: its owner's own setting, else what the receiver's well-known
8
+ * file asked for, else every tool event. Never thinned on nobody's say-so: a receiver
9
+ * that reads a subagent's tool calls (sessionpipe-gui does) keeps them on an upgrade. */
10
+ export declare function toolsMode(s: Pick<SinkConfig, "url" | "tools" | "receiver_tools">): ToolsMode;
11
+ /** Whether a sink in `mode` is sent `e`. `clock` holds, per session (`key`), the time
12
+ * of the last tool event it was sent, and moves when this one is. Times are the
13
+ * events' own, so a backlog thins the same way it would have live. An event a little
14
+ * out of time order (hooks reach the outbox in lock order, not hook order) falls in
15
+ * the window like any other; only a jump back by a whole window or more (a clock set
16
+ * back) sends and restarts it. */
17
+ export declare function sendTool(e: Event, mode: ToolsMode, clock: Record<string, number>, key: string): boolean;
18
+ /** <state>/folds/<sink>.json: the per-session clock `sendTool` reads, beside the
19
+ * sink's cursors. Written with them, after a batch was acknowledged, so a refused
20
+ * batch's tool event is not taken for sent. */
21
+ export declare class ToolClock {
22
+ readonly root: string;
23
+ readonly sink: string;
24
+ constructor(root: string, sink: string);
25
+ private file;
26
+ read(): Record<string, number>;
27
+ write(c: Record<string, number>): void;
28
+ }
29
+ //# sourceMappingURL=fold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fold.d.ts","sourceRoot":"","sources":["../src/fold.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,UAAU,EAAU,MAAM,mBAAmB,CAAC;AAExE,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAChD,eAAO,MAAM,WAAW,EAAE,SAAS,SAAS,EAA4B,CAAC;AAEzE,2EAA2E;AAC3E,eAAO,MAAM,YAAY,QAAS,CAAC;AAKnC,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,SAAS,CAEtD;AAED;;0FAE0F;AAC1F,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,KAAK,GAAG,OAAO,GAAG,gBAAgB,CAAC,GAAG,SAAS,CAI5F;AASD;;;;;mCAKmC;AACnC,wBAAgB,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAuBvG;AAED;;gDAEgD;AAChD,qBAAa,SAAS;IAElB,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM;IAFvB,YACW,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACnB;IACJ,OAAO,CAAC,IAAI;IAGZ,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAO7B;IACD,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CASrC;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AAGA,wBAAgB,UAAU,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA4D/E;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAO5F"}
1
+ {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AAGA,wBAAgB,UAAU,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA6D/E;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAO5F"}
@@ -1 +1 @@
1
- {"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":";AA0BA,iFAAiF;AACjF,MAAM,WAAW,MAAM;IACrB,KAAK,IAAI,MAAM,CAAC;IAChB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;0FAE0F;AAC1F,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwRhG"}
1
+ {"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":";AA0BA,iFAAiF;AACjF,MAAM,WAAW,MAAM;IACrB,KAAK,IAAI,MAAM,CAAC;IAChB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;0FAE0F;AAC1F,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4RhG"}
package/dist/hook.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // sessionpipe 0.13.0 · Apache-2.0 · https://sessionpipe.org
2
+ // sessionpipe 0.13.1 · Apache-2.0 · https://sessionpipe.org
3
3
 
4
4
  // src/hook.ts
5
5
  import { spawn } from "node:child_process";
@@ -233,7 +233,7 @@ async function hookMain(argv, env, io) {
233
233
  function anySinkAbove(tier) {
234
234
  try {
235
235
  const c = JSON.parse(readFileSync(configFile(), "utf8"));
236
- return (c.sinks ?? []).some((s) => Number(s.tier) > tier && !s.paused);
236
+ return (c.sinks ?? []).some((s) => Math.trunc(Math.min(Number(s.tier), s.max_tier ?? 3)) > tier && !s.paused);
237
237
  } catch {
238
238
  return false;
239
239
  }
package/dist/hook.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/hook.ts", "../src/control/local.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\n// SPDX-License-Identifier: Apache-2.0\n// The hook path. A harness runs `node hook.js <harness> <event>`; this reads stdin,\n// writes one job file, spawns the worker detached, prints what the harness needs\n// (Antigravity's answer) and exits 0 \u2014 in milliseconds, with nothing but node:\n// builtins imported (the build checks that). No network, no schema library, no\n// config parsing beyond one small file read for the throttle.\nimport { spawn } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { appendFileSync, existsSync, mkdirSync, readFileSync, realpathSync, statSync, writeFileSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { ask, socketPath } from \"./control/local.js\";\n\n/** A Claude Code session id (the same test as core's notClaudeCode). */\nconst UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n/** A permission mode as a hook payload spells it (core's `hookMode`, repeated because\n * this file imports nothing but node builtins). Claude Code writes `permission_mode`;\n * `permissionMode` is the spelling its transcript records use, taken too. */\nconst MODE_SHAPE = /^[A-Za-z]{1,40}$/;\nconst modeOf = (s: Record<string, unknown>): string | undefined => {\n const v = typeof s.permission_mode === \"string\" ? s.permission_mode : s.permissionMode;\n return typeof v === \"string\" && MODE_SHAPE.test(v) ? v : undefined;\n};\n\n/** The two streams the hook touches: stdin once, whole; stdout for an answer. */\nexport interface HookIO {\n stdin(): Buffer;\n stdout(text: string): void;\n}\n\n/** One hook run: `argv` is [harness, event, ...] as the harness invoked it, `env` the\n * process environment. Resolves once the job is on its way and any answer printed;\n * the process then exits 0, whatever happened (the hook is invisible to the harness). */\nexport async function hookMain(argv: string[], env: NodeJS.ProcessEnv, io: HookIO): Promise<void> {\n const t0 = process.hrtime.bigint();\n /** The hook's own work, when a control wait follows it (the wait is not the hook's cost). */\n let workMs: number | null = null;\n const [harness = \"\", event = \"\", ...rest] = argv;\n\n function stateDir(): string {\n if (env.SESSIONPIPE_STATE) return path.resolve(env.SESSIONPIPE_STATE);\n const home = os.homedir();\n if (process.platform === \"win32\")\n return path.join(env.LOCALAPPDATA || path.join(home, \"AppData\", \"Local\"), \"sessionpipe\");\n return path.join(env.XDG_STATE_HOME || path.join(home, \".local\", \"state\"), \"sessionpipe\");\n }\n function configFile(): string {\n if (env.SESSIONPIPE_CONFIG) return path.resolve(env.SESSIONPIPE_CONFIG);\n const home = os.homedir();\n if (process.platform === \"win32\")\n return path.join(env.APPDATA || path.join(home, \"AppData\", \"Roaming\"), \"sessionpipe\", \"config.json\");\n return path.join(env.XDG_CONFIG_HOME || path.join(home, \".config\"), \"sessionpipe\", \"config.json\");\n }\n\n // Antigravity parses stdout as the hook's answer; `{}` is \"carry on\" for every event we\n // register. PreToolUse is not one of them: `{}` there is a deny, so an entry an older\n // install left behind asks the person instead (core's AG_STALE_PRETOOL, same bytes).\n if (harness === \"antigravity\") {\n try {\n io.stdout(\n event === \"PreToolUse\"\n ? '{\"decision\":\"ask\",\"reason\":\"sessionpipe: an outdated PreToolUse hook is still loaded. Restart this conversation (or run sessionpipe install) to drop it.\"}\\n'\n : \"{}\\n\",\n );\n } catch {}\n }\n\n const state = stateDir();\n try {\n if (!harness || !event) throw new Error(\"usage: hook <harness> <event>\");\n let stdin = \"\";\n if (harness !== \"codex\" || event !== \"notify\") {\n try {\n const buf = io.stdin();\n stdin = buf.subarray(0, 1024 * 1024).toString(\"utf8\");\n } catch {}\n }\n // Claude Code's status line (install --status-line) runs on every refresh. It shows\n // the account's limits, and only a change becomes a job (limits.observed): at most\n // one a minute per config dir, and none when no sink takes tier 1.\n if (harness === \"claude-code\" && event === \"StatusLine\") {\n const limits = statusLimits(stdin);\n if (limits.line) {\n try {\n io.stdout(`${limits.line}\\n`);\n } catch {}\n }\n if (!limits.sig || !anySinkAbove(0) || !limitsDue(limits.sig)) return finish(false);\n }\n // Tool events are the bulk of what a harness fires. When no sink takes tier \u2265 1\n // they are only a \"still working\" signal: one heartbeat a minute per session.\n const TOOL = /^(PreToolUse|PostToolUse|PostToolUseFailure|BeforeTool|AfterTool|PostInvocation)$/;\n if (TOOL.test(event) && !anySinkAbove(0)) {\n const id = sessionIdOf(stdin);\n if (!id || !beatDue(id)) return finish(false);\n }\n // A Stop asks the daemon BEFORE its event goes to the worker: the worker reports the\n // Stop to the daemon too, and a message queued for this Stop must be taken here,\n // not rerouted because the event got there first.\n const stopAnswer = event === \"Stop\" ? await (controlAsk(stdin) ?? Promise.resolve(null)) : null;\n mkdirSync(path.join(state, \"jobs\"), { recursive: true, mode: 0o700 });\n const job = {\n harness,\n event,\n argv: [harness, event, ...rest],\n stdin,\n cwd: process.cwd(),\n env: pick([\n // Where a harness keeps its config and its sessions, so a job swept by a worker\n // some other harness's hook spawned still resolves this harness's own homes\n // (run.ts sweepJobs runs any stale job file, whatever spawned the worker).\n \"APPDATA\",\n \"CLAUDE_CODE_HOST_SESSION_ID\",\n // session.attended: Claude Code's own word, and SESSIONPIPE_CONTROL_JOB below, the\n // control daemon's mark on a turn it runs for a person's message.\n \"CLAUDE_CODE_SESSION_ATTENDED\",\n \"CLAUDE_CONFIG_DIR\",\n \"CLAUDE_PROJECT_DIR\",\n \"CODEX_HOME\",\n // Devin's payload names no folder at all; this is the only thing that does.\n \"DEVIN_PROJECT_DIR\",\n \"GEMINI_CLI_HOME\",\n // The session the control daemon ran this one for (PROTOCOL.md \u00A73 delegated_by).\n \"SESSIONPIPE_ASKED_BY\",\n \"SESSIONPIPE_CONTROL_JOB\",\n // The launcher a script named for a session it starts (PROTOCOL.md \u00A73 launched_by).\n \"SESSIONPIPE_LAUNCHED_BY\",\n // Devin's config file and session store are both resolved through these.\n \"XDG_CONFIG_HOME\",\n \"XDG_DATA_HOME\",\n ]),\n ppid: process.ppid,\n at: Date.now(),\n };\n const jobFile = path.join(\n state,\n \"jobs\",\n `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}.json`,\n );\n writeFileSync(jobFile, JSON.stringify(job), { mode: 0o600 });\n if (!env.SESSIONPIPE_NO_WORKER) {\n const worker = path.join(path.dirname(fileURLToPath(import.meta.url)), \"worker.js\");\n const p = spawn(process.execPath, [worker, jobFile], { detached: true, stdio: \"ignore\", windowsHide: true, env });\n p.unref();\n }\n if (stopAnswer) {\n try {\n io.stdout(`${stopAnswer}\\n`);\n } catch {}\n }\n // A PermissionRequest waits AFTER its event is on its way, so the receiver already\n // shows the Allow / Deny this answer is for.\n const ctl = event === \"PermissionRequest\" ? controlAsk(stdin) : null;\n if (ctl) {\n workMs = Number(process.hrtime.bigint() - t0) / 1e6;\n const out = await ctl;\n if (out) {\n try {\n io.stdout(`${out}\\n`);\n } catch {}\n }\n }\n return finish(true);\n } catch {\n return finish(false); // the hook must be invisible to the harness\n }\n\n /** Control (spec/CONTROL.md \u00A76, \u00A79): only on a machine with control paired, and only\n * for a message the daemon itself verified. A Stop hook asks for a queued message and\n * answers a block with it; a PermissionRequest hook waits for the person's signed\n * answer while the terminal shows its own prompt, first answer wins. Anything that\n * goes wrong (no daemon, a timeout) prints nothing: the harness carries on as usual. */\n function controlAsk(stdin: string): Promise<string | null> | null {\n if (harness !== \"claude-code\" || (event !== \"Stop\" && event !== \"PermissionRequest\")) return null;\n // A turn the daemon itself runs (a held Agent SDK session, a headless resume) never\n // asks at its Stop: the daemon hands that session its next message itself. Its\n // permission prompts do park: nobody is at a terminal there, so the owner's signed\n // answer is the only one it can get (a session started at edits, auto or inherit\n // asks before a Bash).\n if (env.SESSIONPIPE_CONTROL_JOB && event === \"Stop\") return null;\n const sock = socketPath(state, env);\n if (\n process.platform === \"win32\"\n ? !existsSync(path.join(path.dirname(configFile()), \"control.json\"))\n : !existsSync(sock)\n )\n return null;\n let s: Record<string, unknown>;\n try {\n s = JSON.parse(stdin) as Record<string, unknown>;\n } catch {\n return null;\n }\n const id = typeof s.session_id === \"string\" ? s.session_id : \"\";\n if (!id) return null;\n // Our entry in ~/.claude/settings.json is run by every harness that imports that file\n // \u2014 Devin's `claude` hooks provider is live, not a stub \u2014 and it arrives under the\n // claude-code name. Every Claude Code payload names a transcript and a UUID session;\n // a payload with neither is somebody else's, and must not be parked for up to 125 s\n // waiting on an answer that is not coming. Same test as core's notClaudeCode\n // (claude-code.ts), which the worker applies; repeated here because this file imports\n // nothing but node builtins.\n if (typeof s.transcript_path !== \"string\" && !UUID.test(id)) return null;\n const session = `claude-code:${id}`;\n // The session's own permission mode, in its own words. Every Claude Code hook\n // payload carries it, and it is the only place a mode the person chose at the\n // keyboard can be read from (CONTROL.md \u00A76, The session's mode): the daemon records\n // it, and the in-place lane and a relaunch's narrowing both rest on it. Taken as a\n // shape, not as a value \u2014 the daemon knows the modes it acts on; this file imports\n // nothing but node builtins.\n const mode = modeOf(s);\n if (event === \"Stop\")\n return ask(\n sock,\n { op: \"stop\", session, active: s.stop_hook_active === true, ...(mode ? { mode } : {}) },\n 300,\n ).then((r) => (r?.op === \"block\" ? JSON.stringify({ decision: \"block\", reason: r.reason }) : null));\n // The attention id the adapter puts on attention.needed (claude-code.ts), so the\n // receiver's Allow / Deny names this very prompt.\n const tool =\n typeof s.tool_name === \"string\" && /^[A-Za-z0-9_.:-]{1,120}$/.test(s.tool_name) ? s.tool_name : undefined;\n const turn = typeof s.prompt_id === \"string\" ? s.prompt_id : undefined;\n const attention = `perm-${createHash(\"sha256\")\n .update(`${turn ?? \"\"}|${tool ?? \"\"}|${JSON.stringify(s.tool_input ?? null)}`)\n .digest(\"hex\")\n .slice(0, 16)}`;\n return ask(sock, { op: \"permission\", session, attention, ...(tool ? { tool } : {}) }, 125_000).then((r) =>\n r?.op === \"decision\"\n ? JSON.stringify({\n hookSpecificOutput: {\n hookEventName: \"PermissionRequest\",\n decision:\n r.behavior === \"allow\"\n ? { behavior: \"allow\" }\n : { behavior: \"deny\", message: r.message || \"Denied by the owner (sessionpipe control).\" },\n },\n })\n : null,\n );\n }\n\n /** The timing line; the process exits 0 right after. */\n function finish(spawned: boolean): void {\n const total = Number(process.hrtime.bigint() - t0) / 1e6;\n const ms = workMs ?? total;\n try {\n mkdirSync(state, { recursive: true });\n appendFileSync(\n path.join(state, \"timing.jsonl\"),\n `${JSON.stringify({ at: Date.now(), harness, event, ms: Math.round(ms * 10) / 10, spawned, ...(workMs !== null ? { control_wait_ms: Math.round(total - workMs) } : {}) })}\\n`,\n );\n } catch {}\n }\n function pick(names: string[]): Record<string, string> {\n const out: Record<string, string> = {};\n for (const n of names) if (env[n] !== undefined) out[n] = env[n] as string;\n return out;\n }\n function anySinkAbove(tier: number): boolean {\n try {\n const c = JSON.parse(readFileSync(configFile(), \"utf8\")) as { sinks?: { tier?: number; paused?: string }[] };\n return (c.sinks ?? []).some((s) => Number(s.tier) > tier && !s.paused);\n } catch {\n return false;\n }\n }\n function sessionIdOf(stdin: string): string {\n const m = /\"(?:session_id|sessionId|conversationId)\"\\s*:\\s*\"([^\"]{1,128})\"/.exec(stdin);\n return m?.[1] ?? \"\";\n }\n /** The status line's `rate_limits` as one short line (`5h 23% \u00B7 week 41%`), and as\n * the text a change is told by. Empty when the account has none. */\n function statusLimits(stdin: string): { line: string; sig: string } {\n let rl: unknown;\n try {\n rl = (JSON.parse(stdin) as { rate_limits?: unknown }).rate_limits;\n } catch {}\n if (!rl || typeof rl !== \"object\") return { line: \"\", sig: \"\" };\n const label: Record<string, string> = { five_hour: \"5h\", seven_day: \"week\", spend_limit: \"spend\" };\n const parts = Object.entries(rl as Record<string, { used_percentage?: unknown }>)\n .filter(([, w]) => typeof w?.used_percentage === \"number\")\n .map(([id, w]) => `${label[id] ?? id} ${Math.round(w.used_percentage as number)}%`);\n return parts.length ? { line: parts.join(\" \u00B7 \"), sig: JSON.stringify(rl) } : { line: \"\", sig: \"\" };\n }\n /** A change of limits, at most one a minute per config dir (one account each): the\n * stamp holds the last limits sent, its mtime when. */\n function limitsDue(sig: string): boolean {\n const dir = createHash(\"sha256\")\n .update(env.CLAUDE_CONFIG_DIR ?? \"\")\n .digest(\"hex\")\n .slice(0, 12);\n const stamp = path.join(state, \"beats\", `${harness}-limits-${dir}`);\n try {\n if (readFileSync(stamp, \"utf8\") === sig || Date.now() - statSync(stamp).mtimeMs < 60_000) return false;\n } catch {}\n try {\n mkdirSync(path.dirname(stamp), { recursive: true, mode: 0o700 });\n writeFileSync(stamp, sig, { mode: 0o600 });\n } catch {}\n return true;\n }\n /** One heartbeat per minute per session: the stamp file's mtime is the clock. */\n function beatDue(id: string): boolean {\n const stamp = path.join(state, \"beats\", `${harness}-${id.replace(/[^A-Za-z0-9_-]/g, \"_\")}`);\n try {\n if (Date.now() - statSync(stamp).mtimeMs < 60_000) return false;\n } catch {}\n try {\n mkdirSync(path.dirname(stamp), { recursive: true, mode: 0o700 });\n writeFileSync(stamp, \"\", { mode: 0o600 });\n } catch {}\n return true;\n }\n}\n\n// Run as `node hook.js <harness> <event>`; importing this module runs nothing. The main\n// module is known by its real path: node resolves symlinks for import.meta.url, argv[1]\n// keeps the spelling it was given (/var \u2192 /private/var on macOS).\nif (process.argv[1] && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href)\n hookMain(process.argv.slice(2), process.env, {\n // fd 0 and 1 are the test runner's own (a read of 0 would block it); launcher.test.ts\n // and the bench run these two through the real binary.\n /* v8 ignore next -- see above */\n stdin: () => readFileSync(0),\n /* v8 ignore next -- see above */\n stdout: (text) => writeFileSync(1, text),\n }).then(() => process.exit(0));\n", "// SPDX-License-Identifier: Apache-2.0\n// The daemon's local socket (spec/CONTROL.md \u00A78, \u00A713): how the waiter, the Stop and\n// PermissionRequest hooks, the worker and `sessionpipe ask` talk to the one daemon on\n// this machine. Line-delimited JSON, one request per connection; every request but an\n// ask gets one reply, an ask gets a few in order on the same connection. A Unix socket\n// in the state directory (0600, in a 0700 dir); a per-user named pipe on Windows. Only\n// node: builtins \u2014 the hook bundle imports this.\nimport net from \"node:net\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nexport type LocalRequest =\n /** A waiter parks until a message for its session arrives. `channel`: the waiter is\n * `sessionpipe channel`, which pushes the message into the session rather than handing\n * it to a turn that asked for it (CONTROL.md \u00A78). */\n | { op: \"wait\"; session: string; pid?: number; channel?: boolean }\n /** A Stop hook asks for a queued message (turn mode). `mode` is the session's own\n * permission mode, as its payload reports it (CONTROL.md \u00A76, The session's mode). */\n | { op: \"stop\"; session: string; active: boolean; mode?: string }\n /** A PermissionRequest hook parks until a verified answer, or until it's released. */\n | { op: \"permission\"; session: string; attention: string; tool?: string }\n /** The worker reports a hook event: turn state, attention closure, and the session's\n * own permission mode where its payload named one. */\n | { op: \"event\"; session: string; event: string; transcript?: string; cwd?: string; mode?: string }\n /** `sessionpipe control status`. */\n | { op: \"status\" }\n /** `sessionpipe update` installed a new copy: restart onto it once nothing is in hand. */\n | { op: \"restart\" }\n /** `sessionpipe pool \u2026` while the daemon runs: the daemon holds the pool's engine\n * (pins, credentials, the listener), so a change goes through it. `status` reads;\n * the rest are CONTROL.md \u00A76's actions, plus `import` (reads this machine's own\n * Claude Code logins, which no receiver may ask for). */\n | { op: \"pool\"; action: PoolOp; account?: string; order?: string[]; code?: string }\n /** `sessionpipe ask` (CONTROL.md \u00A713): a session here hands a task to another agent on\n * this machine and gets the answer back on this connection. */\n | AskRequest;\n\nexport type PoolOp =\n | \"status\"\n | \"on\"\n | \"off\"\n | \"enable\"\n | \"disable\"\n | \"remove\"\n | \"order\"\n | \"refresh\"\n | \"login.begin\"\n | \"login.complete\"\n | \"import\";\n\nexport interface AskRequest {\n op: \"ask\";\n /** `<harness>:<id>` of the asking session, when known: the events go on it. */\n from?: string;\n /** The agent to ask. */\n harness: string;\n /** An existing `<harness>:<id>` to continue instead of a new session. */\n session?: string;\n /** 1\u201320 000 characters, not all whitespace. */\n text: string;\n /** Absolute; the caller's folder by default. */\n cwd: string;\n /** Every ancestor ref, outermost first (from env SESSIONPIPE_ASK_CHAIN). */\n chain: string[];\n /** Narrower than the machine's mode, never wider. */\n permission?: \"read\" | \"safe\";\n model?: string;\n pid?: number;\n}\n\nexport type LocalReply =\n | { op: \"message\"; text: string; id: string }\n | { op: \"block\"; reason: string; id: string }\n | { op: \"decision\"; behavior: \"allow\" | \"deny\"; message?: string; id: string }\n | { op: \"none\" }\n /** A newer waiter for the same session took over; this one stops. */\n | { op: \"replaced\" }\n | { op: \"ok\" }\n | { op: \"status\"; status: unknown }\n /** A pool op's answer: the ack it would earn (CONTROL.md \u00A76) and the pool as it now\n * stands (`status`: the fa\u00E7ade's PoolStatus; `detail`: the summary line, or a\n * login.begin's \"<pending id> <URL>\"). */\n | {\n op: \"pool\";\n outcome: \"delivered\" | \"refused\" | \"failed\" | \"unsupported\";\n code?: string;\n detail: string;\n status?: unknown;\n /** `import`: what was added and what was left out (control/pool.ts Imported). */\n imported?: unknown;\n }\n // An ask's replies, in order (askMany): `asked`, any `progress`, then exactly one of\n // `answer`, `refused` and `failed`, after which the daemon closes the connection.\n /** The run began; `session` once it is known. */\n | { op: \"asked\"; ask_id: string; session?: string }\n /** The answer so far, whole, with a rising seq. */\n | { op: \"progress\"; text: string; seq: number }\n | { op: \"answer\"; ask_id: string; session: string; text: string; ms: number }\n /** ask_off \u00B7 harness \u00B7 folder \u00B7 depth \u00B7 loop \u00B7 start_limit \u00B7 bad_fields */\n | { op: \"refused\"; code: string; detail: string }\n | { op: \"failed\"; detail: string };\n\n/** The replies that end an ask. */\nexport type AskEnd = Extract<LocalReply, { op: \"answer\" | \"refused\" | \"failed\" }>;\n\n/** Where the daemon listens. `SESSIONPIPE_SOCKET` overrides (tests). */\nexport function socketPath(state: string, env: NodeJS.ProcessEnv = process.env): string {\n if (env.SESSIONPIPE_SOCKET) return env.SESSIONPIPE_SOCKET;\n if (process.platform === \"win32\") return `\\\\\\\\.\\\\pipe\\\\sessionpipe-control-${os.userInfo().username}`;\n return path.join(state, \"control.sock\");\n}\n\n/** One request, one reply. `timeoutMs` bounds the whole exchange; null on any\n * failure (no daemon, a timeout, a garbled reply) \u2014 callers treat that as \"none\". */\nexport function ask(sock: string, req: LocalRequest, timeoutMs: number): Promise<LocalReply | null> {\n return new Promise((resolve) => {\n let buf = \"\";\n let done = false;\n const s = net.connect(sock);\n const finish = (r: LocalReply | null) => {\n if (done) return;\n done = true;\n clearTimeout(t);\n s.destroy();\n resolve(r);\n };\n const t = setTimeout(() => finish(null), timeoutMs);\n s.on(\"connect\", () => s.write(`${JSON.stringify(req)}\\n`));\n s.on(\"data\", (d) => {\n buf += d.toString(\"utf8\");\n const i = buf.indexOf(\"\\n\");\n if (i < 0) return;\n try {\n finish(JSON.parse(buf.slice(0, i)) as LocalReply);\n } catch {\n finish(null);\n }\n });\n s.on(\"error\", () => finish(null));\n s.on(\"close\", () => finish(null));\n });\n}\n\n/** One request, several replies on the same connection (an ask): `onReply` sees each one\n * in order, the promise settles with the one that ends the exchange. `timeoutMs` bounds\n * the whole exchange; null when it ends without an end \u2014 no daemon, a timeout, a garbled\n * line, a connection that closed mid-run. */\nexport function askMany(\n sock: string,\n req: LocalRequest,\n onReply: (r: LocalReply) => void,\n timeoutMs: number,\n): Promise<AskEnd | null> {\n return new Promise((resolve) => {\n let buf = \"\";\n let done = false;\n const s = net.connect(sock);\n const finish = (r: AskEnd | null) => {\n if (done) return;\n done = true;\n clearTimeout(t);\n s.destroy();\n resolve(r);\n };\n const t = setTimeout(() => finish(null), timeoutMs);\n s.on(\"connect\", () => s.write(`${JSON.stringify(req)}\\n`));\n s.on(\"data\", (d) => {\n buf += d.toString(\"utf8\");\n for (let i = buf.indexOf(\"\\n\"); i >= 0 && !done; i = buf.indexOf(\"\\n\")) {\n const line = buf.slice(0, i);\n buf = buf.slice(i + 1);\n let r: LocalReply;\n try {\n r = JSON.parse(line) as LocalReply;\n } catch {\n finish(null);\n return;\n }\n onReply(r);\n if (r.op === \"answer\" || r.op === \"refused\" || r.op === \"failed\") finish(r);\n }\n });\n s.on(\"error\", () => finish(null));\n s.on(\"close\", () => finish(null));\n });\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["#!/usr/bin/env node\n// SPDX-License-Identifier: Apache-2.0\n// The hook path. A harness runs `node hook.js <harness> <event>`; this reads stdin,\n// writes one job file, spawns the worker detached, prints what the harness needs\n// (Antigravity's answer) and exits 0 \u2014 in milliseconds, with nothing but node:\n// builtins imported (the build checks that). No network, no schema library, no\n// config parsing beyond one small file read for the throttle.\nimport { spawn } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { appendFileSync, existsSync, mkdirSync, readFileSync, realpathSync, statSync, writeFileSync } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { ask, socketPath } from \"./control/local.js\";\n\n/** A Claude Code session id (the same test as core's notClaudeCode). */\nconst UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n/** A permission mode as a hook payload spells it (core's `hookMode`, repeated because\n * this file imports nothing but node builtins). Claude Code writes `permission_mode`;\n * `permissionMode` is the spelling its transcript records use, taken too. */\nconst MODE_SHAPE = /^[A-Za-z]{1,40}$/;\nconst modeOf = (s: Record<string, unknown>): string | undefined => {\n const v = typeof s.permission_mode === \"string\" ? s.permission_mode : s.permissionMode;\n return typeof v === \"string\" && MODE_SHAPE.test(v) ? v : undefined;\n};\n\n/** The two streams the hook touches: stdin once, whole; stdout for an answer. */\nexport interface HookIO {\n stdin(): Buffer;\n stdout(text: string): void;\n}\n\n/** One hook run: `argv` is [harness, event, ...] as the harness invoked it, `env` the\n * process environment. Resolves once the job is on its way and any answer printed;\n * the process then exits 0, whatever happened (the hook is invisible to the harness). */\nexport async function hookMain(argv: string[], env: NodeJS.ProcessEnv, io: HookIO): Promise<void> {\n const t0 = process.hrtime.bigint();\n /** The hook's own work, when a control wait follows it (the wait is not the hook's cost). */\n let workMs: number | null = null;\n const [harness = \"\", event = \"\", ...rest] = argv;\n\n function stateDir(): string {\n if (env.SESSIONPIPE_STATE) return path.resolve(env.SESSIONPIPE_STATE);\n const home = os.homedir();\n if (process.platform === \"win32\")\n return path.join(env.LOCALAPPDATA || path.join(home, \"AppData\", \"Local\"), \"sessionpipe\");\n return path.join(env.XDG_STATE_HOME || path.join(home, \".local\", \"state\"), \"sessionpipe\");\n }\n function configFile(): string {\n if (env.SESSIONPIPE_CONFIG) return path.resolve(env.SESSIONPIPE_CONFIG);\n const home = os.homedir();\n if (process.platform === \"win32\")\n return path.join(env.APPDATA || path.join(home, \"AppData\", \"Roaming\"), \"sessionpipe\", \"config.json\");\n return path.join(env.XDG_CONFIG_HOME || path.join(home, \".config\"), \"sessionpipe\", \"config.json\");\n }\n\n // Antigravity parses stdout as the hook's answer; `{}` is \"carry on\" for every event we\n // register. PreToolUse is not one of them: `{}` there is a deny, so an entry an older\n // install left behind asks the person instead (core's AG_STALE_PRETOOL, same bytes).\n if (harness === \"antigravity\") {\n try {\n io.stdout(\n event === \"PreToolUse\"\n ? '{\"decision\":\"ask\",\"reason\":\"sessionpipe: an outdated PreToolUse hook is still loaded. Restart this conversation (or run sessionpipe install) to drop it.\"}\\n'\n : \"{}\\n\",\n );\n } catch {}\n }\n\n const state = stateDir();\n try {\n if (!harness || !event) throw new Error(\"usage: hook <harness> <event>\");\n let stdin = \"\";\n if (harness !== \"codex\" || event !== \"notify\") {\n try {\n const buf = io.stdin();\n stdin = buf.subarray(0, 1024 * 1024).toString(\"utf8\");\n } catch {}\n }\n // Claude Code's status line (install --status-line) runs on every refresh. It shows\n // the account's limits, and only a change becomes a job (limits.observed): at most\n // one a minute per config dir, and none when no sink takes tier 1.\n if (harness === \"claude-code\" && event === \"StatusLine\") {\n const limits = statusLimits(stdin);\n if (limits.line) {\n try {\n io.stdout(`${limits.line}\\n`);\n } catch {}\n }\n if (!limits.sig || !anySinkAbove(0) || !limitsDue(limits.sig)) return finish(false);\n }\n // Tool events are the bulk of what a harness fires. When no sink takes tier \u2265 1\n // they are only a \"still working\" signal: one heartbeat a minute per session.\n const TOOL = /^(PreToolUse|PostToolUse|PostToolUseFailure|BeforeTool|AfterTool|PostInvocation)$/;\n if (TOOL.test(event) && !anySinkAbove(0)) {\n const id = sessionIdOf(stdin);\n if (!id || !beatDue(id)) return finish(false);\n }\n // A Stop asks the daemon BEFORE its event goes to the worker: the worker reports the\n // Stop to the daemon too, and a message queued for this Stop must be taken here,\n // not rerouted because the event got there first.\n const stopAnswer = event === \"Stop\" ? await (controlAsk(stdin) ?? Promise.resolve(null)) : null;\n mkdirSync(path.join(state, \"jobs\"), { recursive: true, mode: 0o700 });\n const job = {\n harness,\n event,\n argv: [harness, event, ...rest],\n stdin,\n cwd: process.cwd(),\n env: pick([\n // Where a harness keeps its config and its sessions, so a job swept by a worker\n // some other harness's hook spawned still resolves this harness's own homes\n // (run.ts sweepJobs runs any stale job file, whatever spawned the worker).\n \"APPDATA\",\n \"CLAUDE_CODE_HOST_SESSION_ID\",\n // session.attended: Claude Code's own word, and SESSIONPIPE_CONTROL_JOB below, the\n // control daemon's mark on a turn it runs for a person's message.\n \"CLAUDE_CODE_SESSION_ATTENDED\",\n \"CLAUDE_CONFIG_DIR\",\n \"CLAUDE_PROJECT_DIR\",\n \"CODEX_HOME\",\n // Devin's payload names no folder at all; this is the only thing that does.\n \"DEVIN_PROJECT_DIR\",\n \"GEMINI_CLI_HOME\",\n // The session the control daemon ran this one for (PROTOCOL.md \u00A73 delegated_by).\n \"SESSIONPIPE_ASKED_BY\",\n \"SESSIONPIPE_CONTROL_JOB\",\n // The launcher a script named for a session it starts (PROTOCOL.md \u00A73 launched_by).\n \"SESSIONPIPE_LAUNCHED_BY\",\n // Devin's config file and session store are both resolved through these.\n \"XDG_CONFIG_HOME\",\n \"XDG_DATA_HOME\",\n ]),\n ppid: process.ppid,\n at: Date.now(),\n };\n const jobFile = path.join(\n state,\n \"jobs\",\n `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}.json`,\n );\n writeFileSync(jobFile, JSON.stringify(job), { mode: 0o600 });\n if (!env.SESSIONPIPE_NO_WORKER) {\n const worker = path.join(path.dirname(fileURLToPath(import.meta.url)), \"worker.js\");\n const p = spawn(process.execPath, [worker, jobFile], { detached: true, stdio: \"ignore\", windowsHide: true, env });\n p.unref();\n }\n if (stopAnswer) {\n try {\n io.stdout(`${stopAnswer}\\n`);\n } catch {}\n }\n // A PermissionRequest waits AFTER its event is on its way, so the receiver already\n // shows the Allow / Deny this answer is for.\n const ctl = event === \"PermissionRequest\" ? controlAsk(stdin) : null;\n if (ctl) {\n workMs = Number(process.hrtime.bigint() - t0) / 1e6;\n const out = await ctl;\n if (out) {\n try {\n io.stdout(`${out}\\n`);\n } catch {}\n }\n }\n return finish(true);\n } catch {\n return finish(false); // the hook must be invisible to the harness\n }\n\n /** Control (spec/CONTROL.md \u00A76, \u00A79): only on a machine with control paired, and only\n * for a message the daemon itself verified. A Stop hook asks for a queued message and\n * answers a block with it; a PermissionRequest hook waits for the person's signed\n * answer while the terminal shows its own prompt, first answer wins. Anything that\n * goes wrong (no daemon, a timeout) prints nothing: the harness carries on as usual. */\n function controlAsk(stdin: string): Promise<string | null> | null {\n if (harness !== \"claude-code\" || (event !== \"Stop\" && event !== \"PermissionRequest\")) return null;\n // A turn the daemon itself runs (a held Agent SDK session, a headless resume) never\n // asks at its Stop: the daemon hands that session its next message itself. Its\n // permission prompts do park: nobody is at a terminal there, so the owner's signed\n // answer is the only one it can get (a session started at edits, auto or inherit\n // asks before a Bash).\n if (env.SESSIONPIPE_CONTROL_JOB && event === \"Stop\") return null;\n const sock = socketPath(state, env);\n if (\n process.platform === \"win32\"\n ? !existsSync(path.join(path.dirname(configFile()), \"control.json\"))\n : !existsSync(sock)\n )\n return null;\n let s: Record<string, unknown>;\n try {\n s = JSON.parse(stdin) as Record<string, unknown>;\n } catch {\n return null;\n }\n const id = typeof s.session_id === \"string\" ? s.session_id : \"\";\n if (!id) return null;\n // Our entry in ~/.claude/settings.json is run by every harness that imports that file\n // \u2014 Devin's `claude` hooks provider is live, not a stub \u2014 and it arrives under the\n // claude-code name. Every Claude Code payload names a transcript and a UUID session;\n // a payload with neither is somebody else's, and must not be parked for up to 125 s\n // waiting on an answer that is not coming. Same test as core's notClaudeCode\n // (claude-code.ts), which the worker applies; repeated here because this file imports\n // nothing but node builtins.\n if (typeof s.transcript_path !== \"string\" && !UUID.test(id)) return null;\n const session = `claude-code:${id}`;\n // The session's own permission mode, in its own words. Every Claude Code hook\n // payload carries it, and it is the only place a mode the person chose at the\n // keyboard can be read from (CONTROL.md \u00A76, The session's mode): the daemon records\n // it, and the in-place lane and a relaunch's narrowing both rest on it. Taken as a\n // shape, not as a value \u2014 the daemon knows the modes it acts on; this file imports\n // nothing but node builtins.\n const mode = modeOf(s);\n if (event === \"Stop\")\n return ask(\n sock,\n { op: \"stop\", session, active: s.stop_hook_active === true, ...(mode ? { mode } : {}) },\n 300,\n ).then((r) => (r?.op === \"block\" ? JSON.stringify({ decision: \"block\", reason: r.reason }) : null));\n // The attention id the adapter puts on attention.needed (claude-code.ts), so the\n // receiver's Allow / Deny names this very prompt.\n const tool =\n typeof s.tool_name === \"string\" && /^[A-Za-z0-9_.:-]{1,120}$/.test(s.tool_name) ? s.tool_name : undefined;\n const turn = typeof s.prompt_id === \"string\" ? s.prompt_id : undefined;\n const attention = `perm-${createHash(\"sha256\")\n .update(`${turn ?? \"\"}|${tool ?? \"\"}|${JSON.stringify(s.tool_input ?? null)}`)\n .digest(\"hex\")\n .slice(0, 16)}`;\n return ask(sock, { op: \"permission\", session, attention, ...(tool ? { tool } : {}) }, 125_000).then((r) =>\n r?.op === \"decision\"\n ? JSON.stringify({\n hookSpecificOutput: {\n hookEventName: \"PermissionRequest\",\n decision:\n r.behavior === \"allow\"\n ? { behavior: \"allow\" }\n : { behavior: \"deny\", message: r.message || \"Denied by the owner (sessionpipe control).\" },\n },\n })\n : null,\n );\n }\n\n /** The timing line; the process exits 0 right after. */\n function finish(spawned: boolean): void {\n const total = Number(process.hrtime.bigint() - t0) / 1e6;\n const ms = workMs ?? total;\n try {\n mkdirSync(state, { recursive: true });\n appendFileSync(\n path.join(state, \"timing.jsonl\"),\n `${JSON.stringify({ at: Date.now(), harness, event, ms: Math.round(ms * 10) / 10, spawned, ...(workMs !== null ? { control_wait_ms: Math.round(total - workMs) } : {}) })}\\n`,\n );\n } catch {}\n }\n function pick(names: string[]): Record<string, string> {\n const out: Record<string, string> = {};\n for (const n of names) if (env[n] !== undefined) out[n] = env[n] as string;\n return out;\n }\n function anySinkAbove(tier: number): boolean {\n try {\n const c = JSON.parse(readFileSync(configFile(), \"utf8\")) as {\n sinks?: { tier?: number; max_tier?: number; paused?: string }[];\n };\n // The tier a sink is sent at (run.ts buildSinks): capped by the receiver's max_tier, and\n // whole (a 0.5 that an older `sink add --tier 0.5` stored is sent as 0).\n return (c.sinks ?? []).some((s) => Math.trunc(Math.min(Number(s.tier), s.max_tier ?? 3)) > tier && !s.paused);\n } catch {\n return false;\n }\n }\n function sessionIdOf(stdin: string): string {\n const m = /\"(?:session_id|sessionId|conversationId)\"\\s*:\\s*\"([^\"]{1,128})\"/.exec(stdin);\n return m?.[1] ?? \"\";\n }\n /** The status line's `rate_limits` as one short line (`5h 23% \u00B7 week 41%`), and as\n * the text a change is told by. Empty when the account has none. */\n function statusLimits(stdin: string): { line: string; sig: string } {\n let rl: unknown;\n try {\n rl = (JSON.parse(stdin) as { rate_limits?: unknown }).rate_limits;\n } catch {}\n if (!rl || typeof rl !== \"object\") return { line: \"\", sig: \"\" };\n const label: Record<string, string> = { five_hour: \"5h\", seven_day: \"week\", spend_limit: \"spend\" };\n const parts = Object.entries(rl as Record<string, { used_percentage?: unknown }>)\n .filter(([, w]) => typeof w?.used_percentage === \"number\")\n .map(([id, w]) => `${label[id] ?? id} ${Math.round(w.used_percentage as number)}%`);\n return parts.length ? { line: parts.join(\" \u00B7 \"), sig: JSON.stringify(rl) } : { line: \"\", sig: \"\" };\n }\n /** A change of limits, at most one a minute per config dir (one account each): the\n * stamp holds the last limits sent, its mtime when. */\n function limitsDue(sig: string): boolean {\n const dir = createHash(\"sha256\")\n .update(env.CLAUDE_CONFIG_DIR ?? \"\")\n .digest(\"hex\")\n .slice(0, 12);\n const stamp = path.join(state, \"beats\", `${harness}-limits-${dir}`);\n try {\n if (readFileSync(stamp, \"utf8\") === sig || Date.now() - statSync(stamp).mtimeMs < 60_000) return false;\n } catch {}\n try {\n mkdirSync(path.dirname(stamp), { recursive: true, mode: 0o700 });\n writeFileSync(stamp, sig, { mode: 0o600 });\n } catch {}\n return true;\n }\n /** One heartbeat per minute per session: the stamp file's mtime is the clock. */\n function beatDue(id: string): boolean {\n const stamp = path.join(state, \"beats\", `${harness}-${id.replace(/[^A-Za-z0-9_-]/g, \"_\")}`);\n try {\n if (Date.now() - statSync(stamp).mtimeMs < 60_000) return false;\n } catch {}\n try {\n mkdirSync(path.dirname(stamp), { recursive: true, mode: 0o700 });\n writeFileSync(stamp, \"\", { mode: 0o600 });\n } catch {}\n return true;\n }\n}\n\n// Run as `node hook.js <harness> <event>`; importing this module runs nothing. The main\n// module is known by its real path: node resolves symlinks for import.meta.url, argv[1]\n// keeps the spelling it was given (/var \u2192 /private/var on macOS).\nif (process.argv[1] && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href)\n hookMain(process.argv.slice(2), process.env, {\n // fd 0 and 1 are the test runner's own (a read of 0 would block it); launcher.test.ts\n // and the bench run these two through the real binary.\n /* v8 ignore next -- see above */\n stdin: () => readFileSync(0),\n /* v8 ignore next -- see above */\n stdout: (text) => writeFileSync(1, text),\n }).then(() => process.exit(0));\n", "// SPDX-License-Identifier: Apache-2.0\n// The daemon's local socket (spec/CONTROL.md \u00A78, \u00A713): how the waiter, the Stop and\n// PermissionRequest hooks, the worker and `sessionpipe ask` talk to the one daemon on\n// this machine. Line-delimited JSON, one request per connection; every request but an\n// ask gets one reply, an ask gets a few in order on the same connection. A Unix socket\n// in the state directory (0600, in a 0700 dir); a per-user named pipe on Windows. Only\n// node: builtins \u2014 the hook bundle imports this.\nimport net from \"node:net\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nexport type LocalRequest =\n /** A waiter parks until a message for its session arrives. `channel`: the waiter is\n * `sessionpipe channel`, which pushes the message into the session rather than handing\n * it to a turn that asked for it (CONTROL.md \u00A78). */\n | { op: \"wait\"; session: string; pid?: number; channel?: boolean }\n /** A Stop hook asks for a queued message (turn mode). `mode` is the session's own\n * permission mode, as its payload reports it (CONTROL.md \u00A76, The session's mode). */\n | { op: \"stop\"; session: string; active: boolean; mode?: string }\n /** A PermissionRequest hook parks until a verified answer, or until it's released. */\n | { op: \"permission\"; session: string; attention: string; tool?: string }\n /** The worker reports a hook event: turn state, attention closure, and the session's\n * own permission mode where its payload named one. */\n | { op: \"event\"; session: string; event: string; transcript?: string; cwd?: string; mode?: string }\n /** `sessionpipe control status`. */\n | { op: \"status\" }\n /** `sessionpipe update` installed a new copy: restart onto it once nothing is in hand. */\n | { op: \"restart\" }\n /** `sessionpipe pool \u2026` while the daemon runs: the daemon holds the pool's engine\n * (pins, credentials, the listener), so a change goes through it. `status` reads;\n * the rest are CONTROL.md \u00A76's actions, plus `import` (reads this machine's own\n * Claude Code logins, which no receiver may ask for). */\n | { op: \"pool\"; action: PoolOp; account?: string; order?: string[]; code?: string }\n /** `sessionpipe ask` (CONTROL.md \u00A713): a session here hands a task to another agent on\n * this machine and gets the answer back on this connection. */\n | AskRequest;\n\nexport type PoolOp =\n | \"status\"\n | \"on\"\n | \"off\"\n | \"enable\"\n | \"disable\"\n | \"remove\"\n | \"order\"\n | \"refresh\"\n | \"login.begin\"\n | \"login.complete\"\n | \"import\";\n\nexport interface AskRequest {\n op: \"ask\";\n /** `<harness>:<id>` of the asking session, when known: the events go on it. */\n from?: string;\n /** The agent to ask. */\n harness: string;\n /** An existing `<harness>:<id>` to continue instead of a new session. */\n session?: string;\n /** 1\u201320 000 characters, not all whitespace. */\n text: string;\n /** Absolute; the caller's folder by default. */\n cwd: string;\n /** Every ancestor ref, outermost first (from env SESSIONPIPE_ASK_CHAIN). */\n chain: string[];\n /** Narrower than the machine's mode, never wider. */\n permission?: \"read\" | \"safe\";\n model?: string;\n pid?: number;\n}\n\nexport type LocalReply =\n | { op: \"message\"; text: string; id: string }\n | { op: \"block\"; reason: string; id: string }\n | { op: \"decision\"; behavior: \"allow\" | \"deny\"; message?: string; id: string }\n | { op: \"none\" }\n /** A newer waiter for the same session took over; this one stops. */\n | { op: \"replaced\" }\n | { op: \"ok\" }\n | { op: \"status\"; status: unknown }\n /** A pool op's answer: the ack it would earn (CONTROL.md \u00A76) and the pool as it now\n * stands (`status`: the fa\u00E7ade's PoolStatus; `detail`: the summary line, or a\n * login.begin's \"<pending id> <URL>\"). */\n | {\n op: \"pool\";\n outcome: \"delivered\" | \"refused\" | \"failed\" | \"unsupported\";\n code?: string;\n detail: string;\n status?: unknown;\n /** `import`: what was added and what was left out (control/pool.ts Imported). */\n imported?: unknown;\n }\n // An ask's replies, in order (askMany): `asked`, any `progress`, then exactly one of\n // `answer`, `refused` and `failed`, after which the daemon closes the connection.\n /** The run began; `session` once it is known. */\n | { op: \"asked\"; ask_id: string; session?: string }\n /** The answer so far, whole, with a rising seq. */\n | { op: \"progress\"; text: string; seq: number }\n | { op: \"answer\"; ask_id: string; session: string; text: string; ms: number }\n /** ask_off \u00B7 harness \u00B7 folder \u00B7 depth \u00B7 loop \u00B7 start_limit \u00B7 bad_fields */\n | { op: \"refused\"; code: string; detail: string }\n | { op: \"failed\"; detail: string };\n\n/** The replies that end an ask. */\nexport type AskEnd = Extract<LocalReply, { op: \"answer\" | \"refused\" | \"failed\" }>;\n\n/** Where the daemon listens. `SESSIONPIPE_SOCKET` overrides (tests). */\nexport function socketPath(state: string, env: NodeJS.ProcessEnv = process.env): string {\n if (env.SESSIONPIPE_SOCKET) return env.SESSIONPIPE_SOCKET;\n if (process.platform === \"win32\") return `\\\\\\\\.\\\\pipe\\\\sessionpipe-control-${os.userInfo().username}`;\n return path.join(state, \"control.sock\");\n}\n\n/** One request, one reply. `timeoutMs` bounds the whole exchange; null on any\n * failure (no daemon, a timeout, a garbled reply) \u2014 callers treat that as \"none\". */\nexport function ask(sock: string, req: LocalRequest, timeoutMs: number): Promise<LocalReply | null> {\n return new Promise((resolve) => {\n let buf = \"\";\n let done = false;\n const s = net.connect(sock);\n const finish = (r: LocalReply | null) => {\n if (done) return;\n done = true;\n clearTimeout(t);\n s.destroy();\n resolve(r);\n };\n const t = setTimeout(() => finish(null), timeoutMs);\n s.on(\"connect\", () => s.write(`${JSON.stringify(req)}\\n`));\n s.on(\"data\", (d) => {\n buf += d.toString(\"utf8\");\n const i = buf.indexOf(\"\\n\");\n if (i < 0) return;\n try {\n finish(JSON.parse(buf.slice(0, i)) as LocalReply);\n } catch {\n finish(null);\n }\n });\n s.on(\"error\", () => finish(null));\n s.on(\"close\", () => finish(null));\n });\n}\n\n/** One request, several replies on the same connection (an ask): `onReply` sees each one\n * in order, the promise settles with the one that ends the exchange. `timeoutMs` bounds\n * the whole exchange; null when it ends without an end \u2014 no daemon, a timeout, a garbled\n * line, a connection that closed mid-run. */\nexport function askMany(\n sock: string,\n req: LocalRequest,\n onReply: (r: LocalReply) => void,\n timeoutMs: number,\n): Promise<AskEnd | null> {\n return new Promise((resolve) => {\n let buf = \"\";\n let done = false;\n const s = net.connect(sock);\n const finish = (r: AskEnd | null) => {\n if (done) return;\n done = true;\n clearTimeout(t);\n s.destroy();\n resolve(r);\n };\n const t = setTimeout(() => finish(null), timeoutMs);\n s.on(\"connect\", () => s.write(`${JSON.stringify(req)}\\n`));\n s.on(\"data\", (d) => {\n buf += d.toString(\"utf8\");\n for (let i = buf.indexOf(\"\\n\"); i >= 0 && !done; i = buf.indexOf(\"\\n\")) {\n const line = buf.slice(0, i);\n buf = buf.slice(i + 1);\n let r: LocalReply;\n try {\n r = JSON.parse(line) as LocalReply;\n } catch {\n finish(null);\n return;\n }\n onReply(r);\n if (r.op === \"answer\" || r.op === \"refused\" || r.op === \"failed\") finish(r);\n }\n });\n s.on(\"error\", () => finish(null));\n s.on(\"close\", () => finish(null));\n });\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["os", "path", "path", "os"]
7
7
  }