dashclaw 4.1.0 → 4.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.
Files changed (3) hide show
  1. package/README.md +56 -0
  2. package/dashclaw.js +65 -0
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -56,6 +56,7 @@ const { action, action_id } = await claw.createAction({
56
56
  action_type: 'deploy',
57
57
  declared_goal: 'Ship v2.4.0 to production',
58
58
  risk_score: 90,
59
+ // session_id: 'sess_…' // optional: link to a started session for exact attribution (else server correlates by agent + time window)
59
60
  });
60
61
 
61
62
  // 3. If the server flagged this for human review, wait for an operator.
@@ -1074,6 +1075,61 @@ x402 and auth metadata are recorded on the provider (`auth_metadata`); no paymen
1074
1075
 
1075
1076
  ---
1076
1077
 
1078
+ ## x402 Spend Governance
1079
+
1080
+ Register x402 providers, govern individual purchases through the guard loop, and record spend for audit. The agent executes the actual x402 call itself — DashClaw records the provider, governs the purchase intent, and keeps a tamper-evident ledger of agent spend. DashClaw never holds a wallet.
1081
+
1082
+ ```js
1083
+ // Register a paid provider
1084
+ const { provider } = await claw.createProvider({
1085
+ name: 'Exa Search',
1086
+ category: 'research',
1087
+ base_url: 'https://api.exa.ai',
1088
+ });
1089
+
1090
+ // Add an endpoint to the provider
1091
+ await claw.createProviderEndpoint(provider.provider_id, {
1092
+ name: 'Search',
1093
+ endpoint_url: 'https://api.exa.ai/search',
1094
+ default_price: 0.01,
1095
+ sensitivity_level: 'low',
1096
+ });
1097
+
1098
+ // Govern + record a purchase (call guard, then agent executes x402)
1099
+ const { action, purchase, decision } = await claw.recordPurchase({
1100
+ agent_id: 'research-agent',
1101
+ provider: provider.provider_id,
1102
+ declared_goal: 'Find recent papers on quantum computing',
1103
+ purchase_reason: 'Context gap: no local data for period 2025-01-01..2026-01-01',
1104
+ context_gap: 'No papers in knowledge base for the requested window',
1105
+ expected_value: 'Retrieve 10+ relevant citations',
1106
+ });
1107
+
1108
+ if (action.status === 'pending_approval') {
1109
+ await claw.waitForApproval(action.id);
1110
+ }
1111
+
1112
+ // Agent executes the x402 call, then records the result
1113
+ const x402Result = { summary: 'Found 14 papers', data: { count: 14 }, url: 'https://...' };
1114
+ await claw.recordPurchaseResult(action.id, x402Result);
1115
+ ```
1116
+
1117
+ - `claw.listProviders(filters?)` -- GET /api/x402/providers
1118
+ - `claw.createProvider(data)` -- POST /api/x402/providers
1119
+ - `claw.getProvider(id)` -- GET /api/x402/providers/:id
1120
+ - `claw.updateProvider(id, patch)` -- PATCH /api/x402/providers/:id
1121
+ - `claw.listProviderEndpoints(id)` -- GET /api/x402/providers/:id/endpoints
1122
+ - `claw.createProviderEndpoint(id, data)` -- POST /api/x402/providers/:id/endpoints
1123
+ - `claw.recordPurchase(data)` -- POST /api/x402/purchases (guard-gated; returns `{ action, purchase, decision }`)
1124
+ - `claw.listPurchases(filters?)` -- GET /api/x402/purchases
1125
+ - `claw.recordPurchaseResult(actionId, result)` -- POST /api/artifacts (attaches the x402 result snapshot to the purchase action via `source_action_id`)
1126
+
1127
+ > **Note:** `recordPurchaseResult` is Node-only. It is a convenience wrapper over `POST /api/artifacts` — Python callers post directly to that endpoint with `artifact_type: 'x402_purchase_result'` and `source_action_id` set to the `act_` id from `record_purchase`.
1128
+
1129
+ > **Operator surface (no SDK wrapper):** The platform also exposes `GET /api/finops/spend?lens=fleet|claude-code` — a read-only operator rollup that aggregates agent LLM cost + x402 purchases (Fleet lens) or Code Sessions cost (Claude-Code lens). It is a presentation layer backed by repository functions (`getFleetSpend` / `getClaudeCodeSpend`), **not** an SDK method, so it does not appear in the method count. Query it directly over HTTP.
1130
+
1131
+ ---
1132
+
1077
1133
  ## Hosted provisioning (operator surface — not an SDK method)
1078
1134
 
1079
1135
  When `DASHCLAW_HOSTED=true` the deployment exposes `/api/hosted/*` routes for one-click trial provisioning. These are operator-facing routes, not SDK methods — they produce the API key the SDK consumes.
package/dashclaw.js CHANGED
@@ -164,7 +164,12 @@ class DashClaw {
164
164
  * to have a `non_fabrication` guard policy verify the content before the
165
165
  * action proceeds. A violation blocks the action or routes it to approval and
166
166
  * is recorded with a signed receipt in the decision ledger.
167
+ *
168
+ * Optional `session_id`: pass the id from `createSession()` to link this
169
+ * action to a session via the Direct path (exact attribution). When omitted,
170
+ * the server falls back to time-window correlation by agent_id.
167
171
  * @param {Object} action
172
+ * @param {string} [action.session_id] Session to attribute this action to.
168
173
  */
169
174
  async createAction(action) {
170
175
  return this._request('/api/actions', 'POST', {
@@ -1415,6 +1420,66 @@ class DashClaw {
1415
1420
  async invokeRegisteredAgent({ registered_agent_id, capability_id, agent_id, payload, declared_goal } = {}) {
1416
1421
  return this._request('/api/agents/invoke', 'POST', { registered_agent_id, capability_id, agent_id, payload, declared_goal });
1417
1422
  }
1423
+
1424
+ // ---------------------------------------------------------------------------
1425
+ // x402 spend governance — provider registry + governed paid acquisition.
1426
+ // The agent executes the actual x402 call itself; these methods register
1427
+ // providers and record/govern the spend. DashClaw never holds a wallet.
1428
+ // ---------------------------------------------------------------------------
1429
+
1430
+ /** GET /api/x402/providers — list registered providers. */
1431
+ async listProviders(filters = {}) {
1432
+ return this._request('/api/x402/providers', 'GET', null, filters);
1433
+ }
1434
+ /** POST /api/x402/providers — register a paid provider. */
1435
+ async createProvider(data = {}) {
1436
+ return this._request('/api/x402/providers', 'POST', data);
1437
+ }
1438
+ /** GET /api/x402/providers/:id — provider detail + endpoints. */
1439
+ async getProvider(id) {
1440
+ return this._request(`/api/x402/providers/${id}`, 'GET');
1441
+ }
1442
+ /** PATCH /api/x402/providers/:id — update a provider. */
1443
+ async updateProvider(id, patch = {}) {
1444
+ return this._request(`/api/x402/providers/${id}`, 'PATCH', patch);
1445
+ }
1446
+ /** GET /api/x402/providers/:id/endpoints — list a provider's endpoints. */
1447
+ async listProviderEndpoints(id) {
1448
+ return this._request(`/api/x402/providers/${id}/endpoints`, 'GET');
1449
+ }
1450
+ /** POST /api/x402/providers/:id/endpoints — add an endpoint. */
1451
+ async createProviderEndpoint(id, data = {}) {
1452
+ return this._request(`/api/x402/providers/${id}/endpoints`, 'POST', data);
1453
+ }
1454
+ /**
1455
+ * POST /api/x402/purchases — govern + record a paid acquisition.
1456
+ * Required: agent_id, provider, declared_goal, purchase_reason, context_gap, expected_value.
1457
+ * Returns { action, purchase, decision }; branch on action.status (running | pending_approval).
1458
+ */
1459
+ async recordPurchase(data = {}) {
1460
+ return this._request('/api/x402/purchases', 'POST', data);
1461
+ }
1462
+ /** GET /api/x402/purchases — list governed purchases. */
1463
+ async listPurchases(filters = {}) {
1464
+ return this._request('/api/x402/purchases', 'GET', null, filters);
1465
+ }
1466
+ /**
1467
+ * POST /api/artifacts — attach the x402 result snapshot to its purchase action.
1468
+ * Reuses the existing artifacts endpoint; links by source_action_id so the
1469
+ * snapshot appears in that action's evidence bundle.
1470
+ * @param {string} actionId - the act_ id returned by recordPurchase
1471
+ * @param {Object} result - { summary?, data?, url? }
1472
+ */
1473
+ async recordPurchaseResult(actionId, result = {}) {
1474
+ return this._request('/api/artifacts', 'POST', {
1475
+ artifact_type: 'x402_purchase_result',
1476
+ name: `x402 result ${actionId}`,
1477
+ description: result.summary || null,
1478
+ content_json: result.data ?? {},
1479
+ content_url: result.url || null,
1480
+ source_action_id: actionId,
1481
+ });
1482
+ }
1418
1483
  }
1419
1484
 
1420
1485
  export { DashClaw, ApprovalDeniedError, GuardBlockedError };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dashclaw",
3
- "version": "4.1.0",
3
+ "version": "4.1.2",
4
4
  "description": "Minimal governance runtime for AI agents. Intercept, govern, and verify agent actions.",
5
5
  "type": "module",
6
6
  "publishConfig": {