@dvmkit/sdk 0.10.0 → 0.10.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.
@@ -483,7 +483,16 @@ var PostgresJobStore = class {
483
483
  held.client.release();
484
484
  }
485
485
  async save(record) {
486
- await this.saveRecord(record, record[JOB_DVM_ID]);
486
+ const dvmId = record[JOB_DVM_ID];
487
+ for (let attempt = 0; ; attempt++) {
488
+ try {
489
+ await this.saveRecord(record, dvmId);
490
+ return;
491
+ } catch (error) {
492
+ if (attempt >= 7 || !await this.canRetrySnapshot(error, record)) throw error;
493
+ await new Promise((resolve) => setTimeout(resolve, 5 * (attempt + 1)));
494
+ }
495
+ }
487
496
  }
488
497
  /** Persist a job while retaining its mount identity for cost-report recovery. */
489
498
  async saveForDvm(record, dvmId) {
@@ -495,6 +504,17 @@ var PostgresJobStore = class {
495
504
  delete scoped[JOB_DVM_ID];
496
505
  }
497
506
  }
507
+ async canRetrySnapshot(error, record) {
508
+ if (error === null || typeof error !== "object") return false;
509
+ const { code, constraint } = error;
510
+ if (code === "40P01") return true;
511
+ if (code !== "23505" || constraint !== "idx_jobs_request_id_caller") return false;
512
+ const { rows } = await this.pool.query(
513
+ "SELECT id FROM jobs WHERE requester_pubkey=$1 AND request_id=$2",
514
+ [record.requesterPubkey, record.requestId]
515
+ );
516
+ return rows[0]?.id === record.id;
517
+ }
498
518
  async saveRecord(record, dvmId) {
499
519
  const now = Date.now();
500
520
  const write = (q) => q.query(
@@ -642,14 +662,14 @@ var PostgresJobStore = class {
642
662
  ]
643
663
  );
644
664
  let rowCount;
645
- if (this.hostingCleanupFence) {
646
- const tx = await this.pool.connect();
647
- try {
648
- await tx.query("BEGIN");
649
- const existing = await tx.query(
650
- "SELECT dvm_id FROM jobs WHERE id=$1 FOR UPDATE",
651
- [record.id]
652
- );
665
+ const tx = await this.pool.connect();
666
+ try {
667
+ await tx.query("BEGIN");
668
+ const existing = await tx.query(
669
+ "SELECT dvm_id FROM jobs WHERE id=$1 FOR UPDATE",
670
+ [record.id]
671
+ );
672
+ if (this.hostingCleanupFence) {
653
673
  if (existing.rows[0]) {
654
674
  if (existing.rows[0].dvm_id !== null && existing.rows[0].dvm_id !== this.hostingCleanupFence.dvmId) {
655
675
  throw new Error("Hosted job belongs to another DVM");
@@ -657,16 +677,14 @@ var PostgresJobStore = class {
657
677
  } else {
658
678
  await this.hostingCleanupFence.assertNewIntent(tx, { jobId: record.id });
659
679
  }
660
- ({ rowCount } = await write(tx));
661
- await tx.query("COMMIT");
662
- } catch (error) {
663
- await tx.query("ROLLBACK").catch(() => void 0);
664
- throw error;
665
- } finally {
666
- tx.release();
667
680
  }
668
- } else {
669
- ({ rowCount } = await write(this.pool));
681
+ ({ rowCount } = await write(tx));
682
+ await tx.query("COMMIT");
683
+ } catch (error) {
684
+ await tx.query("ROLLBACK").catch(() => void 0);
685
+ throw error;
686
+ } finally {
687
+ tx.release();
670
688
  }
671
689
  if (rowCount === 0) {
672
690
  diagnosticConsole.warn(
@@ -1393,8 +1411,12 @@ var PostgresJobStore = class {
1393
1411
  return true;
1394
1412
  }
1395
1413
  async deleteResolvedMessages(jobId) {
1396
- await this.pool.query(this.hostingCleanupFence ? `DELETE FROM job_messages WHERE job_id=$1 AND NOT (
1397
- data->>'type'='payment' AND status IN ('pending-verification','failed-verify'))` : "DELETE FROM job_messages WHERE job_id=$1", [jobId]);
1414
+ await this.pool.query(
1415
+ `DELETE FROM job_messages WHERE job_id=$1 AND NOT (
1416
+ data->>'type'='payment' AND (status='pending-verification'
1417
+ OR ($2::boolean AND status='failed-verify')))`,
1418
+ [jobId, !!this.hostingCleanupFence]
1419
+ );
1398
1420
  }
1399
1421
  async fetchCountersTx(client, jobId) {
1400
1422
  const { rows } = await client.query(
@@ -20,7 +20,7 @@ import {
20
20
  } from "./chunk-YOSZIWC3.js";
21
21
  import {
22
22
  PostgresJobStore
23
- } from "./chunk-Y6DO5WSO.js";
23
+ } from "./chunk-2OGBZPPJ.js";
24
24
  import {
25
25
  parseStoreValue
26
26
  } from "./chunk-YG7G4DPZ.js";
@@ -12725,22 +12725,17 @@ function buildContext(job, opts) {
12725
12725
  };
12726
12726
  const doResolve = async (pc) => {
12727
12727
  if (resolved) return;
12728
+ if (job.pendingPayment?.resolve === doResolve) {
12729
+ job.status = job.pendingPrompts.size > 0 ? "awaiting-input" : "processing";
12730
+ const persist = opts.onPaymentResume ?? opts.onYield;
12731
+ if (job.status === "awaiting-input" && persist) await persist();
12732
+ if (resolved) return;
12733
+ job.pendingPayment = null;
12734
+ }
12728
12735
  resolved = true;
12729
12736
  cleanup();
12730
12737
  creditedToHandlerMsats += amountMsats;
12731
12738
  creditedToHandlerMicro += pendingFiat?.amountMicro ?? 0;
12732
- if (job.pendingPayment?.resolve === doResolve) {
12733
- job.pendingPayment = null;
12734
- job.status = job.pendingPrompts.size > 0 ? "awaiting-input" : "processing";
12735
- if (job.status === "awaiting-input" && opts.onYield) {
12736
- try {
12737
- await opts.onYield();
12738
- } catch (err) {
12739
- reject(err);
12740
- return;
12741
- }
12742
- }
12743
- }
12744
12739
  resolve(pc);
12745
12740
  };
12746
12741
  const doReject = (err) => {
@@ -13266,6 +13261,9 @@ var JobManager = class {
13266
13261
  // A prompt response and a payment NOTIFY must not mistake each other for a
13267
13262
  // different machine's successful claim.
13268
13263
  inputResumeTails = /* @__PURE__ */ new WeakMap();
13264
+ // A failed partial-wait snapshot leaves our durable claim in processing.
13265
+ // Retain its continuation so a later input can finish it without a new claim.
13266
+ claimedPaymentResumes = /* @__PURE__ */ new WeakMap();
13269
13267
  sessionId = randomBytes4(3).toString("hex");
13270
13268
  nextJobId = 1;
13271
13269
  accumulatorMonitor;
@@ -13672,7 +13670,10 @@ var JobManager = class {
13672
13670
  }
13673
13671
  async queueInputResume(job, resume) {
13674
13672
  const previous = this.inputResumeTails.get(job) ?? Promise.resolve();
13675
- const next = previous.catch(() => void 0).then(resume);
13673
+ const next = previous.catch(() => void 0).then(async () => {
13674
+ await this.claimedPaymentResumes.get(job)?.();
13675
+ return resume();
13676
+ });
13676
13677
  this.inputResumeTails.set(job, next);
13677
13678
  try {
13678
13679
  return await next;
@@ -13684,6 +13685,19 @@ var JobManager = class {
13684
13685
  await job.messageAppenderTail;
13685
13686
  return isStreamableJobStore(this.jobStore) ? this.jobStore.claimForProcessing(job.id) : true;
13686
13687
  }
13688
+ async resumeClaimedPayment(job, resume) {
13689
+ const retry = async () => {
13690
+ try {
13691
+ if (!isTerminal(job.status) && !await this.adoptDurableTerminal(job)) await resume();
13692
+ this.claimedPaymentResumes.delete(job);
13693
+ } catch (error) {
13694
+ if (!(error instanceof JobSnapshotPersistenceError)) this.claimedPaymentResumes.delete(job);
13695
+ throw error;
13696
+ }
13697
+ };
13698
+ this.claimedPaymentResumes.set(job, retry);
13699
+ await retry();
13700
+ }
13687
13701
  async dispatchMessageNow(job, type, content) {
13688
13702
  const ctx = job.sdkCtx;
13689
13703
  const cap = this.getCapability(job.capability);
@@ -13712,10 +13726,13 @@ var JobManager = class {
13712
13726
  return;
13713
13727
  }
13714
13728
  if (job.pendingPayment !== pp || isTerminal(job.status)) return;
13715
- job.pendingPayment = null;
13716
- job.status = job.pendingPrompts.size > 0 ? "awaiting-input" : "processing";
13717
- if (job.status === "awaiting-input") await this.persistJob(job);
13718
- await pp.resolve(pc);
13729
+ await this.resumeClaimedPayment(job, async () => {
13730
+ job.status = job.pendingPrompts.size > 0 ? "awaiting-input" : "processing";
13731
+ if (job.status === "awaiting-input") await retryJobSnapshot(() => this.persistJob(job));
13732
+ if (job.pendingPayment !== pp || isTerminal(job.status)) return;
13733
+ job.pendingPayment = null;
13734
+ await pp.resolve(pc);
13735
+ });
13719
13736
  } else if (cap?.onPayment && ctx) {
13720
13737
  await cap.onPayment(ctx, pc);
13721
13738
  }
@@ -13768,10 +13785,14 @@ var JobManager = class {
13768
13785
  record.seq = Math.max(record.seq, highSeq);
13769
13786
  }
13770
13787
  }
13771
- if (this.opts.dvmId && isTerminalCostRecoveryStore(this.jobStore)) {
13772
- await this.jobStore.saveForDvm(record, this.opts.dvmId);
13773
- } else {
13774
- await this.jobStore.save(record);
13788
+ try {
13789
+ if (this.opts.dvmId && isTerminalCostRecoveryStore(this.jobStore)) {
13790
+ await this.jobStore.saveForDvm(record, this.opts.dvmId);
13791
+ } else {
13792
+ await this.jobStore.save(record);
13793
+ }
13794
+ } catch (error) {
13795
+ throw new JobSnapshotPersistenceError(error);
13775
13796
  }
13776
13797
  const saved = await this.jobStore.get(job.id);
13777
13798
  if (saved) {
@@ -15311,6 +15332,7 @@ var JobManager = class {
15311
15332
  fxFetcher: this.opts.fxFetcher,
15312
15333
  onTerminal: () => this.handleJobTerminal(job),
15313
15334
  onYield: () => this.persistJob(job),
15335
+ onPaymentResume: () => retryJobSnapshot(() => this.persistJob(job)),
15314
15336
  subscribeNotifications: isStreamableJobStore(jobStore) ? (cb) => jobStore.subscribeNotifications(job.id, cb) : void 0,
15315
15337
  getCounters: isStreamableJobStore(jobStore) ? () => jobStore.getCounters(job.id) : void 0,
15316
15338
  drawPool: this.opts.creditLedger ? () => this.resolveDrawPool(job) : void 0,
@@ -15321,7 +15343,9 @@ var JobManager = class {
15321
15343
  if (!pending || job.pendingPayment !== pending || isTerminal(job.status)) return false;
15322
15344
  if (!await this.claimLocalInput(job)) return false;
15323
15345
  if (job.pendingPayment !== pending || isTerminal(job.status)) return false;
15324
- await resume?.();
15346
+ await this.resumeClaimedPayment(job, async () => {
15347
+ await resume?.();
15348
+ });
15325
15349
  return true;
15326
15350
  });
15327
15351
  } : void 0,
@@ -16082,6 +16106,23 @@ function resolvePricingMax(raw) {
16082
16106
  if (raw === void 0) return void 0;
16083
16107
  return { amount: roundUsd(parseUsdPrice(raw, "price")), currency: "usd" };
16084
16108
  }
16109
+ var JobSnapshotPersistenceError = class extends Error {
16110
+ constructor(cause) {
16111
+ super("Job snapshot could not be persisted", { cause });
16112
+ this.name = "JobSnapshotPersistenceError";
16113
+ }
16114
+ };
16115
+ async function retryJobSnapshot(persist) {
16116
+ for (let attempt = 0; ; attempt++) {
16117
+ try {
16118
+ await persist();
16119
+ return;
16120
+ } catch (error) {
16121
+ if (!(error instanceof JobSnapshotPersistenceError) || attempt >= 2) throw error;
16122
+ await new Promise((resolve) => setTimeout(resolve, 50 * (attempt + 1)));
16123
+ }
16124
+ }
16125
+ }
16085
16126
 
16086
16127
  // src/sdk/server/mint-health-tracker.ts
16087
16128
  var DEFAULT_TICK_INTERVAL_MS2 = 5 * 60 * 1e3;
@@ -22927,8 +22968,14 @@ var DVMServer = class {
22927
22968
  await jm.markInboundVerified(activeJob.id, inboundSeq2);
22928
22969
  }
22929
22970
  jm.startIdleTimer(activeJob);
22930
- await jm.dispatchMessage(activeJob, body2.type, body2.content);
22931
- await jm.persistJob(activeJob);
22971
+ try {
22972
+ await jm.dispatchMessage(activeJob, body2.type, body2.content);
22973
+ await this.persistMessageSnapshot(jm, activeJob, body2.type);
22974
+ } catch (error) {
22975
+ const response = this.postPaymentSnapshotFailure(c, error, activeJob, body2.type, inboundSeq2, unappliedCredit2);
22976
+ if (response) return response;
22977
+ throw error;
22978
+ }
22932
22979
  const lastMsg2 = activeJob.messages[activeJob.messages.length - 1];
22933
22980
  return c.json({ seq: lastMsg2.seq, ...unappliedCredit2 && { credit: unappliedCredit2 } }, 201);
22934
22981
  }
@@ -23011,20 +23058,48 @@ var DVMServer = class {
23011
23058
  return c.json({ seq: lastMsg2.seq, ...creditBlock }, 201);
23012
23059
  }
23013
23060
  jm.startIdleTimer(job);
23014
- if (isStreamableJobStore(jm.store)) {
23015
- const store = jm.store;
23016
- const lockResult = await store.tryReactivationLock(job.id, async () => {
23061
+ try {
23062
+ if (isStreamableJobStore(jm.store)) {
23063
+ const store = jm.store;
23064
+ const lockResult = await store.tryReactivationLock(job.id, async () => {
23065
+ await this.runReactivation(jm, job, body, record.status);
23066
+ });
23067
+ if (!lockResult.acquired) {
23068
+ this.teardownReactivationScaffold(jm, job);
23069
+ }
23070
+ } else {
23017
23071
  await this.runReactivation(jm, job, body, record.status);
23018
- });
23019
- if (!lockResult.acquired) {
23020
- this.teardownReactivationScaffold(jm, job);
23021
23072
  }
23022
- } else {
23023
- await this.runReactivation(jm, job, body, record.status);
23073
+ } catch (error) {
23074
+ const response = this.postPaymentSnapshotFailure(c, error, job, body.type, inboundSeq, unappliedCredit);
23075
+ if (response) return response;
23076
+ throw error;
23024
23077
  }
23025
23078
  const lastMsg = job.messages[job.messages.length - 1];
23026
23079
  return c.json({ seq: lastMsg.seq, ...creditBlock }, 201);
23027
23080
  }
23081
+ async persistMessageSnapshot(jm, job, type) {
23082
+ if (type === "payment") {
23083
+ await retryJobSnapshot(() => jm.persistJob(job));
23084
+ } else {
23085
+ await jm.persistJob(job);
23086
+ }
23087
+ }
23088
+ postPaymentSnapshotFailure(c, error, job, type, inboundSeq, unappliedCredit) {
23089
+ if (!(error instanceof JobSnapshotPersistenceError) || type !== "payment" || inboundSeq === null || !isStreamableJobStore(this.jobManager.store)) return void 0;
23090
+ diagnosticConsole.error({ level: "job_snapshot_unavailable", job_id: job.id, seq: inboundSeq });
23091
+ return c.json({
23092
+ error: "job_snapshot_unavailable",
23093
+ message: "Payment was recorded but the job snapshot could not be persisted.",
23094
+ display: "Your payment was recorded. The service could not save the latest job progress.",
23095
+ hint: "Do not send another payment. Read the job status and messages; if the worker stopped, resume with a non-payment message.",
23096
+ retryable: false,
23097
+ payment_status: "recorded",
23098
+ job_id: job.id,
23099
+ seq: inboundSeq,
23100
+ ...unappliedCredit && { credit: unappliedCredit }
23101
+ }, 503);
23102
+ }
23028
23103
  /**
23029
23104
  * Run the handler or dispatch the inbound after Tx B + Tx C have already
23030
23105
  * committed the credit. Status decides the behaviour: `awaiting-input`
@@ -23050,7 +23125,7 @@ var DVMServer = class {
23050
23125
  });
23051
23126
  } else {
23052
23127
  await jm.dispatchMessage(job, body.type, body.content);
23053
- await jm.persistJob(job);
23128
+ await this.persistMessageSnapshot(jm, job, body.type);
23054
23129
  }
23055
23130
  }
23056
23131
  /**
@@ -2933,6 +2933,7 @@ declare class JobManager<State, InputSchema extends ZodLike | undefined> {
2933
2933
  /** Job ids that were notified mid-re-read and must be re-checked. */
2934
2934
  private readonly statusChecksQueued;
2935
2935
  private readonly inputResumeTails;
2936
+ private readonly claimedPaymentResumes;
2936
2937
  private readonly sessionId;
2937
2938
  private nextJobId;
2938
2939
  private accumulatorMonitor?;
@@ -3083,6 +3084,7 @@ declare class JobManager<State, InputSchema extends ZodLike | undefined> {
3083
3084
  dispatchMessage(job: ServerJob, type: MessageType, content: unknown): Promise<void>;
3084
3085
  private queueInputResume;
3085
3086
  private claimLocalInput;
3087
+ private resumeClaimedPayment;
3086
3088
  private dispatchMessageNow;
3087
3089
  /**
3088
3090
  * Persist a job to the backing store.
@@ -6,8 +6,8 @@ import { Env, BlankSchema } from 'hono/types';
6
6
  import { Pool } from 'pg';
7
7
  export { Pool } from 'pg';
8
8
  import { g as getWallet } from '../wallet-Dwjs5n_M.js';
9
- import { C as ConsumedCredentialStore, L as LockPubkeyStateLoader } from '../credit-menu-VwX_6KM7.js';
10
- export { A as AccumulatorPool, a as AppEnv, b as CreditFundingReport, D as DEFAULT_LOCK_PUBKEY_GRACE_SECONDS, F as FiatDenomination, c as FiatDenominationFailure, d as FundOnlyRequest, I as IncomingPaymentOpts, J as JobCancelledError, e as LockPubkeyPool, f as LockPubkeyState, M as MintHealthTracker, P as PAYMENT_PROOF_KEYS, g as PaymentErrorCode, h as PaymentErrorDetail, i as PaymentInfo, j as PostgresTempoChargeStore, R as ReporterBannerOpts, k as ResolvedFx, l as RevenueBootCheckOpts, S as SDKServerOpts, m as ServerJob, n as ShortPayForfeit, T as TempoChannelReport, o as TempoObserverHealth, p as TempoSessionChannelMismatchError, U as UpfrontPaymentOpts, V as VerifiedIncomingPayment, q as VerifyIncomingSnapshot, X as X402BatchChannelObservation, r as X402FacilitatorHealth, s as X402SettlementEvidenceOutcome, t as X402SettlementRepair, u as X402SettlementRepairRefusal, v as X402SettlementRepaired, w as X402WedgedSettlement, x as X402WedgedSettlementPage, y as X402_BATCH_SETTLEMENT_MAINNET_NETWORK, z as abortJob, B as activePubkeySet, E as applyPaymentInfoToJob, G as assertRevenueReporterReady, H as buildPaymentErrorResponse, K as clearAccumulatorForDvm, N as createDVMServer, O as creditDepositPayload, Q as derivedFundCreditId, W as devModeSkipsPaymentVerification, Y as fromJobRecord, Z as fundedMicroFor, _ as hasPaymentProof, $ as hashLockKey, a0 as implicitCreditId, a1 as initLockPubkeyTable, a2 as initWalletAccumulatorTable, a3 as insertAccumulatorRows, a4 as isDerivedCreditId, a5 as isTerminal, a6 as isYieldMessage, a7 as issueUpfrontChallenges, a8 as loadLockPubkeyState, a9 as msatsToFiatMicro, aa as paymentErrorBody, ab as pinAskFiat, ac as priceFiatMicro, ad as processIncomingPayment, ae as providerMessage, af as pruneRetired, ag as repairX402ExactSettlementEffect, ah as resolveFxSnapshot, ai as resolvePriceFiat, aj as revenueReporterBannerState, ak as rotateLockPubkey, al as seedLockPubkeyState, am as toCreditTerms, an as toJobRecord, ao as unknownRouteNotFound, ap as verifyIncomingPayment, aq as verifyTempoSessionManagementCredential, ar as verifyUpfrontPayment, as as x402RequiredUsdcMicro, at as x402SettledShare } from '../credit-menu-VwX_6KM7.js';
9
+ import { C as ConsumedCredentialStore, L as LockPubkeyStateLoader } from '../credit-menu-BWsVqMh-.js';
10
+ export { A as AccumulatorPool, a as AppEnv, b as CreditFundingReport, D as DEFAULT_LOCK_PUBKEY_GRACE_SECONDS, F as FiatDenomination, c as FiatDenominationFailure, d as FundOnlyRequest, I as IncomingPaymentOpts, J as JobCancelledError, e as LockPubkeyPool, f as LockPubkeyState, M as MintHealthTracker, P as PAYMENT_PROOF_KEYS, g as PaymentErrorCode, h as PaymentErrorDetail, i as PaymentInfo, j as PostgresTempoChargeStore, R as ReporterBannerOpts, k as ResolvedFx, l as RevenueBootCheckOpts, S as SDKServerOpts, m as ServerJob, n as ShortPayForfeit, T as TempoChannelReport, o as TempoObserverHealth, p as TempoSessionChannelMismatchError, U as UpfrontPaymentOpts, V as VerifiedIncomingPayment, q as VerifyIncomingSnapshot, X as X402BatchChannelObservation, r as X402FacilitatorHealth, s as X402SettlementEvidenceOutcome, t as X402SettlementRepair, u as X402SettlementRepairRefusal, v as X402SettlementRepaired, w as X402WedgedSettlement, x as X402WedgedSettlementPage, y as X402_BATCH_SETTLEMENT_MAINNET_NETWORK, z as abortJob, B as activePubkeySet, E as applyPaymentInfoToJob, G as assertRevenueReporterReady, H as buildPaymentErrorResponse, K as clearAccumulatorForDvm, N as createDVMServer, O as creditDepositPayload, Q as derivedFundCreditId, W as devModeSkipsPaymentVerification, Y as fromJobRecord, Z as fundedMicroFor, _ as hasPaymentProof, $ as hashLockKey, a0 as implicitCreditId, a1 as initLockPubkeyTable, a2 as initWalletAccumulatorTable, a3 as insertAccumulatorRows, a4 as isDerivedCreditId, a5 as isTerminal, a6 as isYieldMessage, a7 as issueUpfrontChallenges, a8 as loadLockPubkeyState, a9 as msatsToFiatMicro, aa as paymentErrorBody, ab as pinAskFiat, ac as priceFiatMicro, ad as processIncomingPayment, ae as providerMessage, af as pruneRetired, ag as repairX402ExactSettlementEffect, ah as resolveFxSnapshot, ai as resolvePriceFiat, aj as revenueReporterBannerState, ak as rotateLockPubkey, al as seedLockPubkeyState, am as toCreditTerms, an as toJobRecord, ao as unknownRouteNotFound, ap as verifyIncomingPayment, aq as verifyTempoSessionManagementCredential, ar as verifyUpfrontPayment, as as x402RequiredUsdcMicro, at as x402SettledShare } from '../credit-menu-BWsVqMh-.js';
11
11
  export { O as OutgoingMessage, S as StaleJobReapable, i as isStaleJobReapable } from '../job-store-92v8e1LQ.js';
12
12
  import { z } from 'zod';
13
13
  export { f as LockPubkeyStoreLockPubkey, t as lockPubkeyStoreToLockPubkey } from '../lightning-backend-9oky_wJi.js';
@@ -61,7 +61,7 @@ import {
61
61
  verifyUpfrontPayment,
62
62
  x402RequiredUsdcMicro,
63
63
  x402SettledShare
64
- } from "../chunk-QNKK7SPY.js";
64
+ } from "../chunk-SYBFMHXQ.js";
65
65
  import "../chunk-XRLKGCAW.js";
66
66
  import {
67
67
  PayoutReporter
@@ -71,7 +71,7 @@ import {
71
71
  verifyWithFacilitator
72
72
  } from "../chunk-VTHYQCDB.js";
73
73
  import "../chunk-YOSZIWC3.js";
74
- import "../chunk-Y6DO5WSO.js";
74
+ import "../chunk-2OGBZPPJ.js";
75
75
  import "../chunk-YG7G4DPZ.js";
76
76
  import {
77
77
  SIGNED_ENVELOPE_FIELDS,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  PostgresJobStore
3
- } from "./chunk-Y6DO5WSO.js";
3
+ } from "./chunk-2OGBZPPJ.js";
4
4
  import "./chunk-AFV77S4C.js";
5
5
  import "./chunk-BQJIFRAZ.js";
6
6
  import "./chunk-COYKJRMM.js";
@@ -1,8 +1,8 @@
1
1
  import { ae as CashuMode, bL as CreditLedgerQuerier, bM as CreditDrainEnqueue, bN as HostedSettlementReportObligations, R as ResolvedCreditConfig, bO as DVMAuthScheme, B as SignedRequestDomain, bP as CreditLedgerLike, bQ as X402RefundSettlementGate, bR as CreditSnapshot, bS as DrawResult, bT as X402SettlementStatus, bU as X402UnresolvedRefund, bV as GrownDrawResult, bW as DrawResolution, bX as FundingRecord, $ as FundingReceipt, bY as CreditInvoiceRecord, bZ as InvoiceSettlement, b_ as BlockedInvoiceCursor, b$ as InvoiceReconciliation, c0 as InvoiceWriteOff, c1 as DrawRecord, c2 as StalePendingDrawCursor, c3 as TempoCreditLossEvidence, c4 as TempoCreditLoss, c5 as X402CreditLossEvidence, c6 as X402CreditLoss, c7 as DrainMethod, c8 as DrainRequestResult, c9 as BitcoinDepositLiability, bp as FundingLot, ca as CreditDrainRecord, cb as ChannelDrainCursor, cc as DrainWriteOff, cd as DrainTransitionResult, ce as DrainReleaseResult, cf as DrainFulfilment, cg as HostingCleanupFence, a0 as JobReceipt, a5 as Message, K as KVStore, G as SignedRequestReplayStore, Z as ZodLike, a as DVMDescriptor } from '../step-cache--7yA5Ihr.js';
2
2
  export { ch as CLIENT_COMPATIBILITY_HEADERS, d as CanonicalEnvelope, ci as ClientCompatibility, cj as ClientCompatibilityEnv, ck as ClientCompatibilityGate, cl as ClientCompatibilityRequirement, cm as ClientSemVer, f as CreateSignedRequestVerifierOpts, cn as CreditFundingBasis, co as CreditInvoiceStatus, cp as CreditLedger, cq as CreditLedgerError, cr as CreditLedgerErrorCode, cs as CreditLedgerErrorDetails, ct as CreditLedgerPool, cu as CreditStatus, cv as DRAIN_DELIVERY_RESERVE_SATS, cw as DVM_PROTOCOL_VERSION, cx as DrainConflictReason, cy as DrawRailValue, cz as DrawStatus, cA as HostedTempoCloseReportWriteOff, cB as JobCostReportPayload, cC as JobTerminalReportPayload, cD as PostgresX402ChannelStorage, cE as ReplayStoreBackend, cF as RevenueSkippedNoRailPayload, cG as RevenueSkippedNoRailReason, x as SIGNED_REQUEST_AUTH_ID, y as SIGNED_REQUEST_STATEMENT_VERSION, cH as Secp256k1AuthOpts, z as SignedRequestAudience, E as SignedRequestError, F as SignedRequestFailure, H as SignedRequestSignOpts, M as SignedRequestStatementHeader, N as SignedRequestVerifier, cI as X402ChannelStorageOpts, cJ as X402RelayLockHolder, cK as X402RelaySubmissionLock, cL as X402RelaySubmissionLockError, cM as allocateDrawValue, cN as clientCompatibilityAttributes, cO as clientCompatibilityMiddleware, cP as clientUpgradeRequired, O as createSignedRequestVerifier, cQ as parseClientCapabilities, cR as parseClientCompatibility, cS as parseDvmClient, cT as parseProtocolVersion, cU as requireClientCompatibility, cV as retryHostedTempoCloseReport, cW as secp256k1Auth, cX as signedRequestInput, V as signedRequestStatementHeader, cY as writeOffHostedTempoCloseReport } from '../step-cache--7yA5Ihr.js';
3
3
  import { Pool } from 'pg';
4
- import { au as CreditMenu, a as AppEnv, U as UpfrontPaymentOpts, i as PaymentInfo, av as ReceiptIssuer, aw as LightningReceive, ax as TempoSettlementReadiness, ay as DVMHostOpts, az as DVMServeResult, L as LockPubkeyStateLoader, C as ConsumedCredentialStore } from '../credit-menu-VwX_6KM7.js';
5
- export { aA as BuildCreditMenuArgs, aB as BuilderIdentity, aC as CREDIT_ENVELOPE_KEYS, aD as CreateX402BatchSettlementServerOpts, aE as CreditEnvelope, aF as CreditEnvelopeError, aG as CreditFundCommitment, aH as CreditTerms, aI as DEFAULT_INVOICE_TTL_SECONDS, aJ as DVMHost, aK as HostingClosureCommand, aL as HostingClosureEvidence, aM as HostingControlCommand, aN as HostingControlConfig, aO as HostingControlStatus, aP as JobManager, aQ as JobManagerOpts, aR as LightningReceiveConfig, aS as MIN_INVOICE_TTL_SECONDS, aT as MemoryConsumedCredentialStore, aU as MemoryConsumedCredentialStoreOpts, aV as MemoryProcessedPaymentStore, aW as MemoryX402ExactSettlementStore, aX as MountOpts, aY as OwnerDisplay, aZ as PaidJobCompletion, a_ as PaymentMode, a$ as PlatformReporterOpts, b0 as PostgresProcessedPaymentStore, b1 as PostgresX402ExactSettlementStore, b2 as PriceFiat, b3 as ProcessedPaymentQuerier, b4 as ProcessedPaymentRail, b5 as ProcessedPaymentRecord, b6 as ProcessedPaymentReplayError, b7 as ProcessedPaymentStore, b8 as X402BatchAcceptance, b9 as X402BatchFunding, ba as X402BatchRefusal, bb as X402BatchSettlementServer, bc as X402ExactAcceptance, bd as X402ExactIntentConflictError, be as X402ExactSettlementAttempt, bf as X402ExactSettlementChainEvidence, bg as X402ExactSettlementEffect, bh as X402ExactSettlementEvidenceMissingError, bi as X402ExactSettlementEvidenceReader, bj as X402ExactSettlementIntent, bk as X402ExactSettlementNotReadyError, bl as X402ExactSettlementServer, bm as X402ExactSettlementServerOpts, bn as X402ExactSettlementStatus, bo as X402ExactSettlementStore, bp as X402SettlementChainEvidence, bq as X402SettlementEvidenceReader, br as X402SettlementSubmissionError, bs as X402_BATCH_AUTO_SETTLEMENT, bt as X402_BATCH_MIN_WITHDRAW_DELAY_SECONDS, bu as X402_BATCH_SETTLEMENT_NETWORK, bv as attachCreditMenu, bw as buildCreditMenu, bx as createDVMHost, by as createX402BatchSettlementServer, bz as creditEnvelopeIgnoreFields, bA as drawSettlementRef, bB as extractCreditEnvelope, bC as fundingCommitment, bD as selectPrimaryCredit, bE as signHostingClosure, bF as signHostingControl, bG as stripCreditEnvelope, bH as toCreditView } from '../credit-menu-VwX_6KM7.js';
4
+ import { au as CreditMenu, a as AppEnv, U as UpfrontPaymentOpts, i as PaymentInfo, av as ReceiptIssuer, aw as LightningReceive, ax as TempoSettlementReadiness, ay as DVMHostOpts, az as DVMServeResult, L as LockPubkeyStateLoader, C as ConsumedCredentialStore } from '../credit-menu-BWsVqMh-.js';
5
+ export { aA as BuildCreditMenuArgs, aB as BuilderIdentity, aC as CREDIT_ENVELOPE_KEYS, aD as CreateX402BatchSettlementServerOpts, aE as CreditEnvelope, aF as CreditEnvelopeError, aG as CreditFundCommitment, aH as CreditTerms, aI as DEFAULT_INVOICE_TTL_SECONDS, aJ as DVMHost, aK as HostingClosureCommand, aL as HostingClosureEvidence, aM as HostingControlCommand, aN as HostingControlConfig, aO as HostingControlStatus, aP as JobManager, aQ as JobManagerOpts, aR as LightningReceiveConfig, aS as MIN_INVOICE_TTL_SECONDS, aT as MemoryConsumedCredentialStore, aU as MemoryConsumedCredentialStoreOpts, aV as MemoryProcessedPaymentStore, aW as MemoryX402ExactSettlementStore, aX as MountOpts, aY as OwnerDisplay, aZ as PaidJobCompletion, a_ as PaymentMode, a$ as PlatformReporterOpts, b0 as PostgresProcessedPaymentStore, b1 as PostgresX402ExactSettlementStore, b2 as PriceFiat, b3 as ProcessedPaymentQuerier, b4 as ProcessedPaymentRail, b5 as ProcessedPaymentRecord, b6 as ProcessedPaymentReplayError, b7 as ProcessedPaymentStore, b8 as X402BatchAcceptance, b9 as X402BatchFunding, ba as X402BatchRefusal, bb as X402BatchSettlementServer, bc as X402ExactAcceptance, bd as X402ExactIntentConflictError, be as X402ExactSettlementAttempt, bf as X402ExactSettlementChainEvidence, bg as X402ExactSettlementEffect, bh as X402ExactSettlementEvidenceMissingError, bi as X402ExactSettlementEvidenceReader, bj as X402ExactSettlementIntent, bk as X402ExactSettlementNotReadyError, bl as X402ExactSettlementServer, bm as X402ExactSettlementServerOpts, bn as X402ExactSettlementStatus, bo as X402ExactSettlementStore, bp as X402SettlementChainEvidence, bq as X402SettlementEvidenceReader, br as X402SettlementSubmissionError, bs as X402_BATCH_AUTO_SETTLEMENT, bt as X402_BATCH_MIN_WITHDRAW_DELAY_SECONDS, bu as X402_BATCH_SETTLEMENT_NETWORK, bv as attachCreditMenu, bw as buildCreditMenu, bx as createDVMHost, by as createX402BatchSettlementServer, bz as creditEnvelopeIgnoreFields, bA as drawSettlementRef, bB as extractCreditEnvelope, bC as fundingCommitment, bD as selectPrimaryCredit, bE as signHostingClosure, bF as signHostingControl, bG as stripCreditEnvelope, bH as toCreditView } from '../credit-menu-BWsVqMh-.js';
6
6
  import { Context, Hono } from 'hono';
7
7
  import { z } from 'zod';
8
8
  import { F as FxFetcher } from '../fx-BM5h4o5S.js';
@@ -403,6 +403,7 @@ declare class PostgresJobStore implements StreamableJobStore, ReceiptIssuingStor
403
403
  save(record: JobRecord): Promise<void>;
404
404
  /** Persist a job while retaining its mount identity for cost-report recovery. */
405
405
  saveForDvm(record: JobRecord, dvmId: string): Promise<void>;
406
+ private canRetrySnapshot;
406
407
  private saveRecord;
407
408
  /** Advance only after the reporter durably enqueued or deduplicated the event. */
408
409
  markTerminalReported(jobId: string): Promise<void>;
@@ -82,7 +82,7 @@ import {
82
82
  toCreditView,
83
83
  unknownRouteNotFound,
84
84
  writeOffHostedTempoCloseReport
85
- } from "../chunk-QNKK7SPY.js";
85
+ } from "../chunk-SYBFMHXQ.js";
86
86
  import {
87
87
  MemoryProcessedPaymentStore,
88
88
  PostgresProcessedPaymentStore,
@@ -95,7 +95,7 @@ import {
95
95
  } from "../chunk-YOSZIWC3.js";
96
96
  import {
97
97
  PostgresJobStore
98
- } from "../chunk-Y6DO5WSO.js";
98
+ } from "../chunk-2OGBZPPJ.js";
99
99
  import "../chunk-YG7G4DPZ.js";
100
100
  import {
101
101
  SignedRequestError,
@@ -1188,7 +1188,7 @@ function createDVMHost(opts = {}) {
1188
1188
  });
1189
1189
  applyRetryToPool(pool, "dvm-host");
1190
1190
  pgPool = pool;
1191
- const { PostgresJobStore: PostgresJobStore2 } = await import("../postgres-job-store-FSRUPYH2.js");
1191
+ const { PostgresJobStore: PostgresJobStore2 } = await import("../postgres-job-store-H45PRBLA.js");
1192
1192
  const pgJobStore = new PostgresJobStore2(pool);
1193
1193
  pendingInits.push(pgJobStore.init(), pgJobStore.initStreaming());
1194
1194
  jobStore = pgJobStore;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dvmkit/sdk",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "description": "SDK for building Digital Vending Machines: pay-per-use HTTPS services AI agents can find, pay, and call with no account or API key",
5
5
  "author": "DVM Technologies Ltd",
6
6
  "keywords": [