ucode-agent 1.41.0 → 1.41.1
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/package.json +1 -1
- package/src/core/loop.js +49 -0
package/package.json
CHANGED
package/src/core/loop.js
CHANGED
|
@@ -1105,6 +1105,7 @@ export class Agent {
|
|
|
1105
1105
|
this.lookedThisTurn = false;
|
|
1106
1106
|
this.reads = new Map();
|
|
1107
1107
|
this.declines = 0;
|
|
1108
|
+
this.apps = [];
|
|
1108
1109
|
forgetReviews(); // a new request: its apps get a fresh design review
|
|
1109
1110
|
const images = await this.attachImages(input);
|
|
1110
1111
|
this.push(images.length
|
|
@@ -1682,6 +1683,13 @@ export class Agent {
|
|
|
1682
1683
|
// a designer's review, and now the app actually driven — and it was the
|
|
1683
1684
|
// quietest line on screen, saying only that it had happened. Its verdict
|
|
1684
1685
|
// goes on the same line, the way a change carries its two numbers.
|
|
1686
|
+
// Which app folders this turn actually made, so a second one can be
|
|
1687
|
+
// refused before it is built and any leftovers can be counted at the end.
|
|
1688
|
+
if (call.name === 'create_app' && call.args?.folder) {
|
|
1689
|
+
const made = path.resolve(this.cwd, String(call.args.folder));
|
|
1690
|
+
if (!(this.apps ??= []).includes(made)) this.apps.push(made);
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1685
1693
|
if (call.name === 'look_at_app') {
|
|
1686
1694
|
const found = /^(\d+) problem/.exec(out.summary ?? '');
|
|
1687
1695
|
this.ui.runStat?.(found ? `${found[1]} to fix` : 'clean');
|
|
@@ -1784,6 +1792,30 @@ export class Agent {
|
|
|
1784
1792
|
this.reads.set(key, seen + 1);
|
|
1785
1793
|
}
|
|
1786
1794
|
|
|
1795
|
+
// Starting a second app instead of fixing the first.
|
|
1796
|
+
//
|
|
1797
|
+
// A traced build hit a problem in todo/, abandoned it and made todo-fixed/
|
|
1798
|
+
// — three create_app calls, two folders, one broken, the app typed twice.
|
|
1799
|
+
// Starting over is never the cheap way out of a problem in a file, and it
|
|
1800
|
+
// leaves the user to work out which folder is the real one.
|
|
1801
|
+
if (call.name === 'create_app' && call.args?.folder && (this.apps ?? []).length) {
|
|
1802
|
+
const wanted = path.resolve(this.cwd, String(call.args.folder));
|
|
1803
|
+
const already = this.apps.filter((f) => f !== wanted);
|
|
1804
|
+
if (already.length && !this.apps.includes(wanted)) {
|
|
1805
|
+
const show = already.map((f) => path.basename(f)).join(', ');
|
|
1806
|
+
throw new ToolFailure({
|
|
1807
|
+
kind: 'already_building',
|
|
1808
|
+
attempted: `creating ${call.args.folder}`,
|
|
1809
|
+
failed: `You already made ${show} this turn, and it is still there.`,
|
|
1810
|
+
fix:
|
|
1811
|
+
`Fix ${show} instead of starting again — whatever is wrong with it is a smaller `
|
|
1812
|
+
+ 'job than writing the whole app a second time, and a half-finished folder left '
|
|
1813
|
+
+ `beside the real one is worse than either. If ${show} genuinely cannot be saved, `
|
|
1814
|
+
+ 'delete it first, then create this one.',
|
|
1815
|
+
});
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1787
1819
|
if (call.name === 'load_skill') return this.loadSkill(call.args?.name);
|
|
1788
1820
|
if (call.name === 'update_plan') return this.updatePlan(call.args?.items);
|
|
1789
1821
|
if (call.name === 'delegate') return this.delegate(call.args?.tasks);
|
|
@@ -2082,6 +2114,23 @@ export class Agent {
|
|
|
2082
2114
|
const live = await this.liveErrors();
|
|
2083
2115
|
if (live) problems.push(live);
|
|
2084
2116
|
|
|
2117
|
+
// Two app folders, one of them abandoned.
|
|
2118
|
+
//
|
|
2119
|
+
// A build hit a problem in todo/, started todo-fixed/, then said in its
|
|
2120
|
+
// reply that it had removed the duplicate — and had not. Both were still
|
|
2121
|
+
// on disk for the user to sort out, and the claim that they were not is
|
|
2122
|
+
// the failure this whole checking pass exists to catch: saying a thing is
|
|
2123
|
+
// done when it is not. So it is checked rather than believed.
|
|
2124
|
+
const apps = this.apps ?? [];
|
|
2125
|
+
if (apps.length > 1) {
|
|
2126
|
+
const names = apps.map((f) => path.basename(f));
|
|
2127
|
+
problems.push(
|
|
2128
|
+
`There are ${apps.length} app folders here now: ${names.join(', ')}. Only one of them is `
|
|
2129
|
+
+ 'the app. Delete the ones you are not shipping — actually delete them, do not just say '
|
|
2130
|
+
+ 'you have — and make sure the one you keep is the one that works.',
|
|
2131
|
+
);
|
|
2132
|
+
}
|
|
2133
|
+
|
|
2085
2134
|
// Then look at it, in the same pass that type-checks — not when the model
|
|
2086
2135
|
// remembers to. A check that runs only when it is asked for reports
|
|
2087
2136
|
// nothing on exactly the builds that needed it, and this is the only one
|