approval-box 0.1.21 → 0.1.22
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/THIRD_PARTY_NOTICES.md +1 -1
- package/dist/approval-box-claude-hook.mjs +1 -1
- package/dist/approval-box-cursor-hook.mjs +1 -1
- package/dist/approval-box-receive.mjs +1 -1
- package/dist/chunks/{chunk-OVDAILMZ.mjs → chunk-SN7I52NL.mjs} +233 -139
- package/dist/cli.mjs +13 -4
- package/package.json +2 -2
|
@@ -2,7 +2,7 @@ import { createRequire as __kbCreateRequire } from 'node:module'; const require
|
|
|
2
2
|
import {
|
|
3
3
|
PROFILE,
|
|
4
4
|
runChannelReceiveMain
|
|
5
|
-
} from "./chunks/chunk-
|
|
5
|
+
} from "./chunks/chunk-SN7I52NL.mjs";
|
|
6
6
|
|
|
7
7
|
// src/hooks/receive.ts
|
|
8
8
|
await runChannelReceiveMain(PROFILE);
|
|
@@ -20014,7 +20014,7 @@ function resolveCodexExecutable() {
|
|
|
20014
20014
|
const fallback = path4.join(home2, ".local", "bin", "codex");
|
|
20015
20015
|
if (isUsableAgentExecutableFile(fallback))
|
|
20016
20016
|
return resolveWindowsCodexShim(fallback);
|
|
20017
|
-
const w = spawnSync2(isWin ? "where" : "which", ["codex"], { encoding: "utf8", timeout: 5e3 });
|
|
20017
|
+
const w = spawnSync2(isWin ? "where" : "which", ["codex"], { encoding: "utf8", timeout: 5e3, windowsHide: true });
|
|
20018
20018
|
if (w.status === 0 && (w.stdout ?? "").trim()) {
|
|
20019
20019
|
const found = w.stdout.trim().split(/\r?\n/).filter(Boolean);
|
|
20020
20020
|
const ordered = isWin ? [...found.filter((p) => /\.(?:exe|com|cmd|bat)$/i.test(p)), ...found.filter((p) => !/\.(?:exe|com|cmd|bat)$/i.test(p))] : found;
|
|
@@ -20025,8 +20025,17 @@ function resolveCodexExecutable() {
|
|
|
20025
20025
|
}
|
|
20026
20026
|
return null;
|
|
20027
20027
|
}
|
|
20028
|
+
function codexSpawnEnv(env = process.env, node2 = process.execPath, platform = process.platform) {
|
|
20029
|
+
const windows = platform === "win32";
|
|
20030
|
+
const key = Object.keys(env).find((name) => windows ? name.toLowerCase() === "path" : name === "PATH") ?? "PATH";
|
|
20031
|
+
const delimiter2 = windows ? ";" : ":";
|
|
20032
|
+
const directory2 = (windows ? path4.win32 : path4.posix).dirname(node2);
|
|
20033
|
+
const current = env[key] ?? "";
|
|
20034
|
+
const listed = current.split(delimiter2).some((part) => windows ? part.toLowerCase() === directory2.toLowerCase() : part === directory2);
|
|
20035
|
+
return listed ? env : { ...env, [key]: current ? `${directory2}${delimiter2}${current}` : directory2 };
|
|
20036
|
+
}
|
|
20028
20037
|
function command(executable, args) {
|
|
20029
|
-
const result = spawnSync2(executable, args, { encoding: "utf8", timeout: 15e3 });
|
|
20038
|
+
const result = spawnSync2(executable, args, { encoding: "utf8", timeout: 15e3, env: codexSpawnEnv(), windowsHide: true });
|
|
20030
20039
|
if (result.error || result.status !== 0)
|
|
20031
20040
|
throw new SetupError("codex_steer_setup_failed", `${path4.basename(executable)}\u3092\u5B9F\u884C\u3067\u304D\u307E\u305B\u3093`);
|
|
20032
20041
|
return result.stdout.trim();
|
|
@@ -20039,13 +20048,13 @@ function desktopBundledCodex(app) {
|
|
|
20039
20048
|
return layouts.find((file2) => fs2.existsSync(file2)) ?? null;
|
|
20040
20049
|
}
|
|
20041
20050
|
function findDesktopBinary() {
|
|
20042
|
-
const search = spawnSync2("/usr/bin/mdfind", ["kMDItemCFBundleIdentifier == 'com.openai.codex'"], { encoding: "utf8", timeout: 1e4 });
|
|
20051
|
+
const search = spawnSync2("/usr/bin/mdfind", ["kMDItemCFBundleIdentifier == 'com.openai.codex'"], { encoding: "utf8", timeout: 1e4, windowsHide: true });
|
|
20043
20052
|
const candidates = [.../* @__PURE__ */ new Set(["/Applications/Codex.app", "/Applications/ChatGPT.app", ...search.status === 0 ? search.stdout.trim().split("\n") : []])];
|
|
20044
20053
|
const found = candidates.flatMap((app) => {
|
|
20045
20054
|
const binary2 = app ? desktopBundledCodex(app) : null;
|
|
20046
20055
|
if (!binary2)
|
|
20047
20056
|
return [];
|
|
20048
|
-
const result = spawnSync2("/usr/libexec/PlistBuddy", ["-c", "Print:CFBundleIdentifier", path4.join(app, "Contents", "Info.plist")], { encoding: "utf8", timeout: 5e3 });
|
|
20057
|
+
const result = spawnSync2("/usr/libexec/PlistBuddy", ["-c", "Print:CFBundleIdentifier", path4.join(app, "Contents", "Info.plist")], { encoding: "utf8", timeout: 5e3, windowsHide: true });
|
|
20049
20058
|
return result.status === 0 && result.stdout.trim() === "com.openai.codex" ? [binary2] : [];
|
|
20050
20059
|
});
|
|
20051
20060
|
if (found.length !== 1)
|
|
@@ -20086,7 +20095,7 @@ Join-Path $packages[0].InstallLocation 'app/resources'`, () => new CodexDelivery
|
|
|
20086
20095
|
return value;
|
|
20087
20096
|
}
|
|
20088
20097
|
function assertSteerVersion(executable, subject) {
|
|
20089
|
-
const result = spawnSync2(executable, ["--version"], { encoding: "utf8", windowsHide: true, timeout: 15e3 });
|
|
20098
|
+
const result = spawnSync2(executable, ["--version"], { encoding: "utf8", windowsHide: true, timeout: 15e3, env: codexSpawnEnv() });
|
|
20090
20099
|
if (result.error || result.status !== 0)
|
|
20091
20100
|
throw new SetupError("codex_binary_unavailable", `${subject}\u3092\u8D77\u52D5\u3067\u304D\u307E\u305B\u3093`);
|
|
20092
20101
|
const match = /codex-cli (\d+)\.(\d+)\.(\d+)/.exec(result.stdout ?? "");
|
|
@@ -20139,7 +20148,7 @@ async function currentCodexDesktopBinary(profile, config2, options = {}) {
|
|
|
20139
20148
|
}
|
|
20140
20149
|
|
|
20141
20150
|
// ../../node_modules/aiterm-steer-delivery/dist/codex-receiver.js
|
|
20142
|
-
import { spawn } from "node:child_process";
|
|
20151
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
20143
20152
|
import { createInterface } from "node:readline";
|
|
20144
20153
|
import * as path6 from "node:path";
|
|
20145
20154
|
|
|
@@ -20316,6 +20325,53 @@ function assertCodexHooksReady(profile, response, command2, file2) {
|
|
|
20316
20325
|
}
|
|
20317
20326
|
}
|
|
20318
20327
|
|
|
20328
|
+
// ../../node_modules/aiterm-steer-delivery/dist/codex-wake.js
|
|
20329
|
+
import * as fs4 from "node:fs";
|
|
20330
|
+
import { spawn, spawnSync as spawnSync4 } from "node:child_process";
|
|
20331
|
+
import { fileURLToPath } from "node:url";
|
|
20332
|
+
var TAIL_FIRST_BYTES = 256 * 1024;
|
|
20333
|
+
var TAIL_MAX_BYTES = 16 * 1024 * 1024;
|
|
20334
|
+
var RECORD_KEEP_MS = 3 * 24 * 60 * 60 * 1e3;
|
|
20335
|
+
function codexWakeWatchEnabled(platform = process.platform, env = process.env) {
|
|
20336
|
+
if (env.AITERM_STEER_CODEX_WAKE === "0")
|
|
20337
|
+
return false;
|
|
20338
|
+
return platform === "darwin" || platform === "win32";
|
|
20339
|
+
}
|
|
20340
|
+
var CODEX_WAKE_PAYLOAD_ENV = "AITERM_STEER_CODEX_WAKE_PAYLOAD";
|
|
20341
|
+
function serializeWakeProfile(profile) {
|
|
20342
|
+
const { state_root, config_root, channels: _channels, ...rest } = profile;
|
|
20343
|
+
return { ...rest, dispatch_tools: [...profile.dispatch_tools], state_root: state_root(), config_root: config_root() };
|
|
20344
|
+
}
|
|
20345
|
+
function startCodexWakeWatch(profile, parent, deliveryId, options = {}) {
|
|
20346
|
+
const env = options.env ?? process.env;
|
|
20347
|
+
if (!codexWakeWatchEnabled(options.platform, env))
|
|
20348
|
+
return false;
|
|
20349
|
+
try {
|
|
20350
|
+
const entry = options.entry ?? fileURLToPath(new URL("./codex-wake-main.js", import.meta.url));
|
|
20351
|
+
if (!fs4.existsSync(entry))
|
|
20352
|
+
return false;
|
|
20353
|
+
const payload = JSON.stringify({
|
|
20354
|
+
profile: serializeWakeProfile(profile),
|
|
20355
|
+
parent,
|
|
20356
|
+
delivery_id: deliveryId,
|
|
20357
|
+
...options.delay_ms === void 0 ? {} : { delay_ms: options.delay_ms }
|
|
20358
|
+
});
|
|
20359
|
+
const child = spawn(process.execPath, [entry], { detached: true, stdio: "ignore", windowsHide: true, env: { ...env, [CODEX_WAKE_PAYLOAD_ENV]: payload } });
|
|
20360
|
+
child.on("error", () => {
|
|
20361
|
+
});
|
|
20362
|
+
child.unref();
|
|
20363
|
+
return true;
|
|
20364
|
+
} catch {
|
|
20365
|
+
return false;
|
|
20366
|
+
}
|
|
20367
|
+
}
|
|
20368
|
+
var payloadSchema = external_exports.object({
|
|
20369
|
+
profile: external_exports.object({ state_root: external_exports.string(), config_root: external_exports.string() }).passthrough(),
|
|
20370
|
+
parent: external_exports.object({ thread_id: external_exports.uuid(), codex_home: external_exports.string() }).strict(),
|
|
20371
|
+
delivery_id: external_exports.uuid(),
|
|
20372
|
+
delay_ms: external_exports.number().int().min(0).optional()
|
|
20373
|
+
}).strict();
|
|
20374
|
+
|
|
20319
20375
|
// ../../node_modules/aiterm-steer-delivery/dist/codex-receiver.js
|
|
20320
20376
|
function codexParentFromRequest(clientName, metadata) {
|
|
20321
20377
|
if (clientName !== "codex-mcp-client")
|
|
@@ -20331,9 +20387,9 @@ async function withCodexReceiver(profile, parent, action, runtime = {}) {
|
|
|
20331
20387
|
const executable = runtime.executable ?? (config2?.enabled ? await currentCodexDesktopBinary(profile, config2) : null) ?? resolveCodexExecutable();
|
|
20332
20388
|
if (!executable)
|
|
20333
20389
|
throw new CodexDeliveryError("CODEX_RECEIVER_UNAVAILABLE", "Codex\u306E\u5B9F\u884C\u30D5\u30A1\u30A4\u30EB\u3092\u78BA\u8A8D\u3067\u304D\u307E\u305B\u3093");
|
|
20334
|
-
const child =
|
|
20390
|
+
const child = spawn2(executable, runtime.args ?? ["app-server", "--listen", "stdio://"], {
|
|
20335
20391
|
stdio: ["pipe", "pipe", "ignore"],
|
|
20336
|
-
env: { ...runtime.env ?? process.env, CODEX_HOME: parent.codex_home },
|
|
20392
|
+
env: { ...codexSpawnEnv(runtime.env ?? process.env), CODEX_HOME: parent.codex_home },
|
|
20337
20393
|
windowsHide: true
|
|
20338
20394
|
});
|
|
20339
20395
|
const pending = /* @__PURE__ */ new Map();
|
|
@@ -20410,8 +20466,9 @@ async function submitCodexParentAnswer(profile, parent, deliveryId, text, runtim
|
|
|
20410
20466
|
const hook = root && readCodexHookConfig(profile, root)?.enabled;
|
|
20411
20467
|
if (hook)
|
|
20412
20468
|
registerCodexHookInput(parent.codex_home, parent.thread_id, deliveryId, text, root);
|
|
20469
|
+
let accepted;
|
|
20413
20470
|
try {
|
|
20414
|
-
|
|
20471
|
+
accepted = await withCodexReceiver(profile, parent, async (request) => {
|
|
20415
20472
|
const result = await request("thread/queue/add", {
|
|
20416
20473
|
threadId: parent.thread_id,
|
|
20417
20474
|
input: [{ type: "text", text, text_elements: [] }],
|
|
@@ -20426,10 +20483,13 @@ async function submitCodexParentAnswer(profile, parent, deliveryId, text, runtim
|
|
|
20426
20483
|
if (hook)
|
|
20427
20484
|
finishCodexHookSubmission(parent.codex_home, parent.thread_id, deliveryId, root);
|
|
20428
20485
|
}
|
|
20486
|
+
if (runtime?.wake ?? !runtime)
|
|
20487
|
+
startCodexWakeWatch(profile, parent, deliveryId);
|
|
20488
|
+
return accepted;
|
|
20429
20489
|
}
|
|
20430
20490
|
|
|
20431
20491
|
// ../../node_modules/aiterm-steer-delivery/dist/claude-receiver.js
|
|
20432
|
-
import * as
|
|
20492
|
+
import * as fs5 from "node:fs";
|
|
20433
20493
|
import * as path7 from "node:path";
|
|
20434
20494
|
var requestId = external_exports.string().regex(/^[A-Za-z0-9_-]{1,160}$/);
|
|
20435
20495
|
var invocationSchema = external_exports.object({
|
|
@@ -20454,7 +20514,7 @@ function directory(parent) {
|
|
|
20454
20514
|
function readInvocation(profile, parent) {
|
|
20455
20515
|
let value;
|
|
20456
20516
|
try {
|
|
20457
|
-
value = invocationSchema.parse(JSON.parse(
|
|
20517
|
+
value = invocationSchema.parse(JSON.parse(fs5.readFileSync(path7.join(directory(parent), "request.json"), "utf8")));
|
|
20458
20518
|
} catch {
|
|
20459
20519
|
throw new ClaudeDeliveryError("CLAUDE_PARENT_HOOK_UNAVAILABLE", `\u89AA\u306Ehook\u8A18\u9332\u304C\u3042\u308A\u307E\u305B\u3093\u3002${profile.setup_command}\u3092\u5B9F\u884C\u3057\u3001Claude Code\u306Ehook\u3092\u6709\u52B9\u306B\u3057\u3066\u304F\u3060\u3055\u3044`);
|
|
20460
20520
|
}
|
|
@@ -20464,7 +20524,7 @@ function readInvocation(profile, parent) {
|
|
|
20464
20524
|
return value;
|
|
20465
20525
|
}
|
|
20466
20526
|
function assertOpen(parent) {
|
|
20467
|
-
if (
|
|
20527
|
+
if (fs5.existsSync(path7.join(directory(parent), "closed.json"))) {
|
|
20468
20528
|
throw new ClaudeDeliveryError("CLAUDE_PARENT_SESSION_CLOSED", "\u4F9D\u983C\u5143\u306E\u4F1A\u8A71\u306F\u7D42\u4E86\u3057\u307E\u3057\u305F\u3002\u56DE\u7B54\u3092\u5225\u306E\u4F1A\u8A71\u3078\u9001\u3063\u3066\u3044\u307E\u305B\u3093");
|
|
20469
20529
|
}
|
|
20470
20530
|
}
|
|
@@ -20475,7 +20535,7 @@ function prepareClaudeHookRequest(input2, root) {
|
|
|
20475
20535
|
if (!owner)
|
|
20476
20536
|
throw new ClaudeDeliveryError("CLAUDE_PARENT_PROCESS_UNAVAILABLE", "hook\u3092\u8D77\u52D5\u3057\u305F\u89AAprocess\u3092\u78BA\u8A8D\u3067\u304D\u307E\u305B\u3093");
|
|
20477
20537
|
const dir = path7.join(root, event.tool_use_id);
|
|
20478
|
-
|
|
20538
|
+
fs5.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
20479
20539
|
writeJson0600(path7.join(dir, "request.json"), {
|
|
20480
20540
|
request_id: event.tool_use_id,
|
|
20481
20541
|
session_id: event.session_id,
|
|
@@ -20493,7 +20553,7 @@ var REQUEST_FILES = /* @__PURE__ */ new Set(["request.json", "delivery.json", "a
|
|
|
20493
20553
|
function sweepClaudeHookRequests(root, rows, now = Date.now()) {
|
|
20494
20554
|
let entries;
|
|
20495
20555
|
try {
|
|
20496
|
-
entries =
|
|
20556
|
+
entries = fs5.readdirSync(root, { withFileTypes: true });
|
|
20497
20557
|
} catch {
|
|
20498
20558
|
return 0;
|
|
20499
20559
|
}
|
|
@@ -20503,23 +20563,23 @@ function sweepClaudeHookRequests(root, rows, now = Date.now()) {
|
|
|
20503
20563
|
continue;
|
|
20504
20564
|
const dir = path7.join(root, entry.name);
|
|
20505
20565
|
try {
|
|
20506
|
-
if (now -
|
|
20566
|
+
if (now - fs5.statSync(dir).mtimeMs < STALE_REQUEST_MS)
|
|
20507
20567
|
continue;
|
|
20508
|
-
const names =
|
|
20568
|
+
const names = fs5.readdirSync(dir);
|
|
20509
20569
|
if (!names.every((name) => REQUEST_FILES.has(name) || name.endsWith(".tmp")))
|
|
20510
20570
|
continue;
|
|
20511
|
-
if (names.some((name) => now -
|
|
20571
|
+
if (names.some((name) => now - fs5.statSync(path7.join(dir, name)).mtimeMs < STALE_REQUEST_MS))
|
|
20512
20572
|
continue;
|
|
20513
20573
|
if (names.includes("delivery.json") && !names.includes("emitted.json")) {
|
|
20514
20574
|
let invocation;
|
|
20515
20575
|
try {
|
|
20516
|
-
invocation = invocationSchema.parse(JSON.parse(
|
|
20576
|
+
invocation = invocationSchema.parse(JSON.parse(fs5.readFileSync(path7.join(dir, "request.json"), "utf8")));
|
|
20517
20577
|
} catch {
|
|
20518
20578
|
}
|
|
20519
20579
|
if (invocation && rows.find((row) => row.pid === invocation.parent_pid)?.started_identity === invocation.parent_started_identity)
|
|
20520
20580
|
continue;
|
|
20521
20581
|
}
|
|
20522
|
-
|
|
20582
|
+
fs5.rmSync(dir, { recursive: true, force: true });
|
|
20523
20583
|
removed += 1;
|
|
20524
20584
|
} catch {
|
|
20525
20585
|
}
|
|
@@ -20534,7 +20594,7 @@ function claudeParentFromRequest(profile, clientName, metadata, root) {
|
|
|
20534
20594
|
throw new ClaudeDeliveryError("CLAUDE_PARENT_ID_UNAVAILABLE", "MCP\u8981\u6C42\u306BtoolUseId\u304C\u3042\u308A\u307E\u305B\u3093\u3002\u5BFE\u5FDC\u3059\u308BClaude Code\u3078\u66F4\u65B0\u3057\u3066\u304F\u3060\u3055\u3044");
|
|
20535
20595
|
let invocation;
|
|
20536
20596
|
try {
|
|
20537
|
-
invocation = invocationSchema.parse(JSON.parse(
|
|
20597
|
+
invocation = invocationSchema.parse(JSON.parse(fs5.readFileSync(path7.join(root, parsed.data, "request.json"), "utf8")));
|
|
20538
20598
|
} catch {
|
|
20539
20599
|
throw new ClaudeDeliveryError("CLAUDE_PARENT_HOOK_UNAVAILABLE", `\u89AA\u306EPreToolUse hook\u3092\u78BA\u8A8D\u3067\u304D\u307E\u305B\u3093\u3002${profile.setup_command}\u3092\u5B9F\u884C\u3057\u3001hook\u3092\u6709\u52B9\u306B\u3057\u3066\u304F\u3060\u3055\u3044`);
|
|
20540
20600
|
}
|
|
@@ -20550,15 +20610,15 @@ function verifyClaudeParent(profile, parent) {
|
|
|
20550
20610
|
}
|
|
20551
20611
|
function closeClaudeParentSession(input2, root) {
|
|
20552
20612
|
const { session_id } = external_exports.object({ session_id: external_exports.uuid() }).parse(input2);
|
|
20553
|
-
if (!
|
|
20613
|
+
if (!fs5.existsSync(root))
|
|
20554
20614
|
return;
|
|
20555
20615
|
let failure2;
|
|
20556
|
-
for (const entry of
|
|
20616
|
+
for (const entry of fs5.readdirSync(root, { withFileTypes: true })) {
|
|
20557
20617
|
if (!entry.isDirectory())
|
|
20558
20618
|
continue;
|
|
20559
20619
|
let invocation;
|
|
20560
20620
|
try {
|
|
20561
|
-
invocation = invocationSchema.parse(JSON.parse(
|
|
20621
|
+
invocation = invocationSchema.parse(JSON.parse(fs5.readFileSync(path7.join(root, entry.name, "request.json"), "utf8")));
|
|
20562
20622
|
} catch {
|
|
20563
20623
|
continue;
|
|
20564
20624
|
}
|
|
@@ -20585,24 +20645,24 @@ async function runClaudeResultHook(profile, input2, emit, root) {
|
|
|
20585
20645
|
const invocation = readInvocation(profile, parent);
|
|
20586
20646
|
const dir = directory(parent);
|
|
20587
20647
|
const binding = path7.join(dir, "delivery.json");
|
|
20588
|
-
if (!
|
|
20589
|
-
|
|
20648
|
+
if (!fs5.existsSync(binding)) {
|
|
20649
|
+
fs5.rmSync(dir, { recursive: true });
|
|
20590
20650
|
return 0;
|
|
20591
20651
|
}
|
|
20592
|
-
const deliveryId = external_exports.uuid().parse(JSON.parse(
|
|
20652
|
+
const deliveryId = external_exports.uuid().parse(JSON.parse(fs5.readFileSync(binding, "utf8")).delivery_id);
|
|
20593
20653
|
const identity = processIdentity(process.pid);
|
|
20594
20654
|
if (!identity)
|
|
20595
20655
|
throw new ClaudeDeliveryError("CLAUDE_PARENT_HOOK_UNAVAILABLE", "\u53D7\u4FE1hook\u306Eprocess\u3092\u78BA\u8A8D\u3067\u304D\u307E\u305B\u3093");
|
|
20596
20656
|
writeJson0600(path7.join(dir, "hook.json"), { pid: process.pid, started_identity: identity });
|
|
20597
20657
|
try {
|
|
20598
20658
|
const answer = await waitForFileState(dir, () => {
|
|
20599
|
-
if (
|
|
20659
|
+
if (fs5.existsSync(path7.join(dir, "closed.json")))
|
|
20600
20660
|
return null;
|
|
20601
20661
|
assertParentAlive(invocation);
|
|
20602
20662
|
const file2 = path7.join(dir, "answer.json");
|
|
20603
|
-
if (!
|
|
20663
|
+
if (!fs5.existsSync(file2))
|
|
20604
20664
|
return void 0;
|
|
20605
|
-
const value = external_exports.object({ delivery_id: external_exports.uuid(), text: external_exports.string() }).strict().parse(JSON.parse(
|
|
20665
|
+
const value = external_exports.object({ delivery_id: external_exports.uuid(), text: external_exports.string() }).strict().parse(JSON.parse(fs5.readFileSync(file2, "utf8")));
|
|
20606
20666
|
if (value.delivery_id !== deliveryId)
|
|
20607
20667
|
throw new ClaudeDeliveryError("CLAUDE_PARENT_DELIVERY_MISMATCH", "\u4FDD\u5B58\u3055\u308C\u305F\u56DE\u7B54\u306E\u914D\u9001ID\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093");
|
|
20608
20668
|
return value;
|
|
@@ -20615,18 +20675,18 @@ async function runClaudeResultHook(profile, input2, emit, root) {
|
|
|
20615
20675
|
writeJson0600(path7.join(dir, "emitted.json"), { delivery_id: deliveryId });
|
|
20616
20676
|
return 2;
|
|
20617
20677
|
} catch (error62) {
|
|
20618
|
-
writeJson0600(path7.join(dir, "failed.json"), { outcome_unknown:
|
|
20678
|
+
writeJson0600(path7.join(dir, "failed.json"), { outcome_unknown: fs5.existsSync(path7.join(dir, "sending.json")) });
|
|
20619
20679
|
throw error62;
|
|
20620
20680
|
}
|
|
20621
20681
|
}
|
|
20622
20682
|
|
|
20623
20683
|
// ../../node_modules/aiterm-steer-delivery/dist/cursor-receiver.js
|
|
20624
|
-
import * as
|
|
20684
|
+
import * as fs6 from "node:fs";
|
|
20625
20685
|
import { homedir as homedir3 } from "node:os";
|
|
20626
20686
|
import * as path8 from "node:path";
|
|
20627
20687
|
|
|
20628
20688
|
// ../../node_modules/aiterm-steer-delivery/dist/hook-setup.js
|
|
20629
|
-
import { copyFileSync, existsSync as
|
|
20689
|
+
import { copyFileSync, existsSync as existsSync6, lstatSync, mkdirSync as mkdirSync4, readFileSync as readFileSync5, realpathSync as realpathSync3, renameSync as renameSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
20630
20690
|
import { dirname as dirname3 } from "node:path";
|
|
20631
20691
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
20632
20692
|
import { isDeepStrictEqual } from "node:util";
|
|
@@ -20652,16 +20712,22 @@ function claudeParentHookEntries(profile, hook, platform = process.platform) {
|
|
|
20652
20712
|
PreToolUse: [{ matcher, hooks: [{ ...command2, timeout: 15 }] }],
|
|
20653
20713
|
PostToolUse: [{ matcher, hooks: [{ ...command2, asyncRewake: true, timeout: 86400 }] }],
|
|
20654
20714
|
// 長く続く受信(channel)では、turnが終わるたびに待機を張り直す。
|
|
20655
|
-
|
|
20715
|
+
// 会話の始まり(SessionStart)でも張る。Claude Codeが起動し直して同じ会話を再開した時、番が1つも回らないうちから、
|
|
20716
|
+
// 前のprocessが開いたchannelの本文を受け取れる。開いているchannelの無い会話では、何もせず終わる。
|
|
20717
|
+
...profile.channels ? {
|
|
20718
|
+
Stop: [{ hooks: [{ ...command2, asyncRewake: true, timeout: 86400 }] }],
|
|
20719
|
+
SessionStart: [{ hooks: [{ ...command2, asyncRewake: true, timeout: 86400 }] }]
|
|
20720
|
+
} : {},
|
|
20656
20721
|
SessionEnd: [{ hooks: [{ ...command2, timeout: 15 }] }]
|
|
20657
20722
|
};
|
|
20658
20723
|
}
|
|
20724
|
+
var OPTIONAL_CLAUDE_EVENTS = /* @__PURE__ */ new Set(["SessionStart"]);
|
|
20659
20725
|
function mergeClaudeParentHooks(profile, file2, hook) {
|
|
20660
|
-
const target2 =
|
|
20726
|
+
const target2 = existsSync6(file2) ? realpathSync3(file2) : file2;
|
|
20661
20727
|
let current = {};
|
|
20662
|
-
if (
|
|
20728
|
+
if (existsSync6(target2)) {
|
|
20663
20729
|
try {
|
|
20664
|
-
current = JSON.parse(
|
|
20730
|
+
current = JSON.parse(readFileSync5(target2, "utf8"));
|
|
20665
20731
|
} catch {
|
|
20666
20732
|
throw new SetupError("config_invalid", "Claude\u306Ehook\u8A2D\u5B9AJSON\u3092\u8AAD\u3081\u307E\u305B\u3093");
|
|
20667
20733
|
}
|
|
@@ -20694,14 +20760,14 @@ function mergeClaudeParentHooks(profile, file2, hook) {
|
|
|
20694
20760
|
try {
|
|
20695
20761
|
writeFileSync3(temporary, `${JSON.stringify(next, null, 2)}
|
|
20696
20762
|
`, { mode: 384, flag: "wx" });
|
|
20697
|
-
if (
|
|
20763
|
+
if (existsSync6(target2))
|
|
20698
20764
|
copyFileSync(target2, `${target2}${profile.backup_suffix}`);
|
|
20699
20765
|
renameSync2(temporary, target2);
|
|
20700
20766
|
} finally {
|
|
20701
|
-
if (
|
|
20767
|
+
if (existsSync6(temporary))
|
|
20702
20768
|
unlinkSync2(temporary);
|
|
20703
20769
|
}
|
|
20704
|
-
if (!isDeepStrictEqual(JSON.parse(
|
|
20770
|
+
if (!isDeepStrictEqual(JSON.parse(readFileSync5(target2, "utf8")), next)) {
|
|
20705
20771
|
throw new SetupError("config_readback_failed", "Claude\u306Ehook\u767B\u9332\u306E\u8AAD\u623B\u3057\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093");
|
|
20706
20772
|
}
|
|
20707
20773
|
return "configured";
|
|
@@ -20720,20 +20786,20 @@ function ownedClaudeParentHooks(profile, document, event) {
|
|
|
20720
20786
|
return hooks.flatMap((group) => record2(group) && Array.isArray(group.hooks) ? group.hooks : []).filter((entry) => isClaudeParentHook(profile, entry));
|
|
20721
20787
|
}
|
|
20722
20788
|
function claudeParentHooksRegistered(profile, document) {
|
|
20723
|
-
return Object.keys(claudeParentHookEntries(profile, { command: "", script: profile.hooks.claude })).every((event) => ownedClaudeParentHooks(profile, document, event).length > 0);
|
|
20789
|
+
return Object.keys(claudeParentHookEntries(profile, { command: "", script: profile.hooks.claude })).filter((event) => !OPTIONAL_CLAUDE_EVENTS.has(event)).every((event) => ownedClaudeParentHooks(profile, document, event).length > 0);
|
|
20724
20790
|
}
|
|
20725
20791
|
function removeClaudeParentHooks(profile, file2) {
|
|
20726
|
-
if (!
|
|
20792
|
+
if (!existsSync6(file2))
|
|
20727
20793
|
return "unchanged";
|
|
20728
20794
|
const target2 = realpathSync3(file2);
|
|
20729
|
-
const current = JSON.parse(
|
|
20795
|
+
const current = JSON.parse(readFileSync5(target2, "utf8"));
|
|
20730
20796
|
if (!record2(current) || current.hooks !== void 0 && !record2(current.hooks)) {
|
|
20731
20797
|
throw new SetupError("config_invalid", "Claude\u306Ehook\u8A2D\u5B9A\u3092\u8AAD\u3081\u307E\u305B\u3093");
|
|
20732
20798
|
}
|
|
20733
20799
|
if (current.hooks === void 0)
|
|
20734
20800
|
return "unchanged";
|
|
20735
20801
|
const hooks = { ...current.hooks };
|
|
20736
|
-
for (const event of ["PreToolUse", "PostToolUse", "Stop", "SessionEnd"]) {
|
|
20802
|
+
for (const event of ["PreToolUse", "PostToolUse", "Stop", "SessionStart", "SessionEnd"]) {
|
|
20737
20803
|
if (hooks[event] === void 0)
|
|
20738
20804
|
continue;
|
|
20739
20805
|
if (!Array.isArray(hooks[event]))
|
|
@@ -20754,10 +20820,10 @@ function removeClaudeParentHooks(profile, file2) {
|
|
|
20754
20820
|
copyFileSync(target2, `${target2}${profile.backup_suffix}`);
|
|
20755
20821
|
renameSync2(temporary, target2);
|
|
20756
20822
|
} finally {
|
|
20757
|
-
if (
|
|
20823
|
+
if (existsSync6(temporary))
|
|
20758
20824
|
unlinkSync2(temporary);
|
|
20759
20825
|
}
|
|
20760
|
-
if (!isDeepStrictEqual(JSON.parse(
|
|
20826
|
+
if (!isDeepStrictEqual(JSON.parse(readFileSync5(target2, "utf8")), next))
|
|
20761
20827
|
throw new SetupError("config_readback_failed", "Claude hook\u89E3\u9664\u306E\u8AAD\u623B\u3057\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093");
|
|
20762
20828
|
return "removed";
|
|
20763
20829
|
}
|
|
@@ -20773,11 +20839,11 @@ function ownsCursorParentHook(profile, hook) {
|
|
|
20773
20839
|
return record2(hook) && typeof hook.command === "string" && commandNamesFile(hook.command, profile.hooks.cursor);
|
|
20774
20840
|
}
|
|
20775
20841
|
function mergeCursorParentHooks(profile, file2, hook) {
|
|
20776
|
-
const target2 =
|
|
20842
|
+
const target2 = existsSync6(file2) ? realpathSync3(file2) : file2;
|
|
20777
20843
|
let current = { version: 1, hooks: {} };
|
|
20778
|
-
if (
|
|
20844
|
+
if (existsSync6(target2)) {
|
|
20779
20845
|
try {
|
|
20780
|
-
current = JSON.parse(
|
|
20846
|
+
current = JSON.parse(readFileSync5(target2, "utf8"));
|
|
20781
20847
|
} catch {
|
|
20782
20848
|
throw new SetupError("config_invalid", "Cursor\u306Ehook\u8A2D\u5B9AJSON\u3092\u8AAD\u3081\u307E\u305B\u3093");
|
|
20783
20849
|
}
|
|
@@ -20814,23 +20880,23 @@ function mergeCursorParentHooks(profile, file2, hook) {
|
|
|
20814
20880
|
try {
|
|
20815
20881
|
writeFileSync3(temporary, `${JSON.stringify(next, null, 2)}
|
|
20816
20882
|
`, { mode: 384, flag: "wx" });
|
|
20817
|
-
if (
|
|
20883
|
+
if (existsSync6(target2))
|
|
20818
20884
|
copyFileSync(target2, `${target2}${profile.backup_suffix}`);
|
|
20819
20885
|
renameSync2(temporary, target2);
|
|
20820
20886
|
} finally {
|
|
20821
|
-
if (
|
|
20887
|
+
if (existsSync6(temporary))
|
|
20822
20888
|
unlinkSync2(temporary);
|
|
20823
20889
|
}
|
|
20824
|
-
if (!isDeepStrictEqual(JSON.parse(
|
|
20890
|
+
if (!isDeepStrictEqual(JSON.parse(readFileSync5(target2, "utf8")), next)) {
|
|
20825
20891
|
throw new SetupError("config_readback_failed", "Cursor\u306Ehook\u767B\u9332\u306E\u8AAD\u623B\u3057\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093");
|
|
20826
20892
|
}
|
|
20827
20893
|
return "configured";
|
|
20828
20894
|
}
|
|
20829
20895
|
function removeCursorParentHooks(profile, file2) {
|
|
20830
|
-
if (!
|
|
20896
|
+
if (!existsSync6(file2))
|
|
20831
20897
|
return "unchanged";
|
|
20832
20898
|
const target2 = realpathSync3(file2);
|
|
20833
|
-
const current = JSON.parse(
|
|
20899
|
+
const current = JSON.parse(readFileSync5(target2, "utf8"));
|
|
20834
20900
|
if (!record2(current) || current.hooks !== void 0 && !record2(current.hooks)) {
|
|
20835
20901
|
throw new SetupError("config_invalid", "Cursor\u306Ehook\u8A2D\u5B9A\u3092\u8AAD\u3081\u307E\u305B\u3093");
|
|
20836
20902
|
}
|
|
@@ -20858,10 +20924,10 @@ function removeCursorParentHooks(profile, file2) {
|
|
|
20858
20924
|
copyFileSync(target2, `${target2}${profile.backup_suffix}`);
|
|
20859
20925
|
renameSync2(temporary, target2);
|
|
20860
20926
|
} finally {
|
|
20861
|
-
if (
|
|
20927
|
+
if (existsSync6(temporary))
|
|
20862
20928
|
unlinkSync2(temporary);
|
|
20863
20929
|
}
|
|
20864
|
-
if (!isDeepStrictEqual(JSON.parse(
|
|
20930
|
+
if (!isDeepStrictEqual(JSON.parse(readFileSync5(target2, "utf8")), next)) {
|
|
20865
20931
|
throw new SetupError("config_readback_failed", "Cursor hook\u89E3\u9664\u306E\u8AAD\u623B\u3057\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093");
|
|
20866
20932
|
}
|
|
20867
20933
|
return "removed";
|
|
@@ -20902,7 +20968,7 @@ function verifyCursorParent(profile, parent, hooksFile = cursorHooksFile()) {
|
|
|
20902
20968
|
cursorParentSchema.parse(parent);
|
|
20903
20969
|
let document;
|
|
20904
20970
|
try {
|
|
20905
|
-
document = JSON.parse(
|
|
20971
|
+
document = JSON.parse(fs6.readFileSync(hooksFile, "utf8"));
|
|
20906
20972
|
} catch {
|
|
20907
20973
|
throw new CursorDeliveryError("CURSOR_PARENT_HOOK_UNAVAILABLE", `Cursor\u306Ehook\u304C\u767B\u9332\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002${profile.setup_command}\u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044`);
|
|
20908
20974
|
}
|
|
@@ -20968,7 +21034,7 @@ function toolBaseName(profile, name) {
|
|
|
20968
21034
|
}
|
|
20969
21035
|
function claim2(dir, channel) {
|
|
20970
21036
|
try {
|
|
20971
|
-
|
|
21037
|
+
fs6.writeFileSync(path8.join(dir, "claim.json"), JSON.stringify({ channel, at: (/* @__PURE__ */ new Date()).toISOString() }), { flag: "wx", mode: 384 });
|
|
20972
21038
|
return true;
|
|
20973
21039
|
} catch (error62) {
|
|
20974
21040
|
if (error62.code === "EEXIST")
|
|
@@ -20978,30 +21044,30 @@ function claim2(dir, channel) {
|
|
|
20978
21044
|
}
|
|
20979
21045
|
function bind(hookRoot, deliveryId, conv) {
|
|
20980
21046
|
const dir = path8.join(hookRoot, "deliveries", deliveryId);
|
|
20981
|
-
if (!
|
|
21047
|
+
if (!fs6.existsSync(dir))
|
|
20982
21048
|
return;
|
|
20983
21049
|
const bindFile = path8.join(dir, "bind.json");
|
|
20984
|
-
if (!
|
|
21050
|
+
if (!fs6.existsSync(bindFile)) {
|
|
20985
21051
|
writeJson0600(bindFile, { conversation_id: conv, created_at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
20986
21052
|
}
|
|
20987
21053
|
const indexDir = path8.join(hookRoot, "conversations", conv);
|
|
20988
|
-
|
|
21054
|
+
fs6.mkdirSync(indexDir, { recursive: true, mode: 448 });
|
|
20989
21055
|
const index = path8.join(indexDir, deliveryId);
|
|
20990
|
-
if (!
|
|
20991
|
-
|
|
21056
|
+
if (!fs6.existsSync(index))
|
|
21057
|
+
fs6.writeFileSync(index, "", { mode: 384 });
|
|
20992
21058
|
}
|
|
20993
21059
|
function inject(hookRoot, conv) {
|
|
20994
21060
|
const indexDir = path8.join(hookRoot, "conversations", conv);
|
|
20995
|
-
if (!
|
|
21061
|
+
if (!fs6.existsSync(indexDir))
|
|
20996
21062
|
return [];
|
|
20997
|
-
const pending =
|
|
21063
|
+
const pending = fs6.readdirSync(indexDir).flatMap((deliveryId) => {
|
|
20998
21064
|
const dir = path8.join(hookRoot, "deliveries", deliveryId);
|
|
20999
21065
|
const answerFile = path8.join(dir, "answer.json");
|
|
21000
21066
|
const bindFile = path8.join(dir, "bind.json");
|
|
21001
|
-
if (!
|
|
21067
|
+
if (!fs6.existsSync(answerFile) || !fs6.existsSync(bindFile))
|
|
21002
21068
|
return [];
|
|
21003
|
-
const answer = external_exports.object({ delivery_id: external_exports.string(), text: external_exports.string() }).parse(JSON.parse(
|
|
21004
|
-
const bound = external_exports.object({ conversation_id: external_exports.string(), created_at: external_exports.string() }).parse(JSON.parse(
|
|
21069
|
+
const answer = external_exports.object({ delivery_id: external_exports.string(), text: external_exports.string() }).parse(JSON.parse(fs6.readFileSync(answerFile, "utf8")));
|
|
21070
|
+
const bound = external_exports.object({ conversation_id: external_exports.string(), created_at: external_exports.string() }).parse(JSON.parse(fs6.readFileSync(bindFile, "utf8")));
|
|
21005
21071
|
if (answer.delivery_id !== deliveryId || bound.conversation_id !== conv)
|
|
21006
21072
|
return [];
|
|
21007
21073
|
return [{ deliveryId, dir, created_at: bound.created_at, text: answer.text }];
|
|
@@ -21010,12 +21076,12 @@ function inject(hookRoot, conv) {
|
|
|
21010
21076
|
for (const item of pending) {
|
|
21011
21077
|
const index = path8.join(indexDir, item.deliveryId);
|
|
21012
21078
|
if (!claim2(item.dir, "hook")) {
|
|
21013
|
-
if (
|
|
21014
|
-
|
|
21079
|
+
if (fs6.existsSync(path8.join(item.dir, "claim.json")))
|
|
21080
|
+
fs6.rmSync(index, { force: true });
|
|
21015
21081
|
continue;
|
|
21016
21082
|
}
|
|
21017
21083
|
texts.push(item.text);
|
|
21018
|
-
|
|
21084
|
+
fs6.rmSync(index, { force: true });
|
|
21019
21085
|
}
|
|
21020
21086
|
return texts;
|
|
21021
21087
|
}
|
|
@@ -21059,7 +21125,7 @@ function waitProcessCommandLine(wait, platform = process.platform) {
|
|
|
21059
21125
|
}
|
|
21060
21126
|
|
|
21061
21127
|
// ../../node_modules/aiterm-steer-delivery/dist/channel.js
|
|
21062
|
-
import * as
|
|
21128
|
+
import * as fs7 from "node:fs";
|
|
21063
21129
|
import * as path9 from "node:path";
|
|
21064
21130
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
21065
21131
|
import { setTimeout as delay } from "node:timers/promises";
|
|
@@ -21084,7 +21150,7 @@ function processIdentity2(pid) {
|
|
|
21084
21150
|
}
|
|
21085
21151
|
function mkdirs(...dirs) {
|
|
21086
21152
|
for (const dir of dirs)
|
|
21087
|
-
|
|
21153
|
+
fs7.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
21088
21154
|
}
|
|
21089
21155
|
function openChannel(profile, parent) {
|
|
21090
21156
|
const channel_id = randomUUID3();
|
|
@@ -21098,7 +21164,7 @@ function openChannel(profile, parent) {
|
|
|
21098
21164
|
else if (parent.kind === "cursor")
|
|
21099
21165
|
channel = { schema: "aiterm-steer.channel.v1", channel_id, kind: "cursor", created_at };
|
|
21100
21166
|
else {
|
|
21101
|
-
const request = external_exports.object({ session_id: external_exports.uuid(), parent_pid: external_exports.number().int().positive(), parent_started_identity: external_exports.string() }).loose().parse(JSON.parse(
|
|
21167
|
+
const request = external_exports.object({ session_id: external_exports.uuid(), parent_pid: external_exports.number().int().positive(), parent_started_identity: external_exports.string() }).loose().parse(JSON.parse(fs7.readFileSync(path9.join(parent.hook_root, parent.request_id, "request.json"), "utf8")));
|
|
21102
21168
|
if (request.session_id !== parent.session_id)
|
|
21103
21169
|
throw new ChannelError("CHANNEL_PARENT_SESSION_MISMATCH", "\u8981\u6C42\u3068hook\u306E\u4F1A\u8A71\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093");
|
|
21104
21170
|
channel = {
|
|
@@ -21114,14 +21180,14 @@ function openChannel(profile, parent) {
|
|
|
21114
21180
|
if (channel.claude) {
|
|
21115
21181
|
const index = path9.join(channelRoot(profile), "claude-sessions", channel.claude.session_id);
|
|
21116
21182
|
mkdirs(index);
|
|
21117
|
-
|
|
21183
|
+
fs7.writeFileSync(path9.join(index, channel_id), "", { mode: 384 });
|
|
21118
21184
|
}
|
|
21119
21185
|
return channel;
|
|
21120
21186
|
}
|
|
21121
21187
|
function readChannel(profile, channelId) {
|
|
21122
21188
|
const file2 = path9.join(channelDir(profile, channelId), "channel.json");
|
|
21123
21189
|
try {
|
|
21124
|
-
return channelSchema.parse(JSON.parse(
|
|
21190
|
+
return channelSchema.parse(JSON.parse(fs7.readFileSync(file2, "utf8")));
|
|
21125
21191
|
} catch (error62) {
|
|
21126
21192
|
if (error62.code === "ENOENT")
|
|
21127
21193
|
throw new ChannelError("CHANNEL_UNKNOWN", "channel\u306E\u8A18\u9332\u304C\u3042\u308A\u307E\u305B\u3093");
|
|
@@ -21129,11 +21195,11 @@ function readChannel(profile, channelId) {
|
|
|
21129
21195
|
}
|
|
21130
21196
|
}
|
|
21131
21197
|
function channelClosed(profile, channelId) {
|
|
21132
|
-
return
|
|
21198
|
+
return fs7.existsSync(path9.join(channelDir(profile, channelId), "closed.json"));
|
|
21133
21199
|
}
|
|
21134
21200
|
function closeChannel(profile, channelId, reason = "closed") {
|
|
21135
21201
|
const dir = channelDir(profile, channelId);
|
|
21136
|
-
if (!
|
|
21202
|
+
if (!fs7.existsSync(dir))
|
|
21137
21203
|
return;
|
|
21138
21204
|
writeJson0600(path9.join(dir, "closed.json"), { reason, at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
21139
21205
|
}
|
|
@@ -21147,22 +21213,25 @@ async function sendToChannel(profile, channelId, deliveryId, text, runtime) {
|
|
|
21147
21213
|
return { state: "submitted", queued_submission_id: result.queued_submission_id };
|
|
21148
21214
|
}
|
|
21149
21215
|
const dir = channelDir(profile, channelId);
|
|
21216
|
+
if (fs7.readdirSync(path9.join(dir, "inbox")).some((entry) => entry.endsWith(`-${deliveryId}.json`))) {
|
|
21217
|
+
throw new ChannelError("CHANNEL_DELIVERY_DUPLICATE", "\u540C\u3058\u914D\u9001ID\u306E\u672C\u6587\u304C\u3059\u3067\u306B\u53D7\u4FE1\u7BB1\u306B\u3042\u308A\u307E\u3059");
|
|
21218
|
+
}
|
|
21150
21219
|
for (const sub of ["claims", "emitted"]) {
|
|
21151
|
-
if (
|
|
21220
|
+
if (fs7.existsSync(path9.join(dir, sub, `${deliveryId}.json`)))
|
|
21152
21221
|
throw new ChannelError("CHANNEL_DELIVERY_DUPLICATE", "\u540C\u3058\u914D\u9001ID\u306E\u672C\u6587\u306F\u3059\u3067\u306B\u53D7\u3051\u53D6\u3089\u308C\u3066\u3044\u307E\u3059");
|
|
21153
21222
|
}
|
|
21154
21223
|
const name = `${Date.now().toString().padStart(15, "0")}-${(sendSequence++).toString().padStart(9, "0")}-${deliveryId}.json`;
|
|
21155
21224
|
const item = { delivery_id: deliveryId, text, at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
21156
21225
|
const temporary = path9.join(dir, `.${deliveryId}.${randomUUID3()}.tmp`);
|
|
21157
|
-
|
|
21226
|
+
fs7.writeFileSync(temporary, JSON.stringify(item) + "\n", { flag: "wx", mode: 384 });
|
|
21158
21227
|
try {
|
|
21159
|
-
|
|
21228
|
+
fs7.linkSync(temporary, path9.join(dir, "inbox", name));
|
|
21160
21229
|
} catch (error62) {
|
|
21161
21230
|
if (error62.code === "EEXIST")
|
|
21162
21231
|
throw new ChannelError("CHANNEL_DELIVERY_DUPLICATE", "\u540C\u3058\u914D\u9001ID\u306E\u672C\u6587\u304C\u3059\u3067\u306B\u53D7\u4FE1\u7BB1\u306B\u3042\u308A\u307E\u3059");
|
|
21163
21232
|
throw error62;
|
|
21164
21233
|
} finally {
|
|
21165
|
-
|
|
21234
|
+
fs7.rmSync(temporary, { force: true });
|
|
21166
21235
|
}
|
|
21167
21236
|
return { state: "queued", queued_submission_id: null };
|
|
21168
21237
|
}
|
|
@@ -21172,13 +21241,13 @@ function channelDeliveryState(profile, channelId, deliveryId) {
|
|
|
21172
21241
|
if (channel.kind === "codex")
|
|
21173
21242
|
return null;
|
|
21174
21243
|
const dir = channelDir(profile, channelId);
|
|
21175
|
-
if (
|
|
21244
|
+
if (fs7.existsSync(path9.join(dir, "emitted", `${deliveryId}.json`)))
|
|
21176
21245
|
return "emitted";
|
|
21177
21246
|
const claim3 = path9.join(dir, "claims", `${deliveryId}.json`);
|
|
21178
|
-
if (
|
|
21247
|
+
if (fs7.existsSync(claim3)) {
|
|
21179
21248
|
let value;
|
|
21180
21249
|
try {
|
|
21181
|
-
value = JSON.parse(
|
|
21250
|
+
value = JSON.parse(fs7.readFileSync(claim3, "utf8"));
|
|
21182
21251
|
} catch {
|
|
21183
21252
|
return "sending";
|
|
21184
21253
|
}
|
|
@@ -21190,41 +21259,48 @@ function channelDeliveryState(profile, channelId, deliveryId) {
|
|
|
21190
21259
|
return "unknown";
|
|
21191
21260
|
return "sending";
|
|
21192
21261
|
}
|
|
21193
|
-
return
|
|
21262
|
+
return fs7.readdirSync(path9.join(dir, "inbox")).some((name) => name.endsWith(`-${deliveryId}.json`)) ? "queued" : null;
|
|
21194
21263
|
}
|
|
21195
21264
|
function withdrawFromChannel(profile, channelId, deliveryId) {
|
|
21196
21265
|
uuid3.parse(deliveryId);
|
|
21197
21266
|
const dir = channelDir(profile, channelId);
|
|
21198
21267
|
const inbox = path9.join(dir, "inbox");
|
|
21199
|
-
const name =
|
|
21268
|
+
const name = fs7.existsSync(inbox) ? fs7.readdirSync(inbox).find((entry) => entry.endsWith(`-${deliveryId}.json`)) : void 0;
|
|
21200
21269
|
if (!name)
|
|
21201
21270
|
return false;
|
|
21202
21271
|
const claim3 = path9.join(dir, "claims", `${deliveryId}.json`);
|
|
21203
21272
|
try {
|
|
21204
|
-
|
|
21205
|
-
|
|
21273
|
+
fs7.linkSync(path9.join(inbox, name), claim3);
|
|
21274
|
+
fs7.unlinkSync(path9.join(inbox, name));
|
|
21206
21275
|
} catch (error62) {
|
|
21207
21276
|
if (["ENOENT", "EEXIST"].includes(error62.code ?? ""))
|
|
21208
21277
|
return false;
|
|
21209
21278
|
throw error62;
|
|
21210
21279
|
}
|
|
21280
|
+
if (alreadyEmitted(dir, deliveryId)) {
|
|
21281
|
+
fs7.rmSync(claim3, { force: true });
|
|
21282
|
+
return false;
|
|
21283
|
+
}
|
|
21211
21284
|
writeJson0600(claim3, { delivery_id: deliveryId, state: "withdrawn", at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
21212
21285
|
return true;
|
|
21213
21286
|
}
|
|
21287
|
+
function alreadyEmitted(dir, deliveryId) {
|
|
21288
|
+
return fs7.existsSync(path9.join(dir, "emitted", `${deliveryId}.json`));
|
|
21289
|
+
}
|
|
21214
21290
|
function claimPending(profile, channelId, by, limit = Infinity) {
|
|
21215
21291
|
const dir = channelDir(profile, channelId);
|
|
21216
21292
|
const inbox = path9.join(dir, "inbox");
|
|
21217
|
-
if (!
|
|
21293
|
+
if (!fs7.existsSync(inbox))
|
|
21218
21294
|
return [];
|
|
21219
21295
|
let identity;
|
|
21220
21296
|
const claimed = [];
|
|
21221
|
-
for (const name of
|
|
21297
|
+
for (const name of fs7.readdirSync(inbox).filter((entry) => entry.endsWith(".json")).sort()) {
|
|
21222
21298
|
if (claimed.length >= limit)
|
|
21223
21299
|
break;
|
|
21224
21300
|
const source = path9.join(inbox, name);
|
|
21225
21301
|
let item;
|
|
21226
21302
|
try {
|
|
21227
|
-
item = itemSchema.parse(JSON.parse(
|
|
21303
|
+
item = itemSchema.parse(JSON.parse(fs7.readFileSync(source, "utf8")));
|
|
21228
21304
|
} catch (error62) {
|
|
21229
21305
|
if (error62.code === "ENOENT")
|
|
21230
21306
|
continue;
|
|
@@ -21232,13 +21308,17 @@ function claimPending(profile, channelId, by, limit = Infinity) {
|
|
|
21232
21308
|
}
|
|
21233
21309
|
const claim3 = path9.join(dir, "claims", `${item.delivery_id}.json`);
|
|
21234
21310
|
try {
|
|
21235
|
-
|
|
21236
|
-
|
|
21311
|
+
fs7.linkSync(source, claim3);
|
|
21312
|
+
fs7.unlinkSync(source);
|
|
21237
21313
|
} catch (error62) {
|
|
21238
21314
|
if (["ENOENT", "EEXIST"].includes(error62.code ?? ""))
|
|
21239
21315
|
continue;
|
|
21240
21316
|
throw error62;
|
|
21241
21317
|
}
|
|
21318
|
+
if (alreadyEmitted(dir, item.delivery_id)) {
|
|
21319
|
+
fs7.rmSync(claim3, { force: true });
|
|
21320
|
+
continue;
|
|
21321
|
+
}
|
|
21242
21322
|
identity ??= processIdentity2(process.pid) ?? "unknown";
|
|
21243
21323
|
writeJson0600(claim3, { ...item, state: "sending", by, pid: process.pid, started_identity: identity });
|
|
21244
21324
|
claimed.push({ channel_id: channelId, item, claim: claim3, dir });
|
|
@@ -21249,7 +21329,7 @@ function settle2(entries, by, state) {
|
|
|
21249
21329
|
for (const entry of entries) {
|
|
21250
21330
|
if (state === "emitted") {
|
|
21251
21331
|
writeJson0600(path9.join(entry.dir, "emitted", `${entry.item.delivery_id}.json`), { delivery_id: entry.item.delivery_id, by, at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
21252
|
-
|
|
21332
|
+
fs7.rmSync(entry.claim, { force: true });
|
|
21253
21333
|
} else {
|
|
21254
21334
|
writeJson0600(entry.claim, { ...entry.item, state: "unknown", by });
|
|
21255
21335
|
}
|
|
@@ -21269,9 +21349,9 @@ function sessionIndex(profile, sessionId) {
|
|
|
21269
21349
|
}
|
|
21270
21350
|
function openClaudeChannels(profile, sessionId) {
|
|
21271
21351
|
const index = sessionIndex(profile, sessionId);
|
|
21272
|
-
if (!
|
|
21352
|
+
if (!fs7.existsSync(index))
|
|
21273
21353
|
return [];
|
|
21274
|
-
return
|
|
21354
|
+
return fs7.readdirSync(index).filter((name) => uuid3.safeParse(name).success).flatMap((name) => {
|
|
21275
21355
|
try {
|
|
21276
21356
|
const channel = readChannel(profile, name);
|
|
21277
21357
|
return channel.claude?.session_id === sessionId && !channelClosed(profile, name) ? [channel] : [];
|
|
@@ -21289,7 +21369,7 @@ function acquireWaiter(index) {
|
|
|
21289
21369
|
throw new ChannelError("CHANNEL_WAITER_UNAVAILABLE", "\u53D7\u4FE1hook\u306Eprocess\u3092\u78BA\u8A8D\u3067\u304D\u307E\u305B\u3093");
|
|
21290
21370
|
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
21291
21371
|
try {
|
|
21292
|
-
|
|
21372
|
+
fs7.writeFileSync(file2, JSON.stringify({ pid: process.pid, started_identity: identity }) + "\n", { flag: "wx", mode: 384 });
|
|
21293
21373
|
return identity;
|
|
21294
21374
|
} catch (error62) {
|
|
21295
21375
|
if (error62.code !== "EEXIST")
|
|
@@ -21297,33 +21377,38 @@ function acquireWaiter(index) {
|
|
|
21297
21377
|
}
|
|
21298
21378
|
let owner = {};
|
|
21299
21379
|
try {
|
|
21300
|
-
owner = JSON.parse(
|
|
21380
|
+
owner = JSON.parse(fs7.readFileSync(file2, "utf8"));
|
|
21301
21381
|
} catch {
|
|
21302
21382
|
}
|
|
21303
21383
|
if (typeof owner.pid === "number" && typeof owner.started_identity === "string" && processIdentity2(owner.pid) === owner.started_identity)
|
|
21304
21384
|
return null;
|
|
21305
21385
|
try {
|
|
21306
|
-
|
|
21386
|
+
fs7.renameSync(file2, path9.join(index, `waiter.${randomUUID3()}.stale`));
|
|
21307
21387
|
} catch {
|
|
21308
21388
|
}
|
|
21309
|
-
for (const name of
|
|
21310
|
-
|
|
21389
|
+
for (const name of fs7.readdirSync(index).filter((entry) => entry.endsWith(".stale")))
|
|
21390
|
+
fs7.rmSync(path9.join(index, name), { force: true });
|
|
21311
21391
|
}
|
|
21312
21392
|
return null;
|
|
21313
21393
|
}
|
|
21314
21394
|
function releaseWaiter(index, identity) {
|
|
21315
21395
|
const file2 = path9.join(index, "waiter.json");
|
|
21316
21396
|
try {
|
|
21317
|
-
const owner = JSON.parse(
|
|
21397
|
+
const owner = JSON.parse(fs7.readFileSync(file2, "utf8"));
|
|
21318
21398
|
if (owner.pid === process.pid && owner.started_identity === identity)
|
|
21319
|
-
|
|
21399
|
+
fs7.rmSync(file2, { force: true });
|
|
21320
21400
|
} catch {
|
|
21321
21401
|
}
|
|
21322
21402
|
}
|
|
21403
|
+
function currentHookOwner() {
|
|
21404
|
+
const owner = hookOwnerProcess(readRuntimeProcesses(), process.ppid);
|
|
21405
|
+
return owner ? { pid: owner.pid, started_identity: owner.started_identity } : null;
|
|
21406
|
+
}
|
|
21323
21407
|
async function runClaudeChannelWaiter(profile, input2, emit, options = {}) {
|
|
21324
21408
|
const event = external_exports.object({ session_id: external_exports.uuid() }).loose().parse(input2);
|
|
21325
21409
|
if (!openClaudeChannels(profile, event.session_id).length)
|
|
21326
21410
|
return 0;
|
|
21411
|
+
const owner = options.owner === void 0 ? currentHookOwner() : options.owner;
|
|
21327
21412
|
const index = sessionIndex(profile, event.session_id);
|
|
21328
21413
|
const identity = acquireWaiter(index);
|
|
21329
21414
|
if (!identity)
|
|
@@ -21337,10 +21422,11 @@ async function runClaudeChannelWaiter(profile, input2, emit, options = {}) {
|
|
|
21337
21422
|
return 0;
|
|
21338
21423
|
if (Date.now() - lastParentCheck >= 5e3) {
|
|
21339
21424
|
lastParentCheck = Date.now();
|
|
21340
|
-
|
|
21425
|
+
const alive = owner ? processIdentity2(owner.pid) === owner.started_identity : channels.some((channel) => processIdentity2(channel.claude.parent_pid) === channel.claude.parent_started_identity);
|
|
21426
|
+
if (!alive)
|
|
21341
21427
|
return 0;
|
|
21342
21428
|
}
|
|
21343
|
-
const claimed = channels.flatMap((channel) => claimPending(profile, channel.channel_id, "claude_hook"));
|
|
21429
|
+
const claimed = channels.flatMap((channel) => claimPending(profile, channel.channel_id, "claude_hook")).sort((left, right) => left.item.at < right.item.at ? -1 : left.item.at > right.item.at ? 1 : 0);
|
|
21344
21430
|
if (claimed.length) {
|
|
21345
21431
|
await emitClaimed(claimed, "claude_hook", (texts) => emit(texts.join("\n\n")));
|
|
21346
21432
|
return 2;
|
|
@@ -21425,25 +21511,25 @@ async function handleCursorChannelHook(profile, event, emit) {
|
|
|
21425
21511
|
const payload = name === "afterMCPExecution" ? event.result_json : event.tool_output;
|
|
21426
21512
|
const bound = channelIdFromResult(payload);
|
|
21427
21513
|
const conversations = path9.join(channelRoot(profile), "cursor-conversations");
|
|
21428
|
-
if (bound &&
|
|
21514
|
+
if (bound && fs7.existsSync(channelDir(profile, bound))) {
|
|
21429
21515
|
const channel = readChannel(profile, bound);
|
|
21430
21516
|
if (channel.kind === "cursor") {
|
|
21431
21517
|
const bindFile = path9.join(channelDir(profile, bound), "bind.json");
|
|
21432
|
-
if (!
|
|
21518
|
+
if (!fs7.existsSync(bindFile))
|
|
21433
21519
|
writeJson0600(bindFile, { conversation_id: conv, at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
21434
|
-
const bindConv = JSON.parse(
|
|
21520
|
+
const bindConv = JSON.parse(fs7.readFileSync(bindFile, "utf8")).conversation_id;
|
|
21435
21521
|
if (bindConv === conv) {
|
|
21436
21522
|
mkdirs(path9.join(conversations, conv));
|
|
21437
|
-
|
|
21523
|
+
fs7.writeFileSync(path9.join(conversations, conv, bound), "", { mode: 384 });
|
|
21438
21524
|
}
|
|
21439
21525
|
}
|
|
21440
21526
|
}
|
|
21441
21527
|
if (name === "afterMCPExecution")
|
|
21442
21528
|
return false;
|
|
21443
21529
|
const index = path9.join(conversations, conv);
|
|
21444
|
-
if (!
|
|
21530
|
+
if (!fs7.existsSync(index))
|
|
21445
21531
|
return false;
|
|
21446
|
-
const claimed =
|
|
21532
|
+
const claimed = fs7.readdirSync(index).filter((id) => uuid3.safeParse(id).success && !channelClosed(profile, id)).flatMap((id) => claimPending(profile, id, "cursor_hook"));
|
|
21447
21533
|
if (!claimed.length)
|
|
21448
21534
|
return false;
|
|
21449
21535
|
await emitClaimed(claimed, "cursor_hook", (texts) => emit(texts.join("\n\n")));
|
|
@@ -21512,6 +21598,11 @@ async function runClaudeHookMain(profile, root = claudeHookRoot(profile)) {
|
|
|
21512
21598
|
throw new Error("CLAUDE_PARENT_HOOK_EVENT_INVALID: \u672A\u5BFE\u5FDC\u306Ehook\u3067\u3059");
|
|
21513
21599
|
process.exitCode = await runClaudeChannelWaiter(profile, event, write);
|
|
21514
21600
|
break;
|
|
21601
|
+
case "SessionStart":
|
|
21602
|
+
if (!profile.channels)
|
|
21603
|
+
throw new Error("CLAUDE_PARENT_HOOK_EVENT_INVALID: \u672A\u5BFE\u5FDC\u306Ehook\u3067\u3059");
|
|
21604
|
+
process.exitCode = await runClaudeChannelWaiter(profile, event, write);
|
|
21605
|
+
break;
|
|
21515
21606
|
case "SessionEnd":
|
|
21516
21607
|
closeClaudeParentSession(event, root);
|
|
21517
21608
|
if (profile.channels)
|
|
@@ -21563,8 +21654,8 @@ function setupNodeExecutable(executable = process.execPath) {
|
|
|
21563
21654
|
}
|
|
21564
21655
|
|
|
21565
21656
|
// ../../node_modules/aiterm-steer-delivery/dist/aiterm-provider.js
|
|
21566
|
-
import { spawn as
|
|
21567
|
-
import * as
|
|
21657
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
21658
|
+
import * as fs8 from "node:fs";
|
|
21568
21659
|
import * as os2 from "node:os";
|
|
21569
21660
|
import * as path10 from "node:path";
|
|
21570
21661
|
var AITERM_PARENT_DELIVERY_SCHEMA = "aiterm.parent-delivery.v1";
|
|
@@ -21577,7 +21668,7 @@ var recordSchema = external_exports.object({
|
|
|
21577
21668
|
}).strict();
|
|
21578
21669
|
var isFile = (file2) => {
|
|
21579
21670
|
try {
|
|
21580
|
-
return
|
|
21671
|
+
return fs8.statSync(file2).isFile();
|
|
21581
21672
|
} catch {
|
|
21582
21673
|
return false;
|
|
21583
21674
|
}
|
|
@@ -21590,7 +21681,7 @@ function findAitermDeliveryProvider(options = {}) {
|
|
|
21590
21681
|
}
|
|
21591
21682
|
const home2 = options.home ?? env.HOME ?? os2.homedir();
|
|
21592
21683
|
try {
|
|
21593
|
-
const record3 = recordSchema.parse(JSON.parse(
|
|
21684
|
+
const record3 = recordSchema.parse(JSON.parse(fs8.readFileSync(path10.join(home2, ".config", "aiterm-mcp", "delivery-provider.json"), "utf8")));
|
|
21594
21685
|
const node2 = options.node ?? record3.node;
|
|
21595
21686
|
if (isFile(record3.cli) && isFile(node2))
|
|
21596
21687
|
return { node: node2, cli: record3.cli, version: record3.version, source: "record" };
|
|
@@ -21607,7 +21698,7 @@ function findAitermDeliveryProvider(options = {}) {
|
|
|
21607
21698
|
if (!isFile(shim))
|
|
21608
21699
|
continue;
|
|
21609
21700
|
try {
|
|
21610
|
-
return { node: options.node ?? process.execPath, cli:
|
|
21701
|
+
return { node: options.node ?? process.execPath, cli: fs8.realpathSync(shim), version: null, source: "path" };
|
|
21611
21702
|
} catch {
|
|
21612
21703
|
}
|
|
21613
21704
|
}
|
|
@@ -21630,7 +21721,7 @@ async function callAiterm(args, input2, options, sends) {
|
|
|
21630
21721
|
clearTimeout(timer);
|
|
21631
21722
|
resolve2({ stdout, started, failure: failure2 });
|
|
21632
21723
|
};
|
|
21633
|
-
const child =
|
|
21724
|
+
const child = spawn3(provider.node, [provider.cli, ...args], { stdio: ["pipe", "pipe", "ignore"], env: options.env ?? process.env, windowsHide: true });
|
|
21634
21725
|
const timer = setTimeout(() => {
|
|
21635
21726
|
child.kill("SIGKILL");
|
|
21636
21727
|
finish("\u6642\u9593\u5185\u306B\u8FD4\u308A\u304C\u3042\u308A\u307E\u305B\u3093");
|
|
@@ -21682,7 +21773,8 @@ async function codexDeliveryDetailViaAiterm(parent, deliveryId, options = {}) {
|
|
|
21682
21773
|
hook: value.hook ?? null,
|
|
21683
21774
|
turn_id: value.turn_id ?? null,
|
|
21684
21775
|
queued: value.queued ?? null,
|
|
21685
|
-
...typeof value.queue_error === "string" ? { queue_error: value.queue_error } : {}
|
|
21776
|
+
...typeof value.queue_error === "string" ? { queue_error: value.queue_error } : {},
|
|
21777
|
+
...value.wake !== null && typeof value.wake === "object" ? { wake: value.wake } : {}
|
|
21686
21778
|
};
|
|
21687
21779
|
}
|
|
21688
21780
|
async function codexDeliveryStateViaAiterm(parent, deliveryId, options = {}) {
|
|
@@ -21690,7 +21782,7 @@ async function codexDeliveryStateViaAiterm(parent, deliveryId, options = {}) {
|
|
|
21690
21782
|
}
|
|
21691
21783
|
|
|
21692
21784
|
// ../../node_modules/aiterm-steer-delivery/dist/codex-setup.js
|
|
21693
|
-
import * as
|
|
21785
|
+
import * as fs9 from "node:fs";
|
|
21694
21786
|
import * as path11 from "node:path";
|
|
21695
21787
|
import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
|
|
21696
21788
|
function codexHookCommand(node2, hook, directory2, platform = process.platform, powershell = () => resolveWindowsPowerShell7()) {
|
|
@@ -21701,20 +21793,20 @@ function codexHookCommand(node2, hook, directory2, platform = process.platform,
|
|
|
21701
21793
|
return [node2, hook, directory2].map((value) => "'" + value.replace(/'/g, `'"'"'`) + "'").join(" ");
|
|
21702
21794
|
}
|
|
21703
21795
|
function planCodexParentHooks(file2, command2, previousCommand) {
|
|
21704
|
-
if (!
|
|
21796
|
+
if (!fs9.existsSync(file2)) {
|
|
21705
21797
|
try {
|
|
21706
|
-
if (
|
|
21798
|
+
if (fs9.lstatSync(file2).isSymbolicLink())
|
|
21707
21799
|
throw new SetupError("codex_hook_config_invalid", "hook\u8A2D\u5B9Asymlink\u306E\u53C2\u7167\u5148\u304C\u3042\u308A\u307E\u305B\u3093");
|
|
21708
21800
|
} catch (error62) {
|
|
21709
21801
|
if (error62.code !== "ENOENT")
|
|
21710
21802
|
throw error62;
|
|
21711
21803
|
}
|
|
21712
21804
|
}
|
|
21713
|
-
const target2 =
|
|
21805
|
+
const target2 = fs9.existsSync(file2) ? fs9.realpathSync(file2) : file2;
|
|
21714
21806
|
let current = {};
|
|
21715
|
-
if (
|
|
21807
|
+
if (fs9.existsSync(target2)) {
|
|
21716
21808
|
try {
|
|
21717
|
-
current = JSON.parse(
|
|
21809
|
+
current = JSON.parse(fs9.readFileSync(target2, "utf8"));
|
|
21718
21810
|
} catch {
|
|
21719
21811
|
throw new SetupError("codex_hook_config_invalid", "Codex\u306Ehook\u8A2D\u5B9AJSON\u3092\u8AAD\u3081\u307E\u305B\u3093");
|
|
21720
21812
|
}
|
|
@@ -21767,10 +21859,10 @@ function planCodexParentHooks(file2, command2, previousCommand) {
|
|
|
21767
21859
|
function writeCodexHookPlan(profile, plan) {
|
|
21768
21860
|
if (!plan.changed)
|
|
21769
21861
|
return false;
|
|
21770
|
-
if (
|
|
21771
|
-
|
|
21862
|
+
if (fs9.existsSync(plan.target))
|
|
21863
|
+
fs9.copyFileSync(plan.target, `${plan.target}${profile.backup_suffix}`);
|
|
21772
21864
|
writeHookJson(plan.target, plan.next);
|
|
21773
|
-
if (!isDeepStrictEqual2(JSON.parse(
|
|
21865
|
+
if (!isDeepStrictEqual2(JSON.parse(fs9.readFileSync(plan.target, "utf8")), plan.next))
|
|
21774
21866
|
throw new SetupError("codex_hook_readback_failed", "Codex hook\u306E\u8AAD\u623B\u3057\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093");
|
|
21775
21867
|
return true;
|
|
21776
21868
|
}
|
|
@@ -21790,7 +21882,7 @@ async function applyCodexHookPlan(profile, plan, codexHome, executable) {
|
|
|
21790
21882
|
}
|
|
21791
21883
|
return withCodexReceiver(profile, { thread_id: "00000000-0000-4000-8000-000000000000", codex_home: codexHome }, async (request) => {
|
|
21792
21884
|
const listed = await request("hooks/list", { cwds: [codexHome] });
|
|
21793
|
-
const source =
|
|
21885
|
+
const source = fs9.realpathSync(plan.target);
|
|
21794
21886
|
const sample = (listed?.data?.[0]?.hooks ?? []).find((hook) => hook.sourcePath === source && typeof hook.key === "string");
|
|
21795
21887
|
if (!sample)
|
|
21796
21888
|
throw new SetupError("codex_hook_schema_unknown", "\u516C\u5F0FAPI\u3067hook\u306E\u9375\u3092\u78BA\u8A8D\u3067\u304D\u307E\u305B\u3093");
|
|
@@ -21818,7 +21910,7 @@ async function applyCodexHookPlan(profile, plan, codexHome, executable) {
|
|
|
21818
21910
|
}
|
|
21819
21911
|
async function cleanVacatedTrust(profile, plan, codexHome, executable) {
|
|
21820
21912
|
await withCodexReceiver(profile, { thread_id: "00000000-0000-4000-8000-000000000000", codex_home: codexHome }, async (request) => {
|
|
21821
|
-
const source =
|
|
21913
|
+
const source = fs9.realpathSync(plan.target);
|
|
21822
21914
|
const prefix = `${source}`;
|
|
21823
21915
|
const key = (event, [g, h]) => `${prefix}:${snake(event)}:${g}:${h}`;
|
|
21824
21916
|
const state = (await request("config/read", { includeLayers: false }))?.config?.hooks?.state ?? {};
|
|
@@ -21839,12 +21931,12 @@ function samePath(a, b) {
|
|
|
21839
21931
|
if (a === b)
|
|
21840
21932
|
return true;
|
|
21841
21933
|
try {
|
|
21842
|
-
return
|
|
21934
|
+
return fs9.realpathSync(a) === fs9.realpathSync(b);
|
|
21843
21935
|
} catch {
|
|
21844
21936
|
return process.platform === "win32" && a.toLowerCase() === b.toLowerCase();
|
|
21845
21937
|
}
|
|
21846
21938
|
}
|
|
21847
|
-
function processCodexHome(pid, platform = process.platform, read = (file2) =>
|
|
21939
|
+
function processCodexHome(pid, platform = process.platform, read = (file2) => fs9.readFileSync(file2)) {
|
|
21848
21940
|
if (platform !== "linux")
|
|
21849
21941
|
return null;
|
|
21850
21942
|
let raw;
|
|
@@ -21861,8 +21953,8 @@ function processCodexHome(pid, platform = process.platform, read = (file2) => fs
|
|
|
21861
21953
|
return home2 ? path11.posix.resolve(home2) : null;
|
|
21862
21954
|
}
|
|
21863
21955
|
async function verifyCodexHookRegistration(profile, config2, approve, directory2 = codexHookDirectory(profile)) {
|
|
21864
|
-
|
|
21865
|
-
|
|
21956
|
+
fs9.accessSync(config2.node, fs9.constants.X_OK);
|
|
21957
|
+
fs9.accessSync(config2.hook, fs9.constants.R_OK);
|
|
21866
21958
|
const file2 = path11.join(config2.codex_home, "hooks.json");
|
|
21867
21959
|
await withCodexReceiver(profile, { thread_id: "00000000-0000-4000-8000-000000000000", codex_home: config2.codex_home }, async (request) => {
|
|
21868
21960
|
const list = () => request("hooks/list", { cwds: [config2.codex_home] });
|
|
@@ -21923,11 +22015,11 @@ async function configureCodexSteer(profile, action = "status", overrides) {
|
|
|
21923
22015
|
return runtime.disableLegacy();
|
|
21924
22016
|
return previous?.enabled ? { status: "restart_required", reason_code: "codex_restart_required" } : { status: "disabled" };
|
|
21925
22017
|
}
|
|
21926
|
-
if (previous?.enabled &&
|
|
22018
|
+
if (previous?.enabled && fs9.realpathSync(previous.codex_home) !== fs9.realpathSync(runtime.codex_home))
|
|
21927
22019
|
throw new SetupError("codex_steer_configuration_conflict", "\u5225\u306ECODEX_HOME\u3067Steer\u304C\u6709\u52B9\u3067\u3059\u3002\u5148\u306B\u65E2\u5B58\u306E\u9078\u629E\u3092\u89E3\u9664\u3057\u3066\u304F\u3060\u3055\u3044");
|
|
21928
22020
|
const node2 = setupNodeExecutable(runtime.node);
|
|
21929
|
-
|
|
21930
|
-
|
|
22021
|
+
fs9.accessSync(node2, fs9.constants.X_OK);
|
|
22022
|
+
fs9.accessSync(runtime.hook, fs9.constants.R_OK);
|
|
21931
22023
|
const binary = runtime.findBinary();
|
|
21932
22024
|
const command2 = codexHookCommand(node2, runtime.hook, runtime.directory, runtime.platform, runtime.powershell);
|
|
21933
22025
|
const changed = await applyCodexHookPlan(profile, planCodexParentHooks(file2, command2, previous?.command), runtime.codex_home, binary);
|
|
@@ -21935,7 +22027,7 @@ async function configureCodexSteer(profile, action = "status", overrides) {
|
|
|
21935
22027
|
const packageRoot = (file3) => {
|
|
21936
22028
|
let real = file3;
|
|
21937
22029
|
try {
|
|
21938
|
-
real =
|
|
22030
|
+
real = fs9.realpathSync(file3);
|
|
21939
22031
|
} catch {
|
|
21940
22032
|
}
|
|
21941
22033
|
return /[\\/]bin[\\/]codex\.js$/u.test(real) ? path11.dirname(path11.dirname(real)) : null;
|
|
@@ -21960,10 +22052,12 @@ async function configureCodexSteer(profile, action = "status", overrides) {
|
|
|
21960
22052
|
stale_processes: stale
|
|
21961
22053
|
};
|
|
21962
22054
|
await runtime.verify(config2, true);
|
|
21963
|
-
|
|
22055
|
+
const alive = runtime.processes();
|
|
22056
|
+
const saved = { ...config2, stale_processes: config2.stale_processes.filter((stale2) => alive.some((row) => row.pid === stale2.pid && row.started_identity === stale2.started_identity)) };
|
|
22057
|
+
save(saved);
|
|
21964
22058
|
if (legacy?.enabled)
|
|
21965
22059
|
await runtime.disableLegacy();
|
|
21966
|
-
return
|
|
22060
|
+
return saved.stale_processes.length ? { status: "restart_required", reason_code: "codex_restart_required" } : { status: "ready" };
|
|
21967
22061
|
}
|
|
21968
22062
|
|
|
21969
22063
|
export {
|
package/dist/cli.mjs
CHANGED
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
waitProcessCommandLine,
|
|
57
57
|
withCodexReceiver,
|
|
58
58
|
withdrawFromChannel
|
|
59
|
-
} from "./chunks/chunk-
|
|
59
|
+
} from "./chunks/chunk-SN7I52NL.mjs";
|
|
60
60
|
|
|
61
61
|
// ../../node_modules/qrcode/lib/can-promise.js
|
|
62
62
|
var require_can_promise = __commonJS({
|
|
@@ -11916,7 +11916,16 @@ var provider = {
|
|
|
11916
11916
|
async function sendChannelAnswer(channelId, deliveryId, text2, codex = provider) {
|
|
11917
11917
|
if (channelClosed(PROFILE, channelId)) throw Object.assign(new Error("\u7533\u8ACB\u3092\u51FA\u3057\u305FAI\u306E\u4F1A\u8A71\u304C\u7D42\u308F\u3063\u3066\u3044\u307E\u3059"), { closed: true });
|
|
11918
11918
|
const channel = readChannel(PROFILE, channelId);
|
|
11919
|
-
if (channel.kind !== "codex")
|
|
11919
|
+
if (channel.kind !== "codex") {
|
|
11920
|
+
try {
|
|
11921
|
+
return await sendToChannel(PROFILE, channelId, deliveryId, text2);
|
|
11922
|
+
} catch (error) {
|
|
11923
|
+
if (error.delivery_code !== "CHANNEL_DELIVERY_DUPLICATE") throw error;
|
|
11924
|
+
const state = channelDeliveryState(PROFILE, channelId, deliveryId);
|
|
11925
|
+
if (state === null || state === "withdrawn") throw error;
|
|
11926
|
+
return { state: "queued", queued_submission_id: null };
|
|
11927
|
+
}
|
|
11928
|
+
}
|
|
11920
11929
|
if (!channel.codex) throw new CodexDeliveryError("CODEX_PARENT_ID_UNAVAILABLE", "channel\u306B\u5143\u306ECodex\u4F1A\u8A71\u304C\u3042\u308A\u307E\u305B\u3093");
|
|
11921
11930
|
const result = await codex.submit(channel.codex, deliveryId, text2);
|
|
11922
11931
|
return { state: "submitted", queued_submission_id: result.queued_submission_id };
|
|
@@ -15896,7 +15905,7 @@ function claudeChannelIsCurrent(profile, channelId, parent) {
|
|
|
15896
15905
|
}
|
|
15897
15906
|
|
|
15898
15907
|
// src/version.ts
|
|
15899
|
-
var VERSION = true ? "0.1.
|
|
15908
|
+
var VERSION = true ? "0.1.22" : "0.0.0-dev";
|
|
15900
15909
|
function osName() {
|
|
15901
15910
|
return process.platform === "darwin" ? "macos" : process.platform === "win32" ? "windows" : process.platform;
|
|
15902
15911
|
}
|
|
@@ -16350,7 +16359,7 @@ async function setup() {
|
|
|
16350
16359
|
out("\u6B21\u306EAI\u306BApproval Box\u3092\u767B\u9332\u3057\u307E\u3059\u3002\u66F8\u304D\u63DB\u3048\u308B\u30D5\u30A1\u30A4\u30EB:");
|
|
16351
16360
|
for (const target of targets) out(` ${LABEL[target]}: ${filesOf(target).join(", ")}`);
|
|
16352
16361
|
out("");
|
|
16353
|
-
if (targets.includes("claude")) out("\u30FBClaude Code \u306E Stop hook \u306F\u3001\u3059\u3079\u3066\u306E\u4F1A\u8A71\u3067\u30BF\u30FC\u30F3\u304C\u7D42\u308F\u308B\u305F\u3073\u306B node \u30921\u56DE\u8D77\u52D5\u3057\u307E\u3059\uFF08Approval Box\u306E\u7533\u8ACB\u304C\u7121\u3051\u308C\u3070\u3059\u3050\u7D42\u308F\u308A\u307E\u3059\uFF09\u3002");
|
|
16362
|
+
if (targets.includes("claude")) out("\u30FBClaude Code \u306E Stop hook \u3068 SessionStart hook \u306F\u3001\u3059\u3079\u3066\u306E\u4F1A\u8A71\u3067\u3001\u30BF\u30FC\u30F3\u304C\u7D42\u308F\u308B\u305F\u3073\u30FB\u4F1A\u8A71\u304C\u59CB\u307E\u308B\u305F\u3073\u306B node \u30921\u56DE\u8D77\u52D5\u3057\u307E\u3059\uFF08Approval Box\u306E\u7533\u8ACB\u304C\u7121\u3051\u308C\u3070\u3059\u3050\u7D42\u308F\u308A\u307E\u3059\uFF09\u3002");
|
|
16354
16363
|
if (targets.includes("codex")) out("\u30FBCodex \u306E\u7B54\u3048\u306F Aiterm \u306E Steer \u3067\u5143\u306E\u4F1A\u8A71\u3078\u8FD4\u3057\u307E\u3059\u3002\u65E7\u7248\u306EApproval Box\u5C02\u7528\u914D\u9001hook\u306F\u64A4\u53BB\u3057\u307E\u3059\u3002");
|
|
16355
16364
|
if (targets.includes("cursor") || targets.includes("grok")) out("\u30FBCursor\uFF08\u6B62\u307E\u3063\u3066\u3044\u308B\u6642\uFF09\u3068 Grok \u306F\u3001\u7533\u8ACB\u306E\u6642\u306BAI\u304C\u80CC\u666F\u3067\u53D7\u4FE1\u3092\u8D77\u52D5\u3057\u307E\u3059\u3002");
|
|
16356
16365
|
out(`\u30FB\u66F8\u304D\u63DB\u3048\u308B\u524D\u306E\u30D5\u30A1\u30A4\u30EB\u306F\u300C${".approval-box-backup"}\u300D\u3092\u4ED8\u3051\u3066\u63A7\u3048\u307E\u3059\u3002\u5143\u306B\u623B\u3059\u306B\u306F npx approval-box uninstall\u3002
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "approval-box",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.22",
|
|
4
4
|
"description": "Approval Box connector: lets Claude Code, Codex, Cursor and Grok ask you for a decision, and steers your answer back into the same session.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://approval-box.kitepon.dev",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@modelcontextprotocol/sdk": "^1.31.0",
|
|
33
33
|
"@types/node": "^25.9.1",
|
|
34
34
|
"@types/qrcode": "^1.5.5",
|
|
35
|
-
"aiterm-steer-delivery": "0.
|
|
35
|
+
"aiterm-steer-delivery": "0.4.4",
|
|
36
36
|
"esbuild": "^0.28.2",
|
|
37
37
|
"qrcode": "^1.5.4",
|
|
38
38
|
"typescript": "^6.0.3",
|