dashclaw 2.13.0 → 3.0.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 +76 -23
- package/dashclaw.js +269 -26
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# DashClaw SDK
|
|
1
|
+
# DashClaw SDK
|
|
2
2
|
|
|
3
3
|
**Minimal governance runtime for AI agents.**
|
|
4
4
|
|
|
@@ -141,14 +141,16 @@ Telegram button.
|
|
|
141
141
|
### The rule every agent author needs to know
|
|
142
142
|
|
|
143
143
|
**`waitForApproval()` must be called with the `action_id` returned by
|
|
144
|
-
`createAction()`, NOT with the
|
|
144
|
+
`createAction()`, NOT with the guard decision's id.**
|
|
145
145
|
|
|
146
146
|
These are two different records in two different tables:
|
|
147
147
|
|
|
148
|
-
| Call | Returns
|
|
149
|
-
|
|
150
|
-
| `guard()` | A row in `guard_decisions` (the decision log) | `act_gd_…` |
|
|
151
|
-
| `createAction()` | A row in `action_records` (the thing you're actually doing) | `act_…` |
|
|
148
|
+
| Call | Returns an id that refers to… | Prefix | Field on the result |
|
|
149
|
+
|---|---|---|---|
|
|
150
|
+
| `guard()` | A row in `guard_decisions` (the decision log) | `act_gd_…` | `decision_id` (canonical); `action_id` is a **deprecated alias** of the same value |
|
|
151
|
+
| `createAction()` | A row in `action_records` (the thing you're actually doing) | `act_…` | `action_id` |
|
|
152
|
+
|
|
153
|
+
> The guard result's `action_id` field is a legacy alias of `decision_id` and will be removed in a future major — read `decision_id` from `guard()`, and `action_id` from `createAction()`.
|
|
152
154
|
|
|
153
155
|
`waitForApproval()` polls `GET /api/actions/:id`, which is the
|
|
154
156
|
`action_records` table. Passing it a `guard_decisions` ID (`act_gd_…`) will
|
|
@@ -221,6 +223,39 @@ answer to "does this need human review?" is always `action.status` on the
|
|
|
221
223
|
Short version: **trust `action.status`, not `decision.decision`, for HITL
|
|
222
224
|
branching.**
|
|
223
225
|
|
|
226
|
+
### Non-fabrication checks
|
|
227
|
+
|
|
228
|
+
When a `non_fabrication` guard policy is active, attach the outbound text and the
|
|
229
|
+
facts it is allowed to state, and DashClaw verifies the content before the action
|
|
230
|
+
proceeds — every amount, date, percentage, and registered ID must trace to an
|
|
231
|
+
allowed fact, every required fact must be present, and no forbidden pattern may
|
|
232
|
+
appear. A violation blocks (or routes to approval) and is recorded with a signed,
|
|
233
|
+
re-verifiable receipt.
|
|
234
|
+
|
|
235
|
+
```javascript
|
|
236
|
+
const decision = await claw.guard({
|
|
237
|
+
action_type: 'message',
|
|
238
|
+
content: 'Hi Jane — your refund of $1,500.00 will arrive by June 1, 2026.',
|
|
239
|
+
sourceOfTruth: {
|
|
240
|
+
allowedFacts: [
|
|
241
|
+
{ label: 'refund', value: '$1,500.00' },
|
|
242
|
+
{ label: 'date', value: 'June 1, 2026' },
|
|
243
|
+
],
|
|
244
|
+
requiredFacts: [{ label: 'name', value: 'Jane' }],
|
|
245
|
+
// forbiddenPatterns, extract (money/dates/percentages/patterns) are optional
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
// decision.decision === 'block' if the text states a fact not in sourceOfTruth.
|
|
249
|
+
// decision.non_fabrication[0].receipt is an Ed25519-signed proof you can
|
|
250
|
+
// re-verify at POST /api/integrity/verify (public key: /.well-known/jwks.json),
|
|
251
|
+
// or null if the instance has no usable signing key — the verdict is enforced either way.
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
`createAction()` accepts the same `content` + `sourceOfTruth` fields. Fail-closed:
|
|
255
|
+
a missing or malformed `sourceOfTruth` blocks. A signature proves integrity, the
|
|
256
|
+
verdict, the ruleset version, and the issuer — not time-of-issuance or the
|
|
257
|
+
correctness of prose with no extractable token.
|
|
258
|
+
|
|
224
259
|
---
|
|
225
260
|
|
|
226
261
|
## SDK Tiers
|
|
@@ -251,7 +286,7 @@ See:
|
|
|
251
286
|
|
|
252
287
|
---
|
|
253
288
|
|
|
254
|
-
## SDK Surface Area
|
|
289
|
+
## SDK Surface Area
|
|
255
290
|
|
|
256
291
|
The v2 SDK exposes the stable governance runtime plus promoted execution domains in the canonical Node client:
|
|
257
292
|
|
|
@@ -264,6 +299,9 @@ The v2 SDK exposes the stable governance runtime plus promoted execution domains
|
|
|
264
299
|
- `approveAction(id, decision, reasoning?)` -- Submit approval decisions from code
|
|
265
300
|
- `getPendingApprovals()` -- List actions awaiting human review
|
|
266
301
|
|
|
302
|
+
### Policies
|
|
303
|
+
- `simulatePolicy({ policy_type, rules, days })` -- Side-effect-free dry-run of a proposed policy against recent historical actions before committing it (pairs with `guard()` for live enforcement). `policy_type` and `rules` are required; `days` is optional. Returns `{ summary: { total, matches, block, warn, require_approval, allow }, matches, sample_size, window_days }`. Persists nothing.
|
|
304
|
+
|
|
267
305
|
### Durable Execution Finality (v2.13.3+)
|
|
268
306
|
Terminal outcome reporting that is one-shot, retry-safe, and immutable once non-pending. Separate from `updateOutcome`, which remains the lifecycle-PATCH path. Full spec: [`docs/architecture/durable-execution-finality.md`](../docs/architecture/durable-execution-finality.md). Detailed examples in the [Action Outcome](#action-outcome-durable-execution-finality) subsection of Execution Studio below.
|
|
269
307
|
|
|
@@ -289,6 +327,22 @@ Terminal outcome reporting that is one-shot, retry-safe, and immutable once non-
|
|
|
289
327
|
- `getLessons({ actionType, limit })` -- Fetch consolidated lessons from scored outcomes.
|
|
290
328
|
- `renderPrompt({ template_id, version_id, variables, record })` -- Fetch a rendered prompt template from DashClaw. `template_id` is required; `version_id` defaults to the active version; `variables` is an object of mustache values; `record: true` persists the render as a governance event.
|
|
291
329
|
|
|
330
|
+
### Prompt Library
|
|
331
|
+
|
|
332
|
+
Manage reusable prompt templates, their versions, and usage analytics. `renderPrompt` (above) fetches a rendered version; these manage the library itself. Mutations (`create*`, `update*`, `delete*`, version creation, and `activate*`) require an admin org role.
|
|
333
|
+
|
|
334
|
+
- `listPromptTemplates({ category })` -- List prompt templates (each with `version_count` + `active_version`). Returns `{ templates }`.
|
|
335
|
+
- `getPromptTemplate(templateId)` -- Fetch a single template.
|
|
336
|
+
- `createPromptTemplate({ name, description, category })` -- Create a template (admin). `name` is required; `description` and `category` are optional. Returns `{ id, name, description, category }`.
|
|
337
|
+
- `updatePromptTemplate(templateId, patch)` -- Update a template (admin). `patch` accepts `name`, `description`, `category`.
|
|
338
|
+
- `deletePromptTemplate(templateId)` -- Delete a template plus its versions and runs (admin). Returns `{ deleted: true }`.
|
|
339
|
+
- `listPromptVersions(templateId)` -- List versions for a template (newest first). Returns `{ versions }`.
|
|
340
|
+
- `createPromptVersion(templateId, { content, model_hint, parameters, changelog })` -- Create a version (admin). `content` is required; `model_hint`, `parameters`, `changelog` are optional.
|
|
341
|
+
- `getPromptVersion(templateId, versionId)` -- Fetch a single version.
|
|
342
|
+
- `activatePromptVersion(templateId, versionId)` -- Activate a version (admin). Activating one version deactivates the others for that template.
|
|
343
|
+
- `getPromptStats({ template_id })` -- Prompt usage analytics, optionally scoped to one template.
|
|
344
|
+
- `listPromptRuns({ template_id, version_id, limit })` -- List recorded prompt runs.
|
|
345
|
+
|
|
292
346
|
### Learning Loop
|
|
293
347
|
|
|
294
348
|
The guard response now includes a `learning` field when DashClaw has historical data for the agent and action type. This creates a closed learning loop: outcomes feed back into guard decisions automatically.
|
|
@@ -313,6 +367,9 @@ lessons.forEach(l => console.log(l.guidance));
|
|
|
313
367
|
// guidance, sample_size
|
|
314
368
|
```
|
|
315
369
|
|
|
370
|
+
- `recordDecision({ decision, context, reasoning, outcome, confidence, agent_id })` -- Record a decision/outcome into the learning ledger. `decision` is required; `agent_id` is auto-injected from the constructor when omitted. Returns `{ decision }`.
|
|
371
|
+
- `getLearningRecommendations({ agent_id, action_type, include_metrics, lookback_days, limit })` -- Read learned recommendations for an agent/action type. `agent_id` defaults to the constructor's agent.
|
|
372
|
+
|
|
316
373
|
### Scoring Profiles
|
|
317
374
|
- `createScorer(name, type, config)` -- Define automated evaluations.
|
|
318
375
|
- `createScoringProfile(profile)` -- Create a weighted multi-dimensional scoring profile.
|
|
@@ -333,9 +390,17 @@ lessons.forEach(l => console.log(l.guidance));
|
|
|
333
390
|
- `deleteRiskTemplate(templateId)` -- Delete a risk template.
|
|
334
391
|
- `autoCalibrate(options)` -- Analyze historical actions and suggest percentile-based scoring scales.
|
|
335
392
|
|
|
393
|
+
### Evaluations
|
|
394
|
+
- `previewScorer({ scorer_type, config, sample })` -- Dry-run a scorer config against a sample action to validate a quality gate before creating a scorer or launching a run. `scorer_type` is required; `config` and `sample` are optional. Writes **no** `eval_scores` row (distinct from the scoring-profiles subsystem above). Returns `{ preview, scorer_type, result: { score, label, reasoning, error } }`.
|
|
395
|
+
|
|
336
396
|
### Messaging
|
|
337
397
|
- `sendMessage({ to, type, subject, body, threadId, urgent })` -- Send a message to another agent or broadcast.
|
|
338
398
|
- `getInbox({ type, unread, limit })` -- Retrieve inbox messages with optional filters.
|
|
399
|
+
- `getSentMessages({ type, threadId, limit })` -- Retrieve messages this agent has sent.
|
|
400
|
+
- `getMessages({ direction, type, unread, threadId, limit })` -- Retrieve messages with flexible filters.
|
|
401
|
+
- `getMessage(messageId)` -- Fetch a single message by id.
|
|
402
|
+
- `markRead(messageIds)` -- Mark messages as read for this agent (`PATCH /api/messages`, `action: 'read'`).
|
|
403
|
+
- `archiveMessages(messageIds)` -- Archive messages for this agent (`PATCH /api/messages`, `action: 'archive'`).
|
|
339
404
|
|
|
340
405
|
```javascript
|
|
341
406
|
// Send a message to another agent
|
|
@@ -382,21 +447,6 @@ if (result.recommendation === 'block') {
|
|
|
382
447
|
}
|
|
383
448
|
```
|
|
384
449
|
|
|
385
|
-
### Feedback
|
|
386
|
-
- `submitFeedback({ action_id, rating, comment, category, tags, metadata })` -- Submit feedback on an action.
|
|
387
|
-
|
|
388
|
-
```javascript
|
|
389
|
-
// Submit feedback on an action
|
|
390
|
-
await claw.submitFeedback({
|
|
391
|
-
action_id: 'act_123',
|
|
392
|
-
rating: 5,
|
|
393
|
-
comment: 'Deploy was smooth',
|
|
394
|
-
category: 'deployment',
|
|
395
|
-
tags: ['fast', 'clean'],
|
|
396
|
-
metadata: { deploy_duration_ms: 1200 }
|
|
397
|
-
});
|
|
398
|
-
```
|
|
399
|
-
|
|
400
450
|
### Context Threads
|
|
401
451
|
- `createThread(thread)` -- Create a context thread for tracking multi-step work.
|
|
402
452
|
- `addThreadEntry(threadId, content, entryType)` -- Add an entry to a context thread.
|
|
@@ -604,7 +654,7 @@ If your agent supports Model Context Protocol (Claude Code, Claude Desktop, Mana
|
|
|
604
654
|
- **Open loops (3):** `dashclaw_loop_add`, `dashclaw_loop_list`, `dashclaw_loop_close` — action-scoped commitments (the "I will X later" tracker).
|
|
605
655
|
- **Learning + retrospection (3):** `dashclaw_learning_log`, `dashclaw_learning_query`, `dashclaw_decisions_recent` — log + query non-obvious decisions; recent governed-action ledger.
|
|
606
656
|
|
|
607
|
-
**
|
|
657
|
+
**6 resources:** `dashclaw://policies`, `dashclaw://capabilities`, `dashclaw://agent/{agent_id}/history`, `dashclaw://status`, `dashclaw://code-sessions/projects`, `dashclaw://code-sessions/sessions/{session_id}`.
|
|
608
658
|
|
|
609
659
|
### Agent runtime endpoints (server-side, no SDK wrapper)
|
|
610
660
|
|
|
@@ -904,6 +954,9 @@ const { results } = await claw.searchKnowledgeCollection(
|
|
|
904
954
|
{ limit: 5 }
|
|
905
955
|
);
|
|
906
956
|
results.forEach(r => console.log(`${(r.score * 100).toFixed(1)}%: ${r.content.slice(0, 80)}...`));
|
|
957
|
+
|
|
958
|
+
// Delete a collection (cascades its items + chunks)
|
|
959
|
+
const { deleted, collection_id } = await claw.deleteKnowledgeCollection(collection.collection_id);
|
|
907
960
|
```
|
|
908
961
|
|
|
909
962
|
### Capability Runtime
|
package/dashclaw.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* DashClaw SDK
|
|
2
|
+
* DashClaw SDK (Stable Runtime API)
|
|
3
3
|
* Focused governance runtime client for AI agents.
|
|
4
|
+
*
|
|
5
|
+
* Version is the single source of truth in sdk/package.json — never
|
|
6
|
+
* hardcoded here, in the README header, or in app/ pages. Consumers
|
|
7
|
+
* read it at runtime via `import pkg from 'dashclaw/package.json'`.
|
|
4
8
|
*/
|
|
5
9
|
|
|
6
10
|
import { createHash } from 'crypto';
|
|
@@ -62,8 +66,16 @@ class DashClaw {
|
|
|
62
66
|
async _request(path, method = 'GET', body = null, params = null) {
|
|
63
67
|
let url = `${this.baseUrl}${path}`;
|
|
64
68
|
if (params) {
|
|
65
|
-
|
|
66
|
-
|
|
69
|
+
// Skip undefined/null values. Passing them straight into URLSearchParams
|
|
70
|
+
// serializes the literal strings "undefined"/"null", which the receiving
|
|
71
|
+
// routes treat as real filter values and match zero rows. Falsy-but-valid
|
|
72
|
+
// values (0, false, '') are preserved. Mirrors the v1 SDK behavior.
|
|
73
|
+
const qs = new URLSearchParams();
|
|
74
|
+
for (const [key, value] of Object.entries(params)) {
|
|
75
|
+
if (value !== undefined && value !== null) qs.append(key, String(value));
|
|
76
|
+
}
|
|
77
|
+
const s = qs.toString();
|
|
78
|
+
if (s) url += `?${s}`;
|
|
67
79
|
}
|
|
68
80
|
|
|
69
81
|
const headers = {
|
|
@@ -78,7 +90,16 @@ class DashClaw {
|
|
|
78
90
|
body: body ? JSON.stringify(body) : undefined
|
|
79
91
|
});
|
|
80
92
|
|
|
81
|
-
|
|
93
|
+
// Parse the body defensively. A non-JSON error body (a Vercel 502/504/413
|
|
94
|
+
// gateway page, a 429 rate-limit page) makes res.json() reject with a
|
|
95
|
+
// SyntaxError, which would propagate instead of the status-bearing error
|
|
96
|
+
// below and lose res.status. Fall back to {} so the real status is thrown.
|
|
97
|
+
let data = {};
|
|
98
|
+
try {
|
|
99
|
+
data = await res.json();
|
|
100
|
+
} catch {
|
|
101
|
+
data = {};
|
|
102
|
+
}
|
|
82
103
|
|
|
83
104
|
if (!res.ok) {
|
|
84
105
|
if (res.status === 403 && data.decision && data.decision.decision === 'block') {
|
|
@@ -100,6 +121,14 @@ class DashClaw {
|
|
|
100
121
|
/**
|
|
101
122
|
* POST /api/guard — "Can I do X?"
|
|
102
123
|
* @param {Object} context
|
|
124
|
+
* @param {string} [context.content] - Outbound content to fabrication-check
|
|
125
|
+
* (e.g. a drafted email/message). Pairs with `sourceOfTruth` and a
|
|
126
|
+
* `non_fabrication` guard policy: every operational token (amounts, dates,
|
|
127
|
+
* percentages, registered IDs) must trace to an allowed fact, or the action
|
|
128
|
+
* is blocked / routed to approval. The response carries a signed,
|
|
129
|
+
* re-verifiable receipt under `non_fabrication`.
|
|
130
|
+
* @param {Object} [context.sourceOfTruth] - The facts `content` is allowed to
|
|
131
|
+
* state: `{ allowedFacts, requiredFacts, forbiddenPatterns?, extract? }`.
|
|
103
132
|
* @returns {Promise<{
|
|
104
133
|
* decision: 'allow'|'block'|'require_approval'|'warn',
|
|
105
134
|
* action_id: string,
|
|
@@ -129,6 +158,13 @@ class DashClaw {
|
|
|
129
158
|
|
|
130
159
|
/**
|
|
131
160
|
* POST /api/actions — "I am attempting X."
|
|
161
|
+
*
|
|
162
|
+
* Optional non-fabrication fields: pass `content` (the outbound text) and
|
|
163
|
+
* `sourceOfTruth` ({ allowedFacts, requiredFacts, forbiddenPatterns?, extract? })
|
|
164
|
+
* to have a `non_fabrication` guard policy verify the content before the
|
|
165
|
+
* action proceeds. A violation blocks the action or routes it to approval and
|
|
166
|
+
* is recorded with a signed receipt in the decision ledger.
|
|
167
|
+
* @param {Object} action
|
|
132
168
|
*/
|
|
133
169
|
async createAction(action) {
|
|
134
170
|
return this._request('/api/actions', 'POST', {
|
|
@@ -289,7 +325,12 @@ class DashClaw {
|
|
|
289
325
|
let printedBlock = false;
|
|
290
326
|
|
|
291
327
|
while (Date.now() - startTime < timeout) {
|
|
292
|
-
|
|
328
|
+
// Return the full GET response (action + open_loops + assumptions +
|
|
329
|
+
// message_summary) so the polling fallback resolves to the same shape as
|
|
330
|
+
// the SSE fast-path above and the Python SDK. Returning only { action }
|
|
331
|
+
// dropped the related collections whenever SSE was unavailable.
|
|
332
|
+
const result = await this._request(`/api/actions/${actionId}`, 'GET');
|
|
333
|
+
const action = result.action;
|
|
293
334
|
|
|
294
335
|
if (!printedBlock) {
|
|
295
336
|
printedBlock = true;
|
|
@@ -319,14 +360,14 @@ class DashClaw {
|
|
|
319
360
|
}
|
|
320
361
|
|
|
321
362
|
if (action.status === 'pending_approval') wasPending = true;
|
|
322
|
-
if (action.approved_by) return
|
|
363
|
+
if (action.approved_by) return result;
|
|
323
364
|
if (action.status === 'failed' || action.status === 'cancelled') {
|
|
324
365
|
throw new ApprovalDeniedError(action.error_message || 'Operator denied the action.', action.status);
|
|
325
366
|
}
|
|
326
367
|
if (wasPending && action.status !== 'pending_approval') {
|
|
327
368
|
throw new Error(`Action ${actionId} left pending_approval state without explicit approval metadata (Status: ${action.status})`);
|
|
328
369
|
}
|
|
329
|
-
if (!wasPending && action.status === 'running') return
|
|
370
|
+
if (!wasPending && action.status === 'running') return result;
|
|
330
371
|
|
|
331
372
|
await new Promise(r => setTimeout(r, interval));
|
|
332
373
|
}
|
|
@@ -611,6 +652,68 @@ class DashClaw {
|
|
|
611
652
|
});
|
|
612
653
|
}
|
|
613
654
|
|
|
655
|
+
/**
|
|
656
|
+
* GET /api/messages — Fetch messages this agent has sent.
|
|
657
|
+
*/
|
|
658
|
+
async getSentMessages({ type, threadId, limit } = {}) {
|
|
659
|
+
return this._request('/api/messages', 'GET', null, {
|
|
660
|
+
agent_id: this.agentId,
|
|
661
|
+
direction: 'sent',
|
|
662
|
+
...(type && { type }),
|
|
663
|
+
...(threadId && { thread_id: threadId }),
|
|
664
|
+
...(limit && { limit }),
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* GET /api/messages — Fetch this agent's messages with flexible filters.
|
|
670
|
+
*/
|
|
671
|
+
async getMessages({ direction, type, unread, threadId, limit } = {}) {
|
|
672
|
+
return this._request('/api/messages', 'GET', null, {
|
|
673
|
+
agent_id: this.agentId,
|
|
674
|
+
...(direction && { direction }),
|
|
675
|
+
...(type && { type }),
|
|
676
|
+
...(unread != null && { unread }),
|
|
677
|
+
...(threadId && { thread_id: threadId }),
|
|
678
|
+
...(limit && { limit }),
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* GET /api/messages/:messageId — Fetch a single message by id.
|
|
684
|
+
*/
|
|
685
|
+
async getMessage(messageId) {
|
|
686
|
+
return this._request(`/api/messages/${encodeURIComponent(messageId)}`, 'GET');
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
/**
|
|
690
|
+
* PATCH /api/messages — Mark messages as read for this agent. Direct messages
|
|
691
|
+
* are marked read only for the target agent (or dashboard); broadcasts update
|
|
692
|
+
* read_by for this agent.
|
|
693
|
+
* @param {string[]} messageIds - Message IDs (msg_*) to mark read.
|
|
694
|
+
* @returns {Promise<{ updated: number }>}
|
|
695
|
+
*/
|
|
696
|
+
async markRead(messageIds) {
|
|
697
|
+
return this._request('/api/messages', 'PATCH', {
|
|
698
|
+
message_ids: messageIds,
|
|
699
|
+
action: 'read',
|
|
700
|
+
agent_id: this.agentId,
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* PATCH /api/messages — Archive messages for this agent.
|
|
706
|
+
* @param {string[]} messageIds - Message IDs (msg_*) to archive.
|
|
707
|
+
* @returns {Promise<{ updated: number }>}
|
|
708
|
+
*/
|
|
709
|
+
async archiveMessages(messageIds) {
|
|
710
|
+
return this._request('/api/messages', 'PATCH', {
|
|
711
|
+
message_ids: messageIds,
|
|
712
|
+
action: 'archive',
|
|
713
|
+
agent_id: this.agentId,
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
|
|
614
717
|
// ---------------------------------------------------------------------------
|
|
615
718
|
// Session Handoffs
|
|
616
719
|
// ---------------------------------------------------------------------------
|
|
@@ -650,25 +753,6 @@ class DashClaw {
|
|
|
650
753
|
});
|
|
651
754
|
}
|
|
652
755
|
|
|
653
|
-
// ---------------------------------------------------------------------------
|
|
654
|
-
// User Feedback
|
|
655
|
-
// ---------------------------------------------------------------------------
|
|
656
|
-
|
|
657
|
-
/**
|
|
658
|
-
* POST /api/feedback — Submit user feedback linked to an action.
|
|
659
|
-
*/
|
|
660
|
-
async submitFeedback({ action_id, rating, comment, category, tags, metadata }) {
|
|
661
|
-
return this._request('/api/feedback', 'POST', {
|
|
662
|
-
action_id,
|
|
663
|
-
agent_id: this.agentId,
|
|
664
|
-
rating,
|
|
665
|
-
comment,
|
|
666
|
-
category,
|
|
667
|
-
tags,
|
|
668
|
-
metadata,
|
|
669
|
-
});
|
|
670
|
-
}
|
|
671
|
-
|
|
672
756
|
// ---------------------------------------------------------------------------
|
|
673
757
|
// Context Threads
|
|
674
758
|
// ---------------------------------------------------------------------------
|
|
@@ -1041,6 +1125,13 @@ class DashClaw {
|
|
|
1041
1125
|
});
|
|
1042
1126
|
}
|
|
1043
1127
|
|
|
1128
|
+
/**
|
|
1129
|
+
* DELETE /api/knowledge/collections/:id — Delete a collection (cascades items + chunks).
|
|
1130
|
+
*/
|
|
1131
|
+
async deleteKnowledgeCollection(collectionId) {
|
|
1132
|
+
return this._request(`/api/knowledge/collections/${collectionId}`, 'DELETE');
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1044
1135
|
// ---------------------------------------------------------------------------
|
|
1045
1136
|
// Execution Studio — Capability Registry
|
|
1046
1137
|
// ---------------------------------------------------------------------------
|
|
@@ -1114,6 +1205,158 @@ class DashClaw {
|
|
|
1114
1205
|
async getCapabilityHistory(capabilityId, filters = {}) {
|
|
1115
1206
|
return this._request(`/api/capabilities/${capabilityId}/history`, 'GET', null, filters);
|
|
1116
1207
|
}
|
|
1208
|
+
|
|
1209
|
+
// ---------------------------------------------------------------------------
|
|
1210
|
+
// Prompt Library — reusable prompt templates, versions, render + analytics.
|
|
1211
|
+
// renderPrompt() already lives in the rendering section above; these add the
|
|
1212
|
+
// template/version management surface so the library is first-class in the SDK.
|
|
1213
|
+
// Mutations (create/update/delete/version/activate) require an admin org role.
|
|
1214
|
+
// ---------------------------------------------------------------------------
|
|
1215
|
+
|
|
1216
|
+
/**
|
|
1217
|
+
* GET /api/prompts/templates — List prompt templates (each with version_count + active_version).
|
|
1218
|
+
* @param {Object} [filters={}] - { category }
|
|
1219
|
+
*/
|
|
1220
|
+
async listPromptTemplates(filters = {}) {
|
|
1221
|
+
return this._request('/api/prompts/templates', 'GET', null, filters);
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
/**
|
|
1225
|
+
* GET /api/prompts/templates/:id — Fetch a single template.
|
|
1226
|
+
*/
|
|
1227
|
+
async getPromptTemplate(templateId) {
|
|
1228
|
+
return this._request(`/api/prompts/templates/${templateId}`, 'GET');
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
/**
|
|
1232
|
+
* POST /api/prompts/templates — Create a template (admin). { name, description?, category? }
|
|
1233
|
+
*/
|
|
1234
|
+
async createPromptTemplate(data) {
|
|
1235
|
+
return this._request('/api/prompts/templates', 'POST', data);
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
/**
|
|
1239
|
+
* PATCH /api/prompts/templates/:id — Update a template (admin). { name?, description?, category? }
|
|
1240
|
+
*/
|
|
1241
|
+
async updatePromptTemplate(templateId, patch) {
|
|
1242
|
+
return this._request(`/api/prompts/templates/${templateId}`, 'PATCH', patch);
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
/**
|
|
1246
|
+
* DELETE /api/prompts/templates/:id — Delete a template + its versions/runs (admin).
|
|
1247
|
+
*/
|
|
1248
|
+
async deletePromptTemplate(templateId) {
|
|
1249
|
+
return this._request(`/api/prompts/templates/${templateId}`, 'DELETE');
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
/**
|
|
1253
|
+
* GET /api/prompts/templates/:id/versions — List versions (newest first).
|
|
1254
|
+
*/
|
|
1255
|
+
async listPromptVersions(templateId) {
|
|
1256
|
+
return this._request(`/api/prompts/templates/${templateId}/versions`, 'GET');
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
/**
|
|
1260
|
+
* POST /api/prompts/templates/:id/versions — Create a version (admin).
|
|
1261
|
+
* @param {string} templateId
|
|
1262
|
+
* @param {Object} data - { content, model_hint?, parameters?, changelog? }
|
|
1263
|
+
*/
|
|
1264
|
+
async createPromptVersion(templateId, data) {
|
|
1265
|
+
return this._request(`/api/prompts/templates/${templateId}/versions`, 'POST', data);
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
/**
|
|
1269
|
+
* GET /api/prompts/templates/:id/versions/:versionId — Fetch a single version.
|
|
1270
|
+
*/
|
|
1271
|
+
async getPromptVersion(templateId, versionId) {
|
|
1272
|
+
return this._request(`/api/prompts/templates/${templateId}/versions/${versionId}`, 'GET');
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
/**
|
|
1276
|
+
* POST /api/prompts/templates/:id/versions/:versionId — Activate a version (admin).
|
|
1277
|
+
* Activating one version deactivates the others for that template.
|
|
1278
|
+
*/
|
|
1279
|
+
async activatePromptVersion(templateId, versionId) {
|
|
1280
|
+
return this._request(`/api/prompts/templates/${templateId}/versions/${versionId}`, 'POST');
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
/**
|
|
1284
|
+
* GET /api/prompts/stats — Prompt usage analytics.
|
|
1285
|
+
* @param {Object} [filters={}] - { template_id }
|
|
1286
|
+
*/
|
|
1287
|
+
async getPromptStats(filters = {}) {
|
|
1288
|
+
return this._request('/api/prompts/stats', 'GET', null, filters);
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
/**
|
|
1292
|
+
* GET /api/prompts/runs — List recorded prompt runs.
|
|
1293
|
+
* @param {Object} [filters={}] - { template_id, version_id, limit }
|
|
1294
|
+
*/
|
|
1295
|
+
async listPromptRuns(filters = {}) {
|
|
1296
|
+
return this._request('/api/prompts/runs', 'GET', null, filters);
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
// ---------------------------------------------------------------------------
|
|
1300
|
+
// Learning — record decisions/outcomes and read back recommendations so the
|
|
1301
|
+
// governance loop improves over time.
|
|
1302
|
+
// ---------------------------------------------------------------------------
|
|
1303
|
+
|
|
1304
|
+
/**
|
|
1305
|
+
* POST /api/learning — Record a decision/outcome into the learning ledger.
|
|
1306
|
+
* @param {Object} entry - { decision (required), context?, reasoning?, outcome?, confidence?, agent_id? }
|
|
1307
|
+
* @returns {Promise<{ decision: Object }>}
|
|
1308
|
+
*/
|
|
1309
|
+
async recordDecision(entry) {
|
|
1310
|
+
return this._request('/api/learning', 'POST', {
|
|
1311
|
+
...entry,
|
|
1312
|
+
agent_id: entry.agent_id || this.agentId,
|
|
1313
|
+
});
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
/**
|
|
1317
|
+
* GET /api/learning/recommendations — Read learned recommendations for an agent/action_type.
|
|
1318
|
+
* @param {Object} [filters={}] - { agent_id, action_type, include_metrics, lookback_days, limit }
|
|
1319
|
+
*/
|
|
1320
|
+
async getLearningRecommendations(filters = {}) {
|
|
1321
|
+
return this._request('/api/learning/recommendations', 'GET', null, {
|
|
1322
|
+
...filters,
|
|
1323
|
+
agent_id: filters.agent_id || this.agentId,
|
|
1324
|
+
});
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
// ---------------------------------------------------------------------------
|
|
1328
|
+
// Policies — dry-run a proposed policy against historical actions before
|
|
1329
|
+
// committing it (no persistence; pairs with guard() for live enforcement).
|
|
1330
|
+
// ---------------------------------------------------------------------------
|
|
1331
|
+
|
|
1332
|
+
/**
|
|
1333
|
+
* POST /api/policies/simulate — Simulate a single proposed policy against
|
|
1334
|
+
* recent historical actions. Side-effect-free.
|
|
1335
|
+
* @param {Object} args - { policy_type (required), rules (Object, required), days? }
|
|
1336
|
+
* @returns {Promise<{ summary: { total, matches, block, warn, require_approval, allow }, matches: Array, sample_size, window_days }>}
|
|
1337
|
+
*/
|
|
1338
|
+
async simulatePolicy({ policy_type, rules, days } = {}) {
|
|
1339
|
+
return this._request('/api/policies/simulate', 'POST', {
|
|
1340
|
+
policy_type,
|
|
1341
|
+
rules,
|
|
1342
|
+
...(days !== undefined ? { days } : {}),
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
// ---------------------------------------------------------------------------
|
|
1347
|
+
// Evaluations — preview a scorer (dry-run, no eval_scores written).
|
|
1348
|
+
// ---------------------------------------------------------------------------
|
|
1349
|
+
|
|
1350
|
+
/**
|
|
1351
|
+
* POST /api/evaluations/scorers/preview — Dry-run a scorer config against a
|
|
1352
|
+
* sample action without persisting a score. Use to validate a quality gate
|
|
1353
|
+
* (e.g. branch-finish scoring) before creating a scorer or launching a run.
|
|
1354
|
+
* @param {Object} args - { scorer_type (required), config?, sample? }
|
|
1355
|
+
* @returns {Promise<{ preview: true, scorer_type, result: { score, label, reasoning, error } }>}
|
|
1356
|
+
*/
|
|
1357
|
+
async previewScorer({ scorer_type, config, sample } = {}) {
|
|
1358
|
+
return this._request('/api/evaluations/scorers/preview', 'POST', { scorer_type, config, sample });
|
|
1359
|
+
}
|
|
1117
1360
|
}
|
|
1118
1361
|
|
|
1119
1362
|
export { DashClaw, ApprovalDeniedError, GuardBlockedError };
|