@possumtech/rummy 0.2.7 → 0.2.8
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/.env.example +1 -2
- package/PLUGINS.md +105 -82
- package/migrations/001_initial_schema.sql +53 -68
- package/package.json +4 -6
- package/service.js +1 -1
- package/src/agent/AgentLoop.js +91 -58
- package/src/agent/ContextAssembler.js +2 -2
- package/src/agent/KnownStore.js +30 -11
- package/src/agent/ProjectAgent.js +1 -3
- package/src/agent/TurnExecutor.js +119 -31
- package/src/agent/XmlParser.js +20 -0
- package/src/agent/known_checks.sql +5 -4
- package/src/agent/known_queries.sql +4 -3
- package/src/agent/known_store.sql +29 -15
- package/src/agent/loops.sql +63 -0
- package/src/agent/runs.sql +7 -7
- package/src/agent/schemes.sql +2 -2
- package/src/agent/turns.sql +3 -3
- package/src/hooks/PluginContext.js +1 -10
- package/src/hooks/RummyContext.js +16 -8
- package/src/plugins/ask_user/ask_user.js +3 -2
- package/src/plugins/cp/cp.js +7 -7
- package/src/plugins/current/current.js +3 -4
- package/src/plugins/engine/engine.sql +5 -3
- package/src/plugins/engine/turn_context.sql +9 -4
- package/src/plugins/env/docs.md +2 -0
- package/src/plugins/env/env.js +3 -2
- package/src/plugins/file/file.js +9 -19
- package/src/plugins/get/docs.md +7 -3
- package/src/plugins/get/get.js +22 -6
- package/src/plugins/hedberg/docs.md +0 -9
- package/src/plugins/hedberg/hedberg.js +2 -5
- package/src/plugins/hedberg/matcher.js +1 -1
- package/src/plugins/hedberg/patterns.js +6 -6
- package/src/plugins/helpers.js +2 -2
- package/src/plugins/index.js +28 -15
- package/src/plugins/instructions/instructions.js +1 -1
- package/src/plugins/known/known.js +9 -11
- package/src/plugins/mv/mv.js +7 -7
- package/src/plugins/previous/previous.js +6 -5
- package/src/plugins/progress/progress.js +6 -0
- package/src/plugins/prompt/prompt.js +9 -10
- package/src/plugins/rm/docs.md +3 -1
- package/src/plugins/rm/rm.js +24 -7
- package/src/plugins/rpc/rpc.js +33 -42
- package/src/plugins/set/docs.md +3 -1
- package/src/plugins/set/set.js +22 -16
- package/src/plugins/sh/sh.js +3 -2
- package/src/plugins/skills/skills.js +3 -4
- package/src/plugins/store/docs.md +2 -1
- package/src/plugins/store/store.js +14 -3
- package/src/plugins/summarize/summarize.js +1 -1
- package/src/plugins/telemetry/telemetry.js +17 -7
- package/src/plugins/unknown/unknown.js +3 -2
- package/src/plugins/update/update.js +1 -1
- package/src/server/ClientConnection.js +3 -5
- package/src/sql/v_model_context.sql +20 -23
- package/src/sql/v_run_log.sql +3 -3
- package/src/agent/prompt_queue.sql +0 -39
package/src/agent/AgentLoop.js
CHANGED
|
@@ -119,7 +119,7 @@ export default class AgentLoop {
|
|
|
119
119
|
if (runInfo.blocked) {
|
|
120
120
|
return {
|
|
121
121
|
run: runInfo.alias,
|
|
122
|
-
status:
|
|
122
|
+
status: 202,
|
|
123
123
|
remainingCount: runInfo.proposed.length,
|
|
124
124
|
proposed: runInfo.proposed,
|
|
125
125
|
};
|
|
@@ -127,8 +127,10 @@ export default class AgentLoop {
|
|
|
127
127
|
|
|
128
128
|
const { runId: currentRunId, alias: currentAlias } = runInfo;
|
|
129
129
|
|
|
130
|
-
await this.#db.
|
|
130
|
+
const loopSeq = await this.#db.next_loop.get({ run_id: currentRunId });
|
|
131
|
+
await this.#db.enqueue_loop.get({
|
|
131
132
|
run_id: currentRunId,
|
|
133
|
+
sequence: loopSeq.sequence,
|
|
132
134
|
mode,
|
|
133
135
|
model: requestedModel,
|
|
134
136
|
prompt: prompt || "",
|
|
@@ -136,7 +138,7 @@ export default class AgentLoop {
|
|
|
136
138
|
});
|
|
137
139
|
|
|
138
140
|
if (this.#activeRuns.has(currentRunId)) {
|
|
139
|
-
return { run: currentAlias, status:
|
|
141
|
+
return { run: currentAlias, status: 100 };
|
|
140
142
|
}
|
|
141
143
|
|
|
142
144
|
return this.#drainQueue(
|
|
@@ -150,35 +152,37 @@ export default class AgentLoop {
|
|
|
150
152
|
|
|
151
153
|
async #drainQueue(currentRunId, currentAlias, projectId, project, options) {
|
|
152
154
|
while (true) {
|
|
153
|
-
const
|
|
155
|
+
const loop = await this.#db.claim_next_loop.get({
|
|
154
156
|
run_id: currentRunId,
|
|
155
157
|
});
|
|
156
|
-
if (!
|
|
158
|
+
if (!loop) break;
|
|
157
159
|
|
|
158
|
-
const
|
|
160
|
+
const loopConfig = loop.config ? JSON.parse(loop.config) : {};
|
|
159
161
|
const result = await this.#executeLoop({
|
|
160
|
-
mode:
|
|
162
|
+
mode: loop.mode,
|
|
161
163
|
project,
|
|
162
164
|
projectId,
|
|
163
165
|
currentRunId,
|
|
164
166
|
currentAlias,
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
167
|
+
currentLoopId: loop.id,
|
|
168
|
+
requestedModel: loop.model,
|
|
169
|
+
prompt: loop.prompt,
|
|
170
|
+
noContext: loopConfig.noContext || false,
|
|
171
|
+
options: { ...options, temperature: loopConfig.temperature },
|
|
172
|
+
hook: loop.mode === "ask" ? this.#hooks.ask : this.#hooks.act,
|
|
170
173
|
});
|
|
171
174
|
|
|
172
|
-
await this.#db.
|
|
173
|
-
id:
|
|
175
|
+
await this.#db.complete_loop.run({
|
|
176
|
+
id: loop.id,
|
|
177
|
+
status: result.status === 202 ? 202 : result.status,
|
|
174
178
|
result: JSON.stringify(result),
|
|
175
179
|
});
|
|
176
180
|
|
|
177
|
-
if (result.status ===
|
|
181
|
+
if (result.status === 202) return result;
|
|
178
182
|
}
|
|
179
183
|
|
|
180
184
|
const runRow = await this.#db.get_run_by_alias.get({ alias: currentAlias });
|
|
181
|
-
return { run: currentAlias, status: runRow?.status
|
|
185
|
+
return { run: currentAlias, status: runRow?.status ?? 200 };
|
|
182
186
|
}
|
|
183
187
|
|
|
184
188
|
async #executeLoop({
|
|
@@ -187,6 +191,7 @@ export default class AgentLoop {
|
|
|
187
191
|
projectId,
|
|
188
192
|
currentRunId,
|
|
189
193
|
currentAlias,
|
|
194
|
+
currentLoopId,
|
|
190
195
|
requestedModel,
|
|
191
196
|
prompt,
|
|
192
197
|
noContext,
|
|
@@ -194,10 +199,10 @@ export default class AgentLoop {
|
|
|
194
199
|
hook,
|
|
195
200
|
}) {
|
|
196
201
|
const runRow = await this.#db.get_run_by_id.get({ id: currentRunId });
|
|
197
|
-
if (runRow.status !==
|
|
202
|
+
if (runRow.status !== 102) {
|
|
198
203
|
await this.#db.update_run_status.run({
|
|
199
204
|
id: currentRunId,
|
|
200
|
-
status:
|
|
205
|
+
status: 102,
|
|
201
206
|
});
|
|
202
207
|
}
|
|
203
208
|
|
|
@@ -219,11 +224,11 @@ export default class AgentLoop {
|
|
|
219
224
|
if (controller.signal.aborted) {
|
|
220
225
|
await this.#db.update_run_status.run({
|
|
221
226
|
id: currentRunId,
|
|
222
|
-
status:
|
|
227
|
+
status: 499,
|
|
223
228
|
});
|
|
224
229
|
const out = {
|
|
225
230
|
run: currentAlias,
|
|
226
|
-
status:
|
|
231
|
+
status: 499,
|
|
227
232
|
turn: loopIteration,
|
|
228
233
|
};
|
|
229
234
|
await hook.completed.emit({ projectId, ...out });
|
|
@@ -247,6 +252,7 @@ export default class AgentLoop {
|
|
|
247
252
|
projectId,
|
|
248
253
|
currentRunId,
|
|
249
254
|
currentAlias,
|
|
255
|
+
currentLoopId,
|
|
250
256
|
requestedModel,
|
|
251
257
|
loopPrompt: turnPrompt,
|
|
252
258
|
noContext,
|
|
@@ -265,14 +271,14 @@ export default class AgentLoop {
|
|
|
265
271
|
const unresolved = await this.#knownStore.getUnresolved(currentRunId);
|
|
266
272
|
|
|
267
273
|
const latestSummary = history
|
|
268
|
-
.filter((e) => e.status === "
|
|
274
|
+
.filter((e) => e.status === 200 && e.path?.startsWith("summarize://"))
|
|
269
275
|
.at(-1);
|
|
270
276
|
|
|
271
277
|
await this.#hooks.run.state.emit({
|
|
272
278
|
projectId,
|
|
273
279
|
run: currentAlias,
|
|
274
280
|
turn: result.turn,
|
|
275
|
-
status: unresolved.length > 0 ?
|
|
281
|
+
status: unresolved.length > 0 ? 202 : 102,
|
|
276
282
|
summary: latestSummary?.body || "",
|
|
277
283
|
history,
|
|
278
284
|
unknowns: unknowns.map((u) => ({ path: u.path, body: u.body })),
|
|
@@ -286,6 +292,12 @@ export default class AgentLoop {
|
|
|
286
292
|
model: result.model,
|
|
287
293
|
temperature: result.temperature,
|
|
288
294
|
context_size: result.contextSize,
|
|
295
|
+
context_tokens: (
|
|
296
|
+
await this.#db.get_turn_budget.get({
|
|
297
|
+
run_id: currentRunId,
|
|
298
|
+
turn: result.turn,
|
|
299
|
+
})
|
|
300
|
+
).total,
|
|
289
301
|
prompt_tokens: runUsage.prompt_tokens,
|
|
290
302
|
cached_tokens: runUsage.cached_tokens,
|
|
291
303
|
completion_tokens: runUsage.completion_tokens,
|
|
@@ -301,11 +313,11 @@ export default class AgentLoop {
|
|
|
301
313
|
if (unresolved.length > 0) {
|
|
302
314
|
await this.#db.update_run_status.run({
|
|
303
315
|
id: currentRunId,
|
|
304
|
-
status:
|
|
316
|
+
status: 202,
|
|
305
317
|
});
|
|
306
318
|
const out = {
|
|
307
319
|
run: currentAlias,
|
|
308
|
-
status:
|
|
320
|
+
status: 202,
|
|
309
321
|
turn: result.turn,
|
|
310
322
|
proposed: unresolved,
|
|
311
323
|
};
|
|
@@ -324,11 +336,11 @@ export default class AgentLoop {
|
|
|
324
336
|
if (!repetition.continue) {
|
|
325
337
|
await this.#db.update_run_status.run({
|
|
326
338
|
id: currentRunId,
|
|
327
|
-
status:
|
|
339
|
+
status: 200,
|
|
328
340
|
});
|
|
329
341
|
const out = {
|
|
330
342
|
run: currentAlias,
|
|
331
|
-
status:
|
|
343
|
+
status: 200,
|
|
332
344
|
turn: result.turn,
|
|
333
345
|
reason: repetition.reason,
|
|
334
346
|
};
|
|
@@ -341,11 +353,11 @@ export default class AgentLoop {
|
|
|
341
353
|
|
|
342
354
|
await this.#db.update_run_status.run({
|
|
343
355
|
id: currentRunId,
|
|
344
|
-
status:
|
|
356
|
+
status: 200,
|
|
345
357
|
});
|
|
346
358
|
const out = {
|
|
347
359
|
run: currentAlias,
|
|
348
|
-
status:
|
|
360
|
+
status: 200,
|
|
349
361
|
turn: result.turn,
|
|
350
362
|
};
|
|
351
363
|
await hook.completed.emit({ projectId, ...out });
|
|
@@ -354,11 +366,11 @@ export default class AgentLoop {
|
|
|
354
366
|
|
|
355
367
|
await this.#db.update_run_status.run({
|
|
356
368
|
id: currentRunId,
|
|
357
|
-
status:
|
|
369
|
+
status: 200,
|
|
358
370
|
});
|
|
359
371
|
const out = {
|
|
360
372
|
run: currentAlias,
|
|
361
|
-
status:
|
|
373
|
+
status: 200,
|
|
362
374
|
turn: loopIteration,
|
|
363
375
|
};
|
|
364
376
|
await hook.completed.emit({ projectId, ...out });
|
|
@@ -367,15 +379,15 @@ export default class AgentLoop {
|
|
|
367
379
|
if (controller.signal.aborted) {
|
|
368
380
|
await this.#db.update_run_status.run({
|
|
369
381
|
id: currentRunId,
|
|
370
|
-
status:
|
|
382
|
+
status: 499,
|
|
371
383
|
});
|
|
372
|
-
return { run: currentAlias, status:
|
|
384
|
+
return { run: currentAlias, status: 499, turn: loopIteration };
|
|
373
385
|
}
|
|
374
386
|
console.warn(`[RUMMY] Run failed: ${err.message}`);
|
|
375
387
|
console.warn(`[RUMMY] Stack: ${err.stack}`);
|
|
376
388
|
await this.#db.update_run_status.run({
|
|
377
389
|
id: currentRunId,
|
|
378
|
-
status:
|
|
390
|
+
status: 500,
|
|
379
391
|
});
|
|
380
392
|
try {
|
|
381
393
|
await this.#knownStore.upsert(
|
|
@@ -383,12 +395,13 @@ export default class AgentLoop {
|
|
|
383
395
|
loopIteration,
|
|
384
396
|
`error://${loopIteration}`,
|
|
385
397
|
`${err.message}\n${err.stack}`,
|
|
386
|
-
|
|
398
|
+
500,
|
|
399
|
+
{ loopId: currentLoopId },
|
|
387
400
|
);
|
|
388
401
|
} catch {}
|
|
389
402
|
const out = {
|
|
390
403
|
run: currentAlias,
|
|
391
|
-
status:
|
|
404
|
+
status: 500,
|
|
392
405
|
turn: loopIteration,
|
|
393
406
|
error: err.message,
|
|
394
407
|
};
|
|
@@ -415,14 +428,14 @@ export default class AgentLoop {
|
|
|
415
428
|
attrs,
|
|
416
429
|
output,
|
|
417
430
|
);
|
|
418
|
-
const
|
|
419
|
-
await this.#knownStore.resolve(runId, path,
|
|
431
|
+
const status = action === "error" ? 500 : 200;
|
|
432
|
+
await this.#knownStore.resolve(runId, path, status, resolvedBody);
|
|
420
433
|
|
|
421
434
|
// Store answer in attributes for ask_user
|
|
422
435
|
if (path.startsWith("ask_user://") && output) {
|
|
423
436
|
const turn = (await this.#db.get_run_by_id.get({ id: runId }))
|
|
424
437
|
.next_turn;
|
|
425
|
-
await this.#knownStore.upsert(runId, turn, path, resolvedBody,
|
|
438
|
+
await this.#knownStore.upsert(runId, turn, path, resolvedBody, status, {
|
|
426
439
|
attributes: { ...attrs, answer: output },
|
|
427
440
|
});
|
|
428
441
|
}
|
|
@@ -441,12 +454,7 @@ export default class AgentLoop {
|
|
|
441
454
|
}
|
|
442
455
|
}
|
|
443
456
|
} else if (action === "reject") {
|
|
444
|
-
await this.#knownStore.resolve(
|
|
445
|
-
runId,
|
|
446
|
-
path,
|
|
447
|
-
"rejected",
|
|
448
|
-
output || "rejected",
|
|
449
|
-
);
|
|
457
|
+
await this.#knownStore.resolve(runId, path, 403, output || "rejected");
|
|
450
458
|
} else {
|
|
451
459
|
throw new Error(msg("error.resolution_invalid", { action }));
|
|
452
460
|
}
|
|
@@ -455,23 +463,46 @@ export default class AgentLoop {
|
|
|
455
463
|
if (unresolved.length > 0) {
|
|
456
464
|
return {
|
|
457
465
|
run: runAlias,
|
|
458
|
-
status:
|
|
466
|
+
status: 202,
|
|
459
467
|
remainingCount: unresolved.length,
|
|
460
468
|
proposed: unresolved,
|
|
461
469
|
};
|
|
462
470
|
}
|
|
463
471
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
472
|
+
// Scope completion checks to the current loop
|
|
473
|
+
const currentLoop = await this.#db.get_current_loop.get({ run_id: runId });
|
|
474
|
+
const loopId = currentLoop?.id ?? null;
|
|
475
|
+
|
|
476
|
+
if (await this.#knownStore.hasRejections(runId, loopId)) {
|
|
477
|
+
if (currentLoop)
|
|
478
|
+
await this.#db.complete_loop.run({
|
|
479
|
+
id: loopId,
|
|
480
|
+
status: 200,
|
|
481
|
+
result: null,
|
|
482
|
+
});
|
|
483
|
+
await this.#db.update_run_status.run({ id: runId, status: 200 });
|
|
484
|
+
return { run: runAlias, status: 200 };
|
|
467
485
|
}
|
|
468
486
|
|
|
469
|
-
const hasSummary = await this.#db.get_latest_summary.get({
|
|
487
|
+
const hasSummary = await this.#db.get_latest_summary.get({
|
|
488
|
+
run_id: runId,
|
|
489
|
+
loop_id: loopId,
|
|
490
|
+
});
|
|
470
491
|
if (hasSummary?.body) {
|
|
471
|
-
|
|
472
|
-
|
|
492
|
+
if (currentLoop)
|
|
493
|
+
await this.#db.complete_loop.run({
|
|
494
|
+
id: loopId,
|
|
495
|
+
status: 200,
|
|
496
|
+
result: null,
|
|
497
|
+
});
|
|
498
|
+
await this.#db.update_run_status.run({ id: runId, status: 200 });
|
|
499
|
+
return { run: runAlias, status: 200 };
|
|
473
500
|
}
|
|
474
501
|
|
|
502
|
+
// No summary and no rejections in this loop — resume it
|
|
503
|
+
const projectId = runRow.project_id;
|
|
504
|
+
const project = await this.#db.get_project_by_id.get({ id: projectId });
|
|
505
|
+
|
|
475
506
|
const latestPrompt = await this.#db.get_latest_prompt.get({
|
|
476
507
|
run_id: runId,
|
|
477
508
|
});
|
|
@@ -479,11 +510,11 @@ export default class AgentLoop {
|
|
|
479
510
|
? JSON.parse(latestPrompt.attributes).mode
|
|
480
511
|
: "ask";
|
|
481
512
|
|
|
482
|
-
|
|
483
|
-
const
|
|
484
|
-
|
|
485
|
-
await this.#db.enqueue_prompt.get({
|
|
513
|
+
// Re-enqueue the current loop's prompt to continue it
|
|
514
|
+
const loopSeq = await this.#db.next_loop.get({ run_id: runId });
|
|
515
|
+
await this.#db.enqueue_loop.get({
|
|
486
516
|
run_id: runId,
|
|
517
|
+
sequence: loopSeq.sequence,
|
|
487
518
|
mode: resumeMode,
|
|
488
519
|
model: runRow.model,
|
|
489
520
|
prompt: "",
|
|
@@ -516,7 +547,7 @@ export default class AgentLoop {
|
|
|
516
547
|
nextTurn,
|
|
517
548
|
`prompt://${nextTurn}`,
|
|
518
549
|
"",
|
|
519
|
-
|
|
550
|
+
200,
|
|
520
551
|
{ attributes: { mode: "ask" } },
|
|
521
552
|
);
|
|
522
553
|
await this.#knownStore.upsert(
|
|
@@ -524,15 +555,17 @@ export default class AgentLoop {
|
|
|
524
555
|
nextTurn,
|
|
525
556
|
`ask://${nextTurn}`,
|
|
526
557
|
message,
|
|
527
|
-
|
|
558
|
+
200,
|
|
528
559
|
);
|
|
529
560
|
|
|
530
561
|
if (this.#activeRuns.has(runRow.id)) {
|
|
531
562
|
return { run: runAlias, status: runRow.status, injected: "next_turn" };
|
|
532
563
|
}
|
|
533
564
|
|
|
534
|
-
await this.#db.
|
|
565
|
+
const injectLoopSeq = await this.#db.next_loop.get({ run_id: runRow.id });
|
|
566
|
+
await this.#db.enqueue_loop.get({
|
|
535
567
|
run_id: runRow.id,
|
|
568
|
+
sequence: injectLoopSeq.sequence,
|
|
536
569
|
mode: "ask",
|
|
537
570
|
model: runRow.model,
|
|
538
571
|
prompt: message,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
export default class ContextAssembler {
|
|
7
7
|
static async assembleFromTurnContext(
|
|
8
8
|
rows,
|
|
9
|
-
{ type = "ask", systemPrompt = "", contextSize = 0 } = {},
|
|
9
|
+
{ type = "ask", systemPrompt = "", contextSize = 0, demoted = [] } = {},
|
|
10
10
|
hooks,
|
|
11
11
|
) {
|
|
12
12
|
// Find loop boundary from active prompt
|
|
@@ -16,7 +16,7 @@ export default class ContextAssembler {
|
|
|
16
16
|
);
|
|
17
17
|
const loopStartTurn = promptEntry?.source_turn ?? 0;
|
|
18
18
|
|
|
19
|
-
const ctx = { rows, loopStartTurn, type, contextSize };
|
|
19
|
+
const ctx = { rows, loopStartTurn, type, contextSize, demoted };
|
|
20
20
|
|
|
21
21
|
const system = await hooks.assembly.system.filter(systemPrompt, ctx);
|
|
22
22
|
const user = await hooks.assembly.user.filter("", ctx);
|
package/src/agent/KnownStore.js
CHANGED
|
@@ -61,15 +61,23 @@ export default class KnownStore {
|
|
|
61
61
|
turn,
|
|
62
62
|
path,
|
|
63
63
|
body,
|
|
64
|
-
|
|
65
|
-
{
|
|
64
|
+
status,
|
|
65
|
+
{
|
|
66
|
+
fidelity = "full",
|
|
67
|
+
attributes = null,
|
|
68
|
+
hash = null,
|
|
69
|
+
updatedAt = null,
|
|
70
|
+
loopId = null,
|
|
71
|
+
} = {},
|
|
66
72
|
) {
|
|
67
73
|
await this.#db.upsert_known_entry.run({
|
|
68
74
|
run_id: runId,
|
|
75
|
+
loop_id: loopId,
|
|
69
76
|
turn,
|
|
70
77
|
path: KnownStore.normalizePath(path),
|
|
71
78
|
body,
|
|
72
|
-
|
|
79
|
+
status,
|
|
80
|
+
fidelity,
|
|
73
81
|
hash,
|
|
74
82
|
attributes: attributes ? JSON.stringify(attributes) : null,
|
|
75
83
|
updated_at: updatedAt,
|
|
@@ -84,17 +92,25 @@ export default class KnownStore {
|
|
|
84
92
|
});
|
|
85
93
|
}
|
|
86
94
|
|
|
87
|
-
async
|
|
88
|
-
const result = await this.#db.
|
|
95
|
+
async setFileFidelity(runId, pattern, fidelity) {
|
|
96
|
+
const result = await this.#db.set_file_fidelity.run({
|
|
89
97
|
run_id: runId,
|
|
90
98
|
pattern,
|
|
91
|
-
|
|
99
|
+
fidelity,
|
|
92
100
|
});
|
|
93
101
|
if (result.changes === 0) {
|
|
94
|
-
await this.upsert(runId, 0, pattern, "",
|
|
102
|
+
await this.upsert(runId, 0, pattern, "", 200, { fidelity });
|
|
95
103
|
}
|
|
96
104
|
}
|
|
97
105
|
|
|
106
|
+
async setFidelity(runId, path, fidelity) {
|
|
107
|
+
await this.#db.set_fidelity.run({
|
|
108
|
+
run_id: runId,
|
|
109
|
+
path: KnownStore.normalizePath(path),
|
|
110
|
+
fidelity,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
98
114
|
async demote(runId, path) {
|
|
99
115
|
await this.#db.demote_path.run({
|
|
100
116
|
run_id: runId,
|
|
@@ -164,11 +180,11 @@ export default class KnownStore {
|
|
|
164
180
|
});
|
|
165
181
|
}
|
|
166
182
|
|
|
167
|
-
async resolve(runId, path,
|
|
183
|
+
async resolve(runId, path, status, body) {
|
|
168
184
|
await this.#db.resolve_known_entry.run({
|
|
169
185
|
run_id: runId,
|
|
170
186
|
path: KnownStore.normalizePath(path),
|
|
171
|
-
|
|
187
|
+
status,
|
|
172
188
|
body,
|
|
173
189
|
});
|
|
174
190
|
}
|
|
@@ -185,8 +201,11 @@ export default class KnownStore {
|
|
|
185
201
|
return this.#db.get_file_states_by_pattern.all({ run_id: runId, pattern });
|
|
186
202
|
}
|
|
187
203
|
|
|
188
|
-
async hasRejections(runId) {
|
|
189
|
-
const row = await this.#db.has_rejections.get({
|
|
204
|
+
async hasRejections(runId, loopId) {
|
|
205
|
+
const row = await this.#db.has_rejections.get({
|
|
206
|
+
run_id: runId,
|
|
207
|
+
loop_id: loopId,
|
|
208
|
+
});
|
|
190
209
|
return row.count > 0;
|
|
191
210
|
}
|
|
192
211
|
|
|
@@ -40,7 +40,7 @@ export default class ProjectAgent {
|
|
|
40
40
|
const projectRow = await this.#db.upsert_project.get({
|
|
41
41
|
name: projectName,
|
|
42
42
|
project_root: projectRoot,
|
|
43
|
-
config_path: configPath
|
|
43
|
+
config_path: configPath ?? null,
|
|
44
44
|
});
|
|
45
45
|
const projectId = projectRow.id;
|
|
46
46
|
|
|
@@ -57,8 +57,6 @@ export default class ProjectAgent {
|
|
|
57
57
|
return this.#knownStore;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
// --- Run operations ---
|
|
61
|
-
|
|
62
60
|
async ask(projectId, model, prompt, run = null, options = {}) {
|
|
63
61
|
return this.#agentLoop.run(
|
|
64
62
|
"ask",
|