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.
- package/README.md +27 -8
- package/dashclaw.js +53 -5
- 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
|
|
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
|
|
79
|
-
|
|
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.
|
|
87
|
-
|
|
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
|
-
*
|
|
7
|
-
* - Action Recording (
|
|
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
|
-
|
|
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.
|
|
4
|
-
"description": "Full-featured agent toolkit for the DashClaw platform.
|
|
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"
|