agentapprove 0.1.1 → 0.1.3
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 +2 -1
- package/dist/cli.js +143 -21
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -48,6 +48,7 @@ agentapprove --no-e2e # Skip end-to-end encryption setup
|
|
|
48
48
|
- **Gemini CLI** - Google's CLI
|
|
49
49
|
- **VS Code Agent** - VS Code agent hooks
|
|
50
50
|
- **GitHub Copilot CLI** - GitHub's coding agent
|
|
51
|
+
- **OpenCode** - Open-source AI coding agent
|
|
51
52
|
- **OpenClaw** - Open-source AI agent platform
|
|
52
53
|
- **OpenAI Codex** - coming soon
|
|
53
54
|
- And more
|
|
@@ -58,7 +59,7 @@ agentapprove --no-e2e # Skip end-to-end encryption setup
|
|
|
58
59
|
- **Push notifications** - Never miss an approval request. Avoid wasted idle time with your agents
|
|
59
60
|
- **Apple Watch** - One-tap approvals from your wrist. Review context and respond without reaching for your phone
|
|
60
61
|
- **Voice commands** - Send follow-up commands to your agents using the microphone when they finish a task
|
|
61
|
-
- **Agent observability** - Full visibility into what all your agents are doing, especially autonomous agents like OpenClaw or long-running loops
|
|
62
|
+
- **Agent observability** - Full visibility into what all your agents are doing, especially autonomous agents like OpenClaw or long-running loops (Ralph loops)
|
|
62
63
|
- **Centralized policies** - Set auto-approve and deny rules across all your agents from a single policy
|
|
63
64
|
- **End-to-end encryption** - You own the keys. Approval requests are encrypted on your machine and decrypted only on your device
|
|
64
65
|
- **Privacy tiers** - Choose minimal, summary, or full data logging. Control retention from 1 to 365 days
|
package/dist/cli.js
CHANGED
|
@@ -2318,10 +2318,19 @@ import { homedir, hostname, platform } from "os";
|
|
|
2318
2318
|
import { join, dirname, basename } from "path";
|
|
2319
2319
|
import { execSync, spawnSync } from "child_process";
|
|
2320
2320
|
import { randomBytes, createHash } from "crypto";
|
|
2321
|
-
var VERSION = "0.1.
|
|
2321
|
+
var VERSION = "0.1.3";
|
|
2322
2322
|
function getApiUrl() {
|
|
2323
2323
|
return process.env.AGENTAPPROVE_API || "https://api.agentapprove.com";
|
|
2324
2324
|
}
|
|
2325
|
+
function getXdgConfigHome() {
|
|
2326
|
+
return process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
|
|
2327
|
+
}
|
|
2328
|
+
function getOpenCodeConfigDir() {
|
|
2329
|
+
return join(getXdgConfigHome(), "opencode");
|
|
2330
|
+
}
|
|
2331
|
+
function getOpenCodeConfigPath() {
|
|
2332
|
+
return join(getOpenCodeConfigDir(), "opencode.json");
|
|
2333
|
+
}
|
|
2325
2334
|
var API_URL = getApiUrl();
|
|
2326
2335
|
var API_VERSION = process.env.AGENTAPPROVE_API_VERSION || "v001";
|
|
2327
2336
|
function hasFlag2(flag) {
|
|
@@ -2446,6 +2455,14 @@ var AGENTS = {
|
|
|
2446
2455
|
hooks: [
|
|
2447
2456
|
{ name: "agentapprove", file: "@agentapprove/openclaw", description: "Tool approval + event monitoring", isApprovalHook: true, isPlugin: true }
|
|
2448
2457
|
]
|
|
2458
|
+
},
|
|
2459
|
+
opencode: {
|
|
2460
|
+
name: "OpenCode",
|
|
2461
|
+
configPath: getOpenCodeConfigPath(),
|
|
2462
|
+
hooksKey: "plugin",
|
|
2463
|
+
hooks: [
|
|
2464
|
+
{ name: "agentapprove", file: "@agentapprove/opencode", description: "Tool approval + event monitoring", isApprovalHook: true, isPlugin: true }
|
|
2465
|
+
]
|
|
2449
2466
|
}
|
|
2450
2467
|
};
|
|
2451
2468
|
function findGitBash() {
|
|
@@ -2619,6 +2636,10 @@ function detectInstalledAgents() {
|
|
|
2619
2636
|
if (existsSync(join(homedir(), ".openclaw"))) {
|
|
2620
2637
|
installed.push(id);
|
|
2621
2638
|
}
|
|
2639
|
+
} else if (id === "opencode") {
|
|
2640
|
+
if (existsSync(getOpenCodeConfigDir())) {
|
|
2641
|
+
installed.push(id);
|
|
2642
|
+
}
|
|
2622
2643
|
} else {
|
|
2623
2644
|
const configDir = dirname(agent.configPath);
|
|
2624
2645
|
if (existsSync(configDir)) {
|
|
@@ -3055,6 +3076,39 @@ async function installHooksForAgent(agentId, hooksDir, mode = "approval") {
|
|
|
3055
3076
|
installedHooks.push("agentapprove");
|
|
3056
3077
|
return { success: true, backupPath, hooks: installedHooks };
|
|
3057
3078
|
}
|
|
3079
|
+
if (agentId === "opencode") {
|
|
3080
|
+
if (!Array.isArray(config.plugin)) {
|
|
3081
|
+
config.plugin = [];
|
|
3082
|
+
}
|
|
3083
|
+
const pluginArray = config.plugin;
|
|
3084
|
+
if (!pluginArray.includes("@agentapprove/opencode")) {
|
|
3085
|
+
pluginArray.push("@agentapprove/opencode");
|
|
3086
|
+
}
|
|
3087
|
+
writeJsonConfig(agent.configPath, config);
|
|
3088
|
+
const opencodePkgDir = join(getOpenCodeConfigDir(), ".opencode");
|
|
3089
|
+
const opencodePkgPath = join(opencodePkgDir, "package.json");
|
|
3090
|
+
try {
|
|
3091
|
+
if (!existsSync(opencodePkgDir)) {
|
|
3092
|
+
mkdirSync(opencodePkgDir, { recursive: true });
|
|
3093
|
+
}
|
|
3094
|
+
let pkgJson = {};
|
|
3095
|
+
if (existsSync(opencodePkgPath)) {
|
|
3096
|
+
pkgJson = JSON.parse(readFileSync(opencodePkgPath, "utf-8"));
|
|
3097
|
+
}
|
|
3098
|
+
if (!pkgJson.dependencies) {
|
|
3099
|
+
pkgJson.dependencies = {};
|
|
3100
|
+
}
|
|
3101
|
+
pkgJson.dependencies["@agentapprove/opencode"] = "latest";
|
|
3102
|
+
writeFileSync(opencodePkgPath, JSON.stringify(pkgJson, null, 2) + `
|
|
3103
|
+
`);
|
|
3104
|
+
} catch (err) {
|
|
3105
|
+
if (err instanceof Error) {
|
|
3106
|
+
console.warn(`Warning: Could not update .opencode/package.json: ${err.message}`);
|
|
3107
|
+
}
|
|
3108
|
+
}
|
|
3109
|
+
installedHooks.push("agentapprove");
|
|
3110
|
+
return { success: true, backupPath, hooks: installedHooks };
|
|
3111
|
+
}
|
|
3058
3112
|
const hooksToInstall = mode === "observe" ? agent.hooks.filter((h2) => !h2.isApprovalHook) : agent.hooks;
|
|
3059
3113
|
for (const hook of hooksToInstall) {
|
|
3060
3114
|
const hookPath = join(hooksDir, hook.file);
|
|
@@ -3364,6 +3418,23 @@ function getManualInstructions(agentId, hooksDir) {
|
|
|
3364
3418
|
"",
|
|
3365
3419
|
"Restart the OpenClaw gateway to activate."
|
|
3366
3420
|
].join(`
|
|
3421
|
+
`);
|
|
3422
|
+
} else if (agentId === "opencode") {
|
|
3423
|
+
const configJson = JSON.stringify({
|
|
3424
|
+
plugin: ["@agentapprove/opencode"]
|
|
3425
|
+
}, null, 2);
|
|
3426
|
+
const opencodeConfigPath = process.env.XDG_CONFIG_HOME ? `${process.env.XDG_CONFIG_HOME}/opencode/opencode.json` : "~/.config/opencode/opencode.json";
|
|
3427
|
+
return [
|
|
3428
|
+
`Add the Agent Approve plugin to your OpenCode config (${opencodeConfigPath}):`,
|
|
3429
|
+
"",
|
|
3430
|
+
configJson,
|
|
3431
|
+
"",
|
|
3432
|
+
"Then add the dependency to .opencode/package.json:",
|
|
3433
|
+
"",
|
|
3434
|
+
' { "dependencies": { "@agentapprove/opencode": "latest" } }',
|
|
3435
|
+
"",
|
|
3436
|
+
"OpenCode will auto-install the plugin on next start."
|
|
3437
|
+
].join(`
|
|
3367
3438
|
`);
|
|
3368
3439
|
}
|
|
3369
3440
|
return "";
|
|
@@ -3987,6 +4058,9 @@ AGENTAPPROVE_E2E_MODE=${installMode}
|
|
|
3987
4058
|
for (const agentId of selectedAgents) {
|
|
3988
4059
|
const agent = AGENTS[agentId];
|
|
3989
4060
|
filesToModify.push(agent.configPath);
|
|
4061
|
+
if (agentId === "opencode") {
|
|
4062
|
+
filesToModify.push(join(getOpenCodeConfigDir(), ".opencode", "package.json"));
|
|
4063
|
+
}
|
|
3990
4064
|
if (agentId === "vscode-agent") {
|
|
3991
4065
|
const vsCodeVariants = findInstalledVSCodeVariants();
|
|
3992
4066
|
for (const { path: settingsPath, variant } of vsCodeVariants) {
|
|
@@ -4100,6 +4174,20 @@ async function statusCommand() {
|
|
|
4100
4174
|
for (const [agentId, agent] of Object.entries(AGENTS)) {
|
|
4101
4175
|
if (existsSync(agent.configPath)) {
|
|
4102
4176
|
const config = readJsonConfig(agent.configPath);
|
|
4177
|
+
if (agentId === "opencode") {
|
|
4178
|
+
const pluginConfig = config.plugin;
|
|
4179
|
+
if (Array.isArray(pluginConfig) && pluginConfig.some((entry) => entry === "@agentapprove/opencode")) {
|
|
4180
|
+
console.log(` ${source_default.green("✓")} ${agent.name}: agentapprove plugin`);
|
|
4181
|
+
}
|
|
4182
|
+
continue;
|
|
4183
|
+
}
|
|
4184
|
+
if (agentId === "openclaw") {
|
|
4185
|
+
const entries = config.plugins?.entries;
|
|
4186
|
+
if (entries?.agentapprove) {
|
|
4187
|
+
console.log(` ${source_default.green("✓")} ${agent.name}: agentapprove plugin`);
|
|
4188
|
+
}
|
|
4189
|
+
continue;
|
|
4190
|
+
}
|
|
4103
4191
|
const hooksConfig = config[agent.hooksKey];
|
|
4104
4192
|
if (hooksConfig) {
|
|
4105
4193
|
const installedHooks = agent.hooks.filter((h2) => {
|
|
@@ -4165,35 +4253,69 @@ async function uninstallCommand() {
|
|
|
4165
4253
|
continue;
|
|
4166
4254
|
const config = readJsonConfig(agent.configPath);
|
|
4167
4255
|
const hooksConfig = config[agent.hooksKey];
|
|
4168
|
-
if (!hooksConfig)
|
|
4256
|
+
if (!hooksConfig && agentId !== "opencode")
|
|
4169
4257
|
continue;
|
|
4170
4258
|
let modified = false;
|
|
4171
|
-
|
|
4172
|
-
const
|
|
4173
|
-
if (
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
return !str.includes("agentapprove");
|
|
4259
|
+
if (agentId === "opencode") {
|
|
4260
|
+
const pluginArray = config.plugin;
|
|
4261
|
+
if (Array.isArray(pluginArray)) {
|
|
4262
|
+
const filtered = pluginArray.filter((p) => {
|
|
4263
|
+
if (typeof p !== "string")
|
|
4264
|
+
return true;
|
|
4265
|
+
return !p.includes("agentapprove");
|
|
4179
4266
|
});
|
|
4180
|
-
if (filtered.length !==
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4267
|
+
if (filtered.length !== pluginArray.length) {
|
|
4268
|
+
config.plugin = filtered;
|
|
4269
|
+
modified = true;
|
|
4270
|
+
}
|
|
4271
|
+
}
|
|
4272
|
+
const opencodePkgDir = join(getOpenCodeConfigDir(), ".opencode");
|
|
4273
|
+
const opencodePkgPath = join(opencodePkgDir, "package.json");
|
|
4274
|
+
try {
|
|
4275
|
+
if (existsSync(opencodePkgPath)) {
|
|
4276
|
+
const pkgJson = JSON.parse(readFileSync(opencodePkgPath, "utf-8"));
|
|
4277
|
+
const deps = pkgJson.dependencies;
|
|
4278
|
+
if (deps && deps["@agentapprove/opencode"]) {
|
|
4279
|
+
delete deps["@agentapprove/opencode"];
|
|
4280
|
+
writeFileSync(opencodePkgPath, JSON.stringify(pkgJson, null, 2) + `
|
|
4281
|
+
`);
|
|
4185
4282
|
}
|
|
4283
|
+
}
|
|
4284
|
+
} catch {}
|
|
4285
|
+
} else if (agentId === "openclaw") {
|
|
4286
|
+
const entries = hooksConfig.entries;
|
|
4287
|
+
if (entries && entries.agentapprove) {
|
|
4288
|
+
delete entries.agentapprove;
|
|
4289
|
+
modified = true;
|
|
4290
|
+
}
|
|
4291
|
+
} else {
|
|
4292
|
+
for (const hook of agent.hooks) {
|
|
4293
|
+
const hookEntry = hooksConfig[hook.name];
|
|
4294
|
+
if (!hookEntry)
|
|
4295
|
+
continue;
|
|
4296
|
+
if (Array.isArray(hookEntry)) {
|
|
4297
|
+
const filtered = hookEntry.filter((e2) => {
|
|
4298
|
+
const str = JSON.stringify(e2);
|
|
4299
|
+
return !str.includes("agentapprove");
|
|
4300
|
+
});
|
|
4301
|
+
if (filtered.length !== hookEntry.length) {
|
|
4302
|
+
if (filtered.length === 0) {
|
|
4303
|
+
delete hooksConfig[hook.name];
|
|
4304
|
+
} else {
|
|
4305
|
+
hooksConfig[hook.name] = filtered;
|
|
4306
|
+
}
|
|
4307
|
+
modified = true;
|
|
4308
|
+
}
|
|
4309
|
+
} else if (typeof hookEntry === "string" && hookEntry.includes("agentapprove")) {
|
|
4310
|
+
delete hooksConfig[hook.name];
|
|
4186
4311
|
modified = true;
|
|
4187
4312
|
}
|
|
4188
|
-
}
|
|
4189
|
-
|
|
4313
|
+
}
|
|
4314
|
+
if (hooksConfig["Prompt"]) {
|
|
4315
|
+
delete hooksConfig["Prompt"];
|
|
4190
4316
|
modified = true;
|
|
4191
4317
|
}
|
|
4192
4318
|
}
|
|
4193
|
-
if (hooksConfig["Prompt"]) {
|
|
4194
|
-
delete hooksConfig["Prompt"];
|
|
4195
|
-
modified = true;
|
|
4196
|
-
}
|
|
4197
4319
|
if (modified) {
|
|
4198
4320
|
writeJsonConfig(agent.configPath, config);
|
|
4199
4321
|
console.log(` ${source_default.green("✓")} Removed hooks from ${agent.name}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentapprove",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Approve AI agent actions from your iPhone or Apple Watch",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"cursor",
|
|
23
23
|
"gemini",
|
|
24
24
|
"openclaw",
|
|
25
|
+
"opencode",
|
|
25
26
|
"ai",
|
|
26
27
|
"agent",
|
|
27
28
|
"approval",
|