@ixo/decision-oracle 0.2.4 → 0.2.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.
Files changed (83) hide show
  1. package/README.md +6 -3
  2. package/dist/cli/commands/init.d.ts +3 -1
  3. package/dist/cli/commands/init.d.ts.map +1 -1
  4. package/dist/cli/commands/init.js +42 -2
  5. package/dist/cli/commands/init.js.map +1 -1
  6. package/dist/cli/commands/oracle-init.d.ts.map +1 -1
  7. package/dist/cli/commands/oracle-init.js +13 -5
  8. package/dist/cli/commands/oracle-init.js.map +1 -1
  9. package/dist/cli/index.js +6 -3
  10. package/dist/cli/index.js.map +1 -1
  11. package/dist/cron/openhands.d.ts +9 -0
  12. package/dist/cron/openhands.d.ts.map +1 -0
  13. package/dist/cron/openhands.js +30 -0
  14. package/dist/cron/openhands.js.map +1 -0
  15. package/dist/cron/scan.d.ts.map +1 -1
  16. package/dist/cron/scan.js +3 -0
  17. package/dist/cron/scan.js.map +1 -1
  18. package/dist/db/schema.d.ts +158 -0
  19. package/dist/db/schema.d.ts.map +1 -1
  20. package/dist/db/schema.js +26 -0
  21. package/dist/db/schema.js.map +1 -1
  22. package/dist/define-oracle.d.ts +3 -0
  23. package/dist/define-oracle.d.ts.map +1 -1
  24. package/dist/define-oracle.js +13 -1
  25. package/dist/define-oracle.js.map +1 -1
  26. package/dist/env.d.ts +12 -0
  27. package/dist/env.d.ts.map +1 -1
  28. package/dist/index.d.ts +1 -1
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/lib/ixo/blocksync/index.d.ts +4 -0
  31. package/dist/lib/ixo/blocksync/index.d.ts.map +1 -1
  32. package/dist/lib/ixo/blocksync/index.js +47 -1
  33. package/dist/lib/ixo/blocksync/index.js.map +1 -1
  34. package/dist/lib/ixo/blocksync/queries.d.ts +2 -0
  35. package/dist/lib/ixo/blocksync/queries.d.ts.map +1 -1
  36. package/dist/lib/ixo/blocksync/queries.js +17 -0
  37. package/dist/lib/ixo/blocksync/queries.js.map +1 -1
  38. package/dist/lib/ixo/chain.d.ts +1 -1
  39. package/dist/lib/ixo/chain.d.ts.map +1 -1
  40. package/dist/lib/openhands/backstop.d.ts +131 -0
  41. package/dist/lib/openhands/backstop.d.ts.map +1 -0
  42. package/dist/lib/openhands/backstop.js +513 -0
  43. package/dist/lib/openhands/backstop.js.map +1 -0
  44. package/dist/lib/openhands/chain.d.ts +218 -0
  45. package/dist/lib/openhands/chain.d.ts.map +1 -0
  46. package/dist/lib/openhands/chain.js +392 -0
  47. package/dist/lib/openhands/chain.js.map +1 -0
  48. package/dist/lib/openhands/options.d.ts +13 -0
  49. package/dist/lib/openhands/options.d.ts.map +1 -0
  50. package/dist/lib/openhands/options.js +28 -0
  51. package/dist/lib/openhands/options.js.map +1 -0
  52. package/dist/lib/openhands/routes.d.ts +73 -0
  53. package/dist/lib/openhands/routes.d.ts.map +1 -0
  54. package/dist/lib/openhands/routes.js +355 -0
  55. package/dist/lib/openhands/routes.js.map +1 -0
  56. package/dist/lib/openhands/store.d.ts +74 -0
  57. package/dist/lib/openhands/store.d.ts.map +1 -0
  58. package/dist/lib/openhands/store.js +148 -0
  59. package/dist/lib/openhands/store.js.map +1 -0
  60. package/dist/oracle.d.ts +52 -1
  61. package/dist/oracle.d.ts.map +1 -1
  62. package/dist/oracle.js +6 -0
  63. package/dist/oracle.js.map +1 -1
  64. package/dist/routes/v1/info.d.ts.map +1 -1
  65. package/dist/routes/v1/info.js +6 -0
  66. package/dist/routes/v1/info.js.map +1 -1
  67. package/dist/runtime.d.ts +6 -0
  68. package/dist/runtime.d.ts.map +1 -1
  69. package/dist/runtime.js +10 -0
  70. package/dist/runtime.js.map +1 -1
  71. package/dist/workflows/openhands-hire.d.ts +65 -0
  72. package/dist/workflows/openhands-hire.d.ts.map +1 -0
  73. package/dist/workflows/openhands-hire.js +203 -0
  74. package/dist/workflows/openhands-hire.js.map +1 -0
  75. package/docs/api.md +70 -7
  76. package/docs/guide.md +33 -0
  77. package/migrations/0025_openhands.sql +12 -0
  78. package/migrations/meta/0025_snapshot.json +2976 -0
  79. package/migrations/meta/_journal.json +7 -0
  80. package/package.json +1 -1
  81. package/skills/README.md +1 -1
  82. package/skills/add-openhands-support/SKILL.md +96 -86
  83. package/skills/create-oracle/SKILL.md +10 -4
@@ -0,0 +1,513 @@
1
+ /**
2
+ * The OpenHands backstop: every ten minutes, find the asks that hired this oracle and never reached
3
+ * it — and the ones it reached on terms that have since changed. The webhook (routes.ts) is the
4
+ * fast path; this is what makes the hire reliable, because the app's call can be lost, refused or
5
+ * never made. Its work is proportional to what CHANGED, never to how many asks exist:
6
+ *
7
+ * 1. WINDOW — a window of watched collections a tick, ONE keyed chain read per admin (its
8
+ * meta-grant and what this oracle minted under it, together): re-hire a collection whose
9
+ * ceiling went stale or whose quota is low, and lift an `engine-no-grant` pause once it holds
10
+ * quota again. Collections paused for that reason come first (at most half the window), the
11
+ * rest rotate in id order, passing over asks that ended past the judge grace.
12
+ * 2. DISCOVER — a few pages of this oracle's grant listing a tick, the cursor persisted, for
13
+ * invitations the webhook never delivered: an admin's own meta-grant whose live, unwatched
14
+ * collections get a hire, at most `DISCOVERY_PER_ADMIN` per admin a pass.
15
+ *
16
+ * Every instance started or restarted spends the pass's `MAX_ACTIONS` and the collection's own
17
+ * restart budget (three a day), so a hire that fails for a reason a rerun cannot fix costs three
18
+ * reads a day, not a broadcast every ten minutes for ever.
19
+ *
20
+ * Ported from the IXO-run OpenHands oracles, which ran it on mainnet first (scale review A1/A8/B3,
21
+ * final review F6, asks 8253 and 8550).
22
+ */
23
+ import { and, asc, eq, gt, inArray, lte } from "drizzle-orm";
24
+ import { watchedCollections } from "../../db/schema.js";
25
+ import { getCollectionsByAdmins, getCollectionsByIds } from "../ixo/blocksync/index.js";
26
+ import { agentQuotaFor, approvalDenomOf, decodeMetaGrants, endsAtOf, grantsPage, holdsMatchingEvaluateGrant, isJudgeable, metasForCollection, needsTopUp, pickMetaGrant, readGrantsFrom, remainingEvaluateQuota, } from "./chain.js";
27
+ import { openhandsOptions, reportQuota } from "./options.js";
28
+ import { claimRestart, GRANTS_CURSOR, hireStates, MAX_RESTARTS, PAUSED_CURSOR, pruneBudgets, readState, refreshHire, restartBudgetName, WINDOW_CURSOR, writeState, } from "./store.js";
29
+ /** Instances one pass may start or restart, across both lanes. */
30
+ export const MAX_ACTIONS = 200;
31
+ /** Discovery hires attempted per admin per pass — one admin's un-hireable asks cannot starve the rest. */
32
+ export const DISCOVERY_PER_ADMIN = 20;
33
+ /** Watched collections verified per tick. */
34
+ export const WINDOW = 100;
35
+ /** Grant-listing pages read for discovery per tick, 200 a page. */
36
+ export const GRANT_PAGES = 10;
37
+ /** Rows the rotation may read per window slot, to fill the window past ended asks. */
38
+ const ROTATION_READ_AHEAD = 3;
39
+ /** How often an ended ask is looked at anyway — its end date can be extended on chain. */
40
+ export const ENDED_RECHECK_MS = 7 * 86_400_000;
41
+ /** Keyed chain reads in flight at once. */
42
+ const READS_IN_FLIGHT = 4;
43
+ /**
44
+ * The decision engine caches its grant answer — a "no" included — for 300 s. An `engine-no-grant`
45
+ * pause lifted sooner than that after a mint sends the parked claims back into a cached 403.
46
+ */
47
+ export const ENGINE_GRANT_CACHE_MS = 300_000;
48
+ const ENGINE_NO_GRANT = "engine-no-grant";
49
+ /** Instance states a rerun can rescue — an ENDED instance, in any of its three endings. */
50
+ export const ENDED = new Set(["complete", "errored", "terminated"]);
51
+ const asMessage = (err) => (err instanceof Error ? err.message : String(err));
52
+ /** The Workflows binding's "an instance with that id already exists", in either spelling. */
53
+ export const isAlreadyExists = (err) => /already[ _]exists/i.test(asMessage(err)) || /\b8104\b/.test(asMessage(err));
54
+ /** The Workflows binding's "no instance with that id", in either spelling and by its code. */
55
+ export const isNotFound = (err) => /not[ _]?found/i.test(asMessage(err)) || /\b10400\b/.test(asMessage(err));
56
+ export function hireWorkflow(env) {
57
+ if (!env.HIRE_WORKFLOW) {
58
+ throw new Error("openhands is on but the HIRE_WORKFLOW binding is missing (wrangler.jsonc)");
59
+ }
60
+ return env.HIRE_WORKFLOW;
61
+ }
62
+ const metaFor = (chain, target) => pickMetaGrant(metasForCollection(chain.metas, target.collectionId), target.admin);
63
+ /**
64
+ * Does this watched collection need its hire re-run, and why? Only a live meta-grant can say yes:
65
+ * without one the hire's own `verify` refuses. A stale cap wins over low quota — its re-mint
66
+ * carries a full batch, so it heals both. Low quota is judged against what the NEXT mint carries.
67
+ */
68
+ export function watchedRestartReason(chain, target, mintCap) {
69
+ const meta = metaFor(chain, target);
70
+ if (!meta)
71
+ return null;
72
+ const stale = !holdsMatchingEvaluateGrant(chain, {
73
+ admin: target.admin,
74
+ collectionId: target.collectionId,
75
+ metaCap: meta.maxAmount,
76
+ approvalDenom: target.approvalDenom,
77
+ mintCap,
78
+ });
79
+ if (stale)
80
+ return "cap";
81
+ if (needsTopUp(remainingEvaluateQuota(chain, target), agentQuotaFor(meta)))
82
+ return "quota";
83
+ return null;
84
+ }
85
+ /**
86
+ * The id a hire started for a collection whose own id is gone or taken — spelt from the budget
87
+ * slot it spent, so one slot creates one id.
88
+ */
89
+ export const revivedHireId = (collectionId, slot) => {
90
+ const [count, start] = slot.split("|");
91
+ return `${collectionId}-r${count || "0"}-${Date.parse(start ?? "") || 0}`;
92
+ };
93
+ function refused(logger, collectionId, why, state) {
94
+ if (why === "raced") {
95
+ logger.info("openhands.hire.raced", { collectionId, state });
96
+ return "existing";
97
+ }
98
+ logger.warn("openhands.hire.throttled", { collectionId, state, maxRestarts: MAX_RESTARTS });
99
+ return "throttled";
100
+ }
101
+ /**
102
+ * Restart the hire instance holding this id, if it has ENDED and the collection's budget allows.
103
+ * An id the runtime no longer holds (aged out of the instance history) gets a FRESH id carrying the
104
+ * collection in its params, on the same budget. `existing` = a run is in flight.
105
+ */
106
+ export async function restartHire(deps, collectionId, now = new Date()) {
107
+ const { env, db, logger } = deps;
108
+ try {
109
+ const workflow = hireWorkflow(env);
110
+ let instance;
111
+ try {
112
+ instance = await workflow.get(collectionId);
113
+ }
114
+ catch (err) {
115
+ if (!isNotFound(err))
116
+ throw err;
117
+ const claim = await claimRestart(db, restartBudgetName(collectionId), now);
118
+ if ("denied" in claim)
119
+ return refused(logger, collectionId, claim.denied, "no instance");
120
+ const id = revivedHireId(collectionId, claim.slot);
121
+ try {
122
+ await workflow.create({ id, params: { collectionId } });
123
+ }
124
+ catch (createErr) {
125
+ if (!isAlreadyExists(createErr))
126
+ throw createErr;
127
+ return "existing";
128
+ }
129
+ logger.info("openhands.hire.revived", { collectionId, instanceId: id });
130
+ return "restarted";
131
+ }
132
+ const { status } = await instance.status();
133
+ if (!ENDED.has(status))
134
+ return "existing";
135
+ const claim = await claimRestart(db, restartBudgetName(collectionId), now);
136
+ if ("denied" in claim)
137
+ return refused(logger, collectionId, claim.denied, `ended ${status}`);
138
+ await instance.restart();
139
+ logger.info("openhands.hire.restarted", { collectionId, was: status });
140
+ return "restarted";
141
+ }
142
+ catch (err) {
143
+ logger.error("openhands.hire.unrevivable", { collectionId, detail: asMessage(err) });
144
+ return "failed";
145
+ }
146
+ }
147
+ /** Start the hire for one collection, or revive the instance that already holds its id. */
148
+ export async function ensureHire(deps, collectionId, now = new Date()) {
149
+ try {
150
+ await hireWorkflow(deps.env).create({ id: collectionId, params: { collectionId } });
151
+ return "started";
152
+ }
153
+ catch (err) {
154
+ if (!isAlreadyExists(err)) {
155
+ deps.logger.error("openhands.hire.unstartable", { collectionId, detail: asMessage(err) });
156
+ return "failed";
157
+ }
158
+ }
159
+ return restartHire(deps, collectionId, now);
160
+ }
161
+ const emptyReport = () => ({
162
+ verified: 0,
163
+ paused: 0,
164
+ ended: 0,
165
+ unindexed: 0,
166
+ admins: 0,
167
+ grantPages: 0,
168
+ wrapped: false,
169
+ invitingAdmins: 0,
170
+ unwatched: 0,
171
+ notServed: 0,
172
+ deferred: 0,
173
+ started: 0,
174
+ existing: 0,
175
+ restarted: 0,
176
+ restartedForCap: 0,
177
+ restartedForQuota: 0,
178
+ resumed: 0,
179
+ throttled: 0,
180
+ failed: 0,
181
+ pruned: 0,
182
+ });
183
+ /**
184
+ * The next `size` watched collections after `after`, in id order, wrapping to the start — so no
185
+ * tick reads more than `size` rows. `paused: true` reads only `engine-no-grant` pauses (the front
186
+ * of the window), on their own cursor.
187
+ */
188
+ export async function watchedWindow(db, after, size, paused = false) {
189
+ const only = paused
190
+ ? and(eq(watchedCollections.status, "paused"), eq(watchedCollections.pausedReason, ENGINE_NO_GRANT))
191
+ : undefined;
192
+ const read = (op, limit) => db
193
+ .select({
194
+ collectionId: watchedCollections.collectionId,
195
+ status: watchedCollections.status,
196
+ pausedReason: watchedCollections.pausedReason,
197
+ })
198
+ .from(watchedCollections)
199
+ .where(and(only, op(watchedCollections.collectionId, after)))
200
+ .orderBy(asc(watchedCollections.collectionId))
201
+ .limit(limit);
202
+ const rows = await read(gt, size);
203
+ if (rows.length < size && after !== "")
204
+ rows.push(...(await read(lte, size - rows.length)));
205
+ return rows.map((r) => ({ ...r, pausedReason: r.pausedReason ?? null }));
206
+ }
207
+ /** Passed over without a read: last seen ended past its grace, and that sighting is under a week old. */
208
+ function isEnded(state, now) {
209
+ if (!state?.endsAt)
210
+ return false;
211
+ const recheckFrom = new Date(now.getTime() - ENDED_RECHECK_MS).toISOString();
212
+ return state.endsAt <= now.toISOString() && state.checkedAt > recheckFrom;
213
+ }
214
+ /**
215
+ * Lift an `engine-no-grant` pause once the chain shows quota to judge with AND the last quota read
216
+ * (the mint, or the window's previous visit) is older than the engine's grant cache. The guard is
217
+ * in the statement: a collection re-paused meanwhile, or by an operator, is left alone.
218
+ */
219
+ async function resumeIfHealed(db, row, remaining, state, now) {
220
+ if (row.status !== "paused" || row.pausedReason !== ENGINE_NO_GRANT || remaining <= 0) {
221
+ return false;
222
+ }
223
+ const last = Date.parse(state?.checkedAt ?? "");
224
+ if (Number.isFinite(last) && now.getTime() - last < ENGINE_GRANT_CACHE_MS)
225
+ return false;
226
+ const flipped = await db
227
+ .update(watchedCollections)
228
+ .set({ status: "active", pausedReason: null })
229
+ .where(and(eq(watchedCollections.collectionId, row.collectionId), eq(watchedCollections.status, "paused"), eq(watchedCollections.pausedReason, ENGINE_NO_GRANT)))
230
+ .returning({ id: watchedCollections.collectionId });
231
+ return flipped.length > 0;
232
+ }
233
+ /** `fn` over `items`, at most `limit` in flight, each failure caught by `fn` itself. */
234
+ async function eachLimit(items, limit, fn) {
235
+ let next = 0;
236
+ const worker = async () => {
237
+ while (next < items.length)
238
+ await fn(items[next++]);
239
+ };
240
+ await Promise.all(Array.from({ length: Math.max(1, Math.min(limit, items.length)) }, worker));
241
+ }
242
+ /** Lane 1: this tick's window, each collection judged against ONE keyed read of its admin. */
243
+ async function verifyWindow(deps, ctx) {
244
+ const { db, logger, config } = deps;
245
+ const { now, actions, report } = ctx;
246
+ const mintCap = openhandsOptions().maxCustomAmount;
247
+ const [pausedAfter, rotationAfter] = await Promise.all([
248
+ readState(db, PAUSED_CURSOR),
249
+ readState(db, WINDOW_CURSOR),
250
+ ]);
251
+ const ours = await watchedWindow(db, pausedAfter ?? "", Math.max(1, Math.floor(WINDOW / 2)), true);
252
+ const candidates = await watchedWindow(db, rotationAfter ?? "", WINDOW * ROTATION_READ_AHEAD);
253
+ const states = await hireStates(db, [
254
+ ...new Set([...ours, ...candidates].map((row) => row.collectionId)),
255
+ ]);
256
+ const rows = [];
257
+ const taken = new Set();
258
+ for (const row of ours) {
259
+ if (isEnded(states.get(row.collectionId), now))
260
+ continue;
261
+ rows.push(row);
262
+ taken.add(row.collectionId);
263
+ }
264
+ report.paused = rows.length;
265
+ let examined = null;
266
+ for (const row of candidates) {
267
+ if (rows.length >= WINDOW)
268
+ break;
269
+ examined = row.collectionId;
270
+ if (taken.has(row.collectionId))
271
+ continue;
272
+ if (isEnded(states.get(row.collectionId), now)) {
273
+ report.ended += 1;
274
+ continue;
275
+ }
276
+ rows.push(row);
277
+ taken.add(row.collectionId);
278
+ }
279
+ report.verified = rows.length;
280
+ if (rows.length > 0) {
281
+ const known = await getCollectionsByIds(deps.blocksync, rows.map((row) => row.collectionId));
282
+ const byAdmin = new Map();
283
+ for (const row of rows) {
284
+ const node = known.get(row.collectionId);
285
+ if (!node?.admin) {
286
+ report.unindexed += 1;
287
+ continue;
288
+ }
289
+ const list = byAdmin.get(node.admin) ?? [];
290
+ list.push({
291
+ row,
292
+ target: {
293
+ collectionId: row.collectionId,
294
+ admin: node.admin,
295
+ approvalDenom: approvalDenomOf(node.payments),
296
+ },
297
+ endDate: node.endDate,
298
+ });
299
+ byAdmin.set(node.admin, list);
300
+ }
301
+ report.admins = byAdmin.size;
302
+ await eachLimit([...byAdmin], READS_IN_FLIGHT, async ([admin, items]) => {
303
+ let chain;
304
+ try {
305
+ chain = await readGrantsFrom(config, admin);
306
+ }
307
+ catch (err) {
308
+ report.failed += 1;
309
+ logger.error("openhands.backstop.grants-unreadable", {
310
+ admin,
311
+ waiting: items.length,
312
+ detail: asMessage(err),
313
+ });
314
+ return;
315
+ }
316
+ for (const { row, target, endDate } of items) {
317
+ const { collectionId } = target;
318
+ const remaining = remainingEvaluateQuota(chain, target);
319
+ const meta = metaFor(chain, target);
320
+ const mintQuota = meta ? agentQuotaFor(meta) : 0;
321
+ const endsAt = endsAtOf(endDate);
322
+ const before = states.get(collectionId);
323
+ try {
324
+ await refreshHire(db, { collectionId, remaining, mintQuota, now, endsAt });
325
+ }
326
+ catch (err) {
327
+ logger.warn("openhands.quota.unwritten", { collectionId, detail: asMessage(err) });
328
+ }
329
+ await reportQuota(deps.env, logger, { collectionId, remaining, mintQuota, endsAt });
330
+ try {
331
+ if (await resumeIfHealed(db, row, remaining, before, now)) {
332
+ report.resumed += 1;
333
+ logger.info("openhands.backstop.resumed", { collectionId, remaining });
334
+ }
335
+ }
336
+ catch (err) {
337
+ report.failed += 1;
338
+ logger.error("openhands.backstop.unresumable", { collectionId, detail: asMessage(err) });
339
+ }
340
+ if (!isJudgeable(endDate, now) || actions.left <= 0)
341
+ continue;
342
+ const reason = watchedRestartReason(chain, target, mintCap);
343
+ if (reason === null)
344
+ continue;
345
+ const outcome = await restartHire(deps, collectionId, now);
346
+ if (outcome === "restarted") {
347
+ actions.left -= 1;
348
+ if (reason === "cap")
349
+ report.restartedForCap += 1;
350
+ else
351
+ report.restartedForQuota += 1;
352
+ }
353
+ else
354
+ report[outcome] += 1;
355
+ }
356
+ });
357
+ }
358
+ // Advanced only once the window was walked: a tick that failed before here sees it again.
359
+ const lastOurs = ours[ours.length - 1];
360
+ if (lastOurs)
361
+ await writeState(db, PAUSED_CURSOR, lastOurs.collectionId);
362
+ if (examined !== null)
363
+ await writeState(db, WINDOW_CURSOR, examined);
364
+ }
365
+ /** A `granteeGrants` page key as a stored value, and back. "" is the first page. */
366
+ export const encodeGrantsKey = (key) => key.length === 0 ? "" : btoa(String.fromCharCode(...key));
367
+ export function decodeGrantsKey(value) {
368
+ if (!value)
369
+ return new Uint8Array();
370
+ try {
371
+ return Uint8Array.from(atob(value), (c) => c.charCodeAt(0));
372
+ }
373
+ catch {
374
+ // A mangled cursor restarts discovery from the top: a brake on work, never a reason to stop.
375
+ return new Uint8Array();
376
+ }
377
+ }
378
+ const IN_CHUNK = 90;
379
+ /** Which of `ids` this oracle watches already — read for these ids only. */
380
+ async function watchedAmong(db, ids) {
381
+ const out = new Set();
382
+ for (let i = 0; i < ids.length; i += IN_CHUNK) {
383
+ const rows = await db
384
+ .select({ id: watchedCollections.collectionId })
385
+ .from(watchedCollections)
386
+ .where(inArray(watchedCollections.collectionId, ids.slice(i, i + IN_CHUNK)));
387
+ for (const row of rows)
388
+ out.add(row.id);
389
+ }
390
+ return out;
391
+ }
392
+ /**
393
+ * Lane 2: the next `GRANT_PAGES` pages of the grant listing from where the last tick stopped. Only
394
+ * a meta-grant an admin signed for itself is an invitation the chain would honour. The cursor is
395
+ * saved only AFTER the hires: a pass that runs out part-way re-reads that page next tick.
396
+ */
397
+ async function discoverUnwatched(deps, ctx) {
398
+ const { db, logger, config } = deps;
399
+ const { now, actions, report } = ctx;
400
+ let key = decodeGrantsKey(await readState(db, GRANTS_CURSOR));
401
+ const metasByAdmin = new Map();
402
+ const pageKeys = [];
403
+ const adminPage = new Map();
404
+ for (let page = 0; page < GRANT_PAGES; page++) {
405
+ let read;
406
+ try {
407
+ read = await grantsPage(config, key);
408
+ }
409
+ catch (err) {
410
+ report.failed += 1;
411
+ logger.error("openhands.backstop.listing-unreadable", { detail: asMessage(err) });
412
+ break;
413
+ }
414
+ pageKeys.push(key);
415
+ report.grantPages += 1;
416
+ for (const meta of decodeMetaGrants(read.grants, read.sdk, now)) {
417
+ if (meta.granter !== meta.admin)
418
+ continue;
419
+ const list = metasByAdmin.get(meta.admin) ?? [];
420
+ list.push(meta);
421
+ metasByAdmin.set(meta.admin, list);
422
+ if (!adminPage.has(meta.admin))
423
+ adminPage.set(meta.admin, page);
424
+ }
425
+ key = read.nextKey;
426
+ if (key.length === 0) {
427
+ report.wrapped = true;
428
+ break;
429
+ }
430
+ }
431
+ const endKey = key;
432
+ report.invitingAdmins = metasByAdmin.size;
433
+ if (metasByAdmin.size === 0) {
434
+ await writeState(db, GRANTS_CURSOR, encodeGrantsKey(endKey));
435
+ return;
436
+ }
437
+ const collections = await getCollectionsByAdmins(deps.blocksync, [...metasByAdmin.keys()]);
438
+ const covered = collections.filter((c) => c.admin !== null &&
439
+ isJudgeable(c.endDate, now) &&
440
+ pickMetaGrant(metasForCollection(metasByAdmin.get(c.admin) ?? [], c.id), c.admin) !== null);
441
+ const watched = await watchedAmong(db, covered.map((c) => c.id));
442
+ const unwatched = covered.filter((c) => !watched.has(c.id));
443
+ report.unwatched = unwatched.length;
444
+ // The hire's `verify` refuses these anyway; asking `admit` here keeps an ask the provider will
445
+ // not serve from spending this pass's instances and its own restart budget every pass.
446
+ const admit = openhandsOptions().admit;
447
+ const served = [];
448
+ for (const c of unwatched) {
449
+ const refusal = admit
450
+ ? await Promise.resolve(admit({ collectionId: c.id, admin: c.admin ?? "", entity: c.entity }, deps.env)).catch(() => null)
451
+ : null;
452
+ if (refusal)
453
+ report.notServed += 1;
454
+ else
455
+ served.push(c);
456
+ }
457
+ const pageOf = (admin) => adminPage.get(admin ?? "") ?? 0;
458
+ const ordered = [...served].sort((a, b) => pageOf(a.admin) - pageOf(b.admin));
459
+ let attempts = MAX_ACTIONS;
460
+ const tried = new Map();
461
+ let heldAt = null;
462
+ for (const c of ordered) {
463
+ const admin = c.admin ?? "";
464
+ const sofar = tried.get(admin) ?? 0;
465
+ if (sofar >= DISCOVERY_PER_ADMIN) {
466
+ report.deferred += 1;
467
+ continue;
468
+ }
469
+ if (actions.left <= 0 || attempts <= 0) {
470
+ heldAt = pageOf(admin);
471
+ break;
472
+ }
473
+ attempts -= 1;
474
+ tried.set(admin, sofar + 1);
475
+ const outcome = await ensureHire(deps, c.id, now);
476
+ if (outcome === "started" || outcome === "restarted")
477
+ actions.left -= 1;
478
+ report[outcome] += 1;
479
+ }
480
+ const resumeKey = heldAt === null ? endKey : (pageKeys[heldAt] ?? endKey);
481
+ await writeState(db, GRANTS_CURSOR, encodeGrantsKey(resumeKey));
482
+ }
483
+ /**
484
+ * One tick of the backstop: prune spent budgets, verify the window, discover undelivered
485
+ * invitations. Each lane is independent — one that fails is counted and logged, the others run.
486
+ */
487
+ export async function runBackstop(deps, now = new Date()) {
488
+ const report = emptyReport();
489
+ const ctx = { now, actions: { left: MAX_ACTIONS }, report };
490
+ const lanes = [
491
+ [
492
+ "prune",
493
+ async () => {
494
+ report.pruned = await pruneBudgets(deps.db, now);
495
+ },
496
+ ],
497
+ // Watched asks first: keeping a hired ask judging matters more than finding a new one.
498
+ ["window", () => verifyWindow(deps, ctx)],
499
+ ["discover", () => discoverUnwatched(deps, ctx)],
500
+ ];
501
+ for (const [name, lane] of lanes) {
502
+ try {
503
+ await lane();
504
+ }
505
+ catch (err) {
506
+ report.failed += 1;
507
+ deps.logger.error("openhands.backstop.lane-failed", { lane: name, detail: asMessage(err) });
508
+ }
509
+ }
510
+ deps.logger.info("openhands.backstop", { ...report });
511
+ return report;
512
+ }
513
+ //# sourceMappingURL=backstop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backstop.js","sourceRoot":"","sources":["../../../src/lib/openhands/backstop.ts"],"names":[],"mappings":"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"}