@astrosheep/square 0.4.4 → 0.4.6
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/artifact-store.d.ts +1 -1
- package/dist/artifact-store.js +32 -15
- package/dist/artifact.d.ts +1 -4
- package/dist/artifact.js +0 -28
- package/dist/attention-presentation.js +1 -1
- package/dist/boundary-presentation.js +2 -2
- package/dist/claude-boundary-state.d.ts +6 -6
- package/dist/claude-boundary-state.js +13 -13
- package/dist/claude-hook.js +25 -24
- package/dist/claude-mcp-context.d.ts +2 -2
- package/dist/claude-mcp-context.js +6 -6
- package/dist/cli/context.js +3 -6
- package/dist/cli/json.js +1 -1
- package/dist/cli/mcp-server-command.js +3 -3
- package/dist/cli/observation-commands.d.ts +2 -2
- package/dist/cli/observation-commands.js +23 -51
- package/dist/cli/perceive-presentation.d.ts +3 -0
- package/dist/cli/{catch-presentation.js → perceive-presentation.js} +3 -3
- package/dist/cli/registry.js +2 -2
- package/dist/codex-address.d.ts +3 -0
- package/dist/codex-address.js +7 -0
- package/dist/codex-hook.d.ts +1 -1
- package/dist/codex-hook.js +11 -8
- package/dist/codex-queue.d.ts +3 -2
- package/dist/codex-queue.js +8 -11
- package/dist/codex-watch.d.ts +6 -1
- package/dist/codex-watch.js +27 -29
- package/dist/delivery-ledger-sqlite.d.ts +25 -20
- package/dist/delivery-ledger-sqlite.js +76 -61
- package/dist/delivery-ledger.d.ts +24 -19
- package/dist/delivery-ledger.js +150 -81
- package/dist/delivery-lifetime.d.ts +2 -2
- package/dist/delivery-lifetime.js +6 -18
- package/dist/help.js +12 -12
- package/dist/hints.d.ts +2 -2
- package/dist/hints.js +7 -7
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/list.d.ts +2 -2
- package/dist/list.js +4 -3
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +8 -32
- package/dist/neutral.d.ts +5 -5
- package/dist/notifications.js +12 -6
- package/dist/operation-presentation.d.ts +8 -3
- package/dist/operation-presentation.js +50 -12
- package/dist/packages/agent-delivery/src/file-lock.js +4 -1
- package/dist/perceive-decisions.d.ts +28 -0
- package/dist/{catch-decisions.js → perceive-decisions.js} +24 -24
- package/dist/{catch-selection.d.ts → perceive-selection.d.ts} +2 -2
- package/dist/{catch-selection.js → perceive-selection.js} +3 -3
- package/dist/plugins/opencode/index.js +4 -4
- package/dist/plugins/opencode-shared/delivery.d.ts +6 -6
- package/dist/plugins/opencode-shared/delivery.js +27 -21
- package/dist/plugins/opencode-v1/runtime.js +3 -3
- package/dist/ports.d.ts +0 -4
- package/dist/presentation.d.ts +1 -1
- package/dist/presentation.js +13 -13
- package/dist/session-lifecycle.d.ts +2 -2
- package/dist/session-lifecycle.js +11 -11
- package/dist/sqlite-square.d.ts +2 -4
- package/dist/sqlite-square.js +47 -54
- package/dist/sqlite-transaction.d.ts +2 -0
- package/dist/sqlite-transaction.js +25 -3
- package/dist/square-api.d.ts +1 -1
- package/dist/square-api.js +1 -1
- package/dist/square-domain.js +1 -1
- package/dist/square-facade.d.ts +15 -13
- package/dist/square-location.js +1 -1
- package/dist/square-posting.d.ts +5 -5
- package/dist/square-posting.js +39 -38
- package/dist/square-tools.d.ts +15 -4
- package/dist/square-tools.js +35 -17
- package/dist/views.d.ts +7 -3
- package/dist/views.js +6 -3
- package/guides/architect.md +2 -2
- package/guides/change-waits.md +1 -1
- package/guides/codex-delivery.md +40 -35
- package/guides/delivery-primitives.md +22 -7
- package/guides/mcp.md +4 -2
- package/guides/operation-cancellation.md +11 -3
- package/guides/pi-native-delivery.md +1 -1
- package/guides/pi-tools.md +11 -6
- package/guides/receive-primitive.md +3 -3
- package/guides/square-api.md +15 -8
- package/package.json +2 -2
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/skills/square/SKILL.md +10 -10
- package/plugins/codex/.codex-plugin/plugin.json +2 -2
- package/plugins/codex/hooks/hooks.json +3 -0
- package/plugins/opencode/index.ts +4 -4
- package/plugins/opencode-shared/delivery.ts +27 -21
- package/plugins/opencode-v1/runtime.ts +3 -3
- package/plugins/paseo/client/markdown.tsx +9 -26
- package/plugins/paseo/client/square-message.tsx +10 -14
- package/plugins/pi/square-pi.js +100 -20
- package/skills/square/SKILL.md +10 -10
- package/dist/catch-decisions.d.ts +0 -28
- package/dist/cli/catch-presentation.d.ts +0 -3
- package/guides/mcp-connection-lifetime.md +0 -22
|
@@ -22,7 +22,7 @@ export const { DatabaseSync } = await (process.versions.bun
|
|
|
22
22
|
},
|
|
23
23
|
}))
|
|
24
24
|
: import('node:sqlite'));
|
|
25
|
-
import { inSqliteTransaction } from './sqlite-transaction.js';
|
|
25
|
+
import { inSqliteTransaction, retrySqliteBusy, awaitSqliteQueue } from './sqlite-transaction.js';
|
|
26
26
|
import { validateSchema } from './sqlite-framing.js';
|
|
27
27
|
const FORMAT = 3;
|
|
28
28
|
const APPLICATION_ID = 0x444c4752;
|
|
@@ -70,12 +70,16 @@ export class LedgerStore {
|
|
|
70
70
|
clock;
|
|
71
71
|
pending = Promise.resolve();
|
|
72
72
|
closed = false;
|
|
73
|
+
cancellation = new AbortController();
|
|
74
|
+
ordinaryCancellation = new AbortController();
|
|
75
|
+
closing;
|
|
73
76
|
constructor(location, db, clock) {
|
|
74
77
|
this.location = location;
|
|
75
78
|
this.db = db;
|
|
76
79
|
this.clock = clock;
|
|
77
80
|
}
|
|
78
|
-
static async open(location, clock) {
|
|
81
|
+
static async open(location, clock, signal) {
|
|
82
|
+
signal?.throwIfAborted();
|
|
79
83
|
try {
|
|
80
84
|
await fs.access(location);
|
|
81
85
|
}
|
|
@@ -87,14 +91,15 @@ export class LedgerStore {
|
|
|
87
91
|
let initial;
|
|
88
92
|
try {
|
|
89
93
|
await (await fs.open(temporary, 'wx', 0o600)).close();
|
|
90
|
-
initial = new DatabaseSync(temporary);
|
|
94
|
+
initial = await retrySqliteBusy(() => new DatabaseSync(temporary), signal);
|
|
91
95
|
await inSqliteTransaction(initial, true, () => undefined, () => {
|
|
92
96
|
initial.exec(SCHEMA);
|
|
93
97
|
initial.prepare('INSERT INTO meta VALUES(?,1)').run(FORMAT);
|
|
94
98
|
initial.exec(`PRAGMA application_id=${APPLICATION_ID}; PRAGMA user_version=${FORMAT}`);
|
|
95
|
-
});
|
|
99
|
+
}, signal);
|
|
96
100
|
initial.close();
|
|
97
101
|
initial = undefined;
|
|
102
|
+
signal?.throwIfAborted();
|
|
98
103
|
try {
|
|
99
104
|
await fs.link(temporary, location);
|
|
100
105
|
}
|
|
@@ -109,16 +114,16 @@ export class LedgerStore {
|
|
|
109
114
|
}
|
|
110
115
|
}
|
|
111
116
|
// Existing formats are inspected on a read-only connection before any writable open.
|
|
112
|
-
const probe = new DatabaseSync(location, { readOnly: true });
|
|
117
|
+
const probe = await retrySqliteBusy(() => new DatabaseSync(location, { readOnly: true }), signal);
|
|
113
118
|
try {
|
|
114
|
-
validate(probe, location);
|
|
119
|
+
await retrySqliteBusy(() => validate(probe, location), signal);
|
|
115
120
|
}
|
|
116
121
|
finally {
|
|
117
122
|
probe.close();
|
|
118
123
|
}
|
|
119
|
-
const db = new DatabaseSync(location);
|
|
124
|
+
const db = await retrySqliteBusy(() => new DatabaseSync(location), signal);
|
|
120
125
|
try {
|
|
121
|
-
validate(db, location);
|
|
126
|
+
await retrySqliteBusy(() => { validate(db, location); db.exec('PRAGMA busy_timeout=0; PRAGMA synchronous=FULL'); }, signal);
|
|
122
127
|
return new LedgerStore(location, db, clock);
|
|
123
128
|
}
|
|
124
129
|
catch (error) {
|
|
@@ -126,27 +131,37 @@ export class LedgerStore {
|
|
|
126
131
|
throw error;
|
|
127
132
|
}
|
|
128
133
|
}
|
|
134
|
+
/** Stop ordinary work while captured effects retain access to settlement. */
|
|
135
|
+
retire() { this.ordinaryCancellation.abort(new Error('Delivery ledger is closed')); }
|
|
129
136
|
close() {
|
|
137
|
+
this.retire();
|
|
130
138
|
this.closed = true;
|
|
131
|
-
|
|
139
|
+
this.cancellation.abort(new Error('Delivery ledger is closed'));
|
|
140
|
+
return this.closing ??= this.pending.then(() => this.db.close());
|
|
132
141
|
}
|
|
133
|
-
transaction(write, change, signal) {
|
|
134
|
-
if (this.closed)
|
|
142
|
+
transaction(write, change, signal, settlement = false) {
|
|
143
|
+
if (this.closed || !settlement && this.ordinaryCancellation.signal.aborted)
|
|
135
144
|
return Promise.reject(new Error('Delivery ledger is closed'));
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
signal = AbortSignal.any([this.cancellation.signal, ...(!settlement ? [this.ordinaryCancellation.signal] : []), ...(signal ? [signal] : [])]);
|
|
146
|
+
let started = false;
|
|
147
|
+
const result = this.pending.then(() => {
|
|
148
|
+
signal.throwIfAborted();
|
|
149
|
+
started = true;
|
|
150
|
+
return inSqliteTransaction(this.db, write, () => validate(this.db, this.location), () => {
|
|
151
|
+
const now = this.clock();
|
|
152
|
+
if (!Number.isFinite(now))
|
|
153
|
+
throw new TypeError('Expected finite ledger time');
|
|
154
|
+
const changes = Number(this.db.prepare('SELECT total_changes() AS n').get().n);
|
|
155
|
+
const result = change(now);
|
|
156
|
+
if (write && Number(this.db.prepare('SELECT total_changes() AS n').get().n) > changes) {
|
|
157
|
+
this.normalize(now);
|
|
158
|
+
this.gc(now);
|
|
159
|
+
}
|
|
160
|
+
return result;
|
|
161
|
+
}, signal);
|
|
162
|
+
});
|
|
148
163
|
this.pending = result.catch(() => undefined);
|
|
149
|
-
return result;
|
|
164
|
+
return awaitSqliteQueue(result, signal, () => started);
|
|
150
165
|
}
|
|
151
166
|
getSession(owner) {
|
|
152
167
|
return session(this.db.prepare('SELECT * FROM sessions WHERE owner=?').get(owner));
|
|
@@ -215,19 +230,19 @@ export class LedgerStore {
|
|
|
215
230
|
this.deleteCard(row.seq, now);
|
|
216
231
|
this.db.prepare('DELETE FROM receipts WHERE rowid IN (SELECT rowid FROM receipts WHERE at<? ORDER BY at LIMIT 100)').run(cutoff);
|
|
217
232
|
}
|
|
218
|
-
session(owner) { return this.transaction(false, () => this.getSession(owner)); }
|
|
219
|
-
sessions() {
|
|
220
|
-
return this.transaction(false, () => this.db.prepare('SELECT * FROM sessions ORDER BY owner').all().map(row => session(row)));
|
|
233
|
+
session(owner, signal) { return this.transaction(false, () => this.getSession(owner), signal); }
|
|
234
|
+
sessions(signal) {
|
|
235
|
+
return this.transaction(false, () => this.db.prepare('SELECT * FROM sessions ORDER BY owner').all().map(row => session(row)), signal);
|
|
221
236
|
}
|
|
222
|
-
pendingCards(owner, generation) {
|
|
237
|
+
pendingCards(owner, generation, signal) {
|
|
223
238
|
return this.transaction(false, now => this.attached(owner, generation)
|
|
224
|
-
? this.db.prepare('SELECT * FROM cards WHERE owner=? ORDER BY seq').all(owner).filter(row => this.eligible(row, now)).map(card) : []);
|
|
239
|
+
? this.db.prepare('SELECT * FROM cards WHERE owner=? ORDER BY seq').all(owner).filter(row => this.eligible(row, now)).map(card) : [], signal);
|
|
225
240
|
}
|
|
226
|
-
handoffs(owner, generation) {
|
|
241
|
+
handoffs(owner, generation, signal) {
|
|
227
242
|
return this.transaction(false, () => this.db.prepare(`SELECT a.* FROM attempts a JOIN cards c ON c.seq=a.seq
|
|
228
|
-
WHERE c.owner=? AND a.generation=? AND a.track='handoff' ORDER BY a.rowid`).all(owner, generation).map(attempt));
|
|
243
|
+
WHERE c.owner=? AND a.generation=? AND a.track='handoff' ORDER BY a.rowid`).all(owner, generation).map(attempt), signal);
|
|
229
244
|
}
|
|
230
|
-
attach(input) {
|
|
245
|
+
attach(input, signal) {
|
|
231
246
|
const encoded = JSON.stringify(input.routes);
|
|
232
247
|
return this.transaction(true, now => {
|
|
233
248
|
const previous = this.getSession(input.owner);
|
|
@@ -237,27 +252,27 @@ export class LedgerStore {
|
|
|
237
252
|
this.db.prepare(`INSERT INTO sessions VALUES(?,?,'attached',?,?) ON CONFLICT(owner)
|
|
238
253
|
DO UPDATE SET generation=excluded.generation,state=excluded.state,routes_json=excluded.routes_json,at=excluded.at`).run(input.owner, generation, encoded, now);
|
|
239
254
|
return this.getSession(input.owner);
|
|
240
|
-
});
|
|
255
|
+
}, signal);
|
|
241
256
|
}
|
|
242
|
-
updateRoutes(input) {
|
|
257
|
+
updateRoutes(input, signal) {
|
|
243
258
|
const encoded = JSON.stringify(input.routes);
|
|
244
259
|
return this.transaction(true, now => {
|
|
245
260
|
if (!this.attached(input.owner, input.generation))
|
|
246
261
|
return false;
|
|
247
262
|
this.db.prepare('UPDATE sessions SET routes_json=?,at=? WHERE owner=?').run(encoded, now, input.owner);
|
|
248
263
|
return true;
|
|
249
|
-
});
|
|
264
|
+
}, signal);
|
|
250
265
|
}
|
|
251
|
-
lifecycle(input, state) {
|
|
266
|
+
lifecycle(input, state, signal) {
|
|
252
267
|
return this.transaction(true, now => {
|
|
253
268
|
const s = this.getSession(input.owner);
|
|
254
269
|
if (!s || s.generation !== input.generation || s.state === 'deleted')
|
|
255
270
|
return false;
|
|
256
271
|
this.db.prepare('UPDATE sessions SET state=?,at=? WHERE owner=?').run(state, now, input.owner);
|
|
257
272
|
return true;
|
|
258
|
-
});
|
|
273
|
+
}, signal);
|
|
259
274
|
}
|
|
260
|
-
post(input) {
|
|
275
|
+
post(input, signal) {
|
|
261
276
|
return this.transaction(true, now => {
|
|
262
277
|
const s = this.getSession(input.owner);
|
|
263
278
|
if (!s)
|
|
@@ -279,9 +294,9 @@ export class LedgerStore {
|
|
|
279
294
|
this.db.prepare('UPDATE meta SET next_seq=?').run(seq + 1);
|
|
280
295
|
this.db.prepare('INSERT INTO cards VALUES(?,?,?,?,?,?)').run(seq, input.owner, input.key, input.text, input.details, now);
|
|
281
296
|
return { status: suppressed ? 'suppressed' : 'posted' };
|
|
282
|
-
});
|
|
297
|
+
}, signal);
|
|
283
298
|
}
|
|
284
|
-
suppress(input) {
|
|
299
|
+
suppress(input, signal) {
|
|
285
300
|
return this.transaction(true, now => {
|
|
286
301
|
const permanentId = input.scope === 'exact' && input.expiresAt === undefined
|
|
287
302
|
? this.db.prepare("SELECT id FROM suppressions WHERE owner=? AND key=? AND scope='exact' AND expires_at IS NULL").get(input.owner, input.key)?.id
|
|
@@ -298,22 +313,22 @@ export class LedgerStore {
|
|
|
298
313
|
this.deleteCard(row.seq);
|
|
299
314
|
}
|
|
300
315
|
return { id, status: inCustody ? 'in-custody' : 'suppressed' };
|
|
301
|
-
});
|
|
316
|
+
}, signal);
|
|
302
317
|
}
|
|
303
|
-
renewSuppression(input) {
|
|
304
|
-
return this.transaction(true, now => this.db.prepare('UPDATE suppressions SET expires_at=? WHERE owner=? AND id=? AND (expires_at IS NULL OR expires_at>?)').run(input.expiresAt, input.owner, input.id, now).changes > 0);
|
|
318
|
+
renewSuppression(input, signal) {
|
|
319
|
+
return this.transaction(true, now => this.db.prepare('UPDATE suppressions SET expires_at=? WHERE owner=? AND id=? AND (expires_at IS NULL OR expires_at>?)').run(input.expiresAt, input.owner, input.id, now).changes > 0, signal);
|
|
305
320
|
}
|
|
306
|
-
releaseSuppression(input) {
|
|
307
|
-
return this.transaction(true, () => this.db.prepare('DELETE FROM suppressions WHERE owner=? AND id=?').run(input.owner, input.id).changes > 0);
|
|
321
|
+
releaseSuppression(input, signal) {
|
|
322
|
+
return this.transaction(true, () => this.db.prepare('DELETE FROM suppressions WHERE owner=? AND id=?').run(input.owner, input.id).changes > 0, signal);
|
|
308
323
|
}
|
|
309
|
-
cancel(input) {
|
|
324
|
+
cancel(input, signal) {
|
|
310
325
|
return this.transaction(true, () => {
|
|
311
326
|
if (!this.attached(input.owner, input.generation))
|
|
312
327
|
return false;
|
|
313
328
|
this.db.prepare(`INSERT INTO cancellations VALUES(?,?,(SELECT next_seq-1 FROM meta))
|
|
314
329
|
ON CONFLICT(owner) DO UPDATE SET generation=excluded.generation,through_seq=MAX(through_seq,excluded.through_seq)`).run(input.owner, input.generation);
|
|
315
330
|
return true;
|
|
316
|
-
});
|
|
331
|
+
}, signal);
|
|
317
332
|
}
|
|
318
333
|
isSuppressed(owner, key, now) {
|
|
319
334
|
return !!this.db.prepare(`SELECT 1 FROM suppressions WHERE owner=? AND (expires_at IS NULL OR expires_at>?)
|
|
@@ -413,7 +428,7 @@ export class LedgerStore {
|
|
|
413
428
|
this.receipt(handoff.seq, now);
|
|
414
429
|
return true;
|
|
415
430
|
}
|
|
416
|
-
settle(tokens, outcome) {
|
|
431
|
+
settle(tokens, outcome, signal) {
|
|
417
432
|
return this.transaction(true, now => {
|
|
418
433
|
const attempts = tokens.map(token => this.getAttempt(token));
|
|
419
434
|
if (attempts.some(a => !a || a.track === 'presentation' && outcome === 'accepted'
|
|
@@ -440,7 +455,7 @@ export class LedgerStore {
|
|
|
440
455
|
}
|
|
441
456
|
}
|
|
442
457
|
return true;
|
|
443
|
-
});
|
|
458
|
+
}, signal, true);
|
|
444
459
|
}
|
|
445
460
|
handoffFacts(token) {
|
|
446
461
|
const a = this.getAttempt(token);
|
|
@@ -463,16 +478,16 @@ export class LedgerStore {
|
|
|
463
478
|
const s = this.attached(facts.ref.owner, facts.ref.generation);
|
|
464
479
|
return facts.attempt.expiresAt > now && !!s && s.routes.some(route => route.kind === facts.ref.routeKind) && this.eligible(facts.row, now);
|
|
465
480
|
}
|
|
466
|
-
handoff(token) {
|
|
467
|
-
return this.transaction(false, () => this.handoffFacts(token)?.ref);
|
|
481
|
+
handoff(token, signal) {
|
|
482
|
+
return this.transaction(false, () => this.handoffFacts(token)?.ref, signal);
|
|
468
483
|
}
|
|
469
|
-
guardHandoff(ref) {
|
|
484
|
+
guardHandoff(ref, signal) {
|
|
470
485
|
return this.transaction(false, now => {
|
|
471
486
|
const facts = this.matchingHandoff(ref);
|
|
472
487
|
return !!facts && ['dispatching', 'unknown'].includes(facts.attempt.outcome) && this.currentHandoff(facts, now);
|
|
473
|
-
});
|
|
488
|
+
}, signal);
|
|
474
489
|
}
|
|
475
|
-
acceptHandoff(ref) {
|
|
490
|
+
acceptHandoff(ref, signal) {
|
|
476
491
|
return this.transaction(true, now => {
|
|
477
492
|
const a = this.matchingHandoff(ref)?.attempt;
|
|
478
493
|
if (!a || !['dispatching', 'unknown', 'accepted'].includes(a.outcome))
|
|
@@ -480,9 +495,9 @@ export class LedgerStore {
|
|
|
480
495
|
if (a.outcome !== 'accepted')
|
|
481
496
|
this.db.prepare("UPDATE attempts SET outcome='accepted',settled_at=? WHERE token=?").run(now, a.token);
|
|
482
497
|
return true;
|
|
483
|
-
});
|
|
498
|
+
}, signal);
|
|
484
499
|
}
|
|
485
|
-
observePresentation(handoff, options) {
|
|
500
|
+
observePresentation(handoff, options, signal) {
|
|
486
501
|
return this.transaction(true, now => {
|
|
487
502
|
const facts = typeof handoff === 'string' ? undefined : this.matchingHandoff(handoff);
|
|
488
503
|
if (options?.requireCurrent) {
|
|
@@ -494,14 +509,14 @@ export class LedgerStore {
|
|
|
494
509
|
}
|
|
495
510
|
const a = typeof handoff === 'string' ? this.getAttempt(handoff) : facts?.attempt;
|
|
496
511
|
return a ? this.confirm(a, now) : false;
|
|
497
|
-
});
|
|
512
|
+
}, signal);
|
|
498
513
|
}
|
|
499
|
-
receipts(owner, options) {
|
|
514
|
+
receipts(owner, options, signal) {
|
|
500
515
|
return this.transaction(false, () => this.db.prepare('SELECT * FROM receipts WHERE owner=? AND at>=? ORDER BY at,key').all(owner, options.since ?? -Number.MAX_VALUE)
|
|
501
516
|
.filter(row => options.keys === undefined || options.keys.includes(row.key))
|
|
502
|
-
.map(row => ({ owner: row.owner, key: row.key, at: row.at })));
|
|
517
|
+
.map(row => ({ owner: row.owner, key: row.key, at: row.at })), signal);
|
|
503
518
|
}
|
|
504
|
-
health(owner) {
|
|
519
|
+
health(owner, signal) {
|
|
505
520
|
return this.transaction(false, now => {
|
|
506
521
|
const all = this.db.prepare('SELECT a.* FROM attempts a JOIN cards c ON c.seq=a.seq WHERE (? IS NULL OR c.owner=?) ORDER BY a.started_at,a.token').all(owner ?? null, owner ?? null).map(attempt);
|
|
507
522
|
const repeatedFailures = this.db.prepare(`SELECT c.owner,c.key,COUNT(*) AS count FROM attempts a JOIN cards c ON c.seq=a.seq
|
|
@@ -511,6 +526,6 @@ export class LedgerStore {
|
|
|
511
526
|
return { unknownAttempts: all.filter(a => a.outcome === 'unknown' || a.outcome === 'dispatching' && a.expiresAt <= now)
|
|
512
527
|
.map(a => a.outcome === 'dispatching' ? { ...a, outcome: 'unknown' } : a), repeatedFailures,
|
|
513
528
|
sessionsWithoutRoute: sessions.filter(s => s.routes.length === 0).map(s => s.owner) };
|
|
514
|
-
});
|
|
529
|
+
}, signal);
|
|
515
530
|
}
|
|
516
531
|
}
|
|
@@ -109,83 +109,88 @@ export declare function deliveryLedgerLocation(env?: NodeJS.ProcessEnv, homeDir?
|
|
|
109
109
|
export declare class DeliveryLedger {
|
|
110
110
|
private readonly store;
|
|
111
111
|
private readonly leaseMs;
|
|
112
|
+
private readonly settlements;
|
|
113
|
+
private retired;
|
|
112
114
|
private constructor();
|
|
113
115
|
static open(options?: {
|
|
114
116
|
readonly location?: string;
|
|
115
117
|
readonly clock?: () => number;
|
|
116
118
|
readonly leaseMs?: number;
|
|
119
|
+
readonly signal?: AbortSignal;
|
|
117
120
|
}): Promise<DeliveryLedger>;
|
|
118
121
|
close(): Promise<void>;
|
|
122
|
+
private retainSettlement;
|
|
123
|
+
private diagnose;
|
|
119
124
|
attach(input: {
|
|
120
125
|
readonly owner: Owner;
|
|
121
126
|
readonly expectedGeneration: string | null;
|
|
122
127
|
readonly routes: readonly DeliveryRoute[];
|
|
123
|
-
}): Promise<DeliverySession | false>;
|
|
128
|
+
}, signal?: AbortSignal): Promise<DeliverySession | false>;
|
|
124
129
|
updateRoutes(input: {
|
|
125
130
|
readonly owner: Owner;
|
|
126
131
|
readonly generation: string;
|
|
127
132
|
readonly routes: readonly DeliveryRoute[];
|
|
128
|
-
}): Promise<boolean>;
|
|
133
|
+
}, signal?: AbortSignal): Promise<boolean>;
|
|
129
134
|
detach(input: {
|
|
130
135
|
readonly owner: Owner;
|
|
131
136
|
readonly generation: string;
|
|
132
|
-
}): Promise<boolean>;
|
|
137
|
+
}, signal?: AbortSignal): Promise<boolean>;
|
|
133
138
|
markDeleted(input: {
|
|
134
139
|
readonly owner: Owner;
|
|
135
140
|
readonly generation: string;
|
|
136
|
-
}): Promise<boolean>;
|
|
141
|
+
}, signal?: AbortSignal): Promise<boolean>;
|
|
137
142
|
private lifecycle;
|
|
138
|
-
session(owner: Owner): Promise<DeliverySession | undefined>;
|
|
139
|
-
sessions(): Promise<readonly DeliverySession[]>;
|
|
143
|
+
session(owner: Owner, signal?: AbortSignal): Promise<DeliverySession | undefined>;
|
|
144
|
+
sessions(signal?: AbortSignal): Promise<readonly DeliverySession[]>;
|
|
140
145
|
pending(owner: Owner, options: {
|
|
141
146
|
readonly generation: string;
|
|
142
|
-
}): Promise<readonly DeliveryCard[]>;
|
|
147
|
+
}, signal?: AbortSignal): Promise<readonly DeliveryCard[]>;
|
|
143
148
|
handoffs(owner: Owner, options: {
|
|
144
149
|
readonly generation: string;
|
|
145
|
-
}): Promise<readonly DeliveryAttempt[]>;
|
|
150
|
+
}, signal?: AbortSignal): Promise<readonly DeliveryAttempt[]>;
|
|
146
151
|
post(input: {
|
|
147
152
|
readonly owner: Owner;
|
|
148
153
|
readonly key: string;
|
|
149
154
|
readonly text: string;
|
|
150
155
|
readonly details?: Readonly<Record<string, unknown>>;
|
|
151
|
-
}): Promise<PostResult>;
|
|
156
|
+
}, signal?: AbortSignal): Promise<PostResult>;
|
|
152
157
|
suppress(input: {
|
|
153
158
|
readonly owner: Owner;
|
|
154
159
|
readonly key: string;
|
|
155
160
|
readonly scope: 'exact' | 'prefix';
|
|
156
161
|
readonly expiresAt?: number;
|
|
157
|
-
}): Promise<SuppressionResult>;
|
|
162
|
+
}, signal?: AbortSignal): Promise<SuppressionResult>;
|
|
158
163
|
renewSuppression(input: {
|
|
159
164
|
readonly owner: Owner;
|
|
160
165
|
readonly id: string;
|
|
161
166
|
readonly expiresAt: number;
|
|
162
|
-
}): Promise<boolean>;
|
|
167
|
+
}, signal?: AbortSignal): Promise<boolean>;
|
|
163
168
|
releaseSuppression(input: {
|
|
164
169
|
readonly owner: Owner;
|
|
165
170
|
readonly id: string;
|
|
166
|
-
}): Promise<boolean>;
|
|
171
|
+
}, signal?: AbortSignal): Promise<boolean>;
|
|
167
172
|
cancel(input: {
|
|
168
173
|
readonly owner: Owner;
|
|
169
174
|
readonly generation: string;
|
|
170
|
-
}): Promise<boolean>;
|
|
175
|
+
}, signal?: AbortSignal): Promise<boolean>;
|
|
171
176
|
receipts(owner: Owner, options?: {
|
|
172
177
|
readonly keys?: readonly string[];
|
|
173
178
|
readonly since?: number;
|
|
174
|
-
}): Promise<readonly DeliveryReceipt[]>;
|
|
179
|
+
}, signal?: AbortSignal): Promise<readonly DeliveryReceipt[]>;
|
|
175
180
|
claimPresentation(owner: Owner, options: {
|
|
176
181
|
readonly generation: string;
|
|
177
182
|
readonly budgetChars: number;
|
|
178
183
|
readonly signal?: AbortSignal;
|
|
179
184
|
}): Promise<PresentationClaim | undefined>;
|
|
180
185
|
/** Resolve the original prepared handoff, including its stored route kind. */
|
|
181
|
-
handoff(token: string): Promise<DeliveryHandoffRef | undefined>;
|
|
182
|
-
guardHandoff(ref: DeliveryHandoffRef): Promise<boolean>;
|
|
183
|
-
acceptHandoff(ref: DeliveryHandoffRef): Promise<boolean>;
|
|
186
|
+
handoff(token: string, signal?: AbortSignal): Promise<DeliveryHandoffRef | undefined>;
|
|
187
|
+
guardHandoff(ref: DeliveryHandoffRef, signal?: AbortSignal): Promise<boolean>;
|
|
188
|
+
acceptHandoff(ref: DeliveryHandoffRef, signal?: AbortSignal): Promise<boolean>;
|
|
184
189
|
/** Confirms the exact existing external effect; never sends or returns text. */
|
|
185
190
|
observePresentation(handoff: string | DeliveryHandoffRef, options?: {
|
|
186
191
|
readonly requireCurrent?: boolean;
|
|
187
|
-
}): Promise<boolean>;
|
|
188
|
-
health(owner?: Owner): Promise<DeliveryHealth>;
|
|
192
|
+
}, signal?: AbortSignal): Promise<boolean>;
|
|
193
|
+
health(owner?: Owner, signal?: AbortSignal): Promise<DeliveryHealth>;
|
|
189
194
|
/** Subscribe first; read the returned version, inspect state, then await changed(version,...). */
|
|
190
195
|
observe(owner: Owner): Promise<VersionObserver<string>>;
|
|
191
196
|
dispatchHandoff(owner: Owner, key: string, transport: DeliveryTransport, options: {
|