@devlab.group/agent-commerce 2.1.0 → 2.2.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.
- package/README.md +35 -5
- package/dist/ap2.js +3 -3
- package/dist/{chunk-LZS5BL3W.js → chunk-2DAJAJI7.js} +23 -5
- package/dist/chunk-2DAJAJI7.js.map +1 -0
- package/dist/{chunk-UHMYRV3J.js → chunk-BNUD4RBN.js} +22 -7
- package/dist/chunk-BNUD4RBN.js.map +1 -0
- package/dist/{chunk-IFGRCXME.js → chunk-REBY2IEP.js} +24 -20
- package/dist/chunk-REBY2IEP.js.map +1 -0
- package/dist/{chunk-SY6GUYSQ.js → chunk-XYHDQ22D.js} +3 -3
- package/dist/{chunk-SY6GUYSQ.js.map → chunk-XYHDQ22D.js.map} +1 -1
- package/dist/cli/ap2-HLBIUSTK.js +678 -0
- package/dist/cli/ap2-HLBIUSTK.js.map +1 -0
- package/dist/cli/chunk-2LN5PO5I.js +1352 -0
- package/dist/cli/chunk-2LN5PO5I.js.map +1 -0
- package/dist/cli/chunk-3EQBCFZY.js +53 -0
- package/dist/cli/chunk-3EQBCFZY.js.map +1 -0
- package/dist/cli/chunk-3M6U7ILB.js +8 -0
- package/dist/cli/chunk-3M6U7ILB.js.map +1 -0
- package/dist/cli/chunk-3MGAJ5FX.js +70 -0
- package/dist/cli/chunk-3MGAJ5FX.js.map +1 -0
- package/dist/cli/chunk-5K4XEAZV.js +113 -0
- package/dist/cli/chunk-5K4XEAZV.js.map +1 -0
- package/dist/cli/chunk-AA3FIEAR.js +27 -0
- package/dist/cli/chunk-AA3FIEAR.js.map +1 -0
- package/dist/cli/chunk-FHCFR2GS.js +17 -0
- package/dist/cli/chunk-FHCFR2GS.js.map +1 -0
- package/dist/cli/chunk-ILUYEQSV.js +1744 -0
- package/dist/cli/chunk-ILUYEQSV.js.map +1 -0
- package/dist/cli/chunk-KTV52MCU.js +338 -0
- package/dist/cli/chunk-KTV52MCU.js.map +1 -0
- package/dist/cli/chunk-OSTCU6ZK.js +44 -0
- package/dist/cli/chunk-OSTCU6ZK.js.map +1 -0
- package/dist/cli/chunk-OZ4LAWBK.js +256 -0
- package/dist/cli/chunk-OZ4LAWBK.js.map +1 -0
- package/dist/cli/chunk-QQ3WY5L3.js +271 -0
- package/dist/cli/chunk-QQ3WY5L3.js.map +1 -0
- package/dist/cli/chunk-QY3K6PEQ.js +8 -0
- package/dist/cli/chunk-QY3K6PEQ.js.map +1 -0
- package/dist/cli/chunk-QZ6TOMX6.js +1413 -0
- package/dist/cli/chunk-QZ6TOMX6.js.map +1 -0
- package/dist/cli/chunk-SNM3OVCY.js +625 -0
- package/dist/cli/chunk-SNM3OVCY.js.map +1 -0
- package/dist/cli/chunk-SPAYKVUP.js +118 -0
- package/dist/cli/chunk-SPAYKVUP.js.map +1 -0
- package/dist/cli/chunk-TPC4EJLT.js +11 -0
- package/dist/cli/chunk-TPC4EJLT.js.map +1 -0
- package/dist/cli/config-VYAJGZXE.js +11 -0
- package/dist/cli/config-VYAJGZXE.js.map +1 -0
- package/dist/cli/index.js +150 -3627
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-HFD7ZNCQ.js +559 -0
- package/dist/cli/mcp-HFD7ZNCQ.js.map +1 -0
- package/dist/cli/near-5AY3HWYF.js +58 -0
- package/dist/cli/near-5AY3HWYF.js.map +1 -0
- package/dist/cli/provider-JV5HCQGR.js +396 -0
- package/dist/cli/provider-JV5HCQGR.js.map +1 -0
- package/dist/cli/run-WV44B62Y.js +7301 -0
- package/dist/cli/run-WV44B62Y.js.map +1 -0
- package/dist/cli/svm-3MMYFPC7.js +33 -0
- package/dist/cli/svm-3MMYFPC7.js.map +1 -0
- package/dist/cli/x402-NADFV5CD.js +96 -0
- package/dist/cli/x402-NADFV5CD.js.map +1 -0
- package/dist/index.d.ts +12 -3
- package/dist/index.js +82 -11
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +6 -16
- package/dist/mcp.js.map +1 -1
- package/dist/mpp.js +3 -3
- package/dist/{networks-olfflCI_.d.ts → networks-DTWRlj-K.d.ts} +2 -2
- package/dist/x402.d.ts +7 -2
- package/dist/x402.js +4 -4
- package/package.json +2 -2
- package/dist/chunk-IFGRCXME.js.map +0 -1
- package/dist/chunk-LZS5BL3W.js.map +0 -1
- package/dist/chunk-UHMYRV3J.js.map +0 -1
|
@@ -0,0 +1,625 @@
|
|
|
1
|
+
import { ACP_CHECKOUT_OPERATIONS, ACP_SPEC_VERSION } from './chunk-2LN5PO5I.js';
|
|
2
|
+
import { openSqliteDatabase } from './chunk-3MGAJ5FX.js';
|
|
3
|
+
import { PACKAGE_VERSION } from './chunk-QY3K6PEQ.js';
|
|
4
|
+
import { NOOP_LOGGER, systemClock, toCommerceError, CommerceError } from './chunk-QQ3WY5L3.js';
|
|
5
|
+
import { randomUUID } from 'crypto';
|
|
6
|
+
import { accessSync, constants } from 'fs';
|
|
7
|
+
|
|
8
|
+
// src/storage/receipts/redact.ts
|
|
9
|
+
var SECRET_KEY_PATTERN = /private[-_ ]?key|secret|password|mnemonic|seed[-_ ]?phrase|api[-_ ]?key|authoriz(e|ation)|^auth$|auth[-_]?header|payment[-_ ]?proof|^proof$|x-payment|signature|signed[-_ ]?message|token|bearer|credential|cookie|session|jwt/i;
|
|
10
|
+
var REDACTED = "[REDACTED]";
|
|
11
|
+
function isSecretKey(key) {
|
|
12
|
+
return SECRET_KEY_PATTERN.test(key);
|
|
13
|
+
}
|
|
14
|
+
function redact(value) {
|
|
15
|
+
return redactValue(value);
|
|
16
|
+
}
|
|
17
|
+
function redactValue(value) {
|
|
18
|
+
if (Array.isArray(value)) {
|
|
19
|
+
return value.map(redactValue);
|
|
20
|
+
}
|
|
21
|
+
if (value !== null && typeof value === "object") {
|
|
22
|
+
const out = {};
|
|
23
|
+
for (const [key, inner] of Object.entries(value)) {
|
|
24
|
+
out[key] = isSecretKey(key) ? REDACTED : redactValue(inner);
|
|
25
|
+
}
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// src/storage/receipts/rows.ts
|
|
32
|
+
function receiptToRow(receipt) {
|
|
33
|
+
return {
|
|
34
|
+
id: receipt.id,
|
|
35
|
+
request_id: receipt.requestId,
|
|
36
|
+
resource_id: receipt.resourceId,
|
|
37
|
+
payment_json: receipt.payment !== void 0 ? JSON.stringify(redact(receipt.payment)) : null,
|
|
38
|
+
delivered_at: receipt.deliveredAt,
|
|
39
|
+
backend_status: receipt.backendStatus,
|
|
40
|
+
duration_ms: receipt.durationMs ?? null,
|
|
41
|
+
protocol: receipt.protocol ?? null,
|
|
42
|
+
metadata_json: receipt.metadata !== void 0 ? JSON.stringify(redact(receipt.metadata)) : null,
|
|
43
|
+
authorization_json: receipt.authorization !== void 0 ? JSON.stringify(redact(receipt.authorization)) : null
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function rowToReceipt(row) {
|
|
47
|
+
const payment = row.payment_json !== null ? JSON.parse(row.payment_json) : void 0;
|
|
48
|
+
const metadata = row.metadata_json !== null ? JSON.parse(row.metadata_json) : void 0;
|
|
49
|
+
const authorization = row.authorization_json !== null ? JSON.parse(row.authorization_json) : void 0;
|
|
50
|
+
return {
|
|
51
|
+
id: row.id,
|
|
52
|
+
requestId: row.request_id,
|
|
53
|
+
resourceId: row.resource_id,
|
|
54
|
+
deliveredAt: row.delivered_at,
|
|
55
|
+
backendStatus: row.backend_status,
|
|
56
|
+
...payment !== void 0 ? { payment } : {},
|
|
57
|
+
...row.duration_ms !== null ? { durationMs: row.duration_ms } : {},
|
|
58
|
+
...row.protocol !== null ? { protocol: row.protocol } : {},
|
|
59
|
+
...metadata !== void 0 ? { metadata } : {},
|
|
60
|
+
...authorization !== void 0 ? { authorization } : {}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function eventToRow(event) {
|
|
64
|
+
return {
|
|
65
|
+
id: event.id,
|
|
66
|
+
type: event.type,
|
|
67
|
+
request_id: event.requestId,
|
|
68
|
+
resource_id: event.resourceId ?? null,
|
|
69
|
+
at: event.at,
|
|
70
|
+
adapter: event.adapter ?? null,
|
|
71
|
+
payment_provider: event.paymentProvider ?? null,
|
|
72
|
+
duration_ms: event.durationMs ?? null,
|
|
73
|
+
status: event.status ?? null,
|
|
74
|
+
data_json: event.data !== void 0 ? JSON.stringify(redact(event.data)) : null
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function rowToEvent(row) {
|
|
78
|
+
const data = row.data_json !== null ? JSON.parse(row.data_json) : void 0;
|
|
79
|
+
return {
|
|
80
|
+
id: row.id,
|
|
81
|
+
type: row.type,
|
|
82
|
+
requestId: row.request_id,
|
|
83
|
+
at: row.at,
|
|
84
|
+
...row.resource_id !== null ? { resourceId: row.resource_id } : {},
|
|
85
|
+
...row.adapter !== null ? { adapter: row.adapter } : {},
|
|
86
|
+
...row.payment_provider !== null ? { paymentProvider: row.payment_provider } : {},
|
|
87
|
+
...row.duration_ms !== null ? { durationMs: row.duration_ms } : {},
|
|
88
|
+
...row.status !== null ? { status: row.status } : {},
|
|
89
|
+
...data !== void 0 ? { data } : {}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function rowToPaymentAttempt(row) {
|
|
93
|
+
return {
|
|
94
|
+
id: row.id,
|
|
95
|
+
requestId: row.request_id,
|
|
96
|
+
resourceId: row.resource_id,
|
|
97
|
+
provider: row.provider,
|
|
98
|
+
replayKey: row.replay_key,
|
|
99
|
+
status: row.status,
|
|
100
|
+
amount: row.amount,
|
|
101
|
+
currency: row.currency,
|
|
102
|
+
...row.payer !== null ? { payer: row.payer } : {},
|
|
103
|
+
...row.payee !== null ? { payee: row.payee } : {},
|
|
104
|
+
...row.external_reference !== null ? { externalReference: row.external_reference } : {},
|
|
105
|
+
...row.rejection_reason !== null ? { rejectionReason: row.rejection_reason } : {},
|
|
106
|
+
createdAt: row.created_at,
|
|
107
|
+
updatedAt: row.updated_at
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// src/storage/receipts/schema.ts
|
|
112
|
+
var MIGRATIONS = [
|
|
113
|
+
{
|
|
114
|
+
version: 1,
|
|
115
|
+
up(db) {
|
|
116
|
+
db.exec(`
|
|
117
|
+
CREATE TABLE IF NOT EXISTS receipts (
|
|
118
|
+
seq INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
119
|
+
id TEXT NOT NULL UNIQUE,
|
|
120
|
+
request_id TEXT NOT NULL,
|
|
121
|
+
resource_id TEXT NOT NULL,
|
|
122
|
+
payment_json TEXT,
|
|
123
|
+
delivered_at TEXT NOT NULL,
|
|
124
|
+
backend_status INTEGER NOT NULL,
|
|
125
|
+
duration_ms INTEGER,
|
|
126
|
+
protocol TEXT,
|
|
127
|
+
metadata_json TEXT
|
|
128
|
+
);
|
|
129
|
+
CREATE INDEX IF NOT EXISTS idx_receipts_request_id ON receipts(request_id);
|
|
130
|
+
CREATE INDEX IF NOT EXISTS idx_receipts_delivered_at ON receipts(delivered_at);
|
|
131
|
+
|
|
132
|
+
CREATE TABLE IF NOT EXISTS events (
|
|
133
|
+
seq INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
134
|
+
id TEXT NOT NULL UNIQUE,
|
|
135
|
+
type TEXT NOT NULL,
|
|
136
|
+
request_id TEXT NOT NULL,
|
|
137
|
+
resource_id TEXT,
|
|
138
|
+
at TEXT NOT NULL,
|
|
139
|
+
adapter TEXT,
|
|
140
|
+
payment_provider TEXT,
|
|
141
|
+
duration_ms INTEGER,
|
|
142
|
+
status TEXT,
|
|
143
|
+
data_json TEXT
|
|
144
|
+
);
|
|
145
|
+
CREATE INDEX IF NOT EXISTS idx_events_request_id ON events(request_id);
|
|
146
|
+
CREATE INDEX IF NOT EXISTS idx_events_at ON events(at);
|
|
147
|
+
|
|
148
|
+
CREATE TABLE IF NOT EXISTS payment_attempts (
|
|
149
|
+
seq INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
150
|
+
id TEXT NOT NULL UNIQUE,
|
|
151
|
+
request_id TEXT NOT NULL,
|
|
152
|
+
resource_id TEXT NOT NULL,
|
|
153
|
+
provider TEXT NOT NULL,
|
|
154
|
+
replay_key TEXT NOT NULL UNIQUE,
|
|
155
|
+
status TEXT NOT NULL,
|
|
156
|
+
amount TEXT NOT NULL,
|
|
157
|
+
currency TEXT NOT NULL,
|
|
158
|
+
payer TEXT,
|
|
159
|
+
payee TEXT,
|
|
160
|
+
external_reference TEXT,
|
|
161
|
+
rejection_reason TEXT,
|
|
162
|
+
created_at TEXT NOT NULL,
|
|
163
|
+
updated_at TEXT NOT NULL
|
|
164
|
+
);
|
|
165
|
+
CREATE INDEX IF NOT EXISTS idx_payment_attempts_request_id ON payment_attempts(request_id);
|
|
166
|
+
CREATE INDEX IF NOT EXISTS idx_payment_attempts_created_at ON payment_attempts(created_at);
|
|
167
|
+
`);
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
version: 2,
|
|
172
|
+
up(db) {
|
|
173
|
+
db.exec(`ALTER TABLE receipts ADD COLUMN authorization_json TEXT;`);
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
version: 3,
|
|
178
|
+
up(db) {
|
|
179
|
+
db.exec(`
|
|
180
|
+
CREATE TABLE IF NOT EXISTS payment_attempt_history (
|
|
181
|
+
seq INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
182
|
+
id TEXT NOT NULL,
|
|
183
|
+
request_id TEXT NOT NULL,
|
|
184
|
+
resource_id TEXT NOT NULL,
|
|
185
|
+
provider TEXT NOT NULL,
|
|
186
|
+
replay_key TEXT NOT NULL,
|
|
187
|
+
status TEXT NOT NULL,
|
|
188
|
+
amount TEXT NOT NULL,
|
|
189
|
+
currency TEXT NOT NULL,
|
|
190
|
+
payer TEXT,
|
|
191
|
+
payee TEXT,
|
|
192
|
+
external_reference TEXT,
|
|
193
|
+
rejection_reason TEXT,
|
|
194
|
+
created_at TEXT NOT NULL,
|
|
195
|
+
updated_at TEXT NOT NULL,
|
|
196
|
+
superseded_at TEXT NOT NULL
|
|
197
|
+
);
|
|
198
|
+
CREATE INDEX IF NOT EXISTS idx_payment_attempt_history_replay_key ON payment_attempt_history(replay_key);
|
|
199
|
+
CREATE INDEX IF NOT EXISTS idx_payment_attempt_history_request_id ON payment_attempt_history(request_id);
|
|
200
|
+
`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
];
|
|
204
|
+
var SCHEMA_VERSION = MIGRATIONS.at(-1)?.version ?? 0;
|
|
205
|
+
function migrate(db) {
|
|
206
|
+
const current = db.pragma("user_version", { simple: true });
|
|
207
|
+
for (const migration of MIGRATIONS) {
|
|
208
|
+
if (migration.version <= current) continue;
|
|
209
|
+
const apply = db.transaction(() => {
|
|
210
|
+
migration.up(db);
|
|
211
|
+
db.pragma(`user_version = ${migration.version}`);
|
|
212
|
+
});
|
|
213
|
+
apply();
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// src/storage/receipts/store.ts
|
|
218
|
+
var DEFAULT_LIST_LIMIT = 50;
|
|
219
|
+
var MAX_LIST_LIMIT = 500;
|
|
220
|
+
function clampListLimit(limit) {
|
|
221
|
+
const base = limit !== void 0 && Number.isFinite(limit) ? limit : DEFAULT_LIST_LIMIT;
|
|
222
|
+
return Math.min(Math.max(Math.trunc(base), 1), MAX_LIST_LIMIT);
|
|
223
|
+
}
|
|
224
|
+
var UNDELIVERED = "backend_status NOT BETWEEN 200 AND 299";
|
|
225
|
+
var defaultIds = {
|
|
226
|
+
next: (prefix) => prefix !== void 0 ? `${prefix}_${randomUUID()}` : randomUUID()
|
|
227
|
+
};
|
|
228
|
+
function isUniqueConstraintOn(err, column) {
|
|
229
|
+
return err instanceof Error && "code" in err && err.code === "SQLITE_CONSTRAINT_UNIQUE" && err.message.includes(column);
|
|
230
|
+
}
|
|
231
|
+
function createSqliteReceiptStore(options) {
|
|
232
|
+
const logger = options.logger ?? NOOP_LOGGER;
|
|
233
|
+
const clock = options.clock ?? systemClock;
|
|
234
|
+
const ids = options.ids ?? defaultIds;
|
|
235
|
+
const path = options.path;
|
|
236
|
+
const isFileBacked = path !== ":memory:";
|
|
237
|
+
const db = openSqliteDatabase({ path, label: "Receipt database", logger });
|
|
238
|
+
migrate(db);
|
|
239
|
+
const insertReceiptStmt = db.prepare(
|
|
240
|
+
`INSERT INTO receipts (id, request_id, resource_id, payment_json, delivered_at, backend_status, duration_ms, protocol, metadata_json, authorization_json)
|
|
241
|
+
VALUES (@id, @request_id, @resource_id, @payment_json, @delivered_at, @backend_status, @duration_ms, @protocol, @metadata_json, @authorization_json)`
|
|
242
|
+
);
|
|
243
|
+
const getReceiptStmt = db.prepare("SELECT * FROM receipts WHERE id = ?");
|
|
244
|
+
const listReceiptsStmt = db.prepare(
|
|
245
|
+
"SELECT * FROM receipts ORDER BY delivered_at DESC, seq DESC LIMIT ?"
|
|
246
|
+
);
|
|
247
|
+
const listReceiptsByRequestStmt = db.prepare(
|
|
248
|
+
"SELECT * FROM receipts WHERE request_id = ? ORDER BY delivered_at DESC, seq DESC LIMIT ?"
|
|
249
|
+
);
|
|
250
|
+
const listUndeliveredReceiptsStmt = db.prepare(
|
|
251
|
+
`SELECT * FROM receipts WHERE ${UNDELIVERED} ORDER BY delivered_at DESC, seq DESC LIMIT ?`
|
|
252
|
+
);
|
|
253
|
+
const listUndeliveredReceiptsByRequestStmt = db.prepare(
|
|
254
|
+
`SELECT * FROM receipts WHERE request_id = ? AND ${UNDELIVERED} ORDER BY delivered_at DESC, seq DESC LIMIT ?`
|
|
255
|
+
);
|
|
256
|
+
const countReceiptsStmt = db.prepare(
|
|
257
|
+
"SELECT COUNT(*) AS count FROM receipts"
|
|
258
|
+
);
|
|
259
|
+
const countUndeliveredReceiptsStmt = db.prepare(
|
|
260
|
+
`SELECT COUNT(*) AS count FROM receipts WHERE ${UNDELIVERED}`
|
|
261
|
+
);
|
|
262
|
+
const insertEventStmt = db.prepare(
|
|
263
|
+
`INSERT INTO events (id, type, request_id, resource_id, at, adapter, payment_provider, duration_ms, status, data_json)
|
|
264
|
+
VALUES (@id, @type, @request_id, @resource_id, @at, @adapter, @payment_provider, @duration_ms, @status, @data_json)`
|
|
265
|
+
);
|
|
266
|
+
const listEventsStmt = db.prepare(
|
|
267
|
+
"SELECT * FROM events ORDER BY at DESC, seq DESC LIMIT ?"
|
|
268
|
+
);
|
|
269
|
+
const listEventsByRequestStmt = db.prepare(
|
|
270
|
+
"SELECT * FROM events WHERE request_id = ? ORDER BY at DESC, seq DESC LIMIT ?"
|
|
271
|
+
);
|
|
272
|
+
const insertPaymentAttemptStmt = db.prepare(
|
|
273
|
+
`INSERT INTO payment_attempts (id, request_id, resource_id, provider, replay_key, status, amount, currency, payer, payee, external_reference, rejection_reason, created_at, updated_at)
|
|
274
|
+
VALUES (@id, @request_id, @resource_id, @provider, @replay_key, @status, @amount, @currency, @payer, @payee, @external_reference, @rejection_reason, @created_at, @updated_at)
|
|
275
|
+
RETURNING *`
|
|
276
|
+
);
|
|
277
|
+
const archiveRejectedAttemptStmt = db.prepare(
|
|
278
|
+
`INSERT INTO payment_attempt_history (id, request_id, resource_id, provider, replay_key, status, amount, currency, payer, payee, external_reference, rejection_reason, created_at, updated_at, superseded_at)
|
|
279
|
+
SELECT id, request_id, resource_id, provider, replay_key, status, amount, currency, payer, payee, external_reference, rejection_reason, created_at, updated_at, @created_at
|
|
280
|
+
FROM payment_attempts
|
|
281
|
+
WHERE replay_key = @replay_key AND provider = @provider AND status = 'rejected'`
|
|
282
|
+
);
|
|
283
|
+
const reclaimPaymentAttemptStmt = db.prepare(
|
|
284
|
+
`UPDATE payment_attempts SET id = @id, request_id = @request_id, resource_id = @resource_id,
|
|
285
|
+
status = 'reserved', amount = @amount, currency = @currency,
|
|
286
|
+
payer = @payer, payee = @payee, external_reference = NULL, rejection_reason = NULL,
|
|
287
|
+
created_at = @created_at, updated_at = @updated_at
|
|
288
|
+
WHERE replay_key = @replay_key AND provider = @provider AND status = 'rejected'
|
|
289
|
+
RETURNING *`
|
|
290
|
+
);
|
|
291
|
+
const updatePaymentAttemptStmt = db.prepare(
|
|
292
|
+
`UPDATE payment_attempts SET status = @status,
|
|
293
|
+
external_reference = COALESCE(@external_reference, external_reference),
|
|
294
|
+
rejection_reason = COALESCE(@rejection_reason, rejection_reason),
|
|
295
|
+
updated_at = @updated_at
|
|
296
|
+
WHERE replay_key = @replay_key`
|
|
297
|
+
);
|
|
298
|
+
const listPaymentAttemptsStmt = db.prepare(
|
|
299
|
+
"SELECT * FROM payment_attempts ORDER BY created_at DESC, seq DESC LIMIT ?"
|
|
300
|
+
);
|
|
301
|
+
const listPaymentAttemptsByRequestStmt = db.prepare(
|
|
302
|
+
"SELECT * FROM payment_attempts WHERE request_id = ? ORDER BY created_at DESC, seq DESC LIMIT ?"
|
|
303
|
+
);
|
|
304
|
+
const paymentAttemptStatusStmt = db.prepare(
|
|
305
|
+
"SELECT status FROM payment_attempts WHERE replay_key = ?"
|
|
306
|
+
);
|
|
307
|
+
const reclaimRejectedAttempt = db.transaction(
|
|
308
|
+
(params) => {
|
|
309
|
+
archiveRejectedAttemptStmt.run(params);
|
|
310
|
+
return reclaimPaymentAttemptStmt.get(params);
|
|
311
|
+
}
|
|
312
|
+
);
|
|
313
|
+
let closed = false;
|
|
314
|
+
const descriptor = {
|
|
315
|
+
name: "sqlite-receipt-store",
|
|
316
|
+
kind: "storage",
|
|
317
|
+
implementationVersion: PACKAGE_VERSION,
|
|
318
|
+
supportedSpec: `sqlite-schema-v${SCHEMA_VERSION}`,
|
|
319
|
+
capabilities: ["receipts", "events", "payment-attempts"],
|
|
320
|
+
status: "stable"
|
|
321
|
+
};
|
|
322
|
+
const store = {
|
|
323
|
+
async init() {
|
|
324
|
+
const version = db.pragma("user_version", { simple: true });
|
|
325
|
+
if (version !== SCHEMA_VERSION) {
|
|
326
|
+
throw new CommerceError(
|
|
327
|
+
"STORAGE_ERROR",
|
|
328
|
+
`Receipt store schema version mismatch (found ${version}, expected ${SCHEMA_VERSION})`
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
async appendEvent(event) {
|
|
333
|
+
try {
|
|
334
|
+
insertEventStmt.run(eventToRow(event));
|
|
335
|
+
} catch (err) {
|
|
336
|
+
logger.warn(
|
|
337
|
+
{
|
|
338
|
+
err: err instanceof Error ? err.message : String(err),
|
|
339
|
+
eventId: event.id,
|
|
340
|
+
requestId: event.requestId
|
|
341
|
+
},
|
|
342
|
+
"receipt-store: failed to persist commerce event"
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
async reservePaymentAttempt(reservation) {
|
|
347
|
+
const now = clock.nowIso();
|
|
348
|
+
const params = {
|
|
349
|
+
id: ids.next("attempt"),
|
|
350
|
+
request_id: reservation.requestId,
|
|
351
|
+
resource_id: reservation.resourceId,
|
|
352
|
+
provider: reservation.provider,
|
|
353
|
+
replay_key: reservation.replayKey,
|
|
354
|
+
amount: reservation.amount,
|
|
355
|
+
currency: reservation.currency,
|
|
356
|
+
payer: reservation.payer ?? null,
|
|
357
|
+
payee: reservation.payee ?? null,
|
|
358
|
+
created_at: now,
|
|
359
|
+
updated_at: now
|
|
360
|
+
};
|
|
361
|
+
let row;
|
|
362
|
+
try {
|
|
363
|
+
row = (reservation.reclaimRejected === true ? reclaimRejectedAttempt.immediate(params) : void 0) ?? // RETURNING on a successful insert always yields the inserted row
|
|
364
|
+
insertPaymentAttemptStmt.get({
|
|
365
|
+
...params,
|
|
366
|
+
status: "reserved",
|
|
367
|
+
external_reference: null,
|
|
368
|
+
rejection_reason: null
|
|
369
|
+
});
|
|
370
|
+
} catch (err) {
|
|
371
|
+
if (isUniqueConstraintOn(err, "payment_attempts.replay_key")) {
|
|
372
|
+
const existing = paymentAttemptStatusStmt.get(reservation.replayKey);
|
|
373
|
+
throw new CommerceError(
|
|
374
|
+
"PAYMENT_REPLAYED",
|
|
375
|
+
`Payment authorization has already been used (replayKey=${reservation.replayKey})`,
|
|
376
|
+
{
|
|
377
|
+
requestId: reservation.requestId,
|
|
378
|
+
resourceId: reservation.resourceId,
|
|
379
|
+
...existing !== void 0 ? { details: { attemptStatus: existing.status } } : {}
|
|
380
|
+
}
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
throw toCommerceError(err, "STORAGE_ERROR", "Failed to reserve payment attempt");
|
|
384
|
+
}
|
|
385
|
+
return rowToPaymentAttempt(row);
|
|
386
|
+
},
|
|
387
|
+
async updatePaymentAttempt(update) {
|
|
388
|
+
try {
|
|
389
|
+
const result = updatePaymentAttemptStmt.run({
|
|
390
|
+
replay_key: update.replayKey,
|
|
391
|
+
status: update.status,
|
|
392
|
+
external_reference: update.externalReference ?? null,
|
|
393
|
+
rejection_reason: update.rejectionReason ?? null,
|
|
394
|
+
updated_at: clock.nowIso()
|
|
395
|
+
});
|
|
396
|
+
if (result.changes === 0) {
|
|
397
|
+
throw new CommerceError(
|
|
398
|
+
"STORAGE_ERROR",
|
|
399
|
+
`No payment attempt found for replayKey=${update.replayKey}`
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
} catch (err) {
|
|
403
|
+
throw toCommerceError(err, "STORAGE_ERROR", "Failed to update payment attempt");
|
|
404
|
+
}
|
|
405
|
+
},
|
|
406
|
+
async saveReceipt(receipt) {
|
|
407
|
+
try {
|
|
408
|
+
insertReceiptStmt.run(receiptToRow(receipt));
|
|
409
|
+
} catch (err) {
|
|
410
|
+
throw toCommerceError(err, "STORAGE_ERROR", "Failed to save receipt");
|
|
411
|
+
}
|
|
412
|
+
},
|
|
413
|
+
async getReceipt(id) {
|
|
414
|
+
const row = getReceiptStmt.get(id);
|
|
415
|
+
return row !== void 0 ? rowToReceipt(row) : void 0;
|
|
416
|
+
},
|
|
417
|
+
async listReceipts(listOptions = {}) {
|
|
418
|
+
const limit = clampListLimit(listOptions.limit);
|
|
419
|
+
const undelivered = listOptions.undelivered === true;
|
|
420
|
+
const rows = listOptions.requestId !== void 0 ? (undelivered ? listUndeliveredReceiptsByRequestStmt : listReceiptsByRequestStmt).all(
|
|
421
|
+
listOptions.requestId,
|
|
422
|
+
limit
|
|
423
|
+
) : (undelivered ? listUndeliveredReceiptsStmt : listReceiptsStmt).all(limit);
|
|
424
|
+
return rows.map(rowToReceipt);
|
|
425
|
+
},
|
|
426
|
+
// Exact total, not bounded by the listReceipts clamp (see ReceiptStore.countReceipts)
|
|
427
|
+
async countReceipts() {
|
|
428
|
+
return countReceiptsStmt.get()?.count ?? 0;
|
|
429
|
+
},
|
|
430
|
+
// Exact count of non-2xx receipts (see ReceiptStore.countUndeliveredReceipts)
|
|
431
|
+
async countUndeliveredReceipts() {
|
|
432
|
+
return countUndeliveredReceiptsStmt.get()?.count ?? 0;
|
|
433
|
+
},
|
|
434
|
+
async listEvents(listOptions = {}) {
|
|
435
|
+
const limit = clampListLimit(listOptions.limit);
|
|
436
|
+
const rows = listOptions.requestId !== void 0 ? listEventsByRequestStmt.all(listOptions.requestId, limit) : listEventsStmt.all(limit);
|
|
437
|
+
return rows.map(rowToEvent);
|
|
438
|
+
},
|
|
439
|
+
async listPaymentAttempts(listOptions = {}) {
|
|
440
|
+
const limit = clampListLimit(listOptions.limit);
|
|
441
|
+
const rows = listOptions.requestId !== void 0 ? listPaymentAttemptsByRequestStmt.all(listOptions.requestId, limit) : listPaymentAttemptsStmt.all(limit);
|
|
442
|
+
return rows.map(rowToPaymentAttempt);
|
|
443
|
+
},
|
|
444
|
+
descriptor,
|
|
445
|
+
async health() {
|
|
446
|
+
const startedAt = clock.monotonicMs();
|
|
447
|
+
if (closed) {
|
|
448
|
+
return { status: "fail", detail: "store-unavailable", checkedAt: clock.nowIso() };
|
|
449
|
+
}
|
|
450
|
+
if (isFileBacked) {
|
|
451
|
+
try {
|
|
452
|
+
accessSync(path, constants.W_OK);
|
|
453
|
+
} catch (err) {
|
|
454
|
+
logger.warn(
|
|
455
|
+
{ err: err instanceof Error ? err.message : String(err) },
|
|
456
|
+
"receipt-store: health check failed (store not writable)"
|
|
457
|
+
);
|
|
458
|
+
return {
|
|
459
|
+
status: "fail",
|
|
460
|
+
detail: "store-unwritable",
|
|
461
|
+
checkedAt: clock.nowIso(),
|
|
462
|
+
durationMs: clock.monotonicMs() - startedAt
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
try {
|
|
467
|
+
const version = db.pragma("user_version", { simple: true });
|
|
468
|
+
if (version !== SCHEMA_VERSION) {
|
|
469
|
+
logger.warn(
|
|
470
|
+
{ found: version, expected: SCHEMA_VERSION },
|
|
471
|
+
"receipt-store: health check failed (schema version mismatch)"
|
|
472
|
+
);
|
|
473
|
+
return {
|
|
474
|
+
status: "fail",
|
|
475
|
+
detail: "store-schema-mismatch",
|
|
476
|
+
checkedAt: clock.nowIso(),
|
|
477
|
+
durationMs: clock.monotonicMs() - startedAt
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
return {
|
|
481
|
+
status: "pass",
|
|
482
|
+
detail: `sqlite schema v${SCHEMA_VERSION} writable`,
|
|
483
|
+
checkedAt: clock.nowIso(),
|
|
484
|
+
durationMs: clock.monotonicMs() - startedAt
|
|
485
|
+
};
|
|
486
|
+
} catch (err) {
|
|
487
|
+
logger.warn(
|
|
488
|
+
{ err: err instanceof Error ? err.message : String(err) },
|
|
489
|
+
"receipt-store: health check failed (store unavailable)"
|
|
490
|
+
);
|
|
491
|
+
return {
|
|
492
|
+
status: "fail",
|
|
493
|
+
detail: "store-unavailable",
|
|
494
|
+
checkedAt: clock.nowIso(),
|
|
495
|
+
durationMs: clock.monotonicMs() - startedAt
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
},
|
|
499
|
+
async close() {
|
|
500
|
+
if (!closed) {
|
|
501
|
+
closed = true;
|
|
502
|
+
db.close();
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
return store;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// src/protocols/a2a/constants.ts
|
|
510
|
+
var A2A_SPEC_VERSION = "1.0.1";
|
|
511
|
+
var A2A_PROTOCOL_VERSION = "1.0";
|
|
512
|
+
var A2A_PROTOCOL_BINDING = "JSONRPC";
|
|
513
|
+
var A2A_AGENT_CARD_PATH = "/.well-known/agent-card.json";
|
|
514
|
+
var A2A_DEFAULT_MOUNT_PATH = "/a2a";
|
|
515
|
+
var A2A_JSON_MEDIA_TYPE = "application/json";
|
|
516
|
+
var A2A_DEFAULT_AGENT_NAME = "agent-commerce";
|
|
517
|
+
var A2A_VERSION_HEADER = "a2a-version";
|
|
518
|
+
var A2A_METHOD_SEND_MESSAGE = "SendMessage";
|
|
519
|
+
var A2A_PUSH_CONFIG_METHODS = [
|
|
520
|
+
"CreateTaskPushNotificationConfig",
|
|
521
|
+
"GetTaskPushNotificationConfig",
|
|
522
|
+
"ListTaskPushNotificationConfigs",
|
|
523
|
+
"DeleteTaskPushNotificationConfig"
|
|
524
|
+
];
|
|
525
|
+
var A2A_UNSUPPORTED_METHODS = [
|
|
526
|
+
"SendStreamingMessage",
|
|
527
|
+
"GetTask",
|
|
528
|
+
"ListTasks",
|
|
529
|
+
"CancelTask",
|
|
530
|
+
"SubscribeToTask",
|
|
531
|
+
...A2A_PUSH_CONFIG_METHODS,
|
|
532
|
+
"GetExtendedAgentCard"
|
|
533
|
+
];
|
|
534
|
+
var A2A_TASK_LOOKUP_METHODS = ["GetTask", "CancelTask"];
|
|
535
|
+
var A2A_TASK_STATE_COMPLETED = "TASK_STATE_COMPLETED";
|
|
536
|
+
var A2A_TASK_STATE_FAILED = "TASK_STATE_FAILED";
|
|
537
|
+
var A2A_TASK_STATE_INPUT_REQUIRED = "TASK_STATE_INPUT_REQUIRED";
|
|
538
|
+
var A2A_EXTENSIONS_HEADER = "a2a-extensions";
|
|
539
|
+
|
|
540
|
+
// src/protocols/a2a/descriptor.ts
|
|
541
|
+
var A2A_CAPABILITIES = [
|
|
542
|
+
"agent-card",
|
|
543
|
+
"jsonrpc",
|
|
544
|
+
"SendMessage",
|
|
545
|
+
// The x402 A2A transport, opt-in per request
|
|
546
|
+
"x402-extension"
|
|
547
|
+
];
|
|
548
|
+
var A2A_UNSUPPORTED = [
|
|
549
|
+
// Methods, as the protocol names them; the transport refuses the same list
|
|
550
|
+
...A2A_UNSUPPORTED_METHODS,
|
|
551
|
+
// Transports other than the one binding served
|
|
552
|
+
"HTTP+JSON/REST binding",
|
|
553
|
+
"gRPC binding",
|
|
554
|
+
// Behaviors
|
|
555
|
+
"SSE",
|
|
556
|
+
"long-running task persistence",
|
|
557
|
+
"task resumption other than an x402 extension payment",
|
|
558
|
+
"push notifications",
|
|
559
|
+
"multi-turn conversational continuation",
|
|
560
|
+
"authenticated extended agent cards",
|
|
561
|
+
"A2A authentication schemes",
|
|
562
|
+
"artifact types beyond Agent Commerce outcome data",
|
|
563
|
+
// Pending x402 payments live in process memory
|
|
564
|
+
"x402 extension payments across gateway restarts or instances"
|
|
565
|
+
];
|
|
566
|
+
function buildDescriptor(implementationVersion) {
|
|
567
|
+
return {
|
|
568
|
+
name: "a2a",
|
|
569
|
+
kind: "protocol",
|
|
570
|
+
implementationVersion,
|
|
571
|
+
supportedSpec: A2A_SPEC_VERSION,
|
|
572
|
+
capabilities: A2A_CAPABILITIES,
|
|
573
|
+
status: "experimental",
|
|
574
|
+
unsupported: A2A_UNSUPPORTED
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// src/protocols/acp/descriptor.ts
|
|
579
|
+
var ACP_CAPABILITIES = [
|
|
580
|
+
"rest transport",
|
|
581
|
+
"well-known discovery",
|
|
582
|
+
"bearer authentication",
|
|
583
|
+
"API-Version enforcement",
|
|
584
|
+
// Forwarded as received: the gateway verifies neither signature header
|
|
585
|
+
"request header forwarding to the merchant",
|
|
586
|
+
"checkout service",
|
|
587
|
+
...ACP_CHECKOUT_OPERATIONS
|
|
588
|
+
];
|
|
589
|
+
var ACP_UNSUPPORTED = [
|
|
590
|
+
// Services this seller does not implement, named as ACP names them. The
|
|
591
|
+
// discovery document advertises `checkout` alone, and these are the reason.
|
|
592
|
+
"carts service",
|
|
593
|
+
"feed service",
|
|
594
|
+
"standalone orders service",
|
|
595
|
+
"delegate_payment",
|
|
596
|
+
"delegate_authentication",
|
|
597
|
+
// Bindings and delivery directions
|
|
598
|
+
"ACP MCP transport binding",
|
|
599
|
+
"webhooks",
|
|
600
|
+
"outbound merchant-to-agent delivery",
|
|
601
|
+
"ACP client role",
|
|
602
|
+
// Request authentication beyond the bearer token
|
|
603
|
+
"Signature header verification",
|
|
604
|
+
"Timestamp replay-window verification",
|
|
605
|
+
// Extensions, versioning and payment handlers
|
|
606
|
+
"discount extension",
|
|
607
|
+
"general ACP extension framework",
|
|
608
|
+
"multiple ACP API versions",
|
|
609
|
+
"seller-backed payment handler integration"
|
|
610
|
+
];
|
|
611
|
+
function buildDescriptor2(implementationVersion) {
|
|
612
|
+
return {
|
|
613
|
+
name: "acp",
|
|
614
|
+
kind: "protocol",
|
|
615
|
+
implementationVersion,
|
|
616
|
+
supportedSpec: ACP_SPEC_VERSION,
|
|
617
|
+
capabilities: ACP_CAPABILITIES,
|
|
618
|
+
status: "experimental",
|
|
619
|
+
unsupported: ACP_UNSUPPORTED
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
export { A2A_AGENT_CARD_PATH, A2A_DEFAULT_AGENT_NAME, A2A_DEFAULT_MOUNT_PATH, A2A_EXTENSIONS_HEADER, A2A_JSON_MEDIA_TYPE, A2A_METHOD_SEND_MESSAGE, A2A_PROTOCOL_BINDING, A2A_PROTOCOL_VERSION, A2A_PUSH_CONFIG_METHODS, A2A_SPEC_VERSION, A2A_TASK_LOOKUP_METHODS, A2A_TASK_STATE_COMPLETED, A2A_TASK_STATE_FAILED, A2A_TASK_STATE_INPUT_REQUIRED, A2A_UNSUPPORTED, A2A_UNSUPPORTED_METHODS, A2A_VERSION_HEADER, ACP_UNSUPPORTED, buildDescriptor, buildDescriptor2, createSqliteReceiptStore };
|
|
624
|
+
//# sourceMappingURL=chunk-SNM3OVCY.js.map
|
|
625
|
+
//# sourceMappingURL=chunk-SNM3OVCY.js.map
|