approval-box 0.1.2 → 0.1.4
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 +4 -2
- package/dist/cli.mjs +93 -29
- package/package.json +9 -1
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# approval-box
|
|
2
2
|
|
|
3
|
-
Approval Box connector. When an AI coding agent needs a human decision, it files a request to Approval Box
|
|
3
|
+
Approval Box connector. When an AI coding agent needs a human decision, approval or action, it also files a request to Approval Box. You answer from the Approval Box app or web, and the answer is delivered straight back into the same agent session — mid-turn if the agent is working, as a new turn if it is idle. The agent never polls.
|
|
4
4
|
|
|
5
5
|
Supported agents: Claude Code, Codex, Cursor, Grok — on macOS, Windows and Linux.
|
|
6
6
|
|
|
7
|
-
AI
|
|
7
|
+
AIが人間の判断・承認・操作を求める時に、Approval Boxへも申請します。アプリかWeb版で答えると、その答えが申請したAIの会話へそのまま届きます。
|
|
8
8
|
|
|
9
9
|
## Setup / 使い方
|
|
10
10
|
|
|
@@ -14,6 +14,8 @@ npx -y approval-box@latest setup
|
|
|
14
14
|
|
|
15
15
|
1. `setup` finds the agents on this machine and registers Approval Box (MCP server and hooks). It shows the files it will change and keeps a backup (`*.approval-box-backup`) before writing.
|
|
16
16
|
PCにあるAIを見つけて登録します。書き換えるファイルを先に見せ、控えを残してから書き換えます。
|
|
17
|
+
It also offers to add one short paragraph to each agent's global instructions (`~/.claude/CLAUDE.md`, `$CODEX_HOME/AGENTS.md`, `~/.grok/AGENTS.md`) so the agent also files decisions, approvals and actions with `request_decision`. Cursor reads these from Settings → Rules → User Rules, so setup shows the text to paste. Skip with `--no-instructions`.
|
|
18
|
+
AIが毎回読む全体の指示に「判断・承認・操作が要る時は request_decision でも申請する」という一節を足すかを聞きます。Cursor は Settings → Rules → User Rules に貼る一文を案内します。足さない時は `--no-instructions`。
|
|
17
19
|
2. Scan the QR code or enter the code in “Add device” in the app or web.
|
|
18
20
|
画面のQRコードかコードを、アプリかWeb版の「端末を追加」で読み取ります。
|
|
19
21
|
3. Tell your agent: `Approval Boxのsetup_testを実行して` (or “run Approval Box setup_test”). Answer the test request; when the answer reaches the agent, you are ready.
|
package/dist/cli.mjs
CHANGED
|
@@ -11754,7 +11754,7 @@ var require_dist = __commonJS({
|
|
|
11754
11754
|
|
|
11755
11755
|
// src/cli.ts
|
|
11756
11756
|
var import_qrcode = __toESM(require_lib(), 1);
|
|
11757
|
-
import { cpSync, existsSync as
|
|
11757
|
+
import { cpSync, existsSync as existsSync6, mkdirSync as mkdirSync4, rmSync as rmSync2 } from "node:fs";
|
|
11758
11758
|
import { hostname } from "node:os";
|
|
11759
11759
|
import { join as join6 } from "node:path";
|
|
11760
11760
|
import { createInterface } from "node:readline/promises";
|
|
@@ -12048,9 +12048,41 @@ async function runDaemon() {
|
|
|
12048
12048
|
|
|
12049
12049
|
// src/harness.ts
|
|
12050
12050
|
import { execFileSync } from "node:child_process";
|
|
12051
|
-
import { copyFileSync, existsSync as
|
|
12051
|
+
import { copyFileSync, existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
|
|
12052
12052
|
import { homedir } from "node:os";
|
|
12053
|
-
import { delimiter, dirname as
|
|
12053
|
+
import { delimiter, dirname as dirname4, join as join4 } from "node:path";
|
|
12054
|
+
|
|
12055
|
+
// src/instructions.ts
|
|
12056
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "node:fs";
|
|
12057
|
+
import { dirname as dirname3 } from "node:path";
|
|
12058
|
+
var INSTRUCTION_TEXT = "\u30E6\u30FC\u30B6\u30FC\u306E\u5224\u65AD\u30FB\u627F\u8A8D\u30FB\u64CD\u4F5C\u304C\u5FC5\u8981\u306A\u3068\u304D\u306F\u3001\u6C7A\u88C1\u30B7\u30B9\u30C6\u30E0\u3067\u3042\u308B Approval Box \u306E request_decision \u3067\u3082\u7533\u8ACB\u3059\u308B\u3002\u3053\u308C\u3092\u4F7F\u3048\u3070\u30E6\u30FC\u30B6\u30FC\u304C\u7533\u8ACB\u306B\u6C17\u3065\u304D\u3084\u3059\u3044\u306E\u3067\u3001\u5F37\u304F\u63A8\u5968\u3059\u308B\u3002";
|
|
12059
|
+
var START = "<!-- approval-box:start -->";
|
|
12060
|
+
var END = "<!-- approval-box:end -->";
|
|
12061
|
+
var BLOCK = `${START}
|
|
12062
|
+
## Approval Box
|
|
12063
|
+
|
|
12064
|
+
${INSTRUCTION_TEXT}
|
|
12065
|
+
${END}
|
|
12066
|
+
`;
|
|
12067
|
+
var PATTERN = new RegExp(`\\n*${START}[\\s\\S]*?${END}\\n?`, "g");
|
|
12068
|
+
function hasInstructions(file) {
|
|
12069
|
+
return existsSync3(file) && readFileSync3(file, "utf8").includes(START);
|
|
12070
|
+
}
|
|
12071
|
+
function writeInstructions(file) {
|
|
12072
|
+
const current = existsSync3(file) ? readFileSync3(file, "utf8").replace(PATTERN, "\n").trimEnd() : "";
|
|
12073
|
+
mkdirSync3(dirname3(file), { recursive: true, mode: 448 });
|
|
12074
|
+
writeFileSync2(file, current ? `${current}
|
|
12075
|
+
|
|
12076
|
+
${BLOCK}` : BLOCK);
|
|
12077
|
+
}
|
|
12078
|
+
function removeInstructions(file) {
|
|
12079
|
+
if (!hasInstructions(file)) return;
|
|
12080
|
+
const rest = readFileSync3(file, "utf8").replace(PATTERN, "\n").trimEnd();
|
|
12081
|
+
writeFileSync2(file, rest ? `${rest}
|
|
12082
|
+
` : "");
|
|
12083
|
+
}
|
|
12084
|
+
|
|
12085
|
+
// src/harness.ts
|
|
12054
12086
|
var HARNESSES = ["claude", "codex", "cursor", "grok"];
|
|
12055
12087
|
var LABEL = { claude: "Claude Code", codex: "Codex", cursor: "Cursor", grok: "Grok" };
|
|
12056
12088
|
var CLIENT = { claude: "claude-code", codex: "codex", cursor: "cursor", grok: "grok" };
|
|
@@ -12065,18 +12097,24 @@ function filesOf(target) {
|
|
|
12065
12097
|
if (target === "codex") return [join4(codexHome(), "config.toml"), join4(codexHome(), "hooks.json")];
|
|
12066
12098
|
return [join4(grokDir(), "config.toml")];
|
|
12067
12099
|
}
|
|
12100
|
+
function instructionsFileOf(target) {
|
|
12101
|
+
if (target === "claude") return join4(claudeDir(), "CLAUDE.md");
|
|
12102
|
+
if (target === "codex") return join4(codexHome(), "AGENTS.md");
|
|
12103
|
+
if (target === "grok") return join4(grokDir(), "AGENTS.md");
|
|
12104
|
+
return null;
|
|
12105
|
+
}
|
|
12068
12106
|
function onPath(command2) {
|
|
12069
12107
|
const names = process.platform === "win32" ? [`${command2}.exe`, `${command2}.cmd`, command2] : [command2];
|
|
12070
12108
|
for (const dir of (process.env.PATH ?? "").split(delimiter)) {
|
|
12071
|
-
for (const name of names) if (dir &&
|
|
12109
|
+
for (const name of names) if (dir && existsSync4(join4(dir, name))) return join4(dir, name);
|
|
12072
12110
|
}
|
|
12073
12111
|
return null;
|
|
12074
12112
|
}
|
|
12075
12113
|
function detect(target) {
|
|
12076
|
-
if (target === "claude") return
|
|
12077
|
-
if (target === "codex") return
|
|
12078
|
-
if (target === "cursor") return
|
|
12079
|
-
return
|
|
12114
|
+
if (target === "claude") return existsSync4(claudeDir()) || !!onPath("claude");
|
|
12115
|
+
if (target === "codex") return existsSync4(codexHome()) || !!onPath("codex");
|
|
12116
|
+
if (target === "cursor") return existsSync4(cursorDir()) || !!onPath("cursor-agent");
|
|
12117
|
+
return existsSync4(grokDir()) || !!onPath("grok");
|
|
12080
12118
|
}
|
|
12081
12119
|
function stableNode() {
|
|
12082
12120
|
try {
|
|
@@ -12089,7 +12127,7 @@ var CURSOR_TOOLS = ["list_my_decisions", "request_decision", "amend_decision", "
|
|
|
12089
12127
|
var cursorCliConfig = () => join4(cursorDir(), "cli-config.json");
|
|
12090
12128
|
function setCursorPermissions(enable) {
|
|
12091
12129
|
const file = cursorCliConfig();
|
|
12092
|
-
if (!
|
|
12130
|
+
if (!existsSync4(file) && !enable) return;
|
|
12093
12131
|
backupOnce(file);
|
|
12094
12132
|
const current = readJson(file);
|
|
12095
12133
|
const permissions = current.permissions ?? {};
|
|
@@ -12100,12 +12138,12 @@ function setCursorPermissions(enable) {
|
|
|
12100
12138
|
}
|
|
12101
12139
|
var registration = () => ({ command: stableNode(), args: [runtimeEntry("cli"), "mcp"] });
|
|
12102
12140
|
function readJson(file) {
|
|
12103
|
-
if (!
|
|
12104
|
-
return JSON.parse(
|
|
12141
|
+
if (!existsSync4(file)) return {};
|
|
12142
|
+
return JSON.parse(readFileSync4(file, "utf8").replace(/^/, ""));
|
|
12105
12143
|
}
|
|
12106
12144
|
function backupOnce(file) {
|
|
12107
12145
|
const copy = `${file}${PROFILE.backup_suffix}`;
|
|
12108
|
-
if (
|
|
12146
|
+
if (existsSync4(file) && !existsSync4(copy)) copyFileSync(file, copy);
|
|
12109
12147
|
}
|
|
12110
12148
|
function setMcpJson(file, value) {
|
|
12111
12149
|
backupOnce(file);
|
|
@@ -12118,7 +12156,15 @@ function setMcpJson(file, value) {
|
|
|
12118
12156
|
async function withCodexConfig(fn) {
|
|
12119
12157
|
return withCodexReceiver(PROFILE, { thread_id: "00000000-0000-4000-8000-000000000000", codex_home: codexHome() }, fn);
|
|
12120
12158
|
}
|
|
12121
|
-
async function register(target) {
|
|
12159
|
+
async function register(target, options = {}) {
|
|
12160
|
+
const file = instructionsFileOf(target);
|
|
12161
|
+
if (options.instructions && file) {
|
|
12162
|
+
try {
|
|
12163
|
+
writeInstructions(file);
|
|
12164
|
+
} catch (error) {
|
|
12165
|
+
return { target, status: "failed", detail: `${file}: ${error.message}` };
|
|
12166
|
+
}
|
|
12167
|
+
}
|
|
12122
12168
|
const hook = (kind) => ({ command: stableNode(), script: runtimeEntry(kind) });
|
|
12123
12169
|
try {
|
|
12124
12170
|
if (target === "claude") {
|
|
@@ -12159,15 +12205,17 @@ async function register(target) {
|
|
|
12159
12205
|
}
|
|
12160
12206
|
async function unregister(target) {
|
|
12161
12207
|
try {
|
|
12208
|
+
const file = instructionsFileOf(target);
|
|
12209
|
+
if (file) removeInstructions(file);
|
|
12162
12210
|
if (target === "claude") {
|
|
12163
|
-
if (
|
|
12211
|
+
if (existsSync4(claudeJson())) setMcpJson(claudeJson(), null);
|
|
12164
12212
|
removeClaudeParentHooks(PROFILE, join4(claudeDir(), "settings.json"));
|
|
12165
12213
|
} else if (target === "cursor") {
|
|
12166
|
-
if (
|
|
12214
|
+
if (existsSync4(join4(cursorDir(), "mcp.json"))) setMcpJson(join4(cursorDir(), "mcp.json"), null);
|
|
12167
12215
|
removeCursorParentHooks(PROFILE, join4(cursorDir(), "hooks.json"));
|
|
12168
12216
|
setCursorPermissions(false);
|
|
12169
12217
|
} else if (target === "codex") {
|
|
12170
|
-
if (
|
|
12218
|
+
if (existsSync4(join4(codexHome(), "config.toml"))) {
|
|
12171
12219
|
await withCodexConfig(async (request) => {
|
|
12172
12220
|
await request("config/batchWrite", { filePath: join4(codexHome(), "config.toml"), edits: [{ keyPath: `mcp_servers.${MCP_SERVER}`, value: null, mergeStrategy: "replace" }] });
|
|
12173
12221
|
});
|
|
@@ -12186,6 +12234,10 @@ async function unregister(target) {
|
|
|
12186
12234
|
}
|
|
12187
12235
|
}
|
|
12188
12236
|
function registered(target) {
|
|
12237
|
+
const file = instructionsFileOf(target);
|
|
12238
|
+
return { ...registeredTools(target), instructions: file ? hasInstructions(file) : null };
|
|
12239
|
+
}
|
|
12240
|
+
function registeredTools(target) {
|
|
12189
12241
|
const entryOf = (value) => (value?.args ?? [])[0];
|
|
12190
12242
|
if (target === "claude") {
|
|
12191
12243
|
const entry = readJson(claudeJson()).mcpServers?.[MCP_SERVER];
|
|
@@ -12199,10 +12251,10 @@ function registered(target) {
|
|
|
12199
12251
|
return { mcp: !!entry, hooks: cursorParentHooksRegistered(PROFILE, readJson(join4(cursorDir(), "hooks.json"))), ...e ? { entry: e } : {} };
|
|
12200
12252
|
}
|
|
12201
12253
|
if (target === "codex") {
|
|
12202
|
-
const toml2 =
|
|
12254
|
+
const toml2 = existsSync4(join4(codexHome(), "config.toml")) ? readFileSync4(join4(codexHome(), "config.toml"), "utf8") : "";
|
|
12203
12255
|
return { mcp: toml2.includes(`[mcp_servers.${MCP_SERVER}]`), hooks: null };
|
|
12204
12256
|
}
|
|
12205
|
-
const toml =
|
|
12257
|
+
const toml = existsSync4(join4(grokDir(), "config.toml")) ? readFileSync4(join4(grokDir(), "config.toml"), "utf8") : "";
|
|
12206
12258
|
return { mcp: toml.includes(MCP_SERVER), hooks: null };
|
|
12207
12259
|
}
|
|
12208
12260
|
|
|
@@ -15566,11 +15618,11 @@ var StdioServerTransport = class {
|
|
|
15566
15618
|
};
|
|
15567
15619
|
|
|
15568
15620
|
// src/mcp.ts
|
|
15569
|
-
import { existsSync as
|
|
15621
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5 } from "node:fs";
|
|
15570
15622
|
import { basename as basename2, join as join5 } from "node:path";
|
|
15571
15623
|
|
|
15572
15624
|
// src/version.ts
|
|
15573
|
-
var VERSION = true ? "0.1.
|
|
15625
|
+
var VERSION = true ? "0.1.4" : "0.0.0-dev";
|
|
15574
15626
|
function osName() {
|
|
15575
15627
|
return process.platform === "darwin" ? "macos" : process.platform === "win32" ? "windows" : process.platform;
|
|
15576
15628
|
}
|
|
@@ -15586,7 +15638,7 @@ function harnessOf(clientName) {
|
|
|
15586
15638
|
return "other";
|
|
15587
15639
|
}
|
|
15588
15640
|
var INSTRUCTIONS = [
|
|
15589
|
-
"Approval Box\u306F\u3001\u5229\u7528\u8005\uFF08\u4EBA\u9593\uFF09\u306E\u5224\u65AD\u304C\u8981\u308B\u6642\u306B\u4F7F\u3046\
|
|
15641
|
+
"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",
|
|
15590
15642
|
"\u7533\u8ACB\u306E\u524D\u306B\u5FC5\u305A list_my_decisions \u3067\u81EA\u5206\u306E\u7533\u8ACB\u3092\u898B\u308B\u3002\u540C\u3058\u4EF6\u304C\u672A\u6C7A\u30FB\u4FDD\u7559\u306B\u3042\u308C\u3070\u65B0\u3057\u304F\u51FA\u3055\u306A\u3044\u3002\u5185\u5BB9\u304C\u5909\u308F\u3063\u305F\u306A\u3089 amend_decision\u3001\u8981\u3089\u306A\u304F\u306A\u3063\u305F\u306A\u3089 cancel_decision\u3002\u7B54\u3048\u304C\u51FA\u3066\u3044\u308C\u3070\u3001\u305D\u306E\u7B54\u3048\u306B\u5F93\u3046\u3002\u307E\u3060\u7121\u3044\u4EF6\u3060\u3051\u3092 request_decision \u3067\u7533\u8ACB\u3059\u308B\u3002",
|
|
15591
15643
|
"\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",
|
|
15592
15644
|
"\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"
|
|
@@ -15669,7 +15721,7 @@ var processChannels = /* @__PURE__ */ new Map();
|
|
|
15669
15721
|
var lastChannel;
|
|
15670
15722
|
function savedParents() {
|
|
15671
15723
|
try {
|
|
15672
|
-
return
|
|
15724
|
+
return existsSync5(parentsFile()) ? JSON.parse(readFileSync5(parentsFile(), "utf8")) : {};
|
|
15673
15725
|
} catch {
|
|
15674
15726
|
return {};
|
|
15675
15727
|
}
|
|
@@ -15895,7 +15947,7 @@ function installRuntime() {
|
|
|
15895
15947
|
const target = join6(home(), "runtime", VERSION);
|
|
15896
15948
|
if (runtimeDir() !== target) {
|
|
15897
15949
|
rmSync2(target, { recursive: true, force: true });
|
|
15898
|
-
|
|
15950
|
+
mkdirSync4(target, { recursive: true });
|
|
15899
15951
|
cpSync(runtimeDir(), target, { recursive: true });
|
|
15900
15952
|
}
|
|
15901
15953
|
return join6(target, "cli.mjs");
|
|
@@ -15976,6 +16028,13 @@ async function setup() {
|
|
|
15976
16028
|
out("\u3084\u3081\u307E\u3057\u305F\u3002");
|
|
15977
16029
|
return;
|
|
15978
16030
|
}
|
|
16031
|
+
out("\nAI\u304C\u6BCE\u56DE\u8AAD\u3080\u5168\u4F53\u306E\u6307\u793A\u306B\u3001\u6B21\u306E\u4E00\u7BC0\u3092\u8DB3\u3059\u3068\u3001AI\u304CApproval Box\u3092\u4F7F\u3046\u3088\u3046\u306B\u306A\u308A\u307E\u3059\uFF08\u5916\u3059\u6642\u306F uninstall\uFF09\u3002");
|
|
16032
|
+
out(` \u300C${INSTRUCTION_TEXT}\u300D`);
|
|
16033
|
+
for (const target of targets) {
|
|
16034
|
+
const file = instructionsFileOf(target);
|
|
16035
|
+
out(` ${LABEL[target]}: ${file ?? "\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u306F\u8AAD\u307E\u306A\u3044\u305F\u3081\u3001\u767B\u9332\u5F8C\u306B\u8CBC\u308B\u5834\u6240\u3092\u6848\u5185\u3057\u307E\u3059"}`);
|
|
16036
|
+
}
|
|
16037
|
+
const instructions = !flag("no-instructions") && (flag("yes") || !/^n(o)?$/i.test(await ask("\u8DB3\u3057\u307E\u3059\u304B\uFF1F [Y/n] ")));
|
|
15979
16038
|
const cli = installRuntime();
|
|
15980
16039
|
const token = option("token") ?? (config?.server === server ? config?.token : void 0);
|
|
15981
16040
|
let connection;
|
|
@@ -15993,7 +16052,7 @@ async function setup() {
|
|
|
15993
16052
|
throw error;
|
|
15994
16053
|
}
|
|
15995
16054
|
const { spawnSync } = await import("node:child_process");
|
|
15996
|
-
const result = spawnSync(process.execPath, [cli, "register", "--targets", targets.join(",")], { stdio: "inherit" });
|
|
16055
|
+
const result = spawnSync(process.execPath, [cli, "register", "--targets", targets.join(","), ...instructions ? ["--instructions"] : []], { stdio: "inherit" });
|
|
15997
16056
|
if (result.status !== 0) throw new Error("AI\u3078\u306E\u767B\u9332\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002");
|
|
15998
16057
|
await api.call("PUT", "/connection/clients", { clients: targets.map((t) => CLIENT[t]), os: osName() });
|
|
15999
16058
|
if (flag("no-test")) return;
|
|
@@ -16003,11 +16062,16 @@ async function registerTargets() {
|
|
|
16003
16062
|
const targets = (option("targets") ?? "").split(",").filter(Boolean);
|
|
16004
16063
|
let failed = false;
|
|
16005
16064
|
for (const target of targets) {
|
|
16006
|
-
const result = await register(target);
|
|
16065
|
+
const result = await register(target, { instructions: flag("instructions") });
|
|
16007
16066
|
const extra = result.steer ? `\uFF08${STEER_LABEL[result.steer.split(":")[0] ?? ""] ?? `\u4F5C\u696D\u4E2D\u306E\u5272\u308A\u8FBC\u307F: ${result.steer}`}\uFF09` : "";
|
|
16008
16067
|
out(` ${LABEL[target]}: ${result.status === "registered" ? "\u767B\u9332\u3057\u307E\u3057\u305F" : `\u5931\u6557 \u2014 ${result.detail}`}${extra}`);
|
|
16009
16068
|
if (result.status === "failed") failed = true;
|
|
16010
16069
|
}
|
|
16070
|
+
if (flag("instructions") && targets.includes("cursor")) {
|
|
16071
|
+
out(`
|
|
16072
|
+
Cursor \u306F\u5168\u4F53\u306E\u6307\u793A\u3092\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u8AAD\u307F\u307E\u305B\u3093\u3002Cursor \u306E Settings \u2192 Rules \u2192 User Rules \u306B\u3001\u6B21\u306E\u4E00\u6587\u3092\u8CBC\u3063\u3066\u304F\u3060\u3055\u3044\u3002
|
|
16073
|
+
${INSTRUCTION_TEXT}`);
|
|
16074
|
+
}
|
|
16011
16075
|
ensureDaemon();
|
|
16012
16076
|
out("\n\u767B\u9332\u3057\u305FAI\u306F\u3001\u958B\u3044\u3066\u3044\u308B\u4F1A\u8A71\u3092\u9589\u3058\u3066\u958B\u304D\u76F4\u3059\u3068Approval Box\u3092\u4F7F\u3048\u307E\u3059\u3002");
|
|
16013
16077
|
if (failed) process.exit(1);
|
|
@@ -16056,7 +16120,7 @@ async function status() {
|
|
|
16056
16120
|
for (const target of HARNESSES) {
|
|
16057
16121
|
if (!detect(target)) continue;
|
|
16058
16122
|
const r = registered(target);
|
|
16059
|
-
out(` ${LABEL[target]}: MCP ${r.mcp ? "\u767B\u9332\u6E08\u307F" : "\u672A\u767B\u9332"}${r.hooks === null ? "" : ` / hook ${r.hooks ? "\u767B\u9332\u6E08\u307F" : "\u672A\u767B\u9332"}`}`);
|
|
16123
|
+
out(` ${LABEL[target]}: MCP ${r.mcp ? "\u767B\u9332\u6E08\u307F" : "\u672A\u767B\u9332"}${r.hooks === null ? "" : ` / hook ${r.hooks ? "\u767B\u9332\u6E08\u307F" : "\u672A\u767B\u9332"}`}${r.instructions === null ? "" : ` / \u6307\u793A ${r.instructions ? "\u3042\u308A" : "\u306A\u3057"}`}`);
|
|
16060
16124
|
}
|
|
16061
16125
|
const d = daemonStatus();
|
|
16062
16126
|
out(`\u914D\u9001\u30C7\u30FC\u30E2\u30F3: ${d.running ? `\u52D5\u4F5C\u4E2D\uFF08pid ${d.pid}\uFF09` : "\u505C\u6B62\u4E2D\uFF08\u6B21\u306E\u7533\u8ACB\u3067\u8D77\u52D5\u3057\u307E\u3059\uFF09"}`);
|
|
@@ -16072,13 +16136,13 @@ async function doctor() {
|
|
|
16072
16136
|
problems.push(error instanceof ServerError && error.status === 401 ? "\u3053\u306E\u7AEF\u672B\u306E\u63A5\u7D9A\u304C\u5916\u3055\u308C\u3066\u3044\u307E\u3059 \u2192 npx approval-box setup" : `\u30B5\u30FC\u30D0\u30FC\u306B\u3064\u306A\u304C\u308A\u307E\u305B\u3093: ${error.message}`);
|
|
16073
16137
|
}
|
|
16074
16138
|
}
|
|
16075
|
-
if (!
|
|
16139
|
+
if (!existsSync6(process.execPath)) problems.push(`node \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\uFF08${process.execPath}\uFF09`);
|
|
16076
16140
|
for (const target of HARNESSES) {
|
|
16077
16141
|
if (!detect(target)) continue;
|
|
16078
16142
|
const r = registered(target);
|
|
16079
16143
|
if (!r.mcp) problems.push(`${LABEL[target]}: MCP\u304C\u767B\u9332\u3055\u308C\u3066\u3044\u307E\u305B\u3093 \u2192 npx approval-box setup --only ${target}`);
|
|
16080
16144
|
if (r.hooks === false) problems.push(`${LABEL[target]}: hook\u304C\u767B\u9332\u3055\u308C\u3066\u3044\u307E\u305B\u3093 \u2192 npx approval-box setup --only ${target}`);
|
|
16081
|
-
if (r.entry && !
|
|
16145
|
+
if (r.entry && !existsSync6(r.entry)) problems.push(`${LABEL[target]}: \u767B\u9332\u5148\u306E\u30D5\u30A1\u30A4\u30EB\u304C\u3042\u308A\u307E\u305B\u3093\uFF08${r.entry}\uFF09\u3002node \u3084Approval Box\u3092\u5165\u308C\u76F4\u3057\u305F\u6642\u306B\u8D77\u304D\u307E\u3059 \u2192 npx approval-box setup`);
|
|
16082
16146
|
}
|
|
16083
16147
|
if (!problems.length) out("\u554F\u984C\u306F\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u5C4A\u304B\u306A\u3044\u6642\u306F\u3001AI\u306B\u300CApproval Box\u306Esetup_test\u3092\u5B9F\u884C\u3057\u3066\u300D\u3068\u8A00\u3063\u3066\u3001\u3069\u3053\u3067\u6B62\u307E\u308B\u304B\u3092\u78BA\u304B\u3081\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
16084
16148
|
else for (const problem of problems) out(`\u2717 ${problem}`);
|
|
@@ -16094,7 +16158,7 @@ async function test() {
|
|
|
16094
16158
|
function help() {
|
|
16095
16159
|
out(`Approval Box ${VERSION}
|
|
16096
16160
|
|
|
16097
|
-
npx approval-box setup [--server URL] [--token TOKEN] [--only claude,codex,cursor,grok] [--yes]
|
|
16161
|
+
npx approval-box setup [--server URL] [--token TOKEN] [--only claude,codex,cursor,grok] [--no-instructions] [--yes]
|
|
16098
16162
|
AI\u306BApproval Box\u3092\u767B\u9332\u3057\u3001\u3053\u306E\u7AEF\u672B\u3092\u30A2\u30AB\u30A6\u30F3\u30C8\u306B\u7D50\u3073\u3001\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u78BA\u8A8D\u307E\u3067\u884C\u3046
|
|
16099
16163
|
npx approval-box test \u63A5\u7D9A\u30C6\u30B9\u30C8\uFF08AI\u306B\u300CApproval Box\u306Esetup_test\u3092\u5B9F\u884C\u3057\u3066\u300D\u3068\u8A00\u3063\u3066\u78BA\u304B\u3081\u308B\uFF09
|
|
16100
16164
|
npx approval-box status \u3064\u306A\u304C\u308A\u3001\u767B\u9332\u3001\u78BA\u8A8D\u306E\u72B6\u614B
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "approval-box",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
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",
|
|
@@ -41,5 +41,13 @@
|
|
|
41
41
|
},
|
|
42
42
|
"engines": {
|
|
43
43
|
"node": ">=20"
|
|
44
|
+
},
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "git+https://github.com/kitepon/approval-box.git",
|
|
48
|
+
"directory": "packages/connector"
|
|
49
|
+
},
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/kitepon/approval-box/issues"
|
|
44
52
|
}
|
|
45
53
|
}
|