@dvmkit/sdk 0.14.1 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-ITRSITFP.js → chunk-2I6NXIPG.js} +1 -1
- package/dist/{chunk-TKJBUFYY.js → chunk-33J3NQDZ.js} +1 -1
- package/dist/{chunk-7KQLPVV7.js → chunk-7NZRJPEP.js} +1 -1
- package/dist/{chunk-Z4FOPROB.js → chunk-BAHZK334.js} +2 -0
- package/dist/{chunk-D4FFS3IS.js → chunk-CRH6BMMG.js} +1 -1
- package/dist/{chunk-LDKV4UHI.js → chunk-CVT5LTAK.js} +1 -1
- package/dist/{chunk-EP7OVWI5.js → chunk-FOXGN4KQ.js} +1 -1
- package/dist/{chunk-VWIMQ5H5.js → chunk-G47UY3BK.js} +1 -1
- package/dist/{chunk-JLT2YIBS.js → chunk-GB2N4NG5.js} +2 -2
- package/dist/{chunk-E7ZBCT5U.js → chunk-I2H2XYQV.js} +1 -1
- package/dist/{chunk-3YFFZLW7.js → chunk-IUODXRQN.js} +2 -2
- package/dist/{chunk-566CFXGU.js → chunk-IVW5UMD3.js} +1 -1
- package/dist/{chunk-AFV77S4C.js → chunk-KVKJ7R5V.js} +81 -2
- package/dist/{chunk-A2YESDQM.js → chunk-LM6E4YHQ.js} +2 -2
- package/dist/{chunk-5JSPTVIK.js → chunk-LZFZGY7L.js} +1 -1
- package/dist/{chunk-FFRTAQUW.js → chunk-P5KQKLWL.js} +1 -1
- package/dist/{chunk-KJZVTWMX.js → chunk-PKLNMMKF.js} +52 -15
- package/dist/{chunk-M4NFYEEY.js → chunk-QRYGBKCR.js} +1 -1
- package/dist/{chunk-HNXMWHLU.js → chunk-R7FH7SHX.js} +1 -1
- package/dist/{chunk-NS2OMIU7.js → chunk-RQK7OFJO.js} +1 -1
- package/dist/{chunk-TWKQFIOW.js → chunk-YMMCRQ2H.js} +84 -14
- package/dist/{chunk-JFH34P3M.js → chunk-ZJRGORJ3.js} +359 -169
- package/dist/{chunk-HULU2UVM.js → chunk-ZO2ZAPG3.js} +1 -1
- package/dist/{content-retention-BcHNpP2F.d.ts → content-retention-BASsjgKw.d.ts} +1 -1
- package/dist/{credit-ledger-D3UUR2GW.js → credit-ledger-EZDZYLSK.js} +3 -3
- package/dist/{credit-menu-C-kmf61K.d.ts → credit-menu-B239nIY5.d.ts} +23 -9
- package/dist/{fx-hFlF4Cn8.d.ts → fx-BmvWGISH.d.ts} +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.js +12 -5
- package/dist/internal/caller.d.ts +11 -7
- package/dist/internal/caller.js +7 -7
- package/dist/internal/server.d.ts +7 -7
- package/dist/internal/server.js +21 -21
- package/dist/{job-store-DVCATwhU.d.ts → job-store-CA7u1nHV.d.ts} +22 -4
- package/dist/{lightning-backend-DXNVlVs9.d.ts → lightning-backend-BOcopzXk.d.ts} +1 -1
- package/dist/{memory-credit-ledger-SCXQO4HZ.js → memory-credit-ledger-REZGHPJP.js} +4 -4
- package/dist/{mpp-setup-JU3MT7QX.js → mpp-setup-RG5JDMIO.js} +3 -3
- package/dist/{payout-reporter-NXWQVKXW.js → payout-reporter-DDQ7FGRC.js} +2 -2
- package/dist/{postgres-consumed-credential-store-WXJLM6J7.js → postgres-consumed-credential-store-I4WTNVQZ.js} +1 -1
- package/dist/{postgres-job-store-ZVMAN6L2.js → postgres-job-store-IXTNWT4K.js} +3 -3
- package/dist/{postgres-replay-store-QJ4FG6AR.js → postgres-replay-store-3F5FCUXN.js} +2 -2
- package/dist/{pricing-KCLENT2C.js → pricing-HLYEGPXD.js} +3 -3
- package/dist/{revenue-reporter-HD4GMXGD.js → revenue-reporter-RIEHBKRA.js} +2 -2
- package/dist/server/index.d.ts +15 -12
- package/dist/server/index.js +28 -28
- package/dist/{step-cache-CoORQQ_Y.d.ts → step-cache-BCRHimiY.d.ts} +48 -9
- package/dist/{tempo-charge-store-7LTUAQHQ.js → tempo-charge-store-B5SYDCBK.js} +2 -2
- package/dist/{tempo-session-store-LYAIDR2B.js → tempo-session-store-FHW7N22I.js} +3 -3
- package/dist/testing/index.d.ts +7 -4
- package/dist/testing/index.js +7 -7
- package/dist/{usd-CeXGiyTC.d.ts → usd-B8_WMfHT.d.ts} +1 -1
- package/dist/{x402-RUJ4LUKF.js → x402-AY6P5KV4.js} +3 -3
- package/package.json +1 -1
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ContentHoldError,
|
|
3
|
-
applyContentHoldMutation
|
|
4
|
-
|
|
3
|
+
applyContentHoldMutation,
|
|
4
|
+
callerDeadline,
|
|
5
|
+
hasCallerDeadline
|
|
6
|
+
} from "./chunk-KVKJ7R5V.js";
|
|
5
7
|
import {
|
|
6
8
|
withSdkInitLock
|
|
7
9
|
} from "./chunk-COYKJRMM.js";
|
|
8
10
|
import {
|
|
9
11
|
diagnosticConsole
|
|
10
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-BAHZK334.js";
|
|
11
13
|
|
|
12
14
|
// src/sdk/server/postgres-job-store.ts
|
|
13
15
|
import { createHash } from "crypto";
|
|
@@ -261,6 +263,7 @@ var PostgresJobStore = class {
|
|
|
261
263
|
-- with a fund-and-draw response. INSERT-only for replay stability.
|
|
262
264
|
ALTER TABLE jobs ADD COLUMN IF NOT EXISTS funding_receipt JSONB;
|
|
263
265
|
ALTER TABLE jobs ADD COLUMN IF NOT EXISTS funding_credit JSONB;
|
|
266
|
+
ALTER TABLE jobs ADD COLUMN IF NOT EXISTS upfront_payment JSONB;
|
|
264
267
|
-- the outstanding mid-job ask, denominated in fiat micro at the
|
|
265
268
|
-- instant it was emitted. The top-up's ledger leg funds and grows the
|
|
266
269
|
-- draw in this figure, so it must not move with the BTC/USD rate between
|
|
@@ -490,6 +493,18 @@ var PostgresJobStore = class {
|
|
|
490
493
|
}
|
|
491
494
|
held.client.release();
|
|
492
495
|
}
|
|
496
|
+
async saveStep(jobId, record) {
|
|
497
|
+
const result = await this.pool.query(
|
|
498
|
+
`UPDATE jobs SET step_cache = CASE
|
|
499
|
+
WHEN EXISTS (SELECT 1 FROM jsonb_array_elements(step_cache) AS step
|
|
500
|
+
WHERE step->>'id' = $2::jsonb->>'id') THEN step_cache
|
|
501
|
+
ELSE step_cache || jsonb_build_array($2::jsonb) END
|
|
502
|
+
WHERE id = $1 AND status NOT IN ('completed', 'failed', 'cancelled')
|
|
503
|
+
AND redacted_at IS NULL`,
|
|
504
|
+
[jobId, JSON.stringify(record)]
|
|
505
|
+
);
|
|
506
|
+
if (result.rowCount !== 1) throw new Error("Step persistence requires a live job");
|
|
507
|
+
}
|
|
493
508
|
async save(record) {
|
|
494
509
|
const dvmId = record[JOB_DVM_ID];
|
|
495
510
|
for (let attempt = 0; ; attempt++) {
|
|
@@ -536,8 +551,8 @@ var PostgresJobStore = class {
|
|
|
536
551
|
last_activity_at, next_seq, requester_token_hash, requester_token,
|
|
537
552
|
request_fingerprint, requester_pubkey, request_id, credit_id, draw_id,
|
|
538
553
|
pending_payment_fiat_micro, pending_payment_fiat_currency, auth_request_path,
|
|
539
|
-
funding_receipt, funding_credit, dvm_id, terminal_at_ms, caller_wait_ms, awaiting_input_at_ms, ended_by, timing_known
|
|
540
|
-
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39,$40,$41,$42,$43,$44,$45,$46,$47,$48,$49,$51)
|
|
554
|
+
funding_receipt, funding_credit, dvm_id, terminal_at_ms, caller_wait_ms, awaiting_input_at_ms, ended_by, timing_known, upfront_payment
|
|
555
|
+
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39,$40,$41,$42,$43,$44,$45,$46,$47,$48,$49,$51,$52)
|
|
541
556
|
ON CONFLICT (id) DO UPDATE SET
|
|
542
557
|
terminal_at_ms = COALESCE(jobs.terminal_at_ms, EXCLUDED.terminal_at_ms),
|
|
543
558
|
ended_by = CASE WHEN jobs.status IN ('completed', 'failed', 'cancelled') THEN jobs.ended_by ELSE EXCLUDED.ended_by END,
|
|
@@ -588,7 +603,17 @@ var PostgresJobStore = class {
|
|
|
588
603
|
pending_x402_nonce = EXCLUDED.pending_x402_nonce,
|
|
589
604
|
pending_x402_amount_usdc_micro = EXCLUDED.pending_x402_amount_usdc_micro,
|
|
590
605
|
required_msats = EXCLUDED.required_msats,
|
|
591
|
-
|
|
606
|
+
-- A stale snapshot must not erase a step committed by saveStep.
|
|
607
|
+
-- First stored result wins for each id, matching cached replay.
|
|
608
|
+
step_cache = (
|
|
609
|
+
SELECT COALESCE(jsonb_agg(entry ORDER BY position), '[]'::jsonb)
|
|
610
|
+
FROM (
|
|
611
|
+
SELECT DISTINCT ON (entry->>'id') entry, position
|
|
612
|
+
FROM jsonb_array_elements(jobs.step_cache || EXCLUDED.step_cache)
|
|
613
|
+
WITH ORDINALITY AS steps(entry, position)
|
|
614
|
+
ORDER BY entry->>'id', position
|
|
615
|
+
) AS merged_steps
|
|
616
|
+
),
|
|
592
617
|
state = EXCLUDED.state,
|
|
593
618
|
last_activity_at = CASE WHEN jobs.status IN ('completed', 'failed', 'cancelled') THEN jobs.last_activity_at ELSE EXCLUDED.last_activity_at END
|
|
594
619
|
-- terminal is terminal. On a multi-machine DVM a DELETE can
|
|
@@ -666,7 +691,8 @@ var PostgresJobStore = class {
|
|
|
666
691
|
record.status === "awaiting-input" ? record.awaitingInputAtMs ?? now : null,
|
|
667
692
|
isTerminalStatus(record.status) && record.status !== "completed" ? record.endedBy ?? "provider" : null,
|
|
668
693
|
now,
|
|
669
|
-
record.timingKnown ?? true
|
|
694
|
+
record.timingKnown ?? true,
|
|
695
|
+
record.upfrontPayment ? JSON.stringify(record.upfrontPayment) : null
|
|
670
696
|
]
|
|
671
697
|
);
|
|
672
698
|
let rowCount;
|
|
@@ -705,6 +731,7 @@ var PostgresJobStore = class {
|
|
|
705
731
|
return;
|
|
706
732
|
}
|
|
707
733
|
if (record.status === "completed" || record.status === "failed" || record.status === "cancelled") {
|
|
734
|
+
await this.pool.query("SELECT pg_notify('job_messages', $1)", [record.id]).catch(() => void 0);
|
|
708
735
|
await this.deleteResolvedMessages(record.id).catch(() => void 0);
|
|
709
736
|
}
|
|
710
737
|
}
|
|
@@ -1173,7 +1200,11 @@ var PostgresJobStore = class {
|
|
|
1173
1200
|
}
|
|
1174
1201
|
async markInboundFailed(jobId, seq, _reason) {
|
|
1175
1202
|
await this.pool.query(
|
|
1176
|
-
|
|
1203
|
+
`WITH failed AS (
|
|
1204
|
+
UPDATE job_messages SET status='failed-verify'
|
|
1205
|
+
WHERE job_id = $1 AND seq = $2 AND status = 'pending-verification'
|
|
1206
|
+
RETURNING job_id
|
|
1207
|
+
) SELECT pg_notify('job_messages', job_id) FROM failed`,
|
|
1177
1208
|
[jobId, seq]
|
|
1178
1209
|
);
|
|
1179
1210
|
}
|
|
@@ -1292,10 +1323,24 @@ var PostgresJobStore = class {
|
|
|
1292
1323
|
if (subSet.size === 0) this.notifySubscribers.delete(jobId);
|
|
1293
1324
|
});
|
|
1294
1325
|
}
|
|
1295
|
-
async getMessages(jobId, afterSeq) {
|
|
1326
|
+
async getMessages(jobId, afterSeq, options) {
|
|
1296
1327
|
const { rows } = await this.pool.query(
|
|
1297
|
-
|
|
1298
|
-
|
|
1328
|
+
`WITH terminal AS (
|
|
1329
|
+
SELECT messages FROM jobs WHERE id = $1 AND status IN ('completed', 'failed', 'cancelled')
|
|
1330
|
+
), history AS (
|
|
1331
|
+
SELECT seq, data, 0 AS origin FROM job_messages
|
|
1332
|
+
WHERE job_id = $1 AND seq > $2 AND status = 'verified'
|
|
1333
|
+
AND ($3::boolean OR EXISTS (SELECT 1 FROM terminal)
|
|
1334
|
+
OR EXISTS (SELECT 1 FROM job_messages WHERE job_id = $1 AND status = 'verified'
|
|
1335
|
+
AND data->>'from' = 'provider' AND data->>'type' IN ('complete', 'cancel'))
|
|
1336
|
+
OR seq < COALESCE((SELECT MIN(seq) FROM job_messages
|
|
1337
|
+
WHERE job_id = $1 AND status = 'pending-verification' AND data->>'type' = 'payment'), 9223372036854775807))
|
|
1338
|
+
UNION ALL
|
|
1339
|
+
SELECT (message->>'seq')::bigint, message, 1 AS origin
|
|
1340
|
+
FROM terminal CROSS JOIN LATERAL jsonb_array_elements(terminal.messages) AS snapshot(message)
|
|
1341
|
+
WHERE (message->>'seq')::bigint > $2
|
|
1342
|
+
) SELECT DISTINCT ON (seq) data FROM history ORDER BY seq, origin`,
|
|
1343
|
+
[jobId, afterSeq, options?.includeHeld ?? false]
|
|
1299
1344
|
);
|
|
1300
1345
|
return rows.map((r) => typeof r.data === "string" ? JSON.parse(r.data) : r.data);
|
|
1301
1346
|
}
|
|
@@ -1373,7 +1418,7 @@ var PostgresJobStore = class {
|
|
|
1373
1418
|
try {
|
|
1374
1419
|
await client.query("BEGIN");
|
|
1375
1420
|
const { rows } = await client.query(
|
|
1376
|
-
`SELECT
|
|
1421
|
+
`SELECT * FROM jobs
|
|
1377
1422
|
WHERE id = $1
|
|
1378
1423
|
AND status IN ('processing', 'working', 'awaiting-input')
|
|
1379
1424
|
${staleOnly ? "AND last_activity_at <= $2" : ""}
|
|
@@ -1384,6 +1429,22 @@ var PostgresJobStore = class {
|
|
|
1384
1429
|
await client.query("ROLLBACK");
|
|
1385
1430
|
return false;
|
|
1386
1431
|
}
|
|
1432
|
+
let terminalMessages;
|
|
1433
|
+
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);
|
|
1443
|
+
if (terminalStatus === "cancelled" !== awaiting || deadline !== void 0 && Date.now() < deadline) {
|
|
1444
|
+
await client.query("ROLLBACK");
|
|
1445
|
+
return false;
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1387
1448
|
const nextSeq = rows[0].next_seq;
|
|
1388
1449
|
const now = Date.now();
|
|
1389
1450
|
const cancelMsg = {
|
|
@@ -1406,12 +1467,20 @@ var PostgresJobStore = class {
|
|
|
1406
1467
|
awaiting_input_at_ms = NULL,
|
|
1407
1468
|
status = $6,
|
|
1408
1469
|
summary = COALESCE(summary, $2),
|
|
1409
|
-
messages = COALESCE(messages, '[]'::jsonb) || $3::jsonb,
|
|
1470
|
+
messages = ${staleOnly ? "$3::jsonb" : "COALESCE(messages, '[]'::jsonb) || $3::jsonb"},
|
|
1410
1471
|
seq = $4,
|
|
1411
1472
|
next_seq = $4 + 1,
|
|
1412
1473
|
last_activity_at = $5
|
|
1413
1474
|
WHERE id = $1`,
|
|
1414
|
-
[
|
|
1475
|
+
[
|
|
1476
|
+
jobId,
|
|
1477
|
+
reason,
|
|
1478
|
+
JSON.stringify([...terminalMessages ?? [], cancelMsg]),
|
|
1479
|
+
nextSeq,
|
|
1480
|
+
now,
|
|
1481
|
+
terminalStatus,
|
|
1482
|
+
staleOnly ? terminalStatus === "cancelled" ? "caller" : "provider" : endedBy
|
|
1483
|
+
]
|
|
1415
1484
|
);
|
|
1416
1485
|
await client.query("SELECT pg_notify('job_messages', $1)", [jobId]);
|
|
1417
1486
|
await client.query("COMMIT");
|
|
@@ -1499,6 +1568,7 @@ function rowToRecord(row) {
|
|
|
1499
1568
|
summary: row.summary,
|
|
1500
1569
|
messages: row.messages,
|
|
1501
1570
|
seq: row.seq,
|
|
1571
|
+
upfrontPayment: row.upfront_payment ?? void 0,
|
|
1502
1572
|
paidMsats: Number(row.paid_msats),
|
|
1503
1573
|
paymentMint: row.payment_mint,
|
|
1504
1574
|
paymentRail: row.payment_rail ?? void 0,
|