brass-runtime 1.13.5 → 1.13.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/cli/main.cjs +2022 -0
- package/dist/agent/cli/main.js +184 -184
- package/dist/agent/index.cjs +153 -0
- package/dist/agent/index.js +153 -153
- package/dist/chunk-3IF374MG.js +121 -121
- package/dist/chunk-AC4RFFVX.cjs +407 -0
- package/dist/chunk-DB57UZBE.cjs +2879 -0
- package/dist/chunk-HRVX2IYW.js +345 -345
- package/dist/chunk-KT4IKCIU.cjs +2556 -0
- package/dist/chunk-TGOMLZ65.js +317 -317
- package/dist/http/index.cjs +453 -0
- package/dist/http/index.js +74 -74
- package/dist/index.cjs +855 -0
- package/dist/index.js +340 -340
- package/package.json +5 -5
- package/dist/agent/cli/main.d.mts +0 -1
- package/dist/agent/index.d.mts +0 -688
- package/dist/effect-ISvXPLgc.d.mts +0 -797
- package/dist/http/index.d.mts +0 -154
- package/dist/index.d.mts +0 -258
- package/dist/stream-C0-LWnUP.d.mts +0 -66
package/dist/chunk-HRVX2IYW.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
import {
|
|
2
|
+
Cause,
|
|
3
|
+
Exit,
|
|
4
|
+
async,
|
|
5
|
+
asyncFail,
|
|
6
|
+
asyncFlatMap,
|
|
7
|
+
asyncFold,
|
|
8
|
+
asyncMap,
|
|
9
|
+
asyncSucceed,
|
|
10
|
+
asyncSync,
|
|
11
|
+
fromPromiseAbortable,
|
|
12
|
+
race,
|
|
13
|
+
withScopeAsync
|
|
14
|
+
} from "./chunk-TGOMLZ65.js";
|
|
15
15
|
|
|
16
16
|
// src/agent/core/state.ts
|
|
17
17
|
var initialAgentState = (goal) => ({
|
|
@@ -200,12 +200,12 @@ var clampPositiveInteger = (value, fallback) => {
|
|
|
200
200
|
return Math.max(0, Math.floor(value));
|
|
201
201
|
};
|
|
202
202
|
var configFor = (state) => ({
|
|
203
|
-
enabled:
|
|
204
|
-
maxSearchQueries: clampPositiveInteger(
|
|
205
|
-
maxFiles: clampPositiveInteger(
|
|
206
|
-
maxSearchResults: clampPositiveInteger(
|
|
207
|
-
globs:
|
|
208
|
-
excludeGlobs:
|
|
203
|
+
enabled: state.goal.context?.enabled ?? true,
|
|
204
|
+
maxSearchQueries: clampPositiveInteger(state.goal.context?.maxSearchQueries, DEFAULT_MAX_SEARCH_QUERIES),
|
|
205
|
+
maxFiles: clampPositiveInteger(state.goal.context?.maxFiles, DEFAULT_MAX_FILES),
|
|
206
|
+
maxSearchResults: clampPositiveInteger(state.goal.context?.maxSearchResults, DEFAULT_MAX_SEARCH_RESULTS),
|
|
207
|
+
globs: state.goal.context?.globs ?? DEFAULT_CONTEXT_GLOBS,
|
|
208
|
+
excludeGlobs: state.goal.context?.excludeGlobs ?? []
|
|
209
209
|
});
|
|
210
210
|
var normalizeSlashes = (value) => value.replace(/\\/g, "/");
|
|
211
211
|
var trimLeadingDotSlash = (value) => value.replace(/^(?:\.\/)+/, "");
|
|
@@ -279,7 +279,7 @@ var extractLikelyFilePaths = (state) => {
|
|
|
279
279
|
`(?:file://)?(?:[A-Za-z]:)?[./\\\\]?(?:[A-Za-z0-9_@.-]+[/\\\\])*[A-Za-z0-9_@.-]+\\.(?:${PATH_EXTENSIONS.join("|")})(?::\\d+){0,2}`,
|
|
280
280
|
"g"
|
|
281
281
|
);
|
|
282
|
-
const matches =
|
|
282
|
+
const matches = corpus.match(pathPattern) ?? [];
|
|
283
283
|
return unique(matches.map((match) => toWorkspaceRelativePath(state.goal.cwd, match)).filter((path) => Boolean(path)).filter((path) => !matchesAnyExclude(path, config.excludeGlobs)));
|
|
284
284
|
};
|
|
285
285
|
var searchedQueries = (state) => unique(state.observations.filter((obs) => obs.type === "fs.searchResult").map((obs) => obs.query));
|
|
@@ -308,7 +308,7 @@ var extractQuotedSignals = (text) => {
|
|
|
308
308
|
const regex = /["'`]([^"'`\n]{4,80})["'`]/g;
|
|
309
309
|
let match;
|
|
310
310
|
while (match = regex.exec(text)) {
|
|
311
|
-
const value =
|
|
311
|
+
const value = match[1]?.trim();
|
|
312
312
|
if (!value) continue;
|
|
313
313
|
if (/\s{3,}/.test(value)) continue;
|
|
314
314
|
if (/^[A-Za-z0-9_./:-]+$/.test(value)) out.push(value);
|
|
@@ -318,7 +318,7 @@ var extractQuotedSignals = (text) => {
|
|
|
318
318
|
var deriveContextSearchQueries = (state) => {
|
|
319
319
|
const corpus = discoveryCorpus(state);
|
|
320
320
|
const quoted = extractQuotedSignals(corpus);
|
|
321
|
-
const tokens =
|
|
321
|
+
const tokens = corpus.match(/[A-Za-z_][A-Za-z0-9_]{3,}/g) ?? [];
|
|
322
322
|
const candidates = unique([...quoted, ...tokens]).map((value) => value.trim()).filter((value) => value.length >= 4 && value.length <= 80).filter((value) => !value.includes("/")).filter((value) => !STOP_WORDS.has(value.toLowerCase())).filter((value) => !/^\d+$/.test(value)).filter((value) => /^[A-Za-z0-9_]+$/.test(value));
|
|
323
323
|
return [...candidates].sort((a, b) => tokenScore(b) - tokenScore(a)).slice(0, 8);
|
|
324
324
|
};
|
|
@@ -358,7 +358,7 @@ var summarizeContextDiscovery = (state) => {
|
|
|
358
358
|
var nextContextDiscoveryAction = (state) => {
|
|
359
359
|
const config = configFor(state);
|
|
360
360
|
if (!config.enabled) return void 0;
|
|
361
|
-
if (
|
|
361
|
+
if (state.goal.initialPatch?.trim()) return void 0;
|
|
362
362
|
const searched = searchedQueries(state);
|
|
363
363
|
const readsRemaining = Math.max(0, config.maxFiles - contextFileReadCount(state));
|
|
364
364
|
const directPaths = extractLikelyFilePaths(state);
|
|
@@ -412,7 +412,7 @@ var parsePackageJson = (state) => {
|
|
|
412
412
|
try {
|
|
413
413
|
const parsed = JSON.parse(observation.content);
|
|
414
414
|
return isRecord(parsed) ? parsed : void 0;
|
|
415
|
-
} catch
|
|
415
|
+
} catch {
|
|
416
416
|
return void 0;
|
|
417
417
|
}
|
|
418
418
|
};
|
|
@@ -426,7 +426,7 @@ var packageScripts = (pkg) => {
|
|
|
426
426
|
};
|
|
427
427
|
var markerExists = (state, path) => state.observations.some((obs) => obs.type === "fs.exists" && obs.path === path && obs.exists);
|
|
428
428
|
var hasDependencyName = (pkg, dependency) => {
|
|
429
|
-
const collections = [
|
|
429
|
+
const collections = [pkg?.dependencies, pkg?.devDependencies, pkg?.optionalDependencies];
|
|
430
430
|
return collections.some((collection) => isRecord(collection) && typeof collection[dependency] === "string");
|
|
431
431
|
};
|
|
432
432
|
var hasAnyDependency = (pkg, dependencies) => dependencies.some((dependency) => hasDependencyName(pkg, dependency));
|
|
@@ -455,7 +455,7 @@ var discoverProjectProfile = (state, packageManager) => {
|
|
|
455
455
|
if (desktopPresent) stacks.push("desktop");
|
|
456
456
|
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"));
|
|
457
457
|
if (bridgePresent) stacks.push("bridge");
|
|
458
|
-
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(
|
|
458
|
+
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(pkg?.workspaces);
|
|
459
459
|
if (monorepoPresent) stacks.push("monorepo");
|
|
460
460
|
const candidateValidationScripts = unique2([
|
|
461
461
|
...scriptNamesMatching(scripts, [
|
|
@@ -537,7 +537,7 @@ var parseProjectPackageJson = (state) => {
|
|
|
537
537
|
try {
|
|
538
538
|
const parsed = JSON.parse(observation.content);
|
|
539
539
|
return isRecord2(parsed) ? parsed : void 0;
|
|
540
|
-
} catch
|
|
540
|
+
} catch {
|
|
541
541
|
return void 0;
|
|
542
542
|
}
|
|
543
543
|
};
|
|
@@ -552,7 +552,7 @@ var packageScripts2 = (pkg) => {
|
|
|
552
552
|
var hasFsExistsObservation = (state, path) => state.observations.some((obs) => obs.type === "fs.exists" && obs.path === path);
|
|
553
553
|
var nextProjectProbeAction = (state) => {
|
|
554
554
|
const project = state.goal.project;
|
|
555
|
-
if (!
|
|
555
|
+
if (!project?.validationCommands && (!project?.packageManager || project.packageManager === "auto")) {
|
|
556
556
|
for (const path of PROJECT_LOCKFILE_PROBES) {
|
|
557
557
|
if (!hasFsExistsObservation(state, path)) return { type: "fs.exists", path };
|
|
558
558
|
}
|
|
@@ -561,9 +561,9 @@ var nextProjectProbeAction = (state) => {
|
|
|
561
561
|
return profileProbe ? { type: "fs.exists", path: profileProbe } : void 0;
|
|
562
562
|
};
|
|
563
563
|
var packageManagerFromPackageJson = (pkg) => {
|
|
564
|
-
const raw = typeof
|
|
564
|
+
const raw = typeof pkg?.packageManager === "string" ? pkg.packageManager : void 0;
|
|
565
565
|
if (!raw) return void 0;
|
|
566
|
-
const name =
|
|
566
|
+
const name = raw.split("@")[0]?.trim();
|
|
567
567
|
if (name === "npm" || name === "pnpm" || name === "yarn" || name === "bun") return name;
|
|
568
568
|
return void 0;
|
|
569
569
|
};
|
|
@@ -576,9 +576,9 @@ var packageManagerFromLockfiles = (state) => {
|
|
|
576
576
|
return void 0;
|
|
577
577
|
};
|
|
578
578
|
var discoverPackageManager = (state) => {
|
|
579
|
-
const configured =
|
|
579
|
+
const configured = state.goal.project?.packageManager;
|
|
580
580
|
if (configured && configured !== "auto") return configured;
|
|
581
|
-
return
|
|
581
|
+
return packageManagerFromPackageJson(parseProjectPackageJson(state)) ?? packageManagerFromLockfiles(state) ?? "npm";
|
|
582
582
|
};
|
|
583
583
|
var isPlaceholderTestScript = (script) => /no test specified/i.test(script) && /exit\s+1/.test(script);
|
|
584
584
|
var firstExistingScript = (scripts, names, options = {}) => {
|
|
@@ -664,7 +664,7 @@ var commandForScript = (packageManager, scriptName) => {
|
|
|
664
664
|
}
|
|
665
665
|
};
|
|
666
666
|
var configuredValidationCommands = (project) => {
|
|
667
|
-
if (!
|
|
667
|
+
if (!project?.validationCommands) return void 0;
|
|
668
668
|
return project.validationCommands.map((command) => splitCommand(command)).filter((command) => command.length > 0);
|
|
669
669
|
};
|
|
670
670
|
var discoverValidationCommands = (state) => {
|
|
@@ -689,7 +689,7 @@ var discoverValidationCommands = (state) => {
|
|
|
689
689
|
const notes = [];
|
|
690
690
|
const testScript = firstExistingScript(
|
|
691
691
|
scripts,
|
|
692
|
-
|
|
692
|
+
project?.testScriptNames ?? DEFAULT_TEST_SCRIPT_NAMES,
|
|
693
693
|
{ skipPlaceholderTest: true }
|
|
694
694
|
);
|
|
695
695
|
if (testScript) {
|
|
@@ -703,7 +703,7 @@ var discoverValidationCommands = (state) => {
|
|
|
703
703
|
notes.push(`Selected project health script: ${healthScript}.`);
|
|
704
704
|
}
|
|
705
705
|
}
|
|
706
|
-
const includeTypecheck =
|
|
706
|
+
const includeTypecheck = project?.includeTypecheck === true || goalMentionsAny(state.goal.text, ["typecheck", "type-check", "type check", "types", "tsc"]) || commands.length === 0;
|
|
707
707
|
if (includeTypecheck) {
|
|
708
708
|
const typecheckScript = firstExistingScript(scripts, TYPECHECK_SCRIPT_NAMES);
|
|
709
709
|
if (typecheckScript) {
|
|
@@ -711,7 +711,7 @@ var discoverValidationCommands = (state) => {
|
|
|
711
711
|
notes.push(`Selected typecheck script: ${typecheckScript}.`);
|
|
712
712
|
}
|
|
713
713
|
}
|
|
714
|
-
const includeLint =
|
|
714
|
+
const includeLint = project?.includeLint === true || goalMentionsAny(state.goal.text, ["lint", "eslint"]) || commands.length === 0;
|
|
715
715
|
if (includeLint) {
|
|
716
716
|
const lintScript = firstExistingScript(scripts, LINT_SCRIPT_NAMES);
|
|
717
717
|
if (lintScript) {
|
|
@@ -723,7 +723,7 @@ var discoverValidationCommands = (state) => {
|
|
|
723
723
|
commands.push(["cargo", "check"]);
|
|
724
724
|
notes.push("Selected Cargo check because a root Cargo.toml was detected.");
|
|
725
725
|
}
|
|
726
|
-
const max =
|
|
726
|
+
const max = project?.maxValidationCommands ?? 2;
|
|
727
727
|
const validationCommands = dedupeCommands(commands).slice(0, Math.max(0, max));
|
|
728
728
|
return {
|
|
729
729
|
packageManager,
|
|
@@ -751,9 +751,9 @@ var clampNonNegativeInteger = (value, fallback) => {
|
|
|
751
751
|
};
|
|
752
752
|
var patchRepairAttemptsUsed = (state) => state.observations.filter((obs) => obs.type === "llm.response" && obs.purpose === "patch").length;
|
|
753
753
|
var patchQualitySummary = (state) => {
|
|
754
|
-
const enabled =
|
|
754
|
+
const enabled = state.goal.patchQuality?.enabled ?? true;
|
|
755
755
|
const maxRepairAttempts = clampNonNegativeInteger(
|
|
756
|
-
|
|
756
|
+
state.goal.patchQuality?.maxRepairAttempts,
|
|
757
757
|
DEFAULT_MAX_REPAIR_ATTEMPTS
|
|
758
758
|
);
|
|
759
759
|
const repairAttemptsUsed = patchRepairAttemptsUsed(state);
|
|
@@ -762,7 +762,7 @@ var patchQualitySummary = (state) => {
|
|
|
762
762
|
maxRepairAttempts,
|
|
763
763
|
repairAttemptsUsed,
|
|
764
764
|
repairsRemaining: Math.max(0, maxRepairAttempts - repairAttemptsUsed),
|
|
765
|
-
exactSuppliedPatch: Boolean(
|
|
765
|
+
exactSuppliedPatch: Boolean(state.goal.initialPatch?.trim())
|
|
766
766
|
};
|
|
767
767
|
};
|
|
768
768
|
var canRequestPatchRepair = (state) => {
|
|
@@ -804,26 +804,26 @@ var clampNonNegativeInteger2 = (value, fallback) => {
|
|
|
804
804
|
var rollbackStrategy = (value) => value === "last" ? "last" : "all";
|
|
805
805
|
var rollbackSafetySummary = (state) => {
|
|
806
806
|
const rollback = state.goal.rollback;
|
|
807
|
-
const enabled =
|
|
808
|
-
const maxRollbackDepth = clampNonNegativeInteger2(
|
|
807
|
+
const enabled = rollback?.enabled ?? true;
|
|
808
|
+
const maxRollbackDepth = clampNonNegativeInteger2(rollback?.maxRollbackDepth, DEFAULT_MAX_ROLLBACK_DEPTH);
|
|
809
809
|
const rollbackCount = state.observations.filter((obs) => obs.type === "patch.rolledBack").length;
|
|
810
810
|
const appliedStackDepth = unappliedPatchStack(state).length;
|
|
811
811
|
return {
|
|
812
812
|
enabled,
|
|
813
|
-
onFinalValidationFailure:
|
|
814
|
-
strategy: rollbackStrategy(
|
|
813
|
+
onFinalValidationFailure: rollback?.onFinalValidationFailure ?? true,
|
|
814
|
+
strategy: rollbackStrategy(rollback?.strategy),
|
|
815
815
|
maxRollbackDepth,
|
|
816
|
-
runValidationAfterRollback:
|
|
817
|
-
allowForSuppliedPatches:
|
|
816
|
+
runValidationAfterRollback: rollback?.runValidationAfterRollback ?? true,
|
|
817
|
+
allowForSuppliedPatches: rollback?.allowForSuppliedPatches ?? false,
|
|
818
818
|
rollbackCount,
|
|
819
819
|
appliedStackDepth,
|
|
820
|
-
exactSuppliedPatch: Boolean(
|
|
820
|
+
exactSuppliedPatch: Boolean(state.goal.initialPatch?.trim())
|
|
821
821
|
};
|
|
822
822
|
};
|
|
823
823
|
var unappliedPatchStack = (state) => {
|
|
824
824
|
const stack = [];
|
|
825
825
|
for (const [index, observation] of state.observations.entries()) {
|
|
826
|
-
if (observation.type === "patch.applied" &&
|
|
826
|
+
if (observation.type === "patch.applied" && observation.patch?.trim()) {
|
|
827
827
|
stack.push({
|
|
828
828
|
index,
|
|
829
829
|
patch: observation.patch,
|
|
@@ -831,8 +831,8 @@ var unappliedPatchStack = (state) => {
|
|
|
831
831
|
});
|
|
832
832
|
continue;
|
|
833
833
|
}
|
|
834
|
-
if (observation.type === "patch.rolledBack" &&
|
|
835
|
-
const existingIndex = [...stack].reverse().findIndex((entry) => entry.patch.trim() ===
|
|
834
|
+
if (observation.type === "patch.rolledBack" && observation.patch?.trim()) {
|
|
835
|
+
const existingIndex = [...stack].reverse().findIndex((entry) => entry.patch.trim() === observation.patch?.trim());
|
|
836
836
|
if (existingIndex >= 0) {
|
|
837
837
|
stack.splice(stack.length - 1 - existingIndex, 1);
|
|
838
838
|
}
|
|
@@ -851,7 +851,7 @@ var canAutoRollback = (state) => {
|
|
|
851
851
|
var shouldContinueRollbackStack = (state) => {
|
|
852
852
|
const summary = rollbackSafetySummary(state);
|
|
853
853
|
const latest = state.observations.at(-1);
|
|
854
|
-
return
|
|
854
|
+
return latest?.type === "patch.rolledBack" && summary.strategy === "all" && canAutoRollback(state);
|
|
855
855
|
};
|
|
856
856
|
var commandsEqual3 = (a, b) => a.length === b.length && a.every((part, index) => part === b[index]);
|
|
857
857
|
var shellResultsForCommands2 = (commands, observations) => commands.flatMap(
|
|
@@ -903,7 +903,7 @@ var extractUnifiedDiff = (content) => {
|
|
|
903
903
|
if (!normalized) return void 0;
|
|
904
904
|
const matches = normalized.matchAll(FENCED_DIFF_BLOCK);
|
|
905
905
|
for (const match of matches) {
|
|
906
|
-
const candidate = normalizePatch(
|
|
906
|
+
const candidate = normalizePatch(match[1] ?? "");
|
|
907
907
|
if (looksLikeUnifiedDiff(candidate)) {
|
|
908
908
|
return candidate;
|
|
909
909
|
}
|
|
@@ -943,12 +943,12 @@ var DEFAULT_SECRET_PATTERNS = [
|
|
|
943
943
|
var toRegExp = (pattern) => {
|
|
944
944
|
try {
|
|
945
945
|
return new RegExp(pattern, "gi");
|
|
946
|
-
} catch
|
|
946
|
+
} catch {
|
|
947
947
|
return void 0;
|
|
948
948
|
}
|
|
949
949
|
};
|
|
950
|
-
var configuredPatterns = (config) => (
|
|
951
|
-
var isRedactionEnabled = (config) =>
|
|
950
|
+
var configuredPatterns = (config) => (config?.additionalPatterns ?? []).map(toRegExp).filter((pattern) => Boolean(pattern));
|
|
951
|
+
var isRedactionEnabled = (config) => config?.enabled ?? true;
|
|
952
952
|
var redactText = (value, config) => {
|
|
953
953
|
if (!isRedactionEnabled(config) || !value) return value;
|
|
954
954
|
return [...DEFAULT_SECRET_PATTERNS, ...configuredPatterns(config)].reduce(
|
|
@@ -985,12 +985,12 @@ var inferUserLanguage = (text) => {
|
|
|
985
985
|
return void 0;
|
|
986
986
|
};
|
|
987
987
|
var configuredLanguageName = (language) => {
|
|
988
|
-
const response =
|
|
989
|
-
if (response === "custom") return
|
|
988
|
+
const response = language?.response ?? "auto";
|
|
989
|
+
if (response === "custom") return language?.custom?.trim() || void 0;
|
|
990
990
|
if (response === "auto" || response === "match-user") return void 0;
|
|
991
991
|
return LANGUAGE_LABELS[response];
|
|
992
992
|
};
|
|
993
|
-
var responseLanguageName = (goal) =>
|
|
993
|
+
var responseLanguageName = (goal) => configuredLanguageName(goal.language) ?? inferUserLanguage(goal.text);
|
|
994
994
|
var describeLanguagePolicy = (goal) => {
|
|
995
995
|
const configured = configuredLanguageName(goal.language);
|
|
996
996
|
const inferred = inferUserLanguage(goal.text);
|
|
@@ -1035,7 +1035,7 @@ var observationsAfterLatestWorkspaceChange = (state) => {
|
|
|
1035
1035
|
var latestWorkspaceChange = (state) => {
|
|
1036
1036
|
const index = latestWorkspaceChangeIndex(state);
|
|
1037
1037
|
const observation = index < 0 ? void 0 : state.observations[index];
|
|
1038
|
-
return
|
|
1038
|
+
return observation?.type === "patch.applied" || observation?.type === "patch.rolledBack" ? observation : void 0;
|
|
1039
1039
|
};
|
|
1040
1040
|
var compactObservation = (obs) => {
|
|
1041
1041
|
switch (obs.type) {
|
|
@@ -1098,7 +1098,7 @@ var causeMessage = (cause) => {
|
|
|
1098
1098
|
try {
|
|
1099
1099
|
const json = JSON.stringify(cause);
|
|
1100
1100
|
if (json && json !== "{}") return json;
|
|
1101
|
-
} catch
|
|
1101
|
+
} catch {
|
|
1102
1102
|
}
|
|
1103
1103
|
}
|
|
1104
1104
|
return String(cause);
|
|
@@ -1138,7 +1138,7 @@ ${result.stderr.slice(-8e3)}` : void 0
|
|
|
1138
1138
|
var buildPatchRepairPrompt = (state, reason) => {
|
|
1139
1139
|
const discovery = discoverValidationCommands(state);
|
|
1140
1140
|
const quality = patchQualitySummary(state);
|
|
1141
|
-
const latestPatchError =
|
|
1141
|
+
const latestPatchError = lastObservation(state, "agent.error")?.error;
|
|
1142
1142
|
const latestPatch = lastMaterializedPatch(state);
|
|
1143
1143
|
return redactForPrompt(state, [
|
|
1144
1144
|
"You are repairing a generated patch for a coding agent running on brass-runtime.",
|
|
@@ -1164,7 +1164,7 @@ ${latestPatch.slice(-8e3)}` : "Latest materialized patch: none.",
|
|
|
1164
1164
|
failedValidationLines(state).length > 0 ? `Failed validation after latest patch:
|
|
1165
1165
|
${failedValidationLines(state).join("\n\n")}` : "Failed validation after latest patch: none recorded.",
|
|
1166
1166
|
"",
|
|
1167
|
-
|
|
1167
|
+
latestPatchError?._tag === "PatchError" ? `Latest patch error during ${latestPatchError.operation}: ${String(latestPatchError.cause)}` : "Latest patch error: none.",
|
|
1168
1168
|
"",
|
|
1169
1169
|
"Recent observations:",
|
|
1170
1170
|
compactObservations(state) || "No observations yet."
|
|
@@ -1176,14 +1176,14 @@ var buildValidationSummary = (state) => {
|
|
|
1176
1176
|
if (validationResults.length === 0) return void 0;
|
|
1177
1177
|
const change = latestWorkspaceChange(state);
|
|
1178
1178
|
const spanish = spanishLike(state.goal);
|
|
1179
|
-
const label =
|
|
1179
|
+
const label = change?.type === "patch.rolledBack" ? spanish ? "rollback" : "rollback" : spanish ? "aplicar patch" : "apply";
|
|
1180
1180
|
return [
|
|
1181
1181
|
spanish ? `Validaci\xF3n despu\xE9s de ${label}:` : `Validation after latest ${label}:`,
|
|
1182
1182
|
...validationResults.map((result) => `- ${result.command.join(" ")} ${spanish ? "termin\xF3 con c\xF3digo" : "exited with"} ${result.exitCode}.`)
|
|
1183
1183
|
].join("\n");
|
|
1184
1184
|
};
|
|
1185
1185
|
var buildCompletionSummary = (state, patch) => {
|
|
1186
|
-
const plan =
|
|
1186
|
+
const plan = firstObservation(state, "llm.response")?.content?.trim() ?? "No plan was generated.";
|
|
1187
1187
|
const latestResponse = lastObservation(state, "llm.response");
|
|
1188
1188
|
const patchApplied = lastObservation(state, "patch.applied");
|
|
1189
1189
|
const patchRolledBack = lastObservation(state, "patch.rolledBack");
|
|
@@ -1191,7 +1191,7 @@ var buildCompletionSummary = (state, patch) => {
|
|
|
1191
1191
|
const validation = buildValidationSummary(state);
|
|
1192
1192
|
const spanish = spanishLike(state.goal);
|
|
1193
1193
|
const lines = [plan];
|
|
1194
|
-
if (
|
|
1194
|
+
if (latestResponse?.purpose === "patch" && latestResponse.content.trim()) {
|
|
1195
1195
|
lines.push("", spanish ? "\xDAltima respuesta de reparaci\xF3n del patch:" : "Latest patch repair response:", latestResponse.content.trim());
|
|
1196
1196
|
}
|
|
1197
1197
|
if (patchRolledBack) {
|
|
@@ -1215,14 +1215,14 @@ var buildCompletionSummary = (state, patch) => {
|
|
|
1215
1215
|
return redactForPrompt(state, lines.join("\n").trim());
|
|
1216
1216
|
};
|
|
1217
1217
|
var buildErrorSummary = (state) => {
|
|
1218
|
-
const latestError =
|
|
1218
|
+
const latestError = lastObservation(state, "agent.error")?.error;
|
|
1219
1219
|
const spanish = spanishLike(state.goal);
|
|
1220
1220
|
if (!latestError) return spanish ? "La ejecuci\xF3n del agente fall\xF3." : "Agent run failed.";
|
|
1221
1221
|
switch (latestError._tag) {
|
|
1222
1222
|
case "FsError":
|
|
1223
1223
|
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)}`;
|
|
1224
1224
|
case "ShellError":
|
|
1225
|
-
return spanish ? `El agente se detuvo por un error ejecutando ${
|
|
1225
|
+
return spanish ? `El agente se detuvo por un error ejecutando ${latestError.command?.join(" ") ?? latestError.operation}: ${errorDetail(state, latestError.cause)}` : `Agent stopped after a shell error during ${latestError.command?.join(" ") ?? latestError.operation}: ${errorDetail(state, latestError.cause)}`;
|
|
1226
1226
|
case "LLMError":
|
|
1227
1227
|
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)}`;
|
|
1228
1228
|
case "PatchError":
|
|
@@ -1270,7 +1270,7 @@ var latestLlmPatchCandidate = (state) => {
|
|
|
1270
1270
|
var latestExtractedPatch = (state) => {
|
|
1271
1271
|
for (let index = state.observations.length - 1; index >= 0; index -= 1) {
|
|
1272
1272
|
const observation = state.observations[index];
|
|
1273
|
-
if (
|
|
1273
|
+
if (observation?.type !== "llm.response") continue;
|
|
1274
1274
|
const patch = extractUnifiedDiff(observation.content);
|
|
1275
1275
|
if (patch) return patch;
|
|
1276
1276
|
}
|
|
@@ -1279,8 +1279,8 @@ var latestExtractedPatch = (state) => {
|
|
|
1279
1279
|
var lastMaterializedPatch = (state) => {
|
|
1280
1280
|
for (let index = state.observations.length - 1; index >= 0; index -= 1) {
|
|
1281
1281
|
const observation = state.observations[index];
|
|
1282
|
-
if (
|
|
1283
|
-
if (
|
|
1282
|
+
if (observation?.type === "patch.proposed") return observation.patch;
|
|
1283
|
+
if (observation?.type === "patch.applied") {
|
|
1284
1284
|
if (observation.patch) return observation.patch;
|
|
1285
1285
|
const previousLlmPatch = state.observations.slice(0, index).reverse().find((obs) => obs.type === "llm.response" && Boolean(extractUnifiedDiff(obs.content)));
|
|
1286
1286
|
return previousLlmPatch ? extractUnifiedDiff(previousLlmPatch.content) : state.goal.initialPatch;
|
|
@@ -1290,7 +1290,7 @@ var lastMaterializedPatch = (state) => {
|
|
|
1290
1290
|
};
|
|
1291
1291
|
var shouldRequestRepairAfterValidation = (state) => {
|
|
1292
1292
|
if (!isWritableMode(state.goal.mode)) return false;
|
|
1293
|
-
if (
|
|
1293
|
+
if (latestWorkspaceChange(state)?.type !== "patch.applied") return false;
|
|
1294
1294
|
if (!canRequestPatchRepair(state)) return false;
|
|
1295
1295
|
const commands = discoverValidationCommands(state).validationCommands;
|
|
1296
1296
|
const status = patchValidationStatus(commands, observationsAfterPatch(state));
|
|
@@ -1298,7 +1298,7 @@ var shouldRequestRepairAfterValidation = (state) => {
|
|
|
1298
1298
|
};
|
|
1299
1299
|
var shouldAutoRollbackAfterFinalValidationFailure = (state) => {
|
|
1300
1300
|
if (!isWritableMode(state.goal.mode)) return false;
|
|
1301
|
-
if (
|
|
1301
|
+
if (latestWorkspaceChange(state)?.type !== "patch.applied") return false;
|
|
1302
1302
|
if (canRequestPatchRepair(state)) return false;
|
|
1303
1303
|
const summary = rollbackSafetySummary(state);
|
|
1304
1304
|
if (!summary.onFinalValidationFailure) return false;
|
|
@@ -1311,7 +1311,7 @@ var shouldRequestRepairAfterPatchError = (state) => {
|
|
|
1311
1311
|
if (!isWritableMode(state.goal.mode)) return false;
|
|
1312
1312
|
if (!canRequestPatchRepair(state)) return false;
|
|
1313
1313
|
const latest = state.observations.at(-1);
|
|
1314
|
-
return
|
|
1314
|
+
return latest?.type === "agent.error" && latest.error._tag === "PatchError";
|
|
1315
1315
|
};
|
|
1316
1316
|
var repairAction = (state, reason) => ({
|
|
1317
1317
|
type: "llm.complete",
|
|
@@ -1348,24 +1348,24 @@ var initialPatchFlowAction = (state, suppliedPatch) => {
|
|
|
1348
1348
|
};
|
|
1349
1349
|
var decideNextAction = (state) => {
|
|
1350
1350
|
const latest = state.observations.at(-1);
|
|
1351
|
-
if (
|
|
1351
|
+
if (latest?.type === "agent.error") {
|
|
1352
1352
|
if (shouldRequestRepairAfterPatchError(state)) {
|
|
1353
|
-
return
|
|
1353
|
+
return asyncSucceed(repairAction(state, "previous patch failed to apply"));
|
|
1354
1354
|
}
|
|
1355
|
-
return
|
|
1355
|
+
return asyncSucceed({ type: "agent.finish", summary: buildErrorSummary(state) });
|
|
1356
1356
|
}
|
|
1357
1357
|
if (!hasObservation(state, "fs.fileRead")) {
|
|
1358
|
-
return
|
|
1358
|
+
return asyncSucceed({ type: "fs.readFile", path: "package.json" });
|
|
1359
1359
|
}
|
|
1360
1360
|
const probeAction = nextProjectProbeAction(state);
|
|
1361
1361
|
if (probeAction) {
|
|
1362
|
-
return
|
|
1362
|
+
return asyncSucceed(probeAction);
|
|
1363
1363
|
}
|
|
1364
|
-
const suppliedPatch =
|
|
1364
|
+
const suppliedPatch = state.goal.initialPatch?.trim();
|
|
1365
1365
|
if (suppliedPatch) {
|
|
1366
1366
|
const action = initialPatchFlowAction(state, suppliedPatch);
|
|
1367
|
-
if (action) return
|
|
1368
|
-
return
|
|
1367
|
+
if (action) return asyncSucceed(action);
|
|
1368
|
+
return asyncSucceed({
|
|
1369
1369
|
type: "agent.finish",
|
|
1370
1370
|
summary: buildCompletionSummary(state, suppliedPatch)
|
|
1371
1371
|
});
|
|
@@ -1373,10 +1373,10 @@ var decideNextAction = (state) => {
|
|
|
1373
1373
|
const pendingLlmPatch = latestLlmPatchCandidate(state);
|
|
1374
1374
|
if (pendingLlmPatch) {
|
|
1375
1375
|
if (isWritableMode(state.goal.mode)) {
|
|
1376
|
-
return
|
|
1376
|
+
return asyncSucceed({ type: "patch.apply", patch: pendingLlmPatch.patch });
|
|
1377
1377
|
}
|
|
1378
1378
|
if (state.goal.mode === "propose") {
|
|
1379
|
-
return
|
|
1379
|
+
return asyncSucceed({ type: "patch.propose", patch: pendingLlmPatch.patch });
|
|
1380
1380
|
}
|
|
1381
1381
|
}
|
|
1382
1382
|
const planResponse = state.observations.find(
|
|
@@ -1384,10 +1384,10 @@ var decideNextAction = (state) => {
|
|
|
1384
1384
|
);
|
|
1385
1385
|
if (!planResponse) {
|
|
1386
1386
|
const validationAction = nextValidationActionBeforePlanning(state);
|
|
1387
|
-
if (validationAction) return
|
|
1387
|
+
if (validationAction) return asyncSucceed(validationAction);
|
|
1388
1388
|
const contextAction = nextContextDiscoveryAction(state);
|
|
1389
|
-
if (contextAction) return
|
|
1390
|
-
return
|
|
1389
|
+
if (contextAction) return asyncSucceed(contextAction);
|
|
1390
|
+
return asyncSucceed({
|
|
1391
1391
|
type: "llm.complete",
|
|
1392
1392
|
purpose: "plan",
|
|
1393
1393
|
prompt: buildPlanningPrompt(state)
|
|
@@ -1396,48 +1396,48 @@ var decideNextAction = (state) => {
|
|
|
1396
1396
|
if (isWritableMode(state.goal.mode)) {
|
|
1397
1397
|
if (shouldContinueRollbackStack(state)) {
|
|
1398
1398
|
const rollbackAction = automaticRollbackAction(state, "continuing rollback of generated patch stack");
|
|
1399
|
-
if (rollbackAction) return
|
|
1399
|
+
if (rollbackAction) return asyncSucceed(rollbackAction);
|
|
1400
1400
|
}
|
|
1401
|
-
if (
|
|
1401
|
+
if (latestWorkspaceChange(state)?.type === "patch.rolledBack") {
|
|
1402
1402
|
const summary = rollbackSafetySummary(state);
|
|
1403
1403
|
if (summary.runValidationAfterRollback) {
|
|
1404
1404
|
const validationAction = nextValidationActionAfterLatestWorkspaceChange(state);
|
|
1405
|
-
if (validationAction) return
|
|
1405
|
+
if (validationAction) return asyncSucceed(validationAction);
|
|
1406
1406
|
}
|
|
1407
1407
|
}
|
|
1408
|
-
if (
|
|
1408
|
+
if (latestWorkspaceChange(state)?.type === "patch.applied") {
|
|
1409
1409
|
const validationAction = nextValidationActionAfterPatch(state);
|
|
1410
|
-
if (validationAction) return
|
|
1410
|
+
if (validationAction) return asyncSucceed(validationAction);
|
|
1411
1411
|
if (shouldRequestRepairAfterValidation(state)) {
|
|
1412
|
-
return
|
|
1412
|
+
return asyncSucceed(repairAction(state, "validation failed after applying the generated patch"));
|
|
1413
1413
|
}
|
|
1414
1414
|
if (shouldAutoRollbackAfterFinalValidationFailure(state)) {
|
|
1415
1415
|
const rollbackAction = automaticRollbackAction(state, "validation failed after generated patches and no repair attempts remain");
|
|
1416
|
-
if (rollbackAction) return
|
|
1416
|
+
if (rollbackAction) return asyncSucceed(rollbackAction);
|
|
1417
1417
|
}
|
|
1418
1418
|
}
|
|
1419
1419
|
}
|
|
1420
1420
|
const patch = latestExtractedPatch(state);
|
|
1421
|
-
return
|
|
1421
|
+
return asyncSucceed({
|
|
1422
1422
|
type: "agent.finish",
|
|
1423
1423
|
summary: buildCompletionSummary(state, patch)
|
|
1424
1424
|
});
|
|
1425
1425
|
};
|
|
1426
1426
|
|
|
1427
1427
|
// src/agent/core/events.ts
|
|
1428
|
-
var nowMillis = () =>
|
|
1428
|
+
var nowMillis = () => async((_env, cb) => {
|
|
1429
1429
|
cb({ _tag: "Success", value: Date.now() });
|
|
1430
1430
|
});
|
|
1431
|
-
var emitAgentEvent = (event) =>
|
|
1431
|
+
var emitAgentEvent = (event) => async((env, cb) => {
|
|
1432
1432
|
try {
|
|
1433
|
-
|
|
1434
|
-
} catch
|
|
1433
|
+
env.events?.emit(event);
|
|
1434
|
+
} catch {
|
|
1435
1435
|
}
|
|
1436
1436
|
cb({ _tag: "Success", value: void 0 });
|
|
1437
1437
|
});
|
|
1438
1438
|
var emitAgentEvents = (events) => events.reduce(
|
|
1439
|
-
(acc, event) =>
|
|
1440
|
-
|
|
1439
|
+
(acc, event) => asyncFlatMap(acc, () => emitAgentEvent(event)),
|
|
1440
|
+
asyncSucceed(void 0)
|
|
1441
1441
|
);
|
|
1442
1442
|
var summarizeAgentAction = (action) => {
|
|
1443
1443
|
switch (action.type) {
|
|
@@ -1549,7 +1549,7 @@ var observationEventFor = (state, observation, at) => {
|
|
|
1549
1549
|
var runStatusFor = (phase) => phase === "done" ? "done" : "failed";
|
|
1550
1550
|
|
|
1551
1551
|
// src/agent/tools/env.ts
|
|
1552
|
-
var service = (key) =>
|
|
1552
|
+
var service = (key) => asyncSync((env) => env[key]);
|
|
1553
1553
|
|
|
1554
1554
|
// src/agent/tools/path.ts
|
|
1555
1555
|
var isAbsoluteLike = (path) => path.startsWith("/") || /^[A-Za-z]:[\\/]/.test(path);
|
|
@@ -1575,49 +1575,49 @@ var normalizeWorkspaceRelativePath = (inputPath) => {
|
|
|
1575
1575
|
var resolveWorkspacePath = (cwd, inputPath) => {
|
|
1576
1576
|
const normalized = normalizeWorkspaceRelativePath(inputPath);
|
|
1577
1577
|
if (!normalized) {
|
|
1578
|
-
return
|
|
1578
|
+
return asyncFail({ _tag: "PathOutsideWorkspace", path: inputPath, cwd });
|
|
1579
1579
|
}
|
|
1580
|
-
return
|
|
1580
|
+
return asyncSucceed(`${trimTrailingSlash(cwd)}/${normalized}`);
|
|
1581
1581
|
};
|
|
1582
1582
|
|
|
1583
1583
|
// src/agent/tools/actionToEffect.ts
|
|
1584
1584
|
var actionToEffect = (action, state) => {
|
|
1585
1585
|
switch (action.type) {
|
|
1586
1586
|
case "fs.readFile":
|
|
1587
|
-
return
|
|
1587
|
+
return asyncFlatMap(
|
|
1588
1588
|
resolveWorkspacePath(state.goal.cwd, action.path),
|
|
1589
|
-
(path) =>
|
|
1589
|
+
(path) => asyncFlatMap(
|
|
1590
1590
|
service("fs"),
|
|
1591
|
-
(fs) =>
|
|
1591
|
+
(fs) => asyncMap(
|
|
1592
1592
|
fs.readFile(path),
|
|
1593
1593
|
(content) => ({ type: "fs.fileRead", path: action.path, content })
|
|
1594
1594
|
)
|
|
1595
1595
|
)
|
|
1596
1596
|
);
|
|
1597
1597
|
case "fs.exists":
|
|
1598
|
-
return
|
|
1598
|
+
return asyncFlatMap(
|
|
1599
1599
|
resolveWorkspacePath(state.goal.cwd, action.path),
|
|
1600
|
-
(path) =>
|
|
1600
|
+
(path) => asyncFlatMap(
|
|
1601
1601
|
service("fs"),
|
|
1602
|
-
(fs) =>
|
|
1602
|
+
(fs) => asyncMap(
|
|
1603
1603
|
fs.exists(path),
|
|
1604
1604
|
(exists) => ({ type: "fs.exists", path: action.path, exists })
|
|
1605
1605
|
)
|
|
1606
1606
|
)
|
|
1607
1607
|
);
|
|
1608
1608
|
case "fs.searchText":
|
|
1609
|
-
return
|
|
1609
|
+
return asyncFlatMap(
|
|
1610
1610
|
service("fs"),
|
|
1611
|
-
(fs) =>
|
|
1611
|
+
(fs) => asyncMap(
|
|
1612
1612
|
fs.searchText(state.goal.cwd, action.query, { globs: action.globs }),
|
|
1613
1613
|
(matches) => ({ type: "fs.searchResult", query: action.query, matches })
|
|
1614
1614
|
)
|
|
1615
1615
|
);
|
|
1616
1616
|
case "shell.exec":
|
|
1617
|
-
return
|
|
1617
|
+
return asyncFlatMap(
|
|
1618
1618
|
service("shell"),
|
|
1619
|
-
(shell) =>
|
|
1620
|
-
shell.exec(action.command, { cwd:
|
|
1619
|
+
(shell) => asyncMap(
|
|
1620
|
+
shell.exec(action.command, { cwd: action.cwd ?? state.goal.cwd }),
|
|
1621
1621
|
(result) => ({
|
|
1622
1622
|
type: "shell.result",
|
|
1623
1623
|
command: action.command,
|
|
@@ -1628,19 +1628,19 @@ var actionToEffect = (action, state) => {
|
|
|
1628
1628
|
)
|
|
1629
1629
|
);
|
|
1630
1630
|
case "llm.complete":
|
|
1631
|
-
return
|
|
1631
|
+
return asyncFlatMap(
|
|
1632
1632
|
service("llm"),
|
|
1633
|
-
(llm) =>
|
|
1633
|
+
(llm) => asyncMap(
|
|
1634
1634
|
llm.complete({ purpose: action.purpose, prompt: action.prompt }),
|
|
1635
1635
|
(response) => ({ type: "llm.response", purpose: action.purpose, content: response.content })
|
|
1636
1636
|
)
|
|
1637
1637
|
);
|
|
1638
1638
|
case "patch.propose":
|
|
1639
|
-
return
|
|
1639
|
+
return asyncSucceed({ type: "patch.proposed", patch: action.patch });
|
|
1640
1640
|
case "patch.apply":
|
|
1641
|
-
return
|
|
1641
|
+
return asyncFlatMap(
|
|
1642
1642
|
service("patch"),
|
|
1643
|
-
(patch) =>
|
|
1643
|
+
(patch) => asyncMap(
|
|
1644
1644
|
patch.apply(state.goal.cwd, action.patch),
|
|
1645
1645
|
(result) => ({
|
|
1646
1646
|
type: "patch.applied",
|
|
@@ -1650,9 +1650,9 @@ var actionToEffect = (action, state) => {
|
|
|
1650
1650
|
)
|
|
1651
1651
|
);
|
|
1652
1652
|
case "patch.rollback":
|
|
1653
|
-
return
|
|
1653
|
+
return asyncFlatMap(
|
|
1654
1654
|
service("patch"),
|
|
1655
|
-
(patch) =>
|
|
1655
|
+
(patch) => asyncMap(
|
|
1656
1656
|
patch.rollback(state.goal.cwd, action.patch),
|
|
1657
1657
|
(result) => ({
|
|
1658
1658
|
type: "patch.rolledBack",
|
|
@@ -1664,33 +1664,33 @@ var actionToEffect = (action, state) => {
|
|
|
1664
1664
|
)
|
|
1665
1665
|
);
|
|
1666
1666
|
case "agent.finish":
|
|
1667
|
-
return
|
|
1667
|
+
return asyncSucceed({ type: "agent.done", summary: action.summary });
|
|
1668
1668
|
case "agent.fail":
|
|
1669
|
-
return
|
|
1669
|
+
return asyncFail({ _tag: "AgentLoopError", message: action.reason });
|
|
1670
1670
|
}
|
|
1671
1671
|
};
|
|
1672
1672
|
|
|
1673
1673
|
// src/agent/tools/retry.ts
|
|
1674
1674
|
var retry = (make, options) => {
|
|
1675
|
-
const loop = (remaining) =>
|
|
1675
|
+
const loop = (remaining) => asyncFold(
|
|
1676
1676
|
make(),
|
|
1677
1677
|
(error) => {
|
|
1678
1678
|
if (remaining > 0 && options.while(error)) return loop(remaining - 1);
|
|
1679
|
-
return
|
|
1679
|
+
return asyncFail(error);
|
|
1680
1680
|
},
|
|
1681
|
-
(value) =>
|
|
1681
|
+
(value) => asyncSucceed(value)
|
|
1682
1682
|
);
|
|
1683
1683
|
return loop(options.times);
|
|
1684
1684
|
};
|
|
1685
1685
|
|
|
1686
1686
|
// src/agent/tools/timeout.ts
|
|
1687
|
-
var sleep = (ms) =>
|
|
1687
|
+
var sleep = (ms) => async((_env, cb) => {
|
|
1688
1688
|
const id = setTimeout(() => cb({ _tag: "Success", value: void 0 }), ms);
|
|
1689
1689
|
return () => clearTimeout(id);
|
|
1690
1690
|
});
|
|
1691
|
-
var timeout = (effect, ms, scope) =>
|
|
1691
|
+
var timeout = (effect, ms, scope) => race(
|
|
1692
1692
|
effect,
|
|
1693
|
-
|
|
1693
|
+
asyncFlatMap(sleep(ms), () => asyncFail({ _tag: "ToolTimeout", timeoutMs: ms })),
|
|
1694
1694
|
scope
|
|
1695
1695
|
);
|
|
1696
1696
|
|
|
@@ -1717,14 +1717,14 @@ var defaultPolicyFor = (action) => {
|
|
|
1717
1717
|
};
|
|
1718
1718
|
var configuredPolicyFor = (action, overrides) => {
|
|
1719
1719
|
const base = defaultPolicyFor(action);
|
|
1720
|
-
const override =
|
|
1720
|
+
const override = overrides?.[action.type];
|
|
1721
1721
|
return {
|
|
1722
1722
|
...base,
|
|
1723
|
-
timeoutMs:
|
|
1724
|
-
retries:
|
|
1723
|
+
timeoutMs: override?.timeoutMs !== void 0 ? Math.max(1, Math.floor(override.timeoutMs)) : base.timeoutMs,
|
|
1724
|
+
retries: override?.retries !== void 0 ? Math.max(0, Math.floor(override.retries)) : base.retries
|
|
1725
1725
|
};
|
|
1726
1726
|
};
|
|
1727
|
-
var runAuthorizedAction = (action, state, scope) =>
|
|
1727
|
+
var runAuthorizedAction = (action, state, scope) => asyncFlatMap(asyncSync((env) => env.toolPolicies), (toolPolicies) => {
|
|
1728
1728
|
const policy = configuredPolicyFor(action, toolPolicies);
|
|
1729
1729
|
return retry(() => timeout(actionToEffect(action, state), policy.timeoutMs, scope), {
|
|
1730
1730
|
times: policy.retries,
|
|
@@ -1736,7 +1736,7 @@ var rejected = (action, reason) => ({
|
|
|
1736
1736
|
action,
|
|
1737
1737
|
reason
|
|
1738
1738
|
});
|
|
1739
|
-
var emitApprovalResolved = (action, state, approved, reason) =>
|
|
1739
|
+
var emitApprovalResolved = (action, state, approved, reason) => asyncFlatMap(
|
|
1740
1740
|
nowMillis(),
|
|
1741
1741
|
(at) => emitAgentEvent({
|
|
1742
1742
|
type: "agent.approval.resolved",
|
|
@@ -1749,10 +1749,10 @@ var emitApprovalResolved = (action, state, approved, reason) => _chunkTGOMLZ65js
|
|
|
1749
1749
|
})
|
|
1750
1750
|
);
|
|
1751
1751
|
var requestApproval = (action, state, decision) => {
|
|
1752
|
-
const defaultAnswer =
|
|
1753
|
-
return
|
|
1752
|
+
const defaultAnswer = decision.defaultAnswer ?? "reject";
|
|
1753
|
+
return asyncFlatMap(
|
|
1754
1754
|
nowMillis(),
|
|
1755
|
-
(at) =>
|
|
1755
|
+
(at) => asyncFlatMap(
|
|
1756
1756
|
emitAgentEvent({
|
|
1757
1757
|
type: "agent.approval.requested",
|
|
1758
1758
|
action,
|
|
@@ -1763,15 +1763,15 @@ var requestApproval = (action, state, decision) => {
|
|
|
1763
1763
|
defaultAnswer,
|
|
1764
1764
|
at
|
|
1765
1765
|
}),
|
|
1766
|
-
() =>
|
|
1766
|
+
() => asyncFlatMap(service("approvals"), (approvals) => {
|
|
1767
1767
|
if (!approvals) {
|
|
1768
1768
|
const reason = "No approval service configured.";
|
|
1769
|
-
return
|
|
1769
|
+
return asyncFlatMap(
|
|
1770
1770
|
emitApprovalResolved(action, state, false, reason),
|
|
1771
|
-
() =>
|
|
1771
|
+
() => asyncFail(rejected(action, reason))
|
|
1772
1772
|
);
|
|
1773
1773
|
}
|
|
1774
|
-
return
|
|
1774
|
+
return asyncFlatMap(
|
|
1775
1775
|
approvals.request({
|
|
1776
1776
|
action,
|
|
1777
1777
|
state,
|
|
@@ -1781,15 +1781,15 @@ var requestApproval = (action, state, decision) => {
|
|
|
1781
1781
|
}),
|
|
1782
1782
|
(response) => {
|
|
1783
1783
|
if (response.type === "approved") {
|
|
1784
|
-
return
|
|
1784
|
+
return asyncFlatMap(
|
|
1785
1785
|
emitApprovalResolved(action, state, true, void 0),
|
|
1786
|
-
() =>
|
|
1786
|
+
() => asyncSucceed(void 0)
|
|
1787
1787
|
);
|
|
1788
1788
|
}
|
|
1789
|
-
const reason =
|
|
1790
|
-
return
|
|
1789
|
+
const reason = response.reason ?? "Approval rejected.";
|
|
1790
|
+
return asyncFlatMap(
|
|
1791
1791
|
emitApprovalResolved(action, state, false, reason),
|
|
1792
|
-
() =>
|
|
1792
|
+
() => asyncFail(rejected(action, reason))
|
|
1793
1793
|
);
|
|
1794
1794
|
}
|
|
1795
1795
|
);
|
|
@@ -1797,18 +1797,18 @@ var requestApproval = (action, state, decision) => {
|
|
|
1797
1797
|
)
|
|
1798
1798
|
);
|
|
1799
1799
|
};
|
|
1800
|
-
var invokeAction = (action, state, scope) =>
|
|
1800
|
+
var invokeAction = (action, state, scope) => asyncFlatMap(
|
|
1801
1801
|
service("permissions"),
|
|
1802
|
-
(permissions) =>
|
|
1802
|
+
(permissions) => asyncFlatMap(permissions.check(action, state), (decision) => {
|
|
1803
1803
|
if (decision.type === "deny") {
|
|
1804
|
-
return
|
|
1804
|
+
return asyncFail({
|
|
1805
1805
|
_tag: "PermissionDenied",
|
|
1806
1806
|
action,
|
|
1807
1807
|
reason: decision.reason
|
|
1808
1808
|
});
|
|
1809
1809
|
}
|
|
1810
1810
|
if (decision.type === "ask") {
|
|
1811
|
-
return
|
|
1811
|
+
return asyncFlatMap(
|
|
1812
1812
|
requestApproval(action, state, decision),
|
|
1813
1813
|
() => runAuthorizedAction(action, state, scope)
|
|
1814
1814
|
);
|
|
@@ -1818,9 +1818,9 @@ var invokeAction = (action, state, scope) => _chunkTGOMLZ65js.asyncFlatMap.call(
|
|
|
1818
1818
|
);
|
|
1819
1819
|
|
|
1820
1820
|
// src/agent/core/runAgent.ts
|
|
1821
|
-
var executeAction = (action, state, scope) =>
|
|
1821
|
+
var executeAction = (action, state, scope) => asyncFlatMap(
|
|
1822
1822
|
nowMillis(),
|
|
1823
|
-
(startedAt) =>
|
|
1823
|
+
(startedAt) => asyncFlatMap(
|
|
1824
1824
|
emitAgentEvent({
|
|
1825
1825
|
type: "agent.action.started",
|
|
1826
1826
|
action,
|
|
@@ -1828,9 +1828,9 @@ var executeAction = (action, state, scope) => _chunkTGOMLZ65js.asyncFlatMap.call
|
|
|
1828
1828
|
phase: state.phase,
|
|
1829
1829
|
at: startedAt
|
|
1830
1830
|
}),
|
|
1831
|
-
() =>
|
|
1831
|
+
() => asyncFold(
|
|
1832
1832
|
invokeAction(action, state, scope),
|
|
1833
|
-
(error) =>
|
|
1833
|
+
(error) => asyncFlatMap(nowMillis(), (endedAt) => {
|
|
1834
1834
|
const specific = errorEventFor(action, state, error, endedAt);
|
|
1835
1835
|
const events = [
|
|
1836
1836
|
...specific ? [specific] : [],
|
|
@@ -1844,14 +1844,14 @@ var executeAction = (action, state, scope) => _chunkTGOMLZ65js.asyncFlatMap.call
|
|
|
1844
1844
|
at: endedAt
|
|
1845
1845
|
}
|
|
1846
1846
|
];
|
|
1847
|
-
return
|
|
1847
|
+
return asyncFlatMap(
|
|
1848
1848
|
emitAgentEvents(events),
|
|
1849
|
-
() =>
|
|
1849
|
+
() => asyncSucceed({ type: "agent.error", error })
|
|
1850
1850
|
);
|
|
1851
1851
|
}),
|
|
1852
|
-
(observation) =>
|
|
1852
|
+
(observation) => asyncFlatMap(
|
|
1853
1853
|
nowMillis(),
|
|
1854
|
-
(endedAt) =>
|
|
1854
|
+
(endedAt) => asyncFlatMap(
|
|
1855
1855
|
emitAgentEvent({
|
|
1856
1856
|
type: "agent.action.completed",
|
|
1857
1857
|
action,
|
|
@@ -1861,13 +1861,13 @@ var executeAction = (action, state, scope) => _chunkTGOMLZ65js.asyncFlatMap.call
|
|
|
1861
1861
|
durationMs: endedAt - startedAt,
|
|
1862
1862
|
at: endedAt
|
|
1863
1863
|
}),
|
|
1864
|
-
() =>
|
|
1864
|
+
() => asyncSucceed(observation)
|
|
1865
1865
|
)
|
|
1866
1866
|
)
|
|
1867
1867
|
)
|
|
1868
1868
|
)
|
|
1869
1869
|
);
|
|
1870
|
-
var recordObservation = (next, observation) =>
|
|
1870
|
+
var recordObservation = (next, observation) => asyncFlatMap(nowMillis(), (at) => {
|
|
1871
1871
|
const specific = observationEventFor(next, observation, at);
|
|
1872
1872
|
const events = [
|
|
1873
1873
|
{
|
|
@@ -1883,9 +1883,9 @@ var recordObservation = (next, observation) => _chunkTGOMLZ65js.asyncFlatMap.cal
|
|
|
1883
1883
|
});
|
|
1884
1884
|
var runLoop = (state, scope, runStartedAt) => {
|
|
1885
1885
|
if (isTerminal(state)) {
|
|
1886
|
-
return
|
|
1886
|
+
return asyncFlatMap(
|
|
1887
1887
|
nowMillis(),
|
|
1888
|
-
(at) =>
|
|
1888
|
+
(at) => asyncFlatMap(
|
|
1889
1889
|
emitAgentEvent({
|
|
1890
1890
|
type: "agent.run.completed",
|
|
1891
1891
|
goal: state.goal,
|
|
@@ -1895,26 +1895,26 @@ var runLoop = (state, scope, runStartedAt) => {
|
|
|
1895
1895
|
durationMs: at - runStartedAt,
|
|
1896
1896
|
at
|
|
1897
1897
|
}),
|
|
1898
|
-
() =>
|
|
1898
|
+
() => asyncSucceed(state)
|
|
1899
1899
|
)
|
|
1900
1900
|
);
|
|
1901
1901
|
}
|
|
1902
|
-
return
|
|
1902
|
+
return asyncFlatMap(
|
|
1903
1903
|
decideNextAction(state),
|
|
1904
|
-
(action) =>
|
|
1904
|
+
(action) => asyncFlatMap(executeAction(action, state, scope), (observation) => {
|
|
1905
1905
|
const next = reduceAgentState(state, observation);
|
|
1906
|
-
return
|
|
1906
|
+
return asyncFlatMap(
|
|
1907
1907
|
recordObservation(next, observation),
|
|
1908
1908
|
() => runLoop(next, scope, runStartedAt)
|
|
1909
1909
|
);
|
|
1910
1910
|
})
|
|
1911
1911
|
);
|
|
1912
1912
|
};
|
|
1913
|
-
var runAgent = (runtime, goal) =>
|
|
1913
|
+
var runAgent = (runtime, goal) => withScopeAsync(
|
|
1914
1914
|
runtime,
|
|
1915
|
-
(scope) =>
|
|
1915
|
+
(scope) => asyncFlatMap(
|
|
1916
1916
|
nowMillis(),
|
|
1917
|
-
(startedAt) =>
|
|
1917
|
+
(startedAt) => asyncFlatMap(
|
|
1918
1918
|
emitAgentEvent({ type: "agent.run.started", goal, at: startedAt }),
|
|
1919
1919
|
() => runLoop(initialAgentState(goal), scope, startedAt)
|
|
1920
1920
|
)
|
|
@@ -2018,31 +2018,31 @@ var matchesPattern = (command, pattern) => {
|
|
|
2018
2018
|
const re = new RegExp(`^${normalizedPattern.split("*").map(escapeRegExp).join(".*")}$`);
|
|
2019
2019
|
return re.test(normalizedCommand);
|
|
2020
2020
|
};
|
|
2021
|
-
var matchAny = (command, patterns) => Boolean(
|
|
2021
|
+
var matchAny = (command, patterns) => Boolean(patterns?.some((pattern) => matchesPattern(command, pattern)));
|
|
2022
2022
|
var allow = () => ({ type: "allow" });
|
|
2023
2023
|
var deny = (reason) => ({ type: "deny", reason });
|
|
2024
2024
|
var ask = (reason, risk, defaultAnswer = "reject") => ({ type: "ask", reason, risk, defaultAnswer });
|
|
2025
2025
|
var describeCommand = (action) => action.type === "shell.exec" ? action.command.join(" ") : action.type;
|
|
2026
2026
|
var shellAskRulePattern = (rule) => typeof rule === "string" ? rule : rule.pattern;
|
|
2027
2027
|
var shellAskDecision = (command, rules) => {
|
|
2028
|
-
const rule =
|
|
2028
|
+
const rule = rules?.find((candidate) => matchesPattern(command, shellAskRulePattern(candidate)));
|
|
2029
2029
|
if (!rule) return void 0;
|
|
2030
2030
|
if (typeof rule === "string") {
|
|
2031
2031
|
return ask(`Run command: ${shellCommandText(command)}`, "high", "reject");
|
|
2032
2032
|
}
|
|
2033
2033
|
return ask(
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2034
|
+
rule.reason ?? `Run command: ${shellCommandText(command)}`,
|
|
2035
|
+
rule.risk ?? "high",
|
|
2036
|
+
rule.defaultAnswer ?? "reject"
|
|
2037
2037
|
);
|
|
2038
2038
|
};
|
|
2039
2039
|
var configuredShellAllowPatterns = (config) => [
|
|
2040
|
-
...
|
|
2041
|
-
...
|
|
2040
|
+
...config?.inheritDefaults === false ? [] : DEFAULT_SAFE_SHELL_PATTERNS,
|
|
2041
|
+
...config?.allow ?? []
|
|
2042
2042
|
];
|
|
2043
2043
|
var shellDecisionFromConfig = (command, config) => {
|
|
2044
|
-
if (matchAny(command,
|
|
2045
|
-
const askDecision = shellAskDecision(command,
|
|
2044
|
+
if (matchAny(command, config?.deny)) return deny(`Command denied by policy: ${shellCommandText(command)}`);
|
|
2045
|
+
const askDecision = shellAskDecision(command, config?.ask);
|
|
2046
2046
|
if (askDecision) return askDecision;
|
|
2047
2047
|
if (matchAny(command, configuredShellAllowPatterns(config))) return allow();
|
|
2048
2048
|
return void 0;
|
|
@@ -2051,10 +2051,10 @@ var defaultPatchMutationReason = (action) => action.type === "patch.rollback" ?
|
|
|
2051
2051
|
var patchApplyDecisionFromConfig = (action, config) => {
|
|
2052
2052
|
const defaultReason = defaultPatchMutationReason(action);
|
|
2053
2053
|
if (!config) return ask(defaultReason, "high", "reject");
|
|
2054
|
-
const decision = typeof config === "string" ? config :
|
|
2055
|
-
const reason = typeof config === "string" ? defaultReason :
|
|
2056
|
-
const risk = typeof config === "string" ? "high" :
|
|
2057
|
-
const defaultAnswer = typeof config === "string" ? "reject" :
|
|
2054
|
+
const decision = typeof config === "string" ? config : config.decision ?? "ask";
|
|
2055
|
+
const reason = typeof config === "string" ? defaultReason : config.reason ?? defaultReason;
|
|
2056
|
+
const risk = typeof config === "string" ? "high" : config.risk ?? "high";
|
|
2057
|
+
const defaultAnswer = typeof config === "string" ? "reject" : config.defaultAnswer ?? "reject";
|
|
2058
2058
|
if (decision === "allow") return allow();
|
|
2059
2059
|
if (decision === "deny") return deny(reason);
|
|
2060
2060
|
return ask(reason, risk, defaultAnswer);
|
|
@@ -2064,45 +2064,45 @@ var makeConfiguredPermissions = (config = {}) => ({
|
|
|
2064
2064
|
switch (state.goal.mode) {
|
|
2065
2065
|
case "read-only": {
|
|
2066
2066
|
if (action.type === "fs.readFile" || action.type === "fs.exists" || action.type === "fs.searchText" || action.type === "llm.complete" || action.type === "agent.finish" || action.type === "agent.fail") {
|
|
2067
|
-
return
|
|
2067
|
+
return asyncSucceed(allow());
|
|
2068
2068
|
}
|
|
2069
|
-
return
|
|
2069
|
+
return asyncSucceed(deny(`Action ${action.type} is not allowed in read-only mode`));
|
|
2070
2070
|
}
|
|
2071
2071
|
case "propose": {
|
|
2072
2072
|
if (action.type === "shell.exec") {
|
|
2073
2073
|
const decision = shellDecisionFromConfig(action.command, config.shell);
|
|
2074
|
-
return
|
|
2075
|
-
|
|
2074
|
+
return asyncSucceed(
|
|
2075
|
+
decision ?? deny(`Command not whitelisted: ${action.command.join(" ")}`)
|
|
2076
2076
|
);
|
|
2077
2077
|
}
|
|
2078
2078
|
if (action.type === "patch.apply" || action.type === "patch.rollback") {
|
|
2079
|
-
return
|
|
2079
|
+
return asyncSucceed(deny(`${action.type} is not allowed in propose mode; use write mode or --apply.`));
|
|
2080
2080
|
}
|
|
2081
|
-
return
|
|
2081
|
+
return asyncSucceed(allow());
|
|
2082
2082
|
}
|
|
2083
2083
|
case "write": {
|
|
2084
2084
|
if (action.type === "shell.exec") {
|
|
2085
2085
|
const decision = shellDecisionFromConfig(action.command, config.shell);
|
|
2086
|
-
return
|
|
2087
|
-
|
|
2086
|
+
return asyncSucceed(
|
|
2087
|
+
decision ?? deny(`Command not whitelisted: ${action.command.join(" ")}`)
|
|
2088
2088
|
);
|
|
2089
2089
|
}
|
|
2090
2090
|
if (action.type === "patch.apply" || action.type === "patch.rollback") {
|
|
2091
|
-
return
|
|
2091
|
+
return asyncSucceed(patchApplyDecisionFromConfig(action, config.patchApply));
|
|
2092
2092
|
}
|
|
2093
|
-
return
|
|
2093
|
+
return asyncSucceed(allow());
|
|
2094
2094
|
}
|
|
2095
2095
|
case "autonomous": {
|
|
2096
2096
|
if (action.type === "patch.apply" || action.type === "patch.rollback") {
|
|
2097
|
-
return
|
|
2097
|
+
return asyncSucceed(patchApplyDecisionFromConfig(action, config.patchApply));
|
|
2098
2098
|
}
|
|
2099
2099
|
if (action.type === "shell.exec") {
|
|
2100
2100
|
const decision = shellDecisionFromConfig(action.command, config.shell);
|
|
2101
|
-
return
|
|
2102
|
-
|
|
2101
|
+
return asyncSucceed(
|
|
2102
|
+
decision ?? ask(`Run non-whitelisted command: ${describeCommand(action)}`, "high", "reject")
|
|
2103
2103
|
);
|
|
2104
2104
|
}
|
|
2105
|
-
return
|
|
2105
|
+
return asyncSucceed(allow());
|
|
2106
2106
|
}
|
|
2107
2107
|
}
|
|
2108
2108
|
}
|
|
@@ -2111,25 +2111,25 @@ var defaultPermissions = makeConfiguredPermissions();
|
|
|
2111
2111
|
|
|
2112
2112
|
// src/agent/tools/approvals.ts
|
|
2113
2113
|
var autoApproveApprovals = {
|
|
2114
|
-
request: () =>
|
|
2114
|
+
request: () => asyncSucceed({ type: "approved" })
|
|
2115
2115
|
};
|
|
2116
2116
|
var makeAutoDenyApprovals = (reason = "Approval denied by non-interactive policy.") => ({
|
|
2117
|
-
request: () =>
|
|
2117
|
+
request: () => asyncSucceed({ type: "rejected", reason })
|
|
2118
2118
|
});
|
|
2119
2119
|
|
|
2120
2120
|
// src/agent/node/nodeShell.ts
|
|
2121
2121
|
var dynamicImport = new Function("specifier", "return import(specifier)");
|
|
2122
2122
|
var chunkToString = (chunk) => {
|
|
2123
|
-
const maybeToString =
|
|
2123
|
+
const maybeToString = chunk?.toString;
|
|
2124
2124
|
return typeof maybeToString === "function" ? maybeToString.call(chunk, "utf8") : String(chunk);
|
|
2125
2125
|
};
|
|
2126
2126
|
var NodeShell = {
|
|
2127
|
-
exec: (command, options) =>
|
|
2127
|
+
exec: (command, options) => async((_env, cb) => {
|
|
2128
2128
|
const [bin, ...args] = command;
|
|
2129
2129
|
if (!bin) {
|
|
2130
2130
|
cb(
|
|
2131
|
-
|
|
2132
|
-
|
|
2131
|
+
Exit.failCause(
|
|
2132
|
+
Cause.fail({
|
|
2133
2133
|
_tag: "ShellError",
|
|
2134
2134
|
operation: "exec",
|
|
2135
2135
|
command,
|
|
@@ -2150,18 +2150,18 @@ var NodeShell = {
|
|
|
2150
2150
|
shell: false,
|
|
2151
2151
|
stdio: ["pipe", "pipe", "pipe"]
|
|
2152
2152
|
});
|
|
2153
|
-
|
|
2153
|
+
child.stdout?.on("data", (chunk) => {
|
|
2154
2154
|
stdout += chunkToString(chunk);
|
|
2155
|
-
})
|
|
2156
|
-
|
|
2155
|
+
});
|
|
2156
|
+
child.stderr?.on("data", (chunk) => {
|
|
2157
2157
|
stderr += chunkToString(chunk);
|
|
2158
|
-
})
|
|
2158
|
+
});
|
|
2159
2159
|
child.on("error", (cause) => {
|
|
2160
2160
|
if (done) return;
|
|
2161
2161
|
done = true;
|
|
2162
2162
|
cb(
|
|
2163
|
-
|
|
2164
|
-
|
|
2163
|
+
Exit.failCause(
|
|
2164
|
+
Cause.fail({
|
|
2165
2165
|
_tag: "ShellError",
|
|
2166
2166
|
operation: "exec",
|
|
2167
2167
|
command,
|
|
@@ -2174,24 +2174,24 @@ var NodeShell = {
|
|
|
2174
2174
|
if (done) return;
|
|
2175
2175
|
done = true;
|
|
2176
2176
|
cb(
|
|
2177
|
-
|
|
2178
|
-
exitCode:
|
|
2177
|
+
Exit.succeed({
|
|
2178
|
+
exitCode: code ?? 1,
|
|
2179
2179
|
stdout,
|
|
2180
2180
|
stderr
|
|
2181
2181
|
})
|
|
2182
2182
|
);
|
|
2183
2183
|
});
|
|
2184
2184
|
if (options.stdin !== void 0) {
|
|
2185
|
-
|
|
2185
|
+
child.stdin?.end(options.stdin);
|
|
2186
2186
|
} else {
|
|
2187
|
-
|
|
2187
|
+
child.stdin?.end();
|
|
2188
2188
|
}
|
|
2189
2189
|
}).catch((cause) => {
|
|
2190
2190
|
if (done) return;
|
|
2191
2191
|
done = true;
|
|
2192
2192
|
cb(
|
|
2193
|
-
|
|
2194
|
-
|
|
2193
|
+
Exit.failCause(
|
|
2194
|
+
Cause.fail({
|
|
2195
2195
|
_tag: "ShellError",
|
|
2196
2196
|
operation: "exec",
|
|
2197
2197
|
command,
|
|
@@ -2203,7 +2203,7 @@ var NodeShell = {
|
|
|
2203
2203
|
return () => {
|
|
2204
2204
|
if (done) return;
|
|
2205
2205
|
done = true;
|
|
2206
|
-
|
|
2206
|
+
child?.kill?.("SIGTERM");
|
|
2207
2207
|
};
|
|
2208
2208
|
})
|
|
2209
2209
|
};
|
|
@@ -2215,28 +2215,28 @@ var parseRipgrep = (stdout) => stdout.split("\n").filter(Boolean).map((line) =>
|
|
|
2215
2215
|
return { path, line: Number(lineNo), text: rest.join(":") };
|
|
2216
2216
|
});
|
|
2217
2217
|
var makeNodeFileSystem = (shell) => ({
|
|
2218
|
-
readFile: (path) =>
|
|
2219
|
-
|
|
2218
|
+
readFile: (path) => fromPromiseAbortable(
|
|
2219
|
+
async (signal) => {
|
|
2220
2220
|
const { readFile } = await dynamicImport2("node:fs/promises");
|
|
2221
2221
|
return readFile(path, { encoding: "utf8", signal });
|
|
2222
2222
|
},
|
|
2223
2223
|
(cause) => ({ _tag: "FsError", operation: "readFile", cause })
|
|
2224
2224
|
),
|
|
2225
|
-
exists: (path) =>
|
|
2226
|
-
|
|
2225
|
+
exists: (path) => fromPromiseAbortable(
|
|
2226
|
+
async (signal) => {
|
|
2227
2227
|
if (signal.aborted) return false;
|
|
2228
2228
|
const { stat } = await dynamicImport2("node:fs/promises");
|
|
2229
2229
|
if (signal.aborted) return false;
|
|
2230
2230
|
try {
|
|
2231
2231
|
await stat(path);
|
|
2232
2232
|
return true;
|
|
2233
|
-
} catch
|
|
2233
|
+
} catch {
|
|
2234
2234
|
return false;
|
|
2235
2235
|
}
|
|
2236
2236
|
},
|
|
2237
2237
|
(cause) => ({ _tag: "FsError", operation: "exists", cause })
|
|
2238
2238
|
),
|
|
2239
|
-
searchText: (cwd, query, options) =>
|
|
2239
|
+
searchText: (cwd, query, options) => asyncFlatMap(
|
|
2240
2240
|
shell.exec(
|
|
2241
2241
|
[
|
|
2242
2242
|
"rg",
|
|
@@ -2247,7 +2247,7 @@ var makeNodeFileSystem = (shell) => ({
|
|
|
2247
2247
|
"never",
|
|
2248
2248
|
"--max-count",
|
|
2249
2249
|
"5",
|
|
2250
|
-
...
|
|
2250
|
+
...options?.globs?.flatMap((glob) => ["--glob", glob]) ?? [],
|
|
2251
2251
|
"--",
|
|
2252
2252
|
query,
|
|
2253
2253
|
"."
|
|
@@ -2256,27 +2256,27 @@ var makeNodeFileSystem = (shell) => ({
|
|
|
2256
2256
|
),
|
|
2257
2257
|
(result) => {
|
|
2258
2258
|
if (result.exitCode > 1) {
|
|
2259
|
-
return
|
|
2259
|
+
return asyncFail({
|
|
2260
2260
|
_tag: "FsError",
|
|
2261
2261
|
operation: "searchText",
|
|
2262
2262
|
cause: result.stderr
|
|
2263
2263
|
});
|
|
2264
2264
|
}
|
|
2265
|
-
return
|
|
2265
|
+
return asyncSucceed(parseRipgrep(result.stdout));
|
|
2266
2266
|
}
|
|
2267
2267
|
)
|
|
2268
2268
|
});
|
|
2269
2269
|
|
|
2270
2270
|
// src/agent/node/nodePatchService.ts
|
|
2271
2271
|
var validatePatchTargets = (cwd, paths) => paths.reduce(
|
|
2272
|
-
(acc, path) =>
|
|
2272
|
+
(acc, path) => asyncFlatMap(
|
|
2273
2273
|
acc,
|
|
2274
|
-
(validated) =>
|
|
2274
|
+
(validated) => asyncFlatMap(
|
|
2275
2275
|
resolveWorkspacePath(cwd, path),
|
|
2276
|
-
() =>
|
|
2276
|
+
() => asyncSucceed([...validated, path])
|
|
2277
2277
|
)
|
|
2278
2278
|
),
|
|
2279
|
-
|
|
2279
|
+
asyncSucceed([])
|
|
2280
2280
|
);
|
|
2281
2281
|
var patchFailure = (operation, cause, patch) => ({
|
|
2282
2282
|
_tag: "PatchError",
|
|
@@ -2286,13 +2286,13 @@ var patchFailure = (operation, cause, patch) => ({
|
|
|
2286
2286
|
});
|
|
2287
2287
|
var makeNodePatchService = (shell) => {
|
|
2288
2288
|
const runGitApply = (cwd, rawPatch, reverse) => {
|
|
2289
|
-
const patch =
|
|
2289
|
+
const patch = extractUnifiedDiff(rawPatch) ?? rawPatch.trim();
|
|
2290
2290
|
const changedFiles = extractPatchPaths(patch);
|
|
2291
2291
|
const stdin = `${patch.trim()}
|
|
2292
2292
|
`;
|
|
2293
2293
|
const operation = reverse ? "rollback" : "apply";
|
|
2294
2294
|
if (!patch || !changedFiles.length) {
|
|
2295
|
-
return
|
|
2295
|
+
return asyncFail(
|
|
2296
2296
|
patchFailure("extract", "No unified diff with workspace-scoped paths was found.", rawPatch)
|
|
2297
2297
|
);
|
|
2298
2298
|
}
|
|
@@ -2313,13 +2313,13 @@ var makeNodePatchService = (shell) => {
|
|
|
2313
2313
|
"--whitespace=nowarn",
|
|
2314
2314
|
"-"
|
|
2315
2315
|
];
|
|
2316
|
-
return
|
|
2316
|
+
return asyncFlatMap(
|
|
2317
2317
|
validatePatchTargets(cwd, changedFiles),
|
|
2318
|
-
() =>
|
|
2318
|
+
() => asyncFlatMap(
|
|
2319
2319
|
shell.exec(checkArgs, { cwd, stdin }),
|
|
2320
2320
|
(checkResult) => {
|
|
2321
2321
|
if (checkResult.exitCode !== 0) {
|
|
2322
|
-
return
|
|
2322
|
+
return asyncFail(
|
|
2323
2323
|
patchFailure(
|
|
2324
2324
|
`${operation}.check`,
|
|
2325
2325
|
checkResult.stderr || checkResult.stdout || `git apply --check exited with ${checkResult.exitCode}`,
|
|
@@ -2327,11 +2327,11 @@ var makeNodePatchService = (shell) => {
|
|
|
2327
2327
|
)
|
|
2328
2328
|
);
|
|
2329
2329
|
}
|
|
2330
|
-
return
|
|
2330
|
+
return asyncFlatMap(
|
|
2331
2331
|
shell.exec(applyArgs, { cwd, stdin }),
|
|
2332
2332
|
(applyResult) => {
|
|
2333
2333
|
if (applyResult.exitCode !== 0) {
|
|
2334
|
-
return
|
|
2334
|
+
return asyncFail(
|
|
2335
2335
|
patchFailure(
|
|
2336
2336
|
operation,
|
|
2337
2337
|
applyResult.stderr || applyResult.stdout || `git apply exited with ${applyResult.exitCode}`,
|
|
@@ -2339,7 +2339,7 @@ var makeNodePatchService = (shell) => {
|
|
|
2339
2339
|
)
|
|
2340
2340
|
);
|
|
2341
2341
|
}
|
|
2342
|
-
return
|
|
2342
|
+
return asyncSucceed({ changedFiles });
|
|
2343
2343
|
}
|
|
2344
2344
|
);
|
|
2345
2345
|
}
|
|
@@ -2554,15 +2554,15 @@ var validateAgentConfig = (config, sourcePath) => {
|
|
|
2554
2554
|
}
|
|
2555
2555
|
return config;
|
|
2556
2556
|
};
|
|
2557
|
-
var isFile =
|
|
2557
|
+
var isFile = async (path) => {
|
|
2558
2558
|
const { stat } = await dynamicImport3("node:fs/promises");
|
|
2559
2559
|
try {
|
|
2560
2560
|
return (await stat(path)).isFile();
|
|
2561
|
-
} catch
|
|
2561
|
+
} catch {
|
|
2562
2562
|
return false;
|
|
2563
2563
|
}
|
|
2564
2564
|
};
|
|
2565
|
-
var findConfigPath =
|
|
2565
|
+
var findConfigPath = async (cwd) => {
|
|
2566
2566
|
const nodePath = await dynamicImport3("node:path");
|
|
2567
2567
|
let current = nodePath.resolve(cwd);
|
|
2568
2568
|
while (true) {
|
|
@@ -2575,7 +2575,7 @@ var findConfigPath = _chunkTGOMLZ65js.async.call(void 0, cwd) => {
|
|
|
2575
2575
|
current = parent;
|
|
2576
2576
|
}
|
|
2577
2577
|
};
|
|
2578
|
-
var readConfigFile =
|
|
2578
|
+
var readConfigFile = async (path) => {
|
|
2579
2579
|
const { readFile } = await dynamicImport3("node:fs/promises");
|
|
2580
2580
|
const raw = String(await readFile(path, "utf8")).replace(/^\uFEFF/, "");
|
|
2581
2581
|
try {
|
|
@@ -2587,7 +2587,7 @@ var readConfigFile = _chunkTGOMLZ65js.async.call(void 0, path) => {
|
|
|
2587
2587
|
throw error;
|
|
2588
2588
|
}
|
|
2589
2589
|
};
|
|
2590
|
-
var loadNodeAgentConfig =
|
|
2590
|
+
var loadNodeAgentConfig = async (options) => {
|
|
2591
2591
|
if (options.noConfig) return { config: {} };
|
|
2592
2592
|
const nodePath = await dynamicImport3("node:path");
|
|
2593
2593
|
if (options.configPath) {
|
|
@@ -2601,10 +2601,10 @@ var loadNodeAgentConfig = _chunkTGOMLZ65js.async.call(void 0, options) => {
|
|
|
2601
2601
|
};
|
|
2602
2602
|
|
|
2603
2603
|
// src/agent/llm/openAICompatible.ts
|
|
2604
|
-
var extractText = (json) =>
|
|
2604
|
+
var extractText = (json) => json?.choices?.[0]?.message?.content ?? json?.output_text ?? json?.content?.[0]?.text ?? JSON.stringify(json);
|
|
2605
2605
|
var makeOpenAICompatibleLLM = (config) => ({
|
|
2606
|
-
complete: (request) =>
|
|
2607
|
-
|
|
2606
|
+
complete: (request) => fromPromiseAbortable(
|
|
2607
|
+
async (signal) => {
|
|
2608
2608
|
const res = await fetch(config.endpoint, {
|
|
2609
2609
|
method: "POST",
|
|
2610
2610
|
signal,
|
|
@@ -2638,9 +2638,9 @@ var withoutTrailingSlash = (value) => {
|
|
|
2638
2638
|
var normalizeModelName = (model) => model.startsWith("models/") ? model : `models/${model}`;
|
|
2639
2639
|
var makeGenerateContentEndpoint = (config) => {
|
|
2640
2640
|
if (config.endpoint) return config.endpoint;
|
|
2641
|
-
const baseUrl = withoutTrailingSlash(
|
|
2642
|
-
const apiVersion =
|
|
2643
|
-
const model = normalizeModelName(
|
|
2641
|
+
const baseUrl = withoutTrailingSlash(config.baseUrl ?? DEFAULT_BASE_URL);
|
|
2642
|
+
const apiVersion = config.apiVersion ?? DEFAULT_API_VERSION;
|
|
2643
|
+
const model = normalizeModelName(config.model ?? DEFAULT_MODEL);
|
|
2644
2644
|
return `${baseUrl}/${apiVersion}/${model}:generateContent`;
|
|
2645
2645
|
};
|
|
2646
2646
|
var optionalNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
@@ -2653,7 +2653,7 @@ var makeRequestBody = (request, config) => {
|
|
|
2653
2653
|
maxOutputTokens: optionalNumber(config.maxOutputTokens),
|
|
2654
2654
|
stopSequences: config.stopSequences,
|
|
2655
2655
|
responseMimeType: config.responseMimeType,
|
|
2656
|
-
...
|
|
2656
|
+
...config.extraGenerationConfig ?? {}
|
|
2657
2657
|
});
|
|
2658
2658
|
return omitUndefined({
|
|
2659
2659
|
contents: [
|
|
@@ -2669,34 +2669,34 @@ var makeRequestBody = (request, config) => {
|
|
|
2669
2669
|
});
|
|
2670
2670
|
};
|
|
2671
2671
|
var extractGoogleText = (json) => {
|
|
2672
|
-
const text =
|
|
2672
|
+
const text = json.candidates?.flatMap((candidate) => candidate.content?.parts ?? []).map((part) => part.text ?? "").filter(Boolean).join("\n").trim();
|
|
2673
2673
|
if (text) return text;
|
|
2674
|
-
const blockReason =
|
|
2674
|
+
const blockReason = json.promptFeedback?.blockReason;
|
|
2675
2675
|
if (blockReason) {
|
|
2676
|
-
const message =
|
|
2676
|
+
const message = json.promptFeedback?.blockReasonMessage;
|
|
2677
2677
|
throw new Error(`Google Gemini blocked the prompt: ${blockReason}${message ? ` - ${message}` : ""}`);
|
|
2678
2678
|
}
|
|
2679
|
-
const finishReason =
|
|
2679
|
+
const finishReason = json.candidates?.[0]?.finishReason;
|
|
2680
2680
|
if (finishReason) {
|
|
2681
2681
|
throw new Error(`Google Gemini returned no text. finishReason=${finishReason}`);
|
|
2682
2682
|
}
|
|
2683
|
-
if (
|
|
2683
|
+
if (json.error?.message) {
|
|
2684
2684
|
throw new Error(`Google Gemini error: ${json.error.message}`);
|
|
2685
2685
|
}
|
|
2686
2686
|
return JSON.stringify(json);
|
|
2687
2687
|
};
|
|
2688
|
-
var responseErrorMessage =
|
|
2688
|
+
var responseErrorMessage = async (res) => {
|
|
2689
2689
|
const raw = await res.text();
|
|
2690
2690
|
try {
|
|
2691
2691
|
const json = JSON.parse(raw);
|
|
2692
|
-
return
|
|
2693
|
-
} catch
|
|
2692
|
+
return json.error?.message ?? raw;
|
|
2693
|
+
} catch {
|
|
2694
2694
|
return raw;
|
|
2695
2695
|
}
|
|
2696
2696
|
};
|
|
2697
2697
|
var makeGoogleGenerativeAILLM = (config) => ({
|
|
2698
|
-
complete: (request) =>
|
|
2699
|
-
|
|
2698
|
+
complete: (request) => fromPromiseAbortable(
|
|
2699
|
+
async (signal) => {
|
|
2700
2700
|
const res = await fetch(makeGenerateContentEndpoint(config), {
|
|
2701
2701
|
method: "POST",
|
|
2702
2702
|
signal,
|
|
@@ -2726,14 +2726,14 @@ var defaultContent = (request) => [
|
|
|
2726
2726
|
"You can also set BRASS_FAKE_LLM_RESPONSE to provide a deterministic offline response, including a fenced ```diff block."
|
|
2727
2727
|
].join("\n");
|
|
2728
2728
|
var makeFakeLLM = (options = {}) => ({
|
|
2729
|
-
complete: (request) =>
|
|
2730
|
-
content: typeof options.content === "function" ? options.content(request) :
|
|
2729
|
+
complete: (request) => asyncSucceed({
|
|
2730
|
+
content: typeof options.content === "function" ? options.content(request) : options.content ?? defaultContent(request)
|
|
2731
2731
|
})
|
|
2732
2732
|
});
|
|
2733
2733
|
|
|
2734
2734
|
// src/agent/node/nodeWorkspaceDiscovery.ts
|
|
2735
|
-
|
|
2736
|
-
|
|
2735
|
+
import { existsSync, statSync } from "fs";
|
|
2736
|
+
import { dirname, join, resolve } from "path";
|
|
2737
2737
|
var WORKSPACE_MARKERS = [
|
|
2738
2738
|
{ name: ".brass-agent.json", kind: "file" },
|
|
2739
2739
|
{ name: "brass-agent.config.json", kind: "file" },
|
|
@@ -2745,15 +2745,15 @@ var WORKSPACE_MARKERS = [
|
|
|
2745
2745
|
];
|
|
2746
2746
|
var markerExists2 = (path, kind) => {
|
|
2747
2747
|
try {
|
|
2748
|
-
const stat =
|
|
2748
|
+
const stat = statSync(path);
|
|
2749
2749
|
return kind === "directory" ? stat.isDirectory() : stat.isFile();
|
|
2750
|
-
} catch
|
|
2750
|
+
} catch {
|
|
2751
2751
|
return false;
|
|
2752
2752
|
}
|
|
2753
2753
|
};
|
|
2754
2754
|
var firstMarkerIn = (cwd) => {
|
|
2755
2755
|
for (const marker of WORKSPACE_MARKERS) {
|
|
2756
|
-
const markerPath =
|
|
2756
|
+
const markerPath = join(cwd, marker.name);
|
|
2757
2757
|
if (markerExists2(markerPath, marker.kind)) {
|
|
2758
2758
|
return { marker: marker.name, markerPath };
|
|
2759
2759
|
}
|
|
@@ -2761,7 +2761,7 @@ var firstMarkerIn = (cwd) => {
|
|
|
2761
2761
|
return void 0;
|
|
2762
2762
|
};
|
|
2763
2763
|
var discoverNodeWorkspaceRoot = (cwd, options = {}) => {
|
|
2764
|
-
const inputCwd =
|
|
2764
|
+
const inputCwd = resolve(cwd);
|
|
2765
2765
|
if (options.enabled === false) {
|
|
2766
2766
|
return {
|
|
2767
2767
|
inputCwd,
|
|
@@ -2770,7 +2770,7 @@ var discoverNodeWorkspaceRoot = (cwd, options = {}) => {
|
|
|
2770
2770
|
disabled: true
|
|
2771
2771
|
};
|
|
2772
2772
|
}
|
|
2773
|
-
if (!
|
|
2773
|
+
if (!existsSync(inputCwd)) {
|
|
2774
2774
|
return {
|
|
2775
2775
|
inputCwd,
|
|
2776
2776
|
cwd: inputCwd,
|
|
@@ -2789,7 +2789,7 @@ var discoverNodeWorkspaceRoot = (cwd, options = {}) => {
|
|
|
2789
2789
|
changed: current !== inputCwd
|
|
2790
2790
|
};
|
|
2791
2791
|
}
|
|
2792
|
-
const parent =
|
|
2792
|
+
const parent = dirname(current);
|
|
2793
2793
|
if (parent === current) {
|
|
2794
2794
|
return {
|
|
2795
2795
|
inputCwd,
|
|
@@ -2801,79 +2801,79 @@ var discoverNodeWorkspaceRoot = (cwd, options = {}) => {
|
|
|
2801
2801
|
}
|
|
2802
2802
|
};
|
|
2803
2803
|
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2804
|
+
export {
|
|
2805
|
+
initialAgentState,
|
|
2806
|
+
reduceAgentState,
|
|
2807
|
+
isTerminal,
|
|
2808
|
+
extractLikelyFilePaths,
|
|
2809
|
+
deriveContextSearchQueries,
|
|
2810
|
+
describeContextDiscovery,
|
|
2811
|
+
summarizeContextDiscovery,
|
|
2812
|
+
nextContextDiscoveryAction,
|
|
2813
|
+
PROJECT_PROFILE_PROBES,
|
|
2814
|
+
projectProfileProbePending,
|
|
2815
|
+
discoverProjectProfile,
|
|
2816
|
+
describeProjectProfile,
|
|
2817
|
+
PROJECT_LOCKFILE_PROBES,
|
|
2818
|
+
parseProjectPackageJson,
|
|
2819
|
+
nextProjectProbeAction,
|
|
2820
|
+
discoverPackageManager,
|
|
2821
|
+
splitCommand,
|
|
2822
|
+
commandForScript,
|
|
2823
|
+
discoverValidationCommands,
|
|
2824
|
+
nextUnrunValidationCommand,
|
|
2825
|
+
describeCommandDiscovery,
|
|
2826
|
+
patchRepairAttemptsUsed,
|
|
2827
|
+
patchQualitySummary,
|
|
2828
|
+
canRequestPatchRepair,
|
|
2829
|
+
patchValidationStatus,
|
|
2830
|
+
describePatchQuality,
|
|
2831
|
+
rollbackSafetySummary,
|
|
2832
|
+
unappliedPatchStack,
|
|
2833
|
+
latestUnappliedPatch,
|
|
2834
|
+
canAutoRollback,
|
|
2835
|
+
shouldContinueRollbackStack,
|
|
2836
|
+
workspaceValidationStatus,
|
|
2837
|
+
describeRollbackSafety,
|
|
2838
|
+
extractUnifiedDiff,
|
|
2839
|
+
extractPatchPaths,
|
|
2840
|
+
isRedactionEnabled,
|
|
2841
|
+
redactText,
|
|
2842
|
+
inferUserLanguage,
|
|
2843
|
+
responseLanguageName,
|
|
2844
|
+
describeLanguagePolicy,
|
|
2845
|
+
spanishLike,
|
|
2846
|
+
decideNextAction,
|
|
2847
|
+
nowMillis,
|
|
2848
|
+
emitAgentEvent,
|
|
2849
|
+
emitAgentEvents,
|
|
2850
|
+
summarizeAgentAction,
|
|
2851
|
+
summarizeAgentObservation,
|
|
2852
|
+
observationStatus,
|
|
2853
|
+
errorEventFor,
|
|
2854
|
+
observationEventFor,
|
|
2855
|
+
runStatusFor,
|
|
2856
|
+
retry,
|
|
2857
|
+
sleep,
|
|
2858
|
+
timeout,
|
|
2859
|
+
invokeAction,
|
|
2860
|
+
runAgent,
|
|
2861
|
+
isAgentConfigMode,
|
|
2862
|
+
isAgentConfigApprovalMode,
|
|
2863
|
+
isAgentConfigLLMProvider,
|
|
2864
|
+
AGENT_CONFIG_FILE_NAMES,
|
|
2865
|
+
isAgentPreset,
|
|
2866
|
+
goalForAgentPreset,
|
|
2867
|
+
makeConfiguredPermissions,
|
|
2868
|
+
defaultPermissions,
|
|
2869
|
+
autoApproveApprovals,
|
|
2870
|
+
makeAutoDenyApprovals,
|
|
2871
|
+
NodeShell,
|
|
2872
|
+
makeNodeFileSystem,
|
|
2873
|
+
makeNodePatchService,
|
|
2874
|
+
loadNodeAgentConfig,
|
|
2875
|
+
makeOpenAICompatibleLLM,
|
|
2876
|
+
makeGoogleGenerativeAILLM,
|
|
2877
|
+
makeFakeLLM,
|
|
2878
|
+
discoverNodeWorkspaceRoot
|
|
2879
|
+
};
|