dashclaw 4.1.1 → 4.2.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 (3) hide show
  1. package/README.md +68 -0
  2. package/dashclaw.js +114 -0
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1075,6 +1075,74 @@ x402 and auth metadata are recorded on the provider (`auth_metadata`); no paymen
1075
1075
 
1076
1076
  ---
1077
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
+ // Or self-report a SETTLED payment in ONE call — when you pay OUTSIDE a
1117
+ // governance hook (e.g. a native-shell agentcash wrapper) and just need the
1118
+ // spend on Spend → x402. The server resolves/auto-registers the provider from
1119
+ // `provider`, so you don't register one first.
1120
+ const settled = await claw.recordX402Purchase({
1121
+ agent_id: 'research-agent',
1122
+ provider: 'stableenrich.dev', // name/origin
1123
+ spend: 0.007, // settled USD
1124
+ transaction_hash: '0xabc…',
1125
+ request_id: 'req_123',
1126
+ });
1127
+ ```
1128
+
1129
+ - `claw.listProviders(filters?)` -- GET /api/x402/providers
1130
+ - `claw.createProvider(data)` -- POST /api/x402/providers
1131
+ - `claw.getProvider(id)` -- GET /api/x402/providers/:id
1132
+ - `claw.updateProvider(id, patch)` -- PATCH /api/x402/providers/:id
1133
+ - `claw.listProviderEndpoints(id)` -- GET /api/x402/providers/:id/endpoints
1134
+ - `claw.createProviderEndpoint(id, data)` -- POST /api/x402/providers/:id/endpoints
1135
+ - `claw.recordPurchase(data)` -- POST /api/x402/purchases (guard-gated; returns `{ action, purchase, decision }`)
1136
+ - `claw.listPurchases(filters?)` -- GET /api/x402/purchases
1137
+ - `claw.recordPurchaseResult(actionId, result)` -- POST /api/artifacts (attaches the x402 result snapshot to the purchase action via `source_action_id`)
1138
+ - `claw.recordX402Purchase({ agent_id, provider, spend, transaction_hash?, request_id?, ... })` -- one call: govern + record the purchase, mark it succeeded, and attach the receipt. Use for the **pay-outside-a-hook** self-report pattern. Python parity: `record_x402_purchase(...)`.
1139
+
1140
+ > **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`. (`recordX402Purchase` / `record_x402_purchase` exist in both SDKs and handle the receipt internally.)
1141
+
1142
+ > **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.
1143
+
1144
+ ---
1145
+
1078
1146
  ## Hosted provisioning (operator surface — not an SDK method)
1079
1147
 
1080
1148
  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
@@ -1420,6 +1420,120 @@ class DashClaw {
1420
1420
  async invokeRegisteredAgent({ registered_agent_id, capability_id, agent_id, payload, declared_goal } = {}) {
1421
1421
  return this._request('/api/agents/invoke', 'POST', { registered_agent_id, capability_id, agent_id, payload, declared_goal });
1422
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
+ }
1483
+ /**
1484
+ * Convenience: record a SETTLED x402 payment end-to-end in one call — govern +
1485
+ * record the purchase, mark it succeeded, and (when given) attach the on-chain
1486
+ * receipt. Use this when your agent pays OUTSIDE an OpenClaw governance hook
1487
+ * (e.g. a Codex/native-shell agentcash wrapper) and must self-report so the
1488
+ * spend lands on Spend → x402. The server resolves/auto-registers the provider
1489
+ * from `provider`, so you do NOT register one first. Only call this for a
1490
+ * settled payment — a free quote or a failed call has nothing to record.
1491
+ *
1492
+ * @param {Object} p
1493
+ * @param {string} p.agent_id
1494
+ * @param {string} p.provider - provider name/origin, e.g. "stableenrich.dev"
1495
+ * @param {number} p.spend - settled USD amount (> 0)
1496
+ * @param {string} [p.declared_goal]
1497
+ * @param {string} [p.purchase_reason]
1498
+ * @param {string} [p.context_gap]
1499
+ * @param {string} [p.expected_value]
1500
+ * @param {string} [p.transaction_hash] - on-chain tx hash (receipt evidence)
1501
+ * @param {string} [p.request_id]
1502
+ * @param {string} [p.currency='USDC']
1503
+ * @param {string} [p.payment_method='x402']
1504
+ * @returns {Promise<{ action, purchase, decision, outcome }>}
1505
+ */
1506
+ async recordX402Purchase({
1507
+ agent_id, provider, spend,
1508
+ declared_goal, purchase_reason, context_gap, expected_value,
1509
+ transaction_hash, request_id, currency = 'USDC', payment_method = 'x402',
1510
+ } = {}) {
1511
+ const origin = provider;
1512
+ const res = await this.recordPurchase({
1513
+ agent_id,
1514
+ provider: origin,
1515
+ declared_goal: declared_goal || `x402 capability call to ${origin}`,
1516
+ purchase_reason: purchase_reason || `Paid x402 capability call to ${origin}`,
1517
+ context_gap: context_gap || `Capability gated behind payment at ${origin}`,
1518
+ expected_value: expected_value || `Paid result from ${origin}`,
1519
+ spend_amount: spend,
1520
+ cost_estimate: spend,
1521
+ currency,
1522
+ payment_method,
1523
+ });
1524
+ const actionId = res?.action?.action_id ?? res?.action?.id;
1525
+ let outcome = null;
1526
+ if (actionId) {
1527
+ outcome = await this.reportActionSuccess(actionId, `x402 settled: $${spend} ${currency} at ${origin}`);
1528
+ if (transaction_hash || request_id) {
1529
+ await this.recordPurchaseResult(actionId, {
1530
+ summary: `x402 settled: $${spend} ${currency} at ${origin}`,
1531
+ data: { origin, transactionHash: transaction_hash, requestId: request_id },
1532
+ });
1533
+ }
1534
+ }
1535
+ return { action: res?.action, purchase: res?.purchase, decision: res?.decision, outcome };
1536
+ }
1423
1537
  }
1424
1538
 
1425
1539
  export { DashClaw, ApprovalDeniedError, GuardBlockedError };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dashclaw",
3
- "version": "4.1.1",
3
+ "version": "4.2.0",
4
4
  "description": "Minimal governance runtime for AI agents. Intercept, govern, and verify agent actions.",
5
5
  "type": "module",
6
6
  "publishConfig": {