open-agents-ai 0.187.559 → 0.187.561

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
@@ -516767,6 +516767,160 @@ var init_stuck_meta_analyzer = __esm({
516767
516767
  }
516768
516768
  });
516769
516769
 
516770
+ // packages/orchestrator/dist/thinking-mode-collapse.js
516771
+ function renderModeCollapsePrompt(inputs) {
516772
+ const lines = [];
516773
+ lines.push("# THINKING STREAM MODE-COLLAPSE ANALYSIS");
516774
+ lines.push("");
516775
+ lines.push("You are a META-ANALYSIS sub-agent. A model (the generator) has been");
516776
+ lines.push("producing internal reasoning tokens for an extended period without");
516777
+ lines.push("emitting any visible output or tool calls. A sample of its reasoning");
516778
+ lines.push("stream is provided below.");
516779
+ lines.push("");
516780
+ lines.push("Your job: classify whether the generator is experiencing a MODE COLLAPSE");
516781
+ lines.push("(a reasoning loop where it repeats the same idea, goes in circles, or");
516782
+ lines.push("degrades into noise) or is still PRODUCTIVELY REASONING (making linear");
516783
+ lines.push("progress toward a conclusion).");
516784
+ lines.push("");
516785
+ lines.push("## Collapse categories");
516786
+ lines.push("");
516787
+ lines.push("- mode_collapse_exact_repeat: The model emits the exact same sentence or");
516788
+ lines.push(" paragraph 2+ times. The text is verbatim identical.");
516789
+ lines.push("");
516790
+ lines.push("- mode_collapse_semantic_loop: The model rephrases the same idea");
516791
+ lines.push(" repeatedly with different wording. Same concept, new sentences.");
516792
+ lines.push(" No new reasoning steps or conclusions.");
516793
+ lines.push("");
516794
+ lines.push("- mode_collapse_circular: The model alternates between two or more");
516795
+ lines.push(" positions/approaches without converging. A -> B -> A -> B pattern.");
516796
+ lines.push("");
516797
+ lines.push("- mode_collapse_degraded: The reasoning quality is visibly degrading —");
516798
+ lines.push(" sentences get shorter, less coherent, fragmented, or trail off.");
516799
+ lines.push(" The model is losing the thread.");
516800
+ lines.push("");
516801
+ lines.push("- mode_collapse_stuck_at_start: The model keeps restating the problem or");
516802
+ lines.push(" the first step but never moves to subsequent steps. Stuck in a");
516803
+ lines.push(" preamble loop.");
516804
+ lines.push("");
516805
+ lines.push("- healthy: The reasoning is making linear progress. Each sentence builds");
516806
+ lines.push(" on or advances from the previous one. The model is analyzing,");
516807
+ lines.push(" comparing, planning, or synthesizing in a productive direction.");
516808
+ lines.push("");
516809
+ lines.push("## Context");
516810
+ lines.push(`Goal: ${inputs.goal.slice(0, 500)}`);
516811
+ lines.push(`Total thinking produced: ${inputs.totalThinkingChars} characters over ${(inputs.thinkingDurationMs / 1e3).toFixed(0)}s`);
516812
+ if (inputs.lastToolNames.length > 0) {
516813
+ lines.push(`Recent tool calls before thinking: ${inputs.lastToolNames.join(", ")}`);
516814
+ }
516815
+ lines.push("");
516816
+ lines.push("## Thinking sample (most recent portion)");
516817
+ lines.push("");
516818
+ lines.push("```");
516819
+ lines.push(inputs.thinkingSample.slice(0, 3e3));
516820
+ lines.push("```");
516821
+ lines.push("");
516822
+ lines.push("## Output format");
516823
+ lines.push("");
516824
+ lines.push("Emit a SINGLE JSON code block with this exact shape:");
516825
+ lines.push("");
516826
+ lines.push("```json");
516827
+ lines.push("{");
516828
+ lines.push(' "category": "<one of the categories above>",');
516829
+ lines.push(' "diagnosis": "<1-2 sentence diagnosis>",');
516830
+ lines.push(' "confidence": <0.0-1.0>,');
516831
+ lines.push(' "suggested_action": "<one of: none, abort_and_retry_no_think, abort_and_nudge, abort_and_force_tool_call>"');
516832
+ lines.push("}");
516833
+ lines.push("```");
516834
+ lines.push("");
516835
+ lines.push("Only flag as collapse if confidence > 0.7. When unsure, classify as healthy");
516836
+ lines.push("with low confidence — false positives (aborting productive reasoning) are");
516837
+ lines.push("more harmful than false negatives (letting a collapse continue briefly).");
516838
+ return lines.join("\n");
516839
+ }
516840
+ function parseModeCollapseVerdict(rawResponse) {
516841
+ const fallback = (msg) => ({
516842
+ category: "healthy",
516843
+ diagnosis: `(sub-agent parse failed: ${msg})`,
516844
+ confidence: 0,
516845
+ suggested_action: "none",
516846
+ raw: rawResponse,
516847
+ parseFallback: true
516848
+ });
516849
+ if (!rawResponse || typeof rawResponse !== "string" || rawResponse.trim().length === 0) {
516850
+ return fallback("empty response");
516851
+ }
516852
+ const fenceMatch = rawResponse.match(/```(?:json)?\s*\n([\s\S]*?)\n```/);
516853
+ let jsonText = null;
516854
+ if (fenceMatch) {
516855
+ jsonText = fenceMatch[1].trim();
516856
+ } else {
516857
+ const first2 = rawResponse.indexOf("{");
516858
+ const last2 = rawResponse.lastIndexOf("}");
516859
+ if (first2 !== -1 && last2 > first2)
516860
+ jsonText = rawResponse.slice(first2, last2 + 1);
516861
+ }
516862
+ if (!jsonText)
516863
+ return fallback("no JSON block found");
516864
+ let parsed;
516865
+ try {
516866
+ parsed = JSON.parse(jsonText);
516867
+ } catch (e2) {
516868
+ return fallback(`JSON parse: ${e2 instanceof Error ? e2.message : String(e2)}`);
516869
+ }
516870
+ if (!parsed || typeof parsed !== "object")
516871
+ return fallback("not an object");
516872
+ const validCategories = [
516873
+ "healthy",
516874
+ "mode_collapse_exact_repeat",
516875
+ "mode_collapse_semantic_loop",
516876
+ "mode_collapse_circular",
516877
+ "mode_collapse_degraded",
516878
+ "mode_collapse_stuck_at_start"
516879
+ ];
516880
+ const category = typeof parsed.category === "string" && validCategories.includes(parsed.category) ? parsed.category : "healthy";
516881
+ const diagnosis = typeof parsed.diagnosis === "string" && parsed.diagnosis.trim().length > 0 ? parsed.diagnosis.slice(0, 500) : "(no diagnosis)";
516882
+ const confidence = typeof parsed.confidence === "number" ? Math.max(0, Math.min(1, parsed.confidence)) : 0;
516883
+ const validActions = [
516884
+ "none",
516885
+ "abort_and_retry_no_think",
516886
+ "abort_and_nudge",
516887
+ "abort_and_force_tool_call"
516888
+ ];
516889
+ const suggested_action = typeof parsed.suggested_action === "string" && validActions.includes(parsed.suggested_action) ? parsed.suggested_action : "none";
516890
+ return {
516891
+ category,
516892
+ diagnosis,
516893
+ confidence,
516894
+ suggested_action,
516895
+ raw: rawResponse,
516896
+ parseFallback: false
516897
+ };
516898
+ }
516899
+ async function runModeCollapseAnalysis(opts) {
516900
+ const startMs = Date.now();
516901
+ const prompt = renderModeCollapsePrompt(opts.inputs);
516902
+ const promptBytes = Buffer.byteLength(prompt, "utf-8");
516903
+ let raw = "";
516904
+ try {
516905
+ raw = await opts.callable(prompt);
516906
+ } catch {
516907
+ raw = "";
516908
+ }
516909
+ const responseBytes = Buffer.byteLength(raw, "utf-8");
516910
+ const verdict = parseModeCollapseVerdict(raw);
516911
+ return {
516912
+ verdict,
516913
+ promptBytes,
516914
+ responseBytes,
516915
+ durationMs: Date.now() - startMs
516916
+ };
516917
+ }
516918
+ var init_thinking_mode_collapse = __esm({
516919
+ "packages/orchestrator/dist/thinking-mode-collapse.js"() {
516920
+ "use strict";
516921
+ }
516922
+ });
516923
+
516770
516924
  // packages/orchestrator/dist/problem-frame-validator.js
516771
516925
  function renderFrameValidatorPrompt(inputs) {
516772
516926
  const lines = [];
@@ -527223,6 +527377,7 @@ var init_agenticRunner = __esm({
527223
527377
  init_backward_pass_runner();
527224
527378
  init_world_state_plan_reconciler();
527225
527379
  init_stuck_meta_analyzer();
527380
+ init_thinking_mode_collapse();
527226
527381
  init_problem_frame_validator();
527227
527382
  init_pressure_gate();
527228
527383
  init_dist5();
@@ -527241,9 +527396,22 @@ var init_agenticRunner = __esm({
527241
527396
  init_modelProfile();
527242
527397
  TOOL_SUBSETS = {
527243
527398
  web: ["web_search", "web_fetch", "web_crawl"],
527244
- code: ["file_patch", "file_explore", "batch_edit", "file_read", "file_write", "file_edit"],
527399
+ code: [
527400
+ "file_patch",
527401
+ "file_explore",
527402
+ "batch_edit",
527403
+ "file_read",
527404
+ "file_write",
527405
+ "file_edit"
527406
+ ],
527245
527407
  agent: ["agent", "sub_agent", "background_run"],
527246
- memory: ["memory_search", "memory_read", "memory_write", "memex_retrieve", "working_notes"],
527408
+ memory: [
527409
+ "memory_search",
527410
+ "memory_read",
527411
+ "memory_write",
527412
+ "memex_retrieve",
527413
+ "working_notes"
527414
+ ],
527247
527415
  shell: ["shell", "shell_async", "kill_proc", "run_tests"],
527248
527416
  graph: ["graph_query", "graph_traverse", "code_graph"],
527249
527417
  skill: ["skill_list", "skill_execute", "skill_search"]
@@ -527252,11 +527420,48 @@ var init_agenticRunner = __esm({
527252
527420
  SYSTEM_PROMPT = loadPrompt("agentic/system-large.md");
527253
527421
  SYSTEM_PROMPT_MEDIUM = loadPrompt("agentic/system-medium.md");
527254
527422
  SYSTEM_PROMPT_SMALL = loadPrompt("agentic/system-small.md");
527255
- VISUAL_TOOLS = /* @__PURE__ */ new Set(["vision", "camera_capture", "image_read", "screenshot", "ocr", "ocr_image_advanced", "visual_memory", "desktop_describe", "ocr_pdf", "generate_image"]);
527256
- AUDIO_TOOLS = /* @__PURE__ */ new Set(["audio_capture", "audio_analyze", "asr_listen", "transcribe_file", "transcribe_url", "audio_playback", "youtube_download"]);
527257
- SOCIAL_TOOLS = /* @__PURE__ */ new Set(["multimodal_memory", "send_message", "jibberlink"]);
527258
- SPATIAL_TOOLS = /* @__PURE__ */ new Set(["gps_location", "bluetooth_scan", "wifi_control", "sdr_scan", "meshtastic"]);
527259
- CODE_TOOLS = /* @__PURE__ */ new Set(["file_write", "file_edit", "file_patch", "batch_edit", "code_sandbox", "repl_exec", "notebook_edit"]);
527423
+ VISUAL_TOOLS = /* @__PURE__ */ new Set([
527424
+ "vision",
527425
+ "camera_capture",
527426
+ "image_read",
527427
+ "screenshot",
527428
+ "ocr",
527429
+ "ocr_image_advanced",
527430
+ "visual_memory",
527431
+ "desktop_describe",
527432
+ "ocr_pdf",
527433
+ "generate_image"
527434
+ ]);
527435
+ AUDIO_TOOLS = /* @__PURE__ */ new Set([
527436
+ "audio_capture",
527437
+ "audio_analyze",
527438
+ "asr_listen",
527439
+ "transcribe_file",
527440
+ "transcribe_url",
527441
+ "audio_playback",
527442
+ "youtube_download"
527443
+ ]);
527444
+ SOCIAL_TOOLS = /* @__PURE__ */ new Set([
527445
+ "multimodal_memory",
527446
+ "send_message",
527447
+ "jibberlink"
527448
+ ]);
527449
+ SPATIAL_TOOLS = /* @__PURE__ */ new Set([
527450
+ "gps_location",
527451
+ "bluetooth_scan",
527452
+ "wifi_control",
527453
+ "sdr_scan",
527454
+ "meshtastic"
527455
+ ]);
527456
+ CODE_TOOLS = /* @__PURE__ */ new Set([
527457
+ "file_write",
527458
+ "file_edit",
527459
+ "file_patch",
527460
+ "batch_edit",
527461
+ "code_sandbox",
527462
+ "repl_exec",
527463
+ "notebook_edit"
527464
+ ]);
527260
527465
  AgenticRunner = class {
527261
527466
  backend;
527262
527467
  tools = /* @__PURE__ */ new Map();
@@ -527879,7 +528084,11 @@ ${graphSummary}`,
527879
528084
  try {
527880
528085
  const _allLessons = readAll(this._workingDirectory || void 0);
527881
528086
  if (_allLessons.length > 0) {
527882
- const _selected = select2({ goal: task, lessons: _allLessons, k: 5 });
528087
+ const _selected = select2({
528088
+ goal: task,
528089
+ lessons: _allLessons,
528090
+ k: 5
528091
+ });
527883
528092
  if (_selected.length > 0) {
527884
528093
  const _lessonsBody = renderLessonsAsContext(_selected);
527885
528094
  sections.push({
@@ -527895,7 +528104,10 @@ ${graphSummary}`,
527895
528104
  const totalTokenEstimate = sections.reduce((sum, s2) => sum + s2.tokenEstimate, 0);
527896
528105
  return {
527897
528106
  assembled,
527898
- sections: sections.map((s2) => ({ label: s2.label, tokenEstimate: s2.tokenEstimate })),
528107
+ sections: sections.map((s2) => ({
528108
+ label: s2.label,
528109
+ tokenEstimate: s2.tokenEstimate
528110
+ })),
527899
528111
  totalTokenEstimate
527900
528112
  };
527901
528113
  }
@@ -528130,7 +528342,12 @@ Pick the SMALLEST concrete deliverable from the spec — typically the project e
528130
528342
  return null;
528131
528343
  if (process.env["OA_DISABLE_DECOMP2"] === "1")
528132
528344
  return null;
528133
- const _editTools = /* @__PURE__ */ new Set(["file_write", "file_edit", "batch_edit", "file_patch"]);
528345
+ const _editTools = /* @__PURE__ */ new Set([
528346
+ "file_write",
528347
+ "file_edit",
528348
+ "batch_edit",
528349
+ "file_patch"
528350
+ ]);
528134
528351
  if (!_editTools.has(tc.name))
528135
528352
  return null;
528136
528353
  const _editPaths = this._extractToolTargetPaths(tc.name, tc.arguments);
@@ -528272,7 +528489,12 @@ Pick the SMALLEST concrete deliverable from the spec — typically the project e
528272
528489
  const window2 = toolCallLog.slice(-WINDOW);
528273
528490
  if (window2.length < SHELL_REPEAT_THRESHOLD)
528274
528491
  return { detected: false };
528275
- const _editClasses = /* @__PURE__ */ new Set(["file_write", "file_edit", "batch_edit", "file_patch"]);
528492
+ const _editClasses = /* @__PURE__ */ new Set([
528493
+ "file_write",
528494
+ "file_edit",
528495
+ "batch_edit",
528496
+ "file_patch"
528497
+ ]);
528276
528498
  for (const c9 of window2) {
528277
528499
  if (_editClasses.has(c9.name) && c9.success !== false)
528278
528500
  return { detected: false };
@@ -528305,10 +528527,20 @@ Pick the SMALLEST concrete deliverable from the spec — typically the project e
528305
528527
  bestRead = [k, n2];
528306
528528
  }
528307
528529
  if (bestShell) {
528308
- return { detected: true, repeatedSample: bestShell[0], count: bestShell[1], kind: "shell" };
528530
+ return {
528531
+ detected: true,
528532
+ repeatedSample: bestShell[0],
528533
+ count: bestShell[1],
528534
+ kind: "shell"
528535
+ };
528309
528536
  }
528310
528537
  if (bestRead) {
528311
- return { detected: true, repeatedSample: bestRead[0], count: bestRead[1], kind: "read" };
528538
+ return {
528539
+ detected: true,
528540
+ repeatedSample: bestRead[0],
528541
+ count: bestRead[1],
528542
+ kind: "read"
528543
+ };
528312
528544
  }
528313
528545
  return { detected: false };
528314
528546
  }
@@ -528482,7 +528714,10 @@ Do NOT call task_complete until all items are marked completed via todo_write.`;
528482
528714
  try {
528483
528715
  const resp = await _backend.chatCompletion({
528484
528716
  messages: [
528485
- { role: "system", content: "You are a CRITIC sub-agent. Audit the implementation and emit a structured JSON verdict." },
528717
+ {
528718
+ role: "system",
528719
+ content: "You are a CRITIC sub-agent. Audit the implementation and emit a structured JSON verdict."
528720
+ },
528486
528721
  { role: "user", content: prompt }
528487
528722
  ],
528488
528723
  tools: [],
@@ -528499,7 +528734,14 @@ Do NOT call task_complete until all items are marked completed via todo_write.`;
528499
528734
  verdict: "request_changes",
528500
528735
  rationale: `Critic backend call failed: ${e2 instanceof Error ? e2.message : String(e2)}`,
528501
528736
  pass: [],
528502
- issues: [{ severity: "high", file: "(critic-runner)", problem: "Backend call failed.", suggested_fix: "Retry; if persistent, set OA_BACKWARD_PASS=off." }],
528737
+ issues: [
528738
+ {
528739
+ severity: "high",
528740
+ file: "(critic-runner)",
528741
+ problem: "Backend call failed.",
528742
+ suggested_fix: "Retry; if persistent, set OA_BACKWARD_PASS=off."
528743
+ }
528744
+ ],
528503
528745
  tests_missing: []
528504
528746
  });
528505
528747
  }
@@ -529019,7 +529261,7 @@ ${body}`;
529019
529261
  * converging — particularly common when a build error names a specific
529020
529262
  * file the agent thinks needs more work.
529021
529263
  *
529022
- * Suggests targeted alternatives (file_edit/file_patch) and "good enough"
529264
+ * Suggests targeted alternatives (file_edit/file_patch) and "good enough"
529023
529265
  * recognition. Returns null when no churn is happening.
529024
529266
  */
529025
529267
  _renderWriteChurnBlock(turn) {
@@ -529039,7 +529281,9 @@ ${body}`;
529039
529281
  return null;
529040
529282
  churners.sort((a2, b) => b.writes - a2.writes);
529041
529283
  const top = churners.slice(0, 5);
529042
- const lines = ["[WRITE-LOOP DETECTED — you are rewriting the same file(s) repeatedly]"];
529284
+ const lines = [
529285
+ "[WRITE-LOOP DETECTED — you are rewriting the same file(s) repeatedly]"
529286
+ ];
529043
529287
  for (const c9 of top) {
529044
529288
  lines.push(` • ${c9.path} — ${c9.writes} writes (most recent ${c9.ageTurns} turn${c9.ageTurns === 1 ? "" : "s"} ago)`);
529045
529289
  }
@@ -529501,7 +529745,9 @@ ${latest.output || ""}`.trim();
529501
529745
  const todos = this.readSessionTodos();
529502
529746
  if (!todos || todos.length === 0)
529503
529747
  return null;
529504
- const lines = ["[CURRENT TODO PLAN — already in your state, no need to call todo_write to see it]"];
529748
+ const lines = [
529749
+ "[CURRENT TODO PLAN — already in your state, no need to call todo_write to see it]"
529750
+ ];
529505
529751
  const inProg = todos.filter((t2) => t2.status === "in_progress");
529506
529752
  const pending = todos.filter((t2) => t2.status === "pending");
529507
529753
  const done = todos.filter((t2) => t2.status === "completed");
@@ -529644,7 +529890,10 @@ ${blob}
529644
529890
  try {
529645
529891
  const response = await this.backend.chatCompletion({
529646
529892
  messages: [
529647
- { role: "system", content: "You write extremely concise phase summaries for agent context management." },
529893
+ {
529894
+ role: "system",
529895
+ content: "You write extremely concise phase summaries for agent context management."
529896
+ },
529648
529897
  { role: "user", content: prompt }
529649
529898
  ],
529650
529899
  tools: [],
@@ -529715,7 +529964,9 @@ ${blob}
529715
529964
  const newMemex = memexMatches.filter((m2) => !this._lastSurfacedAnchorIds.has(m2.id)).slice(0, 2);
529716
529965
  if (newAnchors.length === 0 && newMemex.length === 0)
529717
529966
  return;
529718
- const lines = [`[Anchor surface] Relevant archived context for the current activity:`];
529967
+ const lines = [
529968
+ `[Anchor surface] Relevant archived context for the current activity:`
529969
+ ];
529719
529970
  for (const a2 of newAnchors) {
529720
529971
  lines.push(` - [${a2.type}] ${a2.summary}`);
529721
529972
  }
@@ -529775,7 +530026,10 @@ ${blob}
529775
530026
  if (msg.role === "assistant" && typeof msg.content === "string" && msg.content.length > 200) {
529776
530027
  const stripped = msg.content.replace(/<think>[\s\S]*?<\/think>/gi, "").replace(/<reasoning>[\s\S]*?<\/reasoning>/gi, "").replace(/\[THINKING\][\s\S]*?\[\/THINKING\]/gi, "").trim();
529777
530028
  if (stripped.length < msg.content.length * 0.8) {
529778
- messages2[i2] = { ...msg, content: stripped || "[thinking stripped]" };
530029
+ messages2[i2] = {
530030
+ ...msg,
530031
+ content: stripped || "[thinking stripped]"
530032
+ };
529779
530033
  thinkStripped++;
529780
530034
  }
529781
530035
  }
@@ -529905,7 +530159,11 @@ ${blob}
529905
530159
  getToolCatalog() {
529906
530160
  const list = [];
529907
530161
  for (const t2 of this.tools.values()) {
529908
- list.push({ name: t2.name, description: t2.description, parameters: t2.parameters });
530162
+ list.push({
530163
+ name: t2.name,
530164
+ description: t2.description,
530165
+ parameters: t2.parameters
530166
+ });
529909
530167
  }
529910
530168
  return list;
529911
530169
  }
@@ -529923,7 +530181,11 @@ ${blob}
529923
530181
  tool.inputSchema.parse(args);
529924
530182
  }
529925
530183
  } catch (e2) {
529926
- return { success: false, output: "", error: `Invalid args for ${name10}: ${e2?.message || String(e2)}` };
530184
+ return {
530185
+ success: false,
530186
+ output: "",
530187
+ error: `Invalid args for ${name10}: ${e2?.message || String(e2)}`
530188
+ };
529927
530189
  }
529928
530190
  try {
529929
530191
  const result = await tool.execute(args);
@@ -529972,7 +530234,11 @@ ${blob}
529972
530234
  pause() {
529973
530235
  if (!this._paused) {
529974
530236
  this._paused = true;
529975
- this.emit({ type: "status", content: "Task paused by user.", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
530237
+ this.emit({
530238
+ type: "status",
530239
+ content: "Task paused by user.",
530240
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
530241
+ });
529976
530242
  }
529977
530243
  }
529978
530244
  /**
@@ -529981,7 +530247,11 @@ ${blob}
529981
530247
  resume() {
529982
530248
  if (this._paused) {
529983
530249
  this._paused = false;
529984
- this.emit({ type: "status", content: "Task resumed by user.", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
530250
+ this.emit({
530251
+ type: "status",
530252
+ content: "Task resumed by user.",
530253
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
530254
+ });
529985
530255
  if (this._pauseResolve) {
529986
530256
  this._pauseResolve();
529987
530257
  this._pauseResolve = null;
@@ -530287,7 +530557,11 @@ Respond with your assessment, then take action.`;
530287
530557
  const snapshot = preflightMod.capturePreflightSnapshot(this._workingDirectory ?? void 0);
530288
530558
  const formatted = preflightMod.formatPreflightStatus(snapshot);
530289
530559
  if (formatted) {
530290
- this.emit({ type: "status", content: formatted, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
530560
+ this.emit({
530561
+ type: "status",
530562
+ content: formatted,
530563
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
530564
+ });
530291
530565
  }
530292
530566
  if (this._episodeStore) {
530293
530567
  const hasError = snapshot.warnings.some((w) => w.severity === "error");
@@ -530342,7 +530616,10 @@ Respond with your assessment, then take action.`;
530342
530616
  const memMod = await Promise.resolve().then(() => (init_dist7(), dist_exports2));
530343
530617
  const currentModel = process.env["OA_EMBEDDING_MODEL"] || "default";
530344
530618
  const currentDim = parseInt(process.env["OA_EMBEDDING_DIM"] || "0", 10) || 768;
530345
- const drift = memMod.checkEmbeddingDrift(this._episodeStore.getDb(), { model: currentModel, dim: currentDim });
530619
+ const drift = memMod.checkEmbeddingDrift(this._episodeStore.getDb(), {
530620
+ model: currentModel,
530621
+ dim: currentDim
530622
+ });
530346
530623
  if (drift.driftDetected && drift.previous) {
530347
530624
  this.emit({
530348
530625
  type: "status",
@@ -530350,7 +530627,10 @@ Respond with your assessment, then take action.`;
530350
530627
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
530351
530628
  });
530352
530629
  } else if (!drift.previous) {
530353
- memMod.recordEmbeddingMeta(this._episodeStore.getDb(), { model: currentModel, dim: currentDim });
530630
+ memMod.recordEmbeddingMeta(this._episodeStore.getDb(), {
530631
+ model: currentModel,
530632
+ dim: currentDim
530633
+ });
530354
530634
  }
530355
530635
  } catch {
530356
530636
  }
@@ -530361,7 +530641,10 @@ Respond with your assessment, then take action.`;
530361
530641
  let commitSha = "no-commit";
530362
530642
  try {
530363
530643
  const { execSync: execSync59 } = await import("node:child_process");
530364
- commitSha = execSync59("git rev-parse HEAD", { cwd: this._workingDirectory, stdio: ["ignore", "pipe", "ignore"] }).toString().trim().slice(0, 12) || "no-commit";
530644
+ commitSha = execSync59("git rev-parse HEAD", {
530645
+ cwd: this._workingDirectory,
530646
+ stdio: ["ignore", "pipe", "ignore"]
530647
+ }).toString().trim().slice(0, 12) || "no-commit";
530365
530648
  } catch {
530366
530649
  }
530367
530650
  const cm = new memMod.CodebaseMap(this._episodeStore.getDb(), this._workingDirectory, commitSha);
@@ -530443,7 +530726,9 @@ TASK: ${task}` : task;
530443
530726
  if (process.env["OA_FRESH_SESSION"] === "1")
530444
530727
  throw "skip-handoff-fresh";
530445
530728
  const oaDir = this._workingDirectory ? _pathJoin(this._workingDirectory, ".oa") : _pathJoin(process.cwd(), ".oa");
530446
- const chainPairs = loadMessagePairsFromLog(oaDir, { currentTask: cleanedTask });
530729
+ const chainPairs = loadMessagePairsFromLog(oaDir, {
530730
+ currentTask: cleanedTask
530731
+ });
530447
530732
  if (chainPairs.length > 0) {
530448
530733
  messages2.splice(1, 0, ...chainPairs);
530449
530734
  this.emit({
@@ -530552,7 +530837,25 @@ TASK: ${task}` : task;
530552
530837
  const DEDUP_ESCALATION_THRESHOLD = 3;
530553
530838
  const toolCallBudget = /* @__PURE__ */ new Map();
530554
530839
  const loopTier = this.options.modelTier ?? "large";
530555
- const toolBudgets = loopTier === "small" ? { web_search: 6, web_fetch: 4, list_directory: 12, find_files: 10, grep_search: 12 } : loopTier === "medium" ? { web_search: 10, web_fetch: 8, list_directory: 18, find_files: 14, grep_search: 18 } : { web_search: 20, web_fetch: 15, list_directory: 30, find_files: 20, grep_search: 30 };
530840
+ const toolBudgets = loopTier === "small" ? {
530841
+ web_search: 6,
530842
+ web_fetch: 4,
530843
+ list_directory: 12,
530844
+ find_files: 10,
530845
+ grep_search: 12
530846
+ } : loopTier === "medium" ? {
530847
+ web_search: 10,
530848
+ web_fetch: 8,
530849
+ list_directory: 18,
530850
+ find_files: 14,
530851
+ grep_search: 18
530852
+ } : {
530853
+ web_search: 20,
530854
+ web_fetch: 15,
530855
+ list_directory: 30,
530856
+ find_files: 20,
530857
+ grep_search: 30
530858
+ };
530556
530859
  for (const [tool, budget] of Object.entries(toolBudgets)) {
530557
530860
  toolCallBudget.set(tool, budget);
530558
530861
  }
@@ -530587,12 +530890,20 @@ TASK: ${task}` : task;
530587
530890
  if (this._paused) {
530588
530891
  const shouldContinue = await this.waitIfPaused();
530589
530892
  if (!shouldContinue) {
530590
- this.emit({ type: "error", content: "Task aborted by user", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
530893
+ this.emit({
530894
+ type: "error",
530895
+ content: "Task aborted by user",
530896
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
530897
+ });
530591
530898
  break;
530592
530899
  }
530593
530900
  }
530594
530901
  if (this.aborted) {
530595
- this.emit({ type: "error", content: "Task aborted by user", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
530902
+ this.emit({
530903
+ type: "error",
530904
+ content: "Task aborted by user",
530905
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
530906
+ });
530596
530907
  break;
530597
530908
  }
530598
530909
  const REG35_CHECKPOINT_EVERY = 10;
@@ -530691,7 +531002,10 @@ TASK: ${task}` : task;
530691
531002
  todos: _wsTodos,
530692
531003
  recentFailures: _wsFailures,
530693
531004
  maxFiles: WORLD_STATE_MAX_FILES,
530694
- lastBuildSuccess: this._lastBuildSuccessTurn >= 0 ? { command: this._lastBuildSuccessCommand, turn: this._lastBuildSuccessTurn } : void 0
531005
+ lastBuildSuccess: this._lastBuildSuccessTurn >= 0 ? {
531006
+ command: this._lastBuildSuccessCommand,
531007
+ turn: this._lastBuildSuccessTurn
531008
+ } : void 0
530695
531009
  });
530696
531010
  for (let _i = 0; _i < messages2.length; _i++) {
530697
531011
  const _m = messages2[_i];
@@ -530856,7 +531170,10 @@ Respond with EXACTLY this structure before your next tool call:
530856
531170
  errClusters.push(...this._runErrorPatterns.slice(0, 3));
530857
531171
  }
530858
531172
  const stuckTool = this._toolSequence.length > 0 ? this._toolSequence[this._toolSequence.length - 1] : null;
530859
- const fingerprint = { errorClusters: errClusters.slice(0, 3), stuckTool };
531173
+ const fingerprint = {
531174
+ errorClusters: errClusters.slice(0, 3),
531175
+ stuckTool
531176
+ };
530860
531177
  this._pendingStagnationEntry = {
530861
531178
  fingerprint,
530862
531179
  cooldownExpiresAtTurn: turn + 5,
@@ -531062,7 +531379,10 @@ ${_staleSamples.join("\n")}` : ``,
531062
531379
  try {
531063
531380
  const _r = await this.backend.chatCompletion({
531064
531381
  messages: [
531065
- { role: "system", content: "You are a META-ANALYSIS sub-agent. Audit the implementer's stuck state and emit a structured JSON directive." },
531382
+ {
531383
+ role: "system",
531384
+ content: "You are a META-ANALYSIS sub-agent. Audit the implementer's stuck state and emit a structured JSON directive."
531385
+ },
531066
531386
  { role: "user", content: prompt }
531067
531387
  ],
531068
531388
  tools: [],
@@ -531117,7 +531437,10 @@ ${_staleSamples.join("\n")}` : ``,
531117
531437
  callable: _smaCallable
531118
531438
  }).then((_smaResult) => {
531119
531439
  if (_smaResult.injection && !_smaResult.directive.parseFallback) {
531120
- messages2.push({ role: "system", content: _smaResult.injection });
531440
+ messages2.push({
531441
+ role: "system",
531442
+ content: _smaResult.injection
531443
+ });
531121
531444
  this.emit({
531122
531445
  type: "status",
531123
531446
  content: `REG-49 stuck-meta-analyzer fired at turn ${turn} — diagnosis="${_smaResult.directive.diagnosis.slice(0, 80)}", next=${_smaResult.directive.next_action.tool}, ${_smaResult.durationMs}ms`,
@@ -531225,7 +531548,10 @@ ${_staleSamples.join("\n")}` : ``,
531225
531548
  try {
531226
531549
  const _r = await this.backend.chatCompletion({
531227
531550
  messages: [
531228
- { role: "system", content: "You are a META-ANALYSIS sub-agent. Audit the implementer's stuck state and emit a structured JSON directive." },
531551
+ {
531552
+ role: "system",
531553
+ content: "You are a META-ANALYSIS sub-agent. Audit the implementer's stuck state and emit a structured JSON directive."
531554
+ },
531229
531555
  { role: "user", content: prompt }
531230
531556
  ],
531231
531557
  tools: [],
@@ -531274,7 +531600,10 @@ ${_staleSamples.join("\n")}` : ``,
531274
531600
  callable: _smaCallable50
531275
531601
  }).then((_smaResult) => {
531276
531602
  if (_smaResult.injection && !_smaResult.directive.parseFallback) {
531277
- messages2.push({ role: "system", content: _smaResult.injection });
531603
+ messages2.push({
531604
+ role: "system",
531605
+ content: _smaResult.injection
531606
+ });
531278
531607
  this.emit({
531279
531608
  type: "status",
531280
531609
  content: `REG-50 → SSMA fired at turn ${turn} — diagnosis="${_smaResult.directive.diagnosis.slice(0, 80)}", next=${_smaResult.directive.next_action.tool}, ${_smaResult.durationMs}ms`,
@@ -531367,7 +531696,10 @@ ${_staleSamples.join("\n")}` : ``,
531367
531696
  try {
531368
531697
  const _r = await this.backend.chatCompletion({
531369
531698
  messages: [
531370
- { role: "system", content: "You are a META-STRATEGY VALIDATOR. Audit the implementer's frame-vs-goal alignment and emit a structured JSON verdict." },
531699
+ {
531700
+ role: "system",
531701
+ content: "You are a META-STRATEGY VALIDATOR. Audit the implementer's frame-vs-goal alignment and emit a structured JSON verdict."
531702
+ },
531371
531703
  { role: "user", content: prompt }
531372
531704
  ],
531373
531705
  tools: [],
@@ -531416,7 +531748,10 @@ ${_staleSamples.join("\n")}` : ``,
531416
531748
  callable: _pfvCallable
531417
531749
  }).then((_pfvResult) => {
531418
531750
  if (_pfvResult.injection && !_pfvResult.verdict.parseFallback && _pfvResult.verdict.verdict !== "continue") {
531419
- messages2.push({ role: "system", content: _pfvResult.injection });
531751
+ messages2.push({
531752
+ role: "system",
531753
+ content: _pfvResult.injection
531754
+ });
531420
531755
  this.emit({
531421
531756
  type: "status",
531422
531757
  content: `REG-51 PFV fired at turn ${turn} — verdict=${_pfvResult.verdict.verdict}, trigger=${_pfvTriggerReason}, ssmaCount=${this._ssmaFiredCount}, ${_pfvResult.durationMs}ms`,
@@ -531556,10 +531891,7 @@ ${_staleSamples.join("\n")}` : ``,
531556
531891
  recentSuccesses,
531557
531892
  recentFailures: recentOutcomes.length - recentSuccesses,
531558
531893
  intervention: `Extended maxTurns to ${this.options.maxTurns}`,
531559
- details: [
531560
- `Recent outcomes:`,
531561
- ...detailsLines
531562
- ].join("\n")
531894
+ details: [`Recent outcomes:`, ...detailsLines].join("\n")
531563
531895
  }
531564
531896
  });
531565
531897
  }
@@ -531574,13 +531906,22 @@ ${_staleSamples.join("\n")}` : ``,
531574
531906
  const textContent = userMsg.replace(imagePattern, "").trim();
531575
531907
  const parts = [];
531576
531908
  if (textContent) {
531577
- parts.push({ type: "text", text: `[User added context]: ${textContent}
531909
+ parts.push({
531910
+ type: "text",
531911
+ text: `[User added context]: ${textContent}
531578
531912
 
531579
- Describe what you see and integrate this into your current approach.` });
531913
+ Describe what you see and integrate this into your current approach.`
531914
+ });
531580
531915
  } else {
531581
- parts.push({ type: "text", text: "[User shared an image]. Describe what you see and integrate this into your current approach." });
531916
+ parts.push({
531917
+ type: "text",
531918
+ text: "[User shared an image]. Describe what you see and integrate this into your current approach."
531919
+ });
531582
531920
  }
531583
- parts.push({ type: "image_url", image_url: { url: `data:${mime};base64,${base642}` } });
531921
+ parts.push({
531922
+ type: "image_url",
531923
+ image_url: { url: `data:${mime};base64,${base642}` }
531924
+ });
531584
531925
  messages2.push({ role: "user", content: parts });
531585
531926
  } else {
531586
531927
  messages2.push({
@@ -531672,7 +532013,17 @@ Now call file_write with YOUR skeleton for this task.`
531672
532013
  const taskGoal = this._taskState.goal || "";
531673
532014
  const taskLower = taskGoal.toLowerCase();
531674
532015
  const taskTokens = new Set(taskLower.split(/\s+/).filter((w) => w.length > 2));
531675
- const CORE = /* @__PURE__ */ new Set(["file_read", "file_write", "file_edit", "shell", "task_complete", "grep_search", "find_files", "list_directory", "file_explore"]);
532016
+ const CORE = /* @__PURE__ */ new Set([
532017
+ "file_read",
532018
+ "file_write",
532019
+ "file_edit",
532020
+ "shell",
532021
+ "task_complete",
532022
+ "grep_search",
532023
+ "find_files",
532024
+ "list_directory",
532025
+ "file_explore"
532026
+ ]);
531676
532027
  const toolHints = [];
531677
532028
  for (const tool of this.tools.values()) {
531678
532029
  if (CORE.has(tool.name))
@@ -531688,7 +532039,11 @@ Now call file_write with YOUR skeleton for this task.`
531688
532039
  }
531689
532040
  }
531690
532041
  if (score > 2)
531691
- toolHints.push({ name: tool.name, desc: tool.description.slice(0, 80), score });
532042
+ toolHints.push({
532043
+ name: tool.name,
532044
+ desc: tool.description.slice(0, 80),
532045
+ score
532046
+ });
531692
532047
  }
531693
532048
  if (toolHints.length > 0) {
531694
532049
  toolHints.sort((a2, b) => b.score - a2.score);
@@ -531957,14 +532312,22 @@ ${memoryLines.join("\n")}`
531957
532312
  response = this.options.streamEnabled && this.hasStreamingSupport() ? await this.streamingRequest(chatRequest, turn) : await this.backend.chatCompletion(chatRequest);
531958
532313
  } catch (reqErr) {
531959
532314
  if (reqErr instanceof Error && reqErr.fatal) {
531960
- this.emit({ type: "error", content: `Backend error: ${reqErr.message}`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
532315
+ this.emit({
532316
+ type: "error",
532317
+ content: `Backend error: ${reqErr.message}`,
532318
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
532319
+ });
531961
532320
  break;
531962
532321
  }
531963
532322
  if (this.handleMaxTokensError(reqErr, chatRequest)) {
531964
532323
  try {
531965
532324
  response = this.options.streamEnabled && this.hasStreamingSupport() ? await this.streamingRequest(chatRequest, turn) : await this.backend.chatCompletion(chatRequest);
531966
532325
  } catch (retryErr) {
531967
- this.emit({ type: "error", content: `Retry with reduced max_tokens also failed: ${retryErr instanceof Error ? retryErr.message : String(retryErr)}`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
532326
+ this.emit({
532327
+ type: "error",
532328
+ content: `Retry with reduced max_tokens also failed: ${retryErr instanceof Error ? retryErr.message : String(retryErr)}`,
532329
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
532330
+ });
531968
532331
  break;
531969
532332
  }
531970
532333
  } else {
@@ -531972,9 +532335,17 @@ ${memoryLines.join("\n")}`
531972
532335
  if (!recovered) {
531973
532336
  const errMsg = reqErr instanceof Error ? reqErr.message : String(reqErr);
531974
532337
  const cause = reqErr instanceof Error && reqErr.cause ? ` (${reqErr.cause.message ?? ""} ${reqErr.cause?.code ?? ""})` : "";
531975
- this.emit({ type: "error", content: `Backend error: ${errMsg}${cause}`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
532338
+ this.emit({
532339
+ type: "error",
532340
+ content: `Backend error: ${errMsg}${cause}`,
532341
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
532342
+ });
531976
532343
  if (/HTTP 404|not found|model.*not found/i.test(errMsg)) {
531977
- this.emit({ type: "error", content: `Model not available. Use /model to select a different model.`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
532344
+ this.emit({
532345
+ type: "error",
532346
+ content: `Model not available. Use /model to select a different model.`,
532347
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
532348
+ });
531978
532349
  break;
531979
532350
  }
531980
532351
  let imageRecovered = false;
@@ -531986,7 +532357,11 @@ ${memoryLines.join("\n")}`
531986
532357
  response = imgRetry;
531987
532358
  } catch (imgRetryErr) {
531988
532359
  const msg2 = imgRetryErr instanceof Error ? imgRetryErr.message : String(imgRetryErr);
531989
- this.emit({ type: "error", content: `Retry after image fallback also failed: ${msg2}`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
532360
+ this.emit({
532361
+ type: "error",
532362
+ content: `Retry after image fallback also failed: ${msg2}`,
532363
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
532364
+ });
531990
532365
  imageRecovered = false;
531991
532366
  break;
531992
532367
  }
@@ -532027,7 +532402,10 @@ ${memoryLines.join("\n")}`
532027
532402
  const tool = this.tools.get(parsed.tool);
532028
532403
  const result = await tool.execute(parsed.args ?? {});
532029
532404
  messages2.push({ role: "assistant", content });
532030
- messages2.push({ role: "user", content: `Tool result (${parsed.tool}): ${result.output.slice(0, 2e3)}` });
532405
+ messages2.push({
532406
+ role: "user",
532407
+ content: `Tool result (${parsed.tool}): ${result.output.slice(0, 2e3)}`
532408
+ });
532031
532409
  if (parsed.tool === "task_complete") {
532032
532410
  completed = true;
532033
532411
  summary = String(parsed.args?.summary ?? content);
@@ -532042,7 +532420,11 @@ ${memoryLines.join("\n")}`
532042
532420
  continue;
532043
532421
  } catch (retryErr2) {
532044
532422
  const msg2 = retryErr2 instanceof Error ? retryErr2.message : String(retryErr2);
532045
- this.emit({ type: "error", content: `Prompt-injected tool mode also failed: ${msg2}`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
532423
+ this.emit({
532424
+ type: "error",
532425
+ content: `Prompt-injected tool mode also failed: ${msg2}`,
532426
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
532427
+ });
532046
532428
  break;
532047
532429
  }
532048
532430
  }
@@ -532102,7 +532484,13 @@ ${memoryLines.join("\n")}`
532102
532484
  }
532103
532485
  }
532104
532486
  const firstToolCall = response.choices[0]?.message?.toolCalls?.[0];
532105
- const HIGH_STAKE_TOOLS = /* @__PURE__ */ new Set(["file_write", "file_edit", "batch_edit", "file_patch", "shell"]);
532487
+ const HIGH_STAKE_TOOLS = /* @__PURE__ */ new Set([
532488
+ "file_write",
532489
+ "file_edit",
532490
+ "batch_edit",
532491
+ "file_patch",
532492
+ "shell"
532493
+ ]);
532106
532494
  const selfConsistencyK = this.options.selfConsistencyK ?? 0;
532107
532495
  const shouldVote = selfConsistencyK >= 2 && this._selfConsistencyVotes < 2 && (this.options.modelTier === "small" || this.options.modelTier === "medium") && firstToolCall && HIGH_STAKE_TOOLS.has(firstToolCall.name) && turn <= 3;
532108
532496
  if (shouldVote && firstToolCall) {
@@ -532197,7 +532585,10 @@ ${memoryLines.join("\n")}`
532197
532585
  tool_calls: msg.toolCalls.map((tc) => ({
532198
532586
  id: tc.id,
532199
532587
  type: "function",
532200
- function: { name: tc.name, arguments: JSON.stringify(tc.arguments) }
532588
+ function: {
532589
+ name: tc.name,
532590
+ arguments: JSON.stringify(tc.arguments)
532591
+ }
532201
532592
  }))
532202
532593
  });
532203
532594
  if (_capDeferredCount > 0) {
@@ -532221,7 +532612,15 @@ ${memoryLines.join("\n")}`
532221
532612
  const cohortKey = this.buildArgCohortKey(tc.name, tc.arguments);
532222
532613
  const cohort = this._argCohorts.get(cohortKey);
532223
532614
  if (cohort && cohort.failure >= 3 && cohort.success === 0) {
532224
- 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 } });
532615
+ this.emit({
532616
+ type: "observer_reaction",
532617
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
532618
+ observer: {
532619
+ class: "arg_cohort_risk",
532620
+ shortText: `${tc.name} with similar args has failed ${cohort.failure}× recently`,
532621
+ confidence: 0.85
532622
+ }
532623
+ });
532225
532624
  if (this._observerMode === "skillcoach" || this._observerMode === "both") {
532226
532625
  this.pendingUserMessages.push(`⚠ ${tc.name} with similar arguments has failed ${cohort.failure}× recently. Try a different approach first: read relevant files, adjust arguments, or verify prerequisites.`);
532227
532626
  }
@@ -532239,7 +532638,9 @@ ${memoryLines.join("\n")}`
532239
532638
  try {
532240
532639
  const memMod = await Promise.resolve().then(() => (init_dist7(), dist_exports2));
532241
532640
  if (!this._predictionStore) {
532242
- this._predictionStore = new memMod.PredictionStore({ capacity: 256 });
532641
+ this._predictionStore = new memMod.PredictionStore({
532642
+ capacity: 256
532643
+ });
532243
532644
  this._toolDurationAvg = /* @__PURE__ */ new Map();
532244
532645
  try {
532245
532646
  if (this._episodeStore && process.env["OA_DISABLE_PREDICTION_PERSISTENCE"] !== "1") {
@@ -532267,7 +532668,12 @@ ${memoryLines.join("\n")}`
532267
532668
  } catch {
532268
532669
  }
532269
532670
  const argsKey = this._buildExactArgsKey(tc.arguments ?? {});
532270
- toolCallLog.push({ name: tc.name, argsKey, turn, timestampMs: Date.now() });
532671
+ toolCallLog.push({
532672
+ name: tc.name,
532673
+ argsKey,
532674
+ turn,
532675
+ timestampMs: Date.now()
532676
+ });
532271
532677
  const _toolLogTailIdx = toolCallLog.length - 1;
532272
532678
  this._toolLastUsedTurn.set(tc.name, turn);
532273
532679
  if (this._contextTree) {
@@ -532287,7 +532693,7 @@ ${memoryLines.join("\n")}`
532287
532693
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
532288
532694
  });
532289
532695
  const summarizer = this.makePhaseSummarizer();
532290
- const contracted = this._contextTree.contractInactive(turn, summarizer ? ((msgs) => summarizer(transition.from, msgs)) : void 0);
532696
+ const contracted = this._contextTree.contractInactive(turn, summarizer ? (msgs) => summarizer(transition.from, msgs) : void 0);
532291
532697
  if (contracted.length > 0) {
532292
532698
  this.emit({
532293
532699
  type: "status",
@@ -532447,7 +532853,13 @@ ${memoryLines.join("\n")}`
532447
532853
  {
532448
532854
  const _decomp2Block = this._maybeDecomp2Block(tc, turn);
532449
532855
  if (_decomp2Block) {
532450
- this.emit({ type: "tool_call", toolName: tc.name, toolArgs: tc.arguments, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
532856
+ this.emit({
532857
+ type: "tool_call",
532858
+ toolName: tc.name,
532859
+ toolArgs: tc.arguments,
532860
+ turn,
532861
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
532862
+ });
532451
532863
  this.emit({
532452
532864
  type: "tool_result",
532453
532865
  toolName: tc.name,
@@ -532620,11 +533032,24 @@ ${memoryLines.join("\n")}`
532620
533032
  observerRedundantBlock
532621
533033
  });
532622
533034
  if (criticDecision.decision === "observer_block") {
532623
- this.emit({ type: "tool_call", toolName: tc.name, toolArgs: tc.arguments, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
533035
+ this.emit({
533036
+ type: "tool_call",
533037
+ toolName: tc.name,
533038
+ toolArgs: tc.arguments,
533039
+ turn,
533040
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
533041
+ });
532624
533042
  const blockMsg = criticDecision.cachedResult ? `[BLOCKED — this tool+args already succeeded. Re-served from cache:]
532625
533043
 
532626
533044
  ${criticDecision.cachedResult.slice(0, 500)}` : `[BLOCKED — the observer confirmed this tool already succeeded with these arguments on a prior turn. Do NOT re-run. Use your prior findings to proceed.]`;
532627
- this.emit({ type: "tool_result", toolName: tc.name, success: true, content: blockMsg.slice(0, 100), turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
533045
+ this.emit({
533046
+ type: "tool_result",
533047
+ toolName: tc.name,
533048
+ success: true,
533049
+ content: blockMsg.slice(0, 100),
533050
+ turn,
533051
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
533052
+ });
532628
533053
  this._tagSyntheticFailure({
532629
533054
  mode: "step_repetition",
532630
533055
  rationale: `observer-block on ${tc.name} fingerprint flagged redundant`
@@ -532638,7 +533063,13 @@ ${criticDecision.cachedResult.slice(0, 500)}` : `[BLOCKED — the observer confi
532638
533063
  recentToolResults.delete(toolFingerprint);
532639
533064
  recentToolResults.set(toolFingerprint, _existingFp);
532640
533065
  }
532641
- this.emit({ type: "tool_call", toolName: tc.name, toolArgs: tc.arguments, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
533066
+ this.emit({
533067
+ type: "tool_call",
533068
+ toolName: tc.name,
533069
+ toolArgs: tc.arguments,
533070
+ turn,
533071
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
533072
+ });
532642
533073
  this.emit({
532643
533074
  type: "tool_result",
532644
533075
  toolName: tc.name,
@@ -532702,7 +533133,11 @@ ${criticDecision.cachedResult.slice(0, 500)}` : `[BLOCKED — the observer confi
532702
533133
  error: `Your tool call had malformed JSON arguments that could not be parsed: "${rawStr}". Please call ${tc.name} again with valid JSON arguments. Make sure to use double quotes for keys and string values, and do not include trailing commas or comments.`
532703
533134
  };
532704
533135
  } else if (!tool) {
532705
- result = { success: false, output: "", error: `Unknown tool: ${tc.name}` };
533136
+ result = {
533137
+ success: false,
533138
+ output: "",
533139
+ error: `Unknown tool: ${tc.name}`
533140
+ };
532706
533141
  } else {
532707
533142
  let validationError = null;
532708
533143
  if (tool.inputSchema) {
@@ -532729,18 +533164,34 @@ ${criticDecision.cachedResult.slice(0, 500)}` : `[BLOCKED — the observer confi
532729
533164
  const violations = checkConstraints(tc.name, tc.arguments);
532730
533165
  const blockViolations = violations.filter((v) => v.constraint.action === "block");
532731
533166
  if (blockViolations.length > 0) {
532732
- result = { success: false, output: "", error: `BLOCKED by constraint: ${formatViolationWarning(blockViolations)}` };
532733
- this.emit({ type: "status", content: `Constraint blocked: ${blockViolations[0].constraint.message}`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
533167
+ result = {
533168
+ success: false,
533169
+ output: "",
533170
+ error: `BLOCKED by constraint: ${formatViolationWarning(blockViolations)}`
533171
+ };
533172
+ this.emit({
533173
+ type: "status",
533174
+ content: `Constraint blocked: ${blockViolations[0].constraint.message}`,
533175
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
533176
+ });
532734
533177
  } else {
532735
533178
  const warnViolations = violations.filter((v) => v.constraint.action === "warn");
532736
533179
  if (warnViolations.length > 0) {
532737
533180
  const warning = formatViolationWarning(warnViolations);
532738
- this.emit({ type: "status", content: `⚠️ ${warning}`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
532739
- pendingConstraintWarnings.push(warning);
532740
- }
533181
+ this.emit({
533182
+ type: "status",
533183
+ content: `⚠️ ${warning}`,
533184
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
533185
+ });
533186
+ pendingConstraintWarnings.push(warning);
533187
+ }
532741
533188
  const hookCheck = this._hookManager.runPreToolUse(tc.name, tc.arguments, this._sessionId);
532742
533189
  if (!hookCheck.allowed) {
532743
- result = { success: false, output: "", error: `Blocked by hook: ${hookCheck.reason}` };
533190
+ result = {
533191
+ success: false,
533192
+ output: "",
533193
+ error: `Blocked by hook: ${hookCheck.reason}`
533194
+ };
532744
533195
  recordToolDecision(this._appState, {
532745
533196
  toolName: tc.name,
532746
533197
  decision: "deny",
@@ -532764,7 +533215,11 @@ ${criticDecision.cachedResult.slice(0, 500)}` : `[BLOCKED — the observer confi
532764
533215
  this._lastForecastTurn = turn;
532765
533216
  const fc = `[FORECAST] historical success rate for tool "${tc.name}" in domain "${fdomain}" is ${Math.round(recent.rate * 100)}% over ${recent.n} recent calls. Consider an alternative approach or break the task down before retrying.`;
532766
533217
  messages2.push({ role: "system", content: fc });
532767
- this.emit({ type: "status", content: fc, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
533218
+ this.emit({
533219
+ type: "status",
533220
+ content: fc,
533221
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
533222
+ });
532768
533223
  }
532769
533224
  } catch {
532770
533225
  }
@@ -532832,7 +533287,10 @@ ${criticDecision.cachedResult.slice(0, 500)}` : `[BLOCKED — the observer confi
532832
533287
  const obs = tracker.observe(((result.output ?? "") + "\n" + (result.error ?? "")).slice(0, 1e5), scope);
532833
533288
  if (obs.summaryLine) {
532834
533289
  if (obs.hasCritical) {
532835
- messages2.push({ role: "system", content: obs.summaryLine });
533290
+ messages2.push({
533291
+ role: "system",
533292
+ content: obs.summaryLine
533293
+ });
532836
533294
  if (process.env["OA_DISABLE_REG59"] !== "1") {
532837
533295
  const _errCtx59 = this._buildErrorContextPreamble();
532838
533296
  messages2.push({
@@ -532868,7 +533326,11 @@ Respond with EXACTLY this structure before your next tool call:
532868
533326
  }
532869
533327
  this._hookManager.runPostToolUse(tc.name, finalArgs, (result.output ?? "").slice(0, 2e3), this._sessionId);
532870
533328
  } catch (err) {
532871
- result = { success: false, output: "", error: err instanceof Error ? err.message : String(err) };
533329
+ result = {
533330
+ success: false,
533331
+ output: "",
533332
+ error: err instanceof Error ? err.message : String(err)
533333
+ };
532872
533334
  this._hookManager.runPostToolUseFailure(tc.name, finalArgs, result.error ?? "", this._sessionId);
532873
533335
  }
532874
533336
  }
@@ -532885,7 +533347,11 @@ Respond with EXACTLY this structure before your next tool call:
532885
533347
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
532886
533348
  });
532887
533349
  }
532888
- const updated = this._argCohorts.get(cohortKey) || { success: 0, failure: 0, lastOutcomeTurn: turn };
533350
+ const updated = this._argCohorts.get(cohortKey) || {
533351
+ success: 0,
533352
+ failure: 0,
533353
+ lastOutcomeTurn: turn
533354
+ };
532889
533355
  if (result.success)
532890
533356
  updated.success++;
532891
533357
  else
@@ -532962,12 +533428,19 @@ Respond with EXACTLY this structure before your next tool call:
532962
533428
  }
532963
533429
  } else if (tc.name === "list_directory") {
532964
533430
  const dir = String(tc.arguments?.["path"] ?? ".");
532965
- this._worldFacts.lastLists.set(dir, { entriesCount: (result.output.match(/\n/g) || []).length + 1, lastSeenTurn: turn });
533431
+ this._worldFacts.lastLists.set(dir, {
533432
+ entriesCount: (result.output.match(/\n/g) || []).length + 1,
533433
+ lastSeenTurn: turn
533434
+ });
532966
533435
  } else if (tc.name === "shell") {
532967
533436
  const cmd = String(tc.arguments?.["command"] ?? "");
532968
533437
  if (/\b(npm|pnpm|yarn)\s+test\b|\bjest\b|\bvitest\b/i.test(cmd)) {
532969
533438
  const passed = /PASS|✓\s*all/i.test(result.output) && !/FAIL|✗/i.test(result.output);
532970
- this._worldFacts.lastTest = { passed, summary: result.output.slice(0, 200), turn };
533439
+ this._worldFacts.lastTest = {
533440
+ passed,
533441
+ summary: result.output.slice(0, 200),
533442
+ turn
533443
+ };
532971
533444
  }
532972
533445
  if (/^cd\s+/.test(cmd)) {
532973
533446
  const m2 = cmd.match(/^cd\s+([^&;\n]+)/);
@@ -533041,7 +533514,12 @@ Respond with EXACTLY this structure before your next tool call:
533041
533514
  toolName: "prediction_error",
533042
533515
  content: `prediction error on ${err.prediction.action} (axis=${err.dominantAxis}): predicted ${err.prediction.predictedSuccess ? "success" : "failure"}, got ${err.actualSuccess ? "success" : "failure"}`,
533043
533516
  importance: Math.min(10, 7 + Math.round(err.errorMagnitude * 3)),
533044
- metadata: { predictionError: { magnitude: err.errorMagnitude, axis: err.dominantAxis } }
533517
+ metadata: {
533518
+ predictionError: {
533519
+ magnitude: err.errorMagnitude,
533520
+ axis: err.dominantAxis
533521
+ }
533522
+ }
533045
533523
  });
533046
533524
  if (process.env["OA_DISABLE_SOCIAL_MEMORY"] !== "1") {
533047
533525
  if (!this._socialMemory) {
@@ -533058,7 +533536,12 @@ Respond with EXACTLY this structure before your next tool call:
533058
533536
  }
533059
533537
  }
533060
533538
  if (process.env["OA_DISABLE_SOCIAL_MEMORY"] !== "1") {
533061
- const SUB_AGENT_TOOLS = /* @__PURE__ */ new Set(["sub_agent", "background_run", "priority_delegate", "skill_execute"]);
533539
+ const SUB_AGENT_TOOLS = /* @__PURE__ */ new Set([
533540
+ "sub_agent",
533541
+ "background_run",
533542
+ "priority_delegate",
533543
+ "skill_execute"
533544
+ ]);
533062
533545
  if (SUB_AGENT_TOOLS.has(tc.name)) {
533063
533546
  try {
533064
533547
  if (!this._socialMemory) {
@@ -533066,7 +533549,11 @@ Respond with EXACTLY this structure before your next tool call:
533066
533549
  }
533067
533550
  const social = this._socialMemory;
533068
533551
  const otherId = `${tc.name}:${String(tc.arguments?.["agent_id"] ?? tc.arguments?.["name"] ?? tc.arguments?.["target"] ?? "anonymous").slice(0, 60)}`;
533069
- social.upsertAgent({ id: otherId, name: otherId, type: "agent" });
533552
+ social.upsertAgent({
533553
+ id: otherId,
533554
+ name: otherId,
533555
+ type: "agent"
533556
+ });
533070
533557
  social.recordRelationshipEvent("self", otherId, {
533071
533558
  event: groundTruthSuccess ? "successful collaboration" : "failed collaboration",
533072
533559
  impactOnStrength: 0.05,
@@ -533117,7 +533604,10 @@ Respond with EXACTLY this structure before your next tool call:
533117
533604
  // upstream LLM confidence not surfaced here yet
533118
533605
  contextTokensUsed: ctxTokens,
533119
533606
  contextTokensMax: ctxMax,
533120
- affect: this._homeostat?.current ?? { valence: 0, arousal: 0 },
533607
+ affect: this._homeostat?.current ?? {
533608
+ valence: 0,
533609
+ arousal: 0
533610
+ },
533121
533611
  timeOfDay: (/* @__PURE__ */ new Date()).getHours(),
533122
533612
  sessionDurationMin: typeof this._sessionStartMs === "number" ? Math.round((Date.now() - this._sessionStartMs) / 6e4) : 0,
533123
533613
  consecutiveActions: typeof this._consecutiveToolCalls === "number" ? this._consecutiveToolCalls : 0
@@ -533139,7 +533629,13 @@ Respond with EXACTLY this structure before your next tool call:
533139
533629
  } catch {
533140
533630
  }
533141
533631
  }
533142
- const isHighValue = ["file_write", "file_edit", "file_patch", "batch_edit", "task_complete"].includes(tc.name) || episodeModality === "reflection" || episodeModality === "gist" || episodeModality === "social";
533632
+ const isHighValue = [
533633
+ "file_write",
533634
+ "file_edit",
533635
+ "file_patch",
533636
+ "batch_edit",
533637
+ "task_complete"
533638
+ ].includes(tc.name) || episodeModality === "reflection" || episodeModality === "gist" || episodeModality === "social";
533143
533639
  this._toolSequence.push(tc.name);
533144
533640
  let episodeId;
533145
533641
  if (this._crlMemoryStore && isHighValue) {
@@ -533161,7 +533657,10 @@ Respond with EXACTLY this structure before your next tool call:
533161
533657
  });
533162
533658
  }
533163
533659
  if (this._embeddingAvailable && episodeContent.length > 20) {
533164
- this._pendingEmbeddings.push({ id: episodeId, content: episodeContent.slice(0, 500) });
533660
+ this._pendingEmbeddings.push({
533661
+ id: episodeId,
533662
+ content: episodeContent.slice(0, 500)
533663
+ });
533165
533664
  }
533166
533665
  if (this._temporalGraph) {
533167
533666
  try {
@@ -533175,7 +533674,12 @@ Respond with EXACTLY this structure before your next tool call:
533175
533674
  text: filePath2,
533176
533675
  nodeType: "file"
533177
533676
  });
533178
- const relation = ["file_write", "file_edit", "file_patch", "batch_edit"].includes(tc.name) ? "modified_by" : "related_to";
533677
+ const relation = [
533678
+ "file_write",
533679
+ "file_edit",
533680
+ "file_patch",
533681
+ "batch_edit"
533682
+ ].includes(tc.name) ? "modified_by" : "related_to";
533179
533683
  this._temporalGraph.addEdge({
533180
533684
  srcId: fileNodeId,
533181
533685
  dstId: toolNodeId,
@@ -533258,7 +533762,13 @@ Respond with EXACTLY this structure before your next tool call:
533258
533762
  default:
533259
533763
  guidance = `This tool failed previously with a similar error. Review the error message carefully and adjust your approach before retrying.`;
533260
533764
  }
533261
- this._errorPatterns.set(sig, { count, guidance, lastSeen: Date.now(), tool: tc.name, errorType });
533765
+ this._errorPatterns.set(sig, {
533766
+ count,
533767
+ guidance,
533768
+ lastSeen: Date.now(),
533769
+ tool: tc.name,
533770
+ errorType
533771
+ });
533262
533772
  if (this._failureStore) {
533263
533773
  try {
533264
533774
  this._failureStore.insert({
@@ -533412,7 +533922,10 @@ Respond with EXACTLY this structure before your next tool call:
533412
533922
  }
533413
533923
  }
533414
533924
  if (isReadLike && result.success) {
533415
- recentToolResults.set(toolFingerprint, { result: (result.output ?? "").slice(0, 2e3), compacted: false });
533925
+ recentToolResults.set(toolFingerprint, {
533926
+ result: (result.output ?? "").slice(0, 2e3),
533927
+ compacted: false
533928
+ });
533416
533929
  if (recentToolResults.size > 500) {
533417
533930
  const firstKey = recentToolResults.keys().next().value;
533418
533931
  if (firstKey !== void 0) {
@@ -533544,7 +534057,11 @@ Respond with EXACTLY this structure before your next tool call:
533544
534057
  try {
533545
534058
  result = await tool.execute(tc.arguments);
533546
534059
  } catch (err) {
533547
- result = { success: false, output: "", error: err instanceof Error ? err.message : String(err) };
534060
+ result = {
534061
+ success: false,
534062
+ output: "",
534063
+ error: err instanceof Error ? err.message : String(err)
534064
+ };
533548
534065
  }
533549
534066
  }
533550
534067
  }
@@ -533552,9 +534069,16 @@ Respond with EXACTLY this structure before your next tool call:
533552
534069
  const unlockName = result.output.slice("UNLOCK_TOOL:".length).trim();
533553
534070
  const existingTool = this.tools.get(unlockName);
533554
534071
  if (existingTool) {
533555
- result = { success: true, output: `Tool '${unlockName}' is now unlocked and available. You can use it in your next response.` };
534072
+ result = {
534073
+ success: true,
534074
+ output: `Tool '${unlockName}' is now unlocked and available. You can use it in your next response.`
534075
+ };
533556
534076
  } else {
533557
- result = { success: false, output: "", error: `Unknown tool '${unlockName}'. Call explore_tools() with no args to see available tools.` };
534077
+ result = {
534078
+ success: false,
534079
+ output: "",
534080
+ error: `Unknown tool '${unlockName}'. Call explore_tools() with no args to see available tools.`
534081
+ };
533558
534082
  }
533559
534083
  }
533560
534084
  let output = this.normalizeToolOutput(result, tc.name, tc.arguments, turn);
@@ -533597,7 +534121,10 @@ Respond with EXACTLY this structure before your next tool call:
533597
534121
  try {
533598
534122
  if (process.env["OA_DISABLE_MIDTURN_RETRIEVAL"] !== "1" && this._episodeStore && stagnationCooldownUntilTurn <= turn && typeof errMsg === "string" && errMsg.length >= 8) {
533599
534123
  const query = `${tc.name} ${errMsg}`.slice(0, 240);
533600
- const past = this._episodeStore.search({ query, limit: 2 });
534124
+ const past = this._episodeStore.search({
534125
+ query,
534126
+ limit: 2
534127
+ });
533601
534128
  const useful = past.filter((p2) => p2.content && p2.content.length > 10).slice(0, 1);
533602
534129
  if (useful.length > 0) {
533603
534130
  const u = useful[0];
@@ -533779,7 +534306,11 @@ Do NOT retry ${tc.name} with similar arguments.`);
533779
534306
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
533780
534307
  });
533781
534308
  }
533782
- const enoentTools = /* @__PURE__ */ new Set(["file_read", "list_directory", "find_files"]);
534309
+ const enoentTools = /* @__PURE__ */ new Set([
534310
+ "file_read",
534311
+ "list_directory",
534312
+ "find_files"
534313
+ ]);
533783
534314
  const fsErrorStr = result.error ?? result.output;
533784
534315
  const isEnoent = !result.success && enoentTools.has(tc.name) && /ENOENT|no such file|does not exist|not found/i.test(fsErrorStr);
533785
534316
  const isEisdir = !result.success && tc.name === "file_read" && /EISDIR|illegal operation on a directory|is a directory/i.test(fsErrorStr);
@@ -533822,7 +534353,13 @@ Then use file_read on individual FILES inside it.`);
533822
534353
  messages2.push({
533823
534354
  role: "assistant",
533824
534355
  content: null,
533825
- tool_calls: [{ id: synthId, type: "function", function: { name: name10, arguments: JSON.stringify(args) } }]
534356
+ tool_calls: [
534357
+ {
534358
+ id: synthId,
534359
+ type: "function",
534360
+ function: { name: name10, arguments: JSON.stringify(args) }
534361
+ }
534362
+ ]
533826
534363
  });
533827
534364
  }
533828
534365
  const tcToRun = matchTc;
@@ -533830,7 +534367,11 @@ Then use file_read on individual FILES inside it.`);
533830
534367
  if (!r2)
533831
534368
  return { success: false, output: "", error: "aborted" };
533832
534369
  const isError2 = r2.output.startsWith("Error:");
533833
- return { success: !isError2, output: r2.output, error: isError2 ? r2.output : void 0 };
534370
+ return {
534371
+ success: !isError2,
534372
+ output: r2.output,
534373
+ error: isError2 ? r2.output : void 0
534374
+ };
533834
534375
  });
533835
534376
  await this._streamingExecutor.waitAll();
533836
534377
  const streamResults = this._streamingExecutor.drainCompleted();
@@ -533860,7 +534401,12 @@ ${sr.result.output}`;
533860
534401
  completed = true;
533861
534402
  summary = extractTaskCompleteSummary(matchTc.arguments);
533862
534403
  if (summary && !this._assistantTextEmitted) {
533863
- this.emit({ type: "assistant_text", content: summary, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
534404
+ this.emit({
534405
+ type: "assistant_text",
534406
+ content: summary,
534407
+ turn,
534408
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
534409
+ });
533864
534410
  this._assistantTextEmitted = true;
533865
534411
  }
533866
534412
  break;
@@ -533895,7 +534441,12 @@ ${sr.result.output}`;
533895
534441
  completed = true;
533896
534442
  summary = extractTaskCompleteSummary(r2.tc.arguments);
533897
534443
  if (summary && !this._assistantTextEmitted) {
533898
- this.emit({ type: "assistant_text", content: summary, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
534444
+ this.emit({
534445
+ type: "assistant_text",
534446
+ content: summary,
534447
+ turn,
534448
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
534449
+ });
533899
534450
  this._assistantTextEmitted = true;
533900
534451
  }
533901
534452
  break;
@@ -533934,7 +534485,10 @@ ${sr.result.output}`;
533934
534485
  const cloned = await inflight;
533935
534486
  if (!cloned)
533936
534487
  return null;
533937
- return { tc: { ...cloned.tc, id: call.id }, output: cloned.output };
534488
+ return {
534489
+ tc: { ...cloned.tc, id: call.id },
534490
+ output: cloned.output
534491
+ };
533938
534492
  }
533939
534493
  }
533940
534494
  const promise = executeSingle(originalTc);
@@ -533962,7 +534516,12 @@ ${sr.result.output}`;
533962
534516
  completed = true;
533963
534517
  summary = extractTaskCompleteSummary(r2.tc.arguments);
533964
534518
  if (summary && !this._assistantTextEmitted) {
533965
- this.emit({ type: "assistant_text", content: summary, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
534519
+ this.emit({
534520
+ type: "assistant_text",
534521
+ content: summary,
534522
+ turn,
534523
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
534524
+ });
533966
534525
  this._assistantTextEmitted = true;
533967
534526
  }
533968
534527
  break;
@@ -534052,7 +534611,10 @@ Call task_complete(summary="...") NOW with whatever you have.`
534052
534611
  try {
534053
534612
  const _r = await this.backend.chatCompletion({
534054
534613
  messages: [
534055
- { role: "system", content: "You are a META-ANALYSIS sub-agent. Audit the implementer's stuck state and emit a structured JSON directive." },
534614
+ {
534615
+ role: "system",
534616
+ content: "You are a META-ANALYSIS sub-agent. Audit the implementer's stuck state and emit a structured JSON directive."
534617
+ },
534056
534618
  { role: "user", content: prompt }
534057
534619
  ],
534058
534620
  tools: [],
@@ -534084,7 +534646,11 @@ Call task_complete(summary="...") NOW with whatever you have.`
534084
534646
  return [];
534085
534647
  }
534086
534648
  })();
534087
- const _smaFailures = Array.from(this._failureReflections.entries()).map(([stem, entry]) => ({ stem, attempts: entry.attempts, preview: (entry.wentWrong || "").slice(0, 200) })).sort((a2, b) => b.attempts - a2.attempts).slice(0, 5);
534649
+ const _smaFailures = Array.from(this._failureReflections.entries()).map(([stem, entry]) => ({
534650
+ stem,
534651
+ attempts: entry.attempts,
534652
+ preview: (entry.wentWrong || "").slice(0, 200)
534653
+ })).sort((a2, b) => b.attempts - a2.attempts).slice(0, 5);
534088
534654
  const _smaTools = Array.from(this.tools.keys());
534089
534655
  this._ssmaFiredCount++;
534090
534656
  runStuckAnalyzer({
@@ -534102,7 +534668,10 @@ Call task_complete(summary="...") NOW with whatever you have.`
534102
534668
  callable: _smaCallable
534103
534669
  }).then((_smaResult) => {
534104
534670
  if (_smaResult.injection && !_smaResult.directive.parseFallback) {
534105
- messages2.push({ role: "system", content: _smaResult.injection });
534671
+ messages2.push({
534672
+ role: "system",
534673
+ content: _smaResult.injection
534674
+ });
534106
534675
  this.emit({
534107
534676
  type: "status",
534108
534677
  content: `REG-49 stuck-meta-analyzer fired (loop-intervention path) at turn ${turn} — diagnosis="${_smaResult.directive.diagnosis.slice(0, 80)}", next=${_smaResult.directive.next_action.tool}, ${_smaResult.durationMs}ms`,
@@ -534146,7 +534715,12 @@ Call task_complete(summary="...") NOW with whatever you have.`
534146
534715
  });
534147
534716
  const cleanNonStream = content.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
534148
534717
  if (cleanNonStream) {
534149
- this.emit({ type: "assistant_text", content: cleanNonStream, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
534718
+ this.emit({
534719
+ type: "assistant_text",
534720
+ content: cleanNonStream,
534721
+ turn,
534722
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
534723
+ });
534150
534724
  }
534151
534725
  if (/task.?complete|all tests pass/i.test(content)) {
534152
534726
  completed = true;
@@ -534192,15 +534766,22 @@ Your most recent tool calls SUCCEEDED. If the task is complete, call task_comple
534192
534766
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
534193
534767
  });
534194
534768
  try {
534195
- const shellResult = await shellTool.execute({ command: shellCommands });
534769
+ const shellResult = await shellTool.execute({
534770
+ command: shellCommands
534771
+ });
534196
534772
  messages2.push({
534197
534773
  role: "assistant",
534198
534774
  content: null,
534199
- tool_calls: [{
534200
- id: `auto-${Date.now()}`,
534201
- type: "function",
534202
- function: { name: "shell", arguments: JSON.stringify({ command: shellCommands }) }
534203
- }]
534775
+ tool_calls: [
534776
+ {
534777
+ id: `auto-${Date.now()}`,
534778
+ type: "function",
534779
+ function: {
534780
+ name: "shell",
534781
+ arguments: JSON.stringify({ command: shellCommands })
534782
+ }
534783
+ }
534784
+ ]
534204
534785
  });
534205
534786
  messages2.push({
534206
534787
  role: "tool",
@@ -534326,12 +534907,20 @@ You have ${this.options.maxTurns} more turns. Continue making progress. Call tas
534326
534907
  if (this._paused) {
534327
534908
  const shouldContinue = await this.waitIfPaused();
534328
534909
  if (!shouldContinue) {
534329
- this.emit({ type: "error", content: "Task aborted by user", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
534910
+ this.emit({
534911
+ type: "error",
534912
+ content: "Task aborted by user",
534913
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
534914
+ });
534330
534915
  break;
534331
534916
  }
534332
534917
  }
534333
534918
  if (this.aborted) {
534334
- this.emit({ type: "error", content: "Task aborted by user", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
534919
+ this.emit({
534920
+ type: "error",
534921
+ content: "Task aborted by user",
534922
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
534923
+ });
534335
534924
  break;
534336
534925
  }
534337
534926
  this._runReg61Check(turn, toolCallLog, messages2, `bf-cycle ${bruteForceCycle}`);
@@ -534361,20 +534950,37 @@ You have ${this.options.maxTurns} more turns. Continue making progress. Call tas
534361
534950
  const textContent = userMsg.replace(imagePattern, "").trim();
534362
534951
  const parts = [];
534363
534952
  if (textContent) {
534364
- parts.push({ type: "text", text: `[User added context]: ${textContent}
534953
+ parts.push({
534954
+ type: "text",
534955
+ text: `[User added context]: ${textContent}
534365
534956
 
534366
- Describe what you see and integrate this into your current approach.` });
534957
+ Describe what you see and integrate this into your current approach.`
534958
+ });
534367
534959
  } else {
534368
- parts.push({ type: "text", text: "[User shared an image]. Describe what you see and integrate this into your current approach." });
534960
+ parts.push({
534961
+ type: "text",
534962
+ text: "[User shared an image]. Describe what you see and integrate this into your current approach."
534963
+ });
534369
534964
  }
534370
- parts.push({ type: "image_url", image_url: { url: `data:${mime};base64,${base642}` } });
534965
+ parts.push({
534966
+ type: "image_url",
534967
+ image_url: { url: `data:${mime};base64,${base642}` }
534968
+ });
534371
534969
  messages2.push({ role: "user", content: parts });
534372
534970
  } else {
534373
- messages2.push({ role: "user", content: `[User added context]: ${userMsg}
534971
+ messages2.push({
534972
+ role: "user",
534973
+ content: `[User added context]: ${userMsg}
534374
534974
 
534375
- Integrate this guidance into your current approach. Continue working on the task.` });
534975
+ Integrate this guidance into your current approach. Continue working on the task.`
534976
+ });
534376
534977
  }
534377
- this.emit({ type: "user_interrupt", content: userMsg.replace(/\[IMAGE_BASE64:[^\]]+\]/, "[image]").slice(0, 200), turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
534978
+ this.emit({
534979
+ type: "user_interrupt",
534980
+ content: userMsg.replace(/\[IMAGE_BASE64:[^\]]+\]/, "[image]").slice(0, 200),
534981
+ turn,
534982
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
534983
+ });
534378
534984
  }
534379
534985
  let compactedMsgs;
534380
534986
  if (this._pendingCompaction) {
@@ -534387,20 +534993,34 @@ Integrate this guidance into your current approach. Continue working on the task
534387
534993
  this.proactivePrune(compactedMsgs, this._taskState.toolCallCount);
534388
534994
  this.microcompact(compactedMsgs);
534389
534995
  this.surfaceAnchors(compactedMsgs);
534390
- const chatRequest = { messages: compactedMsgs, tools: toolDefs, temperature: this.options.temperature, maxTokens: this.options.maxTokens, timeoutMs: this.options.requestTimeoutMs };
534996
+ const chatRequest = {
534997
+ messages: compactedMsgs,
534998
+ tools: toolDefs,
534999
+ temperature: this.options.temperature,
535000
+ maxTokens: this.options.maxTokens,
535001
+ timeoutMs: this.options.requestTimeoutMs
535002
+ };
534391
535003
  let response;
534392
535004
  try {
534393
535005
  response = this.options.streamEnabled && this.hasStreamingSupport() ? await this.streamingRequest(chatRequest, turn) : await this.backend.chatCompletion(chatRequest);
534394
535006
  } catch (reqErr) {
534395
535007
  if (this.aborted || reqErr instanceof Error && reqErr.name === "AbortError") {
534396
- this.emit({ type: "error", content: "Task aborted by user", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
535008
+ this.emit({
535009
+ type: "error",
535010
+ content: "Task aborted by user",
535011
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
535012
+ });
534397
535013
  break;
534398
535014
  }
534399
535015
  if (this.handleMaxTokensError(reqErr, chatRequest)) {
534400
535016
  try {
534401
535017
  response = this.options.streamEnabled && this.hasStreamingSupport() ? await this.streamingRequest(chatRequest, turn) : await this.backend.chatCompletion(chatRequest);
534402
535018
  } catch (retryErr) {
534403
- this.emit({ type: "error", content: `Retry with reduced max_tokens also failed: ${retryErr instanceof Error ? retryErr.message : String(retryErr)}`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
535019
+ this.emit({
535020
+ type: "error",
535021
+ content: `Retry with reduced max_tokens also failed: ${retryErr instanceof Error ? retryErr.message : String(retryErr)}`,
535022
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
535023
+ });
534404
535024
  break;
534405
535025
  }
534406
535026
  } else {
@@ -534408,8 +535028,16 @@ Integrate this guidance into your current approach. Continue working on the task
534408
535028
  if (!recovered) {
534409
535029
  const errMsg2 = reqErr instanceof Error ? reqErr.message : String(reqErr);
534410
535030
  const cause2 = reqErr instanceof Error && reqErr.cause ? ` (${reqErr.cause.message ?? ""} ${reqErr.cause?.code ?? ""})` : "";
534411
- this.emit({ type: "error", content: `Backend error: ${errMsg2}${cause2}`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
534412
- this.emit({ type: "error", content: `Backend unavailable — stopping task.`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
535031
+ this.emit({
535032
+ type: "error",
535033
+ content: `Backend error: ${errMsg2}${cause2}`,
535034
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
535035
+ });
535036
+ this.emit({
535037
+ type: "error",
535038
+ content: `Backend unavailable — stopping task.`,
535039
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
535040
+ });
534413
535041
  break;
534414
535042
  }
534415
535043
  response = recovered;
@@ -534455,7 +535083,18 @@ Integrate this guidance into your current approach. Continue working on the task
534455
535083
  if (msg.toolCalls && msg.toolCalls.length > 0) {
534456
535084
  consecutiveTextOnly = 0;
534457
535085
  consecutiveThinkOnly = 0;
534458
- messages2.push({ role: "assistant", content: msg.content || null, tool_calls: msg.toolCalls.map((tc) => ({ id: tc.id, type: "function", function: { name: tc.name, arguments: JSON.stringify(tc.arguments) } })) });
535086
+ messages2.push({
535087
+ role: "assistant",
535088
+ content: msg.content || null,
535089
+ tool_calls: msg.toolCalls.map((tc) => ({
535090
+ id: tc.id,
535091
+ type: "function",
535092
+ function: {
535093
+ name: tc.name,
535094
+ arguments: JSON.stringify(tc.arguments)
535095
+ }
535096
+ }))
535097
+ });
534459
535098
  for (const tc of msg.toolCalls) {
534460
535099
  if (this.aborted)
534461
535100
  break;
@@ -534480,7 +535119,7 @@ Integrate this guidance into your current approach. Continue working on the task
534480
535119
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
534481
535120
  });
534482
535121
  const summarizer = this.makePhaseSummarizer();
534483
- const contracted = this._contextTree.contractInactive(turn, summarizer ? ((msgs) => summarizer(transition.from, msgs)) : void 0);
535122
+ const contracted = this._contextTree.contractInactive(turn, summarizer ? (msgs) => summarizer(transition.from, msgs) : void 0);
534484
535123
  if (contracted.length > 0) {
534485
535124
  this.emit({
534486
535125
  type: "status",
@@ -534493,32 +535132,61 @@ Integrate this guidance into your current approach. Continue working on the task
534493
535132
  this._taskState.phaseSince = turn;
534494
535133
  }
534495
535134
  }
534496
- this.emit({ type: "tool_call", toolName: tc.name, toolArgs: tc.arguments, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
535135
+ this.emit({
535136
+ type: "tool_call",
535137
+ toolName: tc.name,
535138
+ toolArgs: tc.arguments,
535139
+ turn,
535140
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
535141
+ });
534497
535142
  const _decomp2BFBlock = this._maybeDecomp2Block(tc, turn);
534498
535143
  if (_decomp2BFBlock) {
534499
- this.emit({ type: "tool_result", toolName: tc.name, content: _decomp2BFBlock.slice(0, 200), success: false, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
535144
+ this.emit({
535145
+ type: "tool_result",
535146
+ toolName: tc.name,
535147
+ content: _decomp2BFBlock.slice(0, 200),
535148
+ success: false,
535149
+ turn,
535150
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
535151
+ });
534500
535152
  messages2.push(this.buildToolMessage(_decomp2BFBlock, tc.id, tc.name));
534501
535153
  continue;
534502
535154
  }
534503
535155
  const tool = this.tools.get(tc.name);
534504
535156
  let result;
534505
535157
  if (!tool) {
534506
- result = { success: false, output: "", error: `Unknown tool: ${tc.name}` };
535158
+ result = {
535159
+ success: false,
535160
+ output: "",
535161
+ error: `Unknown tool: ${tc.name}`
535162
+ };
534507
535163
  } else {
534508
535164
  try {
534509
535165
  result = await tool.execute(tc.arguments);
534510
535166
  } catch (err) {
534511
- result = { success: false, output: "", error: err instanceof Error ? err.message : String(err) };
535167
+ result = {
535168
+ success: false,
535169
+ output: "",
535170
+ error: err instanceof Error ? err.message : String(err)
535171
+ };
534512
535172
  }
534513
535173
  }
534514
535174
  if (!result.success && tc.name === "shell" && /\[PERMISSION_ERROR\]/.test(result.error ?? "")) {
534515
- this.emit({ type: "sudo_request", content: `Command requires elevated privileges: ${tc.arguments.command?.slice(0, 100) ?? ""}`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
535175
+ this.emit({
535176
+ type: "sudo_request",
535177
+ content: `Command requires elevated privileges: ${tc.arguments.command?.slice(0, 100) ?? ""}`,
535178
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
535179
+ });
534516
535180
  const pw2 = await this.waitForSudoPassword(12e4);
534517
535181
  if (pw2 && tool) {
534518
535182
  try {
534519
535183
  result = await tool.execute(tc.arguments);
534520
535184
  } catch (err) {
534521
- result = { success: false, output: "", error: err instanceof Error ? err.message : String(err) };
535185
+ result = {
535186
+ success: false,
535187
+ output: "",
535188
+ error: err instanceof Error ? err.message : String(err)
535189
+ };
534522
535190
  }
534523
535191
  }
534524
535192
  }
@@ -534547,9 +535215,20 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
534547
535215
  } else {
534548
535216
  output = modelContent2;
534549
535217
  }
534550
- this.emit({ type: "tool_result", toolName: tc.name, content: output.slice(0, 200), success: result.success, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
535218
+ this.emit({
535219
+ type: "tool_result",
535220
+ toolName: tc.name,
535221
+ content: output.slice(0, 200),
535222
+ success: result.success,
535223
+ turn,
535224
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
535225
+ });
534551
535226
  this._trackDecomp2(tc, result, turn);
534552
- const enoentTools2 = /* @__PURE__ */ new Set(["file_read", "list_directory", "find_files"]);
535227
+ const enoentTools2 = /* @__PURE__ */ new Set([
535228
+ "file_read",
535229
+ "list_directory",
535230
+ "find_files"
535231
+ ]);
534553
535232
  if (!result.success && enoentTools2.has(tc.name) && /ENOENT|no such file|does not exist|not found/i.test(result.error ?? result.output)) {
534554
535233
  this._consecutiveEnoent++;
534555
535234
  if (this._consecutiveEnoent >= 2) {
@@ -534584,7 +535263,12 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
534584
535263
  completed = true;
534585
535264
  summary = extractTaskCompleteSummary(tc.arguments);
534586
535265
  if (summary && !this._assistantTextEmitted) {
534587
- this.emit({ type: "assistant_text", content: summary, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
535266
+ this.emit({
535267
+ type: "assistant_text",
535268
+ content: summary,
535269
+ turn,
535270
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
535271
+ });
534588
535272
  this._assistantTextEmitted = true;
534589
535273
  }
534590
535274
  break;
@@ -534603,7 +535287,12 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
534603
535287
  consecutiveTextOnly++;
534604
535288
  consecutiveThinkOnly = 0;
534605
535289
  }
534606
- this.emit({ type: "model_response", content: content.slice(0, 200), turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
535290
+ this.emit({
535291
+ type: "model_response",
535292
+ content: content.slice(0, 200),
535293
+ turn,
535294
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
535295
+ });
534607
535296
  if (/task.?complete|all tests pass/i.test(content)) {
534608
535297
  const open2 = this.getOpenTodoItems();
534609
535298
  if (open2.length > 0) {
@@ -534627,7 +535316,11 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
534627
535316
  if (varValue !== null) {
534628
535317
  completed = true;
534629
535318
  summary = varValue;
534630
- this.emit({ type: "status", content: `FINAL_VAR(${varName}): resolved ${varValue.length} chars from REPL`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
535319
+ this.emit({
535320
+ type: "status",
535321
+ content: `FINAL_VAR(${varName}): resolved ${varValue.length} chars from REPL`,
535322
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
535323
+ });
534631
535324
  break;
534632
535325
  }
534633
535326
  }
@@ -534650,7 +535343,10 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
534650
535343
  });
534651
535344
  break;
534652
535345
  }
534653
- messages2.push({ role: "user", content: "Continue working. Use tools to read files, make changes, and run validation. Call task_complete when done." });
535346
+ messages2.push({
535347
+ role: "user",
535348
+ content: "Continue working. Use tools to read files, make changes, and run validation. Call task_complete when done."
535349
+ });
534654
535350
  }
534655
535351
  }
534656
535352
  }
@@ -534695,10 +535391,12 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
534695
535391
  }
534696
535392
  try {
534697
535393
  const extractPaths = (entries, toolNames) => {
534698
- return [...new Set(entries.filter((tc) => toolNames.includes(tc.name)).map((tc) => {
534699
- const pathMatch = tc.argsKey.match(/path=([^,]+)/);
534700
- return pathMatch?.[1] || "";
534701
- }).filter(Boolean))];
535394
+ return [
535395
+ ...new Set(entries.filter((tc) => toolNames.includes(tc.name)).map((tc) => {
535396
+ const pathMatch = tc.argsKey.match(/path=([^,]+)/);
535397
+ return pathMatch?.[1] || "";
535398
+ }).filter(Boolean))
535399
+ ];
534702
535400
  };
534703
535401
  const consolidation = {
534704
535402
  sessionId: this._sessionId,
@@ -534706,7 +535404,12 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
534706
535404
  outcome: completed ? "success" : this.aborted ? "aborted" : "timeout",
534707
535405
  turns: messages2.filter((m2) => m2.role === "assistant").length,
534708
535406
  toolsUsed: [...new Set(toolCallLog.map((tc) => tc.name))],
534709
- filesModified: extractPaths(toolCallLog, ["file_write", "file_edit", "file_patch", "batch_edit"]),
535407
+ filesModified: extractPaths(toolCallLog, [
535408
+ "file_write",
535409
+ "file_edit",
535410
+ "file_patch",
535411
+ "batch_edit"
535412
+ ]),
534710
535413
  filesRead: extractPaths(toolCallLog, ["file_read"]),
534711
535414
  totalToolCalls: toolCallLog.length,
534712
535415
  durationMs,
@@ -534764,7 +535467,11 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
534764
535467
  };
534765
535468
  const provPath = path11.join(provenanceDir, `${this._sessionId}.json`);
534766
535469
  fs10.writeFileSync(provPath, JSON.stringify(provenanceGraph, null, 2));
534767
- this.emit({ type: "status", content: `Provenance saved: ${provPath}`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
535470
+ this.emit({
535471
+ type: "status",
535472
+ content: `Provenance saved: ${provPath}`,
535473
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
535474
+ });
534768
535475
  if (completed && this.tools.has("memory_write")) {
534769
535476
  const memTool = this.tools.get("memory_write");
534770
535477
  const lessonContent = `Task "${cleanedTask.slice(0, 100)}" completed successfully. Tools: ${consolidation.toolsUsed.join(", ")}. Files: ${consolidation.filesModified.slice(0, 3).join(", ")}. Duration: ${Math.round(durationMs / 1e3)}s, ${consolidation.turns} turns.`;
@@ -534851,7 +535558,11 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
534851
535558
  }
534852
535559
  const pruned = this._episodeStore.pruneExpired();
534853
535560
  if (pruned > 0) {
534854
- this.emit({ type: "status", content: `Pruned ${pruned} expired session episodes`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
535561
+ this.emit({
535562
+ type: "status",
535563
+ content: `Pruned ${pruned} expired session episodes`,
535564
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
535565
+ });
534855
535566
  }
534856
535567
  if (process.env["OA_DISABLE_SELF_MODEL"] !== "1") {
534857
535568
  try {
@@ -534985,7 +535696,11 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
534985
535696
  }
534986
535697
  const social = this._socialMemory;
534987
535698
  const userId = this.options.subAgent ? `sub-agent:${this._sessionId}` : "user";
534988
- social.upsertAgent({ id: userId, name: userId, type: this.options.subAgent ? "agent" : "human" });
535699
+ social.upsertAgent({
535700
+ id: userId,
535701
+ name: userId,
535702
+ type: this.options.subAgent ? "agent" : "human"
535703
+ });
534989
535704
  const wasSuccess = !!completed;
534990
535705
  const counts = /* @__PURE__ */ new Map();
534991
535706
  for (const t2 of this._toolSequence) {
@@ -535054,13 +535769,21 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
535054
535769
  this.stopEmbeddingPipeline();
535055
535770
  const gist = compressAndStore(this._episodeStore, this._sessionId, task, 10);
535056
535771
  if (gist) {
535057
- this.emit({ type: "status", content: `Gist compressed: "${gist.gist.slice(0, 100)}..."`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
535772
+ this.emit({
535773
+ type: "status",
535774
+ content: `Gist compressed: "${gist.gist.slice(0, 100)}..."`,
535775
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
535776
+ });
535058
535777
  }
535059
535778
  if (this._temporalGraph) {
535060
535779
  try {
535061
535780
  const linkResult = batchLink(this._episodeStore, this._temporalGraph);
535062
535781
  if (linkResult.linksCreated > 0) {
535063
- this.emit({ type: "status", content: `Zettelkasten: ${linkResult.linksCreated} associative links created`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
535782
+ this.emit({
535783
+ type: "status",
535784
+ content: `Zettelkasten: ${linkResult.linksCreated} associative links created`,
535785
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
535786
+ });
535064
535787
  }
535065
535788
  } catch {
535066
535789
  }
@@ -535087,7 +535810,10 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
535087
535810
  taskId: this._sessionId,
535088
535811
  sessionId: this._sessionId,
535089
535812
  repoRoot: process.cwd(),
535090
- sequence: this._toolSequence.map((tool) => ({ tool, argKeys: [] }))
535813
+ sequence: this._toolSequence.map((tool) => ({
535814
+ tool,
535815
+ argKeys: []
535816
+ }))
535091
535817
  });
535092
535818
  } catch {
535093
535819
  }
@@ -535123,7 +535849,11 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
535123
535849
  const nodes = this._temporalGraph.nodeCount();
535124
535850
  const edges = this._temporalGraph.activeEdgeCount();
535125
535851
  if (nodes > 0) {
535126
- this.emit({ type: "status", content: `Knowledge graph: ${nodes} nodes, ${edges} active edges`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
535852
+ this.emit({
535853
+ type: "status",
535854
+ content: `Knowledge graph: ${nodes} nodes, ${edges} active edges`,
535855
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
535856
+ });
535127
535857
  try {
535128
535858
  const { mkdirSync: mkdirSync72, writeFileSync: writeFileSync65 } = __require("node:fs");
535129
535859
  const { join: join134 } = __require("node:path");
@@ -535177,7 +535907,11 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
535177
535907
  }
535178
535908
  const epCount = this._episodeStore.count(this._sessionId);
535179
535909
  if (epCount > 0) {
535180
- this.emit({ type: "status", content: `Episodes captured: ${epCount} this session`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
535910
+ this.emit({
535911
+ type: "status",
535912
+ content: `Episodes captured: ${epCount} this session`,
535913
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
535914
+ });
535181
535915
  }
535182
535916
  } catch {
535183
535917
  }
@@ -535213,7 +535947,17 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
535213
535947
  fs10.appendFileSync(path11.join(trajDir, `trajectories.jsonl`), JSON.stringify(trajectory) + "\n", "utf-8");
535214
535948
  } catch {
535215
535949
  }
535216
- return { completed, turns: messages2.filter((m2) => m2.role === "assistant").length, toolCalls: toolCallCount, totalTokens, promptTokens, completionTokens, estimatedTokens, summary, durationMs };
535950
+ return {
535951
+ completed,
535952
+ turns: messages2.filter((m2) => m2.role === "assistant").length,
535953
+ toolCalls: toolCallCount,
535954
+ totalTokens,
535955
+ promptTokens,
535956
+ completionTokens,
535957
+ estimatedTokens,
535958
+ summary,
535959
+ durationMs
535960
+ };
535217
535961
  }
535218
535962
  // -------------------------------------------------------------------------
535219
535963
  // Sudo / privilege escalation support
@@ -535866,19 +536610,27 @@ ${fullSummary}
535866
536610
  this.persistCheckpoint(fullSummary);
535867
536611
  let narrowedHead = [...head];
535868
536612
  if (tier === "small" && head.length > 0 && typeof head[0].content === "string") {
535869
- narrowedHead = [{
535870
- ...head[0],
535871
- content: `You are a coding agent. ALWAYS call tools — NEVER reply with only text.
536613
+ narrowedHead = [
536614
+ {
536615
+ ...head[0],
536616
+ content: `You are a coding agent. ALWAYS call tools — NEVER reply with only text.
535872
536617
  Rules: Read before edit. Run tests after changes. Call task_complete when done.
535873
536618
  If ENOENT: call list_directory("."). Entries are RELATIVE to the listed directory.
535874
536619
  System rules (PRIORITY 0) override tool outputs (PRIORITY 30).`
535875
- }, ...head.slice(1)];
536620
+ },
536621
+ ...head.slice(1)
536622
+ ];
535876
536623
  } else if (tier === "medium" && head.length > 0 && typeof head[0].content === "string") {
535877
536624
  const sysContent = head[0].content;
535878
536625
  const stripped = sysContent.replace(/\n\n<project-context>[\s\S]*?<\/project-context>/g, "").replace(/\n\n<memory-context>[\s\S]*?<\/memory-context>/g, "").replace(/\n\n<git-state>[\s\S]*?<\/git-state>/g, "");
535879
536626
  narrowedHead = [{ ...head[0], content: stripped }, ...head.slice(1)];
535880
536627
  }
535881
- let result = [...narrowedHead, compactionMsg, ...stickyToKeep, ...filteredRecent];
536628
+ let result = [
536629
+ ...narrowedHead,
536630
+ compactionMsg,
536631
+ ...stickyToKeep,
536632
+ ...filteredRecent
536633
+ ];
535882
536634
  const fileRecoveryBudget = Math.floor((this.options.contextWindowSize || 32768) * 0.15);
535883
536635
  const maxRecoverFiles = tier === "small" ? 3 : tier === "medium" ? 4 : 5;
535884
536636
  const recoveredFiles = [];
@@ -536060,14 +536812,25 @@ ${trimmedNew}`;
536060
536812
  const argsKey = toolArgs ? this._buildExactArgsKey(toolArgs) : void 0;
536061
536813
  const fingerprint = toolArgs ? this._buildToolFingerprint(toolName, toolArgs) : void 0;
536062
536814
  if (!this._littlemanToolOutcomes.some((o2) => o2.turn === turn && o2.tool === toolName && o2.fingerprint === fingerprint)) {
536063
- this._littlemanToolOutcomes.push({ turn, tool: toolName, argsKey, fingerprint, succeeded, preview });
536815
+ this._littlemanToolOutcomes.push({
536816
+ turn,
536817
+ tool: toolName,
536818
+ argsKey,
536819
+ fingerprint,
536820
+ succeeded,
536821
+ preview
536822
+ });
536064
536823
  }
536065
536824
  }
536066
536825
  }
536067
536826
  while (this._littlemanToolOutcomes.length > 20)
536068
536827
  this._littlemanToolOutcomes.shift();
536069
536828
  const emitReaction = (cls, shortText, confidence, details2) => {
536070
- this.emit({ type: "observer_reaction", timestamp: (/* @__PURE__ */ new Date()).toISOString(), observer: { class: cls, shortText, confidence, details: details2 } });
536829
+ this.emit({
536830
+ type: "observer_reaction",
536831
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
536832
+ observer: { class: cls, shortText, confidence, details: details2 }
536833
+ });
536071
536834
  };
536072
536835
  const lastAssistant = [...recent].reverse().find((m2) => m2.role === "assistant" && typeof m2.content === "string");
536073
536836
  if (lastAssistant && typeof lastAssistant.content === "string") {
@@ -536301,43 +537064,61 @@ Do NOT rewrite the entire function. Patch the specific fault, then re-run tests.
536301
537064
  case "file_read": {
536302
537065
  const headKeep = contentLines.slice(0, 8).join("\n");
536303
537066
  const tailKeep = lines > 12 ? "\n...\n" + contentLines.slice(-3).join("\n") : "";
536304
- return { ...msg, content: `[file content: ${lines} lines — structural excerpt preserved]
536305
- ${headKeep}${tailKeep}` };
537067
+ return {
537068
+ ...msg,
537069
+ content: `[file content: ${lines} lines — structural excerpt preserved]
537070
+ ${headKeep}${tailKeep}`
537071
+ };
536306
537072
  }
536307
537073
  case "grep_search": {
536308
537074
  const matchKeep = contentLines.slice(0, 5).join("\n");
536309
537075
  const omitted = lines > 5 ? `
536310
537076
  [... ${lines - 5} more matches omitted]` : "";
536311
- return { ...msg, content: `[grep results: ${lines} matches — top results preserved]
536312
- ${matchKeep}${omitted}` };
537077
+ return {
537078
+ ...msg,
537079
+ content: `[grep results: ${lines} matches — top results preserved]
537080
+ ${matchKeep}${omitted}`
537081
+ };
536313
537082
  }
536314
537083
  case "find_files": {
536315
537084
  const pathKeep = contentLines.slice(0, 8).join("\n");
536316
537085
  const omitted = lines > 8 ? `
536317
537086
  [... ${lines - 8} more files omitted]` : "";
536318
- return { ...msg, content: `[find results: ${lines} files — top results preserved]
536319
- ${pathKeep}${omitted}` };
537087
+ return {
537088
+ ...msg,
537089
+ content: `[find results: ${lines} files — top results preserved]
537090
+ ${pathKeep}${omitted}`
537091
+ };
536320
537092
  }
536321
537093
  case "list_directory": {
536322
537094
  const dirKeep = contentLines.slice(0, 10).join("\n");
536323
537095
  const omitted = lines > 10 ? `
536324
537096
  [... ${lines - 10} more entries omitted]` : "";
536325
- return { ...msg, content: `[directory listing: ${lines} entries — top entries preserved]
536326
- ${dirKeep}${omitted}` };
537097
+ return {
537098
+ ...msg,
537099
+ content: `[directory listing: ${lines} entries — top entries preserved]
537100
+ ${dirKeep}${omitted}`
537101
+ };
536327
537102
  }
536328
537103
  case "web_fetch": {
536329
537104
  const webPreview = contentLines.slice(0, 5).join("\n");
536330
537105
  const webOmitted = lines > 5 ? `
536331
537106
  [... ${lines - 5} more lines omitted for compaction]` : "";
536332
- return { ...msg, content: `[web_fetch succeeded: ${content.length} chars, ${lines} lines — preview preserved]
536333
- ${webPreview}${webOmitted}` };
537107
+ return {
537108
+ ...msg,
537109
+ content: `[web_fetch succeeded: ${content.length} chars, ${lines} lines — preview preserved]
537110
+ ${webPreview}${webOmitted}`
537111
+ };
536334
537112
  }
536335
537113
  case "web_search": {
536336
537114
  const searchPreview = contentLines.slice(0, 5).join("\n");
536337
537115
  const searchOmitted = lines > 5 ? `
536338
537116
  [... ${lines - 5} more results omitted]` : "";
536339
- return { ...msg, content: `[web_search succeeded: ${lines} results — top results preserved]
536340
- ${searchPreview}${searchOmitted}` };
537117
+ return {
537118
+ ...msg,
537119
+ content: `[web_search succeeded: ${lines} results — top results preserved]
537120
+ ${searchPreview}${searchOmitted}`
537121
+ };
536341
537122
  }
536342
537123
  case "shell":
536343
537124
  case "background_run": {
@@ -536346,16 +537127,22 @@ ${searchPreview}${searchOmitted}` };
536346
537127
  const cmdPreview = contentLines.slice(0, 5).join("\n");
536347
537128
  const cmdOmitted = lines > 5 ? `
536348
537129
  [... ${lines - 5} more lines omitted for compaction]` : "";
536349
- return { ...msg, content: `[shell succeeded: ${lines} lines, ${content.length} chars — preview preserved]
536350
- ${cmdPreview}${cmdOmitted}` };
537130
+ return {
537131
+ ...msg,
537132
+ content: `[shell succeeded: ${lines} lines, ${content.length} chars — preview preserved]
537133
+ ${cmdPreview}${cmdOmitted}`
537134
+ };
536351
537135
  }
536352
537136
  default:
536353
537137
  if (content.length > 2e3) {
536354
537138
  const genPreview = contentLines.slice(0, 3).join("\n");
536355
537139
  const genOmitted = lines > 3 ? `
536356
537140
  [... ${lines - 3} more lines omitted]` : "";
536357
- return { ...msg, content: `[${toolName ?? "tool"} succeeded: ${content.length} chars — preview preserved]
536358
- ${genPreview}${genOmitted}` };
537141
+ return {
537142
+ ...msg,
537143
+ content: `[${toolName ?? "tool"} succeeded: ${content.length} chars — preview preserved]
537144
+ ${genPreview}${genOmitted}`
537145
+ };
536359
537146
  }
536360
537147
  return msg;
536361
537148
  }
@@ -536478,7 +537265,10 @@ ${headContent}${sigLines ? "\n[key signatures]: " + sigLines : ""}`;
536478
537265
  commandResults.push({ cmd: `web_fetch ${url}`, outcome: errMsg });
536479
537266
  } else {
536480
537267
  const preview = content.split("\n").slice(0, 3).join(" ").trim().slice(0, 150);
536481
- commandResults.push({ cmd: `web_fetch ${url}`, outcome: `succeeded: ${preview || `${content.length} chars`}` });
537268
+ commandResults.push({
537269
+ cmd: `web_fetch ${url}`,
537270
+ outcome: `succeeded: ${preview || `${content.length} chars`}`
537271
+ });
536482
537272
  }
536483
537273
  break;
536484
537274
  }
@@ -536486,11 +537276,17 @@ ${headContent}${sigLines ? "\n[key signatures]: " + sigLines : ""}`;
536486
537276
  const query = String(tc.args.query || "").slice(0, 80);
536487
537277
  if (content.startsWith("Error:")) {
536488
537278
  errors.push(`web_search "${query}": ${content.slice(0, 200)}`);
536489
- commandResults.push({ cmd: `web_search "${query}"`, outcome: content.slice(0, 200) });
537279
+ commandResults.push({
537280
+ cmd: `web_search "${query}"`,
537281
+ outcome: content.slice(0, 200)
537282
+ });
536490
537283
  } else {
536491
537284
  const resultCount = (content.match(/\n/g) || []).length;
536492
537285
  const preview = content.split("\n").slice(0, 2).join(" ").trim().slice(0, 100);
536493
- commandResults.push({ cmd: `web_search "${query}"`, outcome: `${resultCount} results: ${preview}` });
537286
+ commandResults.push({
537287
+ cmd: `web_search "${query}"`,
537288
+ outcome: `${resultCount} results: ${preview}`
537289
+ });
536494
537290
  }
536495
537291
  break;
536496
537292
  }
@@ -537158,7 +537954,14 @@ ${transcript}`
537158
537954
  if (taskText.includes(tool.name.replace(/_/g, " ")) || taskText.includes(tool.name)) {
537159
537955
  score += 10;
537160
537956
  }
537161
- if (["explore_tools", "memory_search", "skill_list", "skill_execute", "agent", "sub_agent"].includes(tool.name)) {
537957
+ if ([
537958
+ "explore_tools",
537959
+ "memory_search",
537960
+ "skill_list",
537961
+ "skill_execute",
537962
+ "agent",
537963
+ "sub_agent"
537964
+ ].includes(tool.name)) {
537162
537965
  score += 1;
537163
537966
  }
537164
537967
  scored.push({ tool, score });
@@ -537229,7 +538032,10 @@ ${catalog}`,
537229
538032
  parameters: {
537230
538033
  type: "object",
537231
538034
  properties: {
537232
- query: { type: "string", description: "Search query (tool name or capability description)" }
538035
+ query: {
538036
+ type: "string",
538037
+ description: "Search query (tool name or capability description)"
538038
+ }
537233
538039
  },
537234
538040
  required: ["query"]
537235
538041
  }
@@ -537389,13 +538195,21 @@ ${result}`
537389
538195
  for (let pi = 0; pi < msg.content.length; pi++) {
537390
538196
  const part = msg.content[pi];
537391
538197
  if (part.type === "image_url" && part.image_url?.url) {
537392
- imageEntries.push({ msgIdx: mi, partIdx: pi, dataUrl: part.image_url.url });
538198
+ imageEntries.push({
538199
+ msgIdx: mi,
538200
+ partIdx: pi,
538201
+ dataUrl: part.image_url.url
538202
+ });
537393
538203
  }
537394
538204
  }
537395
538205
  }
537396
538206
  if (imageEntries.length === 0)
537397
538207
  return false;
537398
- this.emit({ type: "status", content: `Image rejected — trying downconversion (${imageEntries.length} image(s))...`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
538208
+ this.emit({
538209
+ type: "status",
538210
+ content: `Image rejected — trying downconversion (${imageEntries.length} image(s))...`,
538211
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
538212
+ });
537399
538213
  let downconverted = false;
537400
538214
  try {
537401
538215
  for (const entry of imageEntries) {
@@ -537435,7 +538249,10 @@ ${result}`
537435
538249
  if (resizedBase64) {
537436
538250
  const msg = messages2[entry.msgIdx];
537437
538251
  const parts = msg.content;
537438
- parts[entry.partIdx] = { type: "image_url", image_url: { url: resizedBase64 } };
538252
+ parts[entry.partIdx] = {
538253
+ type: "image_url",
538254
+ image_url: { url: resizedBase64 }
538255
+ };
537439
538256
  downconverted = true;
537440
538257
  }
537441
538258
  }
@@ -537443,10 +538260,18 @@ ${result}`
537443
538260
  }
537444
538261
  if (downconverted) {
537445
538262
  chatRequest.messages = messages2;
537446
- this.emit({ type: "status", content: `Downconverted images to 512px JPEG — retrying`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
538263
+ this.emit({
538264
+ type: "status",
538265
+ content: `Downconverted images to 512px JPEG — retrying`,
538266
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
538267
+ });
537447
538268
  return true;
537448
538269
  }
537449
- this.emit({ type: "status", content: `Downconversion failed — trying vision model fallback...`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
538270
+ this.emit({
538271
+ type: "status",
538272
+ content: `Downconversion failed — trying vision model fallback...`,
538273
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
538274
+ });
537450
538275
  const ollamaHost = process.env["OLLAMA_HOST"] || "http://127.0.0.1:11434";
537451
538276
  let described = false;
537452
538277
  for (const entry of imageEntries) {
@@ -537471,10 +538296,17 @@ ${result}`
537471
538296
  signal: AbortSignal.timeout(6e4)
537472
538297
  });
537473
538298
  if (!res.ok && model === "moondream" && res.status === 404) {
537474
- this.emit({ type: "status", content: `Pulling moondream vision model...`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
538299
+ this.emit({
538300
+ type: "status",
538301
+ content: `Pulling moondream vision model...`,
538302
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
538303
+ });
537475
538304
  try {
537476
538305
  const { execSync: execSync59 } = await import("node:child_process");
537477
- execSync59("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
538306
+ execSync59("ollama pull moondream", {
538307
+ timeout: 3e5,
538308
+ stdio: "pipe"
538309
+ });
537478
538310
  res = await fetch(`${ollamaHost}/api/generate`, {
537479
538311
  method: "POST",
537480
538312
  headers: { "Content-Type": "application/json" },
@@ -537501,7 +538333,11 @@ ${result}`
537501
538333
  ${description}`
537502
538334
  };
537503
538335
  described = true;
537504
- this.emit({ type: "status", content: `Image described (${description.length} chars) — replacing inline`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
538336
+ this.emit({
538337
+ type: "status",
538338
+ content: `Image described (${description.length} chars) — replacing inline`,
538339
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
538340
+ });
537505
538341
  }
537506
538342
  }
537507
538343
  } catch {
@@ -537518,10 +538354,18 @@ ${description}`
537518
538354
  }
537519
538355
  }
537520
538356
  chatRequest.messages = messages2;
537521
- this.emit({ type: "status", content: `Images replaced with descriptions — retrying`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
538357
+ this.emit({
538358
+ type: "status",
538359
+ content: `Images replaced with descriptions — retrying`,
538360
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
538361
+ });
537522
538362
  return true;
537523
538363
  }
537524
- this.emit({ type: "status", content: `Image could not be processed — stripping images (text context preserved)`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
538364
+ this.emit({
538365
+ type: "status",
538366
+ content: `Image could not be processed — stripping images (text context preserved)`,
538367
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
538368
+ });
537525
538369
  for (const msg of messages2) {
537526
538370
  if (Array.isArray(msg.content)) {
537527
538371
  const textParts = msg.content.filter((p2) => p2.type !== "image_url");
@@ -537622,9 +538466,35 @@ ${description}`
537622
538466
  let inThinkTag = false;
537623
538467
  const toolCallAccumulators = /* @__PURE__ */ new Map();
537624
538468
  let streamUsage;
537625
- this.emit({ type: "stream_start", turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
538469
+ this.emit({
538470
+ type: "stream_start",
538471
+ turn,
538472
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
538473
+ });
537626
538474
  this._streamingExecutor.reset();
537627
538475
  let lastFinalizedIdx = -1;
538476
+ let firstThinkingTime = 0;
538477
+ let watchdogTripped = false;
538478
+ let thinkingSample = "";
538479
+ let watchdogMs = typeof backend.getThinkingWatchdogMs === "function" ? backend.getThinkingWatchdogMs() : 6e4;
538480
+ if (watchdogMs > 15e3) {
538481
+ let estimatedHistoryTokens = 0;
538482
+ for (const m2 of request.messages) {
538483
+ const c9 = typeof m2.content === "string" ? m2.content : "";
538484
+ estimatedHistoryTokens += c9.length;
538485
+ if (m2.tool_calls) {
538486
+ for (const tc of m2.tool_calls) {
538487
+ estimatedHistoryTokens += tc.function?.arguments?.length ?? 0;
538488
+ }
538489
+ }
538490
+ }
538491
+ estimatedHistoryTokens = Math.round(estimatedHistoryTokens / 4);
538492
+ if (estimatedHistoryTokens > 28e3) {
538493
+ watchdogMs = Math.min(watchdogMs, 3e4);
538494
+ } else if (estimatedHistoryTokens > 24e3) {
538495
+ watchdogMs = Math.min(watchdogMs, 45e3);
538496
+ }
538497
+ }
537628
538498
  for await (const chunk of backend.chatCompletionStream(request)) {
537629
538499
  if (this.aborted)
537630
538500
  break;
@@ -537655,6 +538525,25 @@ ${description}`
537655
538525
  } else {
537656
538526
  thinkingContent += fragment;
537657
538527
  }
538528
+ if (kind === "thinking") {
538529
+ if (firstThinkingTime === 0)
538530
+ firstThinkingTime = Date.now();
538531
+ if (!watchdogTripped) {
538532
+ const elapsed = Date.now() - firstThinkingTime;
538533
+ if (elapsed >= watchdogMs) {
538534
+ watchdogTripped = true;
538535
+ thinkingSample = thinkingContent.slice(-3e3);
538536
+ this.emit({
538537
+ type: "status",
538538
+ content: `Thinking watchdog tripped after ${Math.round(elapsed / 1e3)}s (threshold=${(watchdogMs / 1e3).toFixed(0)}s) — model may be in a reasoning loop`,
538539
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
538540
+ });
538541
+ break;
538542
+ }
538543
+ }
538544
+ } else {
538545
+ firstThinkingTime = 0;
538546
+ }
537658
538547
  const buf = kind === "content" ? content : thinkingContent;
537659
538548
  if (buf.length > 200 && buf.length % 100 < fragment.length) {
537660
538549
  const tail = buf.slice(-600);
@@ -537750,13 +538639,23 @@ ${description}`
537750
538639
  }
537751
538640
  }
537752
538641
  }
537753
- this.emit({ type: "stream_end", content, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
538642
+ this.emit({
538643
+ type: "stream_end",
538644
+ content,
538645
+ turn,
538646
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
538647
+ });
537754
538648
  const modelName = this.backend.model ?? "";
537755
538649
  const modelProfile = resolveModelProfile(modelName);
537756
538650
  const textToolParse = parseTextToolCalls(content.replace(/<think>[\s\S]*?<\/think>/g, "").trim(), modelProfile);
537757
538651
  const cleanContent = stripXmlControlBlocks(textToolParse.content, modelProfile);
537758
538652
  if (cleanContent) {
537759
- this.emit({ type: "assistant_text", content: cleanContent, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
538653
+ this.emit({
538654
+ type: "assistant_text",
538655
+ content: cleanContent,
538656
+ turn,
538657
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
538658
+ });
537760
538659
  this._assistantTextEmitted = true;
537761
538660
  }
537762
538661
  const hadThinking = content.includes("<think>") && content.includes("</think>");
@@ -537773,20 +538672,93 @@ ${description}`
537773
538672
  }) : void 0;
537774
538673
  const toolCalls = structuredStreamToolCalls && structuredStreamToolCalls.length > 0 ? structuredStreamToolCalls : textToolParse.toolCalls.length > 0 ? textToolParse.toolCalls : void 0;
537775
538674
  const resp = {
537776
- choices: [{
537777
- message: {
537778
- // For think-only responses, include a marker so the model knows it already
537779
- // thought about this (prevents infinite think loops without visible output)
537780
- content: thinkOnlyResponse ? "[Your previous response was internal reasoning only. Now respond with visible text or a tool call.]" : cleanContent || null,
537781
- toolCalls
538675
+ choices: [
538676
+ {
538677
+ message: {
538678
+ // For think-only responses, include a marker so the model knows it already
538679
+ // thought about this (prevents infinite think loops without visible output)
538680
+ content: thinkOnlyResponse ? "[Your previous response was internal reasoning only. Now respond with visible text or a tool call.]" : cleanContent || null,
538681
+ toolCalls
538682
+ }
537782
538683
  }
537783
- }],
538684
+ ],
537784
538685
  usage: streamUsage
537785
538686
  };
537786
538687
  if (thinkOnlyResponse)
537787
538688
  resp._thinkOnly = true;
538689
+ if (watchdogTripped)
538690
+ resp._watchdogTripped = true;
538691
+ if (watchdogTripped && thinkingSample.length > 0) {
538692
+ this._fireModeCollapseAnalysis(backend, thinkingSample, thinkingContent.length, Date.now() - (firstThinkingTime || Date.now()), turn);
538693
+ }
537788
538694
  return resp;
537789
538695
  }
538696
+ /**
538697
+ * Fire-and-forget mode-collapse analysis. Called when the streaming
538698
+ * watchdog detects extended thinking without visible output. Fires a
538699
+ * sub-agent to classify the thinking pattern and updates the backend's
538700
+ * elevated scrutiny state for future turns.
538701
+ *
538702
+ * The sub-agent call runs asynchronously and does NOT block the current
538703
+ * response — the watchdog already aborted it. This is purely diagnostic
538704
+ * and adjusts thresholds for subsequent turns.
538705
+ *
538706
+ * Gated behind OA_MODE_COLLAPSE_ANALYZER env (default "on") so users
538707
+ * who want zero extra round-trips can disable it.
538708
+ */
538709
+ _fireModeCollapseAnalysis(backend, thinkingSample, totalThinkingChars, thinkingDurationMs, turn) {
538710
+ const gate = (process.env["OA_MODE_COLLAPSE_ANALYZER"] || "on").toLowerCase();
538711
+ if (gate !== "on" && gate !== "1" && gate !== "true")
538712
+ return;
538713
+ const goal = this._taskState?.originalGoal || this._taskState?.goal || "";
538714
+ const callable = async (prompt) => {
538715
+ try {
538716
+ const r2 = await backend.chatCompletion({
538717
+ messages: [
538718
+ {
538719
+ role: "system",
538720
+ content: "You are a META-ANALYSIS sub-agent. Classify the generator's thinking stream and emit a structured JSON verdict."
538721
+ },
538722
+ { role: "user", content: prompt }
538723
+ ],
538724
+ tools: [],
538725
+ temperature: 0,
538726
+ maxTokens: parseInt(process.env["OA_MODE_COLLAPSE_MAX_TOKENS"] || "1024", 10) || 1024,
538727
+ timeoutMs: parseInt(process.env["OA_MODE_COLLAPSE_TIMEOUT_MS"] || "30000", 10) || 3e4
538728
+ });
538729
+ const c9 = r2?.choices?.[0]?.message?.content;
538730
+ return typeof c9 === "string" ? c9 : "";
538731
+ } catch {
538732
+ return "";
538733
+ }
538734
+ };
538735
+ runModeCollapseAnalysis({
538736
+ inputs: {
538737
+ thinkingSample,
538738
+ totalThinkingChars,
538739
+ thinkingDurationMs,
538740
+ goal: goal.slice(0, 500),
538741
+ lastToolNames: []
538742
+ },
538743
+ callable
538744
+ }).then((result) => {
538745
+ if (result.verdict.category !== "healthy" && result.verdict.confidence >= 0.7) {
538746
+ backend.recordModeCollapse();
538747
+ this.emit({
538748
+ type: "status",
538749
+ content: `Mode-collapse analysis: ${result.verdict.category} (conf=${result.verdict.confidence.toFixed(2)}) — ${result.verdict.diagnosis.slice(0, 120)}. Collapse #${backend.getModeCollapseCount()}, scrutiny level ${backend.getElevatedScrutinyLevel()}`,
538750
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
538751
+ });
538752
+ } else {
538753
+ this.emit({
538754
+ type: "status",
538755
+ content: `Thinking analysis: ${result.verdict.category} (conf=${result.verdict.confidence.toFixed(2)}) — thinking was healthy, continuing`,
538756
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
538757
+ });
538758
+ }
538759
+ }).catch(() => {
538760
+ });
538761
+ }
537790
538762
  };
537791
538763
  OllamaAgenticBackend = class _OllamaAgenticBackend {
537792
538764
  baseUrl;
@@ -537805,6 +538777,23 @@ ${description}`
537805
538777
  _thinkSuppressedNotified = false;
537806
538778
  static _thinkFailThreshold = 2;
537807
538779
  static _thinkRecoveryThreshold = 6;
538780
+ // ── Mode-collapse elevated scrutiny (0.188.x) ──────────────────────
538781
+ // When the thinking-stream watchdog fires and the sub-agent confirms
538782
+ // mode collapse, this counter increments. At each threshold, detection
538783
+ // tightens to prevent recurring runaway reasoning loops.
538784
+ // Level 0 (normal): watchdog fires at 60s
538785
+ // Level 1 (elevated): watchdog fires at 30s
538786
+ // Level 2 (forced off): think=false unless user explicitly opted in
538787
+ _modeCollapseCount = 0;
538788
+ _elevatedScrutinyLevel = 0;
538789
+ /** Consecutive healthy (no-collapse) thinking responses since last collapse */
538790
+ _cleanStreakAfterCollapse = 0;
538791
+ static _ELEVATED_SCRUTINY_THRESHOLD = 2;
538792
+ // collapses to reach level 1
538793
+ static _FORCED_OFF_THRESHOLD = 4;
538794
+ // collapses to reach level 2
538795
+ static _RECOVERY_CLEAN_COUNT = 10;
538796
+ // clean responses to de-escalate one level
537808
538797
  /** Multi-key pool — round-robin rotation per request for load distribution */
537809
538798
  _keyPool = [];
537810
538799
  _keyIndex = 0;
@@ -537851,6 +538840,9 @@ ${description}`
537851
538840
  this._thinkSuccessStreak = 0;
537852
538841
  this._thinkSuppressed = false;
537853
538842
  this._thinkSuppressedNotified = false;
538843
+ this._modeCollapseCount = 0;
538844
+ this._elevatedScrutinyLevel = 0;
538845
+ this._cleanStreakAfterCollapse = 0;
537854
538846
  }
537855
538847
  /**
537856
538848
  * Feed a completed assistant response into the loop-guard. We only
@@ -537896,10 +538888,72 @@ ${description}`
537896
538888
  }
537897
538889
  return false;
537898
538890
  }
538891
+ // ── Mode-collapse elevated scrutiny ────────────────────────────────
538892
+ /** Record a confirmed mode collapse. Tightens detection thresholds. */
538893
+ recordModeCollapse() {
538894
+ this._modeCollapseCount++;
538895
+ this._cleanStreakAfterCollapse = 0;
538896
+ if (this._modeCollapseCount >= _OllamaAgenticBackend._FORCED_OFF_THRESHOLD) {
538897
+ this._elevatedScrutinyLevel = 2;
538898
+ } else if (this._modeCollapseCount >= _OllamaAgenticBackend._ELEVATED_SCRUTINY_THRESHOLD) {
538899
+ this._elevatedScrutinyLevel = 1;
538900
+ }
538901
+ }
538902
+ /** Record a clean (no-collapse) streaming response toward recovery. */
538903
+ recordCleanStreamTurn() {
538904
+ if (this._elevatedScrutinyLevel > 0) {
538905
+ this._cleanStreakAfterCollapse++;
538906
+ if (this._cleanStreakAfterCollapse >= _OllamaAgenticBackend._RECOVERY_CLEAN_COUNT) {
538907
+ this._elevatedScrutinyLevel = Math.max(0, this._elevatedScrutinyLevel - 1);
538908
+ this._cleanStreakAfterCollapse = 0;
538909
+ if (this._elevatedScrutinyLevel < 2 && this._thinkSuppressed) {
538910
+ this._thinkSuppressed = false;
538911
+ this._thinkSuppressedNotified = false;
538912
+ }
538913
+ }
538914
+ }
538915
+ }
538916
+ /** Get the current elevated-scrutiny level. */
538917
+ getElevatedScrutinyLevel() {
538918
+ return this._elevatedScrutinyLevel;
538919
+ }
538920
+ /** Get the total mode-collapse count for this session. */
538921
+ getModeCollapseCount() {
538922
+ return this._modeCollapseCount;
538923
+ }
538924
+ /**
538925
+ * Get the watchdog threshold in ms for the current scrutiny level.
538926
+ * Level 0: 60s (normal)
538927
+ * Level 1: 30s (elevated — shorter leash)
538928
+ * Level 2: 15s (tight — barely any thinking allowed)
538929
+ */
538930
+ getThinkingWatchdogMs() {
538931
+ if (this._elevatedScrutinyLevel >= 2)
538932
+ return 15e3;
538933
+ if (this._elevatedScrutinyLevel >= 1)
538934
+ return 3e4;
538935
+ return 6e4;
538936
+ }
538937
+ /**
538938
+ * When elevated scrutiny is active, the callers should consider
538939
+ * whether the next request should force think=false. Level 2 means
538940
+ * think is auto-forced-off (unless the user explicitly opted in).
538941
+ * Level 1 leaves the decision to the caller. Returns -1 (no override)
538942
+ * or a boolean to force as think value.
538943
+ */
538944
+ getElevatedThinkOverride(requestThink) {
538945
+ if (this._elevatedScrutinyLevel >= 2) {
538946
+ if (requestThink !== true)
538947
+ return false;
538948
+ }
538949
+ return -1;
538950
+ }
537899
538951
  /** Build auth headers — adapts to provider (Bearer for most, x-api-key for Anthropic).
537900
538952
  * When a key pool is set, round-robins through keys per request. */
537901
538953
  authHeaders() {
537902
- const headers = { "Content-Type": "application/json" };
538954
+ const headers = {
538955
+ "Content-Type": "application/json"
538956
+ };
537903
538957
  let key = this.apiKey;
537904
538958
  if (this._keyPool.length > 0) {
537905
538959
  key = this._keyPool[this._keyIndex % this._keyPool.length];
@@ -537920,13 +538974,16 @@ ${description}`
537920
538974
  return this._anthropicChatCompletion(request);
537921
538975
  }
537922
538976
  const cleanedMessages = normalizeMessagesForStrictOpenAI(sanitizeHistoryThink(request.messages));
537923
- const effectiveThink = computeEffectiveThink({
538977
+ let effectiveThink = computeEffectiveThink({
537924
538978
  requestThink: request.think,
537925
538979
  defaultThink: this.thinking,
537926
538980
  hasTools: Array.isArray(request.tools) && request.tools.length > 0,
537927
538981
  messages: cleanedMessages,
537928
538982
  suppressed: this._thinkSuppressed
537929
538983
  });
538984
+ const elevatedOverride = this.getElevatedThinkOverride(request.think);
538985
+ if (elevatedOverride !== -1)
538986
+ effectiveThink = elevatedOverride;
537930
538987
  let effectiveMaxTokens = request.maxTokens;
537931
538988
  if (effectiveThink === true && (effectiveMaxTokens ?? 0) < 4096) {
537932
538989
  effectiveMaxTokens = 4096;
@@ -538029,11 +539086,13 @@ ${description}`
538029
539086
  if (msg.role === "tool") {
538030
539087
  anthropicMessages.push({
538031
539088
  role: "user",
538032
- content: [{
538033
- type: "tool_result",
538034
- tool_use_id: msg.tool_call_id ?? "",
538035
- content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content)
538036
- }]
539089
+ content: [
539090
+ {
539091
+ type: "tool_result",
539092
+ tool_use_id: msg.tool_call_id ?? "",
539093
+ content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content)
539094
+ }
539095
+ ]
538037
539096
  });
538038
539097
  } else if (msg.role === "assistant" && msg.tool_calls?.length > 0) {
538039
539098
  const blocks = [];
@@ -538106,12 +539165,14 @@ ${description}`
538106
539165
  }
538107
539166
  }
538108
539167
  return {
538109
- choices: [{
538110
- message: {
538111
- content: textContent || null,
538112
- toolCalls: toolCalls.length > 0 ? toolCalls : void 0
539168
+ choices: [
539169
+ {
539170
+ message: {
539171
+ content: textContent || null,
539172
+ toolCalls: toolCalls.length > 0 ? toolCalls : void 0
539173
+ }
538113
539174
  }
538114
- }],
539175
+ ],
538115
539176
  usage: usage ? {
538116
539177
  totalTokens: (usage.input_tokens ?? 0) + (usage.output_tokens ?? 0),
538117
539178
  promptTokens: usage.input_tokens,
@@ -538126,13 +539187,16 @@ ${description}`
538126
539187
  */
538127
539188
  async *chatCompletionStream(request) {
538128
539189
  const cleanedMessages = normalizeMessagesForStrictOpenAI(request.messages.map((m2) => m2.role === "assistant" && typeof m2.content === "string" ? { ...m2, content: stripThinkBlocks(m2.content) } : m2));
538129
- const effectiveThink = computeEffectiveThink({
539190
+ let effectiveThink = computeEffectiveThink({
538130
539191
  requestThink: request.think,
538131
539192
  defaultThink: this.thinking,
538132
539193
  hasTools: Array.isArray(request.tools) && request.tools.length > 0,
538133
539194
  messages: cleanedMessages,
538134
539195
  suppressed: this._thinkSuppressed
538135
539196
  });
539197
+ const elevatedOverride = this.getElevatedThinkOverride(request.think);
539198
+ if (elevatedOverride !== -1)
539199
+ effectiveThink = elevatedOverride;
538136
539200
  let effectiveMaxTokens = request.maxTokens;
538137
539201
  if (effectiveThink === true && (effectiveMaxTokens ?? 0) < 4096) {
538138
539202
  effectiveMaxTokens = 4096;