approval-box 0.1.12 → 0.1.13
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 +11 -0
- package/dist/approval-box-claude-hook.mjs +1 -1
- package/dist/approval-box-codex-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-S4DEUZZH.mjs → chunk-YBOJCW6Y.mjs} +21 -1
- package/dist/cli.mjs +43 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,3 +35,14 @@ npx approval-box uninstall # remove everything and unlink this device / 全部
|
|
|
35
35
|
Self-hosted server: `npx -y approval-box@latest setup --server https://your-server`.
|
|
36
36
|
|
|
37
37
|
Requires Node.js 20 or later. License: MIT.
|
|
38
|
+
|
|
39
|
+
### 会話を開き直した時
|
|
40
|
+
|
|
41
|
+
`list_my_decisions` で、自分が引き継ぐ申請を確かめ、対象ごとに
|
|
42
|
+
`resume_decision({decision_id: "K-…"})` を呼びます。未決・保留なら今の会話へ
|
|
43
|
+
配送先を移し、回答済みなら答えを直接返します。同じ端末にある他の作業の申請は、
|
|
44
|
+
引き継ぐ対象に含めないでください。`amend_decision` も、修正が成功した時に配送先を
|
|
45
|
+
呼び出した会話へ更新します。Cursor・Grokでは、返る案内に従って背景の受信を起動します。
|
|
46
|
+
|
|
47
|
+
この機能はコネクタ0.1.13以降と対応サーバーを使います。会話を開き直しても、
|
|
48
|
+
再開を指定するまでは元の会話が配送先です。答えは `get_decision` でも取得できます。
|
|
@@ -2,7 +2,7 @@ import { createRequire as __kbCreateRequire } from 'node:module'; const require
|
|
|
2
2
|
import {
|
|
3
3
|
PROFILE,
|
|
4
4
|
runCodexHookMain
|
|
5
|
-
} from "./chunks/chunk-
|
|
5
|
+
} from "./chunks/chunk-YBOJCW6Y.mjs";
|
|
6
6
|
|
|
7
7
|
// src/hooks/codex.ts
|
|
8
8
|
await runCodexHookMain(PROFILE, process.argv[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-YBOJCW6Y.mjs";
|
|
6
6
|
|
|
7
7
|
// src/hooks/receive.ts
|
|
8
8
|
await runChannelReceiveMain(PROFILE);
|
|
@@ -43,7 +43,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
43
43
|
import { homedir } from "node:os";
|
|
44
44
|
import { join } from "node:path";
|
|
45
45
|
var MCP_SERVER = "approval-box";
|
|
46
|
-
var DISPATCH_TOOLS = ["request_decision", "setup_test"];
|
|
46
|
+
var DISPATCH_TOOLS = ["request_decision", "setup_test", "amend_decision", "resume_decision"];
|
|
47
47
|
var home = () => process.env.APPROVAL_BOX_HOME ?? join(homedir(), ".approval-box");
|
|
48
48
|
var stateRoot = () => join(home(), "state");
|
|
49
49
|
var HOOK_FILES = {
|
|
@@ -21019,6 +21019,25 @@ function channelDeliveryState(profile, channelId, deliveryId) {
|
|
|
21019
21019
|
}
|
|
21020
21020
|
return fs7.readdirSync(path10.join(dir, "inbox")).some((name) => name.endsWith(`-${deliveryId}.json`)) ? "queued" : null;
|
|
21021
21021
|
}
|
|
21022
|
+
function withdrawFromChannel(profile, channelId, deliveryId) {
|
|
21023
|
+
uuid3.parse(deliveryId);
|
|
21024
|
+
const dir = channelDir(profile, channelId);
|
|
21025
|
+
const inbox = path10.join(dir, "inbox");
|
|
21026
|
+
const name = fs7.existsSync(inbox) ? fs7.readdirSync(inbox).find((entry) => entry.endsWith(`-${deliveryId}.json`)) : void 0;
|
|
21027
|
+
if (!name)
|
|
21028
|
+
return false;
|
|
21029
|
+
const claim3 = path10.join(dir, "claims", `${deliveryId}.json`);
|
|
21030
|
+
try {
|
|
21031
|
+
fs7.linkSync(path10.join(inbox, name), claim3);
|
|
21032
|
+
fs7.unlinkSync(path10.join(inbox, name));
|
|
21033
|
+
} catch (error62) {
|
|
21034
|
+
if (["ENOENT", "EEXIST"].includes(error62.code ?? ""))
|
|
21035
|
+
return false;
|
|
21036
|
+
throw error62;
|
|
21037
|
+
}
|
|
21038
|
+
writeJson0600(claim3, { delivery_id: deliveryId, state: "withdrawn", at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
21039
|
+
return true;
|
|
21040
|
+
}
|
|
21022
21041
|
function claimPending(profile, channelId, by, limit = Infinity) {
|
|
21023
21042
|
const dir = channelDir(profile, channelId);
|
|
21024
21043
|
const inbox = path10.join(dir, "inbox");
|
|
@@ -21925,6 +21944,7 @@ export {
|
|
|
21925
21944
|
channelClosed,
|
|
21926
21945
|
sendToChannel,
|
|
21927
21946
|
channelDeliveryState,
|
|
21947
|
+
withdrawFromChannel,
|
|
21928
21948
|
channelMarker,
|
|
21929
21949
|
handleCursorChannelHook,
|
|
21930
21950
|
channelReceiveProcess,
|
package/dist/cli.mjs
CHANGED
|
@@ -51,8 +51,9 @@ import {
|
|
|
51
51
|
verifyCodexParent,
|
|
52
52
|
verifyCursorParent,
|
|
53
53
|
waitProcessCommandLine,
|
|
54
|
-
withCodexReceiver
|
|
55
|
-
|
|
54
|
+
withCodexReceiver,
|
|
55
|
+
withdrawFromChannel
|
|
56
|
+
} from "./chunks/chunk-YBOJCW6Y.mjs";
|
|
56
57
|
|
|
57
58
|
// ../../node_modules/qrcode/lib/can-promise.js
|
|
58
59
|
var require_can_promise = __commonJS({
|
|
@@ -12074,7 +12075,24 @@ async function runDaemon() {
|
|
|
12074
12075
|
again = false;
|
|
12075
12076
|
try {
|
|
12076
12077
|
const { items } = await api.call("GET", "/deliveries");
|
|
12077
|
-
|
|
12078
|
+
const waiting = new Map(items.map((item) => [item.decision_id, item]));
|
|
12079
|
+
for (const [id, entry] of Object.entries(journal)) {
|
|
12080
|
+
if (entry.state !== "queued") continue;
|
|
12081
|
+
const item = waiting.get(id);
|
|
12082
|
+
if (item && item.delivery_id === entry.delivery_id && item.route.channel_id === entry.channel_id) continue;
|
|
12083
|
+
const withdrawn = withdrawFromChannel(PROFILE, entry.channel_id, entry.delivery_id);
|
|
12084
|
+
if (withdrawn || !item) {
|
|
12085
|
+
delete journal[id];
|
|
12086
|
+
save();
|
|
12087
|
+
log(`\u914D\u9001 ${id} \u2192 ${withdrawn ? "withdrawn" : "resolved"}`);
|
|
12088
|
+
} else {
|
|
12089
|
+
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" });
|
|
12090
|
+
save();
|
|
12091
|
+
await report(id);
|
|
12092
|
+
waiting.delete(id);
|
|
12093
|
+
}
|
|
12094
|
+
}
|
|
12095
|
+
for (const item of waiting.values()) await deliver(item);
|
|
12078
12096
|
} catch (error) {
|
|
12079
12097
|
log(`\u914D\u9001\u5F85\u3061\u306E\u53D6\u5F97\u306B\u5931\u6557: ${error.message}`);
|
|
12080
12098
|
}
|
|
@@ -12247,7 +12265,7 @@ function stableNode() {
|
|
|
12247
12265
|
return process.execPath;
|
|
12248
12266
|
}
|
|
12249
12267
|
}
|
|
12250
|
-
var CURSOR_TOOLS = ["list_my_decisions", "request_decision", "amend_decision", "cancel_decision", "get_decision", "get_attachment", "setup_test", "confirm_setup_test"];
|
|
12268
|
+
var CURSOR_TOOLS = ["list_my_decisions", "request_decision", "amend_decision", "resume_decision", "cancel_decision", "get_decision", "get_attachment", "setup_test", "confirm_setup_test"];
|
|
12251
12269
|
var cursorCliConfig = () => join6(cursorDir(), "cli-config.json");
|
|
12252
12270
|
function setCursorPermissions(enable) {
|
|
12253
12271
|
const file = cursorCliConfig();
|
|
@@ -15770,7 +15788,7 @@ import { existsSync as existsSync6, readFileSync as readFileSync6 } from "node:f
|
|
|
15770
15788
|
import { basename as basename2, join as join7 } from "node:path";
|
|
15771
15789
|
|
|
15772
15790
|
// src/version.ts
|
|
15773
|
-
var VERSION = true ? "0.1.
|
|
15791
|
+
var VERSION = true ? "0.1.13" : "0.0.0-dev";
|
|
15774
15792
|
function osName() {
|
|
15775
15793
|
return process.platform === "darwin" ? "macos" : process.platform === "win32" ? "windows" : process.platform;
|
|
15776
15794
|
}
|
|
@@ -15786,6 +15804,7 @@ function harnessOf(clientName) {
|
|
|
15786
15804
|
return "other";
|
|
15787
15805
|
}
|
|
15788
15806
|
var INSTRUCTIONS = [
|
|
15807
|
+
"\u4F1A\u8A71\u304C\u66FF\u308F\u3063\u305F\u3089 list_my_decisions \u3067\u81EA\u5206\u304C\u5F15\u304D\u7D99\u3050\u7533\u8ACB\u3092\u78BA\u304B\u3081\u3001\u7533\u8ACB\u3054\u3068\u306B resume_decision \u3092\u547C\u3076\u3002\u672A\u6C7A\u30FB\u4FDD\u7559\u306E\u7B54\u3048\u306F\u65B0\u3057\u3044\u4F1A\u8A71\u3078\u5C4A\u304D\u3001\u56DE\u7B54\u6E08\u307F\u306A\u3089\u305D\u306E\u5834\u3067\u7B54\u3048\u304C\u8FD4\u308B\u3002",
|
|
15789
15808
|
"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",
|
|
15790
15809
|
"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",
|
|
15791
15810
|
"\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",
|
|
@@ -15844,6 +15863,11 @@ var TOOLS = [
|
|
|
15844
15863
|
additionalProperties: false
|
|
15845
15864
|
}
|
|
15846
15865
|
},
|
|
15866
|
+
{
|
|
15867
|
+
name: "resume_decision",
|
|
15868
|
+
description: "\u524D\u306E\u4F1A\u8A71\u304B\u3089\u5F15\u304D\u7D99\u3044\u3060\u81EA\u5206\u306E\u7533\u8ACB\u3092\u3001\u3053\u306E\u4F1A\u8A71\u3067\u518D\u958B\u3059\u308B\u3002\u672A\u6C7A\u30FB\u4FDD\u7559\u306A\u3089\u7B54\u3048\u306E\u914D\u9001\u5148\u3092\u3053\u306E\u4F1A\u8A71\u3078\u5909\u66F4\u3057\u3001\u56DE\u7B54\u6E08\u307F\u306A\u3089\u7B54\u3048\u3092\u76F4\u63A5\u8FD4\u3059\u3002list_my_decisions\u3067\u5BFE\u8C61\u3092\u78BA\u304B\u3081\u3001\u5F15\u304D\u7D99\u3050\u7533\u8ACB\u3054\u3068\u306B\u547C\u3076\u3002",
|
|
15869
|
+
inputSchema: { type: "object", properties: { decision_id: { type: "string" } }, required: ["decision_id"], additionalProperties: false }
|
|
15870
|
+
},
|
|
15847
15871
|
{
|
|
15848
15872
|
name: "cancel_decision",
|
|
15849
15873
|
description: "\u672A\u6C7A\u30FB\u4FDD\u7559\u306E\u81EA\u5206\u306E\u7533\u8ACB\u3092\u53D6\u308A\u4E0B\u3052\u308B\u3002reason \u306B\u7406\u7531\u3092\u66F8\u304F\u3002",
|
|
@@ -16028,10 +16052,21 @@ ${JSON.stringify({ error: "duplicate_suspected", existing })}`, { error: "duplic
|
|
|
16028
16052
|
}
|
|
16029
16053
|
if (name === "amend_decision") {
|
|
16030
16054
|
const { decision_id, ...rest } = args;
|
|
16031
|
-
const
|
|
16032
|
-
|
|
16055
|
+
const channelId = await channelFor(harness, clientName, request.params._meta);
|
|
16056
|
+
const decision = await api.call("POST", `/decisions/${encodeURIComponent(String(decision_id))}/amend`, { ...rest, route: { channel_id: channelId, harness } });
|
|
16057
|
+
lastChannel = channelId;
|
|
16058
|
+
return text(`\u76F4\u3057\u307E\u3057\u305F: ${decision.decision_id} version=${decision.version}${receiveGuide(harness, channelId)}
|
|
16033
16059
|
|
|
16034
|
-
${JSON.stringify(decision)}`, decision);
|
|
16060
|
+
${JSON.stringify(decision)}`, { ...decision, steer_channel: { channel_id: channelId } });
|
|
16061
|
+
}
|
|
16062
|
+
if (name === "resume_decision") {
|
|
16063
|
+
const channelId = await channelFor(harness, clientName, request.params._meta);
|
|
16064
|
+
const decision = await api.call("POST", `/decisions/${encodeURIComponent(String(args.decision_id))}/resume`, { channel_id: channelId, harness });
|
|
16065
|
+
lastChannel = channelId;
|
|
16066
|
+
const head = decision.answer_text ? String(decision.answer_text) : `\u518D\u958B\u3057\u307E\u3057\u305F: ${decision.decision_id}\u3002\u7B54\u3048\u306F\u3053\u306E\u4F1A\u8A71\u3078\u5C4A\u304D\u307E\u3059\u3002`;
|
|
16067
|
+
return text(`${head}${decision.answer_text ? "" : receiveGuide(harness, channelId)}
|
|
16068
|
+
|
|
16069
|
+
${JSON.stringify(decision)}`, { ...decision, steer_channel: { channel_id: channelId } });
|
|
16035
16070
|
}
|
|
16036
16071
|
if (name === "cancel_decision") {
|
|
16037
16072
|
const decision = await api.call("POST", `/decisions/${encodeURIComponent(String(args.decision_id))}/cancel`, { reason: args.reason });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "approval-box",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
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",
|