open-agents-ai 0.187.508 → 0.187.509
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/index.js +262 -7
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -523505,13 +523505,7 @@ function checkMutateMtimeDelta(intent, cwd4, ctx3, _result) {
|
|
|
523505
523505
|
bestNewest = auxNewest;
|
|
523506
523506
|
}
|
|
523507
523507
|
if (bestNewest <= 0) {
|
|
523508
|
-
return {
|
|
523509
|
-
trustworthy: false,
|
|
523510
|
-
syntheticError: `Command (${intent.verb}) reported success but ${cwd4} contains no files. The action either didn't run or had no effect.`,
|
|
523511
|
-
intentBucket: bucket,
|
|
523512
|
-
outcomeClass: "broken",
|
|
523513
|
-
detail: "no files under cwd after mutate intent"
|
|
523514
|
-
};
|
|
523508
|
+
return { trustworthy: true, intentBucket: bucket, outcomeClass: "unknown", detail: "empty cwd — verifier abstaining" };
|
|
523515
523509
|
}
|
|
523516
523510
|
if (bestNewest < ctx3.startedAt - MTIME_GRACE_MS) {
|
|
523517
523511
|
const ageSec = Math.round(((ctx3.now ? ctx3.now() : Date.now()) - bestNewest) / 1e3);
|
|
@@ -523918,6 +523912,248 @@ var init_postActionVerifier = __esm({
|
|
|
523918
523912
|
}
|
|
523919
523913
|
});
|
|
523920
523914
|
|
|
523915
|
+
// packages/orchestrator/dist/errorClusterTracker.js
|
|
523916
|
+
var errorClusterTracker_exports = {};
|
|
523917
|
+
__export(errorClusterTracker_exports, {
|
|
523918
|
+
ErrorClusterTracker: () => ErrorClusterTracker,
|
|
523919
|
+
parseErrors: () => parseErrors
|
|
523920
|
+
});
|
|
523921
|
+
function parseErrors(output) {
|
|
523922
|
+
if (!output || typeof output !== "string")
|
|
523923
|
+
return [];
|
|
523924
|
+
const seen = /* @__PURE__ */ new Set();
|
|
523925
|
+
const out = [];
|
|
523926
|
+
for (const { re, build } of ERROR_PATTERNS) {
|
|
523927
|
+
re.lastIndex = 0;
|
|
523928
|
+
let m2;
|
|
523929
|
+
while ((m2 = re.exec(output)) !== null) {
|
|
523930
|
+
const err = build(m2);
|
|
523931
|
+
if (!err)
|
|
523932
|
+
continue;
|
|
523933
|
+
const key = `${err.file}|${err.line ?? ""}|${err.col ?? ""}|${err.code}|${err.message.slice(0, 32)}`;
|
|
523934
|
+
if (seen.has(key))
|
|
523935
|
+
continue;
|
|
523936
|
+
seen.add(key);
|
|
523937
|
+
out.push(err);
|
|
523938
|
+
}
|
|
523939
|
+
}
|
|
523940
|
+
return out;
|
|
523941
|
+
}
|
|
523942
|
+
function clusterKey(scope, file, code8) {
|
|
523943
|
+
return `${scope}\0${file}\0${code8}`;
|
|
523944
|
+
}
|
|
523945
|
+
function parseClusterKey(key) {
|
|
523946
|
+
const parts = key.split("\0");
|
|
523947
|
+
return { file: parts[1] ?? "", code: parts[2] ?? "" };
|
|
523948
|
+
}
|
|
523949
|
+
function shortFile(p2) {
|
|
523950
|
+
const parts = p2.split("/");
|
|
523951
|
+
return parts.length <= 2 ? p2 : `…/${parts.slice(-2).join("/")}`;
|
|
523952
|
+
}
|
|
523953
|
+
function formatStagnantLine(c9, critical) {
|
|
523954
|
+
const codeLabel = c9.key.code ? `× ${c9.key.code}` : "× errors";
|
|
523955
|
+
const tag = critical ? "STAGNANT-CRIT" : "STAGNANT";
|
|
523956
|
+
return `${tag}: ${shortFile(c9.key.file)} ${c9.count}${codeLabel} unchanged across ${c9.attemptsSinceCountChange} attempts — per-line edits aren't converging; consider reverting the affected region or rewriting it as a unit`;
|
|
523957
|
+
}
|
|
523958
|
+
var ERROR_PATTERNS, DEFAULTS, ErrorClusterTracker;
|
|
523959
|
+
var init_errorClusterTracker = __esm({
|
|
523960
|
+
"packages/orchestrator/dist/errorClusterTracker.js"() {
|
|
523961
|
+
"use strict";
|
|
523962
|
+
ERROR_PATTERNS = [
|
|
523963
|
+
// Style A: file:line:col: severity[: code]: message
|
|
523964
|
+
// Matches gcc, clang, eslint, golangci-lint, ruby, generic POSIX tools.
|
|
523965
|
+
{
|
|
523966
|
+
re: /^([^\s:()]+):(\d+):(\d+):\s*(error|warning|note)(?::\s*([A-Za-z][\w/-]*))?\s*:?\s*(.*)$/gm,
|
|
523967
|
+
build: (m2) => {
|
|
523968
|
+
const file = m2[1];
|
|
523969
|
+
if (/^https?:\/\//.test(file))
|
|
523970
|
+
return null;
|
|
523971
|
+
return {
|
|
523972
|
+
file,
|
|
523973
|
+
line: parseInt(m2[2], 10),
|
|
523974
|
+
col: parseInt(m2[3], 10),
|
|
523975
|
+
severity: m2[4],
|
|
523976
|
+
code: (m2[5] ?? "").trim(),
|
|
523977
|
+
message: (m2[6] ?? "").trim().slice(0, 240)
|
|
523978
|
+
};
|
|
523979
|
+
}
|
|
523980
|
+
},
|
|
523981
|
+
// Style B: file(line,col): severity CODE: message (TypeScript)
|
|
523982
|
+
{
|
|
523983
|
+
re: /^([^\s(]+):?\s*\((\d+),(\d+)\)\s*:?\s*(error|warning|note)\s+([A-Z]+\d+)\s*:\s*(.*)$/gm,
|
|
523984
|
+
build: (m2) => ({
|
|
523985
|
+
file: m2[1],
|
|
523986
|
+
line: parseInt(m2[2], 10),
|
|
523987
|
+
col: parseInt(m2[3], 10),
|
|
523988
|
+
severity: m2[4],
|
|
523989
|
+
code: m2[5],
|
|
523990
|
+
message: (m2[6] ?? "").trim().slice(0, 240)
|
|
523991
|
+
})
|
|
523992
|
+
},
|
|
523993
|
+
// Style C: error[CODE]: message ... --> file:line:col (Rust-style)
|
|
523994
|
+
{
|
|
523995
|
+
re: /^error(?:\[([A-Z]\d+)\])?:\s*(.+?)\n\s*-->\s*([^\s:]+):(\d+):(\d+)/gms,
|
|
523996
|
+
build: (m2) => ({
|
|
523997
|
+
file: m2[3],
|
|
523998
|
+
line: parseInt(m2[4], 10),
|
|
523999
|
+
col: parseInt(m2[5], 10),
|
|
524000
|
+
severity: "error",
|
|
524001
|
+
code: (m2[1] ?? "").trim(),
|
|
524002
|
+
message: (m2[2] ?? "").trim().slice(0, 240)
|
|
524003
|
+
})
|
|
524004
|
+
},
|
|
524005
|
+
// Style D: FAILED file::test_id [- message] (pytest, similar)
|
|
524006
|
+
{
|
|
524007
|
+
re: /^FAILED\s+([^\s:]+)::([\w\-.[\]/]+)(?:\s+-\s+(.*))?$/gm,
|
|
524008
|
+
build: (m2) => ({
|
|
524009
|
+
file: m2[1],
|
|
524010
|
+
severity: "error",
|
|
524011
|
+
// Treat the test id as the cluster code so a flapping test stays in
|
|
524012
|
+
// its own bucket, while many distinct tests in the same file each
|
|
524013
|
+
// form their own cluster (more accurate than collapsing all
|
|
524014
|
+
// pytest failures in a file into one).
|
|
524015
|
+
code: m2[2],
|
|
524016
|
+
message: (m2[3] ?? "").trim().slice(0, 240)
|
|
524017
|
+
})
|
|
524018
|
+
}
|
|
524019
|
+
];
|
|
524020
|
+
DEFAULTS = {
|
|
524021
|
+
warnAttempts: 3,
|
|
524022
|
+
criticalAttempts: 5,
|
|
524023
|
+
cooldownAttempts: 2,
|
|
524024
|
+
maxClusters: 200
|
|
524025
|
+
};
|
|
524026
|
+
ErrorClusterTracker = class {
|
|
524027
|
+
opts;
|
|
524028
|
+
now;
|
|
524029
|
+
clusters = /* @__PURE__ */ new Map();
|
|
524030
|
+
lastEmittedAt = /* @__PURE__ */ new Map();
|
|
524031
|
+
// key → observations counter at last emit
|
|
524032
|
+
observationCounter = 0;
|
|
524033
|
+
constructor(options2 = {}) {
|
|
524034
|
+
this.opts = { ...DEFAULTS, ...options2 };
|
|
524035
|
+
this.now = options2.now ?? Date.now;
|
|
524036
|
+
}
|
|
524037
|
+
/**
|
|
524038
|
+
* Feed a new tool output into the tracker. Returns the changes for this
|
|
524039
|
+
* observation plus a one-line summary suitable for context injection.
|
|
524040
|
+
*
|
|
524041
|
+
* @param output raw stdout/stderr from the tool
|
|
524042
|
+
* @param toolKey optional caller-supplied scope (e.g. "tsc:/path/to/cwd").
|
|
524043
|
+
* If two distinct tools emit similar errors in the same
|
|
524044
|
+
* file but in different scopes, pass distinct keys to
|
|
524045
|
+
* keep their clusters separate. Default: "" (shared).
|
|
524046
|
+
*/
|
|
524047
|
+
observe(output, toolKey = "") {
|
|
524048
|
+
this.observationCounter++;
|
|
524049
|
+
const errors = parseErrors(output);
|
|
524050
|
+
const observedClusters = /* @__PURE__ */ new Map();
|
|
524051
|
+
for (const e2 of errors) {
|
|
524052
|
+
const key = clusterKey(toolKey, e2.file, e2.code);
|
|
524053
|
+
const cur = observedClusters.get(key);
|
|
524054
|
+
if (cur)
|
|
524055
|
+
cur.count += 1;
|
|
524056
|
+
else
|
|
524057
|
+
observedClusters.set(key, { count: 1, sample: e2.message });
|
|
524058
|
+
}
|
|
524059
|
+
const changes = [];
|
|
524060
|
+
const lines = [];
|
|
524061
|
+
let hasCritical = false;
|
|
524062
|
+
const nowMs = this.now();
|
|
524063
|
+
for (const [key, { count, sample }] of observedClusters) {
|
|
524064
|
+
const prior = this.clusters.get(key);
|
|
524065
|
+
if (!prior) {
|
|
524066
|
+
const ck = parseClusterKey(key);
|
|
524067
|
+
const entry = {
|
|
524068
|
+
key: ck,
|
|
524069
|
+
count,
|
|
524070
|
+
sample,
|
|
524071
|
+
observations: 1,
|
|
524072
|
+
attemptsSinceCountChange: 1,
|
|
524073
|
+
lastUpdated: nowMs,
|
|
524074
|
+
previousCount: 0
|
|
524075
|
+
};
|
|
524076
|
+
this.clusters.set(key, entry);
|
|
524077
|
+
changes.push({ kind: "new", cluster: entry });
|
|
524078
|
+
continue;
|
|
524079
|
+
}
|
|
524080
|
+
prior.observations++;
|
|
524081
|
+
prior.lastUpdated = nowMs;
|
|
524082
|
+
prior.sample = sample;
|
|
524083
|
+
if (count === prior.count) {
|
|
524084
|
+
prior.attemptsSinceCountChange++;
|
|
524085
|
+
} else {
|
|
524086
|
+
prior.previousCount = prior.count;
|
|
524087
|
+
prior.count = count;
|
|
524088
|
+
prior.attemptsSinceCountChange = 1;
|
|
524089
|
+
}
|
|
524090
|
+
if (count > prior.previousCount && prior.attemptsSinceCountChange === 1) {
|
|
524091
|
+
changes.push({ kind: "grown", cluster: prior, from: prior.previousCount, to: count });
|
|
524092
|
+
lines.push(`${shortFile(prior.key.file)}: ${prior.previousCount}→${count}× ${prior.key.code || "errors"} (regressed)`);
|
|
524093
|
+
} else if (count < prior.previousCount && prior.attemptsSinceCountChange === 1) {
|
|
524094
|
+
changes.push({ kind: "shrunk", cluster: prior, from: prior.previousCount, to: count });
|
|
524095
|
+
lines.push(`${shortFile(prior.key.file)}: ${prior.previousCount}→${count}× ${prior.key.code || "errors"} (improving)`);
|
|
524096
|
+
} else if (prior.attemptsSinceCountChange >= this.opts.warnAttempts) {
|
|
524097
|
+
if (this.lastEmittedAt.has(key)) {
|
|
524098
|
+
const last2 = this.lastEmittedAt.get(key);
|
|
524099
|
+
const sinceEmit = this.observationCounter - last2;
|
|
524100
|
+
if (sinceEmit < this.opts.cooldownAttempts)
|
|
524101
|
+
continue;
|
|
524102
|
+
}
|
|
524103
|
+
const isCritical = prior.attemptsSinceCountChange >= this.opts.criticalAttempts;
|
|
524104
|
+
if (isCritical)
|
|
524105
|
+
hasCritical = true;
|
|
524106
|
+
changes.push({
|
|
524107
|
+
kind: "stagnant",
|
|
524108
|
+
cluster: prior,
|
|
524109
|
+
attempts: prior.attemptsSinceCountChange,
|
|
524110
|
+
severity: isCritical ? "critical" : "warn"
|
|
524111
|
+
});
|
|
524112
|
+
lines.push(formatStagnantLine(prior, isCritical));
|
|
524113
|
+
this.lastEmittedAt.set(key, this.observationCounter);
|
|
524114
|
+
}
|
|
524115
|
+
}
|
|
524116
|
+
for (const [key, prior] of [...this.clusters]) {
|
|
524117
|
+
if (observedClusters.has(key))
|
|
524118
|
+
continue;
|
|
524119
|
+
if (prior.count > 0 && nowMs - prior.lastUpdated < 6e4) {
|
|
524120
|
+
changes.push({ kind: "resolved", key: prior.key });
|
|
524121
|
+
lines.push(`${shortFile(prior.key.file)}: ${prior.count}× ${prior.key.code || "errors"} → 0 (resolved)`);
|
|
524122
|
+
this.clusters.delete(key);
|
|
524123
|
+
this.lastEmittedAt.delete(key);
|
|
524124
|
+
}
|
|
524125
|
+
}
|
|
524126
|
+
this.evictIfNeeded();
|
|
524127
|
+
return {
|
|
524128
|
+
changes,
|
|
524129
|
+
summaryLine: lines.length === 0 ? "" : `[ERROR CLUSTERS] ${lines.join(" | ").slice(0, 360)}`,
|
|
524130
|
+
hasCritical
|
|
524131
|
+
};
|
|
524132
|
+
}
|
|
524133
|
+
/** Read-only snapshot of currently tracked clusters (defensive copy). */
|
|
524134
|
+
snapshot() {
|
|
524135
|
+
return [...this.clusters.values()].map((c9) => ({ ...c9, key: { ...c9.key } }));
|
|
524136
|
+
}
|
|
524137
|
+
/** Remove all state — useful at session boundaries. */
|
|
524138
|
+
reset() {
|
|
524139
|
+
this.clusters.clear();
|
|
524140
|
+
this.lastEmittedAt.clear();
|
|
524141
|
+
this.observationCounter = 0;
|
|
524142
|
+
}
|
|
524143
|
+
evictIfNeeded() {
|
|
524144
|
+
if (this.clusters.size <= this.opts.maxClusters)
|
|
524145
|
+
return;
|
|
524146
|
+
const sorted = [...this.clusters.entries()].sort((a2, b) => a2[1].lastUpdated - b[1].lastUpdated);
|
|
524147
|
+
const toEvict = sorted.slice(0, this.clusters.size - this.opts.maxClusters);
|
|
524148
|
+
for (const [key] of toEvict) {
|
|
524149
|
+
this.clusters.delete(key);
|
|
524150
|
+
this.lastEmittedAt.delete(key);
|
|
524151
|
+
}
|
|
524152
|
+
}
|
|
524153
|
+
};
|
|
524154
|
+
}
|
|
524155
|
+
});
|
|
524156
|
+
|
|
523921
524157
|
// packages/orchestrator/dist/agenticRunner.js
|
|
523922
524158
|
import { existsSync as _fsExistsSync, readFileSync as _fsReadFileSync } from "node:fs";
|
|
523923
524159
|
import { join as _pathJoin } from "node:path";
|
|
@@ -528604,6 +528840,25 @@ ${criticDecision.cachedResult.slice(0, 500)}` : `[BLOCKED — the observer confi
|
|
|
528604
528840
|
toolCallLog[_toolLogTailIdx].intentBucket = _verifierResult.intentBucket;
|
|
528605
528841
|
toolCallLog[_toolLogTailIdx].outcomeClass = _verifierResult.outcomeClass;
|
|
528606
528842
|
}
|
|
528843
|
+
if (tc.name === "shell" && (result.output || result.error)) {
|
|
528844
|
+
try {
|
|
528845
|
+
const ecMod = await Promise.resolve().then(() => (init_errorClusterTracker(), errorClusterTracker_exports));
|
|
528846
|
+
if (!this._errorClusterTracker) {
|
|
528847
|
+
this._errorClusterTracker = new ecMod.ErrorClusterTracker();
|
|
528848
|
+
}
|
|
528849
|
+
const tracker = this._errorClusterTracker;
|
|
528850
|
+
const scope = _verifierResult?.intentBucket ?? "shell";
|
|
528851
|
+
const obs = tracker.observe(((result.output ?? "") + "\n" + (result.error ?? "")).slice(0, 1e5), scope);
|
|
528852
|
+
if (obs.summaryLine) {
|
|
528853
|
+
if (obs.hasCritical) {
|
|
528854
|
+
messages2.push({ role: "system", content: obs.summaryLine });
|
|
528855
|
+
} else {
|
|
528856
|
+
pushSoftInjection("system", obs.summaryLine);
|
|
528857
|
+
}
|
|
528858
|
+
}
|
|
528859
|
+
} catch {
|
|
528860
|
+
}
|
|
528861
|
+
}
|
|
528607
528862
|
this._hookManager.runPostToolUse(tc.name, finalArgs, (result.output ?? "").slice(0, 2e3), this._sessionId);
|
|
528608
528863
|
} catch (err) {
|
|
528609
528864
|
result = { success: false, output: "", error: err instanceof Error ? err.message : String(err) };
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "open-agents-ai",
|
|
3
|
-
"version": "0.187.
|
|
3
|
+
"version": "0.187.509",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "open-agents-ai",
|
|
9
|
-
"version": "0.187.
|
|
9
|
+
"version": "0.187.509",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "CC-BY-NC-4.0",
|
|
12
12
|
"dependencies": {
|
package/package.json
CHANGED