approval-box 0.1.15 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +103 -78
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -4437,10 +4437,10 @@ var require_browser = __commonJS({
|
|
|
4437
4437
|
text2 = canvas;
|
|
4438
4438
|
canvas = void 0;
|
|
4439
4439
|
}
|
|
4440
|
-
return new Promise(function(
|
|
4440
|
+
return new Promise(function(resolve3, reject) {
|
|
4441
4441
|
try {
|
|
4442
4442
|
const data = QRCode2.create(text2, opts);
|
|
4443
|
-
|
|
4443
|
+
resolve3(renderFunc(data, canvas, opts));
|
|
4444
4444
|
} catch (e) {
|
|
4445
4445
|
reject(e);
|
|
4446
4446
|
}
|
|
@@ -4521,11 +4521,11 @@ var require_server = __commonJS({
|
|
|
4521
4521
|
}
|
|
4522
4522
|
function render(renderFunc, text2, params) {
|
|
4523
4523
|
if (!params.cb) {
|
|
4524
|
-
return new Promise(function(
|
|
4524
|
+
return new Promise(function(resolve3, reject) {
|
|
4525
4525
|
try {
|
|
4526
4526
|
const data = QRCode2.create(text2, params.opts);
|
|
4527
4527
|
return renderFunc(data, params.opts, function(err, data2) {
|
|
4528
|
-
return err ? reject(err) :
|
|
4528
|
+
return err ? reject(err) : resolve3(data2);
|
|
4529
4529
|
});
|
|
4530
4530
|
} catch (e) {
|
|
4531
4531
|
reject(e);
|
|
@@ -7540,7 +7540,7 @@ var require_compile = __commonJS({
|
|
|
7540
7540
|
const schOrFunc = root.refs[ref];
|
|
7541
7541
|
if (schOrFunc)
|
|
7542
7542
|
return schOrFunc;
|
|
7543
|
-
let _sch =
|
|
7543
|
+
let _sch = resolve3.call(this, root, ref);
|
|
7544
7544
|
if (_sch === void 0) {
|
|
7545
7545
|
const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
7546
7546
|
const { schemaId } = this.opts;
|
|
@@ -7567,7 +7567,7 @@ var require_compile = __commonJS({
|
|
|
7567
7567
|
function sameSchemaEnv(s1, s2) {
|
|
7568
7568
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
7569
7569
|
}
|
|
7570
|
-
function
|
|
7570
|
+
function resolve3(root, ref) {
|
|
7571
7571
|
let sch;
|
|
7572
7572
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
7573
7573
|
ref = sch;
|
|
@@ -8397,7 +8397,7 @@ var require_fast_uri = __commonJS({
|
|
|
8397
8397
|
}
|
|
8398
8398
|
return uri;
|
|
8399
8399
|
}
|
|
8400
|
-
function
|
|
8400
|
+
function resolve3(baseURI, relativeURI, options) {
|
|
8401
8401
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
8402
8402
|
const {
|
|
8403
8403
|
parsed: baseParsed,
|
|
@@ -8766,7 +8766,7 @@ var require_fast_uri = __commonJS({
|
|
|
8766
8766
|
var fastUri = {
|
|
8767
8767
|
SCHEMES,
|
|
8768
8768
|
normalize,
|
|
8769
|
-
resolve:
|
|
8769
|
+
resolve: resolve3,
|
|
8770
8770
|
resolveComponent,
|
|
8771
8771
|
equal,
|
|
8772
8772
|
serialize,
|
|
@@ -11759,7 +11759,7 @@ var require_dist = __commonJS({
|
|
|
11759
11759
|
var import_qrcode = __toESM(require_lib(), 1);
|
|
11760
11760
|
import { cpSync, existsSync as existsSync7, mkdirSync as mkdirSync5, rmSync as rmSync3 } from "node:fs";
|
|
11761
11761
|
import { hostname } from "node:os";
|
|
11762
|
-
import { join as
|
|
11762
|
+
import { join as join9 } from "node:path";
|
|
11763
11763
|
import { createInterface } from "node:readline/promises";
|
|
11764
11764
|
|
|
11765
11765
|
// src/api.ts
|
|
@@ -11868,24 +11868,50 @@ function writeConfig(config) {
|
|
|
11868
11868
|
writeJsonFile(configFile(), config);
|
|
11869
11869
|
}
|
|
11870
11870
|
|
|
11871
|
+
// src/daemon-launch.ts
|
|
11872
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
11873
|
+
import { closeSync, openSync } from "node:fs";
|
|
11874
|
+
import { join as join2, resolve } from "node:path";
|
|
11875
|
+
function windowsDaemonLaunchScript(executable, entry, cwd, environment) {
|
|
11876
|
+
const env = Object.fromEntries(["APPROVAL_BOX_HOME", "HOME", "USERPROFILE", "APPDATA", "LOCALAPPDATA", "PATH", "CODEX_HOME", "GROK_HOME", "CODEX_BIN"].flatMap((key) => environment[key] === void 0 ? [] : [[key, environment[key]]]));
|
|
11877
|
+
const bootstrap = `Object.assign(process.env,${JSON.stringify(env)});const fs=require('node:fs');process.stderr.write=(text)=>{fs.appendFileSync(${JSON.stringify(join2(cwd, "daemon.log"))},text);return true;};process.argv=[process.execPath,${JSON.stringify(entry)},'daemon'];import(require('node:url').pathToFileURL(${JSON.stringify(entry)}).href).catch(error=>{process.stderr.write(String(error)+'\\n');process.exit(1);});`;
|
|
11878
|
+
const command2 = `"${executable}" -e "eval(Buffer.from('${Buffer.from(bootstrap).toString("base64")}','base64').toString())"`;
|
|
11879
|
+
const literal2 = (s) => `'${s.replaceAll("'", "''")}'`;
|
|
11880
|
+
return `$ErrorActionPreference='Stop';$ProgressPreference='SilentlyContinue';$startup=New-CimInstance -ClassName Win32_ProcessStartup -ClientOnly -Property @{ShowWindow=[uint16]0};$result=Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{CommandLine=${literal2(command2)};CurrentDirectory=${literal2(cwd)};ProcessStartupInformation=$startup};if($result.ReturnValue -ne 0){throw ('daemon creation failed: '+$result.ReturnValue)};$result.ProcessId`;
|
|
11881
|
+
}
|
|
11882
|
+
function launchDaemon(executable, entry, cwd) {
|
|
11883
|
+
if (process.platform === "win32") {
|
|
11884
|
+
const script = windowsDaemonLaunchScript(executable, entry, cwd, { ...process.env, APPROVAL_BOX_HOME: resolve(home()) });
|
|
11885
|
+
const result = spawnSync("pwsh.exe", ["-NoProfile", "-NonInteractive", "-EncodedCommand", Buffer.from(script, "utf16le").toString("base64")], { cwd, windowsHide: true, encoding: "utf8", timeout: 15e3 });
|
|
11886
|
+
if (result.error?.code === "ENOENT") throw new Error("PowerShell 7\uFF08pwsh.exe\uFF09\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u6A19\u6E96PATH\u306BPowerShell 7\u3092\u5C0E\u5165\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
11887
|
+
if (result.error || result.status !== 0 || !/^\s*\d+\s*$/.test(result.stdout ?? "")) throw new Error(`Windows\u306E\u5E38\u99D0\u8D77\u52D5\u306B\u5931\u6557\u3057\u307E\u3057\u305F\uFF08${result.error?.message ?? `exit ${result.status}`}\uFF09`);
|
|
11888
|
+
return;
|
|
11889
|
+
}
|
|
11890
|
+
const log = openSync(join2(cwd, "daemon.log"), "a", 384);
|
|
11891
|
+
try {
|
|
11892
|
+
spawn(executable, [entry, "daemon"], { cwd, detached: true, stdio: ["ignore", "ignore", log], windowsHide: true }).unref();
|
|
11893
|
+
} finally {
|
|
11894
|
+
closeSync(log);
|
|
11895
|
+
}
|
|
11896
|
+
}
|
|
11897
|
+
|
|
11871
11898
|
// src/daemon.ts
|
|
11872
|
-
import {
|
|
11873
|
-
import {
|
|
11874
|
-
import { join as join4 } from "node:path";
|
|
11899
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, rmSync as rmSync2 } from "node:fs";
|
|
11900
|
+
import { join as join5 } from "node:path";
|
|
11875
11901
|
|
|
11876
11902
|
// src/attachments.ts
|
|
11877
11903
|
import { createHash } from "node:crypto";
|
|
11878
11904
|
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync2, rmSync, statSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
11879
|
-
import { join as
|
|
11905
|
+
import { join as join3 } from "node:path";
|
|
11880
11906
|
var KEEP_DAYS = 30;
|
|
11881
|
-
var attachmentsRoot = () =>
|
|
11907
|
+
var attachmentsRoot = () => join3(home(), "attachments");
|
|
11882
11908
|
function safeFileName(name) {
|
|
11883
11909
|
const cleaned = name.replace(/[<>:"/\\|?*\u0000-\u001f]/g, "_").replace(/[. ]+$/, "").trim();
|
|
11884
11910
|
return cleaned.slice(0, 150) || "file";
|
|
11885
11911
|
}
|
|
11886
11912
|
async function saveAttachment(api, decisionId, meta, index) {
|
|
11887
|
-
const dir =
|
|
11888
|
-
const file =
|
|
11913
|
+
const dir = join3(attachmentsRoot(), safeFileName(decisionId));
|
|
11914
|
+
const file = join3(dir, `${index + 1}_${safeFileName(meta.name)}`);
|
|
11889
11915
|
if (existsSync2(file) && sha256(readFileSync2(file)) === meta.sha256) return file;
|
|
11890
11916
|
const data = await api.download(`/decisions/${encodeURIComponent(decisionId)}/attachments/${encodeURIComponent(meta.id)}`);
|
|
11891
11917
|
if (sha256(data) !== meta.sha256) throw new Error(`${meta.name} \u306E\u4E2D\u8EAB\u304C\u30B5\u30FC\u30D0\u30FC\u306E\u8A18\u9332\u3068\u5408\u3044\u307E\u305B\u3093\uFF08\u53D6\u308A\u76F4\u3057\u3066\u304F\u3060\u3055\u3044\uFF09`);
|
|
@@ -11909,7 +11935,7 @@ function pruneAttachments() {
|
|
|
11909
11935
|
if (!existsSync2(root)) return;
|
|
11910
11936
|
const before = Date.now() - KEEP_DAYS * 864e5;
|
|
11911
11937
|
for (const name of readdirSync(root)) {
|
|
11912
|
-
const dir =
|
|
11938
|
+
const dir = join3(root, name);
|
|
11913
11939
|
try {
|
|
11914
11940
|
if (statSync(dir).mtimeMs < before) rmSync(dir, { recursive: true, force: true });
|
|
11915
11941
|
} catch {
|
|
@@ -11919,19 +11945,19 @@ function pruneAttachments() {
|
|
|
11919
11945
|
var sha256 = (data) => createHash("sha256").update(data).digest("hex");
|
|
11920
11946
|
|
|
11921
11947
|
// src/runtime.ts
|
|
11922
|
-
import { basename, dirname as dirname2, join as
|
|
11948
|
+
import { basename, dirname as dirname2, join as join4 } from "node:path";
|
|
11923
11949
|
import { fileURLToPath } from "node:url";
|
|
11924
11950
|
var runtimeDir = () => {
|
|
11925
11951
|
const dir = dirname2(fileURLToPath(import.meta.url));
|
|
11926
11952
|
return basename(dir) === "chunks" ? dirname2(dir) : dir;
|
|
11927
11953
|
};
|
|
11928
11954
|
function runtimeEntry(kind) {
|
|
11929
|
-
return
|
|
11955
|
+
return join4(runtimeDir(), kind === "cli" ? "cli.mjs" : HOOK_FILES[kind]);
|
|
11930
11956
|
}
|
|
11931
11957
|
|
|
11932
11958
|
// src/daemon.ts
|
|
11933
|
-
var lockFile = () =>
|
|
11934
|
-
var journalFile = () =>
|
|
11959
|
+
var lockFile = () => join5(stateRoot(), "daemon.json");
|
|
11960
|
+
var journalFile = () => join5(stateRoot(), "deliveries.json");
|
|
11935
11961
|
var IDLE_EXIT_MS = 30 * 6e4;
|
|
11936
11962
|
function alive(pid) {
|
|
11937
11963
|
try {
|
|
@@ -11974,14 +12000,13 @@ function ensureDaemon() {
|
|
|
11974
12000
|
}
|
|
11975
12001
|
}
|
|
11976
12002
|
mkdirSync3(stateRoot(), { recursive: true, mode: 448 });
|
|
11977
|
-
|
|
11978
|
-
spawn(process.execPath, [runtimeEntry("cli"), "daemon"], { cwd: stateRoot(), detached: true, stdio: ["ignore", "ignore", log], windowsHide: true }).unref();
|
|
12003
|
+
launchDaemon(process.execPath, runtimeEntry("cli"), stateRoot());
|
|
11979
12004
|
} catch (error) {
|
|
11980
12005
|
process.stderr.write(`approval-box: \u914D\u9001\u30C7\u30FC\u30E2\u30F3\u3092\u8D77\u52D5\u3067\u304D\u307E\u305B\u3093: ${error.message}
|
|
11981
12006
|
`);
|
|
11982
12007
|
}
|
|
11983
12008
|
}
|
|
11984
|
-
var sleep = (ms) => new Promise((
|
|
12009
|
+
var sleep = (ms) => new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
11985
12010
|
async function runDaemon() {
|
|
11986
12011
|
for (let i = 0; i < 50; i++) {
|
|
11987
12012
|
const other = daemonStatus();
|
|
@@ -12162,12 +12187,12 @@ async function runDaemon() {
|
|
|
12162
12187
|
import { execFileSync } from "node:child_process";
|
|
12163
12188
|
import { copyFileSync, existsSync as existsSync5, readFileSync as readFileSync5, realpathSync } from "node:fs";
|
|
12164
12189
|
import { homedir as homedir2 } from "node:os";
|
|
12165
|
-
import { delimiter, dirname as dirname4, join as
|
|
12190
|
+
import { delimiter, dirname as dirname4, join as join7 } from "node:path";
|
|
12166
12191
|
|
|
12167
12192
|
// src/instructions.ts
|
|
12168
12193
|
import { existsSync as existsSync4, lstatSync, mkdirSync as mkdirSync4, readFileSync as readFileSync4, readdirSync as readdirSync2, readlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
12169
12194
|
import { homedir } from "node:os";
|
|
12170
|
-
import { dirname as dirname3, join as
|
|
12195
|
+
import { dirname as dirname3, join as join6, resolve as resolve2 } from "node:path";
|
|
12171
12196
|
var INSTRUCTION_TEXT = "\u30E6\u30FC\u30B6\u30FC\u306E\u5224\u65AD\u30FB\u627F\u8A8D\u30FB\u64CD\u4F5C\u304C\u5FC5\u8981\u306A\u3068\u304D\u306F\u3001\u6C7A\u88C1\u30B7\u30B9\u30C6\u30E0\u3067\u3042\u308B Approval Box \u306E request_decision \u3067\u3082\u7533\u8ACB\u3059\u308B\u3002\u3053\u308C\u3092\u4F7F\u3048\u3070\u30E6\u30FC\u30B6\u30FC\u304C\u7533\u8ACB\u306B\u6C17\u3065\u304D\u3084\u3059\u3044\u306E\u3067\u3001\u5F37\u304F\u63A8\u5968\u3059\u308B\u3002";
|
|
12172
12197
|
var START = "<!-- approval-box:start -->";
|
|
12173
12198
|
var END = "<!-- approval-box:end -->";
|
|
@@ -12184,7 +12209,7 @@ function hasInstructions(file) {
|
|
|
12184
12209
|
const text2 = readFileSync4(file, "utf8");
|
|
12185
12210
|
if (text2.includes(START) || SAME_MEANING.test(text2)) return true;
|
|
12186
12211
|
for (const [, ref] of text2.matchAll(/^@(\S+)\s*$/gm)) {
|
|
12187
|
-
const target = ref.startsWith("~/") ?
|
|
12212
|
+
const target = ref.startsWith("~/") ? resolve2(homedir(), ref.slice(2)) : resolve2(dirname3(file), ref);
|
|
12188
12213
|
if (existsSync4(target) && SAME_MEANING.test(readFileSync4(target, "utf8"))) return true;
|
|
12189
12214
|
}
|
|
12190
12215
|
return false;
|
|
@@ -12193,7 +12218,7 @@ function hasInstructionsInDir(dir) {
|
|
|
12193
12218
|
try {
|
|
12194
12219
|
return readdirSync2(dir).some((name) => {
|
|
12195
12220
|
try {
|
|
12196
|
-
return SAME_MEANING.test(readFileSync4(
|
|
12221
|
+
return SAME_MEANING.test(readFileSync4(join6(dir, name), "utf8"));
|
|
12197
12222
|
} catch {
|
|
12198
12223
|
return false;
|
|
12199
12224
|
}
|
|
@@ -12229,27 +12254,27 @@ function removeInstructions(file) {
|
|
|
12229
12254
|
var HARNESSES = ["claude", "codex", "cursor", "grok"];
|
|
12230
12255
|
var LABEL = { claude: "Claude Code", codex: "Codex", cursor: "Cursor", grok: "Grok" };
|
|
12231
12256
|
var CLIENT = { claude: "claude-code", codex: "codex", cursor: "cursor", grok: "grok" };
|
|
12232
|
-
var claudeDir = () => process.env.CLAUDE_CONFIG_DIR ??
|
|
12233
|
-
var claudeJson = () => process.env.CLAUDE_CONFIG_DIR ?
|
|
12234
|
-
var cursorDir = () => process.env.CURSOR_HOME ??
|
|
12235
|
-
var codexHome = () => process.env.CODEX_HOME ??
|
|
12236
|
-
var grokDir = () => process.env.GROK_HOME ??
|
|
12257
|
+
var claudeDir = () => process.env.CLAUDE_CONFIG_DIR ?? join7(homedir2(), ".claude");
|
|
12258
|
+
var claudeJson = () => process.env.CLAUDE_CONFIG_DIR ? join7(process.env.CLAUDE_CONFIG_DIR, ".claude.json") : join7(homedir2(), ".claude.json");
|
|
12259
|
+
var cursorDir = () => process.env.CURSOR_HOME ?? join7(homedir2(), ".cursor");
|
|
12260
|
+
var codexHome = () => process.env.CODEX_HOME ?? join7(homedir2(), ".codex");
|
|
12261
|
+
var grokDir = () => process.env.GROK_HOME ?? join7(homedir2(), ".grok");
|
|
12237
12262
|
function filesOf(target) {
|
|
12238
|
-
if (target === "claude") return [claudeJson(),
|
|
12239
|
-
if (target === "cursor") return [
|
|
12240
|
-
if (target === "codex") return [
|
|
12241
|
-
return [
|
|
12263
|
+
if (target === "claude") return [claudeJson(), join7(claudeDir(), "settings.json")];
|
|
12264
|
+
if (target === "cursor") return [join7(cursorDir(), "mcp.json"), join7(cursorDir(), "hooks.json"), cursorCliConfig()];
|
|
12265
|
+
if (target === "codex") return [join7(codexHome(), "config.toml"), join7(codexHome(), "hooks.json")];
|
|
12266
|
+
return [join7(grokDir(), "config.toml")];
|
|
12242
12267
|
}
|
|
12243
12268
|
function instructionsFileOf(target) {
|
|
12244
|
-
if (target === "claude") return
|
|
12245
|
-
if (target === "codex") return
|
|
12246
|
-
if (target === "grok") return
|
|
12269
|
+
if (target === "claude") return join7(claudeDir(), "CLAUDE.md");
|
|
12270
|
+
if (target === "codex") return join7(codexHome(), "AGENTS.md");
|
|
12271
|
+
if (target === "grok") return join7(grokDir(), "AGENTS.md");
|
|
12247
12272
|
return null;
|
|
12248
12273
|
}
|
|
12249
12274
|
function onPath(command2) {
|
|
12250
12275
|
const names = process.platform === "win32" ? [`${command2}.exe`, `${command2}.cmd`, command2] : [command2];
|
|
12251
12276
|
for (const dir of (process.env.PATH ?? "").split(delimiter)) {
|
|
12252
|
-
for (const name of names) if (dir && existsSync5(
|
|
12277
|
+
for (const name of names) if (dir && existsSync5(join7(dir, name))) return join7(dir, name);
|
|
12253
12278
|
}
|
|
12254
12279
|
return null;
|
|
12255
12280
|
}
|
|
@@ -12267,7 +12292,7 @@ function stableNode() {
|
|
|
12267
12292
|
}
|
|
12268
12293
|
}
|
|
12269
12294
|
var CURSOR_TOOLS = ["list_my_decisions", "request_decision", "amend_decision", "resume_decision", "cancel_decision", "get_decision", "get_attachment", "setup_test", "confirm_setup_test"];
|
|
12270
|
-
var cursorCliConfig = () =>
|
|
12295
|
+
var cursorCliConfig = () => join7(cursorDir(), "cli-config.json");
|
|
12271
12296
|
function setCursorPermissions(enable) {
|
|
12272
12297
|
const file = cursorCliConfig();
|
|
12273
12298
|
if (!existsSync5(file) && !enable) return;
|
|
@@ -12281,7 +12306,7 @@ function setCursorPermissions(enable) {
|
|
|
12281
12306
|
}
|
|
12282
12307
|
var CURSOR_CONTEXT = "cursor-context";
|
|
12283
12308
|
function setCursorContext(enable) {
|
|
12284
|
-
const file =
|
|
12309
|
+
const file = join7(cursorDir(), "hooks.json");
|
|
12285
12310
|
if (!existsSync5(file) && !enable) return;
|
|
12286
12311
|
const target = existsSync5(file) ? realpathSync(file) : file;
|
|
12287
12312
|
backupOnce(target);
|
|
@@ -12294,7 +12319,7 @@ function setCursorContext(enable) {
|
|
|
12294
12319
|
else delete hooks.sessionStart;
|
|
12295
12320
|
writeJsonFile(target, { version: 1, ...current, hooks });
|
|
12296
12321
|
}
|
|
12297
|
-
var cursorContextRegistered = () => JSON.stringify(readJson(
|
|
12322
|
+
var cursorContextRegistered = () => JSON.stringify(readJson(join7(cursorDir(), "hooks.json")).hooks ?? {}).includes(` ${CURSOR_CONTEXT}"`);
|
|
12298
12323
|
var registration = () => ({ command: stableNode(), args: [runtimeEntry("cli"), "mcp"] });
|
|
12299
12324
|
function readJson(file) {
|
|
12300
12325
|
if (!existsSync5(file)) return {};
|
|
@@ -12333,18 +12358,18 @@ async function registerTools(target, options) {
|
|
|
12333
12358
|
try {
|
|
12334
12359
|
if (target === "claude") {
|
|
12335
12360
|
setMcpJson(claudeJson(), { type: "stdio", ...registration() });
|
|
12336
|
-
mergeClaudeParentHooks(PROFILE,
|
|
12361
|
+
mergeClaudeParentHooks(PROFILE, join7(claudeDir(), "settings.json"), hook("claude"));
|
|
12337
12362
|
return { target, status: "registered" };
|
|
12338
12363
|
}
|
|
12339
12364
|
if (target === "cursor") {
|
|
12340
|
-
setMcpJson(
|
|
12341
|
-
mergeCursorParentHooks(PROFILE,
|
|
12365
|
+
setMcpJson(join7(cursorDir(), "mcp.json"), registration());
|
|
12366
|
+
mergeCursorParentHooks(PROFILE, join7(cursorDir(), "hooks.json"), hook("cursor"));
|
|
12342
12367
|
setCursorPermissions(true);
|
|
12343
12368
|
setCursorContext(!!options.instructions);
|
|
12344
12369
|
return { target, status: "registered" };
|
|
12345
12370
|
}
|
|
12346
12371
|
if (target === "codex") {
|
|
12347
|
-
const config =
|
|
12372
|
+
const config = join7(codexHome(), "config.toml");
|
|
12348
12373
|
backupOnce(config);
|
|
12349
12374
|
await withCodexConfig(async (request) => {
|
|
12350
12375
|
await request("config/batchWrite", { filePath: config, edits: [{ keyPath: `mcp_servers.${MCP_SERVER}`, value: { ...registration(), env_vars: ["CODEX_HOME"] }, mergeStrategy: "replace" }] });
|
|
@@ -12360,7 +12385,7 @@ async function registerTools(target, options) {
|
|
|
12360
12385
|
}
|
|
12361
12386
|
const grok = onPath("grok");
|
|
12362
12387
|
if (!grok) throw new Error("grok \u30B3\u30DE\u30F3\u30C9\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093");
|
|
12363
|
-
backupOnce(
|
|
12388
|
+
backupOnce(join7(grokDir(), "config.toml"));
|
|
12364
12389
|
const reg = registration();
|
|
12365
12390
|
execFileSync(grok, ["mcp", "add", MCP_SERVER, "--scope", "user", reg.command, "--", ...reg.args], { stdio: "pipe" });
|
|
12366
12391
|
return { target, status: "registered" };
|
|
@@ -12374,16 +12399,16 @@ async function unregister(target) {
|
|
|
12374
12399
|
if (file) removeInstructions(file);
|
|
12375
12400
|
if (target === "claude") {
|
|
12376
12401
|
if (existsSync5(claudeJson())) setMcpJson(claudeJson(), null);
|
|
12377
|
-
removeClaudeParentHooks(PROFILE,
|
|
12402
|
+
removeClaudeParentHooks(PROFILE, join7(claudeDir(), "settings.json"));
|
|
12378
12403
|
} else if (target === "cursor") {
|
|
12379
|
-
if (existsSync5(
|
|
12380
|
-
removeCursorParentHooks(PROFILE,
|
|
12404
|
+
if (existsSync5(join7(cursorDir(), "mcp.json"))) setMcpJson(join7(cursorDir(), "mcp.json"), null);
|
|
12405
|
+
removeCursorParentHooks(PROFILE, join7(cursorDir(), "hooks.json"));
|
|
12381
12406
|
setCursorPermissions(false);
|
|
12382
12407
|
setCursorContext(false);
|
|
12383
12408
|
} else if (target === "codex") {
|
|
12384
|
-
if (existsSync5(
|
|
12409
|
+
if (existsSync5(join7(codexHome(), "config.toml"))) {
|
|
12385
12410
|
await withCodexConfig(async (request) => {
|
|
12386
|
-
await request("config/batchWrite", { filePath:
|
|
12411
|
+
await request("config/batchWrite", { filePath: join7(codexHome(), "config.toml"), edits: [{ keyPath: `mcp_servers.${MCP_SERVER}`, value: null, mergeStrategy: "replace" }] });
|
|
12387
12412
|
});
|
|
12388
12413
|
}
|
|
12389
12414
|
try {
|
|
@@ -12401,27 +12426,27 @@ async function unregister(target) {
|
|
|
12401
12426
|
}
|
|
12402
12427
|
function registered(target) {
|
|
12403
12428
|
const file = instructionsFileOf(target);
|
|
12404
|
-
const instructions = target === "cursor" ? cursorContextRegistered() || hasInstructions(
|
|
12429
|
+
const instructions = target === "cursor" ? cursorContextRegistered() || hasInstructions(join7(cursorDir(), "AGENTS.md")) || hasInstructionsInDir(join7(cursorDir(), "rules")) : file ? hasInstructions(file) || target === "grok" && hasInstructionsInDir(join7(grokDir(), "rules")) : null;
|
|
12405
12430
|
return { ...registeredTools(target), instructions };
|
|
12406
12431
|
}
|
|
12407
12432
|
function registeredTools(target) {
|
|
12408
12433
|
const entryOf = (value) => (value?.args ?? [])[0];
|
|
12409
12434
|
if (target === "claude") {
|
|
12410
12435
|
const entry = readJson(claudeJson()).mcpServers?.[MCP_SERVER];
|
|
12411
|
-
const settings = readJson(
|
|
12436
|
+
const settings = readJson(join7(claudeDir(), "settings.json"));
|
|
12412
12437
|
const e = entryOf(entry);
|
|
12413
12438
|
return { mcp: !!entry, hooks: claudeParentHooksRegistered(PROFILE, settings), ...e ? { entry: e } : {} };
|
|
12414
12439
|
}
|
|
12415
12440
|
if (target === "cursor") {
|
|
12416
|
-
const entry = readJson(
|
|
12441
|
+
const entry = readJson(join7(cursorDir(), "mcp.json")).mcpServers?.[MCP_SERVER];
|
|
12417
12442
|
const e = entryOf(entry);
|
|
12418
|
-
return { mcp: !!entry, hooks: cursorParentHooksRegistered(PROFILE, readJson(
|
|
12443
|
+
return { mcp: !!entry, hooks: cursorParentHooksRegistered(PROFILE, readJson(join7(cursorDir(), "hooks.json"))), ...e ? { entry: e } : {} };
|
|
12419
12444
|
}
|
|
12420
12445
|
if (target === "codex") {
|
|
12421
|
-
const toml2 = existsSync5(
|
|
12446
|
+
const toml2 = existsSync5(join7(codexHome(), "config.toml")) ? readFileSync5(join7(codexHome(), "config.toml"), "utf8") : "";
|
|
12422
12447
|
return { mcp: toml2.includes(`[mcp_servers.${MCP_SERVER}]`), hooks: null };
|
|
12423
12448
|
}
|
|
12424
|
-
const toml = existsSync5(
|
|
12449
|
+
const toml = existsSync5(join7(grokDir(), "config.toml")) ? readFileSync5(join7(grokDir(), "config.toml"), "utf8") : "";
|
|
12425
12450
|
return { mcp: toml.includes(MCP_SERVER), hooks: null };
|
|
12426
12451
|
}
|
|
12427
12452
|
|
|
@@ -14536,7 +14561,7 @@ var Protocol = class {
|
|
|
14536
14561
|
return;
|
|
14537
14562
|
}
|
|
14538
14563
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
14539
|
-
await new Promise((
|
|
14564
|
+
await new Promise((resolve3) => setTimeout(resolve3, pollInterval));
|
|
14540
14565
|
options?.signal?.throwIfAborted();
|
|
14541
14566
|
}
|
|
14542
14567
|
} catch (error) {
|
|
@@ -14553,7 +14578,7 @@ var Protocol = class {
|
|
|
14553
14578
|
*/
|
|
14554
14579
|
request(request, resultSchema, options) {
|
|
14555
14580
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
14556
|
-
return new Promise((
|
|
14581
|
+
return new Promise((resolve3, reject) => {
|
|
14557
14582
|
const earlyReject = (error) => {
|
|
14558
14583
|
reject(error);
|
|
14559
14584
|
};
|
|
@@ -14631,7 +14656,7 @@ var Protocol = class {
|
|
|
14631
14656
|
if (!parseResult.success) {
|
|
14632
14657
|
reject(parseResult.error);
|
|
14633
14658
|
} else {
|
|
14634
|
-
|
|
14659
|
+
resolve3(parseResult.data);
|
|
14635
14660
|
}
|
|
14636
14661
|
} catch (error) {
|
|
14637
14662
|
reject(error);
|
|
@@ -14892,12 +14917,12 @@ var Protocol = class {
|
|
|
14892
14917
|
}
|
|
14893
14918
|
} catch {
|
|
14894
14919
|
}
|
|
14895
|
-
return new Promise((
|
|
14920
|
+
return new Promise((resolve3, reject) => {
|
|
14896
14921
|
if (signal.aborted) {
|
|
14897
14922
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
14898
14923
|
return;
|
|
14899
14924
|
}
|
|
14900
|
-
const timeoutId = setTimeout(
|
|
14925
|
+
const timeoutId = setTimeout(resolve3, interval);
|
|
14901
14926
|
signal.addEventListener("abort", () => {
|
|
14902
14927
|
clearTimeout(timeoutId);
|
|
14903
14928
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -15773,12 +15798,12 @@ var StdioServerTransport = class {
|
|
|
15773
15798
|
this.onclose?.();
|
|
15774
15799
|
}
|
|
15775
15800
|
send(message) {
|
|
15776
|
-
return new Promise((
|
|
15801
|
+
return new Promise((resolve3) => {
|
|
15777
15802
|
const json = serializeMessage(message);
|
|
15778
15803
|
if (this._stdout.write(json)) {
|
|
15779
|
-
|
|
15804
|
+
resolve3();
|
|
15780
15805
|
} else {
|
|
15781
|
-
this._stdout.once("drain",
|
|
15806
|
+
this._stdout.once("drain", resolve3);
|
|
15782
15807
|
}
|
|
15783
15808
|
});
|
|
15784
15809
|
}
|
|
@@ -15786,10 +15811,10 @@ var StdioServerTransport = class {
|
|
|
15786
15811
|
|
|
15787
15812
|
// src/mcp.ts
|
|
15788
15813
|
import { existsSync as existsSync6, readFileSync as readFileSync6 } from "node:fs";
|
|
15789
|
-
import { basename as basename2, join as
|
|
15814
|
+
import { basename as basename2, join as join8 } from "node:path";
|
|
15790
15815
|
|
|
15791
15816
|
// src/version.ts
|
|
15792
|
-
var VERSION = true ? "0.1.
|
|
15817
|
+
var VERSION = true ? "0.1.17" : "0.0.0-dev";
|
|
15793
15818
|
function osName() {
|
|
15794
15819
|
return process.platform === "darwin" ? "macos" : process.platform === "win32" ? "windows" : process.platform;
|
|
15795
15820
|
}
|
|
@@ -15897,7 +15922,7 @@ var TOOLS = [
|
|
|
15897
15922
|
];
|
|
15898
15923
|
var VIEWABLE_IMAGES = ["image/jpeg", "image/png", "image/gif", "image/webp"];
|
|
15899
15924
|
var MAX_INLINE_IMAGE = 5 * 1024 * 1024;
|
|
15900
|
-
var parentsFile = () =>
|
|
15925
|
+
var parentsFile = () => join8(stateRoot(), "parents.json");
|
|
15901
15926
|
var processChannels = /* @__PURE__ */ new Map();
|
|
15902
15927
|
var lastChannel;
|
|
15903
15928
|
function savedParents() {
|
|
@@ -16167,13 +16192,13 @@ async function ask(question) {
|
|
|
16167
16192
|
}
|
|
16168
16193
|
}
|
|
16169
16194
|
function installRuntime() {
|
|
16170
|
-
const target =
|
|
16195
|
+
const target = join9(home(), "runtime", VERSION);
|
|
16171
16196
|
if (runtimeDir() !== target) {
|
|
16172
16197
|
rmSync3(target, { recursive: true, force: true });
|
|
16173
16198
|
mkdirSync5(target, { recursive: true });
|
|
16174
16199
|
cpSync(runtimeDir(), target, { recursive: true });
|
|
16175
16200
|
}
|
|
16176
|
-
return
|
|
16201
|
+
return join9(target, "cli.mjs");
|
|
16177
16202
|
}
|
|
16178
16203
|
function selectedTargets() {
|
|
16179
16204
|
const only = option("only");
|
|
@@ -16204,7 +16229,7 @@ async function pair(server, targets) {
|
|
|
16204
16229
|
if (result.status === "claimed" && result.token) return { token: result.token, connection_id: result.connection_id };
|
|
16205
16230
|
if (result.status === "rejected") throw new Error("\u30A2\u30D7\u30EA\u3067\u300C\u5FC3\u5F53\u305F\u308A\u304C\u306A\u3044\u300D\u304C\u62BC\u3055\u308C\u307E\u3057\u305F\u3002\u3082\u3046\u4E00\u5EA6 npx approval-box setup \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
16206
16231
|
if (result.status === "expired" || result.status === "delivered") throw new Error("\u30DA\u30A2\u30EA\u30F3\u30B0\u306E\u671F\u9650\u304C\u5207\u308C\u307E\u3057\u305F\u3002\u3082\u3046\u4E00\u5EA6 npx approval-box setup \u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
16207
|
-
await new Promise((
|
|
16232
|
+
await new Promise((resolve3) => setTimeout(resolve3, 2e3));
|
|
16208
16233
|
}
|
|
16209
16234
|
}
|
|
16210
16235
|
async function waitForChecks(api, clients) {
|
|
@@ -16228,7 +16253,7 @@ async function waitForChecks(api, clients) {
|
|
|
16228
16253
|
out("\n\u3059\u3079\u3066\u306EAI\u3067\u78BA\u8A8D\u304C\u6E08\u307F\u307E\u3057\u305F\u3002Approval Box\u3092\u4F7F\u3048\u307E\u3059\u3002");
|
|
16229
16254
|
return;
|
|
16230
16255
|
}
|
|
16231
|
-
await new Promise((
|
|
16256
|
+
await new Promise((resolve3) => setTimeout(resolve3, 3e3));
|
|
16232
16257
|
}
|
|
16233
16258
|
}
|
|
16234
16259
|
async function setup() {
|
|
@@ -16275,8 +16300,8 @@ async function setup() {
|
|
|
16275
16300
|
}
|
|
16276
16301
|
throw error;
|
|
16277
16302
|
}
|
|
16278
|
-
const { spawnSync } = await import("node:child_process");
|
|
16279
|
-
const result =
|
|
16303
|
+
const { spawnSync: spawnSync2 } = await import("node:child_process");
|
|
16304
|
+
const result = spawnSync2(process.execPath, [cli, "register", "--targets", targets.join(","), ...instructions ? ["--instructions"] : []], { stdio: "inherit" });
|
|
16280
16305
|
if (result.status !== 0) throw new Error("AI\u3078\u306E\u767B\u9332\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002");
|
|
16281
16306
|
await api.call("PUT", "/connection/clients", { clients: targets.map((t) => CLIENT[t]), os: osName() });
|
|
16282
16307
|
if (flag("no-test")) return;
|
|
@@ -16319,7 +16344,7 @@ async function uninstall() {
|
|
|
16319
16344
|
out(` \u30B5\u30FC\u30D0\u30FC: \u63A5\u7D9A\u306E\u89E3\u9664\u306B\u5931\u6557\u3057\u307E\u3057\u305F\uFF08\u30A2\u30D7\u30EA\u306E\u300C\u63A5\u7D9A\u300D\u304B\u3089\u5916\u3057\u3066\u304F\u3060\u3055\u3044\uFF09: ${error.message}`);
|
|
16320
16345
|
}
|
|
16321
16346
|
}
|
|
16322
|
-
rmSync3(
|
|
16347
|
+
rmSync3(join9(home(), "config.json"), { force: true });
|
|
16323
16348
|
out("\nApproval Box\u3092\u5916\u3057\u307E\u3057\u305F\u3002npm install -g \u3067\u5165\u308C\u305F\u5834\u5408\u306F\u3001npm uninstall -g approval-box \u3067\u672C\u4F53\u3082\u6D88\u305B\u307E\u3059\u3002");
|
|
16324
16349
|
}
|
|
16325
16350
|
async function status() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "approval-box",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
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",
|