dashclaw 1.3.0 → 1.6.0

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 +27 -8
  2. package/dashclaw.js +53 -5
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Full reference for the DashClaw SDK (Node.js). For Python, see the [Python SDK docs](../sdk-python/README.md).
4
4
 
5
- Install, configure, and instrument your AI agents with 57 methods across action recording, behavior guard, context management, session handoffs, security scanning, and more.
5
+ Install, configure, and instrument your AI agents with 59 methods across action recording, behavior guard, context management, session handoffs, security scanning, and more.
6
6
 
7
7
  ---
8
8
 
@@ -23,6 +23,7 @@ const claw = new DashClaw({
23
23
  apiKey: process.env.DASHCLAW_API_KEY,
24
24
  agentId: 'my-agent',
25
25
  agentName: 'My Agent',
26
+ hitlMode: 'wait', // Optional: automatically wait for human approval
26
27
  });
27
28
  ```
28
29
 
@@ -51,7 +52,7 @@ await claw.updateOutcome(action_id, {
51
52
  Create a DashClaw instance. Requires Node 18+ (native fetch).
52
53
 
53
54
  ```javascript
54
- const claw = new DashClaw({ baseUrl, apiKey, agentId, agentName, swarmId, guardMode, guardCallback });
55
+ const claw = new DashClaw({ baseUrl, apiKey, agentId, agentName, swarmId, guardMode, guardCallback, hitlMode });
55
56
  ```
56
57
 
57
58
  ### Parameters
@@ -64,27 +65,30 @@ const claw = new DashClaw({ baseUrl, apiKey, agentId, agentName, swarmId, guardM
64
65
  | swarmId | string | No | Swarm/group identifier if part of a multi-agent system |
65
66
  | guardMode | string | No | Auto guard check before createAction/track: "off" (default), "warn" (log + proceed), "enforce" (throw on block) |
66
67
  | guardCallback | Function | No | Called with guard decision object when guardMode is active |
68
+ | hitlMode | string | No | HITL behavior: "off" (default - return 202 immediately), "wait" (automatically block and poll until approved/denied) |
67
69
 
68
- ### Guard Mode
70
+ ### Guard Mode & HITL
69
71
  When `guardMode` is set, every call to `createAction()` and `track()` automatically checks guard policies before proceeding.
70
72
 
71
73
  ```javascript
72
- import { DashClaw, GuardBlockedError } from 'dashclaw';
74
+ import { DashClaw, GuardBlockedError, ApprovalDeniedError } from 'dashclaw';
73
75
 
74
76
  const claw = new DashClaw({
75
77
  baseUrl: 'https://your-app.vercel.app',
76
78
  apiKey: process.env.DASHCLAW_API_KEY,
77
79
  agentId: 'my-agent',
78
- guardMode: 'enforce', // throws GuardBlockedError on block/require_approval
79
- guardCallback: (decision) => console.log('Guard:', decision.decision),
80
+ guardMode: 'enforce', // throws GuardBlockedError on block
81
+ hitlMode: 'wait', // poll until approved or throw ApprovalDeniedError
80
82
  });
81
83
 
82
84
  try {
83
85
  await claw.createAction({ action_type: 'deploy', declared_goal: 'Ship v2' });
86
+ // If a policy triggers 'require_approval', the SDK will pause here until an admin clicks 'Allow'
84
87
  } catch (err) {
85
88
  if (err instanceof GuardBlockedError) {
86
- console.log(err.decision); // 'block' or 'require_approval'
87
- console.log(err.reasons); // ['Risk score 90 >= threshold 80']
89
+ console.log('Blocked by policy:', err.reasons);
90
+ } else if (err instanceof ApprovalDeniedError) {
91
+ console.log('Denied by human operator');
88
92
  }
89
93
  }
90
94
  ```
@@ -98,6 +102,8 @@ Create, update, and query action records. Every agent action gets a full audit t
98
102
  ### claw.createAction(action)
99
103
  Create a new action record. The agent's agentId, agentName, and swarmId are automatically attached.
100
104
 
105
+ If `hitlMode` is set to `'wait'` and the action requires approval, this method will not return until the action is approved or denied (or it times out).
106
+
101
107
  **Parameters:**
102
108
  | Parameter | Type | Required | Description |
103
109
  |-----------|------|----------|-------------|
@@ -127,6 +133,19 @@ const { action_id } = await claw.createAction({
127
133
  });
128
134
  ```
129
135
 
136
+ ### claw.waitForApproval(actionId, options?)
137
+ Manual poll for human approval. Only needed if `hitlMode` is `'off'`.
138
+
139
+ **Parameters:**
140
+ | Parameter | Type | Required | Description |
141
+ |-----------|------|----------|-------------|
142
+ | actionId | string | Yes | The action_id to poll |
143
+ | options.timeout | number | No | Max wait time in ms (default: 300000 / 5 min) |
144
+ | options.interval | number | No | Poll interval in ms (default: 5000) |
145
+
146
+ **Returns:** `Promise<{ action: Object, action_id: string }>`
147
+ **Throws:** `ApprovalDeniedError` if denied.
148
+
130
149
  ### claw.updateOutcome(actionId, outcome)
131
150
  Update the outcome of an existing action. Automatically sets timestamp_end if not provided.
132
151
 
package/dashclaw.js CHANGED
@@ -3,8 +3,8 @@
3
3
  * Full-featured agent toolkit for the DashClaw platform.
4
4
  * Zero-dependency ESM SDK — requires Node 18+ (native fetch).
5
5
  *
6
- * 58 methods across 13 categories:
7
- * - Action Recording (6)
6
+ * 59 methods across 13 categories:
7
+ * - Action Recording (7)
8
8
  * - Loops & Assumptions (7)
9
9
  * - Signals (1)
10
10
  * - Dashboard Data (9)
@@ -29,9 +29,10 @@ class DashClaw {
29
29
  * @param {string} [options.swarmId] - Swarm/group identifier if part of a multi-agent system
30
30
  * @param {string} [options.guardMode='off'] - Auto guard check before createAction: 'off' | 'warn' | 'enforce'
31
31
  * @param {Function} [options.guardCallback] - Called with guard decision object when guardMode is active
32
+ * @param {string} [options.hitlMode='off'] - How to handle pending approvals: 'off' (return immediately) | 'wait' (block and poll)
32
33
  * @param {CryptoKey} [options.privateKey] - Web Crypto API Private Key for signing actions
33
34
  */
34
- constructor({ baseUrl, apiKey, agentId, agentName, swarmId, guardMode, guardCallback, privateKey }) {
35
+ constructor({ baseUrl, apiKey, agentId, agentName, swarmId, guardMode, guardCallback, hitlMode, privateKey }) {
35
36
  if (!baseUrl) throw new Error('baseUrl is required');
36
37
  if (!apiKey) throw new Error('apiKey is required');
37
38
  if (!agentId) throw new Error('agentId is required');
@@ -48,6 +49,7 @@ class DashClaw {
48
49
  this.swarmId = swarmId || null;
49
50
  this.guardMode = guardMode || 'off';
50
51
  this.guardCallback = guardCallback || null;
52
+ this.hitlMode = hitlMode || 'off';
51
53
  this.privateKey = privateKey || null;
52
54
 
53
55
  // Auto-import JWK if passed as plain object
@@ -193,10 +195,46 @@ class DashClaw {
193
195
  }
194
196
  }
195
197
 
196
- return this._request('/api/actions', 'POST', {
198
+ const res = await this._request('/api/actions', 'POST', {
197
199
  ...payload,
198
200
  _signature: signature
199
201
  });
202
+
203
+ // Handle HITL Approval
204
+ if (res.action?.status === 'pending_approval' && this.hitlMode === 'wait') {
205
+ console.log(`[DashClaw] Action ${res.action_id} requires human approval. Waiting...`);
206
+ return this.waitForApproval(res.action_id);
207
+ }
208
+
209
+ return res;
210
+ }
211
+
212
+ /**
213
+ * Poll for human approval of a pending action.
214
+ * @param {string} actionId
215
+ * @param {Object} [options]
216
+ * @param {number} [options.timeout=300000] - Max wait time (5 min)
217
+ * @param {number} [options.interval=5000] - Poll interval
218
+ */
219
+ async waitForApproval(actionId, { timeout = 300000, interval = 5000 } = {}) {
220
+ const startTime = Date.now();
221
+
222
+ while (Date.now() - startTime < timeout) {
223
+ const { action } = await this.getAction(actionId);
224
+
225
+ if (action.status === 'running') {
226
+ console.log(`[DashClaw] Action ${actionId} approved by operator.`);
227
+ return { action, action_id: actionId };
228
+ }
229
+
230
+ if (action.status === 'failed' || action.status === 'cancelled') {
231
+ throw new ApprovalDeniedError(action.error_message || 'Operator denied the action.');
232
+ }
233
+
234
+ await new Promise(r => setTimeout(r, interval));
235
+ }
236
+
237
+ throw new Error(`[DashClaw] Timed out waiting for approval of action ${actionId}`);
200
238
  }
201
239
 
202
240
  /**
@@ -1133,8 +1171,18 @@ class GuardBlockedError extends Error {
1133
1171
  }
1134
1172
  }
1135
1173
 
1174
+ /**
1175
+ * Error thrown when a human operator denies an action.
1176
+ */
1177
+ class ApprovalDeniedError extends Error {
1178
+ constructor(message) {
1179
+ super(message);
1180
+ this.name = 'ApprovalDeniedError';
1181
+ }
1182
+ }
1183
+
1136
1184
  // Backward compatibility alias (Legacy)
1137
1185
  const OpenClawAgent = DashClaw;
1138
1186
 
1139
1187
  export default DashClaw;
1140
- export { DashClaw, OpenClawAgent, GuardBlockedError };
1188
+ export { DashClaw, OpenClawAgent, GuardBlockedError, ApprovalDeniedError };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dashclaw",
3
- "version": "1.3.0",
4
- "description": "Full-featured agent toolkit for the DashClaw platform. 58 methods for action recording, context management, session handoffs, security scanning, behavior guard, bulk sync, and more.",
3
+ "version": "1.6.0",
4
+ "description": "Full-featured agent toolkit for the DashClaw platform. 59 methods for action recording, context management, session handoffs, security scanning, behavior guard, bulk sync, and more.",
5
5
  "type": "module",
6
6
  "publishConfig": {
7
7
  "access": "public"