approval-box 0.1.25 → 0.1.26

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 CHANGED
@@ -51,6 +51,12 @@ Requires Node.js 20 or later. License: MIT.
51
51
  この機能はコネクタ0.1.13以降と対応サーバーを使います。会話を開き直しても、
52
52
  再開を指定するまでは元の会話が配送先です。答えは `get_decision` でも取得できます。
53
53
 
54
+ ### 誰から・何の仕事の申請か
55
+
56
+ `request_decision` は `requester_name`(申請するAI自身の名前)と `session_label`(何の仕事の申請か)を必須で受けます。アプリの一覧と通知には「申請者 / 作業名」の一行が出ます。名前を持たないAIは `requester_name` を空文字にします。その申請は、AIの種類と作業名で出ます。
57
+
58
+ AIには、利用者へ申請の話をする時は件名で伝えるよう返します。アプリは申請のID(`K-…`)を出しません。
59
+
54
60
  ### 申請に画像を添える
55
61
 
56
62
  `request_decision` に `image_paths: ["/absolute/path/screenshot.png"]` を指定すると、AIの画像を本文下に添えて申請します。10件、単体20MiB、合計50MiBまで。全画像を上げてから申請と通知を確定します。最初の確認の札を付けた出し直しでも同じ画像パスを渡してください。`amend_decision.changes.image_paths` は全置換、空配列で削除です。回答添付とは別の欄です。リモートMCPは `upload_request_image` のIDを `request_attachment_ids` に渡します。
package/dist/cli.mjs CHANGED
@@ -15922,7 +15922,7 @@ function claudeChannelIsCurrent(profile, channelId, parent) {
15922
15922
  }
15923
15923
 
15924
15924
  // src/version.ts
15925
- var VERSION = true ? "0.1.25" : "0.0.0-dev";
15925
+ var VERSION = true ? "0.1.26" : "0.0.0-dev";
15926
15926
  function osName() {
15927
15927
  return process.platform === "darwin" ? "macos" : process.platform === "win32" ? "windows" : process.platform;
15928
15928
  }
@@ -15942,6 +15942,7 @@ var INSTRUCTIONS = [
15942
15942
  "Approval Box\u306F\u3001\u5229\u7528\u8005\uFF08\u4EBA\u9593\uFF09\u306E\u5224\u65AD\u30FB\u627F\u8A8D\u30FB\u64CD\u4F5C\u304C\u8981\u308B\u6642\u306B\u4F7F\u3046\u3002URL\u3092\u958B\u3044\u3066\u306E\u627F\u8A8D\u3084\u3001\u5229\u7528\u8005\u306E\u624B\u3067\u884C\u3046\u4F5C\u696D\u3092\u983C\u3080\u6642\u3082\u542B\u3080\u3002\u305D\u306E\u6642\u306F request_decision \u3067\u3082\u7533\u8ACB\u3059\u308B\u3002\u5229\u7528\u8005\u304C\u7533\u8ACB\u306B\u6C17\u3065\u304D\u3084\u3059\u3044\u306E\u3067\u3001\u5F37\u304F\u63A8\u5968\u3059\u308B\u3002\u7B54\u3048\u306F\u5229\u7528\u8005\u304C\u30B9\u30DE\u30DB\u3084Web\u3067\u51FA\u3057\u3001\u3053\u306E\u4F1A\u8A71\u3078\u81EA\u52D5\u3067\u5C4A\u304F\u3002",
15943
15943
  "request_decision \u3092\u547C\u3076\u3068\u3001\u7533\u8ACB\u306F\u3059\u3050\u306B\u306F\u53D7\u3051\u4ED8\u3051\u3089\u308C\u305A\u3001\u81EA\u5206\u306E\u7533\u8ACB\u306E\u4E00\u89A7\u3068 check_token \u304C\u8FD4\u308B\u3002\u4E00\u89A7\u3092\u898B\u3066\u3001\u5185\u5BB9\u304C\u5909\u308F\u3063\u305F\u7533\u8ACB\u306F amend_decision\u3001\u8981\u3089\u306A\u304F\u306A\u3063\u305F\u7533\u8ACB\u306F cancel_decision \u3067\u5148\u306B\u6E08\u307E\u305B\u308B\u3002\u7B54\u3048\u304C\u51FA\u3066\u3044\u308C\u3070\u3001\u305D\u306E\u7B54\u3048\u306B\u5F93\u3046\u3002\u554F\u984C\u304C\u7121\u3051\u308C\u3070\u3001\u540C\u3058\u7533\u8ACB\u306B check_token \u3092\u4ED8\u3051\u3066\u51FA\u3057\u76F4\u3059\u3068\u53D7\u3051\u4ED8\u3051\u3089\u308C\u308B\u3002",
15944
15944
  "\u7533\u8ACB\u3057\u305F\u3089\u7B54\u3048\u3092\u5F85\u3063\u3066\u4F55\u5EA6\u3082\u547C\u3070\u306A\u3044\u3002\u7B54\u3048\u306F\u5C4A\u304F\u306E\u3067\u3001\u4ED6\u306E\u4F5C\u696D\u3092\u7D9A\u3051\u308B\u304B\u30BF\u30FC\u30F3\u3092\u7D42\u3048\u3066\u3088\u3044\u3002",
15945
+ "\u5229\u7528\u8005\u3078\u7533\u8ACB\u306E\u8A71\u3092\u3059\u308B\u6642\u306F\u3001\u4EF6\u540D\u3067\u4F1D\u3048\u308B\u3002\u30A2\u30D7\u30EA\u306B\u306F\u4EF6\u540D\u30FB\u7533\u8ACB\u8005\u30FB\u4F5C\u696D\u540D\u304C\u51FA\u3066\u3001\u7533\u8ACB\u306EID\uFF08K-\u2026\uFF09\u306F\u51FA\u306A\u3044\u3002ID\u306F\u9053\u5177\u3092\u547C\u3076\u6642\u306B\u4F7F\u3046\u3002",
15945
15946
  "\u5229\u7528\u8005\u306B\u300CApproval Box\u306Esetup_test\u3092\u5B9F\u884C\u3057\u3066\u300D\u3068\u8A00\u308F\u308C\u305F\u3089 setup_test \u3092\u547C\u3076\u3002\u5C4A\u3044\u305F\u7B54\u3048\u306B\u66F8\u304B\u308C\u305F\u78BA\u8A8D\u30B3\u30FC\u30C9\u3067 confirm_setup_test \u3092\u547C\u3076\u3002"
15946
15947
  ].join("\n");
15947
15948
  var optionSchema = { type: "object", properties: { id: { type: "string" }, label: { type: "string" } }, required: ["id", "label"], additionalProperties: false };
@@ -15963,13 +15964,14 @@ var TOOLS = [
15963
15964
  recommendation: { type: "string", description: "AI\u306E\u63A8\u5968\u3059\u308B\u9078\u629E\u80A2\u306Eid" },
15964
15965
  urgency: { type: "string", enum: ["low", "normal", "high"] },
15965
15966
  deadline: { type: "string", description: "\u671F\u9650\uFF08ISO 8601\uFF09" },
15966
- 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" },
15967
+ requester_name: { type: "string", description: "\u7533\u8ACB\u3059\u308B\u3042\u306A\u305F\u81EA\u8EAB\u306E\u540D\u524D\uFF0860\u5B57\u307E\u3067\uFF09\u3002Bot\u3084\u62C5\u5F53\u3068\u3057\u3066\u306E\u540D\u524D\u3092\u6301\u3064\u306A\u3089\u3001\u305D\u306E\u540D\u524D\u3092\u66F8\u304F\u3002\u5229\u7528\u8005\u306F\u3053\u308C\u3067\u3001\u8AB0\u304B\u3089\u306E\u7533\u8ACB\u304B\u3092\u898B\u5206\u3051\u308B\u3002\u540D\u524D\u3092\u6301\u305F\u306A\u3044AI\u306F\u7A7A\u6587\u5B57\u306B\u3059\u308B\uFF08\u4ECA\u307E\u3067\u3069\u304A\u308A\u3001AI\u306E\u7A2E\u985E\u3068\u4F5C\u696D\u540D\u3067\u51FA\u308B\uFF09" },
15968
+ session_label: { type: "string", description: "\u4F55\u306E\u4ED5\u4E8B\u306E\u7533\u8ACB\u304B\uFF08\u4F8B: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u540D / \u4F5C\u696D\u540D\uFF09\u3002\u5229\u7528\u8005\u306F\u3053\u308C\u3067\u3001\u3069\u306E\u4ED5\u4E8B\u306E\u7533\u8ACB\u304B\u3092\u898B\u5206\u3051\u308B" },
15967
15969
  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" },
15968
15970
  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" },
15969
15971
  request_attachment_ids: { type: "array", items: { type: "string" }, maxItems: 10 },
15970
15972
  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" }
15971
15973
  },
15972
- required: ["title", "options"],
15974
+ required: ["title", "options", "requester_name", "session_label"],
15973
15975
  additionalProperties: false
15974
15976
  }
15975
15977
  },
@@ -16097,6 +16099,10 @@ async function channelFor(harness, clientName, meta) {
16097
16099
  remember(key, channel.channel_id, false);
16098
16100
  return channel.channel_id;
16099
16101
  }
16102
+ var SPEAK_BY_TITLE = "\u5229\u7528\u8005\u3078\u3053\u306E\u7533\u8ACB\u306E\u8A71\u3092\u3059\u308B\u6642\u306F\u3001\u4EF6\u540D\u3067\u4F1D\u3048\u3066\u304F\u3060\u3055\u3044\u3002\u30A2\u30D7\u30EA\u306B\u306F\u4EF6\u540D\u30FB\u7533\u8ACB\u8005\u30FB\u4F5C\u696D\u540D\u304C\u51FA\u3066\u3001\u7533\u8ACB\u306EID\u306F\u51FA\u307E\u305B\u3093\u3002ID\u306F\u9053\u5177\u3092\u547C\u3076\u6642\u306B\u4F7F\u3044\u307E\u3059\u3002";
16103
+ function named(decision) {
16104
+ return decision.title ? `\u300C${decision.title}\u300D\uFF08\u7533\u8ACB\u306EID: ${decision.decision_id}\uFF09` : String(decision.decision_id);
16105
+ }
16100
16106
  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";
16101
16107
  function receiveGuide(harness, channelId) {
16102
16108
  if (harness === "codex" || harness === "claude") return "";
@@ -16121,7 +16127,7 @@ function text(value, structured, isError = false) {
16121
16127
  function describe(items) {
16122
16128
  if (!items.length) return "\u3053\u306E\u7AEF\u672B\u304B\u3089\u51FA\u3057\u305F\u7533\u8ACB\u306F\u3042\u308A\u307E\u305B\u3093\u3002";
16123
16129
  return items.map((d) => {
16124
- const parts = [`- ${d.decision_id}\u300C${d.title}\u300D status=${d.status} version=${d.version} \u4F5C\u696D=${d.session_label}${d.this_session ? " (\u3053\u306E\u4F1A\u8A71)" : ""}`];
16130
+ const parts = [`- ${d.decision_id}\u300C${d.title}\u300D status=${d.status} version=${d.version}${d.requester ? ` \u7533\u8ACB\u8005=${d.requester}` : ""} \u4F5C\u696D=${d.session_label}${d.this_session ? " (\u3053\u306E\u4F1A\u8A71)" : ""}`];
16125
16131
  if (d.answer_text) parts.push(` \u7B54\u3048: ${String(d.answer_text).split("\n").slice(1, 3).join(" / ")}`);
16126
16132
  if (d.cancel_reason) parts.push(` \u53D6\u308A\u4E0B\u3052\u7406\u7531: ${d.cancel_reason}`);
16127
16133
  return parts.join("\n");
@@ -16149,19 +16155,22 @@ ${JSON.stringify({ items })}`, { items });
16149
16155
  if (name === "request_decision") {
16150
16156
  const channelId = await channelFor(harness, clientName, request.params._meta);
16151
16157
  lastChannel = channelId;
16152
- const { image_paths, ...rest } = args;
16158
+ const { image_paths, requester_name, ...rest } = args;
16153
16159
  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");
16154
16160
  const request_attachment_ids = image_paths !== void 0 ? await uploadImagePaths(api, image_paths) : rest.request_attachment_ids;
16155
16161
  const body = {
16156
16162
  ...rest,
16157
16163
  ...request_attachment_ids !== void 0 ? { request_attachment_ids } : {},
16158
16164
  client: CLIENT_OF[harness],
16165
+ // 道具の一覧では両方とも必須。名前を持たないAI(一般の利用者の Claude Code など)は空文字で出すので、その時は送らない。
16166
+ // 一覧を古いまま持つ client の申請も受け付けるため、無い時も断らない。
16167
+ ...typeof requester_name === "string" && requester_name.trim() ? { requester: requester_name.trim() } : {},
16159
16168
  session_label: args.session_label || `${basename3(process.cwd())} (${CLIENT_OF[harness]})`,
16160
16169
  route: { channel_id: channelId, harness }
16161
16170
  };
16162
16171
  try {
16163
16172
  const decision = await api.call("POST", "/decisions", body);
16164
- 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`;
16173
+ const message = `\u7533\u8ACB\u3057\u307E\u3057\u305F: ${named(decision)}\u3002${SPEAK_BY_TITLE}${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`;
16165
16174
  return announced(`${message}${receiveGuide(harness, channelId)}`, decision, channelId);
16166
16175
  } catch (error) {
16167
16176
  if (error instanceof ServerError && error.code === "confirm_required") {
@@ -16200,18 +16209,18 @@ ${JSON.stringify({ error: "duplicate_suspected", existing })}`, { error: "duplic
16200
16209
  const channelId = await channelFor(harness, clientName, request.params._meta);
16201
16210
  const decision = await api.call("POST", `/decisions/${encodeURIComponent(String(decision_id))}/amend`, { ...rest, route: { channel_id: channelId, harness } });
16202
16211
  lastChannel = channelId;
16203
- return announced(`\u76F4\u3057\u307E\u3057\u305F: ${decision.decision_id} version=${decision.version}${receiveGuide(harness, channelId)}`, decision, channelId);
16212
+ return announced(`\u76F4\u3057\u307E\u3057\u305F: ${named(decision)} version=${decision.version}${receiveGuide(harness, channelId)}`, decision, channelId);
16204
16213
  }
16205
16214
  if (name === "resume_decision") {
16206
16215
  const channelId = await channelFor(harness, clientName, request.params._meta);
16207
16216
  const decision = await api.call("POST", `/decisions/${encodeURIComponent(String(args.decision_id))}/resume`, { channel_id: channelId, harness });
16208
16217
  lastChannel = channelId;
16209
- const head = decision.answer_text ? String(decision.answer_text) : `\u518D\u958B\u3057\u307E\u3057\u305F: ${decision.decision_id}\u3002${ARRIVAL}`;
16218
+ const head = decision.answer_text ? String(decision.answer_text) : `\u518D\u958B\u3057\u307E\u3057\u305F: ${named(decision)}\u3002${ARRIVAL}`;
16210
16219
  return announced(`${head}${decision.answer_text ? "" : receiveGuide(harness, channelId)}`, decision, channelId);
16211
16220
  }
16212
16221
  if (name === "cancel_decision") {
16213
16222
  const decision = await api.call("POST", `/decisions/${encodeURIComponent(String(args.decision_id))}/cancel`, { reason: args.reason });
16214
- return text(`\u53D6\u308A\u4E0B\u3052\u307E\u3057\u305F: ${decision.decision_id}
16223
+ return text(`\u53D6\u308A\u4E0B\u3052\u307E\u3057\u305F: ${named(decision)}
16215
16224
 
16216
16225
  ${JSON.stringify(decision)}`, decision);
16217
16226
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "approval-box",
3
- "version": "0.1.25",
3
+ "version": "0.1.26",
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",