dashclaw 1.8.2 → 1.9.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 (4) hide show
  1. package/README.md +154 -9
  2. package/dashclaw.js +108 -20
  3. package/index.cjs +1 -1
  4. package/package.json +2 -2
package/README.md CHANGED
@@ -1,8 +1,10 @@
1
- # DashClaw SDK Reference (Full)
1
+ # DashClaw SDK: Agent Decision Infrastructure
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 95+ methods across 21+ categories including action recording, behavior guard, context management, session handoffs, security scanning, agent messaging, agent pairing, identity binding, organization management, webhooks, policy testing, compliance, task routing, and more.
5
+ DashClaw treats every agent action as a governed decision. The SDK provides decision recording, policy enforcement, assumption tracking, and compliance mapping. It proves what your agents decided and why.
6
+
7
+ Install, configure, and govern your AI agents with 95+ methods across 21+ categories including action recording, behavior guard, context management, session handoffs, security scanning, agent messaging, agent pairing, identity binding, organization management, webhooks, policy testing, compliance, task routing, and more.
6
8
 
7
9
  ---
8
10
 
@@ -111,11 +113,93 @@ try {
111
113
  }
112
114
  ```
113
115
 
116
+ ### Compliance & Governance Patterns
117
+
118
+ DashClaw's guard + action recording pipeline maps directly to compliance controls.
119
+
120
+ **SOC 2 CC6.1: Logical Access Controls**
121
+ ```javascript
122
+ // Before any high-risk operation, enforce policy
123
+ const guardResult = await claw.guard({
124
+ action_type: 'database_write',
125
+ risk_score: 85,
126
+ systems_touched: ['production_db'],
127
+ reversible: false,
128
+ declared_goal: 'Drop legacy user table'
129
+ });
130
+
131
+ if (guardResult.decision === 'block') {
132
+ // SOC 2 control satisfied: unauthorized action prevented
133
+ console.log('Policy blocked:', guardResult.reasons);
134
+ return;
135
+ }
136
+
137
+ // Decision is governed. Record with full lineage
138
+ const { action_id } = await claw.createAction({
139
+ action_type: 'database_write',
140
+ declared_goal: 'Drop legacy user table',
141
+ risk_score: 85,
142
+ reversible: false,
143
+ authorization_scope: 'admin-approved'
144
+ });
145
+
146
+ // Register the assumption this decision relies on
147
+ await claw.registerAssumption({
148
+ action_id,
149
+ assumption: 'Legacy table has zero active references',
150
+ basis: 'Schema dependency scan completed 2h ago'
151
+ });
152
+ ```
153
+
154
+ **EU AI Act Article 14: Human Oversight**
155
+ ```javascript
156
+ // require_approval forces human-in-the-loop
157
+ const result = await claw.guard({
158
+ action_type: 'customer_communication',
159
+ risk_score: 60,
160
+ declared_goal: 'Send pricing update to 500 customers'
161
+ });
162
+
163
+ if (result.decision === 'require_approval') {
164
+ // Create action in pending state, wait for human approval
165
+ const { action_id } = await claw.createAction({
166
+ action_type: 'customer_communication',
167
+ declared_goal: 'Send pricing update to 500 customers',
168
+ status: 'pending'
169
+ });
170
+ // Approval queue at /approvals shows this to operators
171
+ }
172
+ ```
173
+
174
+ **ISO 42001: AI Decision Accountability**
175
+ ```javascript
176
+ // Full decision lineage: guard → action → assumptions → outcome
177
+ const { action_id } = await claw.createAction({
178
+ action_type: 'data_processing',
179
+ declared_goal: 'Rebuild customer segmentation model',
180
+ risk_score: 45,
181
+ systems_touched: ['ml-pipeline', 'customer-db']
182
+ });
183
+
184
+ await claw.registerAssumption({
185
+ action_id,
186
+ assumption: 'Customer data is current as of today',
187
+ basis: 'CRM sync completed at 09:00 UTC'
188
+ });
189
+
190
+ // Later: validate or invalidate assumptions
191
+ await claw.validateAssumption(assumptionId, true);
192
+
193
+ // Decision integrity signals auto-detect when assumptions drift
194
+ const signals = await claw.getSignals();
195
+ // → Returns 'assumption_drift' if too many invalidated
196
+ ```
197
+
114
198
  ---
115
199
 
116
200
  ## Action Recording
117
201
 
118
- Create, update, and query action records. Every agent action gets a full audit trail.
202
+ Create, update, and query action records. Every agent action is a governed decision with a full audit trail capturing intent, reasoning, and outcome for compliance and review.
119
203
 
120
204
  ### claw.createAction(action)
121
205
  Create a new action record. The agent's agentId, agentName, and swarmId are automatically attached.
@@ -268,7 +352,7 @@ stream.close();
268
352
 
269
353
  ### claw.waitForApproval(actionId, { useEvents: true })
270
354
 
271
- SSE-powered approval waiting resolves instantly when the operator approves/denies instead of polling every 5 seconds.
355
+ SSE-powered approval waiting. Resolves instantly when the operator approves/denies instead of polling every 5 seconds.
272
356
 
273
357
  ```javascript
274
358
  // SSE mode (instant, recommended)
@@ -280,7 +364,7 @@ const { action } = await claw.waitForApproval('act_abc');
280
364
 
281
365
  | Parameter | Type | Default | Description |
282
366
  |-----------|------|---------|-------------|
283
- | actionId | string | | Action ID to watch |
367
+ | actionId | string | Yes | Action ID to watch |
284
368
  | options.timeout | number | 300000 | Max wait time (ms) |
285
369
  | options.interval | number | 5000 | Poll interval (polling mode only) |
286
370
  | options.useEvents | boolean | false | Use SSE instead of polling |
@@ -425,7 +509,7 @@ Get current risk signals across all agents. Returns 7 signal types: autonomy_spi
425
509
 
426
510
  ## Behavior Guard
427
511
 
428
- Check org-level policies before executing risky actions. Returns allow, warn, block, or require_approval based on configured guard policies.
512
+ Guard is the heart of DashClaw. Every action can be checked against policies before execution. Returns allow, warn, block, or require_approval based on configured guard policies.
429
513
 
430
514
  ### claw.guard(context, options?)
431
515
  Evaluate guard policies for a proposed action. Call this before risky operations to get a go/no-go decision. The agent_id is auto-attached from the SDK constructor.
@@ -474,6 +558,46 @@ Report a token usage snapshot for this agent.
474
558
 
475
559
  **Returns:** `Promise<{snapshot: Object}>`
476
560
 
561
+ ### claw.wrapClient(llmClient, options?)
562
+ Wrap an Anthropic or OpenAI client to auto-report token usage after every call. Returns the same client instance for fluent usage. Streaming calls (where response lacks `.usage`) are safely ignored.
563
+
564
+ **Parameters:**
565
+ | Parameter | Type | Required | Description |
566
+ |-----------|------|----------|-------------|
567
+ | llmClient | Object | Yes | An Anthropic or OpenAI SDK client instance |
568
+ | options.provider | string | No | Force `'anthropic'` or `'openai'` if auto-detect fails |
569
+
570
+ **Returns:** The wrapped client (same instance)
571
+
572
+ **Example (Anthropic):**
573
+ ```javascript
574
+ import Anthropic from '@anthropic-ai/sdk';
575
+ import { DashClaw } from 'dashclaw';
576
+
577
+ const claw = new DashClaw({ baseUrl: 'http://localhost:3000', agentId: 'my-agent', apiKey: '...' });
578
+ const anthropic = claw.wrapClient(new Anthropic());
579
+
580
+ const msg = await anthropic.messages.create({
581
+ model: 'claude-sonnet-4-20250514',
582
+ max_tokens: 1024,
583
+ messages: [{ role: 'user', content: 'Hello' }],
584
+ });
585
+ // Token usage auto-reported to DashClaw
586
+ ```
587
+
588
+ **Example (OpenAI):**
589
+ ```javascript
590
+ import OpenAI from 'openai';
591
+
592
+ const openai = claw.wrapClient(new OpenAI());
593
+
594
+ const chat = await openai.chat.completions.create({
595
+ model: 'gpt-4o',
596
+ messages: [{ role: 'user', content: 'Hello' }],
597
+ });
598
+ // Token usage auto-reported to DashClaw
599
+ ```
600
+
477
601
  ### claw.recordDecision(entry)
478
602
  Record a decision for the learning database. Track what your agent decides and why.
479
603
 
@@ -1009,6 +1133,27 @@ Scan text and store finding metadata for audit trails. The original content is n
1009
1133
 
1010
1134
  **Returns:** `Promise<{clean: boolean, findings_count: number, findings: Object[], redacted_text: string}>`
1011
1135
 
1136
+ ### claw.scanPromptInjection(text, options?)
1137
+ Scan text for prompt injection attacks — role overrides, delimiter injection, instruction smuggling, data exfiltration attempts, and encoding evasion. Returns risk level and actionable recommendation.
1138
+
1139
+ **Parameters:**
1140
+ | Parameter | Type | Required | Description |
1141
+ |-----------|------|----------|-------------|
1142
+ | text | string | Yes | Text to scan for injection attacks |
1143
+ | options.source | string | No | Where this text came from (e.g. user_input, tool_output, retrieval) |
1144
+
1145
+ **Returns:** `Promise<{clean: boolean, risk_level: string, recommendation: string, findings_count: number, critical_count: number, categories: string[], findings: Object[]}>`
1146
+
1147
+ **Example:**
1148
+ ```javascript
1149
+ const result = await claw.scanPromptInjection(userMessage, { source: 'user_input' });
1150
+ if (result.recommendation === 'block') {
1151
+ console.error(`Blocked: ${result.findings_count} injection patterns detected`);
1152
+ } else if (result.recommendation === 'warn') {
1153
+ console.warn(`Warning: ${result.categories.join(', ')} detected`);
1154
+ }
1155
+ ```
1156
+
1012
1157
  ---
1013
1158
 
1014
1159
  ## Agent Messaging
@@ -1128,7 +1273,7 @@ Get a URL to download an attachment.
1128
1273
  |---|---|---|
1129
1274
  | `attachmentId` | `string` | Attachment ID (`att_*`) |
1130
1275
 
1131
- **Returns:** `string` URL to fetch the attachment binary
1276
+ **Returns:** `string`: URL to fetch the attachment binary
1132
1277
 
1133
1278
  ---
1134
1279
 
@@ -1379,7 +1524,7 @@ Run guardrails tests against all active policies. Returns pass/fail results per
1379
1524
  const report = await claw.testPolicies();
1380
1525
  console.log(`${report.passed}/${report.total} policies passed`);
1381
1526
  for (const r of report.results.filter(r => !r.passed)) {
1382
- console.log(`FAIL: ${r.policy} ${r.reason}`);
1527
+ console.log(`FAIL: ${r.policy}: ${r.reason}`);
1383
1528
  }
1384
1529
  ```
1385
1530
 
@@ -1425,7 +1570,7 @@ Map active policies to framework controls. Returns a control-by-control coverage
1425
1570
  const { controls, coverage_pct } = await claw.mapCompliance('soc2');
1426
1571
  console.log(`SOC 2 coverage: ${coverage_pct}%`);
1427
1572
  for (const ctrl of controls.filter(c => !c.covered)) {
1428
- console.log(`Gap: ${ctrl.id} ${ctrl.name}`);
1573
+ console.log(`Gap: ${ctrl.id}: ${ctrl.name}`);
1429
1574
  }
1430
1575
  ```
1431
1576
 
package/dashclaw.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * DashClaw SDK
3
3
  * Full-featured agent toolkit for the DashClaw platform.
4
- * Zero-dependency ESM SDK requires Node 18+ (native fetch).
4
+ * Zero-dependency ESM SDK. Requires Node 18+ (native fetch).
5
5
  *
6
6
  * 96+ methods across 22+ categories:
7
7
  * - Action Recording (7)
@@ -13,7 +13,7 @@
13
13
  * - Automation Snippets (5)
14
14
  * - User Preferences (6)
15
15
  * - Daily Digest (1)
16
- * - Security Scanning (2)
16
+ * - Security Scanning (3)
17
17
  * - Agent Messaging (9)
18
18
  * - Behavior Guard (2)
19
19
  * - Agent Pairing (3)
@@ -217,7 +217,7 @@ class DashClaw {
217
217
  try {
218
218
  decision = await this.guard(context);
219
219
  } catch (err) {
220
- // Guard API failure is fail-open log and proceed
220
+ // Guard API failure is fail-open: log and proceed
221
221
  console.warn(`[DashClaw] Guard check failed (proceeding): ${err.message}`);
222
222
  return;
223
223
  }
@@ -403,11 +403,11 @@ class DashClaw {
403
403
  }
404
404
 
405
405
  // ══════════════════════════════════════════════
406
- // Category 1: Action Recording (6 methods)
406
+ // Category 1: Decision Recording (6 methods)
407
407
  // ══════════════════════════════════════════════
408
408
 
409
409
  /**
410
- * Create a new action record.
410
+ * Record a governed decision. Every action is a decision with a full audit trail: goal, reasoning, assumptions, and policy compliance.
411
411
  * @param {Object} action
412
412
  * @param {string} action.action_type - One of: build, deploy, post, apply, security, message, api, calendar, research, review, fix, refactor, test, config, monitor, alert, cleanup, sync, migrate, other
413
413
  * @param {string} action.declared_goal - What this action aims to accomplish
@@ -619,9 +619,9 @@ class DashClaw {
619
619
  } else if (line.startsWith('data: ')) {
620
620
  currentData += line.slice(6);
621
621
  } else if (line.startsWith(':')) {
622
- // SSE comment (keepalive heartbeat) — ignore
622
+ // SSE comment (keepalive heartbeat). Ignore.
623
623
  } else if (line === '' && currentEvent) {
624
- // End of SSE frame — dispatch
624
+ // End of SSE frame. Dispatch.
625
625
  if (currentData) {
626
626
  try {
627
627
  const parsed = JSON.parse(currentData);
@@ -631,7 +631,7 @@ class DashClaw {
631
631
  currentEvent = null;
632
632
  currentData = '';
633
633
  } else if (line === '') {
634
- // Blank line without a pending event reset partial state
634
+ // Blank line without a pending event. Reset partial state.
635
635
  currentEvent = null;
636
636
  currentData = '';
637
637
  }
@@ -766,11 +766,11 @@ class DashClaw {
766
766
  }
767
767
 
768
768
  // ══════════════════════════════════════════════
769
- // Category 2: Loops & Assumptions (7 methods)
769
+ // Category 2: Decision Integrity (Loops & Assumptions) (7 methods)
770
770
  // ══════════════════════════════════════════════
771
771
 
772
772
  /**
773
- * Register an open loop for an action.
773
+ * Register an unresolved dependency for a decision. Open loops track work that must be completed before the decision can be considered fully resolved.
774
774
  * @param {Object} loop
775
775
  * @param {string} loop.action_id - Parent action ID
776
776
  * @param {string} loop.loop_type - One of: followup, question, dependency, approval, review, handoff, other
@@ -817,7 +817,7 @@ class DashClaw {
817
817
  }
818
818
 
819
819
  /**
820
- * Register assumptions made during an action.
820
+ * Register assumptions underlying a decision. Assumptions are the decision basis. They must be validated or invalidated to maintain decision integrity.
821
821
  * @param {Object} assumption
822
822
  * @param {string} assumption.action_id - Parent action ID
823
823
  * @param {string} assumption.assumption - The assumption being made
@@ -873,11 +873,11 @@ class DashClaw {
873
873
  }
874
874
 
875
875
  // ══════════════════════════════════════════════
876
- // Category 3: Signals (1 method)
876
+ // Category 3: Decision Integrity Signals (1 method)
877
877
  // ══════════════════════════════════════════════
878
878
 
879
879
  /**
880
- * Get current risk signals.
880
+ * Get current decision integrity signals. Returns autonomy breaches, logic drift, and governance violations.
881
881
  * @returns {Promise<{signals: Object[], counts: {red: number, amber: number, total: number}}>}
882
882
  */
883
883
  async getSignals() {
@@ -885,7 +885,7 @@ class DashClaw {
885
885
  }
886
886
 
887
887
  // ══════════════════════════════════════════════
888
- // Category 4: Dashboard Data (8 methods)
888
+ // Category 4: Dashboard Data (9 methods)
889
889
  // ══════════════════════════════════════════════
890
890
 
891
891
  /**
@@ -905,6 +905,79 @@ class DashClaw {
905
905
  });
906
906
  }
907
907
 
908
+ /**
909
+ * Internal: fire-and-forget token report extracted from an LLM response.
910
+ * @private
911
+ */
912
+ async _reportTokenUsageFromLLM({ tokens_in, tokens_out, model }) {
913
+ if (tokens_in == null && tokens_out == null) return;
914
+ try {
915
+ await this._request('/api/tokens', 'POST', {
916
+ tokens_in: tokens_in || 0,
917
+ tokens_out: tokens_out || 0,
918
+ model: model || undefined,
919
+ agent_id: this.agentId,
920
+ });
921
+ } catch (_) {
922
+ // fire-and-forget: never let telemetry break the caller
923
+ }
924
+ }
925
+
926
+ /**
927
+ * Wrap an Anthropic or OpenAI client to auto-report token usage after each call.
928
+ * Returns the same client instance (mutated) for fluent usage.
929
+ *
930
+ * @param {Object} llmClient - An Anthropic or OpenAI SDK client instance
931
+ * @param {Object} [options]
932
+ * @param {'anthropic'|'openai'} [options.provider] - Force provider detection
933
+ * @returns {Object} The wrapped client
934
+ *
935
+ * @example
936
+ * const anthropic = claw.wrapClient(new Anthropic());
937
+ * const msg = await anthropic.messages.create({ model: 'claude-sonnet-4-20250514', max_tokens: 1024, messages: [...] });
938
+ * // Token usage is auto-reported to DashClaw
939
+ */
940
+ wrapClient(llmClient, { provider } = {}) {
941
+ if (llmClient._dashclawWrapped) return llmClient;
942
+
943
+ const detected = provider
944
+ || (llmClient.messages?.create ? 'anthropic' : null)
945
+ || (llmClient.chat?.completions?.create ? 'openai' : null);
946
+
947
+ if (!detected) {
948
+ throw new Error(
949
+ 'DashClaw.wrapClient: unable to detect provider. Pass { provider: "anthropic" } or { provider: "openai" }.'
950
+ );
951
+ }
952
+
953
+ if (detected === 'anthropic') {
954
+ const original = llmClient.messages.create.bind(llmClient.messages);
955
+ llmClient.messages.create = async (...args) => {
956
+ const response = await original(...args);
957
+ this._reportTokenUsageFromLLM({
958
+ tokens_in: response?.usage?.input_tokens ?? null,
959
+ tokens_out: response?.usage?.output_tokens ?? null,
960
+ model: response?.model ?? null,
961
+ });
962
+ return response;
963
+ };
964
+ } else if (detected === 'openai') {
965
+ const original = llmClient.chat.completions.create.bind(llmClient.chat.completions);
966
+ llmClient.chat.completions.create = async (...args) => {
967
+ const response = await original(...args);
968
+ this._reportTokenUsageFromLLM({
969
+ tokens_in: response?.usage?.prompt_tokens ?? null,
970
+ tokens_out: response?.usage?.completion_tokens ?? null,
971
+ model: response?.model ?? null,
972
+ });
973
+ return response;
974
+ };
975
+ }
976
+
977
+ llmClient._dashclawWrapped = true;
978
+ return llmClient;
979
+ }
980
+
908
981
  /**
909
982
  * Record a decision for the learning database.
910
983
  * @param {Object} entry
@@ -1497,7 +1570,7 @@ class DashClaw {
1497
1570
  }
1498
1571
 
1499
1572
  // ══════════════════════════════════════════════
1500
- // Category 10: Security Scanning (2 methods)
1573
+ // Category 10: Security Scanning (3 methods)
1501
1574
  // ══════════════════════════════════════════════
1502
1575
 
1503
1576
  /**
@@ -1532,6 +1605,22 @@ class DashClaw {
1532
1605
  });
1533
1606
  }
1534
1607
 
1608
+ /**
1609
+ * Scan text for prompt injection attacks (role overrides, delimiter injection,
1610
+ * instruction smuggling, data exfiltration attempts, etc.).
1611
+ * @param {string} text - Text to scan
1612
+ * @param {Object} [options]
1613
+ * @param {string} [options.source] - Where this text came from (for context)
1614
+ * @returns {Promise<{clean: boolean, risk_level: string, recommendation: string, findings_count: number, critical_count: number, categories: string[], findings: Object[]}>}
1615
+ */
1616
+ async scanPromptInjection(text, options = {}) {
1617
+ return this._request('/api/security/prompt-injection', 'POST', {
1618
+ text,
1619
+ source: options.source,
1620
+ agent_id: this.agentId,
1621
+ });
1622
+ }
1623
+
1535
1624
  // ══════════════════════════════════════════════
1536
1625
  // Category 11: Agent Messaging (11 methods)
1537
1626
  // ══════════════════════════════════════════════
@@ -1669,7 +1758,7 @@ class DashClaw {
1669
1758
 
1670
1759
  /**
1671
1760
  * Create or update a shared workspace document.
1672
- * Upserts by (org_id, name) updates increment the version.
1761
+ * Upserts by (org_id, name). Updates increment the version.
1673
1762
  * @param {Object} params
1674
1763
  * @param {string} params.name - Document name (unique per org)
1675
1764
  * @param {string} params.content - Document content
@@ -1717,12 +1806,11 @@ class DashClaw {
1717
1806
  }
1718
1807
 
1719
1808
  // ══════════════════════════════════════════════
1720
- // Category 13: Behavior Guard (2 methods)
1809
+ // Category 13: Policy Enforcement (Guard) (2 methods)
1721
1810
  // ══════════════════════════════════════════════
1722
1811
 
1723
1812
  /**
1724
- * Check guard policies before executing a risky action.
1725
- * Returns allow/warn/block/require_approval.
1813
+ * Enforce policies before a decision executes. Guard is the heart of DashClaw. It intercepts intent and returns allow/warn/block/require_approval.
1726
1814
  * @param {Object} context
1727
1815
  * @param {string} context.action_type - Action type (required)
1728
1816
  * @param {number} [context.risk_score] - Risk score 0-100
@@ -2133,7 +2221,7 @@ class DashClaw {
2133
2221
 
2134
2222
  /**
2135
2223
  * Sync multiple data categories in a single request.
2136
- * Every key is optional only provided categories are processed.
2224
+ * Every key is optional. Only provided categories are processed.
2137
2225
  * @param {Object} state - Data to sync (connections, memory, goals, learning, content, inspiration, context_points, context_threads, handoffs, preferences, snippets)
2138
2226
  * @returns {Promise<{results: Object, total_synced: number, total_errors: number, duration_ms: number}>}
2139
2227
  */
package/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * DashClaw SDK CommonJS compatibility wrapper.
2
+ * DashClaw SDK: CommonJS compatibility wrapper.
3
3
  * For ESM: import { DashClaw } from 'dashclaw'
4
4
  * For CJS: const { DashClaw } = require('dashclaw')
5
5
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dashclaw",
3
- "version": "1.8.2",
3
+ "version": "1.9.0",
4
4
  "description": "Full-featured agent toolkit for the DashClaw platform. 96+ methods across 22+ categories for action recording, context management, session handoffs, security scanning, behavior guard, compliance, task routing, identity binding, organization management, webhooks, bulk sync, and more.",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -22,7 +22,7 @@
22
22
  ],
23
23
  "keywords": [
24
24
  "ai-agent",
25
- "observability",
25
+ "decision-infrastructure",
26
26
  "agent-toolkit",
27
27
  "dashclaw",
28
28
  "dashclaw",