@dvmkit/sdk 0.18.0 → 0.19.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 (34) hide show
  1. package/dist/{chunk-JQ2Z3MIC.js → chunk-34H4ZKBM.js} +1 -1
  2. package/dist/{chunk-WMGXJQI3.js → chunk-5RGZN6WQ.js} +1 -1
  3. package/dist/{chunk-Y6JJDOGO.js → chunk-6RJAE332.js} +17 -7
  4. package/dist/{chunk-3KRFFLAT.js → chunk-C65P6MGZ.js} +1 -1
  5. package/dist/{chunk-AYEBQDAZ.js → chunk-DJRTYBEE.js} +1 -1
  6. package/dist/{chunk-B6T3FEVX.js → chunk-I5MXADJS.js} +1 -1
  7. package/dist/{chunk-IKMRT7O5.js → chunk-INYFUPXV.js} +1 -0
  8. package/dist/{chunk-62FI3NJF.js → chunk-NUDHO4HV.js} +4 -2
  9. package/dist/{chunk-VKFR5PCW.js → chunk-OTNHKRHA.js} +2 -2
  10. package/dist/{chunk-A6EY4K46.js → chunk-QCZXKUS2.js} +45 -13
  11. package/dist/{chunk-QNAYENWA.js → chunk-RPJKEWRR.js} +14050 -13530
  12. package/dist/{content-retention-Cxn-umvR.d.ts → content-retention-C_TToHCi.d.ts} +1 -1
  13. package/dist/{credit-ledger-SBLDJCLE.js → credit-ledger-ZCJXJG6R.js} +2 -2
  14. package/dist/{credit-menu-CYjp3FA3.d.ts → credit-menu-BlODG4E7.d.ts} +144 -6
  15. package/dist/{fx-D2w3wCvY.d.ts → fx-QoVA2oBc.d.ts} +1 -1
  16. package/dist/index.d.ts +5 -5
  17. package/dist/index.js +14 -1
  18. package/dist/internal/caller.d.ts +6 -6
  19. package/dist/internal/caller.js +3 -3
  20. package/dist/internal/server.d.ts +7 -7
  21. package/dist/internal/server.js +10 -10
  22. package/dist/{job-store-Ci2ihiVr.d.ts → job-store-D4-18IKm.d.ts} +5 -1
  23. package/dist/{lightning-backend-DMBY7PaJ.d.ts → lightning-backend-B2wMBR-x.d.ts} +1 -1
  24. package/dist/{memory-credit-ledger-DMIGIH2H.js → memory-credit-ledger-N4PZKTT5.js} +3 -3
  25. package/dist/{postgres-job-store-E5GXLRB4.js → postgres-job-store-QKN5LGAH.js} +1 -1
  26. package/dist/server/index.d.ts +11 -10
  27. package/dist/server/index.js +12 -12
  28. package/dist/{step-cache-B_18RAPb.d.ts → step-cache-B83Y9T9p.d.ts} +31 -8
  29. package/dist/{tempo-session-store-N3TFZ26X.js → tempo-session-store-XJE6GIXN.js} +2 -2
  30. package/dist/testing/index.d.ts +5 -3
  31. package/dist/testing/index.js +1 -1
  32. package/dist/{usd-ROzdYbbm.d.ts → usd-g9kCw86F.d.ts} +1 -1
  33. package/dist/{x402-HVCUEWWU.js → x402-XLFD43RF.js} +4 -4
  34. package/package.json +2 -2
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-COYKJRMM.js";
8
8
  import {
9
9
  withPostgresTransactionRecovery
10
- } from "./chunk-IKMRT7O5.js";
10
+ } from "./chunk-INYFUPXV.js";
11
11
 
12
12
  // src/sdk/server/tempo-session-store.ts
13
13
  import { AsyncLocalStorage } from "async_hooks";
@@ -2,7 +2,7 @@ import {
2
2
  X402_DEFAULT_NETWORK,
3
3
  resolveRpcHttpTransportOptions,
4
4
  resolveRpcOverride
5
- } from "./chunk-62FI3NJF.js";
5
+ } from "./chunk-NUDHO4HV.js";
6
6
  import {
7
7
  redactUrl,
8
8
  redactUrlsInText
@@ -49,6 +49,7 @@ var MemoryJobStore = class {
49
49
  data = /* @__PURE__ */ new Map();
50
50
  messages = /* @__PURE__ */ new Map();
51
51
  nextSeq = /* @__PURE__ */ new Map();
52
+ outgoingAppends = /* @__PURE__ */ new Map();
52
53
  messageSubscribers = /* @__PURE__ */ new Map();
53
54
  notifySubscribers = /* @__PURE__ */ new Map();
54
55
  reactivationLocks = /* @__PURE__ */ new Set();
@@ -136,6 +137,7 @@ var MemoryJobStore = class {
136
137
  delete(id) {
137
138
  this.contentHolds.delete(id);
138
139
  this.data.delete(id);
140
+ this.outgoingAppends.delete(id);
139
141
  this.messages.delete(id);
140
142
  this.nextSeq.delete(id);
141
143
  this.receiptSeqs.delete(id);
@@ -205,6 +207,8 @@ var MemoryJobStore = class {
205
207
  if (!record || record.redactedAt !== void 0) {
206
208
  return Promise.reject(new Error(`appendOutgoing: job ${jobId} not found`));
207
209
  }
210
+ const prior = opts?.appendId ? this.outgoingAppends.get(jobId)?.get(opts.appendId) : void 0;
211
+ if (prior !== void 0) return Promise.resolve(prior);
208
212
  const seq = this.allocateSeq(jobId);
209
213
  const fullMessage = { ...message, seq };
210
214
  if (opts?.awaitingInput && !isTerminal(record.status)) {
@@ -240,6 +244,11 @@ var MemoryJobStore = class {
240
244
  }
241
245
  if (!isTerminal(record.status)) record.lastActivityAt = Date.now();
242
246
  if (seq > record.seq) record.seq = seq;
247
+ if (opts?.appendId) {
248
+ let appends = this.outgoingAppends.get(jobId);
249
+ if (!appends) this.outgoingAppends.set(jobId, appends = /* @__PURE__ */ new Map());
250
+ appends.set(opts.appendId, seq);
251
+ }
243
252
  this.notify(jobId);
244
253
  return Promise.resolve(seq);
245
254
  }
@@ -356,6 +365,9 @@ var MemoryJobStore = class {
356
365
  cancelJob(jobId, reason) {
357
366
  return this.terminateJob(jobId, reason, "cancelled", null);
358
367
  }
368
+ failJob(jobId, reason) {
369
+ return this.terminateJob(jobId, reason, "failed", null);
370
+ }
359
371
  getCounters(jobId) {
360
372
  const record = this.data.get(jobId);
361
373
  if (!record) return Promise.resolve(void 0);
@@ -435,13 +447,11 @@ var MemoryJobStore = class {
435
447
  if (!record) return Promise.resolve(false);
436
448
  const eligible = (record.status === "processing" || record.status === "working" || record.status === "awaiting-input") && (expectedActivityBefore === null || record.lastActivityAt <= expectedActivityBefore);
437
449
  if (!eligible) return Promise.resolve(false);
438
- let terminalMessages = record.messages;
450
+ const messages = this.messagesFor(jobId).filter((entry) => entry.status === "verified").map((entry) => entry.message);
451
+ const terminalMessages = messages.length ? messages : record.messages;
439
452
  if (expectedActivityBefore !== null) {
440
- const messages = this.messagesFor(jobId).filter((entry) => entry.status === "verified").map((entry) => entry.message);
441
- const history = messages.length ? messages : record.messages;
442
- terminalMessages = history;
443
- const deadline = callerDeadline({ ...record, messages: history });
444
- const awaiting = deadline !== void 0 || record.status === "awaiting-input" && !hasCallerDeadline(history);
453
+ const deadline = callerDeadline({ ...record, messages: terminalMessages });
454
+ const awaiting = deadline !== void 0 || record.status === "awaiting-input" && !hasCallerDeadline(terminalMessages);
445
455
  if (terminalStatus === "cancelled" !== awaiting || deadline !== void 0 && Date.now() < deadline) return Promise.resolve(false);
446
456
  }
447
457
  const seq = this.allocateSeq(jobId);
@@ -453,7 +463,7 @@ var MemoryJobStore = class {
453
463
  content: { reason }
454
464
  };
455
465
  this.messagesFor(jobId).push({ message: cancelMsg, status: "verified" });
456
- record.endedBy = expectedActivityBefore === null || terminalStatus === "cancelled" ? "caller" : "provider";
466
+ record.endedBy = terminalStatus === "cancelled" ? "caller" : "provider";
457
467
  applyTiming(record, structuredClone(record), Date.now(), terminalStatus);
458
468
  record.status = terminalStatus;
459
469
  record.summary = record.summary ?? reason;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  X402_DEFAULT_FACILITATOR
3
- } from "./chunk-62FI3NJF.js";
3
+ } from "./chunk-NUDHO4HV.js";
4
4
  import {
5
5
  callerLoggers
6
6
  } from "./chunk-66HGCPBU.js";
@@ -18,7 +18,7 @@ import {
18
18
  refundAssetDelta,
19
19
  refundRequest,
20
20
  x402SettlementPending
21
- } from "./chunk-B6T3FEVX.js";
21
+ } from "./chunk-I5MXADJS.js";
22
22
 
23
23
  // src/sdk/server/memory-credit-ledger.ts
24
24
  import { randomUUID } from "crypto";
@@ -10,7 +10,7 @@ import {
10
10
  } from "./chunk-5UC7TOQC.js";
11
11
  import {
12
12
  applyRetryToPool
13
- } from "./chunk-IKMRT7O5.js";
13
+ } from "./chunk-INYFUPXV.js";
14
14
  import {
15
15
  x402NetworkByCaip2
16
16
  } from "./chunk-BPYMEMQX.js";
@@ -188,6 +188,7 @@ function truncateUtf8(value, maxBytes) {
188
188
 
189
189
  export {
190
190
  withPostgresRecoveryContext,
191
+ isTransportError,
191
192
  withInitRetry,
192
193
  applyRetryToPool,
193
194
  withPostgresTransactionRecovery
@@ -9,11 +9,13 @@ var X402_DEFAULT_FACILITATOR = "https://x402.org/facilitator";
9
9
  // src/lib/x402/spec.ts
10
10
  var X402_VERSION = 2;
11
11
  var X402_V1_VERSION = 1;
12
+ var DEFAULT_MAX_TIMEOUT_SECONDS = 60;
12
13
  var X402_DEFAULT_NETWORK = "eip155:8453";
13
14
  var X402_EXACT_SCHEME = "exact";
14
15
  var X402_BATCH_SETTLEMENT_SCHEME = "batch-settlement";
15
16
  function buildPaymentRequirements(opts) {
16
17
  const { x402Config, requiredUsdcMicro, resource, description, mimeType } = opts;
18
+ const maxTimeoutSeconds = opts.maxTimeoutSeconds ?? DEFAULT_MAX_TIMEOUT_SECONDS;
17
19
  const version = opts.version ?? X402_VERSION;
18
20
  const network = version === X402_V1_VERSION ? caip2ToX402Network(x402Config.network) : x402Config.network;
19
21
  const usdcContract = usdcContractByCaip2(x402Config.network);
@@ -27,7 +29,7 @@ function buildPaymentRequirements(opts) {
27
29
  amount: requiredUsdcMicro.toString(),
28
30
  payTo: x402Config.payTo,
29
31
  asset,
30
- maxTimeoutSeconds: 60,
32
+ maxTimeoutSeconds,
31
33
  extra
32
34
  };
33
35
  }
@@ -40,7 +42,7 @@ function buildPaymentRequirements(opts) {
40
42
  mimeType: mimeType ?? "application/json",
41
43
  payTo: x402Config.payTo,
42
44
  asset,
43
- maxTimeoutSeconds: 60,
45
+ maxTimeoutSeconds,
44
46
  ...Object.keys(extra).length > 0 ? { extra } : {}
45
47
  };
46
48
  }
@@ -2,14 +2,14 @@ import {
2
2
  createX402FacilitatorAuthHeaders,
3
3
  settleWithFacilitator,
4
4
  verifyWithFacilitator
5
- } from "./chunk-3KRFFLAT.js";
5
+ } from "./chunk-C65P6MGZ.js";
6
6
  import {
7
7
  buildPaymentRequirements,
8
8
  decodePayment,
9
9
  encodeSettleResponseHeader,
10
10
  exactEvmAuthorization,
11
11
  usdcToMsats
12
- } from "./chunk-62FI3NJF.js";
12
+ } from "./chunk-NUDHO4HV.js";
13
13
  import {
14
14
  callerLoggers
15
15
  } from "./chunk-66HGCPBU.js";
@@ -345,6 +345,15 @@ var PostgresJobStore = class {
345
345
  ALTER TABLE job_messages ADD COLUMN IF NOT EXISTS status TEXT NOT NULL DEFAULT 'verified';
346
346
  ALTER TABLE job_messages ADD COLUMN IF NOT EXISTS created_at_ms BIGINT;
347
347
 
348
+ -- Survives terminal message cleanup so a lost COMMIT acknowledgement can
349
+ -- be retried without allocating another sequence or applying counters twice.
350
+ CREATE TABLE IF NOT EXISTS job_outgoing_appends (
351
+ job_id TEXT NOT NULL REFERENCES jobs(id) ON DELETE CASCADE,
352
+ append_id TEXT NOT NULL,
353
+ seq INTEGER NOT NULL,
354
+ PRIMARY KEY (job_id, append_id)
355
+ );
356
+
348
357
  -- per-DVM monotonic receipt counter. Single row by
349
358
  -- construction (the CHECK pins the key), and per-DVM by construction
350
359
  -- too \u2014 the SDK runs one database per DVM (see postgres-kv-store.ts).
@@ -791,7 +800,11 @@ var PostgresJobStore = class {
791
800
  if (this.hostingCleanupFence) {
792
801
  throw new Error("Hosted job deletion cannot discard obligation evidence");
793
802
  }
794
- await this.pool.query("DELETE FROM jobs WHERE id = $1", [id]);
803
+ await this.pool.query(
804
+ `WITH deleted AS (DELETE FROM jobs WHERE id=$1 RETURNING id)
805
+ DELETE FROM job_outgoing_appends WHERE job_id IN (SELECT id FROM deleted)`,
806
+ [id]
807
+ );
795
808
  await this.deleteResolvedMessages(id).catch(() => void 0);
796
809
  }
797
810
  async listJobsForRetention(args) {
@@ -945,6 +958,18 @@ var PostgresJobStore = class {
945
958
  const client = await this.pool.connect();
946
959
  try {
947
960
  await client.query("BEGIN");
961
+ if (opts?.appendId) {
962
+ const owner = await client.query("SELECT id FROM jobs WHERE id=$1 AND redacted_at IS NULL FOR UPDATE", [jobId]);
963
+ if (!owner.rows.length) throw new Error(`appendOutgoing: job ${jobId} not found`);
964
+ const prior = await client.query(
965
+ "SELECT seq FROM job_outgoing_appends WHERE job_id=$1 AND append_id=$2",
966
+ [jobId, opts.appendId]
967
+ );
968
+ if (prior.rows[0]) {
969
+ await client.query("COMMIT");
970
+ return prior.rows[0].seq;
971
+ }
972
+ }
948
973
  const { rows } = await client.query(
949
974
  `UPDATE jobs SET next_seq = next_seq + 1, last_activity_at = CASE WHEN status IN ('completed','failed','cancelled') THEN last_activity_at ELSE $2 END,
950
975
  awaiting_input_at_ms = CASE WHEN $3::boolean AND status NOT IN ('completed', 'failed', 'cancelled')
@@ -1024,6 +1049,12 @@ var PostgresJobStore = class {
1024
1049
  ]
1025
1050
  );
1026
1051
  }
1052
+ if (opts?.appendId) {
1053
+ await client.query(
1054
+ "INSERT INTO job_outgoing_appends (job_id, append_id, seq) VALUES ($1,$2,$3)",
1055
+ [jobId, opts.appendId, seq]
1056
+ );
1057
+ }
1027
1058
  await client.query("SELECT pg_notify('job_messages', $1)", [jobId]);
1028
1059
  await client.query("COMMIT");
1029
1060
  return seq;
@@ -1239,6 +1270,9 @@ var PostgresJobStore = class {
1239
1270
  cancelJob(jobId, reason) {
1240
1271
  return this.terminateJob(jobId, reason, "cancelled", null, "caller");
1241
1272
  }
1273
+ failJob(jobId, reason) {
1274
+ return this.terminateJob(jobId, reason, "failed", null, "provider");
1275
+ }
1242
1276
  cancelJobForHosting(jobId, reason) {
1243
1277
  return this.terminateJob(jobId, reason, "cancelled", null, "provider");
1244
1278
  }
@@ -1429,17 +1463,15 @@ var PostgresJobStore = class {
1429
1463
  await client.query("ROLLBACK");
1430
1464
  return false;
1431
1465
  }
1432
- let terminalMessages;
1466
+ const record = rowToRecord(rows[0]);
1467
+ const { rows: messages } = await client.query(
1468
+ "SELECT data FROM job_messages WHERE job_id=$1 AND status='verified' ORDER BY seq",
1469
+ [jobId]
1470
+ );
1471
+ const terminalMessages = messages.length ? messages.map((row) => row.data) : record.messages;
1433
1472
  if (staleOnly) {
1434
- const record = rowToRecord(rows[0]);
1435
- const { rows: messages } = await client.query(
1436
- "SELECT data FROM job_messages WHERE job_id=$1 AND status='verified' ORDER BY seq",
1437
- [jobId]
1438
- );
1439
- const history = messages.length ? messages.map((row) => row.data) : record.messages;
1440
- terminalMessages = history;
1441
- const deadline = callerDeadline({ ...record, messages: history });
1442
- const awaiting = deadline !== void 0 || record.status === "awaiting-input" && !hasCallerDeadline(history);
1473
+ const deadline = callerDeadline({ ...record, messages: terminalMessages });
1474
+ const awaiting = deadline !== void 0 || record.status === "awaiting-input" && !hasCallerDeadline(terminalMessages);
1443
1475
  if (terminalStatus === "cancelled" !== awaiting || deadline !== void 0 && Date.now() < deadline) {
1444
1476
  await client.query("ROLLBACK");
1445
1477
  return false;
@@ -1467,7 +1499,7 @@ var PostgresJobStore = class {
1467
1499
  awaiting_input_at_ms = NULL,
1468
1500
  status = $6,
1469
1501
  summary = COALESCE(summary, $2),
1470
- messages = ${staleOnly ? "$3::jsonb" : "COALESCE(messages, '[]'::jsonb) || $3::jsonb"},
1502
+ messages = $3::jsonb,
1471
1503
  seq = $4,
1472
1504
  next_seq = $4 + 1,
1473
1505
  last_activity_at = $5
@@ -1475,7 +1507,7 @@ var PostgresJobStore = class {
1475
1507
  [
1476
1508
  jobId,
1477
1509
  reason,
1478
- JSON.stringify([...terminalMessages ?? [], cancelMsg]),
1510
+ JSON.stringify([...terminalMessages, cancelMsg]),
1479
1511
  nextSeq,
1480
1512
  now,
1481
1513
  terminalStatus,