open-agents-ai 0.187.154 → 0.187.156
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 +126 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -264709,6 +264709,19 @@ var init_agenticRunner = __esm({
|
|
|
264709
264709
|
// WO-KG-15
|
|
264710
264710
|
_retrievalContextCache = null;
|
|
264711
264711
|
// WO-KG-15: cache per-run
|
|
264712
|
+
// ── WO-NC-07: Error pattern learning → pre-action guidance injection ──
|
|
264713
|
+
// Records error patterns (tool + error signature → learned guidance).
|
|
264714
|
+
// When the same tool+context is about to be called again, injects the
|
|
264715
|
+
// learned guidance BEFORE execution to prevent repeating the same mistake.
|
|
264716
|
+
//
|
|
264717
|
+
// Structure: Map<errorSignature, { count, guidance, lastSeen }>
|
|
264718
|
+
// errorSignature = `${toolName}:${errorType}` (e.g. "file_read:ENOENT", "shell:permission_denied")
|
|
264719
|
+
//
|
|
264720
|
+
// Research: Kumaran et al. (2016) — complementary learning systems
|
|
264721
|
+
// Fast learning from errors → immediate behavioral change
|
|
264722
|
+
_errorPatterns = /* @__PURE__ */ new Map();
|
|
264723
|
+
_errorGuidanceInjected = /* @__PURE__ */ new Set();
|
|
264724
|
+
// prevent duplicate injection per turn
|
|
264712
264725
|
_loopBlockedTools;
|
|
264713
264726
|
// Loop intervention: tools removed from schema
|
|
264714
264727
|
// -- Session Checkpointing (Priority 5) --
|
|
@@ -265234,6 +265247,28 @@ Respond with your assessment, then take action.`;
|
|
|
265234
265247
|
const toolCallLog = [];
|
|
265235
265248
|
this.aborted = false;
|
|
265236
265249
|
this._paused = false;
|
|
265250
|
+
try {
|
|
265251
|
+
const fs4 = await import("node:fs");
|
|
265252
|
+
const path5 = await import("node:path");
|
|
265253
|
+
const os8 = await import("node:os");
|
|
265254
|
+
const globalFile = path5.join(os8.homedir(), ".open-agents", "error-patterns.json");
|
|
265255
|
+
const localFile = path5.join(process.cwd(), ".oa", "error-patterns.json");
|
|
265256
|
+
for (const patternsFile of [globalFile, localFile]) {
|
|
265257
|
+
try {
|
|
265258
|
+
if (fs4.existsSync(patternsFile)) {
|
|
265259
|
+
const saved = JSON.parse(fs4.readFileSync(patternsFile, "utf8"));
|
|
265260
|
+
for (const [sig, pattern] of Object.entries(saved)) {
|
|
265261
|
+
const existing = this._errorPatterns.get(sig);
|
|
265262
|
+
if (!existing || (pattern.count ?? 0) > (existing.count ?? 0)) {
|
|
265263
|
+
this._errorPatterns.set(sig, pattern);
|
|
265264
|
+
}
|
|
265265
|
+
}
|
|
265266
|
+
}
|
|
265267
|
+
} catch {
|
|
265268
|
+
}
|
|
265269
|
+
}
|
|
265270
|
+
} catch {
|
|
265271
|
+
}
|
|
265237
265272
|
this._pauseResolve = null;
|
|
265238
265273
|
this.pendingUserMessages.length = 0;
|
|
265239
265274
|
this._taskState = {
|
|
@@ -265803,6 +265838,14 @@ If you're stuck, try a completely different approach. Do NOT repeat what failed
|
|
|
265803
265838
|
const executeSingle = async (tc) => {
|
|
265804
265839
|
if (this.aborted)
|
|
265805
265840
|
return null;
|
|
265841
|
+
if (this._errorPatterns.size > 0) {
|
|
265842
|
+
for (const [sig, pattern] of this._errorPatterns) {
|
|
265843
|
+
if (pattern.tool === tc.name && pattern.count >= 2 && !this._errorGuidanceInjected.has(sig)) {
|
|
265844
|
+
this._errorGuidanceInjected.add(sig);
|
|
265845
|
+
this.pendingUserMessages.push(`[LEARNED FROM EXPERIENCE] ${tc.name} has failed ${pattern.count} times with "${pattern.errorType}" errors. Guidance: ${pattern.guidance}`);
|
|
265846
|
+
}
|
|
265847
|
+
}
|
|
265848
|
+
}
|
|
265806
265849
|
const toolStart = performance.now();
|
|
265807
265850
|
toolCallCount++;
|
|
265808
265851
|
const argsKey = Object.entries(tc.arguments ?? {}).sort(([a2], [b]) => a2.localeCompare(b)).map(([k, v]) => `${k}=${typeof v === "string" ? v.slice(0, 80) : JSON.stringify(v)}`).join(",");
|
|
@@ -265967,6 +266010,58 @@ If you're stuck, try a completely different approach. Do NOT repeat what failed
|
|
|
265967
266010
|
}
|
|
265968
266011
|
}
|
|
265969
266012
|
}
|
|
266013
|
+
if (!result.success && result.error) {
|
|
266014
|
+
const errorText = result.error;
|
|
266015
|
+
let errorType = "unknown";
|
|
266016
|
+
if (/not found|ENOENT|no such file/i.test(errorText))
|
|
266017
|
+
errorType = "not_found";
|
|
266018
|
+
else if (/permission|denied|EACCES/i.test(errorText))
|
|
266019
|
+
errorType = "permission";
|
|
266020
|
+
else if (/timeout|timed out|ETIMEDOUT/i.test(errorText))
|
|
266021
|
+
errorType = "timeout";
|
|
266022
|
+
else if (/busy|EBUSY|in use/i.test(errorText))
|
|
266023
|
+
errorType = "busy";
|
|
266024
|
+
else if (/syntax|parse|invalid/i.test(errorText))
|
|
266025
|
+
errorType = "syntax";
|
|
266026
|
+
else if (/connect|ECONNREFUSED|network/i.test(errorText))
|
|
266027
|
+
errorType = "network";
|
|
266028
|
+
const sig = `${tc.name}:${errorType}`;
|
|
266029
|
+
const existing = this._errorPatterns.get(sig);
|
|
266030
|
+
const count = (existing?.count ?? 0) + 1;
|
|
266031
|
+
let guidance = "";
|
|
266032
|
+
switch (errorType) {
|
|
266033
|
+
case "not_found":
|
|
266034
|
+
guidance = `File/resource not found. Before retrying: use list_directory or find_files to verify the path exists. Common causes: wrong directory, typo in filename, file was moved/renamed.`;
|
|
266035
|
+
break;
|
|
266036
|
+
case "permission":
|
|
266037
|
+
guidance = `Permission denied. The command may need sudo/elevated privileges. Use shell with sudo, or check file ownership with 'ls -la'.`;
|
|
266038
|
+
break;
|
|
266039
|
+
case "timeout":
|
|
266040
|
+
guidance = `Operation timed out. The target may be unreachable or overloaded. Try: shorter timeout, different endpoint, or verify network connectivity first.`;
|
|
266041
|
+
break;
|
|
266042
|
+
case "busy":
|
|
266043
|
+
guidance = `Resource is busy/locked. Another process may be using it. Check with 'lsof' or 'fuser', or wait and retry.`;
|
|
266044
|
+
break;
|
|
266045
|
+
case "syntax":
|
|
266046
|
+
guidance = `Syntax/parse error. Review the command or input for typos, missing quotes, or incorrect parameter format.`;
|
|
266047
|
+
break;
|
|
266048
|
+
case "network":
|
|
266049
|
+
guidance = `Network error. Check connectivity: ping the target, verify the URL/host is correct, check if a proxy is needed.`;
|
|
266050
|
+
break;
|
|
266051
|
+
default:
|
|
266052
|
+
guidance = `This tool failed previously with a similar error. Review the error message carefully and adjust your approach before retrying.`;
|
|
266053
|
+
}
|
|
266054
|
+
this._errorPatterns.set(sig, { count, guidance, lastSeen: Date.now(), tool: tc.name, errorType });
|
|
266055
|
+
const lastLog = toolCallLog[toolCallLog.length - 1];
|
|
266056
|
+
if (lastLog) {
|
|
266057
|
+
lastLog.success = false;
|
|
266058
|
+
lastLog.outputPreview = errorText.slice(0, 100);
|
|
266059
|
+
}
|
|
266060
|
+
} else if (result.success) {
|
|
266061
|
+
const lastLog = toolCallLog[toolCallLog.length - 1];
|
|
266062
|
+
if (lastLog)
|
|
266063
|
+
lastLog.success = true;
|
|
266064
|
+
}
|
|
265970
266065
|
if (isReadLike && result.success) {
|
|
265971
266066
|
recentToolResults.set(toolFingerprint, (result.output ?? "").slice(0, 2e3));
|
|
265972
266067
|
if (recentToolResults.size > 50) {
|
|
@@ -266640,6 +266735,37 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
|
|
|
266640
266735
|
success: completed,
|
|
266641
266736
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
266642
266737
|
});
|
|
266738
|
+
if (this._errorPatterns.size > 0) {
|
|
266739
|
+
try {
|
|
266740
|
+
const fs4 = await import("node:fs");
|
|
266741
|
+
const path5 = await import("node:path");
|
|
266742
|
+
const os8 = await import("node:os");
|
|
266743
|
+
const globalFile = path5.join(os8.homedir(), ".open-agents", "error-patterns.json");
|
|
266744
|
+
const localFile = path5.join(process.cwd(), ".oa", "error-patterns.json");
|
|
266745
|
+
for (const targetFile of [globalFile, localFile]) {
|
|
266746
|
+
try {
|
|
266747
|
+
const dir = path5.dirname(targetFile);
|
|
266748
|
+
fs4.mkdirSync(dir, { recursive: true });
|
|
266749
|
+
let existing = {};
|
|
266750
|
+
try {
|
|
266751
|
+
existing = JSON.parse(fs4.readFileSync(targetFile, "utf8"));
|
|
266752
|
+
} catch {
|
|
266753
|
+
}
|
|
266754
|
+
for (const [sig, pattern] of this._errorPatterns) {
|
|
266755
|
+
const prev = existing[sig];
|
|
266756
|
+
existing[sig] = {
|
|
266757
|
+
...pattern,
|
|
266758
|
+
count: Math.max(prev?.count ?? 0, pattern.count),
|
|
266759
|
+
firstSeen: prev?.firstSeen ?? pattern.lastSeen
|
|
266760
|
+
};
|
|
266761
|
+
}
|
|
266762
|
+
fs4.writeFileSync(targetFile, JSON.stringify(existing, null, 2));
|
|
266763
|
+
} catch {
|
|
266764
|
+
}
|
|
266765
|
+
}
|
|
266766
|
+
} catch {
|
|
266767
|
+
}
|
|
266768
|
+
}
|
|
266643
266769
|
try {
|
|
266644
266770
|
const extractPaths = (entries, toolNames) => {
|
|
266645
266771
|
return [...new Set(entries.filter((tc) => toolNames.includes(tc.name)).map((tc) => {
|
package/package.json
CHANGED