brass-runtime 1.20.0 → 1.21.0
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/CHANGELOG.md +54 -0
- package/dist/agent/cli/main.cjs +265 -43
- package/dist/agent/cli/main.d.ts +99 -0
- package/dist/agent/cli/main.js +238 -16
- package/dist/agent/cli/main.mjs +238 -16
- package/dist/agent/index.cjs +18 -2
- package/dist/agent/index.d.ts +60 -482
- package/dist/agent/index.js +17 -1
- package/dist/agent/index.mjs +17 -1
- package/dist/{chunk-J4F5KC3U.js → chunk-AI3M6624.js} +1260 -45
- package/dist/{chunk-IHY2EJTT.cjs → chunk-EX4VEKUF.cjs} +1340 -125
- package/dist/{chunk-6BNZS2A4.mjs → chunk-Q57ENQUW.mjs} +1260 -45
- package/dist/nodeWorkspaceDiscovery-Ami1UkMt.d.ts +631 -0
- package/package.json +1 -1
- package/wasm/pkg/package.json +1 -1
|
@@ -15,6 +15,7 @@ var _chunkJKHBEWQAcjs = require('./chunk-JKHBEWQA.cjs');
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
|
|
18
19
|
var _chunkMVGUEJ5Zcjs = require('./chunk-MVGUEJ5Z.cjs');
|
|
19
20
|
|
|
20
21
|
// src/agent/core/state.ts
|
|
@@ -62,6 +63,187 @@ var reduceAgentState = (state, observation) => {
|
|
|
62
63
|
};
|
|
63
64
|
var isTerminal = (state) => state.phase === "done" || state.phase === "failed" || state.steps >= MAX_AGENT_STEPS;
|
|
64
65
|
|
|
66
|
+
// src/agent/core/contextBudget/armExtraction.ts
|
|
67
|
+
var FALLBACK_ARM_ID = "__fallback__";
|
|
68
|
+
var COMPOUND_EXTENSIONS = [
|
|
69
|
+
".test.ts",
|
|
70
|
+
".test.tsx",
|
|
71
|
+
".test.js",
|
|
72
|
+
".test.jsx",
|
|
73
|
+
".spec.ts",
|
|
74
|
+
".spec.tsx",
|
|
75
|
+
".spec.js",
|
|
76
|
+
".spec.jsx",
|
|
77
|
+
".pbt.test.ts",
|
|
78
|
+
".pbt.test.js",
|
|
79
|
+
".d.ts",
|
|
80
|
+
".d.mts",
|
|
81
|
+
".d.cts",
|
|
82
|
+
".config.ts",
|
|
83
|
+
".config.js",
|
|
84
|
+
".config.mjs",
|
|
85
|
+
".config.cjs",
|
|
86
|
+
".module.ts",
|
|
87
|
+
".module.css",
|
|
88
|
+
".stories.tsx",
|
|
89
|
+
".stories.ts"
|
|
90
|
+
];
|
|
91
|
+
var extractExtension = (filename) => {
|
|
92
|
+
const lower = filename.toLowerCase();
|
|
93
|
+
for (const ext of COMPOUND_EXTENSIONS) {
|
|
94
|
+
if (lower.endsWith(ext) && filename.length > ext.length) {
|
|
95
|
+
return filename.slice(filename.length - ext.length);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const dotIndex = filename.lastIndexOf(".");
|
|
99
|
+
if (dotIndex > 0 && dotIndex < filename.length - 1) {
|
|
100
|
+
return filename.slice(dotIndex);
|
|
101
|
+
}
|
|
102
|
+
return "";
|
|
103
|
+
};
|
|
104
|
+
var normalizePath = (filePath) => filePath.replace(/\\/g, "/");
|
|
105
|
+
var deriveArmId = (filePath) => {
|
|
106
|
+
try {
|
|
107
|
+
if (!filePath || typeof filePath !== "string") {
|
|
108
|
+
return FALLBACK_ARM_ID;
|
|
109
|
+
}
|
|
110
|
+
const normalized = normalizePath(filePath.trim());
|
|
111
|
+
if (!normalized) {
|
|
112
|
+
return FALLBACK_ARM_ID;
|
|
113
|
+
}
|
|
114
|
+
const lastSlash = normalized.lastIndexOf("/");
|
|
115
|
+
const directory = lastSlash >= 0 ? normalized.slice(0, lastSlash) : "";
|
|
116
|
+
const filename = lastSlash >= 0 ? normalized.slice(lastSlash + 1) : normalized;
|
|
117
|
+
if (!filename) {
|
|
118
|
+
return FALLBACK_ARM_ID;
|
|
119
|
+
}
|
|
120
|
+
const extension = extractExtension(filename);
|
|
121
|
+
if (!extension) {
|
|
122
|
+
return FALLBACK_ARM_ID;
|
|
123
|
+
}
|
|
124
|
+
const glob = `*${extension}`;
|
|
125
|
+
return directory ? `${directory}/${glob}` : glob;
|
|
126
|
+
} catch (e) {
|
|
127
|
+
return FALLBACK_ARM_ID;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
var assignArm = (filePath) => {
|
|
131
|
+
const id = deriveArmId(filePath);
|
|
132
|
+
return { id, pattern: id };
|
|
133
|
+
};
|
|
134
|
+
var groupByArm = (candidates) => {
|
|
135
|
+
const map = /* @__PURE__ */ new Map();
|
|
136
|
+
for (const path of candidates) {
|
|
137
|
+
const arm = assignArm(path);
|
|
138
|
+
const existing = map.get(arm.id);
|
|
139
|
+
if (existing) {
|
|
140
|
+
existing.push(path);
|
|
141
|
+
} else {
|
|
142
|
+
map.set(arm.id, [path]);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return map;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// src/agent/core/contextBudget/banditEngine.ts
|
|
149
|
+
var defaultArmStats = () => ({
|
|
150
|
+
alpha: 1,
|
|
151
|
+
beta: 1,
|
|
152
|
+
pulls: 0,
|
|
153
|
+
lastPulledAt: 0
|
|
154
|
+
});
|
|
155
|
+
var sampleBeta = (alpha, beta, rng) => {
|
|
156
|
+
const a = Math.max(alpha, 1e-3);
|
|
157
|
+
const b = Math.max(beta, 1e-3);
|
|
158
|
+
const x = sampleGamma(a, rng);
|
|
159
|
+
const y = sampleGamma(b, rng);
|
|
160
|
+
if (x + y === 0) return 0.5;
|
|
161
|
+
return x / (x + y);
|
|
162
|
+
};
|
|
163
|
+
var sampleGamma = (shape, rng) => {
|
|
164
|
+
if (shape < 1) {
|
|
165
|
+
const sample = sampleGamma(shape + 1, rng);
|
|
166
|
+
const u = rng();
|
|
167
|
+
return sample * Math.pow(u === 0 ? 1e-10 : u, 1 / shape);
|
|
168
|
+
}
|
|
169
|
+
const d = shape - 1 / 3;
|
|
170
|
+
const c = 1 / Math.sqrt(9 * d);
|
|
171
|
+
for (; ; ) {
|
|
172
|
+
let x;
|
|
173
|
+
let v;
|
|
174
|
+
do {
|
|
175
|
+
const u1 = rng();
|
|
176
|
+
const u2 = rng();
|
|
177
|
+
x = Math.sqrt(-2 * Math.log(u1 === 0 ? 1e-10 : u1)) * Math.cos(2 * Math.PI * u2);
|
|
178
|
+
v = 1 + c * x;
|
|
179
|
+
} while (v <= 0);
|
|
180
|
+
v = v * v * v;
|
|
181
|
+
const u = rng();
|
|
182
|
+
if (u < 1 - 0.0331 * (x * x) * (x * x)) {
|
|
183
|
+
return d * v;
|
|
184
|
+
}
|
|
185
|
+
if (Math.log(u === 0 ? 1e-10 : u) < 0.5 * x * x + d * (1 - v + Math.log(v))) {
|
|
186
|
+
return d * v;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
var selectArms = (state, candidateArms, rng) => {
|
|
191
|
+
if (candidateArms.length === 0) return [];
|
|
192
|
+
const sampled = candidateArms.map((arm) => {
|
|
193
|
+
const stats = _nullishCoalesce(state.arms[arm.id], () => ( defaultArmStats()));
|
|
194
|
+
const value = sampleBeta(stats.alpha, stats.beta, rng);
|
|
195
|
+
return { arm, value };
|
|
196
|
+
});
|
|
197
|
+
sampled.sort((a, b) => b.value - a.value);
|
|
198
|
+
return sampled.map((s) => s.arm);
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// src/agent/core/contextBudget/integration.ts
|
|
202
|
+
var shouldApplyBandit = (state, contextEnabled, hasInitialPatch) => {
|
|
203
|
+
if (Object.keys(state.arms).length === 0) return false;
|
|
204
|
+
if (!contextEnabled) return false;
|
|
205
|
+
if (hasInitialPatch) return false;
|
|
206
|
+
return true;
|
|
207
|
+
};
|
|
208
|
+
var reorderCandidates = (candidates, state, rng) => {
|
|
209
|
+
try {
|
|
210
|
+
if (Object.keys(state.arms).length === 0) {
|
|
211
|
+
return candidates;
|
|
212
|
+
}
|
|
213
|
+
const armGroups = groupByArm(candidates);
|
|
214
|
+
const uniqueArms = [];
|
|
215
|
+
for (const armId of armGroups.keys()) {
|
|
216
|
+
uniqueArms.push({ id: armId, pattern: armId });
|
|
217
|
+
}
|
|
218
|
+
const prioritizedArms = selectArms(state, uniqueArms, rng);
|
|
219
|
+
const result = [];
|
|
220
|
+
const includedArmIds = /* @__PURE__ */ new Set();
|
|
221
|
+
for (const arm of prioritizedArms) {
|
|
222
|
+
const paths = armGroups.get(arm.id);
|
|
223
|
+
if (paths) {
|
|
224
|
+
for (const p of paths) {
|
|
225
|
+
result.push(p);
|
|
226
|
+
}
|
|
227
|
+
includedArmIds.add(arm.id);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
for (const [armId, paths] of armGroups) {
|
|
231
|
+
if (!includedArmIds.has(armId)) {
|
|
232
|
+
for (const p of paths) {
|
|
233
|
+
result.push(p);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return result;
|
|
238
|
+
} catch (error) {
|
|
239
|
+
console.warn(
|
|
240
|
+
"[contextBudget] reorderCandidates failed, returning original order:",
|
|
241
|
+
error instanceof Error ? error.message : String(error)
|
|
242
|
+
);
|
|
243
|
+
return candidates;
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
|
|
65
247
|
// src/agent/core/contextDiscovery.ts
|
|
66
248
|
var DEFAULT_CONTEXT_GLOBS = [
|
|
67
249
|
"*.ts",
|
|
@@ -359,7 +541,7 @@ var summarizeContextDiscovery = (state) => {
|
|
|
359
541
|
remainingFileBudget
|
|
360
542
|
};
|
|
361
543
|
};
|
|
362
|
-
var nextContextDiscoveryAction = (state) => {
|
|
544
|
+
var nextContextDiscoveryAction = (state, banditState) => {
|
|
363
545
|
const config = configFor(state);
|
|
364
546
|
if (!config.enabled) return void 0;
|
|
365
547
|
if (_optionalChain([state, 'access', _22 => _22.goal, 'access', _23 => _23.initialPatch, 'optionalAccess', _24 => _24.trim, 'call', _25 => _25()])) return void 0;
|
|
@@ -367,8 +549,14 @@ var nextContextDiscoveryAction = (state) => {
|
|
|
367
549
|
const readsRemaining = Math.max(0, config.maxFiles - contextFileReadCount(state));
|
|
368
550
|
const directPaths = extractLikelyFilePaths(state);
|
|
369
551
|
const resultPaths = pathsFromSearchResults(state, config.maxSearchResults);
|
|
552
|
+
const allCandidates = [...directPaths, ...resultPaths];
|
|
553
|
+
const orderedCandidates = banditState && shouldApplyBandit(
|
|
554
|
+
banditState,
|
|
555
|
+
config.enabled,
|
|
556
|
+
Boolean(_optionalChain([state, 'access', _26 => _26.goal, 'access', _27 => _27.initialPatch, 'optionalAccess', _28 => _28.trim, 'call', _29 => _29()]))
|
|
557
|
+
) ? reorderCandidates(allCandidates, banditState, Math.random) : allCandidates;
|
|
370
558
|
if (readsRemaining > 0) {
|
|
371
|
-
const nextPath =
|
|
559
|
+
const nextPath = orderedCandidates.find(
|
|
372
560
|
(path) => path !== "package.json" && !alreadyRead(state, path) && !knownMissing(state, path)
|
|
373
561
|
);
|
|
374
562
|
if (nextPath) {
|
|
@@ -416,7 +604,7 @@ var parsePackageJson = (state) => {
|
|
|
416
604
|
try {
|
|
417
605
|
const parsed = JSON.parse(observation.content);
|
|
418
606
|
return isRecord(parsed) ? parsed : void 0;
|
|
419
|
-
} catch (
|
|
607
|
+
} catch (e2) {
|
|
420
608
|
return void 0;
|
|
421
609
|
}
|
|
422
610
|
};
|
|
@@ -430,7 +618,7 @@ var packageScripts = (pkg) => {
|
|
|
430
618
|
};
|
|
431
619
|
var markerExists = (state, path) => state.observations.some((obs) => obs.type === "fs.exists" && obs.path === path && obs.exists);
|
|
432
620
|
var hasDependencyName = (pkg, dependency) => {
|
|
433
|
-
const collections = [_optionalChain([pkg, 'optionalAccess',
|
|
621
|
+
const collections = [_optionalChain([pkg, 'optionalAccess', _30 => _30.dependencies]), _optionalChain([pkg, 'optionalAccess', _31 => _31.devDependencies]), _optionalChain([pkg, 'optionalAccess', _32 => _32.optionalDependencies])];
|
|
434
622
|
return collections.some((collection) => isRecord(collection) && typeof collection[dependency] === "string");
|
|
435
623
|
};
|
|
436
624
|
var hasAnyDependency = (pkg, dependencies) => dependencies.some((dependency) => hasDependencyName(pkg, dependency));
|
|
@@ -459,7 +647,7 @@ var discoverProjectProfile = (state, packageManager) => {
|
|
|
459
647
|
if (desktopPresent) stacks.push("desktop");
|
|
460
648
|
const bridgePresent = markerExists(state, "bridges") || markerExists(state, "bridges/whatsmeow-bridge/Cargo.toml") || markerExists(state, "bridges/whatsmeow-bridge/package.json") || scriptNames.some((name) => name.includes("bridge"));
|
|
461
649
|
if (bridgePresent) stacks.push("bridge");
|
|
462
|
-
const monorepoPresent = markerExists(state, "pnpm-workspace.yaml") || markerExists(state, "turbo.json") || markerExists(state, "nx.json") || markerExists(state, "apps") || markerExists(state, "packages") || markerExists(state, "bridges") || Array.isArray(_optionalChain([pkg, 'optionalAccess',
|
|
650
|
+
const monorepoPresent = markerExists(state, "pnpm-workspace.yaml") || markerExists(state, "turbo.json") || markerExists(state, "nx.json") || markerExists(state, "apps") || markerExists(state, "packages") || markerExists(state, "bridges") || Array.isArray(_optionalChain([pkg, 'optionalAccess', _33 => _33.workspaces]));
|
|
463
651
|
if (monorepoPresent) stacks.push("monorepo");
|
|
464
652
|
const candidateValidationScripts = unique2([
|
|
465
653
|
...scriptNamesMatching(scripts, [
|
|
@@ -541,7 +729,7 @@ var parseProjectPackageJson = (state) => {
|
|
|
541
729
|
try {
|
|
542
730
|
const parsed = JSON.parse(observation.content);
|
|
543
731
|
return isRecord2(parsed) ? parsed : void 0;
|
|
544
|
-
} catch (
|
|
732
|
+
} catch (e3) {
|
|
545
733
|
return void 0;
|
|
546
734
|
}
|
|
547
735
|
};
|
|
@@ -556,7 +744,7 @@ var packageScripts2 = (pkg) => {
|
|
|
556
744
|
var hasFsExistsObservation = (state, path) => state.observations.some((obs) => obs.type === "fs.exists" && obs.path === path);
|
|
557
745
|
var nextProjectProbeAction = (state) => {
|
|
558
746
|
const project = state.goal.project;
|
|
559
|
-
if (!_optionalChain([project, 'optionalAccess',
|
|
747
|
+
if (!_optionalChain([project, 'optionalAccess', _34 => _34.validationCommands]) && (!_optionalChain([project, 'optionalAccess', _35 => _35.packageManager]) || project.packageManager === "auto")) {
|
|
560
748
|
for (const path of PROJECT_LOCKFILE_PROBES) {
|
|
561
749
|
if (!hasFsExistsObservation(state, path)) return { type: "fs.exists", path };
|
|
562
750
|
}
|
|
@@ -565,9 +753,9 @@ var nextProjectProbeAction = (state) => {
|
|
|
565
753
|
return profileProbe ? { type: "fs.exists", path: profileProbe } : void 0;
|
|
566
754
|
};
|
|
567
755
|
var packageManagerFromPackageJson = (pkg) => {
|
|
568
|
-
const raw = typeof _optionalChain([pkg, 'optionalAccess',
|
|
756
|
+
const raw = typeof _optionalChain([pkg, 'optionalAccess', _36 => _36.packageManager]) === "string" ? pkg.packageManager : void 0;
|
|
569
757
|
if (!raw) return void 0;
|
|
570
|
-
const name = _optionalChain([raw, 'access',
|
|
758
|
+
const name = _optionalChain([raw, 'access', _37 => _37.split, 'call', _38 => _38("@"), 'access', _39 => _39[0], 'optionalAccess', _40 => _40.trim, 'call', _41 => _41()]);
|
|
571
759
|
if (name === "npm" || name === "pnpm" || name === "yarn" || name === "bun") return name;
|
|
572
760
|
return void 0;
|
|
573
761
|
};
|
|
@@ -580,7 +768,7 @@ var packageManagerFromLockfiles = (state) => {
|
|
|
580
768
|
return void 0;
|
|
581
769
|
};
|
|
582
770
|
var discoverPackageManager = (state) => {
|
|
583
|
-
const configured = _optionalChain([state, 'access',
|
|
771
|
+
const configured = _optionalChain([state, 'access', _42 => _42.goal, 'access', _43 => _43.project, 'optionalAccess', _44 => _44.packageManager]);
|
|
584
772
|
if (configured && configured !== "auto") return configured;
|
|
585
773
|
return _nullishCoalesce(_nullishCoalesce(packageManagerFromPackageJson(parseProjectPackageJson(state)), () => ( packageManagerFromLockfiles(state))), () => ( "npm"));
|
|
586
774
|
};
|
|
@@ -668,7 +856,7 @@ var commandForScript = (packageManager, scriptName) => {
|
|
|
668
856
|
}
|
|
669
857
|
};
|
|
670
858
|
var configuredValidationCommands = (project) => {
|
|
671
|
-
if (!_optionalChain([project, 'optionalAccess',
|
|
859
|
+
if (!_optionalChain([project, 'optionalAccess', _45 => _45.validationCommands])) return void 0;
|
|
672
860
|
return project.validationCommands.map((command) => splitCommand(command)).filter((command) => command.length > 0);
|
|
673
861
|
};
|
|
674
862
|
var discoverValidationCommands = (state) => {
|
|
@@ -693,7 +881,7 @@ var discoverValidationCommands = (state) => {
|
|
|
693
881
|
const notes = [];
|
|
694
882
|
const testScript = firstExistingScript(
|
|
695
883
|
scripts,
|
|
696
|
-
_nullishCoalesce(_optionalChain([project, 'optionalAccess',
|
|
884
|
+
_nullishCoalesce(_optionalChain([project, 'optionalAccess', _46 => _46.testScriptNames]), () => ( DEFAULT_TEST_SCRIPT_NAMES)),
|
|
697
885
|
{ skipPlaceholderTest: true }
|
|
698
886
|
);
|
|
699
887
|
if (testScript) {
|
|
@@ -707,7 +895,7 @@ var discoverValidationCommands = (state) => {
|
|
|
707
895
|
notes.push(`Selected project health script: ${healthScript}.`);
|
|
708
896
|
}
|
|
709
897
|
}
|
|
710
|
-
const includeTypecheck = _optionalChain([project, 'optionalAccess',
|
|
898
|
+
const includeTypecheck = _optionalChain([project, 'optionalAccess', _47 => _47.includeTypecheck]) === true || goalMentionsAny(state.goal.text, ["typecheck", "type-check", "type check", "types", "tsc"]) || commands.length === 0;
|
|
711
899
|
if (includeTypecheck) {
|
|
712
900
|
const typecheckScript = firstExistingScript(scripts, TYPECHECK_SCRIPT_NAMES);
|
|
713
901
|
if (typecheckScript) {
|
|
@@ -715,7 +903,7 @@ var discoverValidationCommands = (state) => {
|
|
|
715
903
|
notes.push(`Selected typecheck script: ${typecheckScript}.`);
|
|
716
904
|
}
|
|
717
905
|
}
|
|
718
|
-
const includeLint = _optionalChain([project, 'optionalAccess',
|
|
906
|
+
const includeLint = _optionalChain([project, 'optionalAccess', _48 => _48.includeLint]) === true || goalMentionsAny(state.goal.text, ["lint", "eslint"]) || commands.length === 0;
|
|
719
907
|
if (includeLint) {
|
|
720
908
|
const lintScript = firstExistingScript(scripts, LINT_SCRIPT_NAMES);
|
|
721
909
|
if (lintScript) {
|
|
@@ -727,7 +915,7 @@ var discoverValidationCommands = (state) => {
|
|
|
727
915
|
commands.push(["cargo", "check"]);
|
|
728
916
|
notes.push("Selected Cargo check because a root Cargo.toml was detected.");
|
|
729
917
|
}
|
|
730
|
-
const max = _nullishCoalesce(_optionalChain([project, 'optionalAccess',
|
|
918
|
+
const max = _nullishCoalesce(_optionalChain([project, 'optionalAccess', _49 => _49.maxValidationCommands]), () => ( 2));
|
|
731
919
|
const validationCommands = dedupeCommands(commands).slice(0, Math.max(0, max));
|
|
732
920
|
return {
|
|
733
921
|
packageManager,
|
|
@@ -755,9 +943,9 @@ var clampNonNegativeInteger = (value, fallback) => {
|
|
|
755
943
|
};
|
|
756
944
|
var patchRepairAttemptsUsed = (state) => state.observations.filter((obs) => obs.type === "llm.response" && obs.purpose === "patch").length;
|
|
757
945
|
var patchQualitySummary = (state) => {
|
|
758
|
-
const enabled = _nullishCoalesce(_optionalChain([state, 'access',
|
|
946
|
+
const enabled = _nullishCoalesce(_optionalChain([state, 'access', _50 => _50.goal, 'access', _51 => _51.patchQuality, 'optionalAccess', _52 => _52.enabled]), () => ( true));
|
|
759
947
|
const maxRepairAttempts = clampNonNegativeInteger(
|
|
760
|
-
_optionalChain([state, 'access',
|
|
948
|
+
_optionalChain([state, 'access', _53 => _53.goal, 'access', _54 => _54.patchQuality, 'optionalAccess', _55 => _55.maxRepairAttempts]),
|
|
761
949
|
DEFAULT_MAX_REPAIR_ATTEMPTS
|
|
762
950
|
);
|
|
763
951
|
const repairAttemptsUsed = patchRepairAttemptsUsed(state);
|
|
@@ -766,7 +954,7 @@ var patchQualitySummary = (state) => {
|
|
|
766
954
|
maxRepairAttempts,
|
|
767
955
|
repairAttemptsUsed,
|
|
768
956
|
repairsRemaining: Math.max(0, maxRepairAttempts - repairAttemptsUsed),
|
|
769
|
-
exactSuppliedPatch: Boolean(_optionalChain([state, 'access',
|
|
957
|
+
exactSuppliedPatch: Boolean(_optionalChain([state, 'access', _56 => _56.goal, 'access', _57 => _57.initialPatch, 'optionalAccess', _58 => _58.trim, 'call', _59 => _59()]))
|
|
770
958
|
};
|
|
771
959
|
};
|
|
772
960
|
var canRequestPatchRepair = (state) => {
|
|
@@ -808,26 +996,26 @@ var clampNonNegativeInteger2 = (value, fallback) => {
|
|
|
808
996
|
var rollbackStrategy = (value) => value === "last" ? "last" : "all";
|
|
809
997
|
var rollbackSafetySummary = (state) => {
|
|
810
998
|
const rollback = state.goal.rollback;
|
|
811
|
-
const enabled = _nullishCoalesce(_optionalChain([rollback, 'optionalAccess',
|
|
812
|
-
const maxRollbackDepth = clampNonNegativeInteger2(_optionalChain([rollback, 'optionalAccess',
|
|
999
|
+
const enabled = _nullishCoalesce(_optionalChain([rollback, 'optionalAccess', _60 => _60.enabled]), () => ( true));
|
|
1000
|
+
const maxRollbackDepth = clampNonNegativeInteger2(_optionalChain([rollback, 'optionalAccess', _61 => _61.maxRollbackDepth]), DEFAULT_MAX_ROLLBACK_DEPTH);
|
|
813
1001
|
const rollbackCount = state.observations.filter((obs) => obs.type === "patch.rolledBack").length;
|
|
814
1002
|
const appliedStackDepth = unappliedPatchStack(state).length;
|
|
815
1003
|
return {
|
|
816
1004
|
enabled,
|
|
817
|
-
onFinalValidationFailure: _nullishCoalesce(_optionalChain([rollback, 'optionalAccess',
|
|
818
|
-
strategy: rollbackStrategy(_optionalChain([rollback, 'optionalAccess',
|
|
1005
|
+
onFinalValidationFailure: _nullishCoalesce(_optionalChain([rollback, 'optionalAccess', _62 => _62.onFinalValidationFailure]), () => ( true)),
|
|
1006
|
+
strategy: rollbackStrategy(_optionalChain([rollback, 'optionalAccess', _63 => _63.strategy])),
|
|
819
1007
|
maxRollbackDepth,
|
|
820
|
-
runValidationAfterRollback: _nullishCoalesce(_optionalChain([rollback, 'optionalAccess',
|
|
821
|
-
allowForSuppliedPatches: _nullishCoalesce(_optionalChain([rollback, 'optionalAccess',
|
|
1008
|
+
runValidationAfterRollback: _nullishCoalesce(_optionalChain([rollback, 'optionalAccess', _64 => _64.runValidationAfterRollback]), () => ( true)),
|
|
1009
|
+
allowForSuppliedPatches: _nullishCoalesce(_optionalChain([rollback, 'optionalAccess', _65 => _65.allowForSuppliedPatches]), () => ( false)),
|
|
822
1010
|
rollbackCount,
|
|
823
1011
|
appliedStackDepth,
|
|
824
|
-
exactSuppliedPatch: Boolean(_optionalChain([state, 'access',
|
|
1012
|
+
exactSuppliedPatch: Boolean(_optionalChain([state, 'access', _66 => _66.goal, 'access', _67 => _67.initialPatch, 'optionalAccess', _68 => _68.trim, 'call', _69 => _69()]))
|
|
825
1013
|
};
|
|
826
1014
|
};
|
|
827
1015
|
var unappliedPatchStack = (state) => {
|
|
828
1016
|
const stack = [];
|
|
829
1017
|
for (const [index, observation] of state.observations.entries()) {
|
|
830
|
-
if (observation.type === "patch.applied" && _optionalChain([observation, 'access',
|
|
1018
|
+
if (observation.type === "patch.applied" && _optionalChain([observation, 'access', _70 => _70.patch, 'optionalAccess', _71 => _71.trim, 'call', _72 => _72()])) {
|
|
831
1019
|
stack.push({
|
|
832
1020
|
index,
|
|
833
1021
|
patch: observation.patch,
|
|
@@ -835,8 +1023,8 @@ var unappliedPatchStack = (state) => {
|
|
|
835
1023
|
});
|
|
836
1024
|
continue;
|
|
837
1025
|
}
|
|
838
|
-
if (observation.type === "patch.rolledBack" && _optionalChain([observation, 'access',
|
|
839
|
-
const existingIndex = [...stack].reverse().findIndex((entry) => entry.patch.trim() === _optionalChain([observation, 'access',
|
|
1026
|
+
if (observation.type === "patch.rolledBack" && _optionalChain([observation, 'access', _73 => _73.patch, 'optionalAccess', _74 => _74.trim, 'call', _75 => _75()])) {
|
|
1027
|
+
const existingIndex = [...stack].reverse().findIndex((entry) => entry.patch.trim() === _optionalChain([observation, 'access', _76 => _76.patch, 'optionalAccess', _77 => _77.trim, 'call', _78 => _78()]));
|
|
840
1028
|
if (existingIndex >= 0) {
|
|
841
1029
|
stack.splice(stack.length - 1 - existingIndex, 1);
|
|
842
1030
|
}
|
|
@@ -855,7 +1043,7 @@ var canAutoRollback = (state) => {
|
|
|
855
1043
|
var shouldContinueRollbackStack = (state) => {
|
|
856
1044
|
const summary = rollbackSafetySummary(state);
|
|
857
1045
|
const latest = state.observations.at(-1);
|
|
858
|
-
return _optionalChain([latest, 'optionalAccess',
|
|
1046
|
+
return _optionalChain([latest, 'optionalAccess', _79 => _79.type]) === "patch.rolledBack" && summary.strategy === "all" && canAutoRollback(state);
|
|
859
1047
|
};
|
|
860
1048
|
var commandsEqual3 = (a, b) => a.length === b.length && a.every((part, index) => part === b[index]);
|
|
861
1049
|
var shellResultsForCommands2 = (commands, observations) => commands.flatMap(
|
|
@@ -947,12 +1135,12 @@ var DEFAULT_SECRET_PATTERNS = [
|
|
|
947
1135
|
var toRegExp = (pattern) => {
|
|
948
1136
|
try {
|
|
949
1137
|
return new RegExp(pattern, "gi");
|
|
950
|
-
} catch (
|
|
1138
|
+
} catch (e4) {
|
|
951
1139
|
return void 0;
|
|
952
1140
|
}
|
|
953
1141
|
};
|
|
954
|
-
var configuredPatterns = (config) => (_nullishCoalesce(_optionalChain([config, 'optionalAccess',
|
|
955
|
-
var isRedactionEnabled = (config) => _nullishCoalesce(_optionalChain([config, 'optionalAccess',
|
|
1142
|
+
var configuredPatterns = (config) => (_nullishCoalesce(_optionalChain([config, 'optionalAccess', _80 => _80.additionalPatterns]), () => ( []))).map(toRegExp).filter((pattern) => Boolean(pattern));
|
|
1143
|
+
var isRedactionEnabled = (config) => _nullishCoalesce(_optionalChain([config, 'optionalAccess', _81 => _81.enabled]), () => ( true));
|
|
956
1144
|
var redactText = (value, config) => {
|
|
957
1145
|
if (!isRedactionEnabled(config) || !value) return value;
|
|
958
1146
|
return [...DEFAULT_SECRET_PATTERNS, ...configuredPatterns(config)].reduce(
|
|
@@ -989,8 +1177,8 @@ var inferUserLanguage = (text) => {
|
|
|
989
1177
|
return void 0;
|
|
990
1178
|
};
|
|
991
1179
|
var configuredLanguageName = (language) => {
|
|
992
|
-
const response = _nullishCoalesce(_optionalChain([language, 'optionalAccess',
|
|
993
|
-
if (response === "custom") return _optionalChain([language, 'optionalAccess',
|
|
1180
|
+
const response = _nullishCoalesce(_optionalChain([language, 'optionalAccess', _82 => _82.response]), () => ( "auto"));
|
|
1181
|
+
if (response === "custom") return _optionalChain([language, 'optionalAccess', _83 => _83.custom, 'optionalAccess', _84 => _84.trim, 'call', _85 => _85()]) || void 0;
|
|
994
1182
|
if (response === "auto" || response === "match-user") return void 0;
|
|
995
1183
|
return LANGUAGE_LABELS[response];
|
|
996
1184
|
};
|
|
@@ -1018,6 +1206,343 @@ var describeLanguagePolicy = (goal) => {
|
|
|
1018
1206
|
};
|
|
1019
1207
|
var spanishLike = (goal) => responseLanguageName(goal) === "Spanish";
|
|
1020
1208
|
|
|
1209
|
+
// src/agent/core/patchStrategy/types.ts
|
|
1210
|
+
var PATCH_STRATEGIES = [
|
|
1211
|
+
"direct-patch",
|
|
1212
|
+
"multi-step-patch",
|
|
1213
|
+
"propose-then-refine"
|
|
1214
|
+
];
|
|
1215
|
+
var DEFAULT_STRATEGY = "direct-patch";
|
|
1216
|
+
|
|
1217
|
+
// src/agent/core/patchStrategy/thompson.ts
|
|
1218
|
+
var initialThompsonState = () => ({
|
|
1219
|
+
algorithm: "thompson",
|
|
1220
|
+
arms: {
|
|
1221
|
+
"direct-patch": { alpha: 1, beta: 1 },
|
|
1222
|
+
"multi-step-patch": { alpha: 1, beta: 1 },
|
|
1223
|
+
"propose-then-refine": { alpha: 1, beta: 1 }
|
|
1224
|
+
}
|
|
1225
|
+
});
|
|
1226
|
+
var thompsonSelect = (state, rng) => {
|
|
1227
|
+
let bestArm = PATCH_STRATEGIES[0];
|
|
1228
|
+
let bestSample = -Infinity;
|
|
1229
|
+
for (const arm of PATCH_STRATEGIES) {
|
|
1230
|
+
const { alpha, beta } = state.arms[arm];
|
|
1231
|
+
const sample = rng.sampleBeta(alpha, beta);
|
|
1232
|
+
if (sample > bestSample) {
|
|
1233
|
+
bestSample = sample;
|
|
1234
|
+
bestArm = arm;
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
return bestArm;
|
|
1238
|
+
};
|
|
1239
|
+
var thompsonUpdate = (state, arm, reward) => {
|
|
1240
|
+
const clampedReward = Math.max(0, Math.min(1, reward));
|
|
1241
|
+
const current = state.arms[arm];
|
|
1242
|
+
const newAlpha = Math.max(1, current.alpha + clampedReward);
|
|
1243
|
+
const newBeta = Math.max(1, current.beta + (1 - clampedReward));
|
|
1244
|
+
return {
|
|
1245
|
+
...state,
|
|
1246
|
+
arms: {
|
|
1247
|
+
...state.arms,
|
|
1248
|
+
[arm]: { alpha: newAlpha, beta: newBeta }
|
|
1249
|
+
}
|
|
1250
|
+
};
|
|
1251
|
+
};
|
|
1252
|
+
var thompsonStateFromHistory = (history) => {
|
|
1253
|
+
let state = initialThompsonState();
|
|
1254
|
+
for (const entry of history) {
|
|
1255
|
+
state = thompsonUpdate(state, entry.arm, entry.reward);
|
|
1256
|
+
}
|
|
1257
|
+
return state;
|
|
1258
|
+
};
|
|
1259
|
+
|
|
1260
|
+
// src/agent/core/patchStrategy/exp3.ts
|
|
1261
|
+
var K = 3;
|
|
1262
|
+
var initialEXP3State = (gamma = 0.3) => ({
|
|
1263
|
+
algorithm: "exp3",
|
|
1264
|
+
arms: {
|
|
1265
|
+
"direct-patch": { weight: 1 },
|
|
1266
|
+
"multi-step-patch": { weight: 1 },
|
|
1267
|
+
"propose-then-refine": { weight: 1 }
|
|
1268
|
+
},
|
|
1269
|
+
gamma: Math.max(0, Math.min(1, gamma)) || 0.3,
|
|
1270
|
+
totalRounds: 0
|
|
1271
|
+
});
|
|
1272
|
+
var exp3Probabilities = (state) => {
|
|
1273
|
+
const { arms, gamma } = state;
|
|
1274
|
+
let weightSum = 0;
|
|
1275
|
+
for (const arm of PATCH_STRATEGIES) {
|
|
1276
|
+
weightSum += arms[arm].weight;
|
|
1277
|
+
}
|
|
1278
|
+
const probs = {};
|
|
1279
|
+
let probSum = 0;
|
|
1280
|
+
for (const arm of PATCH_STRATEGIES) {
|
|
1281
|
+
const p = (1 - gamma) * (arms[arm].weight / weightSum) + gamma / K;
|
|
1282
|
+
probs[arm] = p;
|
|
1283
|
+
probSum += p;
|
|
1284
|
+
}
|
|
1285
|
+
for (const arm of PATCH_STRATEGIES) {
|
|
1286
|
+
probs[arm] /= probSum;
|
|
1287
|
+
}
|
|
1288
|
+
return probs;
|
|
1289
|
+
};
|
|
1290
|
+
var exp3Select = (state, rng) => {
|
|
1291
|
+
const probs = exp3Probabilities(state);
|
|
1292
|
+
const r = rng.random();
|
|
1293
|
+
let cumulative = 0;
|
|
1294
|
+
for (const arm of PATCH_STRATEGIES) {
|
|
1295
|
+
cumulative += probs[arm];
|
|
1296
|
+
if (r < cumulative) {
|
|
1297
|
+
return arm;
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
return PATCH_STRATEGIES[PATCH_STRATEGIES.length - 1];
|
|
1301
|
+
};
|
|
1302
|
+
var exp3Update = (state, arm, reward) => {
|
|
1303
|
+
const clampedReward = Math.max(0, Math.min(1, reward));
|
|
1304
|
+
const probs = exp3Probabilities(state);
|
|
1305
|
+
const pSelected = probs[arm];
|
|
1306
|
+
const estimatedReward = clampedReward / pSelected;
|
|
1307
|
+
const currentWeight = state.arms[arm].weight;
|
|
1308
|
+
const newWeight = Math.min(
|
|
1309
|
+
currentWeight * Math.exp(state.gamma * estimatedReward / K),
|
|
1310
|
+
1e100
|
|
1311
|
+
);
|
|
1312
|
+
return {
|
|
1313
|
+
...state,
|
|
1314
|
+
arms: {
|
|
1315
|
+
...state.arms,
|
|
1316
|
+
[arm]: { weight: newWeight }
|
|
1317
|
+
},
|
|
1318
|
+
totalRounds: state.totalRounds + 1
|
|
1319
|
+
};
|
|
1320
|
+
};
|
|
1321
|
+
var exp3StateFromHistory = (history, gamma = 0.3) => {
|
|
1322
|
+
let state = initialEXP3State(gamma);
|
|
1323
|
+
for (const entry of history) {
|
|
1324
|
+
state = exp3Update(state, entry.arm, entry.reward);
|
|
1325
|
+
}
|
|
1326
|
+
return state;
|
|
1327
|
+
};
|
|
1328
|
+
|
|
1329
|
+
// src/agent/core/patchStrategy/selector.ts
|
|
1330
|
+
var selectStrategy = (_signals, config, history, rng) => {
|
|
1331
|
+
if (_optionalChain([config, 'optionalAccess', _86 => _86.enabled]) === false) {
|
|
1332
|
+
return DEFAULT_STRATEGY;
|
|
1333
|
+
}
|
|
1334
|
+
if (history.length === 0) {
|
|
1335
|
+
return DEFAULT_STRATEGY;
|
|
1336
|
+
}
|
|
1337
|
+
const algorithm = _nullishCoalesce(_optionalChain([config, 'optionalAccess', _87 => _87.algorithm]), () => ( "thompson"));
|
|
1338
|
+
switch (algorithm) {
|
|
1339
|
+
case "thompson": {
|
|
1340
|
+
const state = thompsonStateFromHistory(history);
|
|
1341
|
+
return thompsonSelect(state, rng);
|
|
1342
|
+
}
|
|
1343
|
+
case "exp3": {
|
|
1344
|
+
const rawGamma = _nullishCoalesce(_optionalChain([config, 'optionalAccess', _88 => _88.gamma]), () => ( 0.3));
|
|
1345
|
+
const gamma = Math.max(Number.EPSILON, Math.min(1, rawGamma)) || 0.3;
|
|
1346
|
+
const state = exp3StateFromHistory(history, gamma);
|
|
1347
|
+
return exp3Select(state, rng);
|
|
1348
|
+
}
|
|
1349
|
+
default: {
|
|
1350
|
+
const state = thompsonStateFromHistory(history);
|
|
1351
|
+
return thompsonSelect(state, rng);
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
};
|
|
1355
|
+
|
|
1356
|
+
// src/agent/core/patchStrategy/signalExtractor.ts
|
|
1357
|
+
var FILE_EXTENSIONS = [
|
|
1358
|
+
"tsx",
|
|
1359
|
+
"jsx",
|
|
1360
|
+
"mts",
|
|
1361
|
+
"cts",
|
|
1362
|
+
"mjs",
|
|
1363
|
+
"cjs",
|
|
1364
|
+
"json",
|
|
1365
|
+
"yaml",
|
|
1366
|
+
"html",
|
|
1367
|
+
"scss",
|
|
1368
|
+
"ts",
|
|
1369
|
+
"js",
|
|
1370
|
+
"md",
|
|
1371
|
+
"yml",
|
|
1372
|
+
"css"
|
|
1373
|
+
];
|
|
1374
|
+
var ASCII_CASE_BIT = 32;
|
|
1375
|
+
var MAX_FILE_PATH_CANDIDATE_LENGTH = 512;
|
|
1376
|
+
var KEYWORDS = [
|
|
1377
|
+
"refactor",
|
|
1378
|
+
"rename",
|
|
1379
|
+
"bug",
|
|
1380
|
+
"fix",
|
|
1381
|
+
"add",
|
|
1382
|
+
"create",
|
|
1383
|
+
"move",
|
|
1384
|
+
"delete"
|
|
1385
|
+
];
|
|
1386
|
+
var KEYWORD_PATTERNS = new Map(
|
|
1387
|
+
KEYWORDS.map((kw) => [kw, new RegExp(`\\b${kw}\\b`, "i")])
|
|
1388
|
+
);
|
|
1389
|
+
var categorizeGoalLength = (text) => {
|
|
1390
|
+
const len = text.length;
|
|
1391
|
+
if (len < 80) return "short";
|
|
1392
|
+
if (len <= 300) return "medium";
|
|
1393
|
+
return "long";
|
|
1394
|
+
};
|
|
1395
|
+
var isAsciiAlpha = (code) => code >= 65 && code <= 90 || code >= 97 && code <= 122;
|
|
1396
|
+
var isAsciiDigit = (code) => code >= 48 && code <= 57;
|
|
1397
|
+
var isPathCandidateChar = (code) => isAsciiAlpha(code) || isAsciiDigit(code) || code === 95 || // _
|
|
1398
|
+
code === 64 || // @
|
|
1399
|
+
code === 46 || // .
|
|
1400
|
+
code === 45 || // -
|
|
1401
|
+
code === 47 || // /
|
|
1402
|
+
code === 92 || // \
|
|
1403
|
+
code === 58;
|
|
1404
|
+
var matchesExtension = (text, start, end, extension) => {
|
|
1405
|
+
if (end - start !== extension.length) return false;
|
|
1406
|
+
for (let offset = 0; offset < extension.length; offset++) {
|
|
1407
|
+
const textCode = text.charCodeAt(start + offset) | ASCII_CASE_BIT;
|
|
1408
|
+
if (textCode !== extension.charCodeAt(offset)) {
|
|
1409
|
+
return false;
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
return true;
|
|
1413
|
+
};
|
|
1414
|
+
var matchesKnownExtension = (text, start, end) => {
|
|
1415
|
+
for (const extension of FILE_EXTENSIONS) {
|
|
1416
|
+
if (matchesExtension(text, start, end, extension)) {
|
|
1417
|
+
return true;
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
return false;
|
|
1421
|
+
};
|
|
1422
|
+
var stripTrailingPathPunctuation = (text, start, end) => {
|
|
1423
|
+
let currentEnd = end;
|
|
1424
|
+
while (currentEnd > start) {
|
|
1425
|
+
const code = text.charCodeAt(currentEnd - 1);
|
|
1426
|
+
if (code !== 46 && code !== 58) break;
|
|
1427
|
+
currentEnd--;
|
|
1428
|
+
}
|
|
1429
|
+
return currentEnd;
|
|
1430
|
+
};
|
|
1431
|
+
var stripLineSuffixes = (text, start, end) => {
|
|
1432
|
+
let currentEnd = end;
|
|
1433
|
+
for (let suffixCount = 0; suffixCount < 2; suffixCount++) {
|
|
1434
|
+
let cursor = currentEnd - 1;
|
|
1435
|
+
if (cursor < start || !isAsciiDigit(text.charCodeAt(cursor))) break;
|
|
1436
|
+
while (cursor >= start && isAsciiDigit(text.charCodeAt(cursor))) {
|
|
1437
|
+
cursor--;
|
|
1438
|
+
}
|
|
1439
|
+
if (cursor < start || text.charCodeAt(cursor) !== 58) break;
|
|
1440
|
+
currentEnd = cursor;
|
|
1441
|
+
}
|
|
1442
|
+
return currentEnd;
|
|
1443
|
+
};
|
|
1444
|
+
var findLastDot = (text, start, end) => {
|
|
1445
|
+
for (let index = end - 1; index >= start; index--) {
|
|
1446
|
+
if (text.charCodeAt(index) === 46) {
|
|
1447
|
+
return index;
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
return -1;
|
|
1451
|
+
};
|
|
1452
|
+
var findFilenameStart = (text, start, dotIndex) => {
|
|
1453
|
+
let filenameStart = start;
|
|
1454
|
+
for (let index = start; index < dotIndex; index++) {
|
|
1455
|
+
const code = text.charCodeAt(index);
|
|
1456
|
+
if (code === 47 || code === 92) {
|
|
1457
|
+
filenameStart = index + 1;
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
return filenameStart;
|
|
1461
|
+
};
|
|
1462
|
+
var isFilePathCandidate = (text, start, end) => {
|
|
1463
|
+
const punctuationEnd = stripTrailingPathPunctuation(text, start, end);
|
|
1464
|
+
const pathEnd = stripLineSuffixes(text, start, punctuationEnd);
|
|
1465
|
+
const dotIndex = findLastDot(text, start, pathEnd);
|
|
1466
|
+
if (dotIndex < 0 || dotIndex + 1 >= pathEnd) return false;
|
|
1467
|
+
if (!matchesKnownExtension(text, dotIndex + 1, pathEnd)) return false;
|
|
1468
|
+
return dotIndex > findFilenameStart(text, start, dotIndex);
|
|
1469
|
+
};
|
|
1470
|
+
var detectFilePaths = (text) => {
|
|
1471
|
+
let candidateStart = -1;
|
|
1472
|
+
let candidateTooLong = false;
|
|
1473
|
+
for (let index = 0; index <= text.length; index++) {
|
|
1474
|
+
const isCandidateChar = index < text.length && isPathCandidateChar(text.charCodeAt(index));
|
|
1475
|
+
if (isCandidateChar) {
|
|
1476
|
+
if (candidateStart < 0) {
|
|
1477
|
+
candidateStart = index;
|
|
1478
|
+
}
|
|
1479
|
+
if (index + 1 - candidateStart > MAX_FILE_PATH_CANDIDATE_LENGTH) {
|
|
1480
|
+
candidateTooLong = true;
|
|
1481
|
+
}
|
|
1482
|
+
continue;
|
|
1483
|
+
}
|
|
1484
|
+
if (candidateStart >= 0) {
|
|
1485
|
+
if (!candidateTooLong && isFilePathCandidate(text, candidateStart, index)) {
|
|
1486
|
+
return true;
|
|
1487
|
+
}
|
|
1488
|
+
candidateStart = -1;
|
|
1489
|
+
candidateTooLong = false;
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
return false;
|
|
1493
|
+
};
|
|
1494
|
+
var detectKeywords = (text) => {
|
|
1495
|
+
const result = {};
|
|
1496
|
+
for (const kw of KEYWORDS) {
|
|
1497
|
+
result[kw] = KEYWORD_PATTERNS.get(kw).test(text);
|
|
1498
|
+
}
|
|
1499
|
+
return result;
|
|
1500
|
+
};
|
|
1501
|
+
var extractContextSignals = (observations) => {
|
|
1502
|
+
let hasProjectProfile = false;
|
|
1503
|
+
let searchResultCount = 0;
|
|
1504
|
+
let discoveredFileCount = 0;
|
|
1505
|
+
for (const obs of observations) {
|
|
1506
|
+
switch (obs.type) {
|
|
1507
|
+
case "fs.fileRead":
|
|
1508
|
+
discoveredFileCount++;
|
|
1509
|
+
if (obs.path.endsWith("package.json")) {
|
|
1510
|
+
hasProjectProfile = true;
|
|
1511
|
+
}
|
|
1512
|
+
break;
|
|
1513
|
+
case "fs.searchResult":
|
|
1514
|
+
searchResultCount += obs.matches.length;
|
|
1515
|
+
break;
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
return {
|
|
1519
|
+
hasProjectProfile,
|
|
1520
|
+
searchResultCount,
|
|
1521
|
+
discoveredFileCount
|
|
1522
|
+
};
|
|
1523
|
+
};
|
|
1524
|
+
var extractSignals = (state) => {
|
|
1525
|
+
const goalText = state.goal.text;
|
|
1526
|
+
return {
|
|
1527
|
+
goalLengthCategory: categorizeGoalLength(goalText),
|
|
1528
|
+
hasFilePaths: detectFilePaths(goalText),
|
|
1529
|
+
keywords: detectKeywords(goalText),
|
|
1530
|
+
contextSignals: extractContextSignals(state.observations)
|
|
1531
|
+
};
|
|
1532
|
+
};
|
|
1533
|
+
|
|
1534
|
+
// src/agent/core/patchStrategy/promptStrategy.ts
|
|
1535
|
+
var strategyPromptFragment = (strategy) => {
|
|
1536
|
+
switch (strategy) {
|
|
1537
|
+
case "direct-patch":
|
|
1538
|
+
return "Produce a single focused patch in one response. Do not plan multiple steps. Emit one unified diff that addresses the goal directly.";
|
|
1539
|
+
case "multi-step-patch":
|
|
1540
|
+
return "You may produce multiple incremental patches across responses. Start with the most critical change, then refine iteratively based on validation feedback.";
|
|
1541
|
+
case "propose-then-refine":
|
|
1542
|
+
return "First propose a plan describing what changes are needed and why. Do NOT include a patch in this response. After validation feedback, produce the refined patch in a follow-up.";
|
|
1543
|
+
}
|
|
1544
|
+
};
|
|
1545
|
+
|
|
1021
1546
|
// src/agent/core/decide.ts
|
|
1022
1547
|
var hasObservation = (state, type) => state.observations.some((obs) => obs.type === type);
|
|
1023
1548
|
var lastObservation = (state, type) => [...state.observations].reverse().find((obs) => obs.type === type);
|
|
@@ -1039,7 +1564,7 @@ var observationsAfterLatestWorkspaceChange = (state) => {
|
|
|
1039
1564
|
var latestWorkspaceChange = (state) => {
|
|
1040
1565
|
const index = latestWorkspaceChangeIndex(state);
|
|
1041
1566
|
const observation = index < 0 ? void 0 : state.observations[index];
|
|
1042
|
-
return _optionalChain([observation, 'optionalAccess',
|
|
1567
|
+
return _optionalChain([observation, 'optionalAccess', _89 => _89.type]) === "patch.applied" || _optionalChain([observation, 'optionalAccess', _90 => _90.type]) === "patch.rolledBack" ? observation : void 0;
|
|
1043
1568
|
};
|
|
1044
1569
|
var compactObservation = (obs) => {
|
|
1045
1570
|
switch (obs.type) {
|
|
@@ -1102,13 +1627,13 @@ var causeMessage = (cause) => {
|
|
|
1102
1627
|
try {
|
|
1103
1628
|
const json = JSON.stringify(cause);
|
|
1104
1629
|
if (json && json !== "{}") return json;
|
|
1105
|
-
} catch (
|
|
1630
|
+
} catch (e5) {
|
|
1106
1631
|
}
|
|
1107
1632
|
}
|
|
1108
1633
|
return String(cause);
|
|
1109
1634
|
};
|
|
1110
1635
|
var errorDetail = (state, cause) => redactForPrompt(state, causeMessage(cause)).slice(0, 2e3);
|
|
1111
|
-
var buildPlanningPrompt = (state) => {
|
|
1636
|
+
var buildPlanningPrompt = (state, strategy) => {
|
|
1112
1637
|
const discovery = discoverValidationCommands(state);
|
|
1113
1638
|
return redactForPrompt(state, [
|
|
1114
1639
|
"You are a coding agent running on brass-runtime.",
|
|
@@ -1119,6 +1644,7 @@ var buildPlanningPrompt = (state) => {
|
|
|
1119
1644
|
"Only propose a patch when the observations are strong enough.",
|
|
1120
1645
|
"Use the project command discovery summary as context, but do not invent commands that were not run.",
|
|
1121
1646
|
describeLanguagePolicy(state.goal),
|
|
1647
|
+
strategy ? strategyPromptFragment(strategy) : "",
|
|
1122
1648
|
"",
|
|
1123
1649
|
`Goal: ${state.goal.text}`,
|
|
1124
1650
|
`Workspace: ${state.goal.cwd}`,
|
|
@@ -1142,7 +1668,7 @@ ${result.stderr.slice(-8e3)}` : void 0
|
|
|
1142
1668
|
var buildPatchRepairPrompt = (state, reason) => {
|
|
1143
1669
|
const discovery = discoverValidationCommands(state);
|
|
1144
1670
|
const quality = patchQualitySummary(state);
|
|
1145
|
-
const latestPatchError = _optionalChain([lastObservation, 'call',
|
|
1671
|
+
const latestPatchError = _optionalChain([lastObservation, 'call', _91 => _91(state, "agent.error"), 'optionalAccess', _92 => _92.error]);
|
|
1146
1672
|
const latestPatch = lastMaterializedPatch(state);
|
|
1147
1673
|
return redactForPrompt(state, [
|
|
1148
1674
|
"You are repairing a generated patch for a coding agent running on brass-runtime.",
|
|
@@ -1168,7 +1694,7 @@ ${latestPatch.slice(-8e3)}` : "Latest materialized patch: none.",
|
|
|
1168
1694
|
failedValidationLines(state).length > 0 ? `Failed validation after latest patch:
|
|
1169
1695
|
${failedValidationLines(state).join("\n\n")}` : "Failed validation after latest patch: none recorded.",
|
|
1170
1696
|
"",
|
|
1171
|
-
_optionalChain([latestPatchError, 'optionalAccess',
|
|
1697
|
+
_optionalChain([latestPatchError, 'optionalAccess', _93 => _93._tag]) === "PatchError" ? `Latest patch error during ${latestPatchError.operation}: ${String(latestPatchError.cause)}` : "Latest patch error: none.",
|
|
1172
1698
|
"",
|
|
1173
1699
|
"Recent observations:",
|
|
1174
1700
|
compactObservations(state) || "No observations yet."
|
|
@@ -1180,14 +1706,14 @@ var buildValidationSummary = (state) => {
|
|
|
1180
1706
|
if (validationResults.length === 0) return void 0;
|
|
1181
1707
|
const change = latestWorkspaceChange(state);
|
|
1182
1708
|
const spanish = spanishLike(state.goal);
|
|
1183
|
-
const label = _optionalChain([change, 'optionalAccess',
|
|
1709
|
+
const label = _optionalChain([change, 'optionalAccess', _94 => _94.type]) === "patch.rolledBack" ? spanish ? "rollback" : "rollback" : spanish ? "aplicar patch" : "apply";
|
|
1184
1710
|
return [
|
|
1185
1711
|
spanish ? `Validaci\xF3n despu\xE9s de ${label}:` : `Validation after latest ${label}:`,
|
|
1186
1712
|
...validationResults.map((result) => `- ${result.command.join(" ")} ${spanish ? "termin\xF3 con c\xF3digo" : "exited with"} ${result.exitCode}.`)
|
|
1187
1713
|
].join("\n");
|
|
1188
1714
|
};
|
|
1189
1715
|
var buildCompletionSummary = (state, patch) => {
|
|
1190
|
-
const plan = _nullishCoalesce(_optionalChain([firstObservation, 'call',
|
|
1716
|
+
const plan = _nullishCoalesce(_optionalChain([firstObservation, 'call', _95 => _95(state, "llm.response"), 'optionalAccess', _96 => _96.content, 'optionalAccess', _97 => _97.trim, 'call', _98 => _98()]), () => ( "No plan was generated."));
|
|
1191
1717
|
const latestResponse = lastObservation(state, "llm.response");
|
|
1192
1718
|
const patchApplied = lastObservation(state, "patch.applied");
|
|
1193
1719
|
const patchRolledBack = lastObservation(state, "patch.rolledBack");
|
|
@@ -1195,7 +1721,7 @@ var buildCompletionSummary = (state, patch) => {
|
|
|
1195
1721
|
const validation = buildValidationSummary(state);
|
|
1196
1722
|
const spanish = spanishLike(state.goal);
|
|
1197
1723
|
const lines = [plan];
|
|
1198
|
-
if (_optionalChain([latestResponse, 'optionalAccess',
|
|
1724
|
+
if (_optionalChain([latestResponse, 'optionalAccess', _99 => _99.purpose]) === "patch" && latestResponse.content.trim()) {
|
|
1199
1725
|
lines.push("", spanish ? "\xDAltima respuesta de reparaci\xF3n del patch:" : "Latest patch repair response:", latestResponse.content.trim());
|
|
1200
1726
|
}
|
|
1201
1727
|
if (patchRolledBack) {
|
|
@@ -1219,14 +1745,14 @@ var buildCompletionSummary = (state, patch) => {
|
|
|
1219
1745
|
return redactForPrompt(state, lines.join("\n").trim());
|
|
1220
1746
|
};
|
|
1221
1747
|
var buildErrorSummary = (state) => {
|
|
1222
|
-
const latestError = _optionalChain([lastObservation, 'call',
|
|
1748
|
+
const latestError = _optionalChain([lastObservation, 'call', _100 => _100(state, "agent.error"), 'optionalAccess', _101 => _101.error]);
|
|
1223
1749
|
const spanish = spanishLike(state.goal);
|
|
1224
1750
|
if (!latestError) return spanish ? "La ejecuci\xF3n del agente fall\xF3." : "Agent run failed.";
|
|
1225
1751
|
switch (latestError._tag) {
|
|
1226
1752
|
case "FsError":
|
|
1227
1753
|
return spanish ? `El agente se detuvo por un error de filesystem durante ${latestError.operation}: ${errorDetail(state, latestError.cause)}` : `Agent stopped after a filesystem error during ${latestError.operation}: ${errorDetail(state, latestError.cause)}`;
|
|
1228
1754
|
case "ShellError":
|
|
1229
|
-
return spanish ? `El agente se detuvo por un error ejecutando ${_nullishCoalesce(_optionalChain([latestError, 'access',
|
|
1755
|
+
return spanish ? `El agente se detuvo por un error ejecutando ${_nullishCoalesce(_optionalChain([latestError, 'access', _102 => _102.command, 'optionalAccess', _103 => _103.join, 'call', _104 => _104(" ")]), () => ( latestError.operation))}: ${errorDetail(state, latestError.cause)}` : `Agent stopped after a shell error during ${_nullishCoalesce(_optionalChain([latestError, 'access', _105 => _105.command, 'optionalAccess', _106 => _106.join, 'call', _107 => _107(" ")]), () => ( latestError.operation))}: ${errorDetail(state, latestError.cause)}`;
|
|
1230
1756
|
case "LLMError":
|
|
1231
1757
|
return spanish ? `El agente se detuvo porque fall\xF3 la llamada al modelo: ${errorDetail(state, latestError.cause)}` : `Agent stopped because the model call failed: ${errorDetail(state, latestError.cause)}`;
|
|
1232
1758
|
case "PatchError":
|
|
@@ -1274,7 +1800,7 @@ var latestLlmPatchCandidate = (state) => {
|
|
|
1274
1800
|
var latestExtractedPatch = (state) => {
|
|
1275
1801
|
for (let index = state.observations.length - 1; index >= 0; index -= 1) {
|
|
1276
1802
|
const observation = state.observations[index];
|
|
1277
|
-
if (_optionalChain([observation, 'optionalAccess',
|
|
1803
|
+
if (_optionalChain([observation, 'optionalAccess', _108 => _108.type]) !== "llm.response") continue;
|
|
1278
1804
|
const patch = extractUnifiedDiff(observation.content);
|
|
1279
1805
|
if (patch) return patch;
|
|
1280
1806
|
}
|
|
@@ -1283,8 +1809,8 @@ var latestExtractedPatch = (state) => {
|
|
|
1283
1809
|
var lastMaterializedPatch = (state) => {
|
|
1284
1810
|
for (let index = state.observations.length - 1; index >= 0; index -= 1) {
|
|
1285
1811
|
const observation = state.observations[index];
|
|
1286
|
-
if (_optionalChain([observation, 'optionalAccess',
|
|
1287
|
-
if (_optionalChain([observation, 'optionalAccess',
|
|
1812
|
+
if (_optionalChain([observation, 'optionalAccess', _109 => _109.type]) === "patch.proposed") return observation.patch;
|
|
1813
|
+
if (_optionalChain([observation, 'optionalAccess', _110 => _110.type]) === "patch.applied") {
|
|
1288
1814
|
if (observation.patch) return observation.patch;
|
|
1289
1815
|
const previousLlmPatch = state.observations.slice(0, index).reverse().find((obs) => obs.type === "llm.response" && Boolean(extractUnifiedDiff(obs.content)));
|
|
1290
1816
|
return previousLlmPatch ? extractUnifiedDiff(previousLlmPatch.content) : state.goal.initialPatch;
|
|
@@ -1294,7 +1820,7 @@ var lastMaterializedPatch = (state) => {
|
|
|
1294
1820
|
};
|
|
1295
1821
|
var shouldRequestRepairAfterValidation = (state) => {
|
|
1296
1822
|
if (!isWritableMode(state.goal.mode)) return false;
|
|
1297
|
-
if (_optionalChain([latestWorkspaceChange, 'call',
|
|
1823
|
+
if (_optionalChain([latestWorkspaceChange, 'call', _111 => _111(state), 'optionalAccess', _112 => _112.type]) !== "patch.applied") return false;
|
|
1298
1824
|
if (!canRequestPatchRepair(state)) return false;
|
|
1299
1825
|
const commands = discoverValidationCommands(state).validationCommands;
|
|
1300
1826
|
const status = patchValidationStatus(commands, observationsAfterPatch(state));
|
|
@@ -1302,7 +1828,7 @@ var shouldRequestRepairAfterValidation = (state) => {
|
|
|
1302
1828
|
};
|
|
1303
1829
|
var shouldAutoRollbackAfterFinalValidationFailure = (state) => {
|
|
1304
1830
|
if (!isWritableMode(state.goal.mode)) return false;
|
|
1305
|
-
if (_optionalChain([latestWorkspaceChange, 'call',
|
|
1831
|
+
if (_optionalChain([latestWorkspaceChange, 'call', _113 => _113(state), 'optionalAccess', _114 => _114.type]) !== "patch.applied") return false;
|
|
1306
1832
|
if (canRequestPatchRepair(state)) return false;
|
|
1307
1833
|
const summary = rollbackSafetySummary(state);
|
|
1308
1834
|
if (!summary.onFinalValidationFailure) return false;
|
|
@@ -1315,7 +1841,7 @@ var shouldRequestRepairAfterPatchError = (state) => {
|
|
|
1315
1841
|
if (!isWritableMode(state.goal.mode)) return false;
|
|
1316
1842
|
if (!canRequestPatchRepair(state)) return false;
|
|
1317
1843
|
const latest = state.observations.at(-1);
|
|
1318
|
-
return _optionalChain([latest, 'optionalAccess',
|
|
1844
|
+
return _optionalChain([latest, 'optionalAccess', _115 => _115.type]) === "agent.error" && latest.error._tag === "PatchError";
|
|
1319
1845
|
};
|
|
1320
1846
|
var repairAction = (state, reason) => ({
|
|
1321
1847
|
type: "llm.complete",
|
|
@@ -1352,8 +1878,11 @@ var initialPatchFlowAction = (state, suppliedPatch) => {
|
|
|
1352
1878
|
};
|
|
1353
1879
|
var decideNextAction = (state) => {
|
|
1354
1880
|
const latest = state.observations.at(-1);
|
|
1355
|
-
if (_optionalChain([latest, 'optionalAccess',
|
|
1881
|
+
if (_optionalChain([latest, 'optionalAccess', _116 => _116.type]) === "agent.error") {
|
|
1356
1882
|
if (shouldRequestRepairAfterPatchError(state)) {
|
|
1883
|
+
if (state.goal.llmAvailable === false) {
|
|
1884
|
+
return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, { type: "agent.finish", summary: buildErrorSummary(state) });
|
|
1885
|
+
}
|
|
1357
1886
|
return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, repairAction(state, "previous patch failed to apply"));
|
|
1358
1887
|
}
|
|
1359
1888
|
return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, { type: "agent.finish", summary: buildErrorSummary(state) });
|
|
@@ -1365,7 +1894,7 @@ var decideNextAction = (state) => {
|
|
|
1365
1894
|
if (probeAction) {
|
|
1366
1895
|
return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, probeAction);
|
|
1367
1896
|
}
|
|
1368
|
-
const suppliedPatch = _optionalChain([state, 'access',
|
|
1897
|
+
const suppliedPatch = _optionalChain([state, 'access', _117 => _117.goal, 'access', _118 => _118.initialPatch, 'optionalAccess', _119 => _119.trim, 'call', _120 => _120()]);
|
|
1369
1898
|
if (suppliedPatch) {
|
|
1370
1899
|
const action = initialPatchFlowAction(state, suppliedPatch);
|
|
1371
1900
|
if (action) return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, action);
|
|
@@ -1389,12 +1918,25 @@ var decideNextAction = (state) => {
|
|
|
1389
1918
|
if (!planResponse) {
|
|
1390
1919
|
const validationAction = nextValidationActionBeforePlanning(state);
|
|
1391
1920
|
if (validationAction) return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, validationAction);
|
|
1392
|
-
const contextAction = nextContextDiscoveryAction(state);
|
|
1921
|
+
const contextAction = nextContextDiscoveryAction(state, state.goal.banditState);
|
|
1393
1922
|
if (contextAction) return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, contextAction);
|
|
1923
|
+
if (state.goal.llmAvailable === false) {
|
|
1924
|
+
return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, {
|
|
1925
|
+
type: "agent.finish",
|
|
1926
|
+
summary: "No LLM provider configured. Tool-only execution complete."
|
|
1927
|
+
});
|
|
1928
|
+
}
|
|
1929
|
+
const signals = extractSignals(state);
|
|
1930
|
+
const strategy = selectStrategy(
|
|
1931
|
+
signals,
|
|
1932
|
+
state.goal.patchStrategy,
|
|
1933
|
+
_nullishCoalesce(state.goal.rewardHistory, () => ( [])),
|
|
1934
|
+
{ sampleBeta: (a, b) => sampleBeta(a, b, Math.random), random: Math.random }
|
|
1935
|
+
);
|
|
1394
1936
|
return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, {
|
|
1395
1937
|
type: "llm.complete",
|
|
1396
1938
|
purpose: "plan",
|
|
1397
|
-
prompt: buildPlanningPrompt(state)
|
|
1939
|
+
prompt: buildPlanningPrompt(state, strategy)
|
|
1398
1940
|
});
|
|
1399
1941
|
}
|
|
1400
1942
|
if (isWritableMode(state.goal.mode)) {
|
|
@@ -1402,17 +1944,20 @@ var decideNextAction = (state) => {
|
|
|
1402
1944
|
const rollbackAction = automaticRollbackAction(state, "continuing rollback of generated patch stack");
|
|
1403
1945
|
if (rollbackAction) return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, rollbackAction);
|
|
1404
1946
|
}
|
|
1405
|
-
if (_optionalChain([latestWorkspaceChange, 'call',
|
|
1947
|
+
if (_optionalChain([latestWorkspaceChange, 'call', _121 => _121(state), 'optionalAccess', _122 => _122.type]) === "patch.rolledBack") {
|
|
1406
1948
|
const summary = rollbackSafetySummary(state);
|
|
1407
1949
|
if (summary.runValidationAfterRollback) {
|
|
1408
1950
|
const validationAction = nextValidationActionAfterLatestWorkspaceChange(state);
|
|
1409
1951
|
if (validationAction) return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, validationAction);
|
|
1410
1952
|
}
|
|
1411
1953
|
}
|
|
1412
|
-
if (_optionalChain([latestWorkspaceChange, 'call',
|
|
1954
|
+
if (_optionalChain([latestWorkspaceChange, 'call', _123 => _123(state), 'optionalAccess', _124 => _124.type]) === "patch.applied") {
|
|
1413
1955
|
const validationAction = nextValidationActionAfterPatch(state);
|
|
1414
1956
|
if (validationAction) return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, validationAction);
|
|
1415
1957
|
if (shouldRequestRepairAfterValidation(state)) {
|
|
1958
|
+
if (state.goal.llmAvailable === false) {
|
|
1959
|
+
return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, { type: "agent.finish", summary: buildErrorSummary(state) });
|
|
1960
|
+
}
|
|
1416
1961
|
return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, repairAction(state, "validation failed after applying the generated patch"));
|
|
1417
1962
|
}
|
|
1418
1963
|
if (shouldAutoRollbackAfterFinalValidationFailure(state)) {
|
|
@@ -1434,8 +1979,8 @@ var nowMillis = () => _chunkMVGUEJ5Zcjs.asyncEffect.call(void 0, (_env, cb) => {
|
|
|
1434
1979
|
});
|
|
1435
1980
|
var emitAgentEvent = (event) => _chunkMVGUEJ5Zcjs.asyncEffect.call(void 0, (env, cb) => {
|
|
1436
1981
|
try {
|
|
1437
|
-
_optionalChain([env, 'access',
|
|
1438
|
-
} catch (
|
|
1982
|
+
_optionalChain([env, 'access', _125 => _125.events, 'optionalAccess', _126 => _126.emit, 'call', _127 => _127(event)]);
|
|
1983
|
+
} catch (e6) {
|
|
1439
1984
|
}
|
|
1440
1985
|
cb({ _tag: "Success", value: void 0 });
|
|
1441
1986
|
});
|
|
@@ -1632,13 +2177,22 @@ var actionToEffect = (action, state) => {
|
|
|
1632
2177
|
)
|
|
1633
2178
|
);
|
|
1634
2179
|
case "llm.complete":
|
|
1635
|
-
return _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
|
|
1636
|
-
|
|
1637
|
-
|
|
2180
|
+
return _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0, service("llm"), (llm) => {
|
|
2181
|
+
if (!llm) {
|
|
2182
|
+
return _chunkMVGUEJ5Zcjs.asyncFail.call(void 0, {
|
|
2183
|
+
_tag: "LLMError",
|
|
2184
|
+
cause: "llm_unavailable: no LLM provider is configured"
|
|
2185
|
+
});
|
|
2186
|
+
}
|
|
2187
|
+
return _chunkMVGUEJ5Zcjs.asyncMap.call(void 0,
|
|
1638
2188
|
llm.complete({ purpose: action.purpose, prompt: action.prompt }),
|
|
1639
|
-
(response) => ({
|
|
1640
|
-
|
|
1641
|
-
|
|
2189
|
+
(response) => ({
|
|
2190
|
+
type: "llm.response",
|
|
2191
|
+
purpose: action.purpose,
|
|
2192
|
+
content: response.content
|
|
2193
|
+
})
|
|
2194
|
+
);
|
|
2195
|
+
});
|
|
1642
2196
|
case "patch.propose":
|
|
1643
2197
|
return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, { type: "patch.proposed", patch: action.patch });
|
|
1644
2198
|
case "patch.apply":
|
|
@@ -1721,11 +2275,11 @@ var defaultPolicyFor = (action) => {
|
|
|
1721
2275
|
};
|
|
1722
2276
|
var configuredPolicyFor = (action, overrides) => {
|
|
1723
2277
|
const base = defaultPolicyFor(action);
|
|
1724
|
-
const override = _optionalChain([overrides, 'optionalAccess',
|
|
2278
|
+
const override = _optionalChain([overrides, 'optionalAccess', _128 => _128[action.type]]);
|
|
1725
2279
|
return {
|
|
1726
2280
|
...base,
|
|
1727
|
-
timeoutMs: _optionalChain([override, 'optionalAccess',
|
|
1728
|
-
retries: _optionalChain([override, 'optionalAccess',
|
|
2281
|
+
timeoutMs: _optionalChain([override, 'optionalAccess', _129 => _129.timeoutMs]) !== void 0 ? Math.max(1, Math.floor(override.timeoutMs)) : base.timeoutMs,
|
|
2282
|
+
retries: _optionalChain([override, 'optionalAccess', _130 => _130.retries]) !== void 0 ? Math.max(0, Math.floor(override.retries)) : base.retries
|
|
1729
2283
|
};
|
|
1730
2284
|
};
|
|
1731
2285
|
var runAuthorizedAction = (action, state, scope) => _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0, _chunkMVGUEJ5Zcjs.asyncSync.call(void 0, (env) => env.toolPolicies), (toolPolicies) => {
|
|
@@ -1821,7 +2375,265 @@ var invokeAction = (action, state, scope) => _chunkMVGUEJ5Zcjs.asyncFlatMap.call
|
|
|
1821
2375
|
})
|
|
1822
2376
|
);
|
|
1823
2377
|
|
|
2378
|
+
// src/agent/core/llmBudget/config.ts
|
|
2379
|
+
var DEFAULTS = {
|
|
2380
|
+
overshootFraction: 0.1,
|
|
2381
|
+
enabled: true
|
|
2382
|
+
};
|
|
2383
|
+
var resolveBudgetConfig = (goalBudget, configBudget) => {
|
|
2384
|
+
if (goalBudget === void 0 && configBudget === void 0) {
|
|
2385
|
+
return void 0;
|
|
2386
|
+
}
|
|
2387
|
+
const merged = {
|
|
2388
|
+
...configBudget,
|
|
2389
|
+
...goalBudget
|
|
2390
|
+
};
|
|
2391
|
+
if (merged.tokenBudget === void 0) {
|
|
2392
|
+
return void 0;
|
|
2393
|
+
}
|
|
2394
|
+
return {
|
|
2395
|
+
tokenBudget: merged.tokenBudget,
|
|
2396
|
+
overshootFraction: _nullishCoalesce(merged.overshootFraction, () => ( DEFAULTS.overshootFraction)),
|
|
2397
|
+
enabled: _nullishCoalesce(merged.enabled, () => ( DEFAULTS.enabled)),
|
|
2398
|
+
modelTiers: merged.modelTiers
|
|
2399
|
+
};
|
|
2400
|
+
};
|
|
2401
|
+
var validateBudgetConfig = (config) => {
|
|
2402
|
+
if (!Number.isFinite(config.tokenBudget) || config.tokenBudget <= 0) {
|
|
2403
|
+
return `tokenBudget must be a positive finite number, got ${config.tokenBudget}`;
|
|
2404
|
+
}
|
|
2405
|
+
if (!Number.isFinite(config.overshootFraction) || config.overshootFraction < 0 || config.overshootFraction > 1) {
|
|
2406
|
+
return `overshootFraction must be between 0 and 1 inclusive, got ${config.overshootFraction}`;
|
|
2407
|
+
}
|
|
2408
|
+
return void 0;
|
|
2409
|
+
};
|
|
2410
|
+
|
|
2411
|
+
// src/agent/core/llmBudget/state.ts
|
|
2412
|
+
var initBudgetState = () => ({
|
|
2413
|
+
totalInputTokens: 0,
|
|
2414
|
+
totalOutputTokens: 0,
|
|
2415
|
+
totalTokens: 0,
|
|
2416
|
+
callCount: 0,
|
|
2417
|
+
calls: []
|
|
2418
|
+
});
|
|
2419
|
+
var updateBudgetState = (state, usage, tier, confidence, estimated) => {
|
|
2420
|
+
const totalInputTokens = state.totalInputTokens + usage.inputTokens;
|
|
2421
|
+
const totalOutputTokens = state.totalOutputTokens + usage.outputTokens;
|
|
2422
|
+
return {
|
|
2423
|
+
totalInputTokens,
|
|
2424
|
+
totalOutputTokens,
|
|
2425
|
+
totalTokens: totalInputTokens + totalOutputTokens,
|
|
2426
|
+
callCount: state.callCount + 1,
|
|
2427
|
+
calls: [
|
|
2428
|
+
...state.calls,
|
|
2429
|
+
{ usage, tier, confidence, estimated }
|
|
2430
|
+
]
|
|
2431
|
+
};
|
|
2432
|
+
};
|
|
2433
|
+
var budgetStatus = (state, config) => {
|
|
2434
|
+
const { totalTokens } = state;
|
|
2435
|
+
const { tokenBudget, overshootFraction } = config;
|
|
2436
|
+
const hardCap = tokenBudget * (1 + overshootFraction);
|
|
2437
|
+
if (totalTokens <= tokenBudget) {
|
|
2438
|
+
return { type: "under" };
|
|
2439
|
+
}
|
|
2440
|
+
if (totalTokens <= hardCap) {
|
|
2441
|
+
return { type: "warning", overage: totalTokens - tokenBudget };
|
|
2442
|
+
}
|
|
2443
|
+
return { type: "exceeded", overage: totalTokens - tokenBudget };
|
|
2444
|
+
};
|
|
2445
|
+
var budgetAllowsCall = (state, config) => {
|
|
2446
|
+
return budgetStatus(state, config).type !== "exceeded";
|
|
2447
|
+
};
|
|
2448
|
+
|
|
2449
|
+
// src/agent/core/llmBudget/estimation.ts
|
|
2450
|
+
var estimateTokens = (promptLength, responseLength) => ({
|
|
2451
|
+
inputTokens: Math.ceil(promptLength / 4),
|
|
2452
|
+
outputTokens: Math.ceil(responseLength / 4)
|
|
2453
|
+
});
|
|
2454
|
+
|
|
2455
|
+
// src/agent/core/llmBudget/confidence.ts
|
|
2456
|
+
var HEDGING_PHRASES = [
|
|
2457
|
+
"i think",
|
|
2458
|
+
"maybe",
|
|
2459
|
+
"perhaps",
|
|
2460
|
+
"not sure",
|
|
2461
|
+
"might be",
|
|
2462
|
+
"could be"
|
|
2463
|
+
];
|
|
2464
|
+
var hasDiffBlock = (response) => {
|
|
2465
|
+
if (response.includes("```diff")) return true;
|
|
2466
|
+
const lines = response.split("\n");
|
|
2467
|
+
return lines.some(
|
|
2468
|
+
(line) => line.startsWith("---") || line.startsWith("+++")
|
|
2469
|
+
);
|
|
2470
|
+
};
|
|
2471
|
+
var isConcise = (response) => response.length < 2e3;
|
|
2472
|
+
var referencesGoal = (response, goal) => {
|
|
2473
|
+
const words = goal.split(/\s+/).filter((w) => w.length >= 3).map((w) => w.toLowerCase());
|
|
2474
|
+
const responseLower = response.toLowerCase();
|
|
2475
|
+
return words.some((word) => responseLower.includes(word));
|
|
2476
|
+
};
|
|
2477
|
+
var referencesReadFiles = (response, readFiles) => {
|
|
2478
|
+
if (readFiles.length === 0) return false;
|
|
2479
|
+
return readFiles.some((filePath) => response.includes(filePath));
|
|
2480
|
+
};
|
|
2481
|
+
var countHedgingPhrases = (response) => {
|
|
2482
|
+
const responseLower = response.toLowerCase();
|
|
2483
|
+
let count = 0;
|
|
2484
|
+
for (const phrase of HEDGING_PHRASES) {
|
|
2485
|
+
let idx = 0;
|
|
2486
|
+
while (true) {
|
|
2487
|
+
const found = responseLower.indexOf(phrase, idx);
|
|
2488
|
+
if (found === -1) break;
|
|
2489
|
+
count++;
|
|
2490
|
+
idx = found + phrase.length;
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2493
|
+
return count;
|
|
2494
|
+
};
|
|
2495
|
+
var extractConfidenceSignals = (response, goal, readFiles) => ({
|
|
2496
|
+
hasDiffBlock: hasDiffBlock(response),
|
|
2497
|
+
isConcise: isConcise(response),
|
|
2498
|
+
referencesGoal: referencesGoal(response, goal),
|
|
2499
|
+
referencesReadFiles: referencesReadFiles(response, readFiles),
|
|
2500
|
+
hedgingCount: countHedgingPhrases(response)
|
|
2501
|
+
});
|
|
2502
|
+
var estimateConfidence = (response, goal, readFiles) => {
|
|
2503
|
+
const signals = extractConfidenceSignals(response, goal, readFiles);
|
|
2504
|
+
let score = 0.35;
|
|
2505
|
+
if (signals.hasDiffBlock) score += 0.2;
|
|
2506
|
+
if (signals.isConcise) score += 0.15;
|
|
2507
|
+
if (signals.referencesGoal) score += 0.15;
|
|
2508
|
+
if (signals.referencesReadFiles) score += 0.15;
|
|
2509
|
+
const hedgingPenalty = Math.min(signals.hedgingCount * 0.1, 0.3);
|
|
2510
|
+
score -= hedgingPenalty;
|
|
2511
|
+
score = Math.max(0, Math.min(1, score));
|
|
2512
|
+
return { score, signals };
|
|
2513
|
+
};
|
|
2514
|
+
|
|
2515
|
+
// src/agent/core/llmBudget/router.ts
|
|
2516
|
+
var DEFAULT_THRESHOLDS = {
|
|
2517
|
+
goalLength: 500,
|
|
2518
|
+
filesRead: 5,
|
|
2519
|
+
searchMatches: 30,
|
|
2520
|
+
repairAttempts: 1
|
|
2521
|
+
};
|
|
2522
|
+
var extractComplexitySignals = (state) => {
|
|
2523
|
+
const observations = state.observations;
|
|
2524
|
+
const goalLength = state.goal.text.length;
|
|
2525
|
+
let filesRead = 0;
|
|
2526
|
+
let searchMatches2 = 0;
|
|
2527
|
+
let hasValidationErrors = false;
|
|
2528
|
+
let repairAttempts = 0;
|
|
2529
|
+
for (const obs of observations) {
|
|
2530
|
+
switch (obs.type) {
|
|
2531
|
+
case "fs.fileRead":
|
|
2532
|
+
filesRead++;
|
|
2533
|
+
break;
|
|
2534
|
+
case "fs.searchResult":
|
|
2535
|
+
searchMatches2 += obs.matches.length;
|
|
2536
|
+
break;
|
|
2537
|
+
case "shell.result":
|
|
2538
|
+
if (obs.exitCode !== 0) {
|
|
2539
|
+
hasValidationErrors = true;
|
|
2540
|
+
}
|
|
2541
|
+
break;
|
|
2542
|
+
case "llm.response":
|
|
2543
|
+
if (obs.purpose === "patch") {
|
|
2544
|
+
repairAttempts++;
|
|
2545
|
+
}
|
|
2546
|
+
break;
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
return {
|
|
2550
|
+
goalLength,
|
|
2551
|
+
filesRead,
|
|
2552
|
+
searchMatches: searchMatches2,
|
|
2553
|
+
hasValidationErrors,
|
|
2554
|
+
repairAttempts
|
|
2555
|
+
};
|
|
2556
|
+
};
|
|
2557
|
+
var routeModel = (state, _budgetState, thresholds) => {
|
|
2558
|
+
const t = _nullishCoalesce(thresholds, () => ( DEFAULT_THRESHOLDS));
|
|
2559
|
+
const signals = extractComplexitySignals(state);
|
|
2560
|
+
if (signals.goalLength >= t.goalLength || signals.filesRead >= t.filesRead || signals.searchMatches >= t.searchMatches || signals.hasValidationErrors || signals.repairAttempts >= t.repairAttempts) {
|
|
2561
|
+
return "large";
|
|
2562
|
+
}
|
|
2563
|
+
return "small";
|
|
2564
|
+
};
|
|
2565
|
+
|
|
2566
|
+
// src/agent/core/llmBudget/events.ts
|
|
2567
|
+
var makeBudgetUsageEvent = (usage, cumulative, tier, remaining) => ({
|
|
2568
|
+
type: "budget.usage",
|
|
2569
|
+
usage,
|
|
2570
|
+
cumulative,
|
|
2571
|
+
tier,
|
|
2572
|
+
remaining,
|
|
2573
|
+
at: Date.now()
|
|
2574
|
+
});
|
|
2575
|
+
var makeBudgetRoutedEvent = (tier, signals, resolvedProvider) => ({
|
|
2576
|
+
type: "budget.routed",
|
|
2577
|
+
tier,
|
|
2578
|
+
signals,
|
|
2579
|
+
resolvedProvider,
|
|
2580
|
+
at: Date.now()
|
|
2581
|
+
});
|
|
2582
|
+
var makeBudgetConfidenceEvent = (score, signals, purpose) => ({
|
|
2583
|
+
type: "budget.confidence",
|
|
2584
|
+
score,
|
|
2585
|
+
signals,
|
|
2586
|
+
purpose,
|
|
2587
|
+
at: Date.now()
|
|
2588
|
+
});
|
|
2589
|
+
var makeBudgetWarningEvent = (totalTokens, tokenBudget) => ({
|
|
2590
|
+
type: "budget.warning",
|
|
2591
|
+
totalTokens,
|
|
2592
|
+
tokenBudget,
|
|
2593
|
+
at: Date.now()
|
|
2594
|
+
});
|
|
2595
|
+
var makeBudgetExceededEvent = (totalTokens, tokenBudget, overshootFraction, hardCap) => ({
|
|
2596
|
+
type: "budget.exceeded",
|
|
2597
|
+
totalTokens,
|
|
2598
|
+
tokenBudget,
|
|
2599
|
+
overshootFraction,
|
|
2600
|
+
hardCap,
|
|
2601
|
+
at: Date.now()
|
|
2602
|
+
});
|
|
2603
|
+
|
|
2604
|
+
// src/agent/core/llmBudget/persistence.ts
|
|
2605
|
+
var isValidRecord = (r) => {
|
|
2606
|
+
if (r === null || typeof r !== "object") return false;
|
|
2607
|
+
const rec = r;
|
|
2608
|
+
return typeof rec.goalId === "string" && typeof rec.totalTokens === "number" && typeof rec.callCount === "number" && (rec.tier === "small" || rec.tier === "large") && typeof rec.confidence === "number" && typeof rec.timestamp === "number";
|
|
2609
|
+
};
|
|
2610
|
+
var parseLearningStore = (json) => {
|
|
2611
|
+
try {
|
|
2612
|
+
const parsed = JSON.parse(json);
|
|
2613
|
+
if (parsed === null || typeof parsed !== "object") {
|
|
2614
|
+
return { records: [] };
|
|
2615
|
+
}
|
|
2616
|
+
if (!Array.isArray(parsed.records)) {
|
|
2617
|
+
return { records: [] };
|
|
2618
|
+
}
|
|
2619
|
+
const validRecords = parsed.records.filter(isValidRecord);
|
|
2620
|
+
return { records: validRecords };
|
|
2621
|
+
} catch (e7) {
|
|
2622
|
+
return { records: [] };
|
|
2623
|
+
}
|
|
2624
|
+
};
|
|
2625
|
+
var appendRunRecord = (store, record, maxRecords = 100) => {
|
|
2626
|
+
const updated = [...store.records, record];
|
|
2627
|
+
if (updated.length > maxRecords) {
|
|
2628
|
+
return { records: updated.slice(updated.length - maxRecords) };
|
|
2629
|
+
}
|
|
2630
|
+
return { records: updated };
|
|
2631
|
+
};
|
|
2632
|
+
var serializeLearningStore = (store) => JSON.stringify(store, null, 2);
|
|
2633
|
+
|
|
1824
2634
|
// src/agent/core/runAgent.ts
|
|
2635
|
+
var _promises = require('fs/promises');
|
|
2636
|
+
var _path = require('path');
|
|
1825
2637
|
var executeAction = (action, state, scope) => _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
|
|
1826
2638
|
nowMillis(),
|
|
1827
2639
|
(startedAt) => _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
|
|
@@ -1885,45 +2697,197 @@ var recordObservation = (next, observation) => _chunkMVGUEJ5Zcjs.asyncFlatMap.ca
|
|
|
1885
2697
|
];
|
|
1886
2698
|
return emitAgentEvents(events);
|
|
1887
2699
|
});
|
|
1888
|
-
var
|
|
2700
|
+
var buildBudgetExhaustedSummary = (state) => {
|
|
2701
|
+
const observations = state.observations;
|
|
2702
|
+
const fileReads = observations.filter((o) => o.type === "fs.fileRead").length;
|
|
2703
|
+
const llmCalls = observations.filter((o) => o.type === "llm.response").length;
|
|
2704
|
+
if (state.phase === "planning") {
|
|
2705
|
+
const hasPlan = observations.some((o) => o.type === "llm.response");
|
|
2706
|
+
if (!hasPlan) {
|
|
2707
|
+
return "Budget exhausted before planning could complete. No plan was generated within the token budget.";
|
|
2708
|
+
}
|
|
2709
|
+
}
|
|
2710
|
+
if (state.phase === "validating") {
|
|
2711
|
+
return `Budget exhausted during validation. Completed ${state.steps} steps (${fileReads} file reads, ${llmCalls} LLM calls). In-progress non-LLM validation commands were allowed to complete.`;
|
|
2712
|
+
}
|
|
2713
|
+
return `Budget exhausted. Completed ${state.steps} steps (${fileReads} file reads, ${llmCalls} LLM calls) before reaching the token budget hard cap.`;
|
|
2714
|
+
};
|
|
2715
|
+
var extractReadFiles = (state) => state.observations.filter((o) => o.type === "fs.fileRead").map((o) => o.path);
|
|
2716
|
+
var LEARNING_STORE_PATH = ".brass/llm-budget.json";
|
|
2717
|
+
var persistLearningRecord = (state, budgetState) => _chunkMVGUEJ5Zcjs.asyncFold.call(void 0,
|
|
2718
|
+
_chunkMVGUEJ5Zcjs.asyncInterruptible.call(void 0, (_env, cb) => {
|
|
2719
|
+
const filePath = `${state.goal.cwd}/${LEARNING_STORE_PATH}`;
|
|
2720
|
+
const run = async () => {
|
|
2721
|
+
const lastCall = budgetState.calls[budgetState.calls.length - 1];
|
|
2722
|
+
const tier = _nullishCoalesce(_optionalChain([lastCall, 'optionalAccess', _131 => _131.tier]), () => ( "small"));
|
|
2723
|
+
const confidence = budgetState.callCount > 0 ? budgetState.calls.reduce((sum, c) => sum + c.confidence, 0) / budgetState.callCount : 0;
|
|
2724
|
+
const record = {
|
|
2725
|
+
goalId: state.goal.id,
|
|
2726
|
+
totalTokens: budgetState.totalTokens,
|
|
2727
|
+
callCount: budgetState.callCount,
|
|
2728
|
+
tier,
|
|
2729
|
+
confidence,
|
|
2730
|
+
timestamp: Date.now()
|
|
2731
|
+
};
|
|
2732
|
+
let existingJson = "";
|
|
2733
|
+
try {
|
|
2734
|
+
existingJson = await _promises.readFile.call(void 0, filePath, "utf8");
|
|
2735
|
+
} catch (e8) {
|
|
2736
|
+
}
|
|
2737
|
+
const store = parseLearningStore(existingJson);
|
|
2738
|
+
const updated = appendRunRecord(store, record);
|
|
2739
|
+
const serialized = serializeLearningStore(updated);
|
|
2740
|
+
await _promises.mkdir.call(void 0, _path.dirname.call(void 0, filePath), { recursive: true });
|
|
2741
|
+
await _promises.writeFile.call(void 0, filePath, serialized, "utf8");
|
|
2742
|
+
};
|
|
2743
|
+
run().then(
|
|
2744
|
+
() => cb({ _tag: "Success", value: void 0 }),
|
|
2745
|
+
(err) => cb({ _tag: "Failure", cause: { _tag: "Fail", error: { _tag: "FsError", operation: "persistLearningStore", cause: err } } })
|
|
2746
|
+
);
|
|
2747
|
+
}),
|
|
2748
|
+
// On failure: swallow the error silently (Requirement 7.4)
|
|
2749
|
+
() => _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, void 0),
|
|
2750
|
+
// On success: pass through
|
|
2751
|
+
() => _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, void 0)
|
|
2752
|
+
);
|
|
2753
|
+
var executeBudgetGatedLLMCall = (action, state, budgetState, budgetConfig, scope) => {
|
|
2754
|
+
if (!budgetAllowsCall(budgetState, budgetConfig)) {
|
|
2755
|
+
const hardCap = budgetConfig.tokenBudget * (1 + budgetConfig.overshootFraction);
|
|
2756
|
+
const exceededEvent = makeBudgetExceededEvent(
|
|
2757
|
+
budgetState.totalTokens,
|
|
2758
|
+
budgetConfig.tokenBudget,
|
|
2759
|
+
budgetConfig.overshootFraction,
|
|
2760
|
+
hardCap
|
|
2761
|
+
);
|
|
2762
|
+
return _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0, emitAgentEvent(exceededEvent), () => {
|
|
2763
|
+
const finishObservation = {
|
|
2764
|
+
type: "agent.done",
|
|
2765
|
+
summary: buildBudgetExhaustedSummary(state)
|
|
2766
|
+
};
|
|
2767
|
+
return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, { observation: finishObservation, budgetState });
|
|
2768
|
+
});
|
|
2769
|
+
}
|
|
2770
|
+
const tier = routeModel(state, budgetState);
|
|
2771
|
+
const signals = extractComplexitySignals(state);
|
|
2772
|
+
const resolvedProvider = _optionalChain([budgetConfig, 'access', _132 => _132.modelTiers, 'optionalAccess', _133 => _133[tier], 'optionalAccess', _134 => _134.provider]);
|
|
2773
|
+
const routedEvent = makeBudgetRoutedEvent(tier, signals, resolvedProvider);
|
|
2774
|
+
return _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
|
|
2775
|
+
emitAgentEvent(routedEvent),
|
|
2776
|
+
() => (
|
|
2777
|
+
// Execute the LLM call through the normal action execution path
|
|
2778
|
+
// We use the LLM service directly to capture the full LLMResponse with usage
|
|
2779
|
+
_chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0, _chunkMVGUEJ5Zcjs.asyncSync.call(void 0, (env) => env.llm), (llm) => {
|
|
2780
|
+
if (!llm) {
|
|
2781
|
+
return _chunkMVGUEJ5Zcjs.asyncFail.call(void 0, {
|
|
2782
|
+
_tag: "LLMError",
|
|
2783
|
+
cause: "llm_unavailable: no LLM provider is configured"
|
|
2784
|
+
});
|
|
2785
|
+
}
|
|
2786
|
+
return _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
|
|
2787
|
+
llm.complete({ purpose: action.purpose, prompt: action.prompt }),
|
|
2788
|
+
(response) => {
|
|
2789
|
+
const usage = _nullishCoalesce(response.usage, () => ( estimateTokens(
|
|
2790
|
+
action.prompt.length,
|
|
2791
|
+
response.content.length
|
|
2792
|
+
)));
|
|
2793
|
+
const estimated = response.usage === void 0;
|
|
2794
|
+
const readFiles = extractReadFiles(state);
|
|
2795
|
+
const { score: confidence, signals: confidenceSignals } = estimateConfidence(
|
|
2796
|
+
response.content,
|
|
2797
|
+
state.goal.text,
|
|
2798
|
+
readFiles
|
|
2799
|
+
);
|
|
2800
|
+
const newBudgetState = updateBudgetState(budgetState, usage, tier, confidence, estimated);
|
|
2801
|
+
const remaining = Math.max(0, budgetConfig.tokenBudget - newBudgetState.totalTokens);
|
|
2802
|
+
const usageEvent = makeBudgetUsageEvent(
|
|
2803
|
+
usage,
|
|
2804
|
+
{ totalTokens: newBudgetState.totalTokens, callCount: newBudgetState.callCount },
|
|
2805
|
+
tier,
|
|
2806
|
+
remaining
|
|
2807
|
+
);
|
|
2808
|
+
const confidenceEvent = makeBudgetConfidenceEvent(confidence, confidenceSignals, action.purpose);
|
|
2809
|
+
const events = [usageEvent, confidenceEvent];
|
|
2810
|
+
if (newBudgetState.totalTokens > budgetConfig.tokenBudget) {
|
|
2811
|
+
events.push(makeBudgetWarningEvent(newBudgetState.totalTokens, budgetConfig.tokenBudget));
|
|
2812
|
+
}
|
|
2813
|
+
return _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0, emitAgentEvents(events), () => {
|
|
2814
|
+
const observation = {
|
|
2815
|
+
type: "llm.response",
|
|
2816
|
+
purpose: action.purpose,
|
|
2817
|
+
content: response.content
|
|
2818
|
+
};
|
|
2819
|
+
return _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, { observation, budgetState: newBudgetState });
|
|
2820
|
+
});
|
|
2821
|
+
}
|
|
2822
|
+
);
|
|
2823
|
+
})
|
|
2824
|
+
)
|
|
2825
|
+
);
|
|
2826
|
+
};
|
|
2827
|
+
var runLoop = (state, budgetState, budgetConfig, scope, runStartedAt) => {
|
|
1889
2828
|
if (isTerminal(state)) {
|
|
2829
|
+
const persistEffect = budgetConfig !== void 0 && budgetState !== void 0 ? persistLearningRecord(state, budgetState) : _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, void 0);
|
|
1890
2830
|
return _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
|
|
1891
|
-
|
|
1892
|
-
(
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
2831
|
+
persistEffect,
|
|
2832
|
+
() => _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
|
|
2833
|
+
nowMillis(),
|
|
2834
|
+
(at) => _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
|
|
2835
|
+
emitAgentEvent({
|
|
2836
|
+
type: "agent.run.completed",
|
|
2837
|
+
goal: state.goal,
|
|
2838
|
+
status: runStatusFor(state.phase),
|
|
2839
|
+
phase: state.phase,
|
|
2840
|
+
steps: state.steps,
|
|
2841
|
+
durationMs: at - runStartedAt,
|
|
2842
|
+
at
|
|
2843
|
+
}),
|
|
2844
|
+
() => _chunkMVGUEJ5Zcjs.asyncSucceed.call(void 0, state)
|
|
2845
|
+
)
|
|
1903
2846
|
)
|
|
1904
2847
|
);
|
|
1905
2848
|
}
|
|
1906
|
-
return _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
|
|
1907
|
-
|
|
1908
|
-
|
|
2849
|
+
return _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0, decideNextAction(state), (action) => {
|
|
2850
|
+
if (action.type === "llm.complete" && budgetConfig !== void 0 && budgetState !== void 0) {
|
|
2851
|
+
return _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
|
|
2852
|
+
executeBudgetGatedLLMCall(action, state, budgetState, budgetConfig, scope),
|
|
2853
|
+
(result) => {
|
|
2854
|
+
const next = reduceAgentState(state, result.observation);
|
|
2855
|
+
return _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
|
|
2856
|
+
recordObservation(next, result.observation),
|
|
2857
|
+
() => runLoop(next, result.budgetState, budgetConfig, scope, runStartedAt)
|
|
2858
|
+
);
|
|
2859
|
+
}
|
|
2860
|
+
);
|
|
2861
|
+
}
|
|
2862
|
+
return _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0, executeAction(action, state, scope), (observation) => {
|
|
1909
2863
|
const next = reduceAgentState(state, observation);
|
|
1910
2864
|
return _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
|
|
1911
2865
|
recordObservation(next, observation),
|
|
1912
|
-
() => runLoop(next, scope, runStartedAt)
|
|
2866
|
+
() => runLoop(next, budgetState, budgetConfig, scope, runStartedAt)
|
|
1913
2867
|
);
|
|
1914
|
-
})
|
|
1915
|
-
);
|
|
2868
|
+
});
|
|
2869
|
+
});
|
|
1916
2870
|
};
|
|
1917
|
-
var runAgent = (runtime, goal) =>
|
|
1918
|
-
|
|
1919
|
-
(
|
|
1920
|
-
|
|
1921
|
-
(
|
|
1922
|
-
|
|
1923
|
-
|
|
2871
|
+
var runAgent = (runtime, goal, configBudget) => {
|
|
2872
|
+
const budgetConfig = resolveBudgetConfig(goal.budget, configBudget);
|
|
2873
|
+
if (budgetConfig !== void 0) {
|
|
2874
|
+
const validationError = validateBudgetConfig(budgetConfig);
|
|
2875
|
+
if (validationError !== void 0) {
|
|
2876
|
+
return _chunkMVGUEJ5Zcjs.asyncFail.call(void 0, { _tag: "AgentLoopError", message: validationError });
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
const budgetState = budgetConfig !== void 0 ? initBudgetState() : void 0;
|
|
2880
|
+
return _chunkJKHBEWQAcjs.withScopeAsync.call(void 0,
|
|
2881
|
+
runtime,
|
|
2882
|
+
(scope) => _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
|
|
2883
|
+
nowMillis(),
|
|
2884
|
+
(startedAt) => _chunkMVGUEJ5Zcjs.asyncFlatMap.call(void 0,
|
|
2885
|
+
emitAgentEvent({ type: "agent.run.started", goal, at: startedAt }),
|
|
2886
|
+
() => runLoop(initialAgentState(goal), budgetState, budgetConfig, scope, startedAt)
|
|
2887
|
+
)
|
|
1924
2888
|
)
|
|
1925
|
-
)
|
|
1926
|
-
|
|
2889
|
+
);
|
|
2890
|
+
};
|
|
1927
2891
|
|
|
1928
2892
|
// src/agent/core/config.ts
|
|
1929
2893
|
var isAgentConfigMode = (value) => value === "read-only" || value === "propose" || value === "write" || value === "autonomous";
|
|
@@ -1946,6 +2910,243 @@ var goalForAgentPreset = (preset) => {
|
|
|
1946
2910
|
}
|
|
1947
2911
|
};
|
|
1948
2912
|
|
|
2913
|
+
// src/agent/core/hostProfile.ts
|
|
2914
|
+
var deepFreeze = (obj) => {
|
|
2915
|
+
Object.freeze(obj);
|
|
2916
|
+
for (const name of Object.getOwnPropertyNames(obj)) {
|
|
2917
|
+
const value = obj[name];
|
|
2918
|
+
if (value !== null && typeof value === "object" && !Object.isFrozen(value)) {
|
|
2919
|
+
deepFreeze(value);
|
|
2920
|
+
}
|
|
2921
|
+
}
|
|
2922
|
+
return obj;
|
|
2923
|
+
};
|
|
2924
|
+
|
|
2925
|
+
// src/agent/core/hostSignals.ts
|
|
2926
|
+
var MAX_ENV_KEYS = 256;
|
|
2927
|
+
var collectHostSignals = (input) => {
|
|
2928
|
+
const signals = [];
|
|
2929
|
+
try {
|
|
2930
|
+
for (const arg of input.argv) {
|
|
2931
|
+
signals.push({ source: "argv", value: arg });
|
|
2932
|
+
}
|
|
2933
|
+
} catch (e9) {
|
|
2934
|
+
}
|
|
2935
|
+
try {
|
|
2936
|
+
const keys = Object.keys(input.env).sort();
|
|
2937
|
+
const limit = Math.min(keys.length, MAX_ENV_KEYS);
|
|
2938
|
+
for (let i = 0; i < limit; i++) {
|
|
2939
|
+
signals.push({ source: "env-key", value: keys[i] });
|
|
2940
|
+
}
|
|
2941
|
+
} catch (e10) {
|
|
2942
|
+
}
|
|
2943
|
+
try {
|
|
2944
|
+
signals.push({
|
|
2945
|
+
source: "stdio",
|
|
2946
|
+
value: input.stdoutIsTTY ? "stdout:tty" : "stdout:pipe"
|
|
2947
|
+
});
|
|
2948
|
+
signals.push({
|
|
2949
|
+
source: "stdio",
|
|
2950
|
+
value: input.stdinIsTTY ? "stdin:tty" : "stdin:pipe"
|
|
2951
|
+
});
|
|
2952
|
+
if (input.ttyColumns !== void 0) {
|
|
2953
|
+
signals.push({ source: "stdio", value: `columns:${input.ttyColumns}` });
|
|
2954
|
+
}
|
|
2955
|
+
} catch (e11) {
|
|
2956
|
+
}
|
|
2957
|
+
try {
|
|
2958
|
+
if (input.parentProcessName !== void 0) {
|
|
2959
|
+
signals.push({ source: "parent-process", value: input.parentProcessName });
|
|
2960
|
+
}
|
|
2961
|
+
} catch (e12) {
|
|
2962
|
+
}
|
|
2963
|
+
try {
|
|
2964
|
+
for (const marker of input.workspaceMarkers) {
|
|
2965
|
+
signals.push({ source: "workspace-marker", value: marker });
|
|
2966
|
+
}
|
|
2967
|
+
} catch (e13) {
|
|
2968
|
+
}
|
|
2969
|
+
try {
|
|
2970
|
+
if (input.stdinFirstLine !== void 0 && !input.stdinIsTTY) {
|
|
2971
|
+
signals.push({ source: "protocol-handshake", value: input.stdinFirstLine });
|
|
2972
|
+
}
|
|
2973
|
+
} catch (e14) {
|
|
2974
|
+
}
|
|
2975
|
+
try {
|
|
2976
|
+
for (const configPath of input.configPaths) {
|
|
2977
|
+
signals.push({ source: "config", value: configPath });
|
|
2978
|
+
}
|
|
2979
|
+
} catch (e15) {
|
|
2980
|
+
}
|
|
2981
|
+
return deepFreeze(signals);
|
|
2982
|
+
};
|
|
2983
|
+
|
|
2984
|
+
// src/agent/core/hostInference.ts
|
|
2985
|
+
var CI_INDICATORS = [
|
|
2986
|
+
"CI",
|
|
2987
|
+
"GITHUB_ACTIONS",
|
|
2988
|
+
"JENKINS_URL",
|
|
2989
|
+
"CIRCLECI",
|
|
2990
|
+
"TRAVIS",
|
|
2991
|
+
"GITLAB_CI",
|
|
2992
|
+
"BUILDKITE",
|
|
2993
|
+
"TF_BUILD"
|
|
2994
|
+
];
|
|
2995
|
+
var inferTransport = (signals) => {
|
|
2996
|
+
const hasProtocolMcp = signals.some(
|
|
2997
|
+
(s) => s.source === "protocol-handshake" && s.value.toLowerCase().includes("mcp")
|
|
2998
|
+
);
|
|
2999
|
+
if (hasProtocolMcp) return "mcp";
|
|
3000
|
+
const extensionMarkers = [".vscode", ".cursor", ".kiro"];
|
|
3001
|
+
const hasExtensionMarker = signals.some(
|
|
3002
|
+
(s) => s.source === "workspace-marker" && extensionMarkers.some((m) => s.value.toLowerCase().includes(m))
|
|
3003
|
+
);
|
|
3004
|
+
const hasExtensionConfig = signals.some(
|
|
3005
|
+
(s) => s.source === "config" && extensionMarkers.some((m) => s.value.toLowerCase().includes(m))
|
|
3006
|
+
);
|
|
3007
|
+
if (hasExtensionMarker || hasExtensionConfig) return "extension";
|
|
3008
|
+
const hasCiEnv = signals.some(
|
|
3009
|
+
(s) => s.source === "env-key" && CI_INDICATORS.some((ci) => s.value === ci)
|
|
3010
|
+
);
|
|
3011
|
+
if (hasCiEnv) return "ci";
|
|
3012
|
+
const stdoutIsTty = signals.some(
|
|
3013
|
+
(s) => s.source === "stdio" && s.value === "stdout:tty"
|
|
3014
|
+
);
|
|
3015
|
+
if (stdoutIsTty) return "terminal";
|
|
3016
|
+
const stdoutIsPipe = signals.some(
|
|
3017
|
+
(s) => s.source === "stdio" && s.value === "stdout:pipe"
|
|
3018
|
+
);
|
|
3019
|
+
if (stdoutIsPipe) return "stdio";
|
|
3020
|
+
return "unknown";
|
|
3021
|
+
};
|
|
3022
|
+
var inferCapabilities = (signals, transport) => {
|
|
3023
|
+
const hasOwnLLM = signals.some(
|
|
3024
|
+
(s) => s.source === "env-key" && (s.value.toUpperCase().includes("LLM") || s.value.toUpperCase().includes("AI_API")) || s.source === "protocol-handshake" && s.value.toLowerCase().includes("llm")
|
|
3025
|
+
);
|
|
3026
|
+
const wantsJson = transport === "stdio" || transport === "mcp";
|
|
3027
|
+
const supportsStreamingEvents = transport === "terminal" || transport === "mcp" || transport === "extension";
|
|
3028
|
+
const supportsMcp = transport === "mcp";
|
|
3029
|
+
const stdinIsTty = signals.some(
|
|
3030
|
+
(s) => s.source === "stdio" && s.value === "stdin:tty"
|
|
3031
|
+
);
|
|
3032
|
+
const canAskApproval = stdinIsTty || transport === "extension" || transport === "mcp";
|
|
3033
|
+
const ttyColumnsSignal = signals.find(
|
|
3034
|
+
(s) => s.source === "stdio" && s.value.startsWith("columns:")
|
|
3035
|
+
);
|
|
3036
|
+
const ttyColumns = ttyColumnsSignal ? parseInt(ttyColumnsSignal.value.slice("columns:".length), 10) : void 0;
|
|
3037
|
+
const stdoutIsTty = signals.some(
|
|
3038
|
+
(s) => s.source === "stdio" && s.value === "stdout:tty"
|
|
3039
|
+
);
|
|
3040
|
+
const canRenderDiff = stdoutIsTty && ttyColumns !== void 0 && ttyColumns >= 80 || transport === "extension";
|
|
3041
|
+
const canApplyPatch = transport === "extension" || transport === "mcp";
|
|
3042
|
+
const interactiveTty = stdoutIsTty;
|
|
3043
|
+
return {
|
|
3044
|
+
hasOwnLLM,
|
|
3045
|
+
wantsJson,
|
|
3046
|
+
supportsStreamingEvents,
|
|
3047
|
+
supportsMcp,
|
|
3048
|
+
canAskApproval,
|
|
3049
|
+
canRenderDiff,
|
|
3050
|
+
canApplyPatch,
|
|
3051
|
+
interactiveTty
|
|
3052
|
+
};
|
|
3053
|
+
};
|
|
3054
|
+
var inferConstraints = (capabilities, transport) => {
|
|
3055
|
+
const readOnlyByDefault = transport === "ci";
|
|
3056
|
+
const patchPreviewRequired = capabilities.canRenderDiff === true && capabilities.canApplyPatch === false;
|
|
3057
|
+
const requireNoNetwork = false;
|
|
3058
|
+
return {
|
|
3059
|
+
readOnlyByDefault,
|
|
3060
|
+
patchPreviewRequired,
|
|
3061
|
+
requireNoNetwork
|
|
3062
|
+
};
|
|
3063
|
+
};
|
|
3064
|
+
var IDENTITY_PATTERNS = [
|
|
3065
|
+
{
|
|
3066
|
+
name: "cursor",
|
|
3067
|
+
match: (signals) => {
|
|
3068
|
+
if (signals.some((s) => s.source === "workspace-marker" && s.value.toLowerCase().includes(".cursor"))) {
|
|
3069
|
+
return 0.8;
|
|
3070
|
+
}
|
|
3071
|
+
return 0;
|
|
3072
|
+
}
|
|
3073
|
+
},
|
|
3074
|
+
{
|
|
3075
|
+
name: "vscode",
|
|
3076
|
+
match: (signals) => {
|
|
3077
|
+
if (signals.some((s) => s.source === "workspace-marker" && s.value.toLowerCase().includes(".vscode"))) {
|
|
3078
|
+
return 0.8;
|
|
3079
|
+
}
|
|
3080
|
+
return 0;
|
|
3081
|
+
}
|
|
3082
|
+
},
|
|
3083
|
+
{
|
|
3084
|
+
name: "kiro",
|
|
3085
|
+
match: (signals) => {
|
|
3086
|
+
if (signals.some((s) => s.source === "workspace-marker" && s.value.toLowerCase().includes(".kiro"))) {
|
|
3087
|
+
return 0.8;
|
|
3088
|
+
}
|
|
3089
|
+
if (signals.some((s) => s.source === "env-key" && s.value.startsWith("KIRO_"))) {
|
|
3090
|
+
return 0.7;
|
|
3091
|
+
}
|
|
3092
|
+
return 0;
|
|
3093
|
+
}
|
|
3094
|
+
},
|
|
3095
|
+
{
|
|
3096
|
+
name: "codex",
|
|
3097
|
+
match: (signals) => {
|
|
3098
|
+
if (signals.some((s) => s.source === "parent-process" && s.value.toLowerCase().includes("codex"))) {
|
|
3099
|
+
return 0.9;
|
|
3100
|
+
}
|
|
3101
|
+
if (signals.some((s) => s.source === "env-key" && s.value.startsWith("CODEX_"))) {
|
|
3102
|
+
return 0.7;
|
|
3103
|
+
}
|
|
3104
|
+
return 0;
|
|
3105
|
+
}
|
|
3106
|
+
},
|
|
3107
|
+
{
|
|
3108
|
+
name: "claude-code",
|
|
3109
|
+
match: (signals) => {
|
|
3110
|
+
if (signals.some((s) => s.source === "parent-process" && s.value.toLowerCase().includes("claude"))) {
|
|
3111
|
+
return 0.9;
|
|
3112
|
+
}
|
|
3113
|
+
return 0;
|
|
3114
|
+
}
|
|
3115
|
+
}
|
|
3116
|
+
];
|
|
3117
|
+
var inferOptionalIdentity = (signals) => {
|
|
3118
|
+
let bestName;
|
|
3119
|
+
let bestConfidence = 0;
|
|
3120
|
+
for (const pattern of IDENTITY_PATTERNS) {
|
|
3121
|
+
const confidence = pattern.match(signals);
|
|
3122
|
+
if (confidence > bestConfidence) {
|
|
3123
|
+
bestConfidence = confidence;
|
|
3124
|
+
bestName = pattern.name;
|
|
3125
|
+
}
|
|
3126
|
+
}
|
|
3127
|
+
if (bestName === void 0 || bestConfidence <= 0) {
|
|
3128
|
+
return void 0;
|
|
3129
|
+
}
|
|
3130
|
+
return {
|
|
3131
|
+
name: bestName,
|
|
3132
|
+
confidence: Math.round(bestConfidence * 100) / 100
|
|
3133
|
+
};
|
|
3134
|
+
};
|
|
3135
|
+
var buildHostProfile = (input) => {
|
|
3136
|
+
const signals = collectHostSignals(input);
|
|
3137
|
+
const transport = inferTransport(signals);
|
|
3138
|
+
const capabilities = inferCapabilities(signals, transport);
|
|
3139
|
+
const constraints = inferConstraints(capabilities, transport);
|
|
3140
|
+
const identity = inferOptionalIdentity(signals);
|
|
3141
|
+
return deepFreeze({
|
|
3142
|
+
transport,
|
|
3143
|
+
capabilities,
|
|
3144
|
+
constraints,
|
|
3145
|
+
identity,
|
|
3146
|
+
evidence: signals
|
|
3147
|
+
});
|
|
3148
|
+
};
|
|
3149
|
+
|
|
1949
3150
|
// src/agent/tools/permissions.ts
|
|
1950
3151
|
var DEFAULT_SAFE_SHELL_PATTERNS = [
|
|
1951
3152
|
"npm test",
|
|
@@ -2022,14 +3223,14 @@ var matchesPattern = (command, pattern) => {
|
|
|
2022
3223
|
const re = new RegExp(`^${normalizedPattern.split("*").map(escapeRegExp).join(".*")}$`);
|
|
2023
3224
|
return re.test(normalizedCommand);
|
|
2024
3225
|
};
|
|
2025
|
-
var matchAny = (command, patterns) => Boolean(_optionalChain([patterns, 'optionalAccess',
|
|
3226
|
+
var matchAny = (command, patterns) => Boolean(_optionalChain([patterns, 'optionalAccess', _135 => _135.some, 'call', _136 => _136((pattern) => matchesPattern(command, pattern))]));
|
|
2026
3227
|
var allow = () => ({ type: "allow" });
|
|
2027
3228
|
var deny = (reason) => ({ type: "deny", reason });
|
|
2028
3229
|
var ask = (reason, risk, defaultAnswer = "reject") => ({ type: "ask", reason, risk, defaultAnswer });
|
|
2029
3230
|
var describeCommand = (action) => action.type === "shell.exec" ? action.command.join(" ") : action.type;
|
|
2030
3231
|
var shellAskRulePattern = (rule) => typeof rule === "string" ? rule : rule.pattern;
|
|
2031
3232
|
var shellAskDecision = (command, rules) => {
|
|
2032
|
-
const rule = _optionalChain([rules, 'optionalAccess',
|
|
3233
|
+
const rule = _optionalChain([rules, 'optionalAccess', _137 => _137.find, 'call', _138 => _138((candidate) => matchesPattern(command, shellAskRulePattern(candidate)))]);
|
|
2033
3234
|
if (!rule) return void 0;
|
|
2034
3235
|
if (typeof rule === "string") {
|
|
2035
3236
|
return ask(`Run command: ${shellCommandText(command)}`, "high", "reject");
|
|
@@ -2041,12 +3242,12 @@ var shellAskDecision = (command, rules) => {
|
|
|
2041
3242
|
);
|
|
2042
3243
|
};
|
|
2043
3244
|
var configuredShellAllowPatterns = (config) => [
|
|
2044
|
-
..._optionalChain([config, 'optionalAccess',
|
|
2045
|
-
..._nullishCoalesce(_optionalChain([config, 'optionalAccess',
|
|
3245
|
+
..._optionalChain([config, 'optionalAccess', _139 => _139.inheritDefaults]) === false ? [] : DEFAULT_SAFE_SHELL_PATTERNS,
|
|
3246
|
+
..._nullishCoalesce(_optionalChain([config, 'optionalAccess', _140 => _140.allow]), () => ( []))
|
|
2046
3247
|
];
|
|
2047
3248
|
var shellDecisionFromConfig = (command, config) => {
|
|
2048
|
-
if (matchAny(command, _optionalChain([config, 'optionalAccess',
|
|
2049
|
-
const askDecision = shellAskDecision(command, _optionalChain([config, 'optionalAccess',
|
|
3249
|
+
if (matchAny(command, _optionalChain([config, 'optionalAccess', _141 => _141.deny]))) return deny(`Command denied by policy: ${shellCommandText(command)}`);
|
|
3250
|
+
const askDecision = shellAskDecision(command, _optionalChain([config, 'optionalAccess', _142 => _142.ask]));
|
|
2050
3251
|
if (askDecision) return askDecision;
|
|
2051
3252
|
if (matchAny(command, configuredShellAllowPatterns(config))) return allow();
|
|
2052
3253
|
return void 0;
|
|
@@ -2124,7 +3325,7 @@ var makeAutoDenyApprovals = (reason = "Approval denied by non-interactive policy
|
|
|
2124
3325
|
// src/agent/node/nodeShell.ts
|
|
2125
3326
|
var dynamicImport = new Function("specifier", "return import(specifier)");
|
|
2126
3327
|
var chunkToString = (chunk) => {
|
|
2127
|
-
const maybeToString = _optionalChain([chunk, 'optionalAccess',
|
|
3328
|
+
const maybeToString = _optionalChain([chunk, 'optionalAccess', _143 => _143.toString]);
|
|
2128
3329
|
return typeof maybeToString === "function" ? maybeToString.call(chunk, "utf8") : String(chunk);
|
|
2129
3330
|
};
|
|
2130
3331
|
var NodeShell = {
|
|
@@ -2154,10 +3355,10 @@ var NodeShell = {
|
|
|
2154
3355
|
shell: false,
|
|
2155
3356
|
stdio: ["pipe", "pipe", "pipe"]
|
|
2156
3357
|
});
|
|
2157
|
-
_optionalChain([child, 'access',
|
|
3358
|
+
_optionalChain([child, 'access', _144 => _144.stdout, 'optionalAccess', _145 => _145.on, 'call', _146 => _146("data", (chunk) => {
|
|
2158
3359
|
stdout += chunkToString(chunk);
|
|
2159
3360
|
})]);
|
|
2160
|
-
_optionalChain([child, 'access',
|
|
3361
|
+
_optionalChain([child, 'access', _147 => _147.stderr, 'optionalAccess', _148 => _148.on, 'call', _149 => _149("data", (chunk) => {
|
|
2161
3362
|
stderr += chunkToString(chunk);
|
|
2162
3363
|
})]);
|
|
2163
3364
|
child.on("error", (cause) => {
|
|
@@ -2186,9 +3387,9 @@ var NodeShell = {
|
|
|
2186
3387
|
);
|
|
2187
3388
|
});
|
|
2188
3389
|
if (options.stdin !== void 0) {
|
|
2189
|
-
_optionalChain([child, 'access',
|
|
3390
|
+
_optionalChain([child, 'access', _150 => _150.stdin, 'optionalAccess', _151 => _151.end, 'call', _152 => _152(options.stdin)]);
|
|
2190
3391
|
} else {
|
|
2191
|
-
_optionalChain([child, 'access',
|
|
3392
|
+
_optionalChain([child, 'access', _153 => _153.stdin, 'optionalAccess', _154 => _154.end, 'call', _155 => _155()]);
|
|
2192
3393
|
}
|
|
2193
3394
|
}).catch((cause) => {
|
|
2194
3395
|
if (done) return;
|
|
@@ -2207,7 +3408,7 @@ var NodeShell = {
|
|
|
2207
3408
|
return () => {
|
|
2208
3409
|
if (done) return;
|
|
2209
3410
|
done = true;
|
|
2210
|
-
_optionalChain([child, 'optionalAccess',
|
|
3411
|
+
_optionalChain([child, 'optionalAccess', _156 => _156.kill, 'optionalCall', _157 => _157("SIGTERM")]);
|
|
2211
3412
|
};
|
|
2212
3413
|
})
|
|
2213
3414
|
};
|
|
@@ -2221,8 +3422,8 @@ var parseRipgrep = (stdout) => stdout.split("\n").filter(Boolean).map((line) =>
|
|
|
2221
3422
|
var makeNodeFileSystem = (shell) => ({
|
|
2222
3423
|
readFile: (path) => _chunkJKHBEWQAcjs.fromPromiseAbortable.call(void 0,
|
|
2223
3424
|
async (signal) => {
|
|
2224
|
-
const { readFile } = await dynamicImport2("node:fs/promises");
|
|
2225
|
-
return
|
|
3425
|
+
const { readFile: readFile2 } = await dynamicImport2("node:fs/promises");
|
|
3426
|
+
return readFile2(path, { encoding: "utf8", signal });
|
|
2226
3427
|
},
|
|
2227
3428
|
(cause) => ({ _tag: "FsError", operation: "readFile", cause })
|
|
2228
3429
|
),
|
|
@@ -2234,7 +3435,7 @@ var makeNodeFileSystem = (shell) => ({
|
|
|
2234
3435
|
try {
|
|
2235
3436
|
await stat(path);
|
|
2236
3437
|
return true;
|
|
2237
|
-
} catch (
|
|
3438
|
+
} catch (e16) {
|
|
2238
3439
|
return false;
|
|
2239
3440
|
}
|
|
2240
3441
|
},
|
|
@@ -2251,7 +3452,7 @@ var makeNodeFileSystem = (shell) => ({
|
|
|
2251
3452
|
"never",
|
|
2252
3453
|
"--max-count",
|
|
2253
3454
|
"5",
|
|
2254
|
-
..._nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
3455
|
+
..._nullishCoalesce(_optionalChain([options, 'optionalAccess', _158 => _158.globs, 'optionalAccess', _159 => _159.flatMap, 'call', _160 => _160((glob) => ["--glob", glob])]), () => ( [])),
|
|
2255
3456
|
"--",
|
|
2256
3457
|
query,
|
|
2257
3458
|
"."
|
|
@@ -2556,13 +3757,16 @@ var validateAgentConfig = (config, sourcePath) => {
|
|
|
2556
3757
|
config.batch.goals.forEach((goal, index) => validateBatchGoal(goal, `config.batch.goals[${index}]`));
|
|
2557
3758
|
}
|
|
2558
3759
|
}
|
|
3760
|
+
if (config.budget !== void 0) {
|
|
3761
|
+
if (!isRecord3(config.budget)) throw new Error("config.budget must be an object.");
|
|
3762
|
+
}
|
|
2559
3763
|
return config;
|
|
2560
3764
|
};
|
|
2561
3765
|
var isFile = async (path) => {
|
|
2562
3766
|
const { stat } = await dynamicImport3("node:fs/promises");
|
|
2563
3767
|
try {
|
|
2564
3768
|
return (await stat(path)).isFile();
|
|
2565
|
-
} catch (
|
|
3769
|
+
} catch (e17) {
|
|
2566
3770
|
return false;
|
|
2567
3771
|
}
|
|
2568
3772
|
};
|
|
@@ -2580,8 +3784,8 @@ var findConfigPath = async (cwd) => {
|
|
|
2580
3784
|
}
|
|
2581
3785
|
};
|
|
2582
3786
|
var readConfigFile = async (path) => {
|
|
2583
|
-
const { readFile } = await dynamicImport3("node:fs/promises");
|
|
2584
|
-
const raw = String(await
|
|
3787
|
+
const { readFile: readFile2 } = await dynamicImport3("node:fs/promises");
|
|
3788
|
+
const raw = String(await readFile2(path, "utf8")).replace(/^\uFEFF/, "");
|
|
2585
3789
|
try {
|
|
2586
3790
|
return validateAgentConfig(JSON.parse(raw), path);
|
|
2587
3791
|
} catch (error) {
|
|
@@ -2605,7 +3809,7 @@ var loadNodeAgentConfig = async (options) => {
|
|
|
2605
3809
|
};
|
|
2606
3810
|
|
|
2607
3811
|
// src/agent/llm/openAICompatible.ts
|
|
2608
|
-
var extractText = (json) => _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_optionalChain([json, 'optionalAccess',
|
|
3812
|
+
var extractText = (json) => _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_optionalChain([json, 'optionalAccess', _161 => _161.choices, 'optionalAccess', _162 => _162[0], 'optionalAccess', _163 => _163.message, 'optionalAccess', _164 => _164.content]), () => ( _optionalChain([json, 'optionalAccess', _165 => _165.output_text]))), () => ( _optionalChain([json, 'optionalAccess', _166 => _166.content, 'optionalAccess', _167 => _167[0], 'optionalAccess', _168 => _168.text]))), () => ( JSON.stringify(json)));
|
|
2609
3813
|
var makeOpenAICompatibleLLM = (config) => ({
|
|
2610
3814
|
complete: (request) => _chunkJKHBEWQAcjs.fromPromiseAbortable.call(void 0,
|
|
2611
3815
|
async (signal) => {
|
|
@@ -2673,18 +3877,18 @@ var makeRequestBody = (request, config) => {
|
|
|
2673
3877
|
});
|
|
2674
3878
|
};
|
|
2675
3879
|
var extractGoogleText = (json) => {
|
|
2676
|
-
const text = _optionalChain([json, 'access',
|
|
3880
|
+
const text = _optionalChain([json, 'access', _169 => _169.candidates, 'optionalAccess', _170 => _170.flatMap, 'call', _171 => _171((candidate) => _nullishCoalesce(_optionalChain([candidate, 'access', _172 => _172.content, 'optionalAccess', _173 => _173.parts]), () => ( []))), 'access', _174 => _174.map, 'call', _175 => _175((part) => _nullishCoalesce(part.text, () => ( ""))), 'access', _176 => _176.filter, 'call', _177 => _177(Boolean), 'access', _178 => _178.join, 'call', _179 => _179("\n"), 'access', _180 => _180.trim, 'call', _181 => _181()]);
|
|
2677
3881
|
if (text) return text;
|
|
2678
|
-
const blockReason = _optionalChain([json, 'access',
|
|
3882
|
+
const blockReason = _optionalChain([json, 'access', _182 => _182.promptFeedback, 'optionalAccess', _183 => _183.blockReason]);
|
|
2679
3883
|
if (blockReason) {
|
|
2680
|
-
const message = _optionalChain([json, 'access',
|
|
3884
|
+
const message = _optionalChain([json, 'access', _184 => _184.promptFeedback, 'optionalAccess', _185 => _185.blockReasonMessage]);
|
|
2681
3885
|
throw new Error(`Google Gemini blocked the prompt: ${blockReason}${message ? ` - ${message}` : ""}`);
|
|
2682
3886
|
}
|
|
2683
|
-
const finishReason = _optionalChain([json, 'access',
|
|
3887
|
+
const finishReason = _optionalChain([json, 'access', _186 => _186.candidates, 'optionalAccess', _187 => _187[0], 'optionalAccess', _188 => _188.finishReason]);
|
|
2684
3888
|
if (finishReason) {
|
|
2685
3889
|
throw new Error(`Google Gemini returned no text. finishReason=${finishReason}`);
|
|
2686
3890
|
}
|
|
2687
|
-
if (_optionalChain([json, 'access',
|
|
3891
|
+
if (_optionalChain([json, 'access', _189 => _189.error, 'optionalAccess', _190 => _190.message])) {
|
|
2688
3892
|
throw new Error(`Google Gemini error: ${json.error.message}`);
|
|
2689
3893
|
}
|
|
2690
3894
|
return JSON.stringify(json);
|
|
@@ -2693,8 +3897,8 @@ var responseErrorMessage = async (res) => {
|
|
|
2693
3897
|
const raw = await res.text();
|
|
2694
3898
|
try {
|
|
2695
3899
|
const json = JSON.parse(raw);
|
|
2696
|
-
return _nullishCoalesce(_optionalChain([json, 'access',
|
|
2697
|
-
} catch (
|
|
3900
|
+
return _nullishCoalesce(_optionalChain([json, 'access', _191 => _191.error, 'optionalAccess', _192 => _192.message]), () => ( raw));
|
|
3901
|
+
} catch (e18) {
|
|
2698
3902
|
return raw;
|
|
2699
3903
|
}
|
|
2700
3904
|
};
|
|
@@ -2737,7 +3941,7 @@ var makeFakeLLM = (options = {}) => ({
|
|
|
2737
3941
|
|
|
2738
3942
|
// src/agent/node/nodeWorkspaceDiscovery.ts
|
|
2739
3943
|
var _fs = require('fs');
|
|
2740
|
-
|
|
3944
|
+
|
|
2741
3945
|
var WORKSPACE_MARKERS = [
|
|
2742
3946
|
{ name: ".brass-agent.json", kind: "file" },
|
|
2743
3947
|
{ name: "brass-agent.config.json", kind: "file" },
|
|
@@ -2751,7 +3955,7 @@ var markerExists2 = (path, kind) => {
|
|
|
2751
3955
|
try {
|
|
2752
3956
|
const stat = _fs.statSync.call(void 0, path);
|
|
2753
3957
|
return kind === "directory" ? stat.isDirectory() : stat.isFile();
|
|
2754
|
-
} catch (
|
|
3958
|
+
} catch (e19) {
|
|
2755
3959
|
return false;
|
|
2756
3960
|
}
|
|
2757
3961
|
};
|
|
@@ -2880,4 +4084,15 @@ var discoverNodeWorkspaceRoot = (cwd, options = {}) => {
|
|
|
2880
4084
|
|
|
2881
4085
|
|
|
2882
4086
|
|
|
2883
|
-
|
|
4087
|
+
|
|
4088
|
+
|
|
4089
|
+
|
|
4090
|
+
|
|
4091
|
+
|
|
4092
|
+
|
|
4093
|
+
|
|
4094
|
+
|
|
4095
|
+
|
|
4096
|
+
|
|
4097
|
+
|
|
4098
|
+
exports.initialAgentState = initialAgentState; exports.reduceAgentState = reduceAgentState; exports.isTerminal = isTerminal; exports.sampleBeta = sampleBeta; exports.extractLikelyFilePaths = extractLikelyFilePaths; exports.deriveContextSearchQueries = deriveContextSearchQueries; exports.describeContextDiscovery = describeContextDiscovery; exports.summarizeContextDiscovery = summarizeContextDiscovery; exports.nextContextDiscoveryAction = nextContextDiscoveryAction; exports.PROJECT_PROFILE_PROBES = PROJECT_PROFILE_PROBES; exports.projectProfileProbePending = projectProfileProbePending; exports.discoverProjectProfile = discoverProjectProfile; exports.describeProjectProfile = describeProjectProfile; exports.PROJECT_LOCKFILE_PROBES = PROJECT_LOCKFILE_PROBES; exports.parseProjectPackageJson = parseProjectPackageJson; exports.nextProjectProbeAction = nextProjectProbeAction; exports.discoverPackageManager = discoverPackageManager; exports.splitCommand = splitCommand; exports.commandForScript = commandForScript; exports.discoverValidationCommands = discoverValidationCommands; exports.nextUnrunValidationCommand = nextUnrunValidationCommand; exports.describeCommandDiscovery = describeCommandDiscovery; exports.patchRepairAttemptsUsed = patchRepairAttemptsUsed; exports.patchQualitySummary = patchQualitySummary; exports.canRequestPatchRepair = canRequestPatchRepair; exports.patchValidationStatus = patchValidationStatus; exports.describePatchQuality = describePatchQuality; exports.rollbackSafetySummary = rollbackSafetySummary; exports.unappliedPatchStack = unappliedPatchStack; exports.latestUnappliedPatch = latestUnappliedPatch; exports.canAutoRollback = canAutoRollback; exports.shouldContinueRollbackStack = shouldContinueRollbackStack; exports.workspaceValidationStatus = workspaceValidationStatus; exports.describeRollbackSafety = describeRollbackSafety; exports.extractUnifiedDiff = extractUnifiedDiff; exports.extractPatchPaths = extractPatchPaths; exports.isRedactionEnabled = isRedactionEnabled; exports.redactText = redactText; exports.inferUserLanguage = inferUserLanguage; exports.responseLanguageName = responseLanguageName; exports.describeLanguagePolicy = describeLanguagePolicy; exports.spanishLike = spanishLike; exports.selectStrategy = selectStrategy; exports.extractSignals = extractSignals; exports.decideNextAction = decideNextAction; exports.nowMillis = nowMillis; exports.emitAgentEvent = emitAgentEvent; exports.emitAgentEvents = emitAgentEvents; exports.summarizeAgentAction = summarizeAgentAction; exports.summarizeAgentObservation = summarizeAgentObservation; exports.observationStatus = observationStatus; exports.errorEventFor = errorEventFor; exports.observationEventFor = observationEventFor; exports.runStatusFor = runStatusFor; exports.retry = retry; exports.sleep = sleep; exports.timeout = timeout; exports.invokeAction = invokeAction; exports.runAgent = runAgent; exports.isAgentConfigMode = isAgentConfigMode; exports.isAgentConfigApprovalMode = isAgentConfigApprovalMode; exports.isAgentConfigLLMProvider = isAgentConfigLLMProvider; exports.AGENT_CONFIG_FILE_NAMES = AGENT_CONFIG_FILE_NAMES; exports.isAgentPreset = isAgentPreset; exports.goalForAgentPreset = goalForAgentPreset; exports.deepFreeze = deepFreeze; exports.collectHostSignals = collectHostSignals; exports.CI_INDICATORS = CI_INDICATORS; exports.inferTransport = inferTransport; exports.inferCapabilities = inferCapabilities; exports.inferConstraints = inferConstraints; exports.inferOptionalIdentity = inferOptionalIdentity; exports.buildHostProfile = buildHostProfile; exports.makeConfiguredPermissions = makeConfiguredPermissions; exports.defaultPermissions = defaultPermissions; exports.autoApproveApprovals = autoApproveApprovals; exports.makeAutoDenyApprovals = makeAutoDenyApprovals; exports.NodeShell = NodeShell; exports.makeNodeFileSystem = makeNodeFileSystem; exports.makeNodePatchService = makeNodePatchService; exports.loadNodeAgentConfig = loadNodeAgentConfig; exports.makeOpenAICompatibleLLM = makeOpenAICompatibleLLM; exports.makeGoogleGenerativeAILLM = makeGoogleGenerativeAILLM; exports.makeFakeLLM = makeFakeLLM; exports.discoverNodeWorkspaceRoot = discoverNodeWorkspaceRoot;
|