open-agents-ai 0.187.528 → 0.187.529

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
@@ -526701,6 +526701,123 @@ Pick the SMALLEST concrete deliverable from the spec — typically the project e
526701
526701
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
526702
526702
  });
526703
526703
  }
526704
+ /**
526705
+ * DECOMP-2 PRE-dispatch enforcement check. Returns a synthetic block-message
526706
+ * string when the gate should reject this dispatch; null to proceed normally.
526707
+ *
526708
+ * Caller logic differs between main-loop and brute-force dispatchers:
526709
+ * - Main loop returns the block as a synthetic { tc, output } result.
526710
+ * - Brute-force emits tool_result + pushes tool message + `continue`.
526711
+ * Both invoke this method to compute the decision.
526712
+ *
526713
+ * Conditions for blocking:
526714
+ * - `_decomp2GateActive` is true (set by `_trackDecomp2` when threshold crossed)
526715
+ * - tool is one of the 4 creative-edit tools
526716
+ * - the path is NOT in `_decomp2MainContextFiles` (i.e. it's a NEW file)
526717
+ * - kill-switch `OA_DISABLE_DECOMP2` is not set
526718
+ *
526719
+ * Already-touched paths pass through (current-module finishing work allowed).
526720
+ * sub_agent / web_search / task_complete pass through (not creative-edit tools).
526721
+ */
526722
+ _maybeDecomp2Block(tc, turn) {
526723
+ if (!this._decomp2GateActive)
526724
+ return null;
526725
+ if (process.env["OA_DISABLE_DECOMP2"] === "1")
526726
+ return null;
526727
+ const _editTools = /* @__PURE__ */ new Set(["file_write", "file_edit", "batch_edit", "file_patch"]);
526728
+ if (!_editTools.has(tc.name))
526729
+ return null;
526730
+ const _editPath = tc.arguments?.["path"] ?? "";
526731
+ if (!_editPath || this._decomp2MainContextFiles.has(_editPath))
526732
+ return null;
526733
+ const _filesList = [...this._decomp2MainContextFiles].slice(0, 8).map((p2) => ` • ${p2}`).join("\n");
526734
+ const _moreFiles = this._decomp2MainContextFiles.size > 8 ? `
526735
+ ... +${this._decomp2MainContextFiles.size - 8} more` : "";
526736
+ const decomp2Msg = [
526737
+ `[BLOCKED — DECOMP-2 main-context exhaustion]`,
526738
+ ``,
526739
+ `You have already edited ${this._decomp2MainContextFiles.size} distinct files in main context without invoking sub_agent. Continuing to edit ANOTHER new file ('${_editPath}') will keep your context window saturated and trigger compaction thrashing.`,
526740
+ ``,
526741
+ `Files you've already edited (will accept further edits to these):`,
526742
+ _filesList,
526743
+ _moreFiles,
526744
+ ``,
526745
+ `For the next module, you MUST use sub_agent. Workflow:`,
526746
+ ` 1. Pick a pending todo (the orchestrator pre-populated module todos via DECOMP-1).`,
526747
+ ` 2. Call sub_agent({`,
526748
+ ` subagent_type: "general",`,
526749
+ ` prompt: "Implement <module-path> per spec",`,
526750
+ ` relevantFiles: [{path: "<module-path>", content: "" /* or existing content */}],`,
526751
+ ` constraints: ["Stay within <module-path>; integration verification happens later"],`,
526752
+ ` })`,
526753
+ ` 3. After sub_agent returns, mark the todo completed.`,
526754
+ ``,
526755
+ `Why this matters: spreading edits across N files in main context burns ~N × file_size tokens. sub_agent gives the next module a focused context window.`,
526756
+ ``,
526757
+ `If you have ALREADY edited '${_editPath}' (this is a continuation), the orchestrator's set must have missed it — call file_read to verify, then re-edit. Otherwise, dispatch sub_agent now.`
526758
+ ].join("\n");
526759
+ this.emit({
526760
+ type: "status",
526761
+ content: `DECOMP-2 NEW-FILE BLOCK — rejected ${tc.name}('${_editPath}') at turn ${turn}; gate stays active until sub_agent is invoked`,
526762
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
526763
+ });
526764
+ this._tagSyntheticFailure({
526765
+ mode: "step_repetition",
526766
+ rationale: `DECOMP-2 new-file block on '${tc.name}'(${_editPath}) — agent has spread edits across ${this._decomp2MainContextFiles.size} files without sub_agent`
526767
+ });
526768
+ return decomp2Msg;
526769
+ }
526770
+ /**
526771
+ * DECOMP-2 post-dispatch tracking. Refactored from inline so both the
526772
+ * main turn loop AND the brute-force re-engagement inner loop record
526773
+ * edits / sub_agent calls and check the gate-activation threshold.
526774
+ * Without this method on both paths, batch532 measured 14 distinct
526775
+ * files edited but DECOMP-2 never activated — because the main loop
526776
+ * exited via blocked task_complete and all subsequent edits flowed
526777
+ * through the brute-force dispatch which had no tracking.
526778
+ *
526779
+ * Side effects when fired:
526780
+ * - On successful creative edit: adds path to `_decomp2MainContextFiles`,
526781
+ * possibly activates `_decomp2GateActive` (emits status).
526782
+ * - On sub_agent / priority_delegate / background_run: increments
526783
+ * counter, clears gate (emits status).
526784
+ *
526785
+ * Pure post-dispatch: caller invokes AFTER the tool result is in hand,
526786
+ * regardless of which loop the dispatch happened in.
526787
+ */
526788
+ _trackDecomp2(tc, result, turn) {
526789
+ if (process.env["OA_DISABLE_DECOMP2"] === "1")
526790
+ return;
526791
+ if (result && result.success !== false) {
526792
+ const _editTools = /* @__PURE__ */ new Set(["file_write", "file_edit", "batch_edit", "file_patch"]);
526793
+ if (_editTools.has(tc.name)) {
526794
+ const _editPath = tc.arguments?.["path"] ?? "";
526795
+ if (_editPath && typeof _editPath === "string") {
526796
+ this._decomp2MainContextFiles.add(_editPath);
526797
+ const DECOMP2_FILE_SPREAD_THRESHOLD = 5;
526798
+ if (!this._decomp2GateActive && this._decomp2MainContextFiles.size >= DECOMP2_FILE_SPREAD_THRESHOLD && this._decomp2SubAgentCalls === 0) {
526799
+ this._decomp2GateActive = true;
526800
+ this.emit({
526801
+ type: "status",
526802
+ content: `DECOMP-2 NEW-FILE GATE ACTIVATED — ${this._decomp2MainContextFiles.size} distinct files edited in main context, 0 sub_agent calls; further edits to NEW files will be blocked until sub_agent is invoked`,
526803
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
526804
+ });
526805
+ }
526806
+ }
526807
+ }
526808
+ }
526809
+ if (tc.name === "sub_agent" || tc.name === "priority_delegate" || tc.name === "background_run") {
526810
+ this._decomp2SubAgentCalls++;
526811
+ if (this._decomp2GateActive) {
526812
+ this._decomp2GateActive = false;
526813
+ this.emit({
526814
+ type: "status",
526815
+ content: `DECOMP-2 GATE CLEARED — '${tc.name}' satisfied delegation directive at turn ${turn}`,
526816
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
526817
+ });
526818
+ }
526819
+ }
526820
+ }
526704
526821
  readSessionTodos() {
526705
526822
  try {
526706
526823
  const sid = process.env["OA_SESSION_ID"] || this._sessionId || "default";
@@ -530669,69 +530786,19 @@ ${memoryLines.join("\n")}`
530669
530786
  });
530670
530787
  return { tc, output: reg61BlockMsg };
530671
530788
  }
530672
- if (this._decomp2GateActive && process.env["OA_DISABLE_DECOMP2"] !== "1") {
530673
- const DECOMP2_EDIT_TOOLS = /* @__PURE__ */ new Set([
530674
- "file_write",
530675
- "file_edit",
530676
- "batch_edit",
530677
- "file_patch"
530678
- ]);
530679
- if (DECOMP2_EDIT_TOOLS.has(tc.name)) {
530680
- const _editPath = tc.arguments?.["path"] ?? "";
530681
- const _isNewFile = _editPath && !this._decomp2MainContextFiles.has(_editPath);
530682
- if (_isNewFile) {
530683
- this.emit({
530684
- type: "tool_call",
530685
- toolName: tc.name,
530686
- toolArgs: tc.arguments,
530687
- turn,
530688
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
530689
- });
530690
- const _filesList = [...this._decomp2MainContextFiles].slice(0, 8).map((p2) => ` • ${p2}`).join("\n");
530691
- const _moreFiles = this._decomp2MainContextFiles.size > 8 ? `
530692
- ... +${this._decomp2MainContextFiles.size - 8} more` : "";
530693
- const decomp2Msg = [
530694
- `[BLOCKED — DECOMP-2 main-context exhaustion]`,
530695
- ``,
530696
- `You have already edited ${this._decomp2MainContextFiles.size} distinct files in main context without invoking sub_agent. Continuing to edit ANOTHER new file ('${_editPath}') will keep your context window saturated and trigger compaction thrashing.`,
530697
- ``,
530698
- `Files you've already edited (will accept further edits to these):`,
530699
- _filesList,
530700
- _moreFiles,
530701
- ``,
530702
- `For the next module, you MUST use sub_agent. Workflow:`,
530703
- ` 1. Pick a pending todo (the orchestrator pre-populated module todos via DECOMP-1).`,
530704
- ` 2. Call sub_agent({`,
530705
- ` subagent_type: "general",`,
530706
- ` prompt: "Implement <module-path> per spec",`,
530707
- ` relevantFiles: [{path: "<module-path>", content: "" /* or existing content */}],`,
530708
- ` constraints: ["Stay within <module-path>; integration verification happens later"],`,
530709
- ` })`,
530710
- ` 3. After sub_agent returns, mark the todo completed.`,
530711
- ``,
530712
- `Why this matters: spreading edits across N files in main context burns ~N × file_size tokens. sub_agent gives the next module a focused context window.`,
530713
- ``,
530714
- `If you have ALREADY edited '${_editPath}' (this is a continuation), the orchestrator's set must have missed it — call file_read to verify, then re-edit. Otherwise, dispatch sub_agent now.`
530715
- ].join("\n");
530716
- this.emit({
530717
- type: "tool_result",
530718
- toolName: tc.name,
530719
- success: false,
530720
- content: decomp2Msg.slice(0, 120),
530721
- turn,
530722
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
530723
- });
530724
- this.emit({
530725
- type: "status",
530726
- content: `DECOMP-2 NEW-FILE BLOCK — rejected ${tc.name}('${_editPath}') at turn ${turn}; gate stays active until sub_agent is invoked`,
530727
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
530728
- });
530729
- this._tagSyntheticFailure({
530730
- mode: "step_repetition",
530731
- rationale: `DECOMP-2 new-file block on '${tc.name}'(${_editPath}) — agent has spread edits across ${this._decomp2MainContextFiles.size} files without sub_agent`
530732
- });
530733
- return { tc, output: decomp2Msg };
530734
- }
530789
+ {
530790
+ const _decomp2Block = this._maybeDecomp2Block(tc, turn);
530791
+ if (_decomp2Block) {
530792
+ this.emit({ type: "tool_call", toolName: tc.name, toolArgs: tc.arguments, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
530793
+ this.emit({
530794
+ type: "tool_result",
530795
+ toolName: tc.name,
530796
+ success: false,
530797
+ content: _decomp2Block.slice(0, 120),
530798
+ turn,
530799
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
530800
+ });
530801
+ return { tc, output: _decomp2Block };
530735
530802
  }
530736
530803
  }
530737
530804
  const PROGRESS_GATE_BYPASS_TOOLS = /* @__PURE__ */ new Set([
@@ -531841,32 +531908,9 @@ Respond with EXACTLY this structure before your next tool call:
531841
531908
  if (this._fileWriteTimestamps.length > 200) {
531842
531909
  this._fileWriteTimestamps.shift();
531843
531910
  }
531844
- const _editPath = tc.arguments?.["path"] ?? "";
531845
- if (_editPath && typeof _editPath === "string") {
531846
- this._decomp2MainContextFiles.add(_editPath);
531847
- const DECOMP2_FILE_SPREAD_THRESHOLD = 5;
531848
- if (!this._decomp2GateActive && this._decomp2MainContextFiles.size >= DECOMP2_FILE_SPREAD_THRESHOLD && this._decomp2SubAgentCalls === 0 && process.env["OA_DISABLE_DECOMP2"] !== "1") {
531849
- this._decomp2GateActive = true;
531850
- this.emit({
531851
- type: "status",
531852
- content: `DECOMP-2 NEW-FILE GATE ACTIVATED — ${this._decomp2MainContextFiles.size} distinct files edited in main context, 0 sub_agent calls; further edits to NEW files will be blocked until sub_agent is invoked`,
531853
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
531854
- });
531855
- }
531856
- }
531857
- }
531858
- }
531859
- if (tc.name === "sub_agent" || tc.name === "priority_delegate" || tc.name === "background_run") {
531860
- this._decomp2SubAgentCalls++;
531861
- if (this._decomp2GateActive) {
531862
- this._decomp2GateActive = false;
531863
- this.emit({
531864
- type: "status",
531865
- content: `DECOMP-2 GATE CLEARED — '${tc.name}' satisfied delegation directive at turn ${turn}`,
531866
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
531867
- });
531868
531911
  }
531869
531912
  }
531913
+ this._trackDecomp2(tc, result, turn);
531870
531914
  if (result && result.success === false) {
531871
531915
  this._runErrorCount++;
531872
531916
  const errMsg = result.error || "";
@@ -532782,6 +532826,12 @@ Integrate this guidance into your current approach. Continue working on the task
532782
532826
  }
532783
532827
  }
532784
532828
  this.emit({ type: "tool_call", toolName: tc.name, toolArgs: tc.arguments, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
532829
+ const _decomp2BFBlock = this._maybeDecomp2Block(tc, turn);
532830
+ if (_decomp2BFBlock) {
532831
+ this.emit({ type: "tool_result", toolName: tc.name, content: _decomp2BFBlock.slice(0, 200), success: false, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
532832
+ messages2.push(this.buildToolMessage(_decomp2BFBlock, tc.id));
532833
+ continue;
532834
+ }
532785
532835
  const tool = this.tools.get(tc.name);
532786
532836
  let result;
532787
532837
  if (!tool) {
@@ -532830,6 +532880,7 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
532830
532880
  output = modelContent2;
532831
532881
  }
532832
532882
  this.emit({ type: "tool_result", toolName: tc.name, content: output.slice(0, 200), success: result.success, turn, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
532883
+ this._trackDecomp2(tc, result, turn);
532833
532884
  const enoentTools2 = /* @__PURE__ */ new Set(["file_read", "list_directory", "find_files"]);
532834
532885
  if (!result.success && enoentTools2.has(tc.name) && /ENOENT|no such file|does not exist|not found/i.test(result.error ?? result.output)) {
532835
532886
  this._consecutiveEnoent++;
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.528",
3
+ "version": "0.187.529",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "open-agents-ai",
9
- "version": "0.187.528",
9
+ "version": "0.187.529",
10
10
  "hasInstallScript": true,
11
11
  "license": "CC-BY-NC-4.0",
12
12
  "dependencies": {
@@ -1138,9 +1138,9 @@
1138
1138
  }
1139
1139
  },
1140
1140
  "node_modules/@libp2p/webrtc": {
1141
- "version": "6.0.20",
1142
- "resolved": "https://registry.npmjs.org/@libp2p/webrtc/-/webrtc-6.0.20.tgz",
1143
- "integrity": "sha512-hdSgAgXaL0+dbOTNbf5+OQdZHGNQQGVHlursquM3HHsKtkIOVWEWre2Wo8UhAT/LcLtZDVkcx+xsBQmF6ASPyQ==",
1141
+ "version": "6.0.21",
1142
+ "resolved": "https://registry.npmjs.org/@libp2p/webrtc/-/webrtc-6.0.21.tgz",
1143
+ "integrity": "sha512-q7Qiqs/vrdECNRmOfLuYvcH7gLOk94vO8tHpkaIDJv2OxRLDcwAGqQ51K0932shU4DozDJ6203HdWaRJs3MMzg==",
1144
1144
  "license": "Apache-2.0 OR MIT",
1145
1145
  "dependencies": {
1146
1146
  "@chainsafe/is-ip": "^2.1.0",
@@ -1163,7 +1163,7 @@
1163
1163
  "it-stream-types": "^2.0.2",
1164
1164
  "main-event": "^1.0.1",
1165
1165
  "multiformats": "^13.4.0",
1166
- "node-datachannel": "^0.29.0",
1166
+ "node-datachannel": "^0.32.3",
1167
1167
  "p-defer": "^4.0.1",
1168
1168
  "p-event": "^7.0.0",
1169
1169
  "p-timeout": "^7.0.0",
@@ -3179,9 +3179,9 @@
3179
3179
  }
3180
3180
  },
3181
3181
  "node_modules/fast-uri": {
3182
- "version": "3.1.0",
3183
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
3184
- "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==",
3182
+ "version": "3.1.1",
3183
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.1.tgz",
3184
+ "integrity": "sha512-h2r7rcm6Ee/J8o0LD5djLuFVcfbZxhvho4vvsbeV0aMvXjUgqv4YpxpkEx0d68l6+IleVfLAdVEfhR7QNMkGHQ==",
3185
3185
  "funding": [
3186
3186
  {
3187
3187
  "type": "github",
@@ -4558,9 +4558,9 @@
4558
4558
  }
4559
4559
  },
4560
4560
  "node_modules/lru-cache": {
4561
- "version": "11.3.5",
4562
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz",
4563
- "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==",
4561
+ "version": "11.3.6",
4562
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.6.tgz",
4563
+ "integrity": "sha512-Gf/KoL3C/MlI7Bt0PGI9I+TeTC/I6r/csU58N4BSNc4lppLBeKsOdFYkK+dX0ABDUMJNfCHTyPpzwwO21Awd3A==",
4564
4564
  "license": "BlueOak-1.0.0",
4565
4565
  "engines": {
4566
4566
  "node": "20 || >=22"
@@ -4949,9 +4949,9 @@
4949
4949
  "optional": true
4950
4950
  },
4951
4951
  "node_modules/node-datachannel": {
4952
- "version": "0.29.0",
4953
- "resolved": "https://registry.npmjs.org/node-datachannel/-/node-datachannel-0.29.0.tgz",
4954
- "integrity": "sha512-aCRJA5uZRqxMvQAl2QtOnCkodF1qJa1dCUVaXW9D7rku2p6F7PWe5OuRLcIgOYe+e2ZyJu0LefIQ95TtCn6xxA==",
4952
+ "version": "0.32.3",
4953
+ "resolved": "https://registry.npmjs.org/node-datachannel/-/node-datachannel-0.32.3.tgz",
4954
+ "integrity": "sha512-Aok1ZhLsll472lRefgWYuWJ0070jh0ecHravTdRyZEmoESumebMEQV8Y+poBwSW2ZbEwAokAOGsK5Cu8pDDT2g==",
4955
4955
  "hasInstallScript": true,
4956
4956
  "license": "MPL 2.0",
4957
4957
  "dependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.187.528",
3
+ "version": "0.187.529",
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",