@tangle-network/agent-gateway 0.7.1 → 0.8.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.
Files changed (64) hide show
  1. package/README.md +90 -3
  2. package/dist/chunk-C7Z2BRYV.js +5693 -0
  3. package/dist/chunk-C7Z2BRYV.js.map +1 -0
  4. package/dist/chunk-GITV7CPT.js +84 -0
  5. package/dist/chunk-GITV7CPT.js.map +1 -0
  6. package/dist/chunk-J5SDVHOL.js +104 -0
  7. package/dist/chunk-J5SDVHOL.js.map +1 -0
  8. package/dist/index.d.ts +70 -10
  9. package/dist/index.js +303 -21
  10. package/dist/index.js.map +1 -1
  11. package/dist/middleware.d.ts +7 -2
  12. package/dist/middleware.js +3 -2
  13. package/dist/nonce-store.d.ts +47 -11
  14. package/dist/nonce-store.js +9 -3
  15. package/dist/observer-types-A0RtA8uL.d.ts +95 -0
  16. package/dist/observer.d.ts +79 -0
  17. package/dist/observer.js +11 -0
  18. package/dist/observer.js.map +1 -0
  19. package/dist/{types-DEsMmS-X.d.ts → types-oQ58UakD.d.ts} +447 -172
  20. package/dist/types.d.ts +2 -1
  21. package/package.json +1 -1
  22. package/src/a2a/execution-fence.ts +162 -0
  23. package/src/a2a/handler.ts +506 -560
  24. package/src/a2a/message-send-execution.ts +241 -0
  25. package/src/a2a/message-stream-execution.ts +392 -0
  26. package/src/a2a/payment-recovery.ts +431 -0
  27. package/src/a2a/push-config-methods.ts +158 -0
  28. package/src/a2a/push-notifications.ts +172 -22
  29. package/src/a2a/task-cancellation.ts +50 -0
  30. package/src/a2a/task-finalization.ts +451 -0
  31. package/src/a2a/task-lifecycle.ts +54 -0
  32. package/src/a2a/task-methods.ts +163 -0
  33. package/src/a2a/task-push-delivery.ts +119 -0
  34. package/src/a2a/task-recovery.ts +11 -0
  35. package/src/a2a/task-state.ts +99 -0
  36. package/src/a2a/task-store-sql.ts +222 -24
  37. package/src/a2a/task-store.ts +58 -1
  38. package/src/a2a/task-submission-recovery.ts +178 -0
  39. package/src/a2a/types.ts +1 -0
  40. package/src/dispatch-authorization.ts +468 -0
  41. package/src/dispatch-payment-recovery.ts +248 -0
  42. package/src/dispatch-payment.ts +425 -0
  43. package/src/dispatch-pricing.ts +108 -0
  44. package/src/dispatch-sandbox.ts +424 -0
  45. package/src/dispatch-settlement.ts +139 -0
  46. package/src/dispatch-types.ts +84 -0
  47. package/src/dispatch.ts +35 -483
  48. package/src/index.ts +59 -1
  49. package/src/middleware.ts +339 -35
  50. package/src/mpp-payment.ts +117 -0
  51. package/src/nonce-store.ts +122 -20
  52. package/src/observer-types.ts +63 -0
  53. package/src/observer.ts +3 -63
  54. package/src/payment-operations.ts +485 -0
  55. package/src/payment-recovery-sql.ts +108 -0
  56. package/src/payment-recovery-worker.ts +488 -0
  57. package/src/payment-recovery.ts +331 -0
  58. package/src/payment-types.ts +48 -0
  59. package/src/types.ts +188 -49
  60. package/src/verify.ts +240 -71
  61. package/dist/chunk-M7ZJAK4K.js +0 -53
  62. package/dist/chunk-M7ZJAK4K.js.map +0 -1
  63. package/dist/chunk-Q4YAIEZY.js +0 -1763
  64. package/dist/chunk-Q4YAIEZY.js.map +0 -1
package/README.md CHANGED
@@ -14,11 +14,15 @@ npm install @tangle-network/agent-gateway
14
14
  ```ts
15
15
  import {
16
16
  createAgentGateway,
17
+ recoverPayments,
18
+ SqlPaymentRecoveryStore,
17
19
  verifyApiKeyFromStore,
18
20
  } from '@tangle-network/agent-gateway'
19
21
  import { Hono } from 'hono'
20
22
 
21
23
  const app = new Hono()
24
+ const paymentRecoveryStore = new SqlPaymentRecoveryStore(sqlAdapter)
25
+ await paymentRecoveryStore.migrate()
22
26
  app.route('/v1/agents', createAgentGateway({
23
27
  resolveAgent: loadPublishedAgent,
24
28
  getSandbox: openAgentSandbox,
@@ -26,26 +30,109 @@ app.route('/v1/agents', createAgentGateway({
26
30
  x402: {
27
31
  operatorAddress: '0x…',
28
32
  chainId: 3799,
33
+ currencyDecimals: 6,
29
34
  verifySigner: verifySpendAuthSignature,
35
+ paymentProtocolVersion: 2,
36
+ paymentOperations,
37
+ authorizePayment: reserveSpendAuthorization,
30
38
  },
39
+ paymentRecovery: { store: paymentRecoveryStore },
40
+ defaultOutputTokens: 1024,
41
+ maxOutputTokens: 4096,
31
42
  verifyApiKey: (authHeader) => verifyApiKeyFromStore(authHeader, apiKeyStore),
32
43
  }))
33
44
  ```
34
45
 
35
- `x402.verifySigner` is required for production.
46
+ Production requires either `x402.verifySigner` or `verifyApiKey`.
47
+ API-key-only apps can omit `x402` entirely.
36
48
  Set `x402.demoMode: true` only for local development and tests; that explicit mode also enables the built-in `sk_agent_*` demo key verifier.
49
+ Keep `verifySigner` free of side effects.
50
+ Use version 2's `authorizePayment` to reserve or claim funds after rate limits, content checks, and product authorization succeed.
51
+ For production version 2, set `x402.paymentProtocolVersion: 2`, provide `paymentOperations`, and return its operation from `authorizePayment`.
52
+ Production version 2 also requires a durable `paymentRecovery.store`.
53
+ Production version 1 is read-only and must not configure `authorizePayment`.
54
+ Production x402 version 1 also rejects the legacy `settlePayment` callback before it consumes a nonce.
55
+ Use version 2 whenever authorization can reserve, charge, or otherwise mutate external funds.
56
+ Run `recoverPayments(config)` from a private scheduled worker.
57
+ Every live request and worker uses a unique durable fence token.
58
+ A stale request or worker cannot update a row after another worker takes its lease.
59
+ Provider settlement, recovery, and release methods must still use the operation ID idempotently.
60
+ `paymentOperations.getPaymentOperation` must read the authoritative provider state by operation ID without changing it.
61
+ This read is required for recovery of older A2A finalization records that predate the shared payment outbox.
62
+ The operation store owns claim, execution start, receipt retention, partial settle, release, and expiry reclaim.
63
+ An executing or retained operation cannot expire into a refund.
64
+ A retained operation settles from its receipt when one exists.
65
+ If the receipt does not arrive before `receiptTimeoutMs`, recovery settles the original quoted ceiling.
66
+ The fallback never settles the payer's larger authorization amount.
67
+ Keep version 1 explicitly configured while old and new gateways coexist; shared nonce storage must reject a version 1 claim owned by a version 2 operation.
68
+ Before it calls the verifier, the gateway requires the signed amount to cover the complete filtered conversation plus the requested output limit.
69
+ The default bound includes system text, message roles, and JSON framing.
70
+ Set `inputTokenBound` when the provider adds harness, tool, workspace, or other hidden context.
71
+ The gateway rejects `max_tokens` above `maxOutputTokens` and stops the sandbox stream at the accepted limit.
72
+ An unpaid request receives `required_amount`, `currency_decimals`, and `max_output_tokens` in the 402 response.
73
+ Sandbox adapters should emit a complete `sandbox.usage` receipt.
74
+ Requests with a version 2 operation or generic MPP charge reject missing receipts.
75
+ API-key requests keep the legacy visible-token estimate path.
76
+ recordUsage must atomically upsert by event.requestId; recovery may retry an event after its acknowledgement is lost.
77
+ The default gateway still exposes A2A with an in-memory task store.
78
+ Older custom A2A task stores remain source-compatible at the type boundary.
79
+ The OpenAI surface stays available when such a store is configured, while A2A returns `503` until its owner supplies atomic methods.
80
+ Use an atomic task store for multi-worker production deployments.
37
81
 
38
82
  MPP is method-specific.
39
- Configure `mpp.verifySigner` for production MPP credentials; it receives the decoded JSON payload when available plus the original decoded credential, and returns the authenticated consumer ID or `null`.
83
+ Configure `mpp.authenticateCredential` for production MPP credentials.
84
+ This callback receives the decoded payload and live credential.
85
+ It returns `{ consumerId, paymentIdentity }` or `null`.
86
+ `paymentIdentity` must be a stable, non-secret processor identity.
87
+ Equivalent encodings of one credential must return the same payment identity.
88
+ It must not reserve, confirm, or consume payment.
40
89
  The default `blueprintevm` method may reuse `x402.verifySigner` when its credential has the compatible x402 payload shape.
41
- Other methods are not accepted until they have their own verifier.
90
+ Every other method requires an `mpp.charge` lifecycle.
91
+ The lifecycle confirms payment after all request denials.
92
+ The gateway then acquires its execution fence before it returns a response or starts sandbox work.
93
+ `confirmPayment` must bind the provider operation to the supplied `operationId` before confirmation.
94
+ It must return only after it verifies final payment success.
95
+ `recoverPayment` must inspect that operation ID and must never create another charge.
96
+ An authoritative `not-found` result must fence the operation ID against a later charge.
97
+ `releasePayment` must perform an idempotent refund or release.
98
+ The live credential is passed to `confirmPayment` only on the original request.
99
+ The nonce and recovery stores persist only the SHA-256 digest of `paymentIdentity`.
100
+ `Payment-Receipt` values must contain visible ASCII only.
101
+
102
+ `NonceStore` remains source-compatible with 0.7.1 `hasSeen`/`markSeen` stores.
103
+ Payment requests now require its atomic `claim` method, including version 1.
104
+ This is a deliberate safety boundary: a check followed by a write can accept two concurrent payments.
105
+ `KvNonceStore` with plain Cloudflare KV is not atomic and is rejected by `createAgentGateway`.
106
+ Provide `KvNonceStore` an `atomicClaim` callback backed by D1, a Durable Object, or another linearizable store.
107
+ Payment paths fail closed unless the store also provides one atomic `claim` method.
108
+ The 0.7.1 `mpp.verifySigner` callback is also supported; the gateway derives a stable identity until the integration moves to `authenticateCredential`.
42
109
 
43
110
  The same authentication, authorization, rate-limit, filtering, sandbox, settlement, and usage-recording pipeline is used by the OpenAI-compatible and A2A endpoints.
44
111
  Wire protocol handlers only translate their request and response shapes.
45
112
 
113
+ Set `conversationMode: 'thread'` when API calls must use the app's visible conversations.
114
+ The gateway accepts an optional `X-Tangle-Thread-Id` and returns the resolved ID in the same response header.
115
+ Its authenticated `getSandbox` context contains that thread ID, the API-key identity, and the filtered messages.
116
+ An `agent-app` host can use this context to drive its normal persisted chat route instead of opening a second sandbox session.
117
+
46
118
  ## A2A protocol
47
119
 
48
120
  The gateway speaks Google's A2A protocol alongside its OpenAI-compatible surface: discovery via `.well-known/agent.json`, JSON-RPC 2.0 dispatch for `message/send`, `message/stream`, `tasks/get`, `tasks/cancel`, `tasks/resubscribe`, and the four `tasks/pushNotificationConfig/*` methods. Long-horizon agents — durable tasks across worker restarts, webhook delivery on terminal state, `input-required` pauses with multi-turn continuation — are documented in [`docs/a2a-long-horizon.md`](./docs/a2a-long-horizon.md).
121
+ Production A2A task control requires `a2a.authorizeTaskAccess`; explicit demo mode is the local-test exception.
122
+ Custom production task stores must implement atomic `createIfAbsent`, `compareAndSet`, and `compareAndSetExecution` methods.
123
+ `compareAndSetExecution` must reject a renewal when the stored owner lease has expired.
124
+ Task stores must retain payment recovery metadata until reconciliation clears it.
125
+ The short-lived `gatewaySubmission` marker is not a payment recovery record and may expire with its task.
126
+ The bundled memory and SQL stores enforce this rule even after the normal task TTL.
127
+ Push destinations must use HTTPS without URL credentials.
128
+ Push delivery does not follow redirects.
129
+ Production push delivery also requires `a2a.pushUrlValidator` to reject private DNS destinations.
130
+ Production push delivery requires `a2a.webhookSecret` so every webhook has an HMAC signature.
131
+ The exported `deliverPushNotifications` function also requires a non-empty secret.
132
+ Use `deliverDemoPushNotifications` only for explicit local demo mode.
133
+ Tasks created before this release have no recorded origin and fail closed; migrate them with a verified owner binding or let them expire.
134
+ The payment claim keeps its submission lease until the atomic submitted-to-working transition.
135
+ An expired execution lease fails the working task and preserves its payment recovery markers.
49
136
 
50
137
  ## Tier
51
138