open-agents-ai 0.187.520 → 0.187.522

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
@@ -539,6 +539,89 @@ var init_normalizeUrl = __esm({
539
539
  }
540
540
  });
541
541
 
542
+ // packages/backend-vllm/dist/messageNormalize.js
543
+ function normalizeMessagesForStrictOpenAI(messages2, stats) {
544
+ if (stats) {
545
+ stats.inputSystemCount = 0;
546
+ stats.mergedLeading = 0;
547
+ stats.convertedToUser = 0;
548
+ stats.changed = false;
549
+ }
550
+ if (!Array.isArray(messages2) || messages2.length === 0)
551
+ return [];
552
+ const leading = [];
553
+ let i2 = 0;
554
+ while (i2 < messages2.length && messages2[i2].role === "system") {
555
+ leading.push(messages2[i2]);
556
+ i2++;
557
+ }
558
+ if (stats) {
559
+ stats.inputSystemCount += leading.length;
560
+ stats.mergedLeading = leading.length;
561
+ }
562
+ const out = [];
563
+ if (leading.length > 0) {
564
+ if (leading.length === 1) {
565
+ out.push(leading[0]);
566
+ } else {
567
+ const allStrings = leading.every((m2) => typeof m2.content === "string");
568
+ if (allStrings) {
569
+ const merged = leading.map((m2) => m2.content ?? "").filter((s2) => s2.length > 0).join(SYSTEM_MERGE_SEP);
570
+ out.push({ ...leading[0], content: merged });
571
+ } else {
572
+ out.push(leading[0]);
573
+ for (let k = 1; k < leading.length; k++) {
574
+ const c9 = leading[k].content;
575
+ const cs = typeof c9 === "string" ? c9 : "";
576
+ if (cs.length > 0) {
577
+ out.push({ ...leading[k], role: "user", content: `${SYSTEM_AS_USER_PREFIX}${cs}` });
578
+ }
579
+ }
580
+ }
581
+ if (stats)
582
+ stats.changed = true;
583
+ }
584
+ }
585
+ for (; i2 < messages2.length; i2++) {
586
+ const m2 = messages2[i2];
587
+ if (m2.role === "system") {
588
+ if (stats) {
589
+ stats.inputSystemCount += 1;
590
+ stats.convertedToUser += 1;
591
+ stats.changed = true;
592
+ }
593
+ const c9 = m2.content;
594
+ const cs = typeof c9 === "string" ? c9 : "";
595
+ if (cs.length > 0) {
596
+ out.push({ ...m2, role: "user", content: `${SYSTEM_AS_USER_PREFIX}${cs}` });
597
+ }
598
+ } else {
599
+ out.push(m2);
600
+ }
601
+ }
602
+ if (stats && !stats.changed) {
603
+ if (out.length !== messages2.length)
604
+ stats.changed = true;
605
+ else {
606
+ for (let k = 0; k < out.length; k++) {
607
+ if (out[k] !== messages2[k]) {
608
+ stats.changed = true;
609
+ break;
610
+ }
611
+ }
612
+ }
613
+ }
614
+ return out;
615
+ }
616
+ var SYSTEM_MERGE_SEP, SYSTEM_AS_USER_PREFIX;
617
+ var init_messageNormalize = __esm({
618
+ "packages/backend-vllm/dist/messageNormalize.js"() {
619
+ "use strict";
620
+ SYSTEM_MERGE_SEP = "\n\n---\n\n";
621
+ SYSTEM_AS_USER_PREFIX = "[SYSTEM]: ";
622
+ }
623
+ });
624
+
542
625
  // packages/backend-vllm/dist/VllmBackend.js
543
626
  function agentMessageToChatMessage(msg) {
544
627
  return {
@@ -555,6 +638,7 @@ var init_VllmBackend = __esm({
555
638
  "use strict";
556
639
  init_sleep();
557
640
  init_normalizeUrl();
641
+ init_messageNormalize();
558
642
  VllmBackend = class {
559
643
  baseUrl;
560
644
  model;
@@ -594,7 +678,8 @@ var init_VllmBackend = __esm({
594
678
  // LLMBackend — complete
595
679
  // -------------------------------------------------------------------------
596
680
  async complete(request) {
597
- const messages2 = request.messages.map(agentMessageToChatMessage);
681
+ const rawMessages = request.messages.map(agentMessageToChatMessage);
682
+ const messages2 = normalizeMessagesForStrictOpenAI(rawMessages);
598
683
  const body = {
599
684
  model: this.model,
600
685
  messages: messages2,
@@ -709,6 +794,7 @@ var init_OllamaBackend = __esm({
709
794
  "packages/backend-vllm/dist/OllamaBackend.js"() {
710
795
  "use strict";
711
796
  init_normalizeUrl();
797
+ init_messageNormalize();
712
798
  OllamaBackend = class _OllamaBackend {
713
799
  baseUrl;
714
800
  model;
@@ -744,7 +830,7 @@ var init_OllamaBackend = __esm({
744
830
  // LLMBackend — complete
745
831
  // -------------------------------------------------------------------------
746
832
  async complete(request) {
747
- const messages2 = request.messages.map(agentMessageToChatMessage2);
833
+ const messages2 = normalizeMessagesForStrictOpenAI(request.messages.map(agentMessageToChatMessage2));
748
834
  const body = {
749
835
  model: this.model,
750
836
  messages: messages2,
@@ -1140,6 +1226,7 @@ var init_dist = __esm({
1140
1226
  init_sleep();
1141
1227
  init_routing();
1142
1228
  init_normalizeUrl();
1229
+ init_messageNormalize();
1143
1230
  }
1144
1231
  });
1145
1232
 
@@ -525882,6 +525969,17 @@ var init_agenticRunner = __esm({
525882
525969
  // (daemon timeout). End-of-Task block uses this to set finalStatus="timeout"
525883
525970
  // in the session_gist instead of "abandoned".
525884
525971
  _aborting = false;
525972
+ // REG-61 (root-cause from batch523 stax read-paralysis): one-shot early
525973
+ // nudge that fires ONCE when the agent has read >=5 things without making
525974
+ // a single creative edit. REG-44 catches this class but only at turn≥12
525975
+ // (window of 15) — by then the read habit is entrenched and the agent
525976
+ // ignores the prompt. REG-61 fires at turn >=4 with a much harder
525977
+ // directive: "your next tool call must be a creative edit that creates
525978
+ // a deliverable." This is the SAME shape as the osm-vs-stax breakthrough:
525979
+ // osm's first creative edit at call #48 was package.json (build harness),
525980
+ // stax never made one. Generic across ecosystems — names no specific
525981
+ // file/manifest format, just "deliverable".
525982
+ _reg61Fired = false;
525885
525983
  // MEM_PATH item #9: adaptive retrieval cache. When the (goalHash, recent-tool-sig)
525886
525984
  // hasn't changed since last retrieval, skip the PPR call entirely and reuse
525887
525985
  // the previous memoryLines.
@@ -528091,6 +528189,7 @@ Respond with your assessment, then take action.`;
528091
528189
  this._lastFileWriteTurn = -1;
528092
528190
  this._fileWriteTimestamps = [];
528093
528191
  this._aborting = false;
528192
+ this._reg61Fired = false;
528094
528193
  if (!globalThis.__oa_rca1_sigterm_installed) {
528095
528194
  globalThis.__oa_rca1_sigterm_installed = true;
528096
528195
  const _sigtermHandler = () => {
@@ -528514,6 +528613,49 @@ TASK: ${task}` : task;
528514
528613
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
528515
528614
  });
528516
528615
  }
528616
+ const REG61_TURN_FLOOR = 4;
528617
+ const REG61_MIN_READS = 3;
528618
+ if (!this._reg61Fired && turn >= REG61_TURN_FLOOR && this._lastFileWriteTurn < 0 && process.env["OA_DISABLE_REG61"] !== "1") {
528619
+ const _readClassNames = /* @__PURE__ */ new Set([
528620
+ "file_read",
528621
+ "file_explore",
528622
+ "list_directory",
528623
+ "grep_search",
528624
+ "glob_find",
528625
+ "find_files",
528626
+ "code_neighbors",
528627
+ "repo_map",
528628
+ "codebase_map",
528629
+ "semantic_map",
528630
+ "symbol_search",
528631
+ "todo_read",
528632
+ "memory_read",
528633
+ "memory_search"
528634
+ ]);
528635
+ let _readsThisRun = 0;
528636
+ for (const c9 of toolCallLog) {
528637
+ if (_readClassNames.has(c9.name))
528638
+ _readsThisRun++;
528639
+ }
528640
+ if (_readsThisRun >= REG61_MIN_READS) {
528641
+ this._reg61Fired = true;
528642
+ const reg61Msg = `[FIRST-EDIT NUDGE — REG-61]
528643
+ You have made ${_readsThisRun} read/exploration calls without yet producing a creative edit. Reading is preparation; writing is progress. Successful runs produce their first deliverable EARLY and iterate from there — runs that stay in pure-read mode produce zero deliverables.
528644
+
528645
+ Your NEXT tool call MUST be a creative edit:
528646
+ • file_write — create a new file (preferred for greenfield)
528647
+ • file_edit — modify an existing file
528648
+ • batch_edit / file_patch — multi-line changes
528649
+
528650
+ Pick the SMALLEST concrete deliverable from the spec — typically the project entry point or the file most other modules depend on. Write a stub or skeleton if the full implementation is too large; you can iterate later. Do NOT issue another file_read, list_directory, grep_search, or shell-cat before producing this first edit. After the edit lands, continue normally.`;
528651
+ messages2.push({ role: "system", content: reg61Msg });
528652
+ this.emit({
528653
+ type: "status",
528654
+ content: `REG-61 FIRST-EDIT NUDGE — fired at turn ${turn}; reads_so_far=${_readsThisRun}`,
528655
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
528656
+ });
528657
+ }
528658
+ }
528517
528659
  const REG58_NO_WRITE_BUDGET = 30;
528518
528660
  if (turn > stagnationCooldownUntilTurn && this._lastFileWriteTurn >= 0 && turn - this._lastFileWriteTurn >= REG58_NO_WRITE_BUDGET && process.env["OA_DISABLE_REG58"] !== "1") {
528519
528661
  const gap = turn - this._lastFileWriteTurn;
@@ -535544,7 +535686,7 @@ ${description}`
535544
535686
  if (this._isAnthropic) {
535545
535687
  return this._anthropicChatCompletion(request);
535546
535688
  }
535547
- const cleanedMessages = sanitizeHistoryThink(request.messages);
535689
+ const cleanedMessages = normalizeMessagesForStrictOpenAI(sanitizeHistoryThink(request.messages));
535548
535690
  const effectiveThink = computeEffectiveThink({
535549
535691
  requestThink: request.think,
535550
535692
  defaultThink: this.thinking,
@@ -535784,7 +535926,7 @@ ${description}`
535784
535926
  * The existing chatCompletion() method is completely unmodified.
535785
535927
  */
535786
535928
  async *chatCompletionStream(request) {
535787
- const cleanedMessages = request.messages.map((m2) => m2.role === "assistant" && typeof m2.content === "string" ? { ...m2, content: stripThinkBlocks(m2.content) } : m2);
535929
+ const cleanedMessages = normalizeMessagesForStrictOpenAI(request.messages.map((m2) => m2.role === "assistant" && typeof m2.content === "string" ? { ...m2, content: stripThinkBlocks(m2.content) } : m2));
535788
535930
  const effectiveThink = computeEffectiveThink({
535789
535931
  requestThink: request.think,
535790
535932
  defaultThink: this.thinking,
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.520",
3
+ "version": "0.187.522",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "open-agents-ai",
9
- "version": "0.187.520",
9
+ "version": "0.187.522",
10
10
  "hasInstallScript": true,
11
11
  "license": "CC-BY-NC-4.0",
12
12
  "dependencies": {
@@ -7036,9 +7036,9 @@
7036
7036
  }
7037
7037
  },
7038
7038
  "node_modules/yaml": {
7039
- "version": "2.8.3",
7040
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz",
7041
- "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==",
7039
+ "version": "2.8.4",
7040
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.4.tgz",
7041
+ "integrity": "sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog==",
7042
7042
  "license": "ISC",
7043
7043
  "bin": {
7044
7044
  "yaml": "bin.mjs"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.520",
3
+ "version": "0.187.522",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",