open-agents-ai 0.187.479 → 0.187.480

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 CHANGED
@@ -512229,6 +512229,87 @@ var init_critic = __esm({
512229
512229
  }
512230
512230
  });
512231
512231
 
512232
+ // packages/orchestrator/dist/reflection.js
512233
+ function categorizeError(errorText) {
512234
+ if (!errorText)
512235
+ return "unknown";
512236
+ for (const { category, re } of CATEGORY_PATTERNS) {
512237
+ if (re.test(errorText))
512238
+ return category;
512239
+ }
512240
+ return "unknown";
512241
+ }
512242
+ function buildStem(toolName, args) {
512243
+ if (!args || Object.keys(args).length === 0)
512244
+ return toolName;
512245
+ const entries = Object.entries(args).sort(([a2], [b]) => a2.localeCompare(b));
512246
+ const first2 = entries[0];
512247
+ const v = typeof first2[1] === "string" ? first2[1] : JSON.stringify(first2[1]);
512248
+ return `${toolName}:${first2[0]}=${v.slice(0, 60)}`;
512249
+ }
512250
+ function firstSignalLine(errorText) {
512251
+ if (!errorText)
512252
+ return "";
512253
+ const lines = errorText.split(/\r?\n/);
512254
+ for (const raw of lines) {
512255
+ const line = raw.trim();
512256
+ if (!line)
512257
+ continue;
512258
+ if (line === "Error:" || line === "error:")
512259
+ continue;
512260
+ return line.slice(0, 200);
512261
+ }
512262
+ return errorText.slice(0, 200);
512263
+ }
512264
+ function synthesizeReflection(input) {
512265
+ const category = categorizeError(input.errorText);
512266
+ const stem = buildStem(input.toolName, input.args);
512267
+ const argPreview = JSON.stringify(input.args ?? {}).slice(0, 120);
512268
+ return {
512269
+ stem,
512270
+ attempted: `${input.toolName}(${argPreview})`,
512271
+ wentWrong: firstSignalLine(input.errorText),
512272
+ hypothesis: HYPOTHESES[category],
512273
+ turn: input.turn,
512274
+ attempts: (input.priorAttempts ?? 0) + 1
512275
+ };
512276
+ }
512277
+ function renderReflectionMessage(r2) {
512278
+ return [
512279
+ `[REFLECTION — your last attempt of \`${r2.attempted}\` failed (turn ${r2.turn}, ${r2.attempts} attempt${r2.attempts === 1 ? "" : "s"} so far).`,
512280
+ `Last error: "${r2.wentWrong}"`,
512281
+ `Hypothesis: ${r2.hypothesis}`,
512282
+ `VERIFY this hypothesis with a single small command BEFORE retrying the same tool. If you retry without verifying, you will likely fail the same way.]`
512283
+ ].join("\n");
512284
+ }
512285
+ var CATEGORY_PATTERNS, HYPOTHESES;
512286
+ var init_reflection = __esm({
512287
+ "packages/orchestrator/dist/reflection.js"() {
512288
+ "use strict";
512289
+ CATEGORY_PATTERNS = [
512290
+ { category: "permission_denied", re: /\b(permission denied|eacces|access denied|operation not permitted|forbidden)\b/i },
512291
+ { category: "type_or_reference_error", re: /\b(type error|cannot find module|cannot find name|is not (a function|defined|assignable)|undefined reference|unresolved (import|reference)|missing required)\b/i },
512292
+ { category: "connection_refused", re: /\b(connection refused|econnrefused|connection reset|econnreset|host unreachable|getaddrinfo|enotfound)\b/i },
512293
+ { category: "timeout", re: /\b(timeout|timed out|etimedout|deadline exceeded)\b/i },
512294
+ { category: "syntax_error", re: /\b(syntax error|parse error|unexpected token|unexpected end of (input|json)|malformed)\b/i },
512295
+ { category: "not_found", re: /\b(not found|enoent|no such file|cannot find|does not exist|404)\b/i },
512296
+ // Use [1-9]\d* so multi-digit non-zero codes (e.g. "return code 127") match —
512297
+ // the prior [^0] only matched a single character and failed on multi-digit.
512298
+ { category: "nonzero_exit", re: /\b(exit code [1-9]\d*|exit status [1-9]\d*|command failed|exit code: ?[1-9]\d*|return code [1-9]\d*)\b/i }
512299
+ ];
512300
+ HYPOTHESES = {
512301
+ permission_denied: "permissions issue — check ownership and mode of the target; you may need to operate on a writeable location",
512302
+ not_found: "the named resource doesn't exist at the expected location — verify the path/name with a single-line list before retrying",
512303
+ connection_refused: "remote service is unreachable — verify it's running and reachable before retrying with the same address",
512304
+ timeout: "operation took too long — reduce scope (smaller batch, fewer items) or verify the service is healthy",
512305
+ syntax_error: "malformed input — re-read the surrounding context; the input you produced doesn't match what the consumer expects",
512306
+ type_or_reference_error: "a name, type, or import doesn't resolve — verify the reference matches what's defined; do not guess at the symbol",
512307
+ nonzero_exit: "the command exited with a failure code — read the FULL error output and verify args + prerequisites before retrying",
512308
+ unknown: "re-read the full error message and identify the most likely cause; verify your assumption with a single small command before retrying"
512309
+ };
512310
+ }
512311
+ });
512312
+
512232
512313
  // packages/orchestrator/dist/pressure-gate.js
512233
512314
  function detectPressure(message2) {
512234
512315
  const hasProfanity = PRESSURE_SIGNALS.test(message2);
@@ -518460,6 +518541,7 @@ var init_agenticRunner = __esm({
518460
518541
  init_personality();
518461
518542
  init_promptLoader();
518462
518543
  init_critic();
518544
+ init_reflection();
518463
518545
  init_pressure_gate();
518464
518546
  init_dist5();
518465
518547
  init_dist7();
@@ -518586,6 +518668,14 @@ var init_agenticRunner = __esm({
518586
518668
  _errorPatterns = /* @__PURE__ */ new Map();
518587
518669
  _errorGuidanceInjected = /* @__PURE__ */ new Set();
518588
518670
  // prevent duplicate injection per turn
518671
+ // REG-26 (Patch C): Reflexion-style structured failure memory. Indexed by
518672
+ // fingerprint stem (tool + first arg, truncated). When the agent retries a
518673
+ // tool with a stem matching a stored reflection, surface "what was tried,
518674
+ // what went wrong, hypothesis to verify" as a system message before the
518675
+ // dispatch — generic across all stacks. See packages/orchestrator/src/reflection.ts.
518676
+ _failureReflections = /* @__PURE__ */ new Map();
518677
+ _reflectionsInjectedThisTurn = /* @__PURE__ */ new Set();
518678
+ // prevent duplicate inject per turn
518589
518679
  // ── WO-AM-01/04/10: Associative memory stores ──
518590
518680
  // Episode store: every tool call → persistent episode with importance + decay
518591
518681
  // Temporal KG: entities + relations with temporal validity (valid_from/valid_until)
@@ -520729,6 +520819,7 @@ TASK: ${task}` : task;
520729
520819
  break;
520730
520820
  }
520731
520821
  injectionsThisTurn = 0;
520822
+ this._reflectionsInjectedThisTurn.clear();
520732
520823
  while (deferredSoftInjections.length > 0 && injectionsThisTurn < INJECTION_BUDGET_SOFT) {
520733
520824
  const next = deferredSoftInjections.shift();
520734
520825
  messages2.push({ role: next.role, content: next.content });
@@ -521598,6 +521689,16 @@ ${memoryLines.join("\n")}`
521598
521689
  if (observerRedundantBlock) {
521599
521690
  this._littlemanRedundantBlocks.delete(toolFingerprint);
521600
521691
  }
521692
+ {
521693
+ const _reflStem = buildStem(tc.name, tc.arguments ?? {});
521694
+ if (!this._reflectionsInjectedThisTurn.has(_reflStem)) {
521695
+ const _reflEntry = this._failureReflections.get(_reflStem);
521696
+ if (_reflEntry) {
521697
+ this._reflectionsInjectedThisTurn.add(_reflStem);
521698
+ pushSoftInjection("system", renderReflectionMessage(_reflEntry));
521699
+ }
521700
+ }
521701
+ }
521601
521702
  const criticDecision = evaluate({
521602
521703
  proposedCall: { tool: tc.name, args: tc.arguments ?? {} },
521603
521704
  fingerprint: toolFingerprint,
@@ -521624,6 +521725,11 @@ ${criticDecision.cachedResult.slice(0, 500)}` : `[BLOCKED — the observer confi
521624
521725
  }
521625
521726
  if (criticDecision.decision === "force_progress_block") {
521626
521727
  dedupHitCount.set(toolFingerprint, criticDecision.hitNumber);
521728
+ const _existingFp = recentToolResults.get(toolFingerprint);
521729
+ if (_existingFp !== void 0) {
521730
+ recentToolResults.delete(toolFingerprint);
521731
+ recentToolResults.set(toolFingerprint, _existingFp);
521732
+ }
521627
521733
  this.emit({ type: "tool_call", toolName: tc.name, toolArgs: tc.arguments, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
521628
521734
  this.emit({
521629
521735
  type: "tool_result",
@@ -521637,6 +521743,11 @@ ${criticDecision.cachedResult.slice(0, 500)}` : `[BLOCKED — the observer confi
521637
521743
  }
521638
521744
  if (criticDecision.decision === "serve_cached") {
521639
521745
  dedupHitCount.set(toolFingerprint, criticDecision.hitNumber);
521746
+ const _existingFp = recentToolResults.get(toolFingerprint);
521747
+ if (_existingFp !== void 0) {
521748
+ recentToolResults.delete(toolFingerprint);
521749
+ recentToolResults.set(toolFingerprint, _existingFp);
521750
+ }
521640
521751
  this.emit({
521641
521752
  type: "tool_call",
521642
521753
  toolName: tc.name,
@@ -522062,6 +522173,8 @@ ${criticDecision.cachedResult.slice(0, 500)}` : `[BLOCKED — the observer confi
522062
522173
  }
522063
522174
  if (result.success) {
522064
522175
  this._recentFailures = this._recentFailures.filter((f2) => f2.fingerprint !== toolFingerprint);
522176
+ const _stem = buildStem(tc.name, tc.arguments ?? {});
522177
+ this._failureReflections.delete(_stem);
522065
522178
  }
522066
522179
  if (!result.success) {
522067
522180
  this._recentFailures.push({
@@ -522075,6 +522188,22 @@ ${criticDecision.cachedResult.slice(0, 500)}` : `[BLOCKED — the observer confi
522075
522188
  if (this._recentFailures.length > 8) {
522076
522189
  this._recentFailures = this._recentFailures.slice(-8);
522077
522190
  }
522191
+ const _refStem = buildStem(tc.name, tc.arguments ?? {});
522192
+ const _prior = this._failureReflections.get(_refStem);
522193
+ const _refErr = (result.error ?? result.output ?? "").toString();
522194
+ const _entry = synthesizeReflection({
522195
+ toolName: tc.name,
522196
+ args: tc.arguments ?? {},
522197
+ errorText: _refErr,
522198
+ turn,
522199
+ priorAttempts: _prior?.attempts ?? 0
522200
+ });
522201
+ this._failureReflections.set(_refStem, _entry);
522202
+ if (this._failureReflections.size > 32) {
522203
+ const oldestKey = this._failureReflections.keys().next().value;
522204
+ if (oldestKey !== void 0)
522205
+ this._failureReflections.delete(oldestKey);
522206
+ }
522078
522207
  }
522079
522208
  if (!result.success && tc.name === "shell" && /\[PERMISSION_ERROR\]/.test(result.error ?? "")) {
522080
522209
  this.emit({
@@ -522340,9 +522469,35 @@ ${sr.result.output}`;
522340
522469
  for (const batch2 of batches) {
522341
522470
  if (this.aborted)
522342
522471
  break;
522472
+ const batchFingerprintFirstId = /* @__PURE__ */ new Map();
522473
+ const batchInFlight = /* @__PURE__ */ new Map();
522474
+ const buildBatchFp = (call) => {
522475
+ const args = call.args ?? {};
522476
+ const argsKey = Object.entries(args).sort(([a2], [b]) => a2.localeCompare(b)).map(([k, v]) => `${k}=${typeof v === "string" ? v.slice(0, 160) : JSON.stringify(v).slice(0, 160)}`).join(",");
522477
+ return `${call.name}:${argsKey}`;
522478
+ };
522479
+ for (const call of batch2.calls) {
522480
+ const fp = buildBatchFp(call);
522481
+ if (!batchFingerprintFirstId.has(fp)) {
522482
+ batchFingerprintFirstId.set(fp, call.id);
522483
+ }
522484
+ }
522343
522485
  const results = await executeBatch(batch2, async (call) => {
522344
522486
  const originalTc = rawToolCalls.find((tc) => tc.id === call.id);
522345
- return executeSingle(originalTc);
522487
+ const fp = buildBatchFp(call);
522488
+ const firstId = batchFingerprintFirstId.get(fp);
522489
+ if (firstId !== void 0 && call.id !== void 0 && firstId !== call.id) {
522490
+ const inflight = batchInFlight.get(fp);
522491
+ if (inflight) {
522492
+ const cloned = await inflight;
522493
+ if (!cloned)
522494
+ return null;
522495
+ return { tc: { ...cloned.tc, id: call.id }, output: cloned.output };
522496
+ }
522497
+ }
522498
+ const promise = executeSingle(originalTc);
522499
+ batchInFlight.set(fp, promise);
522500
+ return promise;
522346
522501
  }, 5);
522347
522502
  for (const r2 of results) {
522348
522503
  if (r2) {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.479",
3
+ "version": "0.187.480",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "open-agents-ai",
9
- "version": "0.187.479",
9
+ "version": "0.187.480",
10
10
  "hasInstallScript": true,
11
11
  "license": "CC-BY-NC-4.0",
12
12
  "dependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.479",
3
+ "version": "0.187.480",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",