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/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-GH2JG56Y.mjs";
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 open = dijkstra.PriorityQueue.make();
1338
- open.push(s, 0);
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 (!open.empty()) {
1341
- closest = open.pop();
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
- open.push(v, cost_of_s_to_u_plus_cost_of_e);
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
- if (channelClosed(PROFILE, item.route.channel_id)) throw Object.assign(new Error("\u7533\u8ACB\u3092\u51FA\u3057\u305FAI\u306E\u4F1A\u8A71\u304C\u7D42\u308F\u3063\u3066\u3044\u307E\u3059"), { closed: true });
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 channelDeliveryState(PROFILE, entry.channel_id, entry.delivery_id);
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 open = items.some((d) => d.status === "pending" || d.status === "held");
12175
- if (open || Object.keys(journal).length) idleSince = Date.now();
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
- let steerStatus;
12378
- try {
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 basename2, join as join8 } from "node:path";
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.17" : "0.0.0-dev";
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
- ...args,
16111
+ ...rest,
16112
+ ...request_attachment_ids !== void 0 ? { request_attachment_ids } : {},
16041
16113
  client: CLIENT_OF[harness],
16042
- session_label: args.session_label || `${basename2(process.cwd())} (${CLIENT_OF[harness]})`,
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 ${basename2(process.cwd())} (${CLIENT_OF[harness]})`,
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 \u306F\u3001\u4F5C\u696D\u4E2D\u306B\u7B54\u3048\u3092\u5272\u308A\u8FBC\u307E\u305B\u308B\u305F\u3081 hook \u3082\u767B\u9332\u3057\u307E\u3059\u3002\u767B\u9332\u5F8C\u306B Codex \u306E\u518D\u8D77\u52D5\u304C\u8981\u308B\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002");
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
- const extra = result.steer ? `\uFF08${STEER_LABEL[result.steer.split(":")[0] ?? ""] ?? `\u4F5C\u696D\u4E2D\u306E\u5272\u308A\u8FBC\u307F: ${result.steer}`}\uFF09` : "";
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.17",
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": "^0.2.0",
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]);