approval-box 0.1.22 → 0.1.24
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-SN7I52NL.mjs → chunk-HBSDWG62.mjs} +150 -12
- package/dist/cli.mjs +17 -17
- 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-HBSDWG62.mjs";
|
|
6
6
|
|
|
7
7
|
// src/hooks/receive.ts
|
|
8
8
|
await runChannelReceiveMain(PROFILE);
|
|
@@ -20200,6 +20200,136 @@ function hookOwnerProcess(rows, pid) {
|
|
|
20200
20200
|
current = byPid.get(current.parent_pid);
|
|
20201
20201
|
return current;
|
|
20202
20202
|
}
|
|
20203
|
+
function processExists(pid) {
|
|
20204
|
+
if (!Number.isSafeInteger(pid) || pid <= 0)
|
|
20205
|
+
return false;
|
|
20206
|
+
try {
|
|
20207
|
+
process.kill(pid, 0);
|
|
20208
|
+
return true;
|
|
20209
|
+
} catch (error62) {
|
|
20210
|
+
return error62.code === "EPERM";
|
|
20211
|
+
}
|
|
20212
|
+
}
|
|
20213
|
+
function windowsJson(script, failure2) {
|
|
20214
|
+
const source = ["$ErrorActionPreference='Stop'", "[Console]::OutputEncoding=[Text.UTF8Encoding]::new($false)", script].join("\n");
|
|
20215
|
+
const result = spawnSync3(resolveWindowsPowerShell7(), ["-NoLogo", "-NoProfile", "-NonInteractive", "-EncodedCommand", Buffer.from(source, "utf16le").toString("base64")], {
|
|
20216
|
+
encoding: "utf8",
|
|
20217
|
+
timeout: 15e3,
|
|
20218
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
20219
|
+
windowsHide: true
|
|
20220
|
+
});
|
|
20221
|
+
if (result.error || result.status !== 0)
|
|
20222
|
+
throw new ProcessTableError(failure2);
|
|
20223
|
+
try {
|
|
20224
|
+
return JSON.parse(result.stdout);
|
|
20225
|
+
} catch {
|
|
20226
|
+
throw new ProcessTableError(failure2);
|
|
20227
|
+
}
|
|
20228
|
+
}
|
|
20229
|
+
function assertPids(pids) {
|
|
20230
|
+
const wanted = [...new Set(pids)];
|
|
20231
|
+
if (wanted.some((pid) => !Number.isSafeInteger(pid) || pid < 0))
|
|
20232
|
+
throw new ProcessTableError("process\u7167\u4F1A\u306Epid\u304C\u4E0D\u6B63\u3067\u3059");
|
|
20233
|
+
return wanted;
|
|
20234
|
+
}
|
|
20235
|
+
var WINDOWS_STARTED = [
|
|
20236
|
+
"function Started($p) {",
|
|
20237
|
+
" try { return $p.StartTime.ToUniversalTime().ToString('o') }",
|
|
20238
|
+
" catch [InvalidOperationException] { return '' }",
|
|
20239
|
+
` catch { $w = Get-CimInstance Win32_Process -Filter "ProcessId=$($p.Id)" -Property CreationDate; if ($null -eq $w) { return '' }`,
|
|
20240
|
+
" if ($null -eq $w.CreationDate) { return $null }; return $w.CreationDate.ToUniversalTime().ToString('o') }",
|
|
20241
|
+
"}"
|
|
20242
|
+
].join("\n");
|
|
20243
|
+
function readProcessIdentities(pids) {
|
|
20244
|
+
const wanted = assertPids(pids).filter(processExists);
|
|
20245
|
+
if (wanted.length === 0)
|
|
20246
|
+
return [];
|
|
20247
|
+
if (!isWin2) {
|
|
20248
|
+
const result = spawnSync3("/bin/ps", ["-o", "pid=,lstart=", "-p", wanted.join(",")], {
|
|
20249
|
+
encoding: "utf8",
|
|
20250
|
+
env: { ...process.env, LC_ALL: "C" },
|
|
20251
|
+
timeout: 1e4
|
|
20252
|
+
});
|
|
20253
|
+
if (result.error || result.status !== 0 && !(result.status === 1 && !result.stdout.trim())) {
|
|
20254
|
+
throw new ProcessTableError("OS\u306Eprocess\u4E00\u89A7\u3092\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093");
|
|
20255
|
+
}
|
|
20256
|
+
return result.stdout.split("\n").filter((line) => line.trim()).map((line) => {
|
|
20257
|
+
const match = /^\s*(\d+)\s+(\S+\s+\S+\s+\d+\s+\S+\s+\d+)\s*$/.exec(line);
|
|
20258
|
+
if (!match)
|
|
20259
|
+
throw new ProcessTableError("process\u4E00\u89A7\u306E\u5F62\u5F0F\u3092\u8A8D\u8B58\u3067\u304D\u307E\u305B\u3093");
|
|
20260
|
+
return { pid: Number(match[1]), started_identity: match[2].trim() };
|
|
20261
|
+
});
|
|
20262
|
+
}
|
|
20263
|
+
const rows = windowsJson([
|
|
20264
|
+
WINDOWS_STARTED,
|
|
20265
|
+
"$rows=@()",
|
|
20266
|
+
`foreach ($id in @(${wanted.join(",")})) {`,
|
|
20267
|
+
" try { $p=[Diagnostics.Process]::GetProcessById($id) } catch [ArgumentException] { continue }",
|
|
20268
|
+
" $started=Started $p",
|
|
20269
|
+
" if ($started -eq '') { continue }",
|
|
20270
|
+
" $rows += [ordered]@{ pid=[int]$id; started_identity=$started }",
|
|
20271
|
+
"}",
|
|
20272
|
+
"ConvertTo-Json -Compress -InputObject $rows"
|
|
20273
|
+
].join("\n"), "Windows\u306Eprocess\u306E\u958B\u59CB\u6642\u523B\u3092\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093");
|
|
20274
|
+
if (!Array.isArray(rows))
|
|
20275
|
+
throw new ProcessTableError("Windows process\u306E\u8AAD\u307F\u304C\u914D\u5217\u3067\u306F\u3042\u308A\u307E\u305B\u3093");
|
|
20276
|
+
return rows.map((row) => {
|
|
20277
|
+
if (!row || !Number.isSafeInteger(row.pid))
|
|
20278
|
+
throw new ProcessTableError("Windows process\u306E\u8AAD\u307F\u306Efield\u304C\u4E0D\u6B63\u3067\u3059");
|
|
20279
|
+
if (row.started_identity === null)
|
|
20280
|
+
return { pid: row.pid, started_identity: null };
|
|
20281
|
+
if (typeof row.started_identity !== "string" || !Number.isFinite(Date.parse(row.started_identity)))
|
|
20282
|
+
throw new ProcessTableError("Windows process\u306E\u8AAD\u307F\u306Efield\u304C\u4E0D\u6B63\u3067\u3059");
|
|
20283
|
+
return { pid: row.pid, started_identity: new Date(row.started_identity).toISOString() };
|
|
20284
|
+
});
|
|
20285
|
+
}
|
|
20286
|
+
function processIsRunning(pid, startedIdentity) {
|
|
20287
|
+
return processExists(pid) && readProcessIdentities([pid])[0]?.started_identity === startedIdentity;
|
|
20288
|
+
}
|
|
20289
|
+
function readProcessLineage(pid, depth = 8) {
|
|
20290
|
+
if (!isWin2)
|
|
20291
|
+
return readRuntimeProcesses();
|
|
20292
|
+
if (!Number.isSafeInteger(pid) || pid <= 0 || !Number.isSafeInteger(depth) || depth <= 0)
|
|
20293
|
+
throw new ProcessTableError("process\u7167\u4F1A\u306Epid\u304C\u4E0D\u6B63\u3067\u3059");
|
|
20294
|
+
let rows;
|
|
20295
|
+
try {
|
|
20296
|
+
rows = windowsJson([
|
|
20297
|
+
"$rows=@(); $child=$null",
|
|
20298
|
+
`$id=${pid}`,
|
|
20299
|
+
`for ($i=0; $i -lt ${depth} -and $id -gt 0; $i++) {`,
|
|
20300
|
+
" try { $p=Get-Process -Id $id; $started=$p.StartTime.ToUniversalTime() } catch { break }",
|
|
20301
|
+
// Windowsの親PIDは親の終了後も残り、別のprocessへ使い回される。子より後に始まったprocessは親でない。
|
|
20302
|
+
" if ($null -ne $child -and $started -gt $child) { break }",
|
|
20303
|
+
" $parent=0; try { if ($null -ne $p.Parent) { $parent=[int]$p.Parent.Id } } catch { }",
|
|
20304
|
+
" $exe=''; try { $exe=[string]$p.Path } catch { }",
|
|
20305
|
+
" if (-not $exe) { $exe=[string]$p.ProcessName }",
|
|
20306
|
+
" $cpu=0.0; try { $cpu=[double]$p.TotalProcessorTime.TotalSeconds } catch { }",
|
|
20307
|
+
" $rows += [ordered]@{ pid=[int]$p.Id; parent_pid=$parent; executable=$exe; started_identity=$started.ToString('o'); cpu_seconds=$cpu }",
|
|
20308
|
+
" $child=$started; $id=$parent",
|
|
20309
|
+
"}",
|
|
20310
|
+
"ConvertTo-Json -Compress -InputObject $rows"
|
|
20311
|
+
].join("\n"), "Windows\u306Eprocess\u306E\u5148\u7956\u3092\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093");
|
|
20312
|
+
} catch {
|
|
20313
|
+
return readRuntimeProcesses();
|
|
20314
|
+
}
|
|
20315
|
+
if (!Array.isArray(rows) || rows[0]?.pid !== pid)
|
|
20316
|
+
return readRuntimeProcesses();
|
|
20317
|
+
return rows.map((row) => {
|
|
20318
|
+
if (!row || !Number.isSafeInteger(row.pid) || !Number.isSafeInteger(row.parent_pid) || typeof row.executable !== "string" || !Number.isFinite(row.cpu_seconds) || typeof row.started_identity !== "string" || !Number.isFinite(Date.parse(row.started_identity)))
|
|
20319
|
+
throw new ProcessTableError("Windows process\u306E\u8AAD\u307F\u306Efield\u304C\u4E0D\u6B63\u3067\u3059");
|
|
20320
|
+
return {
|
|
20321
|
+
pid: row.pid,
|
|
20322
|
+
parent_pid: row.parent_pid,
|
|
20323
|
+
process_group_id: null,
|
|
20324
|
+
stopped: null,
|
|
20325
|
+
executable: row.executable,
|
|
20326
|
+
started_identity: new Date(row.started_identity).toISOString(),
|
|
20327
|
+
command: row.executable,
|
|
20328
|
+
cpu_seconds: row.cpu_seconds,
|
|
20329
|
+
argv_digest: createHash2("sha256").update(row.executable).digest("hex")
|
|
20330
|
+
};
|
|
20331
|
+
});
|
|
20332
|
+
}
|
|
20203
20333
|
function readRuntimeProcesses() {
|
|
20204
20334
|
if (!isWin2) {
|
|
20205
20335
|
const result2 = spawnSync3("/bin/ps", ["-axww", "-o", "pid=,ppid=,pgid=,stat=,lstart=,time=,command="], {
|
|
@@ -20506,7 +20636,7 @@ var claudeParentSchema = external_exports.object({
|
|
|
20506
20636
|
hook_root: external_exports.string()
|
|
20507
20637
|
}).strict();
|
|
20508
20638
|
function processIdentity(pid) {
|
|
20509
|
-
return
|
|
20639
|
+
return readProcessIdentities([pid])[0]?.started_identity ?? void 0;
|
|
20510
20640
|
}
|
|
20511
20641
|
function directory(parent) {
|
|
20512
20642
|
return path7.join(parent.hook_root, parent.request_id);
|
|
@@ -20530,8 +20660,7 @@ function assertOpen(parent) {
|
|
|
20530
20660
|
}
|
|
20531
20661
|
function prepareClaudeHookRequest(input2, root) {
|
|
20532
20662
|
const event = external_exports.object({ session_id: external_exports.uuid(), tool_use_id: requestId, agent_id: external_exports.string().optional() }).parse(input2);
|
|
20533
|
-
const
|
|
20534
|
-
const owner = hookOwnerProcess(rows, process.ppid);
|
|
20663
|
+
const owner = hookOwnerProcess(readProcessLineage(process.ppid), process.ppid);
|
|
20535
20664
|
if (!owner)
|
|
20536
20665
|
throw new ClaudeDeliveryError("CLAUDE_PARENT_PROCESS_UNAVAILABLE", "hook\u3092\u8D77\u52D5\u3057\u305F\u89AAprocess\u3092\u78BA\u8A8D\u3067\u304D\u307E\u305B\u3093");
|
|
20537
20666
|
const dir = path7.join(root, event.tool_use_id);
|
|
@@ -20544,13 +20673,14 @@ function prepareClaudeHookRequest(input2, root) {
|
|
|
20544
20673
|
parent_started_identity: owner.started_identity
|
|
20545
20674
|
});
|
|
20546
20675
|
try {
|
|
20547
|
-
sweepClaudeHookRequests(root,
|
|
20676
|
+
sweepClaudeHookRequests(root, processIsRunning);
|
|
20548
20677
|
} catch {
|
|
20549
20678
|
}
|
|
20550
20679
|
}
|
|
20551
20680
|
var STALE_REQUEST_MS = 24 * 60 * 60 * 1e3;
|
|
20552
20681
|
var REQUEST_FILES = /* @__PURE__ */ new Set(["request.json", "delivery.json", "answer.json", "hook.json", "sending.json", "emitted.json", "failed.json", "closed.json"]);
|
|
20553
20682
|
function sweepClaudeHookRequests(root, rows, now = Date.now()) {
|
|
20683
|
+
const running = typeof rows === "function" ? rows : (pid, startedIdentity) => rows.find((row) => row.pid === pid)?.started_identity === startedIdentity;
|
|
20554
20684
|
let entries;
|
|
20555
20685
|
try {
|
|
20556
20686
|
entries = fs5.readdirSync(root, { withFileTypes: true });
|
|
@@ -20576,7 +20706,7 @@ function sweepClaudeHookRequests(root, rows, now = Date.now()) {
|
|
|
20576
20706
|
invocation = invocationSchema.parse(JSON.parse(fs5.readFileSync(path7.join(dir, "request.json"), "utf8")));
|
|
20577
20707
|
} catch {
|
|
20578
20708
|
}
|
|
20579
|
-
if (invocation &&
|
|
20709
|
+
if (invocation && running(invocation.parent_pid, invocation.parent_started_identity))
|
|
20580
20710
|
continue;
|
|
20581
20711
|
}
|
|
20582
20712
|
fs5.rmSync(dir, { recursive: true, force: true });
|
|
@@ -20635,7 +20765,7 @@ function closeClaudeParentSession(input2, root) {
|
|
|
20635
20765
|
throw failure2;
|
|
20636
20766
|
}
|
|
20637
20767
|
function assertParentAlive(invocation) {
|
|
20638
|
-
if (
|
|
20768
|
+
if (!processIsRunning(invocation.parent_pid, invocation.parent_started_identity)) {
|
|
20639
20769
|
throw new ClaudeDeliveryError("CLAUDE_PARENT_PROCESS_CLOSED", "\u4F9D\u983C\u5143\u306EClaude process\u306F\u7D42\u4E86\u3057\u307E\u3057\u305F\u3002\u56DE\u7B54\u306F\u4FDD\u5B58\u3057\u305F\u307E\u307E\u3067\u3059");
|
|
20640
20770
|
}
|
|
20641
20771
|
}
|
|
@@ -21146,7 +21276,7 @@ function channelDir(profile, channelId) {
|
|
|
21146
21276
|
return path9.join(channelRoot(profile), uuid3.parse(channelId));
|
|
21147
21277
|
}
|
|
21148
21278
|
function processIdentity2(pid) {
|
|
21149
|
-
return
|
|
21279
|
+
return readProcessIdentities([pid])[0]?.started_identity ?? void 0;
|
|
21150
21280
|
}
|
|
21151
21281
|
function mkdirs(...dirs) {
|
|
21152
21282
|
for (const dir of dirs)
|
|
@@ -21255,7 +21385,7 @@ function channelDeliveryState(profile, channelId, deliveryId) {
|
|
|
21255
21385
|
return "unknown";
|
|
21256
21386
|
if (value.state === "withdrawn")
|
|
21257
21387
|
return "withdrawn";
|
|
21258
|
-
if (typeof value.pid === "number" && typeof value.started_identity === "string" &&
|
|
21388
|
+
if (typeof value.pid === "number" && typeof value.started_identity === "string" && !processIsRunning(value.pid, value.started_identity))
|
|
21259
21389
|
return "unknown";
|
|
21260
21390
|
return "sending";
|
|
21261
21391
|
}
|
|
@@ -21380,7 +21510,7 @@ function acquireWaiter(index) {
|
|
|
21380
21510
|
owner = JSON.parse(fs7.readFileSync(file2, "utf8"));
|
|
21381
21511
|
} catch {
|
|
21382
21512
|
}
|
|
21383
|
-
if (typeof owner.pid === "number" && typeof owner.started_identity === "string" &&
|
|
21513
|
+
if (typeof owner.pid === "number" && typeof owner.started_identity === "string" && processIsRunning(owner.pid, owner.started_identity))
|
|
21384
21514
|
return null;
|
|
21385
21515
|
try {
|
|
21386
21516
|
fs7.renameSync(file2, path9.join(index, `waiter.${randomUUID3()}.stale`));
|
|
@@ -21401,9 +21531,10 @@ function releaseWaiter(index, identity) {
|
|
|
21401
21531
|
}
|
|
21402
21532
|
}
|
|
21403
21533
|
function currentHookOwner() {
|
|
21404
|
-
const owner = hookOwnerProcess(
|
|
21534
|
+
const owner = hookOwnerProcess(readProcessLineage(process.ppid), process.ppid);
|
|
21405
21535
|
return owner ? { pid: owner.pid, started_identity: owner.started_identity } : null;
|
|
21406
21536
|
}
|
|
21537
|
+
var WAITER_OWNER_IDENTITY_RECHECK_MS = 6e4;
|
|
21407
21538
|
async function runClaudeChannelWaiter(profile, input2, emit, options = {}) {
|
|
21408
21539
|
const event = external_exports.object({ session_id: external_exports.uuid() }).loose().parse(input2);
|
|
21409
21540
|
if (!openClaudeChannels(profile, event.session_id).length)
|
|
@@ -21414,15 +21545,22 @@ async function runClaudeChannelWaiter(profile, input2, emit, options = {}) {
|
|
|
21414
21545
|
if (!identity)
|
|
21415
21546
|
return 0;
|
|
21416
21547
|
const deadline = Date.now() + (options.wait_ms ?? 8634e4);
|
|
21548
|
+
const runtime = options.runtime ?? { exists: processExists, identity: processIdentity2 };
|
|
21549
|
+
const recheckMs = options.identity_recheck_ms ?? WAITER_OWNER_IDENTITY_RECHECK_MS;
|
|
21417
21550
|
let lastParentCheck = 0;
|
|
21551
|
+
let lastIdentityCheck = null;
|
|
21418
21552
|
try {
|
|
21419
21553
|
for (; ; ) {
|
|
21420
21554
|
const channels = openClaudeChannels(profile, event.session_id);
|
|
21421
21555
|
if (!channels.length)
|
|
21422
21556
|
return 0;
|
|
21423
|
-
if (Date.now() - lastParentCheck >= 5e3) {
|
|
21557
|
+
if (Date.now() - lastParentCheck >= (options.owner_check_ms ?? 5e3)) {
|
|
21424
21558
|
lastParentCheck = Date.now();
|
|
21425
|
-
const
|
|
21559
|
+
const verify = lastIdentityCheck === null || lastParentCheck - lastIdentityCheck >= recheckMs;
|
|
21560
|
+
if (verify)
|
|
21561
|
+
lastIdentityCheck = lastParentCheck;
|
|
21562
|
+
const running = (pid, identity2) => runtime.exists(pid) && (!verify || runtime.identity(pid) === identity2);
|
|
21563
|
+
const alive = owner ? running(owner.pid, owner.started_identity) : channels.some((channel) => running(channel.claude.parent_pid, channel.claude.parent_started_identity));
|
|
21426
21564
|
if (!alive)
|
|
21427
21565
|
return 0;
|
|
21428
21566
|
}
|
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-HBSDWG62.mjs";
|
|
60
60
|
|
|
61
61
|
// ../../node_modules/qrcode/lib/can-promise.js
|
|
62
62
|
var require_can_promise = __commonJS({
|
|
@@ -12089,7 +12089,9 @@ async function runDaemon() {
|
|
|
12089
12089
|
async function deliver(item) {
|
|
12090
12090
|
const existing = journal[item.decision_id];
|
|
12091
12091
|
if (existing) return;
|
|
12092
|
-
const
|
|
12092
|
+
const verify = `
|
|
12093
|
+
\u78BA\u304B\u3081\u308B\u6642\u306F\u3001Approval Box\u306E get_decision \u3092 decision_id="${item.decision_id}" \u3067\u547C\u3076\u3068\u3001\u540C\u3058\u7B54\u3048\u304C\u8FD4\u308A\u307E\u3059\u3002`;
|
|
12094
|
+
const text2 = (item.attachments?.length ? item.text + await saveAll(api, item.decision_id, item.attachments) : item.text) + verify;
|
|
12093
12095
|
journal[item.decision_id] = { delivery_id: item.delivery_id, channel_id: item.route.channel_id, harness: item.route.harness, state: "sending", at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
12094
12096
|
save();
|
|
12095
12097
|
const entry = journal[item.decision_id];
|
|
@@ -15905,7 +15907,7 @@ function claudeChannelIsCurrent(profile, channelId, parent) {
|
|
|
15905
15907
|
}
|
|
15906
15908
|
|
|
15907
15909
|
// src/version.ts
|
|
15908
|
-
var VERSION = true ? "0.1.
|
|
15910
|
+
var VERSION = true ? "0.1.24" : "0.0.0-dev";
|
|
15909
15911
|
function osName() {
|
|
15910
15912
|
return process.platform === "darwin" ? "macos" : process.platform === "win32" ? "windows" : process.platform;
|
|
15911
15913
|
}
|
|
@@ -16080,6 +16082,7 @@ async function channelFor(harness, clientName, meta) {
|
|
|
16080
16082
|
remember(key, channel.channel_id, false);
|
|
16081
16083
|
return channel.channel_id;
|
|
16082
16084
|
}
|
|
16085
|
+
var ARRIVAL = "\u7B54\u3048\u306F\u3001\u3042\u3068\u3067\u3053\u306E\u4F1A\u8A71\u3078\u300C[Approval Box]\u300D\u3067\u59CB\u307E\u308B\u6587\u3068\u3057\u3066\u81EA\u52D5\u3067\u5C4A\u304D\u307E\u3059\u3002\u4F5C\u696D\u306E\u9014\u4E2D\u306A\u3089\u3001\u307B\u304B\u306E\u9053\u5177\u306E\u7D50\u679C\u3084 hook \u306E\u901A\u77E5\u3068\u4E00\u7DD2\u306B\u5C4A\u304F\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002\u5C4A\u3044\u305F\u7B54\u3048\u306F get_decision \u3067\u78BA\u304B\u3081\u3089\u308C\u307E\u3059\u3002";
|
|
16083
16086
|
function receiveGuide(harness, channelId) {
|
|
16084
16087
|
if (harness === "codex" || harness === "claude") return "";
|
|
16085
16088
|
const line = waitProcessCommandLine(channelReceiveProcess(runtimeEntry("receive"), channelId));
|
|
@@ -16092,6 +16095,11 @@ function receiveGuide(harness, channelId) {
|
|
|
16092
16095
|
);
|
|
16093
16096
|
return lines.join("\n");
|
|
16094
16097
|
}
|
|
16098
|
+
function announced(message, decision, channelId) {
|
|
16099
|
+
return text(`${message}
|
|
16100
|
+
|
|
16101
|
+
${JSON.stringify(decision)}`, { ...decision, steer_channel: { channel_id: channelId }, guide: message });
|
|
16102
|
+
}
|
|
16095
16103
|
function text(value, structured, isError = false) {
|
|
16096
16104
|
return { content: [{ type: "text", text: value }], ...structured ? { structuredContent: structured } : {}, ...isError ? { isError: true } : {} };
|
|
16097
16105
|
}
|
|
@@ -16138,10 +16146,8 @@ ${JSON.stringify({ items })}`, { items });
|
|
|
16138
16146
|
};
|
|
16139
16147
|
try {
|
|
16140
16148
|
const decision = await api.call("POST", "/decisions", body);
|
|
16141
|
-
const message = `\u7533\u8ACB\u3057\u307E\u3057\u305F: ${decision.decision_id}\u300C${decision.title}\u300D\u3002\
|
|
16142
|
-
return
|
|
16143
|
-
|
|
16144
|
-
${JSON.stringify(decision)}`, { ...decision, steer_channel: { channel_id: channelId } });
|
|
16149
|
+
const message = `\u7533\u8ACB\u3057\u307E\u3057\u305F: ${decision.decision_id}\u300C${decision.title}\u300D\u3002${ARRIVAL}\u5F85\u3063\u3066\u547C\u3073\u76F4\u3055\u305A\u3001\u4ED6\u306E\u4F5C\u696D\u3092\u7D9A\u3051\u308B\u304B\u30BF\u30FC\u30F3\u3092\u7D42\u3048\u3066\u304F\u3060\u3055\u3044\u3002`;
|
|
16150
|
+
return announced(`${message}${receiveGuide(harness, channelId)}`, decision, channelId);
|
|
16145
16151
|
} catch (error) {
|
|
16146
16152
|
if (error instanceof ServerError && error.code === "confirm_required") {
|
|
16147
16153
|
const decisions = error.body.decisions ?? [];
|
|
@@ -16179,18 +16185,14 @@ ${JSON.stringify({ error: "duplicate_suspected", existing })}`, { error: "duplic
|
|
|
16179
16185
|
const channelId = await channelFor(harness, clientName, request.params._meta);
|
|
16180
16186
|
const decision = await api.call("POST", `/decisions/${encodeURIComponent(String(decision_id))}/amend`, { ...rest, route: { channel_id: channelId, harness } });
|
|
16181
16187
|
lastChannel = channelId;
|
|
16182
|
-
return
|
|
16183
|
-
|
|
16184
|
-
${JSON.stringify(decision)}`, { ...decision, steer_channel: { channel_id: channelId } });
|
|
16188
|
+
return announced(`\u76F4\u3057\u307E\u3057\u305F: ${decision.decision_id} version=${decision.version}${receiveGuide(harness, channelId)}`, decision, channelId);
|
|
16185
16189
|
}
|
|
16186
16190
|
if (name === "resume_decision") {
|
|
16187
16191
|
const channelId = await channelFor(harness, clientName, request.params._meta);
|
|
16188
16192
|
const decision = await api.call("POST", `/decisions/${encodeURIComponent(String(args.decision_id))}/resume`, { channel_id: channelId, harness });
|
|
16189
16193
|
lastChannel = channelId;
|
|
16190
|
-
const head = decision.answer_text ? String(decision.answer_text) : `\u518D\u958B\u3057\u307E\u3057\u305F: ${decision.decision_id}\u3002
|
|
16191
|
-
return
|
|
16192
|
-
|
|
16193
|
-
${JSON.stringify(decision)}`, { ...decision, steer_channel: { channel_id: channelId } });
|
|
16194
|
+
const head = decision.answer_text ? String(decision.answer_text) : `\u518D\u958B\u3057\u307E\u3057\u305F: ${decision.decision_id}\u3002${ARRIVAL}`;
|
|
16195
|
+
return announced(`${head}${decision.answer_text ? "" : receiveGuide(harness, channelId)}`, decision, channelId);
|
|
16194
16196
|
}
|
|
16195
16197
|
if (name === "cancel_decision") {
|
|
16196
16198
|
const decision = await api.call("POST", `/decisions/${encodeURIComponent(String(args.decision_id))}/cancel`, { reason: args.reason });
|
|
@@ -16232,9 +16234,7 @@ ${JSON.stringify(decision)}`, decision);
|
|
|
16232
16234
|
route: { channel_id: channelId, harness }
|
|
16233
16235
|
});
|
|
16234
16236
|
const message = `\u63A5\u7D9A\u30C6\u30B9\u30C8\u306E\u7533\u8ACB\u3092\u9001\u308A\u307E\u3057\u305F\uFF08${decision.decision_id}\uFF09\u3002\u5229\u7528\u8005\u306B\u30A2\u30D7\u30EA\u304BWeb\u7248\u3067\u7B54\u3048\u308B\u3088\u3046\u4F1D\u3048\u3066\u304F\u3060\u3055\u3044\u3002\u7B54\u3048\u304C\u3053\u306E\u4F1A\u8A71\u3078\u5C4A\u3044\u305F\u3089\u3001\u305D\u3053\u306B\u66F8\u304B\u308C\u305F\u78BA\u8A8D\u30B3\u30FC\u30C9\u3067 confirm_setup_test \u3092\u547C\u3093\u3067\u304F\u3060\u3055\u3044\u3002`;
|
|
16235
|
-
return
|
|
16236
|
-
|
|
16237
|
-
${JSON.stringify(decision)}`, { ...decision, steer_channel: { channel_id: channelId } });
|
|
16237
|
+
return announced(`${message}${receiveGuide(harness, channelId)}`, decision, channelId);
|
|
16238
16238
|
}
|
|
16239
16239
|
if (name === "confirm_setup_test") {
|
|
16240
16240
|
const result = await api.call("POST", "/setup-test/confirm", { decision_id: args.decision_id, code: String(args.code) });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "approval-box",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.24",
|
|
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.4.
|
|
35
|
+
"aiterm-steer-delivery": "0.4.5",
|
|
36
36
|
"esbuild": "^0.28.2",
|
|
37
37
|
"qrcode": "^1.5.4",
|
|
38
38
|
"typescript": "^6.0.3",
|