@venturekit-pro/ai 0.0.48 → 0.0.50

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 (147) hide show
  1. package/README.md +192 -0
  2. package/dist/agent-loop/index.d.ts +9 -0
  3. package/dist/agent-loop/index.d.ts.map +1 -0
  4. package/dist/agent-loop/index.js +7 -0
  5. package/dist/agent-loop/index.js.map +1 -0
  6. package/dist/agent-loop/registry.d.ts +85 -0
  7. package/dist/agent-loop/registry.d.ts.map +1 -0
  8. package/dist/agent-loop/registry.js +100 -0
  9. package/dist/agent-loop/registry.js.map +1 -0
  10. package/dist/agent-loop/run-agent.d.ts +37 -0
  11. package/dist/agent-loop/run-agent.d.ts.map +1 -0
  12. package/dist/agent-loop/run-agent.js +405 -0
  13. package/dist/agent-loop/run-agent.js.map +1 -0
  14. package/dist/agent-loop/tools.d.ts +10 -0
  15. package/dist/agent-loop/tools.d.ts.map +1 -0
  16. package/dist/agent-loop/tools.js +28 -0
  17. package/dist/agent-loop/tools.js.map +1 -0
  18. package/dist/agent-loop/types.d.ts +175 -0
  19. package/dist/agent-loop/types.d.ts.map +1 -0
  20. package/dist/agent-loop/types.js +8 -0
  21. package/dist/agent-loop/types.js.map +1 -0
  22. package/dist/chat/types.d.ts +4 -2
  23. package/dist/chat/types.d.ts.map +1 -1
  24. package/dist/cost/types.d.ts +15 -0
  25. package/dist/cost/types.d.ts.map +1 -1
  26. package/dist/cost-ledger/migrations/vk_ai_cost_0004_llm_gateway.sql +69 -0
  27. package/dist/cost-ledger/migrations/vk_ai_cost_0005_harness.sql +99 -0
  28. package/dist/cost-ledger/migrations/vk_ai_cost_0006_cache_write_prices.sql +17 -0
  29. package/dist/cost-ledger/migrations/vk_ai_cost_0007_harness_fan_out.sql +47 -0
  30. package/dist/gateway/errors.d.ts +24 -0
  31. package/dist/gateway/errors.d.ts.map +1 -0
  32. package/dist/gateway/errors.js +29 -0
  33. package/dist/gateway/errors.js.map +1 -0
  34. package/dist/gateway/gateway.d.ts +27 -0
  35. package/dist/gateway/gateway.d.ts.map +1 -0
  36. package/dist/gateway/gateway.js +503 -0
  37. package/dist/gateway/gateway.js.map +1 -0
  38. package/dist/gateway/index.d.ts +13 -0
  39. package/dist/gateway/index.d.ts.map +1 -0
  40. package/dist/gateway/index.js +10 -0
  41. package/dist/gateway/index.js.map +1 -0
  42. package/dist/gateway/policies.d.ts +32 -0
  43. package/dist/gateway/policies.d.ts.map +1 -0
  44. package/dist/gateway/policies.js +45 -0
  45. package/dist/gateway/policies.js.map +1 -0
  46. package/dist/gateway/postgres.d.ts +55 -0
  47. package/dist/gateway/postgres.d.ts.map +1 -0
  48. package/dist/gateway/postgres.js +127 -0
  49. package/dist/gateway/postgres.js.map +1 -0
  50. package/dist/gateway/pricing.d.ts +11 -0
  51. package/dist/gateway/pricing.d.ts.map +1 -0
  52. package/dist/gateway/pricing.js +47 -0
  53. package/dist/gateway/pricing.js.map +1 -0
  54. package/dist/gateway/routing.d.ts +25 -0
  55. package/dist/gateway/routing.d.ts.map +1 -0
  56. package/dist/gateway/routing.js +23 -0
  57. package/dist/gateway/routing.js.map +1 -0
  58. package/dist/gateway/types.d.ts +225 -0
  59. package/dist/gateway/types.d.ts.map +1 -0
  60. package/dist/gateway/types.js +7 -0
  61. package/dist/gateway/types.js.map +1 -0
  62. package/dist/generate/anthropic.d.ts +38 -0
  63. package/dist/generate/anthropic.d.ts.map +1 -0
  64. package/dist/generate/anthropic.js +446 -0
  65. package/dist/generate/anthropic.js.map +1 -0
  66. package/dist/generate/client.d.ts +9 -0
  67. package/dist/generate/client.d.ts.map +1 -0
  68. package/dist/generate/client.js +44 -0
  69. package/dist/generate/client.js.map +1 -0
  70. package/dist/generate/google.d.ts +39 -0
  71. package/dist/generate/google.d.ts.map +1 -0
  72. package/dist/generate/google.js +372 -0
  73. package/dist/generate/google.js.map +1 -0
  74. package/dist/generate/http.d.ts +48 -0
  75. package/dist/generate/http.d.ts.map +1 -0
  76. package/dist/generate/http.js +180 -0
  77. package/dist/generate/http.js.map +1 -0
  78. package/dist/generate/index.d.ts +13 -0
  79. package/dist/generate/index.d.ts.map +1 -0
  80. package/dist/generate/index.js +12 -0
  81. package/dist/generate/index.js.map +1 -0
  82. package/dist/generate/openai.d.ts +29 -0
  83. package/dist/generate/openai.d.ts.map +1 -0
  84. package/dist/generate/openai.js +314 -0
  85. package/dist/generate/openai.js.map +1 -0
  86. package/dist/generate/perplexity.d.ts +27 -0
  87. package/dist/generate/perplexity.d.ts.map +1 -0
  88. package/dist/generate/perplexity.js +208 -0
  89. package/dist/generate/perplexity.js.map +1 -0
  90. package/dist/generate/types.d.ts +253 -0
  91. package/dist/generate/types.d.ts.map +1 -0
  92. package/dist/generate/types.js +19 -0
  93. package/dist/generate/types.js.map +1 -0
  94. package/dist/harness/define.d.ts +15 -0
  95. package/dist/harness/define.d.ts.map +1 -0
  96. package/dist/harness/define.js +38 -0
  97. package/dist/harness/define.js.map +1 -0
  98. package/dist/harness/harness.d.ts +29 -0
  99. package/dist/harness/harness.d.ts.map +1 -0
  100. package/dist/harness/harness.js +1287 -0
  101. package/dist/harness/harness.js.map +1 -0
  102. package/dist/harness/index.d.ts +14 -0
  103. package/dist/harness/index.d.ts.map +1 -0
  104. package/dist/harness/index.js +10 -0
  105. package/dist/harness/index.js.map +1 -0
  106. package/dist/harness/memory-store.d.ts +8 -0
  107. package/dist/harness/memory-store.d.ts.map +1 -0
  108. package/dist/harness/memory-store.js +270 -0
  109. package/dist/harness/memory-store.js.map +1 -0
  110. package/dist/harness/postgres-store.d.ts +12 -0
  111. package/dist/harness/postgres-store.d.ts.map +1 -0
  112. package/dist/harness/postgres-store.js +368 -0
  113. package/dist/harness/postgres-store.js.map +1 -0
  114. package/dist/harness/scheduler.d.ts +12 -0
  115. package/dist/harness/scheduler.d.ts.map +1 -0
  116. package/dist/harness/scheduler.js +23 -0
  117. package/dist/harness/scheduler.js.map +1 -0
  118. package/dist/harness/store.d.ts +172 -0
  119. package/dist/harness/store.d.ts.map +1 -0
  120. package/dist/harness/store.js +21 -0
  121. package/dist/harness/store.js.map +1 -0
  122. package/dist/harness/types.d.ts +312 -0
  123. package/dist/harness/types.d.ts.map +1 -0
  124. package/dist/harness/types.js +11 -0
  125. package/dist/harness/types.js.map +1 -0
  126. package/dist/index.d.ts +12 -0
  127. package/dist/index.d.ts.map +1 -1
  128. package/dist/index.js +11 -0
  129. package/dist/index.js.map +1 -1
  130. package/dist/model-catalog/crud.d.ts.map +1 -1
  131. package/dist/model-catalog/crud.js +33 -2
  132. package/dist/model-catalog/crud.js.map +1 -1
  133. package/dist/model-catalog/types.d.ts +20 -0
  134. package/dist/model-catalog/types.d.ts.map +1 -1
  135. package/dist/tracing/index.d.ts +68 -0
  136. package/dist/tracing/index.d.ts.map +1 -0
  137. package/dist/tracing/index.js +72 -0
  138. package/dist/tracing/index.js.map +1 -0
  139. package/dist/tracing/recording.d.ts +23 -0
  140. package/dist/tracing/recording.d.ts.map +1 -0
  141. package/dist/tracing/recording.js +49 -0
  142. package/dist/tracing/recording.js.map +1 -0
  143. package/package.json +7 -4
  144. package/src/cost-ledger/migrations/vk_ai_cost_0004_llm_gateway.sql +69 -0
  145. package/src/cost-ledger/migrations/vk_ai_cost_0005_harness.sql +99 -0
  146. package/src/cost-ledger/migrations/vk_ai_cost_0006_cache_write_prices.sql +17 -0
  147. package/src/cost-ledger/migrations/vk_ai_cost_0007_harness_fan_out.sql +47 -0
@@ -0,0 +1,368 @@
1
+ /**
2
+ * Postgres harness store (migration `vk_ai_cost_0005_harness.sql`).
3
+ *
4
+ * Every commit is ONE statement: a version-checked UPDATE of the run in a
5
+ * data-modifying CTE, with the events (sequence numbers taken from the
6
+ * run's `event_seq` counter) and the node-run row inserted from its
7
+ * RETURNING — so a conflict writes nothing and a success writes all.
8
+ */
9
+ const ITEM_COLUMNS = `item_index AS "index", status, input, output, attempt, attempt_base AS "attemptBase", lease_until AS "leaseUntil",
10
+ not_before AS "notBefore", error, cost_usd AS "costUsd", updated_at AS "updatedAt"`;
11
+ const RUN_COLUMNS = `id, graph_key AS "graphKey", graph_version AS "graphVersion", status, context, input, outputs,
12
+ current_node AS "currentNode", step, attempt, attempt_base AS "attemptBase", not_before AS "notBefore",
13
+ lease_until AS "leaseUntil", cancel_requested AS "cancelRequested", error, cost_usd AS "costUsd", version,
14
+ created_at AS "createdAt", updated_at AS "updatedAt", completed_at AS "completedAt"`;
15
+ const EVENT_RECORDSET = `jsonb_to_recordset($EVENTS::jsonb) AS e(i int, at timestamptz, type text, node_id text, step int, attempt int, label text, detail text, data jsonb)`;
16
+ const iso = (v) => v === null || v === undefined
17
+ ? null
18
+ : v instanceof Date
19
+ ? v.toISOString()
20
+ : new Date(v).toISOString();
21
+ function fromRow(r) {
22
+ return {
23
+ id: r.id,
24
+ graphKey: r.graphKey,
25
+ graphVersion: Number(r.graphVersion),
26
+ status: r.status,
27
+ context: r.context ?? {},
28
+ input: r.input,
29
+ outputs: r.outputs ?? {},
30
+ currentNode: r.currentNode,
31
+ step: Number(r.step),
32
+ attempt: Number(r.attempt),
33
+ attemptBase: Number(r.attemptBase),
34
+ notBefore: iso(r.notBefore),
35
+ leaseUntil: iso(r.leaseUntil),
36
+ cancelRequested: r.cancelRequested,
37
+ error: r.error ?? null,
38
+ costUsd: Number(r.costUsd),
39
+ version: Number(r.version),
40
+ createdAt: iso(r.createdAt),
41
+ updatedAt: iso(r.updatedAt),
42
+ completedAt: iso(r.completedAt),
43
+ };
44
+ }
45
+ function fromItemRow(r) {
46
+ return {
47
+ index: Number(r.index),
48
+ status: r.status,
49
+ input: r.input,
50
+ output: r.output,
51
+ attempt: Number(r.attempt),
52
+ attemptBase: Number(r.attemptBase),
53
+ leaseUntil: iso(r.leaseUntil),
54
+ notBefore: iso(r.notBefore),
55
+ error: r.error ?? null,
56
+ costUsd: Number(r.costUsd),
57
+ updatedAt: iso(r.updatedAt),
58
+ };
59
+ }
60
+ const eventsJson = (events) => JSON.stringify(events.map((e, index) => ({
61
+ i: index + 1,
62
+ at: e.at ?? null,
63
+ type: e.type,
64
+ node_id: e.nodeId,
65
+ step: e.step,
66
+ attempt: e.attempt,
67
+ label: e.label,
68
+ detail: e.detail,
69
+ data: e.data === undefined ? null : e.data,
70
+ })));
71
+ /** A jsonb parameter; `null` / `undefined` → SQL NULL. */
72
+ const json = (value) => value === undefined || value === null ? null : JSON.stringify(value);
73
+ export function createPostgresHarnessStore(querier) {
74
+ return {
75
+ async insertRun(run, events) {
76
+ const params = [
77
+ run.id,
78
+ run.context.tenantId ?? null,
79
+ run.graphKey,
80
+ run.graphVersion,
81
+ run.status,
82
+ json(run.context),
83
+ run.context.target?.type ?? null,
84
+ run.context.target?.id ?? null,
85
+ json(run.input),
86
+ json(run.outputs),
87
+ run.currentNode,
88
+ run.step,
89
+ run.attempt,
90
+ run.attemptBase,
91
+ run.notBefore,
92
+ run.leaseUntil,
93
+ run.cancelRequested,
94
+ json(run.error),
95
+ run.costUsd,
96
+ events.length,
97
+ run.version,
98
+ run.createdAt,
99
+ run.updatedAt,
100
+ run.completedAt,
101
+ eventsJson(events),
102
+ ];
103
+ await querier(`WITH ins AS (
104
+ INSERT INTO vk_harness_runs (
105
+ id, tenant_id, graph_key, graph_version, status, context, target_type, target_id, input, outputs,
106
+ current_node, step, attempt, attempt_base, not_before, lease_until, cancel_requested, error, cost_usd,
107
+ event_seq, version, created_at, updated_at, completed_at
108
+ ) VALUES (
109
+ $1, $2, $3, $4, $5, $6::jsonb, $7, $8, $9::jsonb, $10::jsonb,
110
+ $11, $12, $13, $14, $15, $16, $17, $18::jsonb, $19,
111
+ $20, $21, $22, $23, $24
112
+ )
113
+ RETURNING id
114
+ )
115
+ INSERT INTO vk_harness_events (run_id, seq, at, type, node_id, step, attempt, label, detail, data)
116
+ SELECT ins.id, e.i, COALESCE(e.at, now()), e.type, e.node_id, e.step, e.attempt, e.label, e.detail, e.data
117
+ FROM ins, ${EVENT_RECORDSET.replace('$EVENTS', '$25')}`, params);
118
+ },
119
+ async getRun(id) {
120
+ const rows = await querier(`SELECT ${RUN_COLUMNS} FROM vk_harness_runs WHERE id = $1`, [id]);
121
+ return rows[0] ? fromRow(rows[0]) : null;
122
+ },
123
+ async updateRun(id, expectedVersion, patch, extras) {
124
+ const events = extras?.events ?? [];
125
+ const params = [id, expectedVersion, events.length];
126
+ const sets = [
127
+ 'version = version + 1',
128
+ 'updated_at = now()',
129
+ 'event_seq = event_seq + $3',
130
+ ];
131
+ const set = (column, value, cast = '') => {
132
+ params.push(value);
133
+ sets.push(`${column} = $${params.length}${cast}`);
134
+ };
135
+ applyPatch(patch, set);
136
+ params.push(eventsJson(events));
137
+ const eventsParam = params.length;
138
+ let nodeRunCte = '';
139
+ if (extras?.nodeRun) {
140
+ const n = extras.nodeRun;
141
+ const base = params.length;
142
+ params.push(n.step, n.nodeId, n.attempt, n.status, n.startedAt, n.finishedAt, json(n.output), json(n.error), n.costUsd);
143
+ nodeRunCte = `, nr AS (
144
+ INSERT INTO vk_harness_node_runs (run_id, step, node_id, attempt, status, started_at, finished_at, output, error, cost_usd)
145
+ SELECT upd.id, $${base + 1}, $${base + 2}, $${base + 3}, $${base + 4}, $${base + 5}, $${base + 6}, $${base + 7}::jsonb, $${base + 8}::jsonb, $${base + 9}
146
+ FROM upd
147
+ ON CONFLICT (run_id, step, attempt) DO NOTHING
148
+ RETURNING 1
149
+ )`;
150
+ }
151
+ const rows = await querier(`WITH upd AS (
152
+ UPDATE vk_harness_runs SET ${sets.join(', ')}
153
+ WHERE id = $1 AND version = $2
154
+ RETURNING ${RUN_COLUMNS}, event_seq AS "eventSeq"
155
+ ), ev AS (
156
+ INSERT INTO vk_harness_events (run_id, seq, at, type, node_id, step, attempt, label, detail, data)
157
+ SELECT upd.id, upd."eventSeq" - $3 + e.i, COALESCE(e.at, now()), e.type, e.node_id, e.step, e.attempt, e.label, e.detail, e.data
158
+ FROM upd, ${EVENT_RECORDSET.replace('$EVENTS', `$${eventsParam}`)}
159
+ RETURNING 1
160
+ )${nodeRunCte}
161
+ SELECT * FROM upd`, params);
162
+ return rows[0] ? fromRow(rows[0]) : null;
163
+ },
164
+ async appendEvents(id, events) {
165
+ if (events.length === 0)
166
+ return;
167
+ await querier(`WITH s AS (
168
+ UPDATE vk_harness_runs SET event_seq = event_seq + $2 WHERE id = $1 RETURNING id, event_seq
169
+ )
170
+ INSERT INTO vk_harness_events (run_id, seq, at, type, node_id, step, attempt, label, detail, data)
171
+ SELECT s.id, s.event_seq - $2 + e.i, COALESCE(e.at, now()), e.type, e.node_id, e.step, e.attempt, e.label, e.detail, e.data
172
+ FROM s, ${EVENT_RECORDSET.replace('$EVENTS', '$3')}`, [id, events.length, eventsJson(events)]);
173
+ },
174
+ async extendLease(id, version, leaseUntil) {
175
+ const rows = await querier(`UPDATE vk_harness_runs SET lease_until = $3 WHERE id = $1 AND version = $2 AND status = 'running' RETURNING id`, [id, version, leaseUntil]);
176
+ return rows.length > 0;
177
+ },
178
+ async requestCancel(id) {
179
+ await querier(`UPDATE vk_harness_runs SET cancel_requested = true, updated_at = now() WHERE id = $1`, [id]);
180
+ },
181
+ async isCancelRequested(id) {
182
+ const rows = await querier(`SELECT cancel_requested AS "cancelRequested" FROM vk_harness_runs WHERE id = $1`, [id]);
183
+ return rows[0]?.cancelRequested === true;
184
+ },
185
+ async listEvents(id, { afterSeq, limit }) {
186
+ const rows = await querier(`SELECT run_id AS "runId", seq, at, type, node_id AS "nodeId", step, attempt, label, detail, data
187
+ FROM vk_harness_events
188
+ WHERE run_id = $1 AND seq > $2
189
+ ORDER BY seq
190
+ LIMIT $3`, [id, afterSeq ?? 0, limit]);
191
+ return rows.map((r) => ({ ...r, seq: Number(r.seq), at: iso(r.at) }));
192
+ },
193
+ async getMapItems(runId, step) {
194
+ const rows = await querier(`SELECT item_index AS "index", output FROM vk_harness_map_items
195
+ WHERE run_id = $1 AND step = $2 AND status = 'done'`, [runId, step]);
196
+ return new Map(rows.map((r) => [Number(r.index), r.output]));
197
+ },
198
+ async putMapItem(runId, step, index, output) {
199
+ await querier(`INSERT INTO vk_harness_map_items (run_id, step, item_index, output, status) VALUES ($1, $2, $3, $4::jsonb, 'done')
200
+ ON CONFLICT (run_id, step, item_index) DO UPDATE
201
+ SET status = 'done', output = EXCLUDED.output, lease_until = NULL, updated_at = now()
202
+ WHERE vk_harness_map_items.status <> 'done'`, [runId, step, index, json(output)]);
203
+ },
204
+ // ─── Fan-out ───────────────────────────────────────────────────
205
+ async listMapItems(runId, step) {
206
+ const rows = await querier(`SELECT ${ITEM_COLUMNS} FROM vk_harness_map_items WHERE run_id = $1 AND step = $2 ORDER BY item_index`, [runId, step]);
207
+ return rows.map(fromItemRow);
208
+ },
209
+ async beginMap(runId, expectedVersion, { step, items, events, addCostUsd }) {
210
+ const rows = await querier(`WITH upd AS (
211
+ UPDATE vk_harness_runs
212
+ SET version = version + 1, updated_at = now(), lease_until = NULL, event_seq = event_seq + $4,
213
+ cost_usd = cost_usd + $7
214
+ WHERE id = $1 AND version = $2 AND status = 'running'
215
+ RETURNING ${RUN_COLUMNS}, event_seq AS "eventSeq"
216
+ ), items AS (
217
+ INSERT INTO vk_harness_map_items (run_id, step, item_index, input, status, attempt, attempt_base, updated_at)
218
+ SELECT upd.id, $3, x.i, x.input, x.status, 0, 0, now()
219
+ FROM upd, jsonb_to_recordset($5::jsonb) AS x(i int, input jsonb, status text)
220
+ -- A done item keeps its output; every item's spend restarts at 0 (the
221
+ -- earlier attempt charged it to the run when it ended).
222
+ ON CONFLICT (run_id, step, item_index) DO UPDATE SET
223
+ status = CASE WHEN vk_harness_map_items.status = 'done' THEN 'done' ELSE EXCLUDED.status END,
224
+ input = CASE WHEN vk_harness_map_items.status = 'done' THEN vk_harness_map_items.input ELSE EXCLUDED.input END,
225
+ output = CASE WHEN vk_harness_map_items.status = 'done' THEN vk_harness_map_items.output ELSE NULL END,
226
+ error = CASE WHEN vk_harness_map_items.status = 'done' THEN vk_harness_map_items.error ELSE NULL END,
227
+ attempt_base = CASE WHEN vk_harness_map_items.status = 'done' THEN vk_harness_map_items.attempt_base ELSE vk_harness_map_items.attempt END,
228
+ lease_until = NULL,
229
+ not_before = NULL,
230
+ cost_usd = 0,
231
+ updated_at = now()
232
+ RETURNING item_index
233
+ ), counts AS (
234
+ SELECT (SELECT count(*) FROM jsonb_array_elements($5::jsonb))::int AS total,
235
+ (SELECT count(*) FROM vk_harness_map_items m, upd
236
+ WHERE m.run_id = upd.id AND m.step = $3 AND m.status = 'done'
237
+ AND m.item_index IN (SELECT (e->>'i')::int FROM jsonb_array_elements($5::jsonb) e))::int AS done
238
+ ), j AS (
239
+ INSERT INTO vk_harness_map_joins (run_id, step, total, done)
240
+ SELECT upd.id, $3, counts.total, counts.done FROM upd, counts
241
+ ON CONFLICT (run_id, step) DO UPDATE SET total = EXCLUDED.total, done = EXCLUDED.done, updated_at = now()
242
+ RETURNING done, total
243
+ ), ev AS (
244
+ INSERT INTO vk_harness_events (run_id, seq, at, type, node_id, step, attempt, label, detail, data)
245
+ SELECT upd.id, upd."eventSeq" - $4 + e.i, COALESCE(e.at, now()), e.type, e.node_id, e.step, e.attempt, e.label, e.detail, e.data
246
+ FROM upd, ${EVENT_RECORDSET.replace('$EVENTS', '$6')}
247
+ RETURNING 1
248
+ )
249
+ SELECT upd.*, j.done AS "mapDone", j.total AS "mapTotal" FROM upd, j`, [
250
+ runId,
251
+ expectedVersion,
252
+ step,
253
+ events.length,
254
+ JSON.stringify(items.map((it) => ({ i: it.index, input: it.input ?? null, status: it.status }))),
255
+ eventsJson(events),
256
+ addCostUsd,
257
+ ]);
258
+ const row = rows[0];
259
+ return row
260
+ ? { run: fromRow(row), done: Number(row.mapDone), total: Number(row.mapTotal) }
261
+ : null;
262
+ },
263
+ async claimMapItem(runId, step, index, leaseUntil) {
264
+ const rows = await querier(`UPDATE vk_harness_map_items
265
+ SET status = 'running', attempt = attempt + 1, lease_until = $4, updated_at = now()
266
+ WHERE run_id = $1 AND step = $2 AND item_index = $3 AND status = 'queued'
267
+ RETURNING ${ITEM_COLUMNS}`, [runId, step, index, leaseUntil]);
268
+ return rows[0] ? fromItemRow(rows[0]) : null;
269
+ },
270
+ async extendMapItemLease(runId, step, index, attempt, leaseUntil) {
271
+ const rows = await querier(`UPDATE vk_harness_map_items SET lease_until = $5
272
+ WHERE run_id = $1 AND step = $2 AND item_index = $3 AND attempt = $4 AND status = 'running'
273
+ RETURNING item_index AS i`, [runId, step, index, attempt, leaseUntil]);
274
+ return rows.length > 0;
275
+ },
276
+ async completeMapItem(runId, step, index, attempt, { output, costUsd }) {
277
+ const rows = await querier(`WITH item AS (
278
+ UPDATE vk_harness_map_items
279
+ SET status = 'done', output = $5::jsonb, cost_usd = cost_usd + $6, lease_until = NULL,
280
+ error = NULL, updated_at = now()
281
+ WHERE run_id = $1 AND step = $2 AND item_index = $3 AND attempt = $4 AND status = 'running'
282
+ RETURNING 1
283
+ )
284
+ UPDATE vk_harness_map_joins SET done = done + 1, updated_at = now()
285
+ WHERE run_id = $1 AND step = $2 AND EXISTS (SELECT 1 FROM item)
286
+ RETURNING done, total`, [runId, step, index, attempt, json(output), costUsd]);
287
+ return rows[0] ? { done: Number(rows[0].done), total: Number(rows[0].total) } : null;
288
+ },
289
+ async releaseMapItem(runId, step, index, attempt, next) {
290
+ const rows = await querier(`UPDATE vk_harness_map_items
291
+ SET status = $5, not_before = $6, error = $7::jsonb, cost_usd = cost_usd + $8,
292
+ lease_until = NULL, updated_at = now()
293
+ WHERE run_id = $1 AND step = $2 AND item_index = $3 AND attempt = $4 AND status = 'running'
294
+ RETURNING item_index AS i`, [runId, step, index, attempt, next.status, next.notBefore, json(next.error), next.costUsd]);
295
+ return rows.length > 0;
296
+ },
297
+ async claimNextMapItem(runId, step) {
298
+ const rows = await querier(`UPDATE vk_harness_map_items SET status = 'queued', updated_at = now()
299
+ WHERE (run_id, step, item_index) = (
300
+ SELECT run_id, step, item_index FROM vk_harness_map_items
301
+ WHERE run_id = $1 AND step = $2 AND status = 'pending'
302
+ ORDER BY item_index
303
+ LIMIT 1
304
+ FOR UPDATE SKIP LOCKED
305
+ )
306
+ RETURNING item_index AS i`, [runId, step]);
307
+ return rows[0] ? Number(rows[0].i) : null;
308
+ },
309
+ async findMapItemsToSweep({ now, quietBefore, limit }) {
310
+ const rows = await querier(`SELECT m.run_id AS "runId", m.step, m.item_index AS "index", m.status, m.attempt
311
+ FROM vk_harness_map_items m
312
+ JOIN vk_harness_runs r ON r.id = m.run_id AND r.status = 'running' AND r.step = m.step
313
+ WHERE (m.status = 'queued' AND (m.not_before IS NULL OR m.not_before <= $1) AND m.updated_at < $2)
314
+ OR (m.status = 'running' AND m.lease_until < $1)
315
+ ORDER BY m.updated_at
316
+ LIMIT $3`, [now, quietBefore, limit]);
317
+ return rows.map((r) => ({
318
+ ...r,
319
+ step: Number(r.step),
320
+ index: Number(r.index),
321
+ attempt: Number(r.attempt),
322
+ }));
323
+ },
324
+ async touchMapItem(runId, step, index) {
325
+ const rows = await querier(`UPDATE vk_harness_map_items SET updated_at = now()
326
+ WHERE run_id = $1 AND step = $2 AND item_index = $3 AND status = 'queued'
327
+ RETURNING item_index AS i`, [runId, step, index]);
328
+ return rows.length > 0;
329
+ },
330
+ async findRunsToSweep({ now, staleBefore, quietBefore, limit }) {
331
+ const rows = await querier(`SELECT ${RUN_COLUMNS}
332
+ FROM vk_harness_runs
333
+ WHERE (status = 'queued' AND not_before IS NULL AND updated_at < $2)
334
+ OR (status = 'queued' AND not_before <= $1 AND updated_at < $3)
335
+ OR (status = 'running' AND lease_until < $1)
336
+ ORDER BY updated_at
337
+ LIMIT $4`, [now, staleBefore, quietBefore, limit]);
338
+ return rows.map(fromRow);
339
+ },
340
+ };
341
+ }
342
+ function applyPatch(patch, set) {
343
+ if (patch.status !== undefined)
344
+ set('status', patch.status);
345
+ if (patch.outputs !== undefined)
346
+ set('outputs', json(patch.outputs), '::jsonb');
347
+ if (patch.currentNode !== undefined)
348
+ set('current_node', patch.currentNode);
349
+ if (patch.step !== undefined)
350
+ set('step', patch.step);
351
+ if (patch.attempt !== undefined)
352
+ set('attempt', patch.attempt);
353
+ if (patch.attemptBase !== undefined)
354
+ set('attempt_base', patch.attemptBase);
355
+ if (patch.notBefore !== undefined)
356
+ set('not_before', patch.notBefore);
357
+ if (patch.leaseUntil !== undefined)
358
+ set('lease_until', patch.leaseUntil);
359
+ if (patch.error !== undefined)
360
+ set('error', json(patch.error), '::jsonb');
361
+ if (patch.cancelRequested !== undefined)
362
+ set('cancel_requested', patch.cancelRequested);
363
+ if (patch.costUsd !== undefined)
364
+ set('cost_usd', patch.costUsd);
365
+ if (patch.completedAt !== undefined)
366
+ set('completed_at', patch.completedAt);
367
+ }
368
+ //# sourceMappingURL=postgres-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-store.js","sourceRoot":"","sources":["../../src/harness/postgres-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { Harness, HarnessScheduler, RunTask } from './types.js';
2
+ export interface InlineScheduler extends HarnessScheduler {
3
+ /** Tasks waiting to run. */
4
+ readonly pending: RunTask[];
5
+ /** Run queued tasks (and the ones they schedule) until none is left. Delays are skipped. */
6
+ drain(harness: Harness, options?: {
7
+ maxTasks?: number;
8
+ }): Promise<number>;
9
+ }
10
+ /** A scheduler that keeps tasks in memory and runs them on `drain()` — tests and scripts. */
11
+ export declare function createInlineScheduler(): InlineScheduler;
12
+ //# sourceMappingURL=scheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/harness/scheduler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErE,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACvD,4BAA4B;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC;IAC5B,4FAA4F;IAC5F,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC3E;AAED,6FAA6F;AAC7F,wBAAgB,qBAAqB,IAAI,eAAe,CAoBvD"}
@@ -0,0 +1,23 @@
1
+ /** A scheduler that keeps tasks in memory and runs them on `drain()` — tests and scripts. */
2
+ export function createInlineScheduler() {
3
+ const pending = [];
4
+ return {
5
+ pending,
6
+ async enqueue(task) {
7
+ pending.push({ ...task });
8
+ },
9
+ async drain(harness, options = {}) {
10
+ const max = options.maxTasks ?? 1000;
11
+ let ran = 0;
12
+ while (pending.length > 0) {
13
+ if (ran >= max)
14
+ throw new Error(`[ai/harness] drain: more than ${max} tasks — a loop that never ends?`);
15
+ const task = pending.shift();
16
+ ran += 1;
17
+ await harness.execute(task, { ignoreDelay: true });
18
+ }
19
+ return ran;
20
+ },
21
+ };
22
+ }
23
+ //# sourceMappingURL=scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/harness/scheduler.ts"],"names":[],"mappings":"AASA,6FAA6F;AAC7F,MAAM,UAAU,qBAAqB;IACnC,MAAM,OAAO,GAAc,EAAE,CAAC;IAC9B,OAAO;QACL,OAAO;QACP,KAAK,CAAC,OAAO,CAAC,IAAI;YAChB,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;QAC5B,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,EAAE;YAC/B,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC;YACrC,IAAI,GAAG,GAAG,CAAC,CAAC;YACZ,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,IAAI,GAAG,IAAI,GAAG;oBACZ,MAAM,IAAI,KAAK,CAAC,iCAAiC,GAAG,kCAAkC,CAAC,CAAC;gBAC1F,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,EAAG,CAAC;gBAC9B,GAAG,IAAI,CAAC,CAAC;gBACT,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;YACrD,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Harness persistence. Two implementations: `createMemoryHarnessStore`
3
+ * (tests, local tools) and `createPostgresHarnessStore` (migration
4
+ * `vk_ai_cost_0005_harness.sql`).
5
+ *
6
+ * Concurrency: every state change of a run is a compare-and-set on its
7
+ * `version`, applied together with its events and node-run row in one
8
+ * atomic write. The lease renewal and the cancel flag are the only
9
+ * writes that don't bump the version, so they never invalidate a
10
+ * worker's pending commit. Fanned-out map items have their own
11
+ * compare-and-set (status + attempt); the join counter is bumped in the
12
+ * same write as the item, so exactly one item sees `done === total`.
13
+ */
14
+ import type { RunError, RunEvent, RunRecord, RunStatus } from './types.js';
15
+ export interface StoredRun extends RunRecord {
16
+ version: number;
17
+ leaseUntil: string | null;
18
+ /** Attempts consumed before the last `retry()` (the node's attempt budget restarts there). */
19
+ attemptBase: number;
20
+ }
21
+ export type NewRunEvent = Omit<RunEvent, 'runId' | 'seq' | 'at'> & {
22
+ at?: string;
23
+ };
24
+ export interface NodeRunRow {
25
+ step: number;
26
+ nodeId: string;
27
+ attempt: number;
28
+ status: 'succeeded' | 'failed' | 'cancelled';
29
+ startedAt: string;
30
+ finishedAt: string;
31
+ output: unknown;
32
+ error: RunError | null;
33
+ costUsd: number;
34
+ }
35
+ export interface RunPatch {
36
+ status?: RunStatus;
37
+ outputs?: Record<string, unknown>;
38
+ currentNode?: string | null;
39
+ step?: number;
40
+ attempt?: number;
41
+ attemptBase?: number;
42
+ notBefore?: string | null;
43
+ leaseUntil?: string | null;
44
+ error?: RunError | null;
45
+ cancelRequested?: boolean;
46
+ costUsd?: number;
47
+ completedAt?: string | null;
48
+ }
49
+ /**
50
+ * One item of a map node. Inline maps only write `done` rows; a fanned-out
51
+ * map (`dispatch: 'tasks'`) moves each item pending → queued (its task is
52
+ * on the queue) → running (leased) → done, or back to queued to retry, or
53
+ * failed.
54
+ */
55
+ export type MapItemStatus = 'pending' | 'queued' | 'running' | 'done' | 'failed';
56
+ export interface MapItemRow {
57
+ index: number;
58
+ status: MapItemStatus;
59
+ input: unknown;
60
+ output: unknown;
61
+ /** Attempts so far (fan-out only). Never reset: the compare-and-set token of a running item. */
62
+ attempt: number;
63
+ /** `attempt` when the current node attempt fanned out — the item's retry budget counts from there. */
64
+ attemptBase: number;
65
+ leaseUntil: string | null;
66
+ notBefore: string | null;
67
+ error: RunError | null;
68
+ costUsd: number;
69
+ updatedAt: string;
70
+ }
71
+ /** Fan-out storage (`dispatch: 'tasks'` map nodes). Both built-in stores implement it. */
72
+ export interface HarnessMapStore {
73
+ listMapItems(runId: string, step: number): Promise<MapItemRow[]>;
74
+ /**
75
+ * Fan a map node out in ONE write: CAS the run (lease released, stays
76
+ * `running`, version bumped, `addCostUsd` added), upsert the items (a
77
+ * `done` item stays done — a retry only redoes the others, which start
78
+ * a fresh budget: `attemptBase = attempt`; every item's spend restarts
79
+ * at 0, since the earlier attempt charged it to the run when it ended)
80
+ * and set the join counter (`total`, `done` = items already done).
81
+ * `null` on a version conflict.
82
+ */
83
+ beginMap(runId: string, expectedVersion: number, args: {
84
+ step: number;
85
+ items: Array<{
86
+ index: number;
87
+ input: unknown;
88
+ status: 'pending' | 'queued';
89
+ }>;
90
+ events: NewRunEvent[];
91
+ addCostUsd: number;
92
+ }): Promise<{
93
+ run: StoredRun;
94
+ done: number;
95
+ total: number;
96
+ } | null>;
97
+ /** queued → running with a lease, attempt + 1. `null` when the item isn't queued. */
98
+ claimMapItem(runId: string, step: number, index: number, leaseUntil: string): Promise<MapItemRow | null>;
99
+ extendMapItemLease(runId: string, step: number, index: number, attempt: number, leaseUntil: string): Promise<boolean>;
100
+ /**
101
+ * running (this attempt) → done, and bump the join counter in the same
102
+ * write. Returns the counter; `null` when the item moved on.
103
+ */
104
+ completeMapItem(runId: string, step: number, index: number, attempt: number, result: {
105
+ output: unknown;
106
+ costUsd: number;
107
+ }): Promise<{
108
+ done: number;
109
+ total: number;
110
+ } | null>;
111
+ /** running (this attempt) → queued (retry, `notBefore`) or failed. Spend is added. False when it moved on. */
112
+ releaseMapItem(runId: string, step: number, index: number, attempt: number, next: {
113
+ status: 'queued' | 'failed';
114
+ notBefore: string | null;
115
+ error: RunError;
116
+ costUsd: number;
117
+ }): Promise<boolean>;
118
+ /** The lowest pending item → queued (its task can be sent). `null` when none is pending. */
119
+ claimNextMapItem(runId: string, step: number): Promise<number | null>;
120
+ /**
121
+ * Items of running runs the sweep must look at: queued ones due and
122
+ * quiet since `quietBefore` (task lost), running ones whose lease expired.
123
+ */
124
+ findMapItemsToSweep(args: {
125
+ now: string;
126
+ quietBefore: string;
127
+ limit: number;
128
+ }): Promise<Array<{
129
+ runId: string;
130
+ step: number;
131
+ index: number;
132
+ status: 'queued' | 'running';
133
+ attempt: number;
134
+ }>>;
135
+ /** Re-touch a queued item before its task is re-sent (the next sweep waits again). */
136
+ touchMapItem(runId: string, step: number, index: number): Promise<boolean>;
137
+ }
138
+ export interface HarnessStore extends Partial<HarnessMapStore> {
139
+ insertRun(run: StoredRun, events: NewRunEvent[]): Promise<void>;
140
+ getRun(id: string): Promise<StoredRun | null>;
141
+ /** CAS on `version`: apply the patch, bump the version, append the events and the node-run row. `null` on conflict. */
142
+ updateRun(id: string, expectedVersion: number, patch: RunPatch, extras?: {
143
+ events?: NewRunEvent[];
144
+ nodeRun?: NodeRunRow;
145
+ }): Promise<StoredRun | null>;
146
+ appendEvents(id: string, events: NewRunEvent[]): Promise<void>;
147
+ /** Renew a running node's lease (no version bump). False when the run moved on. */
148
+ extendLease(id: string, version: number, leaseUntil: string): Promise<boolean>;
149
+ /** Raise the cancel flag (no version bump). */
150
+ requestCancel(id: string): Promise<void>;
151
+ isCancelRequested(id: string): Promise<boolean>;
152
+ listEvents(id: string, options: {
153
+ afterSeq?: number;
154
+ limit: number;
155
+ }): Promise<RunEvent[]>;
156
+ getMapItems(runId: string, step: number): Promise<Map<number, unknown>>;
157
+ putMapItem(runId: string, step: number, index: number, output: unknown): Promise<void>;
158
+ /**
159
+ * Runs the sweep must look at: queued runs whose task is due and quiet
160
+ * since `quietBefore` (lost, or held back for a long delay), queued runs
161
+ * without a delay quiet since `staleBefore`, and running runs whose
162
+ * lease expired before `now`.
163
+ */
164
+ findRunsToSweep(args: {
165
+ now: string;
166
+ staleBefore: string;
167
+ quietBefore: string;
168
+ limit: number;
169
+ }): Promise<StoredRun[]>;
170
+ }
171
+ export declare function toRunRecord(run: StoredRun): RunRecord;
172
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/harness/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Harness persistence. Two implementations: `createMemoryHarnessStore`
3
+ * (tests, local tools) and `createPostgresHarnessStore` (migration
4
+ * `vk_ai_cost_0005_harness.sql`).
5
+ *
6
+ * Concurrency: every state change of a run is a compare-and-set on its
7
+ * `version`, applied together with its events and node-run row in one
8
+ * atomic write. The lease renewal and the cancel flag are the only
9
+ * writes that don't bump the version, so they never invalidate a
10
+ * worker's pending commit. Fanned-out map items have their own
11
+ * compare-and-set (status + attempt); the join counter is bumped in the
12
+ * same write as the item, so exactly one item sees `done === total`.
13
+ */
14
+ export function toRunRecord(run) {
15
+ const { version: _v, leaseUntil: _l, attemptBase: _a, ...record } = run;
16
+ void _v;
17
+ void _l;
18
+ void _a;
19
+ return record;
20
+ }
21
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/harness/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAgLH,MAAM,UAAU,WAAW,CAAC,GAAc;IACxC,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,GAAG,MAAM,EAAE,GAAG,GAAG,CAAC;IACxE,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;IACR,OAAO,MAAM,CAAC;AAChB,CAAC"}