osuite 2.8.1 → 2.9.1
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 +172 -58
- package/cli.js +366 -75
- package/index.cjs +29 -30
- package/legacy/index-v1.cjs +2 -90
- package/legacy/osuite-v1-runtime.js +7 -0
- package/legacy/osuite-v1.js +1 -1
- package/osuite.js +505 -1
- package/package.json +3 -9
- package/reviewSurface.js +131 -0
- package/LICENSE +0 -21
- package/dashclaw.js +0 -628
- package/legacy/dashclaw-v1.js +0 -2888
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 DashClaw
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/dashclaw.js
DELETED
|
@@ -1,628 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DashClaw SDK v2 (Stable Runtime API)
|
|
3
|
-
* Focused governance runtime client for AI agents.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
class ApprovalDeniedError extends Error {
|
|
7
|
-
constructor(message, decision) {
|
|
8
|
-
super(message);
|
|
9
|
-
this.name = 'ApprovalDeniedError';
|
|
10
|
-
this.decision = decision;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
class GuardBlockedError extends Error {
|
|
15
|
-
constructor(decision) {
|
|
16
|
-
super(decision.reason || 'Action blocked by policy');
|
|
17
|
-
this.name = 'GuardBlockedError';
|
|
18
|
-
this.decision = decision;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
class DashClaw {
|
|
23
|
-
/**
|
|
24
|
-
* @param {Object} options
|
|
25
|
-
* @param {string} options.baseUrl - DashClaw base URL
|
|
26
|
-
* @param {string} options.apiKey - API key for authentication
|
|
27
|
-
* @param {string} options.agentId - Unique identifier for this agent
|
|
28
|
-
*/
|
|
29
|
-
constructor({ baseUrl, apiKey, agentId, agentKeyId = null, provenanceVersion = 'dc-prov-v1' }) {
|
|
30
|
-
if (!baseUrl) throw new Error('baseUrl is required');
|
|
31
|
-
if (!apiKey) throw new Error('apiKey is required');
|
|
32
|
-
if (!agentId) throw new Error('agentId is required');
|
|
33
|
-
|
|
34
|
-
this.baseUrl = baseUrl.replace(/\/$/, '');
|
|
35
|
-
this.apiKey = apiKey;
|
|
36
|
-
this.agentId = agentId;
|
|
37
|
-
this.agentKeyId = agentKeyId;
|
|
38
|
-
this.provenanceVersion = provenanceVersion;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
_withProvenance(payload = {}) {
|
|
42
|
-
const body = { ...payload };
|
|
43
|
-
const signature = body.agentSignature || body.agent_signature || body._signature || null;
|
|
44
|
-
|
|
45
|
-
delete body.agentSignature;
|
|
46
|
-
delete body.agent_signature;
|
|
47
|
-
|
|
48
|
-
if (signature) {
|
|
49
|
-
body._signature = signature;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (body.agent_key_id === undefined && this.agentKeyId) {
|
|
53
|
-
body.agent_key_id = this.agentKeyId;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (body.provenance_version === undefined && this.provenanceVersion) {
|
|
57
|
-
body.provenance_version = this.provenanceVersion;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return body;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async _request(path, method = 'GET', body = null, params = null) {
|
|
64
|
-
let url = `${this.baseUrl}${path}`;
|
|
65
|
-
if (params) {
|
|
66
|
-
const qs = new URLSearchParams(params).toString();
|
|
67
|
-
if (qs) url += `?${qs}`;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const headers = {
|
|
71
|
-
'Content-Type': 'application/json',
|
|
72
|
-
'x-api-key': this.apiKey
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
const res = await fetch(url, {
|
|
76
|
-
method,
|
|
77
|
-
headers,
|
|
78
|
-
body: body ? JSON.stringify(body) : undefined
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
const data = await res.json();
|
|
82
|
-
|
|
83
|
-
if (!res.ok) {
|
|
84
|
-
if (res.status === 403 && data.decision && data.decision.decision === 'block') {
|
|
85
|
-
throw new GuardBlockedError(data.decision);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Prioritize reason (from governance blocks) over generic error field
|
|
89
|
-
const errorMessage = data.reason || data.error || `Request failed with status ${res.status}`;
|
|
90
|
-
const err = new Error(errorMessage);
|
|
91
|
-
err.status = res.status;
|
|
92
|
-
err.details = data.details;
|
|
93
|
-
err.decision = data;
|
|
94
|
-
throw err;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return data;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* POST /api/guard — "Can I do X?"
|
|
102
|
-
* @param {Object} context
|
|
103
|
-
* @returns {Promise<{decision: 'allow'|'block'|'require_approval', action_id: string, reason: string, signals: string[]}>}
|
|
104
|
-
*/
|
|
105
|
-
async guard(context) {
|
|
106
|
-
return this._request('/api/guard', 'POST', this._withProvenance({
|
|
107
|
-
...context,
|
|
108
|
-
agent_id: context.agent_id || this.agentId,
|
|
109
|
-
}));
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* POST /api/actions — "I am attempting X."
|
|
114
|
-
*/
|
|
115
|
-
async createAction(action) {
|
|
116
|
-
return this._request('/api/actions', 'POST', this._withProvenance({
|
|
117
|
-
...action,
|
|
118
|
-
agent_id: this.agentId,
|
|
119
|
-
}));
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* PATCH /api/actions/:id — "X finished with result Y."
|
|
124
|
-
*/
|
|
125
|
-
async updateOutcome(actionId, outcome) {
|
|
126
|
-
return this._request(`/api/actions/${actionId}`, 'PATCH', {
|
|
127
|
-
...outcome,
|
|
128
|
-
timestamp_end: outcome.timestamp_end || new Date().toISOString()
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* GET /api/actions/:id — Fetch a single action by ID.
|
|
134
|
-
*/
|
|
135
|
-
async getAction(actionId) {
|
|
136
|
-
return this._request(`/api/actions/${actionId}`, 'GET');
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* GET /api/actions?status=pending_approval — List actions awaiting approval.
|
|
141
|
-
*/
|
|
142
|
-
async getPendingApprovals(limit = 20, offset = 0) {
|
|
143
|
-
return this._request('/api/actions', 'GET', null, {
|
|
144
|
-
status: 'pending_approval',
|
|
145
|
-
limit,
|
|
146
|
-
offset,
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* POST /api/actions/:id/approve — Approve or deny an action.
|
|
152
|
-
* @param {string} actionId
|
|
153
|
-
* @param {'allow'|'deny'} decision
|
|
154
|
-
* @param {string} [reasoning]
|
|
155
|
-
*/
|
|
156
|
-
async approveAction(actionId, decision, reasoning) {
|
|
157
|
-
const body = { decision };
|
|
158
|
-
if (reasoning) body.reasoning = reasoning;
|
|
159
|
-
return this._request(`/api/approvals/${actionId}`, 'POST', body);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* POST /api/assumptions — "I believe Z is true while doing X."
|
|
164
|
-
*/
|
|
165
|
-
async recordAssumption(assumption) {
|
|
166
|
-
return this._request('/api/assumptions', 'POST', assumption);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* GET /api/actions/:id — Polling helper for human approval.
|
|
171
|
-
*/
|
|
172
|
-
async waitForApproval(actionId, { timeout = 300000, interval = 5000 } = {}) {
|
|
173
|
-
const startTime = Date.now();
|
|
174
|
-
let wasPending = false;
|
|
175
|
-
let printedBlock = false;
|
|
176
|
-
|
|
177
|
-
while (Date.now() - startTime < timeout) {
|
|
178
|
-
const { action } = await this._request(`/api/actions/${actionId}`, 'GET');
|
|
179
|
-
|
|
180
|
-
// Print structured approval block on first fetch
|
|
181
|
-
if (!printedBlock) {
|
|
182
|
-
printedBlock = true;
|
|
183
|
-
try {
|
|
184
|
-
const actionType = action.action_type || 'unknown';
|
|
185
|
-
const riskScore = action.risk_score != null ? String(action.risk_score) : '-';
|
|
186
|
-
const goal = action.declared_goal || '-';
|
|
187
|
-
const agent = action.agent_id || this.agentId;
|
|
188
|
-
const replayUrl = `${this.baseUrl}/replay/${actionId}`;
|
|
189
|
-
|
|
190
|
-
const lines = [
|
|
191
|
-
'\u2554\u2550\u2550 DashClaw Approval Required \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557',
|
|
192
|
-
` Action ID: ${actionId}`,
|
|
193
|
-
` Agent: ${agent}`,
|
|
194
|
-
` Action: ${actionType}`,
|
|
195
|
-
' Policy: require_approval',
|
|
196
|
-
` Risk Score: ${riskScore}`,
|
|
197
|
-
` Goal: ${goal}`,
|
|
198
|
-
'',
|
|
199
|
-
` Replay: ${replayUrl}`,
|
|
200
|
-
'',
|
|
201
|
-
' Waiting for approval... (Ctrl+C to abort)',
|
|
202
|
-
'\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d',
|
|
203
|
-
];
|
|
204
|
-
process.stdout.write('\n' + lines.join('\n') + '\n\n');
|
|
205
|
-
} catch (_) {
|
|
206
|
-
// Rendering failure must not prevent the wait from proceeding
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
if (action.status === 'pending_approval') {
|
|
211
|
-
wasPending = true;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// Explicitly unblocked by approval metadata.
|
|
215
|
-
// API key / CLI approvals may not have a human user id, so approved_at is
|
|
216
|
-
// also treated as authoritative approval evidence.
|
|
217
|
-
if (action.approved_by || action.approved_at) return action;
|
|
218
|
-
|
|
219
|
-
// Denial cases
|
|
220
|
-
if (action.status === 'failed' || action.status === 'cancelled') {
|
|
221
|
-
throw new ApprovalDeniedError(action.error_message || 'Operator denied the action.', action.status);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// Requirement 4: If an action leaves pending_approval without approval metadata, throw an error.
|
|
225
|
-
// This prevents "auto-approval" bugs where status is changed by non-approval paths.
|
|
226
|
-
if (wasPending && action.status !== 'pending_approval') {
|
|
227
|
-
throw new Error(`Action ${actionId} left pending_approval state without explicit approval metadata (Status: ${action.status})`);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// If allowed directly (never intercepted), return immediately
|
|
231
|
-
if (!wasPending && action.status === 'running') {
|
|
232
|
-
return { action };
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
await new Promise(r => setTimeout(r, interval));
|
|
236
|
-
}
|
|
237
|
-
throw new Error(`Timed out waiting for approval of action ${actionId}`);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* POST /api/agents/heartbeat
|
|
242
|
-
*/
|
|
243
|
-
async heartbeat(status = 'online', metadata = null) {
|
|
244
|
-
return this._request('/api/agents/heartbeat', 'POST', {
|
|
245
|
-
agent_id: this.agentId,
|
|
246
|
-
status,
|
|
247
|
-
metadata
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* POST /api/agents/connections
|
|
253
|
-
*/
|
|
254
|
-
async reportConnections(connections) {
|
|
255
|
-
return this._request('/api/agents/connections', 'POST', {
|
|
256
|
-
agent_id: this.agentId,
|
|
257
|
-
connections
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* POST /api/actions/loops
|
|
263
|
-
*/
|
|
264
|
-
async registerOpenLoop(actionId, loopType, description, metadata = null) {
|
|
265
|
-
return this._request('/api/actions/loops', 'POST', {
|
|
266
|
-
action_id: actionId,
|
|
267
|
-
loop_type: loopType,
|
|
268
|
-
description,
|
|
269
|
-
metadata
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* PATCH /api/actions/loops/:id
|
|
275
|
-
*/
|
|
276
|
-
async resolveOpenLoop(loopId, status, resolution = null) {
|
|
277
|
-
return this._request(`/api/actions/loops/${loopId}`, 'PATCH', {
|
|
278
|
-
status,
|
|
279
|
-
resolution
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* GET /api/actions/signals
|
|
285
|
-
*/
|
|
286
|
-
async getSignals() {
|
|
287
|
-
return this._request('/api/actions/signals');
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/**
|
|
291
|
-
* GET /api/learning/analytics/velocity
|
|
292
|
-
*/
|
|
293
|
-
async getLearningVelocity(lookbackDays = 30) {
|
|
294
|
-
return this._request('/api/learning/analytics/velocity', 'GET', null, {
|
|
295
|
-
agent_id: this.agentId,
|
|
296
|
-
lookback_days: lookbackDays
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
/**
|
|
301
|
-
* GET /api/learning/analytics/curves
|
|
302
|
-
*/
|
|
303
|
-
async getLearningCurves(lookbackDays = 60) {
|
|
304
|
-
return this._request('/api/learning/analytics/curves', 'GET', null, {
|
|
305
|
-
agent_id: this.agentId,
|
|
306
|
-
lookback_days: lookbackDays
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
* GET /api/learning/lessons — Fetch consolidated lessons from scored outcomes.
|
|
312
|
-
*/
|
|
313
|
-
async getLessons({ actionType, limit } = {}) {
|
|
314
|
-
return this._request('/api/learning/lessons', 'GET', null, {
|
|
315
|
-
agent_id: this.agentId,
|
|
316
|
-
...(actionType && { action_type: actionType }),
|
|
317
|
-
...(limit && { limit }),
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
/**
|
|
322
|
-
* POST /api/prompts/render
|
|
323
|
-
*/
|
|
324
|
-
async renderPrompt({ template_id, version_id, variables, record = false }) {
|
|
325
|
-
return this._request('/api/prompts/render', 'POST', {
|
|
326
|
-
template_id,
|
|
327
|
-
version_id,
|
|
328
|
-
variables,
|
|
329
|
-
agent_id: this.agentId,
|
|
330
|
-
record
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
* POST /api/evaluations/scorers
|
|
336
|
-
*/
|
|
337
|
-
async createScorer(name, scorer_type, config = null, description = null) {
|
|
338
|
-
return this._request('/api/evaluations/scorers', 'POST', {
|
|
339
|
-
name,
|
|
340
|
-
scorer_type,
|
|
341
|
-
config,
|
|
342
|
-
description
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
/**
|
|
347
|
-
* POST /api/scoring/profiles
|
|
348
|
-
*/
|
|
349
|
-
async createScoringProfile(profile) {
|
|
350
|
-
return this._request('/api/scoring/profiles', 'POST', profile);
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* GET /api/scoring/profiles
|
|
355
|
-
*/
|
|
356
|
-
async listScoringProfiles(filters = {}) {
|
|
357
|
-
return this._request('/api/scoring/profiles', 'GET', null, filters);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
/**
|
|
361
|
-
* GET /api/scoring/profiles/:id
|
|
362
|
-
*/
|
|
363
|
-
async getScoringProfile(profileId) {
|
|
364
|
-
return this._request(`/api/scoring/profiles/${profileId}`, 'GET');
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
/**
|
|
368
|
-
* PATCH /api/scoring/profiles/:id
|
|
369
|
-
*/
|
|
370
|
-
async updateScoringProfile(profileId, updates) {
|
|
371
|
-
return this._request(`/api/scoring/profiles/${profileId}`, 'PATCH', updates);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
/**
|
|
375
|
-
* DELETE /api/scoring/profiles/:id
|
|
376
|
-
*/
|
|
377
|
-
async deleteScoringProfile(profileId) {
|
|
378
|
-
return this._request(`/api/scoring/profiles/${profileId}`, 'DELETE');
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
/**
|
|
382
|
-
* POST /api/scoring/profiles/:id/dimensions
|
|
383
|
-
*/
|
|
384
|
-
async addScoringDimension(profileId, dimension) {
|
|
385
|
-
return this._request(`/api/scoring/profiles/${profileId}/dimensions`, 'POST', dimension);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
/**
|
|
389
|
-
* PATCH /api/scoring/profiles/:id/dimensions/:dimId
|
|
390
|
-
*/
|
|
391
|
-
async updateScoringDimension(profileId, dimensionId, updates) {
|
|
392
|
-
return this._request(`/api/scoring/profiles/${profileId}/dimensions/${dimensionId}`, 'PATCH', updates);
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
/**
|
|
396
|
-
* DELETE /api/scoring/profiles/:id/dimensions/:dimId
|
|
397
|
-
*/
|
|
398
|
-
async deleteScoringDimension(profileId, dimensionId) {
|
|
399
|
-
return this._request(`/api/scoring/profiles/${profileId}/dimensions/${dimensionId}`, 'DELETE');
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
/**
|
|
403
|
-
* POST /api/scoring/score — score a single action against a profile
|
|
404
|
-
*/
|
|
405
|
-
async scoreWithProfile(profileId, action) {
|
|
406
|
-
return this._request('/api/scoring/score', 'POST', { profile_id: profileId, action });
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
/**
|
|
410
|
-
* POST /api/scoring/score — batch score multiple actions against a profile
|
|
411
|
-
*/
|
|
412
|
-
async batchScoreWithProfile(profileId, actions) {
|
|
413
|
-
return this._request('/api/scoring/score', 'POST', { profile_id: profileId, actions });
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
/**
|
|
417
|
-
* GET /api/scoring/score — list stored profile scores
|
|
418
|
-
*/
|
|
419
|
-
async getProfileScores(filters = {}) {
|
|
420
|
-
return this._request('/api/scoring/score', 'GET', null, filters);
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
/**
|
|
424
|
-
* GET /api/scoring/score?view=stats — aggregate stats for a profile
|
|
425
|
-
*/
|
|
426
|
-
async getProfileScoreStats(profileId) {
|
|
427
|
-
return this._request('/api/scoring/score', 'GET', null, { profile_id: profileId, view: 'stats' });
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
/**
|
|
431
|
-
* POST /api/scoring/risk-templates
|
|
432
|
-
*/
|
|
433
|
-
async createRiskTemplate(template) {
|
|
434
|
-
return this._request('/api/scoring/risk-templates', 'POST', template);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
/**
|
|
438
|
-
* GET /api/scoring/risk-templates
|
|
439
|
-
*/
|
|
440
|
-
async listRiskTemplates(filters = {}) {
|
|
441
|
-
return this._request('/api/scoring/risk-templates', 'GET', null, filters);
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
/**
|
|
445
|
-
* PATCH /api/scoring/risk-templates/:id
|
|
446
|
-
*/
|
|
447
|
-
async updateRiskTemplate(templateId, updates) {
|
|
448
|
-
return this._request(`/api/scoring/risk-templates/${templateId}`, 'PATCH', updates);
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
/**
|
|
452
|
-
* DELETE /api/scoring/risk-templates/:id
|
|
453
|
-
*/
|
|
454
|
-
async deleteRiskTemplate(templateId) {
|
|
455
|
-
return this._request(`/api/scoring/risk-templates/${templateId}`, 'DELETE');
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
/**
|
|
459
|
-
* POST /api/scoring/calibrate — analyze historical data and suggest dimension thresholds
|
|
460
|
-
*/
|
|
461
|
-
async autoCalibrate(options = {}) {
|
|
462
|
-
return this._request('/api/scoring/calibrate', 'POST', options);
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
// ---------------------------------------------------------------------------
|
|
466
|
-
// Agent Messaging
|
|
467
|
-
// ---------------------------------------------------------------------------
|
|
468
|
-
|
|
469
|
-
/**
|
|
470
|
-
* POST /api/messages — Send a message to another agent or the dashboard.
|
|
471
|
-
*/
|
|
472
|
-
async sendMessage({ to, type, subject, body, threadId, urgent, actionId }) {
|
|
473
|
-
return this._request('/api/messages', 'POST', {
|
|
474
|
-
from_agent_id: this.agentId,
|
|
475
|
-
to_agent_id: to,
|
|
476
|
-
message_type: type,
|
|
477
|
-
subject,
|
|
478
|
-
body,
|
|
479
|
-
thread_id: threadId,
|
|
480
|
-
urgent,
|
|
481
|
-
action_id: actionId,
|
|
482
|
-
});
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
/**
|
|
486
|
-
* Create a scoped action context that auto-tags messages and assumptions
|
|
487
|
-
* with the given action_id.
|
|
488
|
-
* @param {string} actionId - The action_id to attach to all operations
|
|
489
|
-
* @returns {{ sendMessage, recordAssumption, updateOutcome }}
|
|
490
|
-
*/
|
|
491
|
-
actionContext(actionId) {
|
|
492
|
-
return {
|
|
493
|
-
sendMessage: ({ to, type, subject, body, threadId, urgent }) => {
|
|
494
|
-
return this.sendMessage({ to, type, subject, body, threadId, urgent, actionId });
|
|
495
|
-
},
|
|
496
|
-
recordAssumption: (assumption) => {
|
|
497
|
-
return this.recordAssumption({ ...assumption, action_id: actionId });
|
|
498
|
-
},
|
|
499
|
-
updateOutcome: (outcome) => {
|
|
500
|
-
return this.updateOutcome(actionId, outcome);
|
|
501
|
-
},
|
|
502
|
-
};
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
/**
|
|
506
|
-
* GET /api/messages — Fetch this agent's inbox.
|
|
507
|
-
*/
|
|
508
|
-
async getInbox({ type, unread, limit } = {}) {
|
|
509
|
-
return this._request('/api/messages', 'GET', null, {
|
|
510
|
-
agent_id: this.agentId,
|
|
511
|
-
direction: 'inbox',
|
|
512
|
-
...(type && { type }),
|
|
513
|
-
...(unread != null && { unread }),
|
|
514
|
-
...(limit && { limit }),
|
|
515
|
-
});
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
// ---------------------------------------------------------------------------
|
|
519
|
-
// Session Handoffs
|
|
520
|
-
// ---------------------------------------------------------------------------
|
|
521
|
-
|
|
522
|
-
/**
|
|
523
|
-
* POST /api/handoffs — Create a session handoff record.
|
|
524
|
-
*/
|
|
525
|
-
async createHandoff(handoff) {
|
|
526
|
-
return this._request('/api/handoffs', 'POST', {
|
|
527
|
-
agent_id: this.agentId,
|
|
528
|
-
...handoff,
|
|
529
|
-
});
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
/**
|
|
533
|
-
* GET /api/handoffs — Fetch the most recent handoff for this agent.
|
|
534
|
-
*/
|
|
535
|
-
async getLatestHandoff() {
|
|
536
|
-
return this._request('/api/handoffs', 'GET', null, {
|
|
537
|
-
agent_id: this.agentId,
|
|
538
|
-
latest: 'true',
|
|
539
|
-
});
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
// ---------------------------------------------------------------------------
|
|
543
|
-
// Security Scanning
|
|
544
|
-
// ---------------------------------------------------------------------------
|
|
545
|
-
|
|
546
|
-
/**
|
|
547
|
-
* POST /api/security/prompt-injection — Scan text for prompt injection attacks.
|
|
548
|
-
*/
|
|
549
|
-
async scanPromptInjection(text, { source } = {}) {
|
|
550
|
-
return this._request('/api/security/prompt-injection', 'POST', {
|
|
551
|
-
text,
|
|
552
|
-
source,
|
|
553
|
-
agent_id: this.agentId,
|
|
554
|
-
});
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
// ---------------------------------------------------------------------------
|
|
558
|
-
// User Feedback
|
|
559
|
-
// ---------------------------------------------------------------------------
|
|
560
|
-
|
|
561
|
-
/**
|
|
562
|
-
* POST /api/feedback — Submit user feedback linked to an action.
|
|
563
|
-
*/
|
|
564
|
-
async submitFeedback({ action_id, rating, comment, category, tags, metadata }) {
|
|
565
|
-
return this._request('/api/feedback', 'POST', {
|
|
566
|
-
action_id,
|
|
567
|
-
agent_id: this.agentId,
|
|
568
|
-
rating,
|
|
569
|
-
comment,
|
|
570
|
-
category,
|
|
571
|
-
tags,
|
|
572
|
-
metadata,
|
|
573
|
-
});
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
// ---------------------------------------------------------------------------
|
|
577
|
-
// Context Threads
|
|
578
|
-
// ---------------------------------------------------------------------------
|
|
579
|
-
|
|
580
|
-
/**
|
|
581
|
-
* POST /api/context/threads — Create a reasoning context thread.
|
|
582
|
-
*/
|
|
583
|
-
async createThread(thread) {
|
|
584
|
-
return this._request('/api/context/threads', 'POST', {
|
|
585
|
-
agent_id: this.agentId,
|
|
586
|
-
...thread,
|
|
587
|
-
});
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
/**
|
|
591
|
-
* POST /api/context/threads/:id/entries — Append a reasoning step.
|
|
592
|
-
*/
|
|
593
|
-
async addThreadEntry(threadId, content, entryType) {
|
|
594
|
-
return this._request(`/api/context/threads/${threadId}/entries`, 'POST', {
|
|
595
|
-
content,
|
|
596
|
-
entry_type: entryType,
|
|
597
|
-
});
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
/**
|
|
601
|
-
* PATCH /api/context/threads/:id — Close a reasoning thread.
|
|
602
|
-
*/
|
|
603
|
-
async closeThread(threadId, summary) {
|
|
604
|
-
return this._request(`/api/context/threads/${threadId}`, 'PATCH', {
|
|
605
|
-
status: 'closed',
|
|
606
|
-
...(summary ? { summary } : {}),
|
|
607
|
-
});
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
// ---------------------------------------------------------------------------
|
|
611
|
-
// Bulk Sync
|
|
612
|
-
// ---------------------------------------------------------------------------
|
|
613
|
-
|
|
614
|
-
/**
|
|
615
|
-
* POST /api/sync — Bulk state sync for periodic updates or bootstrap.
|
|
616
|
-
*/
|
|
617
|
-
async syncState(state) {
|
|
618
|
-
return this._request('/api/sync', 'POST', {
|
|
619
|
-
agent_id: this.agentId,
|
|
620
|
-
...state,
|
|
621
|
-
});
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
const OSuite = DashClaw;
|
|
626
|
-
|
|
627
|
-
export default OSuite;
|
|
628
|
-
export { DashClaw, OSuite, ApprovalDeniedError, GuardBlockedError };
|