@agentapprove/openclaw 0.1.7 → 0.1.8

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.
Files changed (3) hide show
  1. package/README.md +12 -0
  2. package/dist/index.js +46 -20
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -10,6 +10,13 @@
10
10
 
11
11
  You decide the rules. Agent Approve enforces them.
12
12
 
13
+ ## Important
14
+
15
+ - A valid Agent Approve subscription is required to use this plugin.
16
+ - You must download the iOS app, run `npx agentapprove`, and pair your device.
17
+ - This plugin is currently pre-launch software. Public App Store availability is not open yet.
18
+ - If a valid token is not configured, tool calls are blocked with setup guidance.
19
+
13
20
  ## How it works
14
21
 
15
22
  This plugin hooks into OpenClaw's agent loop to enforce your approval policy:
@@ -67,6 +74,11 @@ Plugin settings in `~/.openclaw/openclaw.json`:
67
74
  | `privacyTier` | `full` | What tool data is stored in event logs: `minimal`, `summary`, or `full` |
68
75
  | `debug` | `false` | Write debug logs to `~/.agentapprove/hook-debug.log` |
69
76
 
77
+ ## Requirements
78
+
79
+ - OpenClaw runtime
80
+ - Agent Approve iOS app and active subscription ($9.99/month or $99/year, 7-day free trial)
81
+
70
82
  ## Supported agents
71
83
 
72
84
  Agent Approve works with OpenClaw, Claude Code, Cursor, Gemini CLI, VS Code Agent, Copilot CLI, OpenAI Codex (coming soon), and more. Run `npx agentapprove` to configure multiple agents at once.
package/dist/index.js CHANGED
@@ -339,7 +339,7 @@ function loadConfig(openclawConfig, logger) {
339
339
  }
340
340
  let token = process.env.AGENTAPPROVE_TOKEN || getKeychainToken() || parseConfigValue(fileContent, "AGENTAPPROVE_TOKEN") || "";
341
341
  if (!token) {
342
- logger?.warn("No Agent Approve token found. Run the Agent Approve installer to set up.");
342
+ logger?.warn("Missing token. Download the iOS app, run npx agentapprove, and pair your device. Subscription required.");
343
343
  }
344
344
  const rawApiUrl = openclawConfig?.apiUrl || process.env.AGENTAPPROVE_API || parseConfigValue(fileContent, "AGENTAPPROVE_API") || "https://api.agentapprove.com";
345
345
  const rawApiVersion = process.env.AGENTAPPROVE_API_VERSION || parseConfigValue(fileContent, "AGENTAPPROVE_API_VERSION") || "v001";
@@ -387,6 +387,7 @@ function loadConfig(openclawConfig, logger) {
387
387
  privacyTier,
388
388
  debug,
389
389
  hookVersion: "1.1.4",
390
+ agentType: "openclaw",
390
391
  agentName,
391
392
  e2eEnabled,
392
393
  e2eUserKey,
@@ -473,6 +474,7 @@ var CONTENT_FIELDS = [
473
474
  "command",
474
475
  "toolInput",
475
476
  "response",
477
+ "responsePreview",
476
478
  "text",
477
479
  "textPreview",
478
480
  "prompt",
@@ -688,7 +690,7 @@ function httpPost(url, body, headers, timeoutMs) {
688
690
  }
689
691
  async function sendApprovalRequest(request, config, pluginPath, hookName = "openclaw-plugin") {
690
692
  if (!config.token) {
691
- throw new Error("No Agent Approve token configured");
693
+ throw new Error("Missing token. Download the iOS app, run npx agentapprove, and pair your device. Subscription required.");
692
694
  }
693
695
  let payload;
694
696
  if (config.e2eEnabled && config.e2eUserKey) {
@@ -915,13 +917,13 @@ function handleFailBehavior(config, error, toolName, logger, hookName = HOOK_PLU
915
917
  }
916
918
  function register(api) {
917
919
  const config = loadConfig(api.pluginConfig, api.logger);
918
- if (!config.token) {
919
- api.logger.warn(
920
- "Agent Approve: No token found. Run the Agent Approve installer to pair with your account."
921
- );
922
- return;
920
+ const missingTokenMessage = "Missing token. Download the iOS app, run npx agentapprove, and pair your device. Subscription required.";
921
+ const noTokenConfigured = !config.token;
922
+ if (noTokenConfigured) {
923
+ api.logger.warn(`Agent Approve: ${missingTokenMessage}`);
924
+ } else {
925
+ api.logger.info(`Agent Approve: Plugin loaded (privacy: ${config.privacyTier}, fail: ${config.failBehavior})`);
923
926
  }
924
- api.logger.info(`Agent Approve: Plugin loaded (privacy: ${config.privacyTier}, fail: ${config.failBehavior})`);
925
927
  if (config.debug) {
926
928
  const e2eStatus = !config.e2eEnabled ? "disabled" : !config.e2eUserKey ? "enabled (key missing)" : "enabled";
927
929
  debugLog(
@@ -941,16 +943,24 @@ function register(api) {
941
943
  if (config.debug) {
942
944
  debugLog(`Tool: ${displayName} (${toolType}) [agent: ${config.agentName}]`, HOOK_BEFORE_TOOL);
943
945
  }
946
+ if (noTokenConfigured) {
947
+ return {
948
+ block: true,
949
+ blockReason: missingTokenMessage
950
+ };
951
+ }
944
952
  const request = {
945
953
  toolName: displayName,
946
954
  toolType,
947
955
  command,
948
956
  toolInput: event.params,
949
- agent: config.agentName,
957
+ agent: config.agentType,
958
+ agentName: config.agentName,
950
959
  hookType: "before_tool_call",
951
960
  sessionId: conversationId,
952
961
  conversationId,
953
962
  cwd: event.params.workdir || void 0,
963
+ projectPath: process.cwd(),
954
964
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
955
965
  };
956
966
  try {
@@ -994,18 +1004,24 @@ function register(api) {
994
1004
  }
995
1005
  const { toolType } = classifyTool(event.toolName, event.params);
996
1006
  const resultPreview = extractResultPreview(event.toolName, event.params, event.result);
1007
+ const resultStr = event.result != null ? typeof event.result === "string" ? event.result : JSON.stringify(event.result) : void 0;
1008
+ const longPreview = resultStr && resultStr.length > 1e3 ? resultStr.slice(0, 1e3) + "..." : resultStr;
997
1009
  void sendEvent({
998
1010
  toolName: event.toolName,
999
1011
  toolType,
1000
1012
  eventType: "tool_complete",
1001
- agent: config.agentName,
1013
+ agent: config.agentType,
1014
+ agentName: config.agentName,
1002
1015
  hookType: "after_tool_call",
1003
1016
  sessionId: conversationId,
1004
1017
  conversationId,
1005
1018
  command: extractCommand(event.toolName, event.params),
1019
+ toolInput: event.params,
1006
1020
  status: event.error ? "error" : "success",
1007
1021
  response: event.error || resultPreview || void 0,
1022
+ responsePreview: longPreview,
1008
1023
  durationMs: event.durationMs,
1024
+ cwd: event.params?.workdir || void 0,
1009
1025
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
1010
1026
  }, config, pluginFilePath, HOOK_AFTER_TOOL);
1011
1027
  });
@@ -1017,7 +1033,8 @@ function register(api) {
1017
1033
  const conversationId = resolveConversationId();
1018
1034
  void sendEvent({
1019
1035
  eventType: "session_start",
1020
- agent: config.agentName,
1036
+ agent: config.agentType,
1037
+ agentName: config.agentName,
1021
1038
  hookType: "session_start",
1022
1039
  sessionId: conversationId,
1023
1040
  conversationId,
@@ -1032,7 +1049,8 @@ function register(api) {
1032
1049
  const conversationId = resolveConversationId();
1033
1050
  void sendEvent({
1034
1051
  eventType: "session_end",
1035
- agent: config.agentName,
1052
+ agent: config.agentType,
1053
+ agentName: config.agentName,
1036
1054
  hookType: "session_end",
1037
1055
  sessionId: conversationId,
1038
1056
  conversationId,
@@ -1049,7 +1067,8 @@ function register(api) {
1049
1067
  const conversationId = resolveConversationId();
1050
1068
  void sendEvent({
1051
1069
  eventType: "user_prompt",
1052
- agent: config.agentName,
1070
+ agent: config.agentType,
1071
+ agentName: config.agentName,
1053
1072
  hookType: "llm_input",
1054
1073
  sessionId: conversationId,
1055
1074
  conversationId,
@@ -1069,7 +1088,8 @@ function register(api) {
1069
1088
  }
1070
1089
  void sendEvent({
1071
1090
  eventType: "response",
1072
- agent: config.agentName,
1091
+ agent: config.agentType,
1092
+ agentName: config.agentName,
1073
1093
  hookType: "llm_output",
1074
1094
  sessionId: conversationId,
1075
1095
  conversationId,
@@ -1088,7 +1108,8 @@ function register(api) {
1088
1108
  const conversationId = resolveConversationId();
1089
1109
  void sendEvent({
1090
1110
  eventType: "stop",
1091
- agent: config.agentName,
1111
+ agent: config.agentType,
1112
+ agentName: config.agentName,
1092
1113
  hookType: "agent_end",
1093
1114
  sessionId: conversationId,
1094
1115
  conversationId,
@@ -1106,7 +1127,8 @@ function register(api) {
1106
1127
  const conversationId = resolveConversationId();
1107
1128
  void sendEvent({
1108
1129
  eventType: "context_compact",
1109
- agent: config.agentName,
1130
+ agent: config.agentType,
1131
+ agentName: config.agentName,
1110
1132
  hookType: "before_compaction",
1111
1133
  sessionId: conversationId,
1112
1134
  conversationId,
@@ -1122,7 +1144,8 @@ function register(api) {
1122
1144
  const conversationId = resolveConversationId();
1123
1145
  void sendEvent({
1124
1146
  eventType: "subagent_start",
1125
- agent: config.agentName,
1147
+ agent: config.agentType,
1148
+ agentName: config.agentName,
1126
1149
  hookType: "subagent_spawned",
1127
1150
  sessionId: conversationId,
1128
1151
  conversationId,
@@ -1140,7 +1163,8 @@ function register(api) {
1140
1163
  const conversationId = resolveConversationId();
1141
1164
  void sendEvent({
1142
1165
  eventType: "subagent_stop",
1143
- agent: config.agentName,
1166
+ agent: config.agentType,
1167
+ agentName: config.agentName,
1144
1168
  hookType: "subagent_ended",
1145
1169
  sessionId: conversationId,
1146
1170
  conversationId,
@@ -1166,7 +1190,8 @@ function register(api) {
1166
1190
  toolName: `command:${event.action}`,
1167
1191
  toolType: "command",
1168
1192
  eventType: eventTypeMap[event.action] || "command_event",
1169
- agent: config.agentName,
1193
+ agent: config.agentType,
1194
+ agentName: config.agentName,
1170
1195
  hookType: "command_event",
1171
1196
  sessionId: resolveConversationId(),
1172
1197
  conversationId: resolveConversationId(),
@@ -1190,7 +1215,8 @@ function register(api) {
1190
1215
  toolName: `message:${event.action}`,
1191
1216
  toolType: "message_event",
1192
1217
  eventType: isInbound ? "user_prompt" : "response",
1193
- agent: config.agentName,
1218
+ agent: config.agentType,
1219
+ agentName: config.agentName,
1194
1220
  hookType: "session_event",
1195
1221
  sessionId: resolveConversationId(),
1196
1222
  conversationId: resolveConversationId(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentapprove/openclaw",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Agent Approve plugin for OpenClaw - approve or deny AI agent tool calls from your iPhone and Apple Watch",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {