open-agents-ai 0.187.276 → 0.187.277
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 +99 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -269758,6 +269758,10 @@ var init_agenticRunner = __esm({
|
|
|
269758
269758
|
// WO-KG-15
|
|
269759
269759
|
_retrievalContextCache = null;
|
|
269760
269760
|
// WO-KG-15: cache per-run
|
|
269761
|
+
// Observer world-model and cohort stats
|
|
269762
|
+
_observerMode = "both";
|
|
269763
|
+
_worldFacts = { files: /* @__PURE__ */ new Map(), lastTest: {}, lastLists: /* @__PURE__ */ new Map() };
|
|
269764
|
+
_argCohorts = /* @__PURE__ */ new Map();
|
|
269761
269765
|
// ── WO-NC-07: Error pattern learning → pre-action guidance injection ──
|
|
269762
269766
|
// Records error patterns (tool + error signature → learned guidance).
|
|
269763
269767
|
// When the same tool+context is about to be called again, injects the
|
|
@@ -269839,8 +269843,10 @@ var init_agenticRunner = __esm({
|
|
|
269839
269843
|
contextWindowSize: options2?.contextWindowSize ?? 0,
|
|
269840
269844
|
personality: options2?.personality ?? PERSONALITY_PRESETS.balanced,
|
|
269841
269845
|
personalityName: options2?.personalityName ?? "",
|
|
269842
|
-
finalVarResolver: options2?.finalVarResolver ?? void 0
|
|
269846
|
+
finalVarResolver: options2?.finalVarResolver ?? void 0,
|
|
269847
|
+
observerMode: options2?.observerMode ?? "both"
|
|
269843
269848
|
};
|
|
269849
|
+
this._observerMode = this.options.observerMode;
|
|
269844
269850
|
}
|
|
269845
269851
|
/** Update context window size (e.g. after querying Ollama /api/show) */
|
|
269846
269852
|
setContextWindowSize(size) {
|
|
@@ -270206,6 +270212,27 @@ ${body}`;
|
|
|
270206
270212
|
}
|
|
270207
270213
|
}
|
|
270208
270214
|
}
|
|
270215
|
+
/** Build a light fingerprint for arg cohort learning */
|
|
270216
|
+
buildArgCohortKey(tool, args) {
|
|
270217
|
+
const keys = Object.keys(args || {}).sort();
|
|
270218
|
+
const parts = [tool];
|
|
270219
|
+
for (const k of keys) {
|
|
270220
|
+
const v = args[k];
|
|
270221
|
+
if (typeof v === "string")
|
|
270222
|
+
parts.push(`${k}:${v.slice(0, 64)}`);
|
|
270223
|
+
else if (typeof v === "number" || typeof v === "boolean")
|
|
270224
|
+
parts.push(`${k}:${String(v)}`);
|
|
270225
|
+
else
|
|
270226
|
+
parts.push(`${k}:${JSON.stringify(v).slice(0, 64)}`);
|
|
270227
|
+
}
|
|
270228
|
+
let h = 2166136261;
|
|
270229
|
+
const s2 = parts.join("|");
|
|
270230
|
+
for (let i2 = 0; i2 < s2.length; i2++) {
|
|
270231
|
+
h ^= s2.charCodeAt(i2);
|
|
270232
|
+
h = Math.imul(h, 16777619);
|
|
270233
|
+
}
|
|
270234
|
+
return `${tool}#${(h >>> 0).toString(16)}`;
|
|
270235
|
+
}
|
|
270209
270236
|
/** Register a tool for the agent to use */
|
|
270210
270237
|
registerTool(tool) {
|
|
270211
270238
|
this.tools.set(tool.name, tool);
|
|
@@ -270540,6 +270567,9 @@ TASK: ${task}` : task;
|
|
|
270540
270567
|
this._hookDenyHintCount = 0;
|
|
270541
270568
|
this._selfConsistencyVotes = 0;
|
|
270542
270569
|
this._retrievalContextCache = null;
|
|
270570
|
+
this._observerMode = this.options.observerMode ?? "both";
|
|
270571
|
+
this._worldFacts = { files: /* @__PURE__ */ new Map(), lastTest: {}, lastLists: /* @__PURE__ */ new Map() };
|
|
270572
|
+
this._argCohorts.clear();
|
|
270543
270573
|
this._lastTodoWriteTurn = -1;
|
|
270544
270574
|
this._lastTodoReminderTurn = -1;
|
|
270545
270575
|
let pendingConstraintWarnings = [];
|
|
@@ -271114,6 +271144,14 @@ ${memoryLines.join("\n")}`
|
|
|
271114
271144
|
const executeSingle = async (tc) => {
|
|
271115
271145
|
if (this.aborted)
|
|
271116
271146
|
return null;
|
|
271147
|
+
const cohortKey = this.buildArgCohortKey(tc.name, tc.arguments);
|
|
271148
|
+
const cohort = this._argCohorts.get(cohortKey);
|
|
271149
|
+
if (cohort && cohort.failure >= 3 && cohort.success === 0) {
|
|
271150
|
+
this.emit({ type: "observer_reaction", timestamp: (/* @__PURE__ */ new Date()).toISOString(), observer: { class: "arg_cohort_risk", shortText: `${tc.name} with similar args has failed ${cohort.failure}× recently`, confidence: 0.85 } });
|
|
271151
|
+
if (this._observerMode === "skillcoach" || this._observerMode === "both") {
|
|
271152
|
+
this.pendingUserMessages.push(`[LITTLEMAN] ${tc.name} with similar arguments has failed ${cohort.failure}× recently. Try a different approach first: read relevant files, adjust arguments, or verify prerequisites.`);
|
|
271153
|
+
}
|
|
271154
|
+
}
|
|
271117
271155
|
if (this._errorPatterns.size > 0) {
|
|
271118
271156
|
for (const [sig, pattern] of this._errorPatterns) {
|
|
271119
271157
|
if (pattern.tool === tc.name && pattern.count >= 2 && !this._errorGuidanceInjected.has(sig)) {
|
|
@@ -271298,6 +271336,35 @@ ${memoryLines.join("\n")}`
|
|
|
271298
271336
|
}
|
|
271299
271337
|
}
|
|
271300
271338
|
}
|
|
271339
|
+
const updated = this._argCohorts.get(cohortKey) || { success: 0, failure: 0, lastOutcomeTurn: turn };
|
|
271340
|
+
if (result.success)
|
|
271341
|
+
updated.success++;
|
|
271342
|
+
else
|
|
271343
|
+
updated.failure++;
|
|
271344
|
+
updated.lastOutcomeTurn = turn;
|
|
271345
|
+
this._argCohorts.set(cohortKey, updated);
|
|
271346
|
+
try {
|
|
271347
|
+
if (tc.name === "file_read") {
|
|
271348
|
+
const p2 = String(tc.arguments?.["path"] ?? tc.arguments?.["file"] ?? "");
|
|
271349
|
+
if (p2)
|
|
271350
|
+
this._worldFacts.files.set(p2, { exists: result.success, size: (result.output || "").length, hashSample: (result.output || "").slice(0, 32), lastSeenTurn: turn });
|
|
271351
|
+
} else if (tc.name === "list_directory") {
|
|
271352
|
+
const dir = String(tc.arguments?.["path"] ?? ".");
|
|
271353
|
+
this._worldFacts.lastLists.set(dir, { entriesCount: (result.output.match(/\n/g) || []).length + 1, lastSeenTurn: turn });
|
|
271354
|
+
} else if (tc.name === "shell") {
|
|
271355
|
+
const cmd = String(tc.arguments?.["command"] ?? "");
|
|
271356
|
+
if (/\b(npm|pnpm|yarn)\s+test\b|\bjest\b|\bvitest\b/i.test(cmd)) {
|
|
271357
|
+
const passed = /PASS|✓\s*all/i.test(result.output) && !/FAIL|✗/i.test(result.output);
|
|
271358
|
+
this._worldFacts.lastTest = { passed, summary: result.output.slice(0, 200), turn };
|
|
271359
|
+
}
|
|
271360
|
+
if (/^cd\s+/.test(cmd)) {
|
|
271361
|
+
const m2 = cmd.match(/^cd\s+([^&;\n]+)/);
|
|
271362
|
+
if (m2)
|
|
271363
|
+
this._worldFacts.lastCwd = m2[1];
|
|
271364
|
+
}
|
|
271365
|
+
}
|
|
271366
|
+
} catch {
|
|
271367
|
+
}
|
|
271301
271368
|
if (this._episodeStore) {
|
|
271302
271369
|
try {
|
|
271303
271370
|
const episodeContent = result.success ? `${tc.name}: ${(result.output ?? "").slice(0, 500)}` : `${tc.name} ERROR: ${(result.error ?? result.output ?? "").slice(0, 500)}`;
|
|
@@ -273086,6 +273153,9 @@ ${trimmedNew}`;
|
|
|
273086
273153
|
}
|
|
273087
273154
|
while (this._littlemanToolOutcomes.length > 20)
|
|
273088
273155
|
this._littlemanToolOutcomes.shift();
|
|
273156
|
+
const emitReaction = (cls, shortText, confidence, details2) => {
|
|
273157
|
+
this.emit({ type: "observer_reaction", timestamp: (/* @__PURE__ */ new Date()).toISOString(), observer: { class: cls, shortText, confidence, details: details2 } });
|
|
273158
|
+
};
|
|
273089
273159
|
const lastAssistant = [...recent].reverse().find((m2) => m2.role === "assistant" && typeof m2.content === "string");
|
|
273090
273160
|
if (lastAssistant && typeof lastAssistant.content === "string") {
|
|
273091
273161
|
const text = lastAssistant.content.toLowerCase();
|
|
@@ -273095,9 +273165,10 @@ ${trimmedNew}`;
|
|
|
273095
273165
|
const successes = recentOutcomes.filter((o2) => o2.succeeded);
|
|
273096
273166
|
if (successes.length >= 1) {
|
|
273097
273167
|
const successList = successes.map((o2) => `${o2.tool}: ${o2.preview.slice(0, 60)}`).join("; ");
|
|
273098
|
-
|
|
273099
|
-
|
|
273100
|
-
|
|
273168
|
+
emitReaction("false_failure", `Claimed failure, but recent tools succeeded (${successes.length})`, 0.9, successList);
|
|
273169
|
+
if (this._observerMode === "skillcoach" || this._observerMode === "both") {
|
|
273170
|
+
this.pendingUserMessages.push(`[LITTLEMAN] Correction: recent tools DID succeed. Do not retry them. Successful results: ${successList}. Use them to advance the task.`);
|
|
273171
|
+
}
|
|
273101
273172
|
this.emit({
|
|
273102
273173
|
type: "status",
|
|
273103
273174
|
content: `Littleman: corrected false failure claim (${successes.length} tools succeeded)`,
|
|
@@ -273106,6 +273177,22 @@ Build on these results instead of retrying. What is your NEXT step toward the go
|
|
|
273106
273177
|
}
|
|
273107
273178
|
}
|
|
273108
273179
|
}
|
|
273180
|
+
if (lastAssistant && typeof lastAssistant.content === "string") {
|
|
273181
|
+
const text = lastAssistant.content.toLowerCase();
|
|
273182
|
+
const claimsSuccess = /(done|fixed|success|passed|complete)/i.test(text);
|
|
273183
|
+
if (claimsSuccess) {
|
|
273184
|
+
const recentOutcomes = this._littlemanToolOutcomes.slice(-4);
|
|
273185
|
+
const failures = recentOutcomes.filter((o2) => !o2.succeeded);
|
|
273186
|
+
const successes = recentOutcomes.filter((o2) => o2.succeeded);
|
|
273187
|
+
if (failures.length > 0 && successes.length === 0) {
|
|
273188
|
+
const failList = failures.map((o2) => `${o2.tool}: ${o2.preview.slice(0, 60)}`).join("; ");
|
|
273189
|
+
emitReaction("false_success", `Claimed success, but recent tools failed (${failures.length})`, 0.9, failList);
|
|
273190
|
+
if (this._observerMode === "skillcoach" || this._observerMode === "both") {
|
|
273191
|
+
this.pendingUserMessages.push(`[LITTLEMAN] Your recent tools show errors (${failures.length}). Verify the last tool output and correct the issue before claiming success.`);
|
|
273192
|
+
}
|
|
273193
|
+
}
|
|
273194
|
+
}
|
|
273195
|
+
}
|
|
273109
273196
|
const lastToolCalls = recent.filter((m2) => m2.role === "assistant" && m2.tool_calls?.length).flatMap((m2) => m2.tool_calls ?? []);
|
|
273110
273197
|
for (const tc of lastToolCalls) {
|
|
273111
273198
|
const name10 = tc.function.name;
|
|
@@ -273117,8 +273204,10 @@ Build on these results instead of retrying. What is your NEXT step toward the go
|
|
|
273117
273204
|
const argsKey = name10 === "shell" ? String(args.command ?? "").slice(0, 60) : name10 === "web_fetch" ? String(args.url ?? "").slice(0, 80) : String(args.path ?? args.url ?? args.query ?? "").slice(0, 60);
|
|
273118
273205
|
const prior = this._littlemanToolOutcomes.find((o2) => o2.succeeded && o2.tool === name10 && o2.preview.includes(argsKey.slice(0, 30)) && o2.turn < turn);
|
|
273119
273206
|
if (prior) {
|
|
273120
|
-
|
|
273121
|
-
|
|
273207
|
+
emitReaction("redundant_action", `Already ran ${name10} successfully on turn ${prior.turn}`, 0.8, prior.preview);
|
|
273208
|
+
if (this._observerMode === "skillcoach" || this._observerMode === "both") {
|
|
273209
|
+
this.pendingUserMessages.push(`[LITTLEMAN] You already ran ${name10} successfully on turn ${prior.turn} with similar arguments. Do NOT re-run it. Use the existing result and proceed.`);
|
|
273210
|
+
}
|
|
273122
273211
|
this.emit({
|
|
273123
273212
|
type: "status",
|
|
273124
273213
|
content: `Littleman: prevented redundant ${name10} call (succeeded on turn ${prior.turn})`,
|
|
@@ -273140,7 +273229,10 @@ Do NOT re-run it. Use the result you already have and proceed to the next step.`
|
|
|
273140
273229
|
}
|
|
273141
273230
|
}
|
|
273142
273231
|
if (consecutiveShortResults >= 3) {
|
|
273143
|
-
|
|
273232
|
+
emitReaction("idle_think", `Consecutive output without input: ${consecutiveShortResults}`, 0.7);
|
|
273233
|
+
if (this._observerMode === "skillcoach" || this._observerMode === "both") {
|
|
273234
|
+
this.pendingUserMessages.push(`[LITTLEMAN] You have sent ${consecutiveShortResults} consecutive outputs without reading any input. Alternate: receive input, then respond. Call your input tool now.`);
|
|
273235
|
+
}
|
|
273144
273236
|
this.emit({
|
|
273145
273237
|
type: "status",
|
|
273146
273238
|
content: `Littleman: blocked runaway output (${consecutiveShortResults} consecutive sends without receive)`,
|
package/package.json
CHANGED