approval-box 0.1.17 → 0.1.20
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/README.md +8 -0
- 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-GH2JG56Y.mjs → chunk-OVDAILMZ.mjs} +408 -388
- package/dist/cli.mjs +113 -44
- package/package.json +2 -2
- package/dist/approval-box-codex-hook.mjs +0 -8
package/dist/cli.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire as __kbCreateRequire } from 'node:module'; const require = __kbCreateRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
|
+
CodexDeliveryError,
|
|
4
5
|
HOOK_FILES,
|
|
5
6
|
MCP_SERVER,
|
|
6
7
|
PROFILE,
|
|
@@ -18,6 +19,7 @@ import {
|
|
|
18
19
|
claudeHookRoot,
|
|
19
20
|
claudeParentFromRequest,
|
|
20
21
|
claudeParentHooksRegistered,
|
|
22
|
+
codexDeliveryStateViaAiterm,
|
|
21
23
|
codexParentFromRequest,
|
|
22
24
|
configureCodexSteer,
|
|
23
25
|
cursorHookRoot,
|
|
@@ -47,14 +49,14 @@ import {
|
|
|
47
49
|
setupNodeExecutable,
|
|
48
50
|
stateRoot,
|
|
49
51
|
string,
|
|
52
|
+
submitCodexParentAnswerViaAiterm,
|
|
50
53
|
union,
|
|
51
54
|
unknown,
|
|
52
|
-
verifyCodexParent,
|
|
53
55
|
verifyCursorParent,
|
|
54
56
|
waitProcessCommandLine,
|
|
55
57
|
withCodexReceiver,
|
|
56
58
|
withdrawFromChannel
|
|
57
|
-
} from "./chunks/chunk-
|
|
59
|
+
} from "./chunks/chunk-OVDAILMZ.mjs";
|
|
58
60
|
|
|
59
61
|
// ../../node_modules/qrcode/lib/can-promise.js
|
|
60
62
|
var require_can_promise = __commonJS({
|
|
@@ -1334,11 +1336,11 @@ var require_dijkstra = __commonJS({
|
|
|
1334
1336
|
var predecessors = {};
|
|
1335
1337
|
var costs = {};
|
|
1336
1338
|
costs[s] = 0;
|
|
1337
|
-
var
|
|
1338
|
-
|
|
1339
|
+
var open2 = dijkstra.PriorityQueue.make();
|
|
1340
|
+
open2.push(s, 0);
|
|
1339
1341
|
var closest, u, v, cost_of_s_to_u, adjacent_nodes, cost_of_e, cost_of_s_to_u_plus_cost_of_e, cost_of_s_to_v, first_visit;
|
|
1340
|
-
while (!
|
|
1341
|
-
closest =
|
|
1342
|
+
while (!open2.empty()) {
|
|
1343
|
+
closest = open2.pop();
|
|
1342
1344
|
u = closest.value;
|
|
1343
1345
|
cost_of_s_to_u = closest.cost;
|
|
1344
1346
|
adjacent_nodes = graph[u] || {};
|
|
@@ -1350,7 +1352,7 @@ var require_dijkstra = __commonJS({
|
|
|
1350
1352
|
first_visit = typeof costs[v] === "undefined";
|
|
1351
1353
|
if (first_visit || cost_of_s_to_v > cost_of_s_to_u_plus_cost_of_e) {
|
|
1352
1354
|
costs[v] = cost_of_s_to_u_plus_cost_of_e;
|
|
1353
|
-
|
|
1355
|
+
open2.push(v, cost_of_s_to_u_plus_cost_of_e);
|
|
1354
1356
|
predecessors[v] = u;
|
|
1355
1357
|
}
|
|
1356
1358
|
}
|
|
@@ -11812,6 +11814,17 @@ var Api = class {
|
|
|
11812
11814
|
}
|
|
11813
11815
|
return json;
|
|
11814
11816
|
}
|
|
11817
|
+
/** 申請前画像をバイナリで上げる。 */
|
|
11818
|
+
async uploadRequestImage(data, name, contentType) {
|
|
11819
|
+
const response = await fetch(this.url(`/request-images?name=${encodeURIComponent(name)}`), {
|
|
11820
|
+
method: "POST",
|
|
11821
|
+
headers: { authorization: `Bearer ${this.token}`, "content-type": contentType },
|
|
11822
|
+
body: new Uint8Array(data)
|
|
11823
|
+
});
|
|
11824
|
+
const json = await response.json();
|
|
11825
|
+
if (!response.ok) throw new ServerError(response.status, json.error?.code ?? "internal", json.error?.message ?? `HTTP ${response.status}`, json);
|
|
11826
|
+
return json;
|
|
11827
|
+
}
|
|
11815
11828
|
/** ファイルを取る(添付)。誤りはJSONの本文から読む。 */
|
|
11816
11829
|
async download(path) {
|
|
11817
11830
|
let response;
|
|
@@ -11895,6 +11908,26 @@ function launchDaemon(executable, entry, cwd) {
|
|
|
11895
11908
|
}
|
|
11896
11909
|
}
|
|
11897
11910
|
|
|
11911
|
+
// src/channel-delivery.ts
|
|
11912
|
+
var provider = {
|
|
11913
|
+
submit: (parent, id, text2) => submitCodexParentAnswerViaAiterm(parent, id, text2),
|
|
11914
|
+
state: (parent, id) => codexDeliveryStateViaAiterm(parent, id)
|
|
11915
|
+
};
|
|
11916
|
+
async function sendChannelAnswer(channelId, deliveryId, text2, codex = provider) {
|
|
11917
|
+
if (channelClosed(PROFILE, channelId)) throw Object.assign(new Error("\u7533\u8ACB\u3092\u51FA\u3057\u305FAI\u306E\u4F1A\u8A71\u304C\u7D42\u308F\u3063\u3066\u3044\u307E\u3059"), { closed: true });
|
|
11918
|
+
const channel = readChannel(PROFILE, channelId);
|
|
11919
|
+
if (channel.kind !== "codex") return sendToChannel(PROFILE, channelId, deliveryId, text2);
|
|
11920
|
+
if (!channel.codex) throw new CodexDeliveryError("CODEX_PARENT_ID_UNAVAILABLE", "channel\u306B\u5143\u306ECodex\u4F1A\u8A71\u304C\u3042\u308A\u307E\u305B\u3093");
|
|
11921
|
+
const result = await codex.submit(channel.codex, deliveryId, text2);
|
|
11922
|
+
return { state: "submitted", queued_submission_id: result.queued_submission_id };
|
|
11923
|
+
}
|
|
11924
|
+
async function channelAnswerState(channelId, deliveryId, codex = provider) {
|
|
11925
|
+
const channel = readChannel(PROFILE, channelId);
|
|
11926
|
+
if (channel.kind !== "codex") return channelDeliveryState(PROFILE, channelId, deliveryId);
|
|
11927
|
+
if (!channel.codex) throw new CodexDeliveryError("CODEX_PARENT_ID_UNAVAILABLE", "channel\u306B\u5143\u306ECodex\u4F1A\u8A71\u304C\u3042\u308A\u307E\u305B\u3093");
|
|
11928
|
+
return codex.state(channel.codex, deliveryId);
|
|
11929
|
+
}
|
|
11930
|
+
|
|
11898
11931
|
// src/daemon.ts
|
|
11899
11932
|
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, rmSync as rmSync2 } from "node:fs";
|
|
11900
11933
|
import { join as join5 } from "node:path";
|
|
@@ -12023,7 +12056,7 @@ async function runDaemon() {
|
|
|
12023
12056
|
`);
|
|
12024
12057
|
for (const [id, entry] of Object.entries(journal)) {
|
|
12025
12058
|
if (entry.state !== "sending") continue;
|
|
12026
|
-
const current = safeState(entry);
|
|
12059
|
+
const current = await safeState(entry);
|
|
12027
12060
|
if (current === "queued" || current === "emitted" || current === "sending") entry.state = "queued";
|
|
12028
12061
|
else Object.assign(entry, { state: "report", result: "unknown", detail: "\u9001\u4FE1\u306E\u9014\u4E2D\u3067\u914D\u9001\u30C7\u30FC\u30E2\u30F3\u304C\u6B62\u307E\u308A\u307E\u3057\u305F" });
|
|
12029
12062
|
journal[id] = entry;
|
|
@@ -12052,8 +12085,7 @@ async function runDaemon() {
|
|
|
12052
12085
|
save();
|
|
12053
12086
|
const entry = journal[item.decision_id];
|
|
12054
12087
|
try {
|
|
12055
|
-
|
|
12056
|
-
const result = await sendToChannel(PROFILE, item.route.channel_id, item.delivery_id, text2);
|
|
12088
|
+
const result = await sendChannelAnswer(item.route.channel_id, item.delivery_id, text2);
|
|
12057
12089
|
if (result.state === "submitted") Object.assign(entry, { state: "report", result: "delivered" });
|
|
12058
12090
|
else entry.state = "queued";
|
|
12059
12091
|
} catch (error) {
|
|
@@ -12064,9 +12096,9 @@ async function runDaemon() {
|
|
|
12064
12096
|
log(`\u914D\u9001 ${item.decision_id} \u2192 ${entry.state}${entry.result ? `/${entry.result}` : ""}`);
|
|
12065
12097
|
if (entry.state === "report") await report(item.decision_id);
|
|
12066
12098
|
}
|
|
12067
|
-
function safeState(entry) {
|
|
12099
|
+
async function safeState(entry) {
|
|
12068
12100
|
try {
|
|
12069
|
-
return
|
|
12101
|
+
return await channelAnswerState(entry.channel_id, entry.delivery_id);
|
|
12070
12102
|
} catch {
|
|
12071
12103
|
return null;
|
|
12072
12104
|
}
|
|
@@ -12078,7 +12110,7 @@ async function runDaemon() {
|
|
|
12078
12110
|
continue;
|
|
12079
12111
|
}
|
|
12080
12112
|
if (entry.state !== "queued") continue;
|
|
12081
|
-
const current = safeState(entry);
|
|
12113
|
+
const current = await safeState(entry);
|
|
12082
12114
|
if (current === "emitted") Object.assign(entry, { state: "report", result: "delivered" });
|
|
12083
12115
|
else if (current === "unknown") Object.assign(entry, { state: "report", result: "unknown", detail: "\u53D7\u3051\u53E3\u306E\u51FA\u529B\u3092\u78BA\u304B\u3081\u3089\u308C\u307E\u305B\u3093\u3067\u3057\u305F" });
|
|
12084
12116
|
else if (current === null || current === "withdrawn") Object.assign(entry, { state: "report", result: "failed", detail: "\u914D\u9001\u306E\u8A18\u9332\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093" });
|
|
@@ -12112,7 +12144,7 @@ async function runDaemon() {
|
|
|
12112
12144
|
save();
|
|
12113
12145
|
log(`\u914D\u9001 ${id} \u2192 ${withdrawn ? "withdrawn" : "resolved"}`);
|
|
12114
12146
|
} else {
|
|
12115
|
-
Object.assign(entry, safeState(entry) === "emitted" ? { state: "report", result: "delivered" } : { state: "report", result: "unknown", detail: "\u914D\u9001\u5148\u306E\u5909\u66F4\u524D\u306B\u53D7\u3051\u53E3\u304C\u672C\u6587\u3092\u53D6\u5F97\u3057\u307E\u3057\u305F\u3002\u518D\u9001\u3057\u307E\u305B\u3093" });
|
|
12147
|
+
Object.assign(entry, await safeState(entry) === "emitted" ? { state: "report", result: "delivered" } : { state: "report", result: "unknown", detail: "\u914D\u9001\u5148\u306E\u5909\u66F4\u524D\u306B\u53D7\u3051\u53E3\u304C\u672C\u6587\u3092\u53D6\u5F97\u3057\u307E\u3057\u305F\u3002\u518D\u9001\u3057\u307E\u305B\u3093" });
|
|
12116
12148
|
save();
|
|
12117
12149
|
await report(id);
|
|
12118
12150
|
waiting.delete(id);
|
|
@@ -12171,8 +12203,8 @@ async function runDaemon() {
|
|
|
12171
12203
|
await sync();
|
|
12172
12204
|
try {
|
|
12173
12205
|
const { items } = await api.call("GET", "/decisions");
|
|
12174
|
-
const
|
|
12175
|
-
if (
|
|
12206
|
+
const open2 = items.some((d) => d.status === "pending" || d.status === "held");
|
|
12207
|
+
if (open2 || Object.keys(journal).length) idleSince = Date.now();
|
|
12176
12208
|
else if (Date.now() - idleSince > IDLE_EXIT_MS) stop();
|
|
12177
12209
|
} catch {
|
|
12178
12210
|
idleSince = Date.now();
|
|
@@ -12374,14 +12406,8 @@ async function registerTools(target, options) {
|
|
|
12374
12406
|
await withCodexConfig(async (request) => {
|
|
12375
12407
|
await request("config/batchWrite", { filePath: config, edits: [{ keyPath: `mcp_servers.${MCP_SERVER}`, value: { ...registration(), env_vars: ["CODEX_HOME"] }, mergeStrategy: "replace" }] });
|
|
12376
12408
|
});
|
|
12377
|
-
|
|
12378
|
-
|
|
12379
|
-
const result = await configureCodexSteer(PROFILE, "enable", { hook: runtimeEntry("codex"), codex_home: codexHome(), node: stableNode() });
|
|
12380
|
-
steerStatus = result.status + (result.reason_code ? `:${result.reason_code}` : "");
|
|
12381
|
-
} catch (error) {
|
|
12382
|
-
steerStatus = `failed:${error.code ?? error.message}`;
|
|
12383
|
-
}
|
|
12384
|
-
return { target, status: "registered", steer: steerStatus };
|
|
12409
|
+
await configureCodexSteer(PROFILE, "disable", { hook: runtimeEntry("codex"), codex_home: codexHome() });
|
|
12410
|
+
return { target, status: "registered", note: "Codex\u306E\u56DE\u7B54\u914D\u9001\u306FAiterm\u306E\u5171\u901ASteer\u3092\u4F7F\u3044\u307E\u3059\u3002\u65E7\u7248\u306E\u5C02\u7528\u914D\u9001hook\u306F\u767B\u9332\u3057\u307E\u305B\u3093\u3002" };
|
|
12385
12411
|
}
|
|
12386
12412
|
const grok = onPath("grok");
|
|
12387
12413
|
if (!grok) throw new Error("grok \u30B3\u30DE\u30F3\u30C9\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093");
|
|
@@ -15811,10 +15837,53 @@ var StdioServerTransport = class {
|
|
|
15811
15837
|
|
|
15812
15838
|
// src/mcp.ts
|
|
15813
15839
|
import { existsSync as existsSync6, readFileSync as readFileSync6 } from "node:fs";
|
|
15814
|
-
import { basename as
|
|
15840
|
+
import { basename as basename3, join as join8 } from "node:path";
|
|
15841
|
+
|
|
15842
|
+
// src/request-images.ts
|
|
15843
|
+
import { open } from "node:fs/promises";
|
|
15844
|
+
import { basename as basename2 } from "node:path";
|
|
15845
|
+
var MAX_FILE = 20 * 1024 * 1024;
|
|
15846
|
+
var MAX_TOTAL = 50 * 1024 * 1024;
|
|
15847
|
+
function imageType(b) {
|
|
15848
|
+
if (b.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))) return "image/png";
|
|
15849
|
+
if (b.length >= 3 && b[0] === 255 && b[1] === 216 && b[2] === 255) return "image/jpeg";
|
|
15850
|
+
if (b.subarray(0, 4).toString() === "GIF8") return "image/gif";
|
|
15851
|
+
if (b.subarray(0, 4).toString() === "RIFF" && b.subarray(8, 12).toString() === "WEBP") return "image/webp";
|
|
15852
|
+
if (b.subarray(4, 8).toString() === "ftyp" && ["heic", "heix", "hevc", "hevx", "heim", "heis", "mif1", "msf1", "heif"].includes(b.subarray(8, 12).toString())) return "image/heic";
|
|
15853
|
+
throw new Error("\u7533\u8ACB\u306B\u4ED8\u3051\u3089\u308C\u308B\u306E\u306FJPEG\u30FBPNG\u30FBGIF\u30FBWebP\u30FBHEIC\u753B\u50CF\u3067\u3059\u3002");
|
|
15854
|
+
}
|
|
15855
|
+
async function uploadImagePaths(api, paths) {
|
|
15856
|
+
if (!Array.isArray(paths) || paths.length > 10 || paths.some((p) => typeof p !== "string" || !p.trim())) throw new Error("image_paths\u306F10\u4EF6\u307E\u3067\u306E\u753B\u50CF\u30D5\u30A1\u30A4\u30EB\u30D1\u30B9\u914D\u5217\u3067\u3059\u3002");
|
|
15857
|
+
const images = [];
|
|
15858
|
+
let total = 0;
|
|
15859
|
+
for (const path of paths) {
|
|
15860
|
+
const file = await open(path, "r");
|
|
15861
|
+
try {
|
|
15862
|
+
const stat = await file.stat();
|
|
15863
|
+
if (!stat.isFile() || !stat.size || stat.size > MAX_FILE) throw new Error(`${basename2(path)}: \u7A7A\u3067\u306A\u3044\u901A\u5E38\u30D5\u30A1\u30A4\u30EB\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\uFF0820MiB\u307E\u3067\uFF09\u3002`);
|
|
15864
|
+
total += stat.size;
|
|
15865
|
+
if (total > MAX_TOTAL) throw new Error("\u7533\u8ACB\u753B\u50CF\u306F\u5408\u8A0850MiB\u307E\u3067\u3067\u3059\u3002");
|
|
15866
|
+
const data = Buffer.alloc(stat.size + 1);
|
|
15867
|
+
let n = 0;
|
|
15868
|
+
while (n < data.length) {
|
|
15869
|
+
const r = await file.read(data, n, data.length - n, n);
|
|
15870
|
+
if (!r.bytesRead) break;
|
|
15871
|
+
n += r.bytesRead;
|
|
15872
|
+
}
|
|
15873
|
+
if (n !== stat.size) throw new Error(`${basename2(path)}: \u8AAD\u307F\u53D6\u308A\u4E2D\u306B\u753B\u50CF\u304C\u5909\u308F\u308A\u307E\u3057\u305F\u3002`);
|
|
15874
|
+
const bytes = data.subarray(0, n);
|
|
15875
|
+
images.push({ name: basename2(path), data: bytes, type: imageType(bytes) });
|
|
15876
|
+
} finally {
|
|
15877
|
+
await file.close();
|
|
15878
|
+
}
|
|
15879
|
+
}
|
|
15880
|
+
const ids = [];
|
|
15881
|
+
for (const image of images) ids.push((await api.uploadRequestImage(image.data, image.name, image.type)).id);
|
|
15882
|
+
return ids;
|
|
15883
|
+
}
|
|
15815
15884
|
|
|
15816
15885
|
// src/version.ts
|
|
15817
|
-
var VERSION = true ? "0.1.
|
|
15886
|
+
var VERSION = true ? "0.1.20" : "0.0.0-dev";
|
|
15818
15887
|
function osName() {
|
|
15819
15888
|
return process.platform === "darwin" ? "macos" : process.platform === "win32" ? "windows" : process.platform;
|
|
15820
15889
|
}
|
|
@@ -15857,6 +15926,8 @@ var TOOLS = [
|
|
|
15857
15926
|
deadline: { type: "string", description: "\u671F\u9650\uFF08ISO 8601\uFF09" },
|
|
15858
15927
|
session_label: { type: "string", description: "\u3069\u306E\u4F5C\u696D\u306E\u8A71\u304B\uFF08\u4F8B: \u30EA\u30DD\u30B8\u30C8\u30EA\u540D / \u4F5C\u696D\u540D\uFF09\u3002\u7701\u7565\u3059\u308B\u3068\u4F5C\u696D\u30D5\u30A9\u30EB\u30C0\u540D" },
|
|
15859
15928
|
distinct_reason: { type: "string", description: "\u540C\u3058\u4EF6\u540D\u306E\u672A\u6C7A\u304C\u3042\u308B\u306E\u306B\u5225\u4EF6\u3068\u3057\u3066\u51FA\u3059\u6642\u3060\u3051\u3001\u305D\u306E\u7406\u7531" },
|
|
15929
|
+
image_paths: { type: "array", items: { type: "string" }, maxItems: 10, description: "\u7533\u8ACB\u306B\u6DFB\u3048\u308B\u30ED\u30FC\u30AB\u30EB\u753B\u50CF\u30D1\u30B9\u300210\u4EF6/\u5358\u4F5320MiB/\u5408\u8A0850MiB\u307E\u3067\u3002\u30D1\u30B9\u81EA\u4F53\u306F\u4EBA\u3078\u9001\u3089\u306A\u3044" },
|
|
15930
|
+
request_attachment_ids: { type: "array", items: { type: "string" }, maxItems: 10 },
|
|
15860
15931
|
check_token: { type: "string", description: "1\u56DE\u76EE\u306E request_decision \u3067\u8FD4\u3063\u305F\u78BA\u8A8D\u306E\u672D\u3002\u4E00\u89A7\u3092\u78BA\u304B\u3081\u3001\u76F4\u3059\u30FB\u53D6\u308A\u4E0B\u3052\u308B\u7533\u8ACB\u304C\u7121\u3044\u3068\u5224\u65AD\u3057\u305F\u6642\u306B\u4ED8\u3051\u308B" }
|
|
15861
15932
|
},
|
|
15862
15933
|
required: ["title", "options"],
|
|
@@ -15875,6 +15946,8 @@ var TOOLS = [
|
|
|
15875
15946
|
changes: {
|
|
15876
15947
|
type: "object",
|
|
15877
15948
|
properties: {
|
|
15949
|
+
image_paths: { type: "array", items: { type: "string" }, maxItems: 10 },
|
|
15950
|
+
request_attachment_ids: { type: "array", items: { type: "string" }, maxItems: 10 },
|
|
15878
15951
|
title: { type: "string" },
|
|
15879
15952
|
context: { type: "string" },
|
|
15880
15953
|
options: { type: "array", items: optionSchema, minItems: 2, maxItems: 6 },
|
|
@@ -15948,7 +16021,6 @@ function remember(key, channelId, persistent) {
|
|
|
15948
16021
|
writeJsonFile(parentsFile(), all);
|
|
15949
16022
|
} else processChannels.set(key, channelId);
|
|
15950
16023
|
}
|
|
15951
|
-
var verifiedCodexThreads = /* @__PURE__ */ new Set();
|
|
15952
16024
|
async function channelFor(harness, clientName, meta) {
|
|
15953
16025
|
if (harness === "codex") {
|
|
15954
16026
|
const parent = codexParentFromRequest(clientName, meta);
|
|
@@ -15956,10 +16028,6 @@ async function channelFor(harness, clientName, meta) {
|
|
|
15956
16028
|
const key2 = `codex:${parent.codex_home}:${parent.thread_id}`;
|
|
15957
16029
|
const existing2 = reuse(key2, true);
|
|
15958
16030
|
if (existing2) return existing2;
|
|
15959
|
-
if (!verifiedCodexThreads.has(key2)) {
|
|
15960
|
-
await verifyCodexParent(PROFILE, parent);
|
|
15961
|
-
verifiedCodexThreads.add(key2);
|
|
15962
|
-
}
|
|
15963
16031
|
const channel2 = openChannel(PROFILE, parent);
|
|
15964
16032
|
remember(key2, channel2.channel_id, true);
|
|
15965
16033
|
return channel2.channel_id;
|
|
@@ -16036,10 +16104,14 @@ ${JSON.stringify({ items })}`, { items });
|
|
|
16036
16104
|
if (name === "request_decision") {
|
|
16037
16105
|
const channelId = await channelFor(harness, clientName, request.params._meta);
|
|
16038
16106
|
lastChannel = channelId;
|
|
16107
|
+
const { image_paths, ...rest } = args;
|
|
16108
|
+
if (image_paths !== void 0 && rest.request_attachment_ids !== void 0) throw new Error("image_paths\u3068request_attachment_ids\u306F\u7247\u65B9\u3060\u3051\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
16109
|
+
const request_attachment_ids = image_paths !== void 0 ? await uploadImagePaths(api, image_paths) : rest.request_attachment_ids;
|
|
16039
16110
|
const body = {
|
|
16040
|
-
...
|
|
16111
|
+
...rest,
|
|
16112
|
+
...request_attachment_ids !== void 0 ? { request_attachment_ids } : {},
|
|
16041
16113
|
client: CLIENT_OF[harness],
|
|
16042
|
-
session_label: args.session_label || `${
|
|
16114
|
+
session_label: args.session_label || `${basename3(process.cwd())} (${CLIENT_OF[harness]})`,
|
|
16043
16115
|
route: { channel_id: channelId, harness }
|
|
16044
16116
|
};
|
|
16045
16117
|
try {
|
|
@@ -16078,6 +16150,10 @@ ${JSON.stringify({ error: "duplicate_suspected", existing })}`, { error: "duplic
|
|
|
16078
16150
|
}
|
|
16079
16151
|
if (name === "amend_decision") {
|
|
16080
16152
|
const { decision_id, ...rest } = args;
|
|
16153
|
+
const { image_paths, ...changes } = rest.changes ?? {};
|
|
16154
|
+
if (image_paths !== void 0 && changes.request_attachment_ids !== void 0) throw new Error("image_paths\u3068request_attachment_ids\u306F\u7247\u65B9\u3060\u3051\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
16155
|
+
if (image_paths !== void 0) changes.request_attachment_ids = await uploadImagePaths(api, image_paths);
|
|
16156
|
+
rest.changes = changes;
|
|
16081
16157
|
const channelId = await channelFor(harness, clientName, request.params._meta);
|
|
16082
16158
|
const decision = await api.call("POST", `/decisions/${encodeURIComponent(String(decision_id))}/amend`, { ...rest, route: { channel_id: channelId, harness } });
|
|
16083
16159
|
lastChannel = channelId;
|
|
@@ -16112,7 +16188,7 @@ ${JSON.stringify(decision)}`, decision);
|
|
|
16112
16188
|
if (name === "get_attachment") {
|
|
16113
16189
|
const decisionId = String(args.decision_id);
|
|
16114
16190
|
const decision = await api.call("GET", `/decisions/${encodeURIComponent(decisionId)}`);
|
|
16115
|
-
const list = decision.answer?.attachments ?? [];
|
|
16191
|
+
const list = [...decision.request_attachments ?? [], ...decision.answer?.attachments ?? []];
|
|
16116
16192
|
const index = list.findIndex((a) => a.id === args.attachment_id);
|
|
16117
16193
|
if (index < 0) return text(`Approval Box: ${decisionId} \u306E\u7B54\u3048\u306B\u3001\u305D\u306E\u6DFB\u4ED8\u306F\u3042\u308A\u307E\u305B\u3093\u3002get_decision \u306E answer.attachments \u3092\u78BA\u304B\u3081\u3066\u304F\u3060\u3055\u3044\u3002`, { error: "not_found" }, true);
|
|
16118
16194
|
const meta = list[index];
|
|
@@ -16130,7 +16206,7 @@ ${JSON.stringify(decision)}`, decision);
|
|
|
16130
16206
|
const decision = await api.call("POST", "/setup-test", {
|
|
16131
16207
|
client: CLIENT_OF[harness],
|
|
16132
16208
|
os: osName(),
|
|
16133
|
-
session_label: `\u63A5\u7D9A\u30C6\u30B9\u30C8 ${
|
|
16209
|
+
session_label: `\u63A5\u7D9A\u30C6\u30B9\u30C8 ${basename3(process.cwd())} (${CLIENT_OF[harness]})`,
|
|
16134
16210
|
route: { channel_id: channelId, harness }
|
|
16135
16211
|
});
|
|
16136
16212
|
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`;
|
|
@@ -16177,12 +16253,6 @@ var FAILED_HINT = {
|
|
|
16177
16253
|
notify: "\u30A2\u30D7\u30EA\u306E\u901A\u77E5\u304C\u5C4A\u3044\u3066\u3044\u307E\u305B\u3093\u3002\u30A2\u30D7\u30EA\u306E\u901A\u77E5\u306E\u8A31\u53EF\u3092\u78BA\u304B\u3081\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
16178
16254
|
delivery: "\u7B54\u3048\u304CAI\u3078\u5C4A\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002npx approval-box doctor \u3067\u539F\u56E0\u3092\u78BA\u304B\u3081\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
16179
16255
|
};
|
|
16180
|
-
var STEER_LABEL = {
|
|
16181
|
-
ready: "\u4F5C\u696D\u4E2D\u306E\u5272\u308A\u8FBC\u307F\u3082\u4F7F\u3048\u307E\u3059",
|
|
16182
|
-
restart_required: "\u4F5C\u696D\u4E2D\u306E\u5272\u308A\u8FBC\u307F\u306F\u3001\u958B\u3044\u3066\u3044\u308BCodex\u3092\u3059\u3079\u3066\u9589\u3058\u3066\u958B\u304D\u76F4\u3059\u3068\u4F7F\u3048\u307E\u3059\u3002\u305D\u308C\u307E\u3067\u306F\u4F5C\u696D\u306E\u533A\u5207\u308A\u3067\u5C4A\u304D\u307E\u3059",
|
|
16183
|
-
disabled: "\u4F5C\u696D\u4E2D\u306E\u5272\u308A\u8FBC\u307F\u306F\u4F7F\u3044\u307E\u305B\u3093\u3002\u7B54\u3048\u306F\u4F5C\u696D\u306E\u533A\u5207\u308A\u3067\u5C4A\u304D\u307E\u3059",
|
|
16184
|
-
failed: "\u4F5C\u696D\u4E2D\u306E\u5272\u308A\u8FBC\u307F\u3092\u6709\u52B9\u306B\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u7B54\u3048\u306F\u4F5C\u696D\u306E\u533A\u5207\u308A\u3067\u5C4A\u304D\u307E\u3059\uFF08npx approval-box doctor \u3067\u539F\u56E0\u3092\u78BA\u304B\u3081\u3089\u308C\u307E\u3059\uFF09"
|
|
16185
|
-
};
|
|
16186
16256
|
async function ask(question) {
|
|
16187
16257
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
16188
16258
|
try {
|
|
@@ -16268,7 +16338,7 @@ async function setup() {
|
|
|
16268
16338
|
for (const target of targets) out(` ${LABEL[target]}: ${filesOf(target).join(", ")}`);
|
|
16269
16339
|
out("");
|
|
16270
16340
|
if (targets.includes("claude")) out("\u30FBClaude Code \u306E Stop hook \u306F\u3001\u3059\u3079\u3066\u306E\u4F1A\u8A71\u3067\u30BF\u30FC\u30F3\u304C\u7D42\u308F\u308B\u305F\u3073\u306B node \u30921\u56DE\u8D77\u52D5\u3057\u307E\u3059\uFF08Approval Box\u306E\u7533\u8ACB\u304C\u7121\u3051\u308C\u3070\u3059\u3050\u7D42\u308F\u308A\u307E\u3059\uFF09\u3002");
|
|
16271
|
-
if (targets.includes("codex")) out("\u30FBCodex \
|
|
16341
|
+
if (targets.includes("codex")) out("\u30FBCodex \u306E\u7B54\u3048\u306F Aiterm \u306E Steer \u3067\u5143\u306E\u4F1A\u8A71\u3078\u8FD4\u3057\u307E\u3059\u3002\u65E7\u7248\u306EApproval Box\u5C02\u7528\u914D\u9001hook\u306F\u64A4\u53BB\u3057\u307E\u3059\u3002");
|
|
16272
16342
|
if (targets.includes("cursor") || targets.includes("grok")) out("\u30FBCursor\uFF08\u6B62\u307E\u3063\u3066\u3044\u308B\u6642\uFF09\u3068 Grok \u306F\u3001\u7533\u8ACB\u306E\u6642\u306BAI\u304C\u80CC\u666F\u3067\u53D7\u4FE1\u3092\u8D77\u52D5\u3057\u307E\u3059\u3002");
|
|
16273
16343
|
out(`\u30FB\u66F8\u304D\u63DB\u3048\u308B\u524D\u306E\u30D5\u30A1\u30A4\u30EB\u306F\u300C${".approval-box-backup"}\u300D\u3092\u4ED8\u3051\u3066\u63A7\u3048\u307E\u3059\u3002\u5143\u306B\u623B\u3059\u306B\u306F npx approval-box uninstall\u3002
|
|
16274
16344
|
`);
|
|
@@ -16312,8 +16382,7 @@ async function registerTargets() {
|
|
|
16312
16382
|
let failed = false;
|
|
16313
16383
|
for (const target of targets) {
|
|
16314
16384
|
const result = await register(target, { instructions: flag("instructions") });
|
|
16315
|
-
|
|
16316
|
-
out(` ${LABEL[target]}: ${result.status === "registered" ? "\u767B\u9332\u3057\u307E\u3057\u305F" : `\u5931\u6557 \u2014 ${result.detail}`}${extra}`);
|
|
16385
|
+
out(` ${LABEL[target]}: ${result.status === "registered" ? "\u767B\u9332\u3057\u307E\u3057\u305F" : `\u5931\u6557 \u2014 ${result.detail}`}`);
|
|
16317
16386
|
if (result.note) out(` \u30FB${result.note}`);
|
|
16318
16387
|
if (result.status === "failed") failed = true;
|
|
16319
16388
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "approval-box",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.20",
|
|
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": "
|
|
35
|
+
"aiterm-steer-delivery": "0.3.0",
|
|
36
36
|
"esbuild": "^0.28.2",
|
|
37
37
|
"qrcode": "^1.5.4",
|
|
38
38
|
"typescript": "^6.0.3",
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { createRequire as __kbCreateRequire } from 'node:module'; const require = __kbCreateRequire(import.meta.url);
|
|
2
|
-
import {
|
|
3
|
-
PROFILE,
|
|
4
|
-
runCodexHookMain
|
|
5
|
-
} from "./chunks/chunk-GH2JG56Y.mjs";
|
|
6
|
-
|
|
7
|
-
// src/hooks/codex.ts
|
|
8
|
-
await runCodexHookMain(PROFILE, process.argv[2]);
|