dashclaw 2.1.0 → 2.1.2
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 +71 -49
- package/dashclaw.js +138 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# DashClaw SDK (v2)
|
|
1
|
+
# DashClaw SDK (v2.1.2)
|
|
2
2
|
|
|
3
3
|
**Minimal governance runtime for AI agents.**
|
|
4
4
|
|
|
@@ -6,70 +6,102 @@ The DashClaw SDK provides the infrastructure to intercept, govern, and verify ag
|
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
9
|
+
### Node.js
|
|
9
10
|
```bash
|
|
10
11
|
npm install dashclaw
|
|
11
12
|
```
|
|
12
13
|
|
|
14
|
+
### Python
|
|
15
|
+
```bash
|
|
16
|
+
pip install dashclaw
|
|
17
|
+
```
|
|
18
|
+
|
|
13
19
|
## The Governance Loop
|
|
14
20
|
|
|
15
21
|
DashClaw v2 is designed around a single 4-step loop.
|
|
16
22
|
|
|
23
|
+
### Node.js
|
|
17
24
|
```javascript
|
|
18
|
-
import { DashClaw
|
|
25
|
+
import { DashClaw } from 'dashclaw';
|
|
19
26
|
|
|
20
27
|
const claw = new DashClaw({
|
|
21
|
-
baseUrl:
|
|
28
|
+
baseUrl: 'https://dashclaw.io',
|
|
22
29
|
apiKey: process.env.DASHCLAW_API_KEY,
|
|
23
30
|
agentId: 'my-agent'
|
|
24
31
|
});
|
|
25
32
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
33
|
+
// 1. Ask permission
|
|
34
|
+
const res = await claw.guard({ action_type: 'deploy' });
|
|
35
|
+
|
|
36
|
+
// 2. Log intent
|
|
37
|
+
const { action_id } = await claw.createAction({ action_type: 'deploy' });
|
|
38
|
+
|
|
39
|
+
// 3. Log evidence
|
|
40
|
+
await claw.recordAssumption({ action_id, assumption: 'Tests passed' });
|
|
41
|
+
|
|
42
|
+
// 4. Update result
|
|
43
|
+
await claw.updateOutcome(action_id, { status: 'completed' });
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Python
|
|
47
|
+
```python
|
|
48
|
+
from dashclaw import DashClaw
|
|
49
|
+
|
|
50
|
+
claw = DashClaw(
|
|
51
|
+
base_url="https://dashclaw.io",
|
|
52
|
+
api_key="your_api_key",
|
|
53
|
+
agent_id="my-agent"
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
# 1. Ask permission
|
|
57
|
+
res = claw.guard({"action_type": "deploy"})
|
|
58
|
+
|
|
59
|
+
# 2. Log intent
|
|
60
|
+
action = claw.create_action(action_type="deploy")
|
|
61
|
+
action_id = action["action_id"]
|
|
62
|
+
|
|
63
|
+
# 3. Log evidence
|
|
64
|
+
claw.record_assumption({"action_id": action_id, "assumption": "Tests passed"})
|
|
65
|
+
|
|
66
|
+
# 4. Update result
|
|
67
|
+
claw.update_outcome(action_id, status="completed")
|
|
59
68
|
```
|
|
60
69
|
|
|
61
70
|
---
|
|
62
71
|
|
|
63
|
-
## SDK Surface Area (v2)
|
|
72
|
+
## SDK Surface Area (v2.1.2)
|
|
64
73
|
|
|
65
|
-
The v2 SDK is optimized for stability and zero-overhead governance:
|
|
74
|
+
The v2.1.2 SDK is optimized for stability and zero-overhead governance:
|
|
66
75
|
|
|
76
|
+
### Core Runtime
|
|
67
77
|
- `guard(context)` — Policy evaluation ("Can I do X?")
|
|
68
78
|
- `createAction(action)` — Lifecycle tracking ("I am doing X")
|
|
69
79
|
- `updateOutcome(id, outcome)` — Result recording ("X finished with Y")
|
|
70
80
|
- `recordAssumption(assumption)` — Integrity tracking ("I believe Z while doing X")
|
|
71
81
|
- `waitForApproval(id)` — Polling helper for human-in-the-loop approvals
|
|
72
82
|
|
|
83
|
+
### Decision Integrity
|
|
84
|
+
- `registerOpenLoop(actionId, type, desc)` — Register unresolved dependencies.
|
|
85
|
+
- `resolveOpenLoop(loopId, status, res)` — Resolve pending loops.
|
|
86
|
+
- `getSignals()` — Get current risk signals across all agents.
|
|
87
|
+
|
|
88
|
+
### Swarm & Connectivity
|
|
89
|
+
- `heartbeat(status, metadata)` — Report agent presence and health.
|
|
90
|
+
- `reportConnections(connections)` — Report active provider connections.
|
|
91
|
+
|
|
92
|
+
### Learning & Optimization
|
|
93
|
+
- `getLearningVelocity()` — Track agent improvement rate.
|
|
94
|
+
- `getLearningCurves()` — Measure efficiency gains per action type.
|
|
95
|
+
- `renderPrompt(context)` — Fetch rendered prompt templates from DashClaw.
|
|
96
|
+
|
|
97
|
+
### Compliance & Audit
|
|
98
|
+
- `createScorer(name, type, config)` — Define automated evaluations.
|
|
99
|
+
- `createScoringProfile(profile)` — Weighted quality scoring.
|
|
100
|
+
- `mapCompliance(framework)` — Map behavior to regulatory controls.
|
|
101
|
+
- `getProofReport(format)` — Generate audit-ready evidence exports.
|
|
102
|
+
- `getActivityLogs(filters)` — Query the immutable audit trail.
|
|
103
|
+
- `createWebhook(url, events)` — Real-time event exfiltration.
|
|
104
|
+
|
|
73
105
|
---
|
|
74
106
|
|
|
75
107
|
## Error Handling
|
|
@@ -83,17 +115,7 @@ DashClaw uses standard HTTP status codes and custom error classes:
|
|
|
83
115
|
|
|
84
116
|
## Legacy SDK (v1)
|
|
85
117
|
|
|
86
|
-
If you require legacy features (Calendar, Messages, Workflows, etc.), the v1 SDK is available via the `legacy` sub-path
|
|
87
|
-
|
|
88
|
-
```javascript
|
|
89
|
-
// ESM
|
|
90
|
-
import { DashClaw } from 'dashclaw/legacy';
|
|
91
|
-
|
|
92
|
-
// CommonJS
|
|
93
|
-
const { DashClaw } = require('dashclaw/legacy');
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
*Note: Legacy features are now considered "Extensions" and require these routes to be enabled on your DashClaw server.*
|
|
118
|
+
If you require legacy features (Calendar, Messages, Workflows, etc.), the v1 SDK is available via the `legacy` sub-path in Node.js or via the full client in Python.
|
|
97
119
|
|
|
98
120
|
---
|
|
99
121
|
|
package/dashclaw.js
CHANGED
|
@@ -57,10 +57,12 @@ class DashClaw {
|
|
|
57
57
|
const data = await res.json();
|
|
58
58
|
|
|
59
59
|
if (!res.ok) {
|
|
60
|
-
|
|
60
|
+
// Prioritize reason (from governance blocks) over generic error field
|
|
61
|
+
const errorMessage = data.reason || data.error || `Request failed with status ${res.status}`;
|
|
62
|
+
const err = new Error(errorMessage);
|
|
61
63
|
err.status = res.status;
|
|
62
64
|
err.details = data.details;
|
|
63
|
-
err.decision = data
|
|
65
|
+
err.decision = data;
|
|
64
66
|
throw err;
|
|
65
67
|
}
|
|
66
68
|
|
|
@@ -70,9 +72,6 @@ class DashClaw {
|
|
|
70
72
|
/**
|
|
71
73
|
* POST /api/guard — "Can I do X?"
|
|
72
74
|
* @param {Object} context
|
|
73
|
-
* @param {string} context.action - Action type (e.g. "deploy")
|
|
74
|
-
* @param {string} [context.intent] - What the action aims to do
|
|
75
|
-
* @param {number} [context.risk_score] - Risk score 0-100
|
|
76
75
|
* @returns {Promise<{decision: 'allow'|'block'|'require_approval', action_id: string, reason: string, signals: string[]}>}
|
|
77
76
|
*/
|
|
78
77
|
async guard(context) {
|
|
@@ -84,23 +83,16 @@ class DashClaw {
|
|
|
84
83
|
|
|
85
84
|
/**
|
|
86
85
|
* POST /api/actions — "I am attempting X."
|
|
87
|
-
* @param {Object} action
|
|
88
|
-
* @param {string} action.action_type - e.g. "deploy"
|
|
89
|
-
* @param {string} action.declared_goal - e.g. "deploy to production"
|
|
90
|
-
* @returns {Promise<{action: Object, action_id: string}>}
|
|
91
86
|
*/
|
|
92
87
|
async createAction(action) {
|
|
93
|
-
|
|
88
|
+
return this._request('/api/actions', 'POST', {
|
|
94
89
|
...action,
|
|
95
90
|
agent_id: this.agentId,
|
|
96
91
|
});
|
|
97
|
-
return res;
|
|
98
92
|
}
|
|
99
93
|
|
|
100
94
|
/**
|
|
101
95
|
* PATCH /api/actions/:id — "X finished with result Y."
|
|
102
|
-
* @param {string} actionId
|
|
103
|
-
* @param {Object} outcome
|
|
104
96
|
*/
|
|
105
97
|
async updateOutcome(actionId, outcome) {
|
|
106
98
|
return this._request(`/api/actions/${actionId}`, 'PATCH', {
|
|
@@ -111,7 +103,6 @@ class DashClaw {
|
|
|
111
103
|
|
|
112
104
|
/**
|
|
113
105
|
* POST /api/assumptions — "I believe Z is true while doing X."
|
|
114
|
-
* @param {Object} assumption
|
|
115
106
|
*/
|
|
116
107
|
async recordAssumption(assumption) {
|
|
117
108
|
return this._request('/api/assumptions', 'POST', assumption);
|
|
@@ -132,6 +123,139 @@ class DashClaw {
|
|
|
132
123
|
}
|
|
133
124
|
throw new Error(`Timed out waiting for approval of action ${actionId}`);
|
|
134
125
|
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* POST /api/agents/heartbeat
|
|
129
|
+
*/
|
|
130
|
+
async heartbeat(status = 'online', metadata = null) {
|
|
131
|
+
return this._request('/api/agents/heartbeat', 'POST', {
|
|
132
|
+
agent_id: this.agentId,
|
|
133
|
+
status,
|
|
134
|
+
metadata
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* POST /api/agents/connections
|
|
140
|
+
*/
|
|
141
|
+
async reportConnections(connections) {
|
|
142
|
+
return this._request('/api/agents/connections', 'POST', {
|
|
143
|
+
agent_id: this.agentId,
|
|
144
|
+
connections
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* POST /api/actions/loops
|
|
150
|
+
*/
|
|
151
|
+
async registerOpenLoop(actionId, loopType, description, metadata = null) {
|
|
152
|
+
return this._request('/api/actions/loops', 'POST', {
|
|
153
|
+
action_id: actionId,
|
|
154
|
+
loop_type: loopType,
|
|
155
|
+
description,
|
|
156
|
+
metadata
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* PATCH /api/actions/loops/:id
|
|
162
|
+
*/
|
|
163
|
+
async resolveOpenLoop(loopId, status, resolution = null) {
|
|
164
|
+
return this._request(`/api/actions/loops/${loopId}`, 'PATCH', {
|
|
165
|
+
status,
|
|
166
|
+
resolution
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* GET /api/actions/signals
|
|
172
|
+
*/
|
|
173
|
+
async getSignals() {
|
|
174
|
+
return this._request('/api/actions/signals');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* GET /api/learning/analytics/velocity
|
|
179
|
+
*/
|
|
180
|
+
async getLearningVelocity(lookbackDays = 30) {
|
|
181
|
+
return this._request('/api/learning/analytics/velocity', 'GET', null, {
|
|
182
|
+
agent_id: this.agentId,
|
|
183
|
+
lookback_days: lookbackDays
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* GET /api/learning/analytics/curves
|
|
189
|
+
*/
|
|
190
|
+
async getLearningCurves(lookbackDays = 60) {
|
|
191
|
+
return this._request('/api/learning/analytics/curves', 'GET', null, {
|
|
192
|
+
agent_id: this.agentId,
|
|
193
|
+
lookback_days: lookbackDays
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* POST /api/prompts/render
|
|
199
|
+
*/
|
|
200
|
+
async renderPrompt({ template_id, version_id, variables, record = false }) {
|
|
201
|
+
return this._request('/api/prompts/render', 'POST', {
|
|
202
|
+
template_id,
|
|
203
|
+
version_id,
|
|
204
|
+
variables,
|
|
205
|
+
agent_id: this.agentId,
|
|
206
|
+
record
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* POST /api/evaluations/scorers
|
|
212
|
+
*/
|
|
213
|
+
async createScorer(name, scorer_type, config = null, description = null) {
|
|
214
|
+
return this._request('/api/evaluations/scorers', 'POST', {
|
|
215
|
+
name,
|
|
216
|
+
scorer_type,
|
|
217
|
+
config,
|
|
218
|
+
description
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* POST /api/scoring/profiles
|
|
224
|
+
*/
|
|
225
|
+
async createScoringProfile(profile) {
|
|
226
|
+
return this._request('/api/scoring/profiles', 'POST', profile);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* GET /api/compliance/map
|
|
231
|
+
*/
|
|
232
|
+
async mapCompliance(framework) {
|
|
233
|
+
return this._request(`/api/compliance/map`, 'GET', null, { framework });
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* GET /api/policies/proof
|
|
238
|
+
*/
|
|
239
|
+
async getProofReport(format = 'json') {
|
|
240
|
+
return this._request('/api/policies/proof', 'GET', null, { format });
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* GET /api/activity
|
|
245
|
+
*/
|
|
246
|
+
async getActivityLogs(filters = {}) {
|
|
247
|
+
return this._request('/api/activity', 'GET', null, filters);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* POST /api/webhooks
|
|
252
|
+
*/
|
|
253
|
+
async createWebhook(url, events = null) {
|
|
254
|
+
return this._request('/api/webhooks', 'POST', {
|
|
255
|
+
url,
|
|
256
|
+
events
|
|
257
|
+
});
|
|
258
|
+
}
|
|
135
259
|
}
|
|
136
260
|
|
|
137
261
|
export { DashClaw, ApprovalDeniedError, GuardBlockedError };
|