approval-box 0.1.13 → 0.1.14
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-codex-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-YBOJCW6Y.mjs → chunk-GH2JG56Y.mjs} +292 -236
- package/dist/cli.mjs +5 -4
- package/package.json +3 -4
|
@@ -2,7 +2,7 @@ import { createRequire as __kbCreateRequire } from 'node:module'; const require
|
|
|
2
2
|
import {
|
|
3
3
|
PROFILE,
|
|
4
4
|
runCodexHookMain
|
|
5
|
-
} from "./chunks/chunk-
|
|
5
|
+
} from "./chunks/chunk-GH2JG56Y.mjs";
|
|
6
6
|
|
|
7
7
|
// src/hooks/codex.ts
|
|
8
8
|
await runCodexHookMain(PROFILE, process.argv[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-GH2JG56Y.mjs";
|
|
6
6
|
|
|
7
7
|
// src/hooks/receive.ts
|
|
8
8
|
await runChannelReceiveMain(PROFILE);
|
|
@@ -19822,7 +19822,7 @@ function writeHookJson(file2, value) {
|
|
|
19822
19822
|
fs.unlinkSync(temporary);
|
|
19823
19823
|
}
|
|
19824
19824
|
}
|
|
19825
|
-
function waitForFileState(dir, inspect, timeoutMs) {
|
|
19825
|
+
function waitForFileState(dir, inspect, timeoutMs, signal) {
|
|
19826
19826
|
return new Promise((resolve2, reject) => {
|
|
19827
19827
|
let finished = false;
|
|
19828
19828
|
let timer;
|
|
@@ -19837,11 +19837,13 @@ function waitForFileState(dir, inspect, timeoutMs) {
|
|
|
19837
19837
|
clearInterval(timer);
|
|
19838
19838
|
if (timeout)
|
|
19839
19839
|
clearTimeout(timeout);
|
|
19840
|
+
signal?.removeEventListener("abort", abort);
|
|
19840
19841
|
if (error62)
|
|
19841
19842
|
reject(error62);
|
|
19842
19843
|
else
|
|
19843
19844
|
resolve2(value);
|
|
19844
19845
|
};
|
|
19846
|
+
const abort = () => finish(new Error("WAIT_FOR_FILE_ABORTED"));
|
|
19845
19847
|
const check2 = () => {
|
|
19846
19848
|
if (finished)
|
|
19847
19849
|
return;
|
|
@@ -19857,12 +19859,17 @@ function waitForFileState(dir, inspect, timeoutMs) {
|
|
|
19857
19859
|
timer = setInterval(check2, 5e3);
|
|
19858
19860
|
if (timeoutMs !== void 0)
|
|
19859
19861
|
timeout = setTimeout(() => finish(new Error("WAIT_FOR_FILE_TIMEOUT")), timeoutMs);
|
|
19862
|
+
if (signal?.aborted)
|
|
19863
|
+
abort();
|
|
19864
|
+
else
|
|
19865
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
19860
19866
|
check2();
|
|
19861
19867
|
});
|
|
19862
19868
|
}
|
|
19863
19869
|
|
|
19864
19870
|
// ../../node_modules/aiterm-steer-delivery/dist/windows.js
|
|
19865
19871
|
import { execFileSync, spawnSync } from "node:child_process";
|
|
19872
|
+
import { realpathSync } from "node:fs";
|
|
19866
19873
|
import * as path3 from "node:path";
|
|
19867
19874
|
var WINDOWS_POWERSHELL_7_COMMAND = "pwsh.exe";
|
|
19868
19875
|
var WINDOWS_POWERSHELL_7_INSTALL = "winget install --id Microsoft.PowerShell --source winget";
|
|
@@ -19899,9 +19906,15 @@ function resolveWindowsPowerShell7(probe = defaultProbe) {
|
|
|
19899
19906
|
}
|
|
19900
19907
|
if (version2.status !== 0 || identity?.edition !== "Core" || !Number.isInteger(identity.major) || Number(identity.major) < 7)
|
|
19901
19908
|
fail();
|
|
19909
|
+
let canonical;
|
|
19910
|
+
try {
|
|
19911
|
+
canonical = realpathSync.native(executable);
|
|
19912
|
+
} catch {
|
|
19913
|
+
return fail();
|
|
19914
|
+
}
|
|
19902
19915
|
if (probe === defaultProbe)
|
|
19903
|
-
resolvedDefault =
|
|
19904
|
-
return
|
|
19916
|
+
resolvedDefault = canonical;
|
|
19917
|
+
return canonical;
|
|
19905
19918
|
}
|
|
19906
19919
|
var quotePowerShell = (value) => `'${value.replace(/'/g, "''")}'`;
|
|
19907
19920
|
function windowsPowerShellSync(script, onFailure, timeout = 15e3) {
|
|
@@ -20170,6 +20183,18 @@ function parsePosixProcessTable(text) {
|
|
|
20170
20183
|
};
|
|
20171
20184
|
});
|
|
20172
20185
|
}
|
|
20186
|
+
var HOOK_SHELLS = /* @__PURE__ */ new Set(["sh", "bash", "dash", "zsh", "ksh", "ash", "busybox", "pwsh", "powershell", "cmd"]);
|
|
20187
|
+
function executableName(row) {
|
|
20188
|
+
const source = row.executable || (row.command.startsWith('"') ? row.command.slice(1).split('"')[0] : row.command.split(/\s+/u)[0]);
|
|
20189
|
+
return (source.split(/[\\/]/u).pop() ?? "").replace(/^-/u, "").replace(/\.exe$/iu, "").toLowerCase();
|
|
20190
|
+
}
|
|
20191
|
+
function hookOwnerProcess(rows, pid) {
|
|
20192
|
+
const byPid = new Map(rows.map((row) => [row.pid, row]));
|
|
20193
|
+
let current = byPid.get(pid);
|
|
20194
|
+
for (let depth = 0; current && depth < 4 && HOOK_SHELLS.has(executableName(current)); depth += 1)
|
|
20195
|
+
current = byPid.get(current.parent_pid);
|
|
20196
|
+
return current;
|
|
20197
|
+
}
|
|
20173
20198
|
function readRuntimeProcesses() {
|
|
20174
20199
|
if (!isWin2) {
|
|
20175
20200
|
const result2 = spawnSync3("/bin/ps", ["-axww", "-o", "pid=,ppid=,pgid=,stat=,lstart=,time=,command="], {
|
|
@@ -20595,8 +20620,8 @@ function assertOpen(parent) {
|
|
|
20595
20620
|
}
|
|
20596
20621
|
function prepareClaudeHookRequest(input2, root) {
|
|
20597
20622
|
const event = external_exports.object({ session_id: external_exports.uuid(), tool_use_id: requestId, agent_id: external_exports.string().optional() }).parse(input2);
|
|
20598
|
-
const
|
|
20599
|
-
if (!
|
|
20623
|
+
const owner = hookOwnerProcess(readRuntimeProcesses(), process.ppid);
|
|
20624
|
+
if (!owner)
|
|
20600
20625
|
throw new ClaudeDeliveryError("CLAUDE_PARENT_PROCESS_UNAVAILABLE", "hook\u3092\u8D77\u52D5\u3057\u305F\u89AAprocess\u3092\u78BA\u8A8D\u3067\u304D\u307E\u305B\u3093");
|
|
20601
20626
|
const dir = path8.join(root, event.tool_use_id);
|
|
20602
20627
|
fs5.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
@@ -20604,8 +20629,8 @@ function prepareClaudeHookRequest(input2, root) {
|
|
|
20604
20629
|
request_id: event.tool_use_id,
|
|
20605
20630
|
session_id: event.session_id,
|
|
20606
20631
|
agent_id: event.agent_id ?? null,
|
|
20607
|
-
parent_pid:
|
|
20608
|
-
parent_started_identity:
|
|
20632
|
+
parent_pid: owner.pid,
|
|
20633
|
+
parent_started_identity: owner.started_identity
|
|
20609
20634
|
});
|
|
20610
20635
|
}
|
|
20611
20636
|
function claudeParentFromRequest(profile, clientName, metadata, root) {
|
|
@@ -20695,6 +20720,250 @@ async function runClaudeResultHook(profile, input2, emit, root) {
|
|
|
20695
20720
|
import * as fs6 from "node:fs";
|
|
20696
20721
|
import { homedir as homedir3 } from "node:os";
|
|
20697
20722
|
import * as path9 from "node:path";
|
|
20723
|
+
|
|
20724
|
+
// ../../node_modules/aiterm-steer-delivery/dist/hook-setup.js
|
|
20725
|
+
import { copyFileSync, existsSync as existsSync6, lstatSync, mkdirSync as mkdirSync5, readFileSync as readFileSync5, realpathSync as realpathSync4, renameSync as renameSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync3 } from "node:fs";
|
|
20726
|
+
import { dirname as dirname3 } from "node:path";
|
|
20727
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
20728
|
+
import { isDeepStrictEqual } from "node:util";
|
|
20729
|
+
var record2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20730
|
+
function endsWithFile(value, file2) {
|
|
20731
|
+
return value === file2 || value.endsWith(`/${file2}`) || value.endsWith(`\\${file2}`);
|
|
20732
|
+
}
|
|
20733
|
+
function shellQuote(value, platform = process.platform) {
|
|
20734
|
+
if (platform === "win32")
|
|
20735
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
20736
|
+
return `'${value.replace(/'/g, `'"'"'`)}'`;
|
|
20737
|
+
}
|
|
20738
|
+
function claudeParentHookCommand(hook, platform = process.platform) {
|
|
20739
|
+
const words = `${shellQuote(hook.command, platform)} ${shellQuote(hook.script, platform)}`;
|
|
20740
|
+
if (platform === "win32")
|
|
20741
|
+
return { command: `& ${words}; exit (Get-Variable LASTEXITCODE -ValueOnly)`, shell: "powershell" };
|
|
20742
|
+
return { command: `exec ${words}` };
|
|
20743
|
+
}
|
|
20744
|
+
function claudeParentHookEntries(profile, hook, platform = process.platform) {
|
|
20745
|
+
const command2 = { type: "command", ...claudeParentHookCommand(hook, platform) };
|
|
20746
|
+
const matcher = `^mcp__${profile.mcp_server}__(${profile.dispatch_tools.join("|")})$`;
|
|
20747
|
+
return {
|
|
20748
|
+
PreToolUse: [{ matcher, hooks: [{ ...command2, timeout: 15 }] }],
|
|
20749
|
+
PostToolUse: [{ matcher, hooks: [{ ...command2, asyncRewake: true, timeout: 86400 }] }],
|
|
20750
|
+
// 長く続く受信(channel)では、turnが終わるたびに待機を張り直す。
|
|
20751
|
+
...profile.channels ? { Stop: [{ hooks: [{ ...command2, asyncRewake: true, timeout: 86400 }] }] } : {},
|
|
20752
|
+
SessionEnd: [{ hooks: [{ ...command2, timeout: 15 }] }]
|
|
20753
|
+
};
|
|
20754
|
+
}
|
|
20755
|
+
function mergeClaudeParentHooks(profile, file2, hook) {
|
|
20756
|
+
const target = existsSync6(file2) ? realpathSync4(file2) : file2;
|
|
20757
|
+
let current = {};
|
|
20758
|
+
if (existsSync6(target)) {
|
|
20759
|
+
try {
|
|
20760
|
+
current = JSON.parse(readFileSync5(target, "utf8"));
|
|
20761
|
+
} catch {
|
|
20762
|
+
throw new SetupError("config_invalid", "Claude\u306Ehook\u8A2D\u5B9AJSON\u3092\u8AAD\u3081\u307E\u305B\u3093");
|
|
20763
|
+
}
|
|
20764
|
+
}
|
|
20765
|
+
if (!record2(current) || current.hooks !== void 0 && !record2(current.hooks)) {
|
|
20766
|
+
throw new SetupError("config_invalid", "Claude\u306Ehooks\u8A2D\u5B9A\u306Fobject\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059");
|
|
20767
|
+
}
|
|
20768
|
+
if (current.disableAllHooks === true)
|
|
20769
|
+
throw new SetupError("claude_parent_hooks_disabled", "Claude\u306Ehook\u304C\u7121\u52B9\u3067\u3059\u3002disableAllHooks\u3092false\u306B\u5909\u66F4\u3057\u3066\u304B\u3089setup\u3057\u3066\u304F\u3060\u3055\u3044");
|
|
20770
|
+
const hooks = { ...current.hooks };
|
|
20771
|
+
for (const [event, additions] of Object.entries(claudeParentHookEntries(profile, hook))) {
|
|
20772
|
+
const previous = hooks[event] ?? [];
|
|
20773
|
+
if (!Array.isArray(previous) || previous.some((group) => !record2(group) || !Array.isArray(group.hooks))) {
|
|
20774
|
+
throw new SetupError("config_invalid", `Claude\u306E${event} hook\u5F62\u5F0F\u3092\u8AAD\u3081\u307E\u305B\u3093`);
|
|
20775
|
+
}
|
|
20776
|
+
const owned = previous.flatMap((group) => group.hooks.filter((entry) => isClaudeParentHook(profile, entry)));
|
|
20777
|
+
if (owned.length === additions.flatMap((group) => group.hooks).length && additions.every((addition) => previous.some((group) => isDeepStrictEqual(group, addition))))
|
|
20778
|
+
continue;
|
|
20779
|
+
const retained = previous.map((group) => ({
|
|
20780
|
+
...group,
|
|
20781
|
+
hooks: group.hooks.filter((entry) => !isClaudeParentHook(profile, entry))
|
|
20782
|
+
})).filter((group) => group.hooks.length > 0);
|
|
20783
|
+
hooks[event] = [...retained, ...additions];
|
|
20784
|
+
}
|
|
20785
|
+
const next = { ...current, hooks };
|
|
20786
|
+
if (isDeepStrictEqual(current, next))
|
|
20787
|
+
return "unchanged";
|
|
20788
|
+
mkdirSync5(dirname3(target), { recursive: true });
|
|
20789
|
+
const temporary = `${target}.${profile.id}-${randomUUID2()}`;
|
|
20790
|
+
try {
|
|
20791
|
+
writeFileSync3(temporary, `${JSON.stringify(next, null, 2)}
|
|
20792
|
+
`, { mode: 384, flag: "wx" });
|
|
20793
|
+
if (existsSync6(target))
|
|
20794
|
+
copyFileSync(target, `${target}${profile.backup_suffix}`);
|
|
20795
|
+
renameSync2(temporary, target);
|
|
20796
|
+
} finally {
|
|
20797
|
+
if (existsSync6(temporary))
|
|
20798
|
+
unlinkSync3(temporary);
|
|
20799
|
+
}
|
|
20800
|
+
if (!isDeepStrictEqual(JSON.parse(readFileSync5(target, "utf8")), next)) {
|
|
20801
|
+
throw new SetupError("config_readback_failed", "Claude\u306Ehook\u767B\u9332\u306E\u8AAD\u623B\u3057\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093");
|
|
20802
|
+
}
|
|
20803
|
+
return "configured";
|
|
20804
|
+
}
|
|
20805
|
+
function isClaudeParentHook(profile, hook) {
|
|
20806
|
+
if (!record2(hook) || hook.type !== "command")
|
|
20807
|
+
return false;
|
|
20808
|
+
if (Array.isArray(hook.args))
|
|
20809
|
+
return typeof hook.args[0] === "string" && endsWithFile(hook.args[0], profile.hooks.claude);
|
|
20810
|
+
return typeof hook.command === "string" && commandNamesFile(hook.command, profile.hooks.claude);
|
|
20811
|
+
}
|
|
20812
|
+
function ownedClaudeParentHooks(profile, document, event) {
|
|
20813
|
+
const hooks = record2(document) && record2(document.hooks) ? document.hooks[event] : void 0;
|
|
20814
|
+
if (!Array.isArray(hooks))
|
|
20815
|
+
return [];
|
|
20816
|
+
return hooks.flatMap((group) => record2(group) && Array.isArray(group.hooks) ? group.hooks : []).filter((entry) => isClaudeParentHook(profile, entry));
|
|
20817
|
+
}
|
|
20818
|
+
function claudeParentHooksRegistered(profile, document) {
|
|
20819
|
+
return Object.keys(claudeParentHookEntries(profile, { command: "", script: profile.hooks.claude })).every((event) => ownedClaudeParentHooks(profile, document, event).length > 0);
|
|
20820
|
+
}
|
|
20821
|
+
function removeClaudeParentHooks(profile, file2) {
|
|
20822
|
+
if (!existsSync6(file2))
|
|
20823
|
+
return "unchanged";
|
|
20824
|
+
const target = realpathSync4(file2);
|
|
20825
|
+
const current = JSON.parse(readFileSync5(target, "utf8"));
|
|
20826
|
+
if (!record2(current) || current.hooks !== void 0 && !record2(current.hooks)) {
|
|
20827
|
+
throw new SetupError("config_invalid", "Claude\u306Ehook\u8A2D\u5B9A\u3092\u8AAD\u3081\u307E\u305B\u3093");
|
|
20828
|
+
}
|
|
20829
|
+
if (current.hooks === void 0)
|
|
20830
|
+
return "unchanged";
|
|
20831
|
+
const hooks = { ...current.hooks };
|
|
20832
|
+
for (const event of ["PreToolUse", "PostToolUse", "Stop", "SessionEnd"]) {
|
|
20833
|
+
if (hooks[event] === void 0)
|
|
20834
|
+
continue;
|
|
20835
|
+
if (!Array.isArray(hooks[event]))
|
|
20836
|
+
throw new SetupError("config_invalid", "Claude\u306Ehook\u8A2D\u5B9A\u3092\u8AAD\u3081\u307E\u305B\u3093");
|
|
20837
|
+
hooks[event] = hooks[event].map((group) => {
|
|
20838
|
+
if (!record2(group) || !Array.isArray(group.hooks))
|
|
20839
|
+
throw new SetupError("config_invalid", "Claude\u306Ehook\u8A2D\u5B9A\u3092\u8AAD\u3081\u307E\u305B\u3093");
|
|
20840
|
+
return { ...group, hooks: group.hooks.filter((entry) => !isClaudeParentHook(profile, entry)) };
|
|
20841
|
+
}).filter((group) => group.hooks.length > 0);
|
|
20842
|
+
}
|
|
20843
|
+
const next = { ...current, hooks };
|
|
20844
|
+
if (isDeepStrictEqual(current, next))
|
|
20845
|
+
return "unchanged";
|
|
20846
|
+
const temporary = `${target}.${profile.id}-${randomUUID2()}`;
|
|
20847
|
+
try {
|
|
20848
|
+
writeFileSync3(temporary, `${JSON.stringify(next, null, 2)}
|
|
20849
|
+
`, { mode: 384, flag: "wx" });
|
|
20850
|
+
copyFileSync(target, `${target}${profile.backup_suffix}`);
|
|
20851
|
+
renameSync2(temporary, target);
|
|
20852
|
+
} finally {
|
|
20853
|
+
if (existsSync6(temporary))
|
|
20854
|
+
unlinkSync3(temporary);
|
|
20855
|
+
}
|
|
20856
|
+
if (!isDeepStrictEqual(JSON.parse(readFileSync5(target, "utf8")), next))
|
|
20857
|
+
throw new SetupError("config_readback_failed", "Claude hook\u89E3\u9664\u306E\u8AAD\u623B\u3057\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093");
|
|
20858
|
+
return "removed";
|
|
20859
|
+
}
|
|
20860
|
+
function cursorParentHookCommand(hook) {
|
|
20861
|
+
const command2 = `${shellQuote(hook.command)} ${shellQuote(hook.script)}`;
|
|
20862
|
+
return process.platform === "win32" ? `& ${command2}` : command2;
|
|
20863
|
+
}
|
|
20864
|
+
function commandNamesFile(command2, file2) {
|
|
20865
|
+
const escaped = file2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
20866
|
+
return new RegExp(`(?:^|[\\\\/'"\\s])${escaped}(?:['"\\s]|$)`, "u").test(command2);
|
|
20867
|
+
}
|
|
20868
|
+
function ownsCursorParentHook(profile, hook) {
|
|
20869
|
+
return record2(hook) && typeof hook.command === "string" && commandNamesFile(hook.command, profile.hooks.cursor);
|
|
20870
|
+
}
|
|
20871
|
+
function mergeCursorParentHooks(profile, file2, hook) {
|
|
20872
|
+
const target = existsSync6(file2) ? realpathSync4(file2) : file2;
|
|
20873
|
+
let current = { version: 1, hooks: {} };
|
|
20874
|
+
if (existsSync6(target)) {
|
|
20875
|
+
try {
|
|
20876
|
+
current = JSON.parse(readFileSync5(target, "utf8"));
|
|
20877
|
+
} catch {
|
|
20878
|
+
throw new SetupError("config_invalid", "Cursor\u306Ehook\u8A2D\u5B9AJSON\u3092\u8AAD\u3081\u307E\u305B\u3093");
|
|
20879
|
+
}
|
|
20880
|
+
} else {
|
|
20881
|
+
try {
|
|
20882
|
+
if (lstatSync(file2).isSymbolicLink())
|
|
20883
|
+
throw new SetupError("config_invalid", "Cursor\u306Ehooks\u8A2D\u5B9Asymlink\u306E\u53C2\u7167\u5148\u304C\u3042\u308A\u307E\u305B\u3093");
|
|
20884
|
+
} catch (error62) {
|
|
20885
|
+
if (error62.code !== "ENOENT")
|
|
20886
|
+
throw error62;
|
|
20887
|
+
}
|
|
20888
|
+
}
|
|
20889
|
+
if (!record2(current) || current.hooks !== void 0 && !record2(current.hooks)) {
|
|
20890
|
+
throw new SetupError("config_invalid", "Cursor\u306Ehooks\u8A2D\u5B9A\u306Fobject\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059");
|
|
20891
|
+
}
|
|
20892
|
+
const hooks = { ...current.hooks };
|
|
20893
|
+
const entry = { command: cursorParentHookCommand(hook), timeout: 15 };
|
|
20894
|
+
for (const event of ["afterMCPExecution", "postToolUse"]) {
|
|
20895
|
+
const previous = hooks[event] ?? [];
|
|
20896
|
+
if (!Array.isArray(previous))
|
|
20897
|
+
throw new SetupError("config_invalid", `Cursor\u306E${event} hook\u5F62\u5F0F\u3092\u8AAD\u3081\u307E\u305B\u3093`);
|
|
20898
|
+
const retained = previous.filter((hook2) => !ownsCursorParentHook(profile, hook2));
|
|
20899
|
+
const owned = previous.filter((hook2) => ownsCursorParentHook(profile, hook2));
|
|
20900
|
+
if (owned.length === 1 && isDeepStrictEqual(owned[0], entry) && retained.length + 1 === previous.length)
|
|
20901
|
+
continue;
|
|
20902
|
+
const index = previous.findIndex((hook2) => ownsCursorParentHook(profile, hook2));
|
|
20903
|
+
hooks[event] = index < 0 ? [...retained, entry] : previous.map((hook2, i) => i === index ? entry : hook2).filter((hook2, i) => i === index || !ownsCursorParentHook(profile, hook2));
|
|
20904
|
+
}
|
|
20905
|
+
const next = { ...current, version: current.version ?? 1, hooks };
|
|
20906
|
+
if (isDeepStrictEqual(current, next))
|
|
20907
|
+
return "unchanged";
|
|
20908
|
+
mkdirSync5(dirname3(target), { recursive: true });
|
|
20909
|
+
const temporary = `${target}.${profile.id}-${randomUUID2()}`;
|
|
20910
|
+
try {
|
|
20911
|
+
writeFileSync3(temporary, `${JSON.stringify(next, null, 2)}
|
|
20912
|
+
`, { mode: 384, flag: "wx" });
|
|
20913
|
+
if (existsSync6(target))
|
|
20914
|
+
copyFileSync(target, `${target}${profile.backup_suffix}`);
|
|
20915
|
+
renameSync2(temporary, target);
|
|
20916
|
+
} finally {
|
|
20917
|
+
if (existsSync6(temporary))
|
|
20918
|
+
unlinkSync3(temporary);
|
|
20919
|
+
}
|
|
20920
|
+
if (!isDeepStrictEqual(JSON.parse(readFileSync5(target, "utf8")), next)) {
|
|
20921
|
+
throw new SetupError("config_readback_failed", "Cursor\u306Ehook\u767B\u9332\u306E\u8AAD\u623B\u3057\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093");
|
|
20922
|
+
}
|
|
20923
|
+
return "configured";
|
|
20924
|
+
}
|
|
20925
|
+
function removeCursorParentHooks(profile, file2) {
|
|
20926
|
+
if (!existsSync6(file2))
|
|
20927
|
+
return "unchanged";
|
|
20928
|
+
const target = realpathSync4(file2);
|
|
20929
|
+
const current = JSON.parse(readFileSync5(target, "utf8"));
|
|
20930
|
+
if (!record2(current) || current.hooks !== void 0 && !record2(current.hooks)) {
|
|
20931
|
+
throw new SetupError("config_invalid", "Cursor\u306Ehook\u8A2D\u5B9A\u3092\u8AAD\u3081\u307E\u305B\u3093");
|
|
20932
|
+
}
|
|
20933
|
+
if (current.hooks === void 0)
|
|
20934
|
+
return "unchanged";
|
|
20935
|
+
const hooks = { ...current.hooks };
|
|
20936
|
+
for (const event of ["afterMCPExecution", "postToolUse"]) {
|
|
20937
|
+
if (hooks[event] === void 0)
|
|
20938
|
+
continue;
|
|
20939
|
+
if (!Array.isArray(hooks[event]))
|
|
20940
|
+
throw new SetupError("config_invalid", "Cursor\u306Ehook\u8A2D\u5B9A\u3092\u8AAD\u3081\u307E\u305B\u3093");
|
|
20941
|
+
const retained = hooks[event].filter((hook) => !ownsCursorParentHook(profile, hook));
|
|
20942
|
+
if (retained.length)
|
|
20943
|
+
hooks[event] = retained;
|
|
20944
|
+
else
|
|
20945
|
+
delete hooks[event];
|
|
20946
|
+
}
|
|
20947
|
+
const next = { ...current, hooks };
|
|
20948
|
+
if (isDeepStrictEqual(current, next))
|
|
20949
|
+
return "unchanged";
|
|
20950
|
+
const temporary = `${target}.${profile.id}-${randomUUID2()}`;
|
|
20951
|
+
try {
|
|
20952
|
+
writeFileSync3(temporary, `${JSON.stringify(next, null, 2)}
|
|
20953
|
+
`, { mode: 384, flag: "wx" });
|
|
20954
|
+
copyFileSync(target, `${target}${profile.backup_suffix}`);
|
|
20955
|
+
renameSync2(temporary, target);
|
|
20956
|
+
} finally {
|
|
20957
|
+
if (existsSync6(temporary))
|
|
20958
|
+
unlinkSync3(temporary);
|
|
20959
|
+
}
|
|
20960
|
+
if (!isDeepStrictEqual(JSON.parse(readFileSync5(target, "utf8")), next)) {
|
|
20961
|
+
throw new SetupError("config_readback_failed", "Cursor hook\u89E3\u9664\u306E\u8AAD\u623B\u3057\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093");
|
|
20962
|
+
}
|
|
20963
|
+
return "removed";
|
|
20964
|
+
}
|
|
20965
|
+
|
|
20966
|
+
// ../../node_modules/aiterm-steer-delivery/dist/cursor-receiver.js
|
|
20698
20967
|
var cursorParentSchema = external_exports.object({
|
|
20699
20968
|
kind: external_exports.literal("cursor"),
|
|
20700
20969
|
hook_root: external_exports.string()
|
|
@@ -20720,7 +20989,7 @@ function cursorParentHooksRegistered(profile, document) {
|
|
|
20720
20989
|
if (entry === null || typeof entry !== "object")
|
|
20721
20990
|
return false;
|
|
20722
20991
|
const command2 = entry.command;
|
|
20723
|
-
return typeof command2 === "string" && command2
|
|
20992
|
+
return typeof command2 === "string" && commandNamesFile(command2, profile.hooks.cursor);
|
|
20724
20993
|
});
|
|
20725
20994
|
};
|
|
20726
20995
|
return owns("postToolUse") && owns("afterMCPExecution");
|
|
@@ -20888,7 +21157,7 @@ function waitProcessCommandLine(wait, platform = process.platform) {
|
|
|
20888
21157
|
// ../../node_modules/aiterm-steer-delivery/dist/channel.js
|
|
20889
21158
|
import * as fs7 from "node:fs";
|
|
20890
21159
|
import * as path10 from "node:path";
|
|
20891
|
-
import { randomUUID as
|
|
21160
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
20892
21161
|
import { setTimeout as delay } from "node:timers/promises";
|
|
20893
21162
|
var uuid3 = external_exports.uuid();
|
|
20894
21163
|
var channelSchema = external_exports.object({
|
|
@@ -20914,7 +21183,7 @@ function mkdirs(...dirs) {
|
|
|
20914
21183
|
fs7.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
20915
21184
|
}
|
|
20916
21185
|
function openChannel(profile, parent) {
|
|
20917
|
-
const channel_id =
|
|
21186
|
+
const channel_id = randomUUID3();
|
|
20918
21187
|
const dir = channelDir(profile, channel_id);
|
|
20919
21188
|
const created_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
20920
21189
|
let channel;
|
|
@@ -20980,7 +21249,7 @@ async function sendToChannel(profile, channelId, deliveryId, text, runtime) {
|
|
|
20980
21249
|
}
|
|
20981
21250
|
const name = `${Date.now().toString().padStart(15, "0")}-${(sendSequence++).toString().padStart(9, "0")}-${deliveryId}.json`;
|
|
20982
21251
|
const item = { delivery_id: deliveryId, text, at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
20983
|
-
const temporary = path10.join(dir, `.${deliveryId}.${
|
|
21252
|
+
const temporary = path10.join(dir, `.${deliveryId}.${randomUUID3()}.tmp`);
|
|
20984
21253
|
fs7.writeFileSync(temporary, JSON.stringify(item) + "\n", { flag: "wx", mode: 384 });
|
|
20985
21254
|
try {
|
|
20986
21255
|
fs7.linkSync(temporary, path10.join(dir, "inbox", name));
|
|
@@ -21130,7 +21399,7 @@ function acquireWaiter(index) {
|
|
|
21130
21399
|
if (typeof owner.pid === "number" && typeof owner.started_identity === "string" && processIdentity2(owner.pid) === owner.started_identity)
|
|
21131
21400
|
return null;
|
|
21132
21401
|
try {
|
|
21133
|
-
fs7.renameSync(file2, path10.join(index, `waiter.${
|
|
21402
|
+
fs7.renameSync(file2, path10.join(index, `waiter.${randomUUID3()}.stale`));
|
|
21134
21403
|
} catch {
|
|
21135
21404
|
}
|
|
21136
21405
|
for (const name of fs7.readdirSync(index).filter((entry) => entry.endsWith(".stale")))
|
|
@@ -21332,6 +21601,8 @@ async function runCodexHookMain(profile, directory2 = process.argv[2]) {
|
|
|
21332
21601
|
async function runClaudeHookMain(profile, root = claudeHookRoot(profile)) {
|
|
21333
21602
|
try {
|
|
21334
21603
|
const event = JSON.parse(await readStdin());
|
|
21604
|
+
if (event !== null && typeof event === "object" && typeof event.hookEventName === "string")
|
|
21605
|
+
return;
|
|
21335
21606
|
const write = (text) => new Promise((resolve2, reject) => {
|
|
21336
21607
|
process.stderr.write(text, (error62) => error62 ? reject(error62) : resolve2());
|
|
21337
21608
|
});
|
|
@@ -21402,7 +21673,7 @@ function setupNodeExecutable(executable = process.execPath) {
|
|
|
21402
21673
|
// ../../node_modules/aiterm-steer-delivery/dist/codex-setup.js
|
|
21403
21674
|
import * as fs8 from "node:fs";
|
|
21404
21675
|
import * as path11 from "node:path";
|
|
21405
|
-
import { isDeepStrictEqual } from "node:util";
|
|
21676
|
+
import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
|
|
21406
21677
|
function codexHookCommand(node2, hook, directory2, platform = process.platform, powershell = () => resolveWindowsPowerShell7()) {
|
|
21407
21678
|
if (platform === "win32") {
|
|
21408
21679
|
const script = `& ${[node2, hook, directory2].map(quotePowerShell).join(" ")}; exit $LASTEXITCODE`;
|
|
@@ -21472,7 +21743,7 @@ function planCodexParentHooks(file2, command2, previousCommand) {
|
|
|
21472
21743
|
delete hooks[event];
|
|
21473
21744
|
}
|
|
21474
21745
|
const next = { ...current, hooks };
|
|
21475
|
-
return { target, current, next, changed: !
|
|
21746
|
+
return { target, current, next, changed: !isDeepStrictEqual2(current, next), moves, owned: ownedAt };
|
|
21476
21747
|
}
|
|
21477
21748
|
function writeCodexHookPlan(profile, plan) {
|
|
21478
21749
|
if (!plan.changed)
|
|
@@ -21480,7 +21751,7 @@ function writeCodexHookPlan(profile, plan) {
|
|
|
21480
21751
|
if (fs8.existsSync(plan.target))
|
|
21481
21752
|
fs8.copyFileSync(plan.target, `${plan.target}${profile.backup_suffix}`);
|
|
21482
21753
|
writeHookJson(plan.target, plan.next);
|
|
21483
|
-
if (!
|
|
21754
|
+
if (!isDeepStrictEqual2(JSON.parse(fs8.readFileSync(plan.target, "utf8")), plan.next))
|
|
21484
21755
|
throw new SetupError("codex_hook_readback_failed", "Codex hook\u306E\u8AAD\u623B\u3057\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093");
|
|
21485
21756
|
return true;
|
|
21486
21757
|
}
|
|
@@ -21676,222 +21947,6 @@ async function configureCodexSteer(profile, action = "status", overrides) {
|
|
|
21676
21947
|
return needsRestart(config2) ? { status: "restart_required", reason_code: "codex_restart_required" } : { status: "ready" };
|
|
21677
21948
|
}
|
|
21678
21949
|
|
|
21679
|
-
// ../../node_modules/aiterm-steer-delivery/dist/hook-setup.js
|
|
21680
|
-
import { copyFileSync as copyFileSync2, existsSync as existsSync9, lstatSync as lstatSync2, mkdirSync as mkdirSync7, readFileSync as readFileSync8, realpathSync as realpathSync4, renameSync as renameSync3, unlinkSync as unlinkSync4, writeFileSync as writeFileSync5 } from "node:fs";
|
|
21681
|
-
import { dirname as dirname4 } from "node:path";
|
|
21682
|
-
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
21683
|
-
import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
|
|
21684
|
-
var record2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21685
|
-
function endsWithFile(value, file2) {
|
|
21686
|
-
return value === file2 || value.endsWith(`/${file2}`) || value.endsWith(`\\${file2}`);
|
|
21687
|
-
}
|
|
21688
|
-
function claudeParentHookEntries(profile, hook) {
|
|
21689
|
-
const command2 = { type: "command", command: hook.command, args: [hook.script] };
|
|
21690
|
-
const matcher = `^mcp__${profile.mcp_server}__(${profile.dispatch_tools.join("|")})$`;
|
|
21691
|
-
return {
|
|
21692
|
-
PreToolUse: [{ matcher, hooks: [{ ...command2, timeout: 15 }] }],
|
|
21693
|
-
PostToolUse: [{ matcher, hooks: [{ ...command2, asyncRewake: true, timeout: 86400 }] }],
|
|
21694
|
-
// 長く続く受信(channel)では、turnが終わるたびに待機を張り直す。
|
|
21695
|
-
...profile.channels ? { Stop: [{ hooks: [{ ...command2, asyncRewake: true, timeout: 86400 }] }] } : {},
|
|
21696
|
-
SessionEnd: [{ hooks: [{ ...command2, timeout: 15 }] }]
|
|
21697
|
-
};
|
|
21698
|
-
}
|
|
21699
|
-
function mergeClaudeParentHooks(profile, file2, hook) {
|
|
21700
|
-
const target = existsSync9(file2) ? realpathSync4(file2) : file2;
|
|
21701
|
-
let current = {};
|
|
21702
|
-
if (existsSync9(target)) {
|
|
21703
|
-
try {
|
|
21704
|
-
current = JSON.parse(readFileSync8(target, "utf8"));
|
|
21705
|
-
} catch {
|
|
21706
|
-
throw new SetupError("config_invalid", "Claude\u306Ehook\u8A2D\u5B9AJSON\u3092\u8AAD\u3081\u307E\u305B\u3093");
|
|
21707
|
-
}
|
|
21708
|
-
}
|
|
21709
|
-
if (!record2(current) || current.hooks !== void 0 && !record2(current.hooks)) {
|
|
21710
|
-
throw new SetupError("config_invalid", "Claude\u306Ehooks\u8A2D\u5B9A\u306Fobject\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059");
|
|
21711
|
-
}
|
|
21712
|
-
if (current.disableAllHooks === true)
|
|
21713
|
-
throw new SetupError("claude_parent_hooks_disabled", "Claude\u306Ehook\u304C\u7121\u52B9\u3067\u3059\u3002disableAllHooks\u3092false\u306B\u5909\u66F4\u3057\u3066\u304B\u3089setup\u3057\u3066\u304F\u3060\u3055\u3044");
|
|
21714
|
-
const hooks = { ...current.hooks };
|
|
21715
|
-
for (const [event, additions] of Object.entries(claudeParentHookEntries(profile, hook))) {
|
|
21716
|
-
const previous = hooks[event] ?? [];
|
|
21717
|
-
if (!Array.isArray(previous) || previous.some((group) => !record2(group) || !Array.isArray(group.hooks))) {
|
|
21718
|
-
throw new SetupError("config_invalid", `Claude\u306E${event} hook\u5F62\u5F0F\u3092\u8AAD\u3081\u307E\u305B\u3093`);
|
|
21719
|
-
}
|
|
21720
|
-
const retained = previous.map((group) => ({
|
|
21721
|
-
...group,
|
|
21722
|
-
hooks: group.hooks.filter((entry) => !isClaudeParentHook(profile, entry))
|
|
21723
|
-
})).filter((group) => group.hooks.length > 0);
|
|
21724
|
-
hooks[event] = [...retained, ...additions];
|
|
21725
|
-
}
|
|
21726
|
-
const next = { ...current, hooks };
|
|
21727
|
-
if (isDeepStrictEqual2(current, next))
|
|
21728
|
-
return "unchanged";
|
|
21729
|
-
mkdirSync7(dirname4(target), { recursive: true });
|
|
21730
|
-
const temporary = `${target}.${profile.id}-${randomUUID3()}`;
|
|
21731
|
-
try {
|
|
21732
|
-
writeFileSync5(temporary, `${JSON.stringify(next, null, 2)}
|
|
21733
|
-
`, { mode: 384, flag: "wx" });
|
|
21734
|
-
if (existsSync9(target))
|
|
21735
|
-
copyFileSync2(target, `${target}${profile.backup_suffix}`);
|
|
21736
|
-
renameSync3(temporary, target);
|
|
21737
|
-
} finally {
|
|
21738
|
-
if (existsSync9(temporary))
|
|
21739
|
-
unlinkSync4(temporary);
|
|
21740
|
-
}
|
|
21741
|
-
if (!isDeepStrictEqual2(JSON.parse(readFileSync8(target, "utf8")), next)) {
|
|
21742
|
-
throw new SetupError("config_readback_failed", "Claude\u306Ehook\u767B\u9332\u306E\u8AAD\u623B\u3057\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093");
|
|
21743
|
-
}
|
|
21744
|
-
return "configured";
|
|
21745
|
-
}
|
|
21746
|
-
function isClaudeParentHook(profile, hook) {
|
|
21747
|
-
return record2(hook) && hook.type === "command" && Array.isArray(hook.args) && typeof hook.args[0] === "string" && endsWithFile(hook.args[0], profile.hooks.claude);
|
|
21748
|
-
}
|
|
21749
|
-
function removeClaudeParentHooks(profile, file2) {
|
|
21750
|
-
if (!existsSync9(file2))
|
|
21751
|
-
return "unchanged";
|
|
21752
|
-
const target = realpathSync4(file2);
|
|
21753
|
-
const current = JSON.parse(readFileSync8(target, "utf8"));
|
|
21754
|
-
if (!record2(current) || current.hooks !== void 0 && !record2(current.hooks)) {
|
|
21755
|
-
throw new SetupError("config_invalid", "Claude\u306Ehook\u8A2D\u5B9A\u3092\u8AAD\u3081\u307E\u305B\u3093");
|
|
21756
|
-
}
|
|
21757
|
-
if (current.hooks === void 0)
|
|
21758
|
-
return "unchanged";
|
|
21759
|
-
const hooks = { ...current.hooks };
|
|
21760
|
-
for (const event of ["PreToolUse", "PostToolUse", "Stop", "SessionEnd"]) {
|
|
21761
|
-
if (hooks[event] === void 0)
|
|
21762
|
-
continue;
|
|
21763
|
-
if (!Array.isArray(hooks[event]))
|
|
21764
|
-
throw new SetupError("config_invalid", "Claude\u306Ehook\u8A2D\u5B9A\u3092\u8AAD\u3081\u307E\u305B\u3093");
|
|
21765
|
-
hooks[event] = hooks[event].map((group) => {
|
|
21766
|
-
if (!record2(group) || !Array.isArray(group.hooks))
|
|
21767
|
-
throw new SetupError("config_invalid", "Claude\u306Ehook\u8A2D\u5B9A\u3092\u8AAD\u3081\u307E\u305B\u3093");
|
|
21768
|
-
return { ...group, hooks: group.hooks.filter((entry) => !isClaudeParentHook(profile, entry)) };
|
|
21769
|
-
}).filter((group) => group.hooks.length > 0);
|
|
21770
|
-
}
|
|
21771
|
-
const next = { ...current, hooks };
|
|
21772
|
-
if (isDeepStrictEqual2(current, next))
|
|
21773
|
-
return "unchanged";
|
|
21774
|
-
const temporary = `${target}.${profile.id}-${randomUUID3()}`;
|
|
21775
|
-
try {
|
|
21776
|
-
writeFileSync5(temporary, `${JSON.stringify(next, null, 2)}
|
|
21777
|
-
`, { mode: 384, flag: "wx" });
|
|
21778
|
-
copyFileSync2(target, `${target}${profile.backup_suffix}`);
|
|
21779
|
-
renameSync3(temporary, target);
|
|
21780
|
-
} finally {
|
|
21781
|
-
if (existsSync9(temporary))
|
|
21782
|
-
unlinkSync4(temporary);
|
|
21783
|
-
}
|
|
21784
|
-
if (!isDeepStrictEqual2(JSON.parse(readFileSync8(target, "utf8")), next))
|
|
21785
|
-
throw new SetupError("config_readback_failed", "Claude hook\u89E3\u9664\u306E\u8AAD\u623B\u3057\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093");
|
|
21786
|
-
return "removed";
|
|
21787
|
-
}
|
|
21788
|
-
function shellQuote(value) {
|
|
21789
|
-
if (process.platform === "win32")
|
|
21790
|
-
return `'${value.replace(/'/g, "''")}'`;
|
|
21791
|
-
return `'${value.replace(/'/g, `'"'"'`)}'`;
|
|
21792
|
-
}
|
|
21793
|
-
function cursorParentHookCommand(hook) {
|
|
21794
|
-
const command2 = `${shellQuote(hook.command)} ${shellQuote(hook.script)}`;
|
|
21795
|
-
return process.platform === "win32" ? `& ${command2}` : command2;
|
|
21796
|
-
}
|
|
21797
|
-
function ownsCursorParentHook(profile, hook) {
|
|
21798
|
-
return record2(hook) && typeof hook.command === "string" && hook.command.includes(profile.hooks.cursor);
|
|
21799
|
-
}
|
|
21800
|
-
function mergeCursorParentHooks(profile, file2, hook) {
|
|
21801
|
-
const target = existsSync9(file2) ? realpathSync4(file2) : file2;
|
|
21802
|
-
let current = { version: 1, hooks: {} };
|
|
21803
|
-
if (existsSync9(target)) {
|
|
21804
|
-
try {
|
|
21805
|
-
current = JSON.parse(readFileSync8(target, "utf8"));
|
|
21806
|
-
} catch {
|
|
21807
|
-
throw new SetupError("config_invalid", "Cursor\u306Ehook\u8A2D\u5B9AJSON\u3092\u8AAD\u3081\u307E\u305B\u3093");
|
|
21808
|
-
}
|
|
21809
|
-
} else {
|
|
21810
|
-
try {
|
|
21811
|
-
if (lstatSync2(file2).isSymbolicLink())
|
|
21812
|
-
throw new SetupError("config_invalid", "Cursor\u306Ehooks\u8A2D\u5B9Asymlink\u306E\u53C2\u7167\u5148\u304C\u3042\u308A\u307E\u305B\u3093");
|
|
21813
|
-
} catch (error62) {
|
|
21814
|
-
if (error62.code !== "ENOENT")
|
|
21815
|
-
throw error62;
|
|
21816
|
-
}
|
|
21817
|
-
}
|
|
21818
|
-
if (!record2(current) || current.hooks !== void 0 && !record2(current.hooks)) {
|
|
21819
|
-
throw new SetupError("config_invalid", "Cursor\u306Ehooks\u8A2D\u5B9A\u306Fobject\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059");
|
|
21820
|
-
}
|
|
21821
|
-
const hooks = { ...current.hooks };
|
|
21822
|
-
const entry = { command: cursorParentHookCommand(hook), timeout: 15 };
|
|
21823
|
-
for (const event of ["afterMCPExecution", "postToolUse"]) {
|
|
21824
|
-
const previous = hooks[event] ?? [];
|
|
21825
|
-
if (!Array.isArray(previous))
|
|
21826
|
-
throw new SetupError("config_invalid", `Cursor\u306E${event} hook\u5F62\u5F0F\u3092\u8AAD\u3081\u307E\u305B\u3093`);
|
|
21827
|
-
const retained = previous.filter((hook2) => !ownsCursorParentHook(profile, hook2));
|
|
21828
|
-
const owned = previous.filter((hook2) => ownsCursorParentHook(profile, hook2));
|
|
21829
|
-
if (owned.length === 1 && isDeepStrictEqual2(owned[0], entry) && retained.length + 1 === previous.length)
|
|
21830
|
-
continue;
|
|
21831
|
-
const index = previous.findIndex((hook2) => ownsCursorParentHook(profile, hook2));
|
|
21832
|
-
hooks[event] = index < 0 ? [...retained, entry] : previous.map((hook2, i) => i === index ? entry : hook2).filter((hook2, i) => i === index || !ownsCursorParentHook(profile, hook2));
|
|
21833
|
-
}
|
|
21834
|
-
const next = { ...current, version: current.version ?? 1, hooks };
|
|
21835
|
-
if (isDeepStrictEqual2(current, next))
|
|
21836
|
-
return "unchanged";
|
|
21837
|
-
mkdirSync7(dirname4(target), { recursive: true });
|
|
21838
|
-
const temporary = `${target}.${profile.id}-${randomUUID3()}`;
|
|
21839
|
-
try {
|
|
21840
|
-
writeFileSync5(temporary, `${JSON.stringify(next, null, 2)}
|
|
21841
|
-
`, { mode: 384, flag: "wx" });
|
|
21842
|
-
if (existsSync9(target))
|
|
21843
|
-
copyFileSync2(target, `${target}${profile.backup_suffix}`);
|
|
21844
|
-
renameSync3(temporary, target);
|
|
21845
|
-
} finally {
|
|
21846
|
-
if (existsSync9(temporary))
|
|
21847
|
-
unlinkSync4(temporary);
|
|
21848
|
-
}
|
|
21849
|
-
if (!isDeepStrictEqual2(JSON.parse(readFileSync8(target, "utf8")), next)) {
|
|
21850
|
-
throw new SetupError("config_readback_failed", "Cursor\u306Ehook\u767B\u9332\u306E\u8AAD\u623B\u3057\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093");
|
|
21851
|
-
}
|
|
21852
|
-
return "configured";
|
|
21853
|
-
}
|
|
21854
|
-
function removeCursorParentHooks(profile, file2) {
|
|
21855
|
-
if (!existsSync9(file2))
|
|
21856
|
-
return "unchanged";
|
|
21857
|
-
const target = realpathSync4(file2);
|
|
21858
|
-
const current = JSON.parse(readFileSync8(target, "utf8"));
|
|
21859
|
-
if (!record2(current) || current.hooks !== void 0 && !record2(current.hooks)) {
|
|
21860
|
-
throw new SetupError("config_invalid", "Cursor\u306Ehook\u8A2D\u5B9A\u3092\u8AAD\u3081\u307E\u305B\u3093");
|
|
21861
|
-
}
|
|
21862
|
-
if (current.hooks === void 0)
|
|
21863
|
-
return "unchanged";
|
|
21864
|
-
const hooks = { ...current.hooks };
|
|
21865
|
-
for (const event of ["afterMCPExecution", "postToolUse"]) {
|
|
21866
|
-
if (hooks[event] === void 0)
|
|
21867
|
-
continue;
|
|
21868
|
-
if (!Array.isArray(hooks[event]))
|
|
21869
|
-
throw new SetupError("config_invalid", "Cursor\u306Ehook\u8A2D\u5B9A\u3092\u8AAD\u3081\u307E\u305B\u3093");
|
|
21870
|
-
const retained = hooks[event].filter((hook) => !ownsCursorParentHook(profile, hook));
|
|
21871
|
-
if (retained.length)
|
|
21872
|
-
hooks[event] = retained;
|
|
21873
|
-
else
|
|
21874
|
-
delete hooks[event];
|
|
21875
|
-
}
|
|
21876
|
-
const next = { ...current, hooks };
|
|
21877
|
-
if (isDeepStrictEqual2(current, next))
|
|
21878
|
-
return "unchanged";
|
|
21879
|
-
const temporary = `${target}.${profile.id}-${randomUUID3()}`;
|
|
21880
|
-
try {
|
|
21881
|
-
writeFileSync5(temporary, `${JSON.stringify(next, null, 2)}
|
|
21882
|
-
`, { mode: 384, flag: "wx" });
|
|
21883
|
-
copyFileSync2(target, `${target}${profile.backup_suffix}`);
|
|
21884
|
-
renameSync3(temporary, target);
|
|
21885
|
-
} finally {
|
|
21886
|
-
if (existsSync9(temporary))
|
|
21887
|
-
unlinkSync4(temporary);
|
|
21888
|
-
}
|
|
21889
|
-
if (!isDeepStrictEqual2(JSON.parse(readFileSync8(target, "utf8")), next)) {
|
|
21890
|
-
throw new SetupError("config_readback_failed", "Cursor hook\u89E3\u9664\u306E\u8AAD\u623B\u3057\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093");
|
|
21891
|
-
}
|
|
21892
|
-
return "removed";
|
|
21893
|
-
}
|
|
21894
|
-
|
|
21895
21950
|
export {
|
|
21896
21951
|
__require,
|
|
21897
21952
|
__commonJS,
|
|
@@ -21929,16 +21984,17 @@ export {
|
|
|
21929
21984
|
verifyCodexParent,
|
|
21930
21985
|
configureCodexSteer,
|
|
21931
21986
|
claudeParentFromRequest,
|
|
21932
|
-
isCursorMcpClient,
|
|
21933
|
-
cursorParentHooksRegistered,
|
|
21934
|
-
verifyCursorParent,
|
|
21935
|
-
handleCursorHook,
|
|
21936
|
-
waitProcessCommandLine,
|
|
21937
21987
|
mergeClaudeParentHooks,
|
|
21988
|
+
claudeParentHooksRegistered,
|
|
21938
21989
|
removeClaudeParentHooks,
|
|
21939
21990
|
cursorParentHookCommand,
|
|
21940
21991
|
mergeCursorParentHooks,
|
|
21941
21992
|
removeCursorParentHooks,
|
|
21993
|
+
isCursorMcpClient,
|
|
21994
|
+
cursorParentHooksRegistered,
|
|
21995
|
+
verifyCursorParent,
|
|
21996
|
+
handleCursorHook,
|
|
21997
|
+
waitProcessCommandLine,
|
|
21942
21998
|
openChannel,
|
|
21943
21999
|
readChannel,
|
|
21944
22000
|
channelClosed,
|
package/dist/cli.mjs
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
channelReceiveProcess,
|
|
18
18
|
claudeHookRoot,
|
|
19
19
|
claudeParentFromRequest,
|
|
20
|
+
claudeParentHooksRegistered,
|
|
20
21
|
codexParentFromRequest,
|
|
21
22
|
configureCodexSteer,
|
|
22
23
|
cursorHookRoot,
|
|
@@ -53,7 +54,7 @@ import {
|
|
|
53
54
|
waitProcessCommandLine,
|
|
54
55
|
withCodexReceiver,
|
|
55
56
|
withdrawFromChannel
|
|
56
|
-
} from "./chunks/chunk-
|
|
57
|
+
} from "./chunks/chunk-GH2JG56Y.mjs";
|
|
57
58
|
|
|
58
59
|
// ../../node_modules/qrcode/lib/can-promise.js
|
|
59
60
|
var require_can_promise = __commonJS({
|
|
@@ -12407,9 +12408,9 @@ function registeredTools(target) {
|
|
|
12407
12408
|
const entryOf = (value) => (value?.args ?? [])[0];
|
|
12408
12409
|
if (target === "claude") {
|
|
12409
12410
|
const entry = readJson(claudeJson()).mcpServers?.[MCP_SERVER];
|
|
12410
|
-
const settings =
|
|
12411
|
+
const settings = readJson(join6(claudeDir(), "settings.json"));
|
|
12411
12412
|
const e = entryOf(entry);
|
|
12412
|
-
return { mcp: !!entry, hooks:
|
|
12413
|
+
return { mcp: !!entry, hooks: claudeParentHooksRegistered(PROFILE, settings), ...e ? { entry: e } : {} };
|
|
12413
12414
|
}
|
|
12414
12415
|
if (target === "cursor") {
|
|
12415
12416
|
const entry = readJson(join6(cursorDir(), "mcp.json")).mcpServers?.[MCP_SERVER];
|
|
@@ -15788,7 +15789,7 @@ import { existsSync as existsSync6, readFileSync as readFileSync6 } from "node:f
|
|
|
15788
15789
|
import { basename as basename2, join as join7 } from "node:path";
|
|
15789
15790
|
|
|
15790
15791
|
// src/version.ts
|
|
15791
|
-
var VERSION = true ? "0.1.
|
|
15792
|
+
var VERSION = true ? "0.1.14" : "0.0.0-dev";
|
|
15792
15793
|
function osName() {
|
|
15793
15794
|
return process.platform === "darwin" ? "macos" : process.platform === "win32" ? "windows" : process.platform;
|
|
15794
15795
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "approval-box",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
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",
|
|
@@ -28,14 +28,13 @@
|
|
|
28
28
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
29
29
|
"test": "node --test 'test/**/*.test.ts'"
|
|
30
30
|
},
|
|
31
|
-
"dependencies": {},
|
|
32
31
|
"devDependencies": {
|
|
33
32
|
"@modelcontextprotocol/sdk": "^1.31.0",
|
|
34
33
|
"@types/node": "^25.9.1",
|
|
35
|
-
"
|
|
34
|
+
"@types/qrcode": "^1.5.5",
|
|
35
|
+
"aiterm-steer-delivery": "^0.2.0",
|
|
36
36
|
"esbuild": "^0.28.2",
|
|
37
37
|
"qrcode": "^1.5.4",
|
|
38
|
-
"@types/qrcode": "^1.5.5",
|
|
39
38
|
"typescript": "^6.0.3",
|
|
40
39
|
"zod": "^4.4.3"
|
|
41
40
|
},
|