oh-my-opencode-slim 1.1.0 → 2.0.0-beta.0

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
@@ -32,7 +32,7 @@ var __toESM = (mod, isNodeMode, target) => {
32
32
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
33
33
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
34
34
 
35
- // node_modules/@mozilla/readability/Readability.js
35
+ // node_modules/.pnpm/@mozilla+readability@0.6.0/node_modules/@mozilla/readability/Readability.js
36
36
  var require_Readability = __commonJS((exports, module) => {
37
37
  function Readability(doc, options) {
38
38
  if (options && options.documentElement) {
@@ -1603,7 +1603,7 @@ var require_Readability = __commonJS((exports, module) => {
1603
1603
  }
1604
1604
  });
1605
1605
 
1606
- // node_modules/@mozilla/readability/Readability-readerable.js
1606
+ // node_modules/.pnpm/@mozilla+readability@0.6.0/node_modules/@mozilla/readability/Readability-readerable.js
1607
1607
  var require_Readability_readerable = __commonJS((exports, module) => {
1608
1608
  var REGEXPS = {
1609
1609
  unlikelyCandidates: /-ad-|ai2html|banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|footer|gdpr|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i,
@@ -1659,7 +1659,7 @@ var require_Readability_readerable = __commonJS((exports, module) => {
1659
1659
  }
1660
1660
  });
1661
1661
 
1662
- // node_modules/@mozilla/readability/index.js
1662
+ // node_modules/.pnpm/@mozilla+readability@0.6.0/node_modules/@mozilla/readability/index.js
1663
1663
  var require_readability = __commonJS((exports, module) => {
1664
1664
  var Readability = require_Readability();
1665
1665
  var isProbablyReaderable = require_Readability_readerable();
@@ -1669,7 +1669,7 @@ var require_readability = __commonJS((exports, module) => {
1669
1669
  };
1670
1670
  });
1671
1671
 
1672
- // node_modules/@mixmark-io/domino/lib/Event.js
1672
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/Event.js
1673
1673
  var require_Event = __commonJS((exports, module) => {
1674
1674
  module.exports = Event;
1675
1675
  Event.CAPTURING_PHASE = 1;
@@ -1726,7 +1726,7 @@ var require_Event = __commonJS((exports, module) => {
1726
1726
  });
1727
1727
  });
1728
1728
 
1729
- // node_modules/@mixmark-io/domino/lib/UIEvent.js
1729
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/UIEvent.js
1730
1730
  var require_UIEvent = __commonJS((exports, module) => {
1731
1731
  var Event = require_Event();
1732
1732
  module.exports = UIEvent;
@@ -1745,7 +1745,7 @@ var require_UIEvent = __commonJS((exports, module) => {
1745
1745
  });
1746
1746
  });
1747
1747
 
1748
- // node_modules/@mixmark-io/domino/lib/MouseEvent.js
1748
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/MouseEvent.js
1749
1749
  var require_MouseEvent = __commonJS((exports, module) => {
1750
1750
  var UIEvent = require_UIEvent();
1751
1751
  module.exports = MouseEvent;
@@ -1803,7 +1803,7 @@ var require_MouseEvent = __commonJS((exports, module) => {
1803
1803
  });
1804
1804
  });
1805
1805
 
1806
- // node_modules/@mixmark-io/domino/lib/DOMException.js
1806
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/DOMException.js
1807
1807
  var require_DOMException = __commonJS((exports, module) => {
1808
1808
  module.exports = DOMException;
1809
1809
  var INDEX_SIZE_ERR = 1;
@@ -1927,12 +1927,12 @@ var require_DOMException = __commonJS((exports, module) => {
1927
1927
  var c;
1928
1928
  });
1929
1929
 
1930
- // node_modules/@mixmark-io/domino/lib/config.js
1930
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/config.js
1931
1931
  var require_config = __commonJS((exports) => {
1932
1932
  exports.isApiWritable = !globalThis.__domino_frozen__;
1933
1933
  });
1934
1934
 
1935
- // node_modules/@mixmark-io/domino/lib/utils.js
1935
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/utils.js
1936
1936
  var require_utils = __commonJS((exports) => {
1937
1937
  var DOMException = require_DOMException();
1938
1938
  var ERR = DOMException;
@@ -2045,7 +2045,7 @@ var require_utils = __commonJS((exports) => {
2045
2045
  };
2046
2046
  });
2047
2047
 
2048
- // node_modules/@mixmark-io/domino/lib/EventTarget.js
2048
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/EventTarget.js
2049
2049
  var require_EventTarget = __commonJS((exports, module) => {
2050
2050
  var Event = require_Event();
2051
2051
  var MouseEvent = require_MouseEvent();
@@ -2233,7 +2233,7 @@ var require_EventTarget = __commonJS((exports, module) => {
2233
2233
  };
2234
2234
  });
2235
2235
 
2236
- // node_modules/@mixmark-io/domino/lib/LinkedList.js
2236
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/LinkedList.js
2237
2237
  var require_LinkedList = __commonJS((exports, module) => {
2238
2238
  var utils = require_utils();
2239
2239
  var LinkedList = module.exports = {
@@ -2276,7 +2276,7 @@ var require_LinkedList = __commonJS((exports, module) => {
2276
2276
  };
2277
2277
  });
2278
2278
 
2279
- // node_modules/@mixmark-io/domino/lib/NodeUtils.js
2279
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/NodeUtils.js
2280
2280
  var require_NodeUtils = __commonJS((exports, module) => {
2281
2281
  module.exports = {
2282
2282
  serializeOne,
@@ -2452,7 +2452,7 @@ var require_NodeUtils = __commonJS((exports, module) => {
2452
2452
  }
2453
2453
  });
2454
2454
 
2455
- // node_modules/@mixmark-io/domino/lib/Node.js
2455
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/Node.js
2456
2456
  var require_Node = __commonJS((exports, module) => {
2457
2457
  module.exports = Node;
2458
2458
  var EventTarget = require_EventTarget();
@@ -3013,7 +3013,7 @@ var require_Node = __commonJS((exports, module) => {
3013
3013
  });
3014
3014
  });
3015
3015
 
3016
- // node_modules/@mixmark-io/domino/lib/NodeList.es6.js
3016
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/NodeList.es6.js
3017
3017
  var require_NodeList_es6 = __commonJS((exports, module) => {
3018
3018
  module.exports = class NodeList extends Array {
3019
3019
  constructor(a) {
@@ -3030,7 +3030,7 @@ var require_NodeList_es6 = __commonJS((exports, module) => {
3030
3030
  };
3031
3031
  });
3032
3032
 
3033
- // node_modules/@mixmark-io/domino/lib/NodeList.es5.js
3033
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/NodeList.es5.js
3034
3034
  var require_NodeList_es5 = __commonJS((exports, module) => {
3035
3035
  function item(i) {
3036
3036
  return this[i] || null;
@@ -3044,7 +3044,7 @@ var require_NodeList_es5 = __commonJS((exports, module) => {
3044
3044
  module.exports = NodeList;
3045
3045
  });
3046
3046
 
3047
- // node_modules/@mixmark-io/domino/lib/NodeList.js
3047
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/NodeList.js
3048
3048
  var require_NodeList = __commonJS((exports, module) => {
3049
3049
  var NodeList;
3050
3050
  try {
@@ -3055,7 +3055,7 @@ var require_NodeList = __commonJS((exports, module) => {
3055
3055
  module.exports = NodeList;
3056
3056
  });
3057
3057
 
3058
- // node_modules/@mixmark-io/domino/lib/ContainerNode.js
3058
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/ContainerNode.js
3059
3059
  var require_ContainerNode = __commonJS((exports, module) => {
3060
3060
  module.exports = ContainerNode;
3061
3061
  var Node = require_Node();
@@ -3123,7 +3123,7 @@ var require_ContainerNode = __commonJS((exports, module) => {
3123
3123
  });
3124
3124
  });
3125
3125
 
3126
- // node_modules/@mixmark-io/domino/lib/xmlnames.js
3126
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/xmlnames.js
3127
3127
  var require_xmlnames = __commonJS((exports) => {
3128
3128
  exports.isValidName = isValidName;
3129
3129
  exports.isValidQName = isValidQName;
@@ -3172,7 +3172,7 @@ var require_xmlnames = __commonJS((exports) => {
3172
3172
  }
3173
3173
  });
3174
3174
 
3175
- // node_modules/@mixmark-io/domino/lib/attributes.js
3175
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/attributes.js
3176
3176
  var require_attributes = __commonJS((exports) => {
3177
3177
  var utils = require_utils();
3178
3178
  exports.property = function(attr) {
@@ -3308,7 +3308,7 @@ var require_attributes = __commonJS((exports) => {
3308
3308
  };
3309
3309
  });
3310
3310
 
3311
- // node_modules/@mixmark-io/domino/lib/FilteredElementList.js
3311
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/FilteredElementList.js
3312
3312
  var require_FilteredElementList = __commonJS((exports, module) => {
3313
3313
  module.exports = FilteredElementList;
3314
3314
  var Node = require_Node();
@@ -3374,7 +3374,7 @@ var require_FilteredElementList = __commonJS((exports, module) => {
3374
3374
  });
3375
3375
  });
3376
3376
 
3377
- // node_modules/@mixmark-io/domino/lib/DOMTokenList.js
3377
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/DOMTokenList.js
3378
3378
  var require_DOMTokenList = __commonJS((exports, module) => {
3379
3379
  var utils = require_utils();
3380
3380
  module.exports = DOMTokenList;
@@ -3536,7 +3536,7 @@ var require_DOMTokenList = __commonJS((exports, module) => {
3536
3536
  }
3537
3537
  });
3538
3538
 
3539
- // node_modules/@mixmark-io/domino/lib/select.js
3539
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/select.js
3540
3540
  var require_select = __commonJS((exports, module) => {
3541
3541
  var window2 = Object.create(null, {
3542
3542
  location: { get: function() {
@@ -4279,7 +4279,7 @@ var require_select = __commonJS((exports, module) => {
4279
4279
  };
4280
4280
  });
4281
4281
 
4282
- // node_modules/@mixmark-io/domino/lib/ChildNode.js
4282
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/ChildNode.js
4283
4283
  var require_ChildNode = __commonJS((exports, module) => {
4284
4284
  var Node = require_Node();
4285
4285
  var LinkedList = require_LinkedList();
@@ -4369,7 +4369,7 @@ var require_ChildNode = __commonJS((exports, module) => {
4369
4369
  module.exports = ChildNode;
4370
4370
  });
4371
4371
 
4372
- // node_modules/@mixmark-io/domino/lib/NonDocumentTypeChildNode.js
4372
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/NonDocumentTypeChildNode.js
4373
4373
  var require_NonDocumentTypeChildNode = __commonJS((exports, module) => {
4374
4374
  var Node = require_Node();
4375
4375
  var NonDocumentTypeChildNode = {
@@ -4395,7 +4395,7 @@ var require_NonDocumentTypeChildNode = __commonJS((exports, module) => {
4395
4395
  module.exports = NonDocumentTypeChildNode;
4396
4396
  });
4397
4397
 
4398
- // node_modules/@mixmark-io/domino/lib/NamedNodeMap.js
4398
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/NamedNodeMap.js
4399
4399
  var require_NamedNodeMap = __commonJS((exports, module) => {
4400
4400
  module.exports = NamedNodeMap;
4401
4401
  var utils = require_utils();
@@ -4432,7 +4432,7 @@ var require_NamedNodeMap = __commonJS((exports, module) => {
4432
4432
  });
4433
4433
  });
4434
4434
 
4435
- // node_modules/@mixmark-io/domino/lib/Element.js
4435
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/Element.js
4436
4436
  var require_Element = __commonJS((exports, module) => {
4437
4437
  module.exports = Element;
4438
4438
  var xml = require_xmlnames();
@@ -5333,7 +5333,7 @@ var require_Element = __commonJS((exports, module) => {
5333
5333
  }
5334
5334
  });
5335
5335
 
5336
- // node_modules/@mixmark-io/domino/lib/Leaf.js
5336
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/Leaf.js
5337
5337
  var require_Leaf = __commonJS((exports, module) => {
5338
5338
  module.exports = Leaf;
5339
5339
  var Node = require_Node();
@@ -5374,7 +5374,7 @@ var require_Leaf = __commonJS((exports, module) => {
5374
5374
  });
5375
5375
  });
5376
5376
 
5377
- // node_modules/@mixmark-io/domino/lib/CharacterData.js
5377
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/CharacterData.js
5378
5378
  var require_CharacterData = __commonJS((exports, module) => {
5379
5379
  module.exports = CharacterData;
5380
5380
  var Leaf = require_Leaf();
@@ -5431,7 +5431,7 @@ var require_CharacterData = __commonJS((exports, module) => {
5431
5431
  Object.defineProperties(CharacterData.prototype, NonDocumentTypeChildNode);
5432
5432
  });
5433
5433
 
5434
- // node_modules/@mixmark-io/domino/lib/Text.js
5434
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/Text.js
5435
5435
  var require_Text = __commonJS((exports, module) => {
5436
5436
  module.exports = Text;
5437
5437
  var utils = require_utils();
@@ -5501,7 +5501,7 @@ var require_Text = __commonJS((exports, module) => {
5501
5501
  });
5502
5502
  });
5503
5503
 
5504
- // node_modules/@mixmark-io/domino/lib/Comment.js
5504
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/Comment.js
5505
5505
  var require_Comment = __commonJS((exports, module) => {
5506
5506
  module.exports = Comment;
5507
5507
  var Node = require_Node();
@@ -5544,7 +5544,7 @@ var require_Comment = __commonJS((exports, module) => {
5544
5544
  });
5545
5545
  });
5546
5546
 
5547
- // node_modules/@mixmark-io/domino/lib/DocumentFragment.js
5547
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/DocumentFragment.js
5548
5548
  var require_DocumentFragment = __commonJS((exports, module) => {
5549
5549
  module.exports = DocumentFragment;
5550
5550
  var Node = require_Node();
@@ -5601,7 +5601,7 @@ var require_DocumentFragment = __commonJS((exports, module) => {
5601
5601
  });
5602
5602
  });
5603
5603
 
5604
- // node_modules/@mixmark-io/domino/lib/ProcessingInstruction.js
5604
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/ProcessingInstruction.js
5605
5605
  var require_ProcessingInstruction = __commonJS((exports, module) => {
5606
5606
  module.exports = ProcessingInstruction;
5607
5607
  var Node = require_Node();
@@ -5650,7 +5650,7 @@ var require_ProcessingInstruction = __commonJS((exports, module) => {
5650
5650
  });
5651
5651
  });
5652
5652
 
5653
- // node_modules/@mixmark-io/domino/lib/NodeFilter.js
5653
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/NodeFilter.js
5654
5654
  var require_NodeFilter = __commonJS((exports, module) => {
5655
5655
  var NodeFilter = {
5656
5656
  FILTER_ACCEPT: 1,
@@ -5673,7 +5673,7 @@ var require_NodeFilter = __commonJS((exports, module) => {
5673
5673
  module.exports = NodeFilter.constructor = NodeFilter.prototype = NodeFilter;
5674
5674
  });
5675
5675
 
5676
- // node_modules/@mixmark-io/domino/lib/NodeTraversal.js
5676
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/NodeTraversal.js
5677
5677
  var require_NodeTraversal = __commonJS((exports, module) => {
5678
5678
  var NodeTraversal = module.exports = {
5679
5679
  nextSkippingChildren,
@@ -5737,7 +5737,7 @@ var require_NodeTraversal = __commonJS((exports, module) => {
5737
5737
  }
5738
5738
  });
5739
5739
 
5740
- // node_modules/@mixmark-io/domino/lib/TreeWalker.js
5740
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/TreeWalker.js
5741
5741
  var require_TreeWalker = __commonJS((exports, module) => {
5742
5742
  module.exports = TreeWalker;
5743
5743
  var Node = require_Node();
@@ -5967,7 +5967,7 @@ var require_TreeWalker = __commonJS((exports, module) => {
5967
5967
  });
5968
5968
  });
5969
5969
 
5970
- // node_modules/@mixmark-io/domino/lib/NodeIterator.js
5970
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/NodeIterator.js
5971
5971
  var require_NodeIterator = __commonJS((exports, module) => {
5972
5972
  module.exports = NodeIterator;
5973
5973
  var NodeFilter = require_NodeFilter();
@@ -6108,7 +6108,7 @@ var require_NodeIterator = __commonJS((exports, module) => {
6108
6108
  });
6109
6109
  });
6110
6110
 
6111
- // node_modules/@mixmark-io/domino/lib/URL.js
6111
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/URL.js
6112
6112
  var require_URL = __commonJS((exports, module) => {
6113
6113
  module.exports = URL4;
6114
6114
  function URL4(url) {
@@ -6281,7 +6281,7 @@ var require_URL = __commonJS((exports, module) => {
6281
6281
  };
6282
6282
  });
6283
6283
 
6284
- // node_modules/@mixmark-io/domino/lib/CustomEvent.js
6284
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/CustomEvent.js
6285
6285
  var require_CustomEvent = __commonJS((exports, module) => {
6286
6286
  module.exports = CustomEvent;
6287
6287
  var Event = require_Event();
@@ -6293,7 +6293,7 @@ var require_CustomEvent = __commonJS((exports, module) => {
6293
6293
  });
6294
6294
  });
6295
6295
 
6296
- // node_modules/@mixmark-io/domino/lib/events.js
6296
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/events.js
6297
6297
  var require_events = __commonJS((exports, module) => {
6298
6298
  module.exports = {
6299
6299
  Event: require_Event(),
@@ -6303,7 +6303,7 @@ var require_events = __commonJS((exports, module) => {
6303
6303
  };
6304
6304
  });
6305
6305
 
6306
- // node_modules/@mixmark-io/domino/lib/style_parser.js
6306
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/style_parser.js
6307
6307
  var require_style_parser = __commonJS((exports) => {
6308
6308
  Object.defineProperty(exports, "__esModule", { value: true });
6309
6309
  exports.hyphenate = exports.parse = undefined;
@@ -6370,7 +6370,7 @@ var require_style_parser = __commonJS((exports) => {
6370
6370
  exports.hyphenate = hyphenate;
6371
6371
  });
6372
6372
 
6373
- // node_modules/@mixmark-io/domino/lib/CSSStyleDeclaration.js
6373
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/CSSStyleDeclaration.js
6374
6374
  var require_CSSStyleDeclaration = __commonJS((exports, module) => {
6375
6375
  var { parse } = require_style_parser();
6376
6376
  module.exports = function(elt) {
@@ -6546,7 +6546,7 @@ var require_CSSStyleDeclaration = __commonJS((exports, module) => {
6546
6546
  });
6547
6547
  });
6548
6548
 
6549
- // node_modules/@mixmark-io/domino/lib/URLUtils.js
6549
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/URLUtils.js
6550
6550
  var require_URLUtils = __commonJS((exports, module) => {
6551
6551
  var URL4 = require_URL();
6552
6552
  module.exports = URLUtils;
@@ -6780,7 +6780,7 @@ var require_URLUtils = __commonJS((exports, module) => {
6780
6780
  };
6781
6781
  });
6782
6782
 
6783
- // node_modules/@mixmark-io/domino/lib/defineElement.js
6783
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/defineElement.js
6784
6784
  var require_defineElement = __commonJS((exports, module) => {
6785
6785
  var attributes = require_attributes();
6786
6786
  var isApiWritable = require_config().isApiWritable;
@@ -6842,7 +6842,7 @@ var require_defineElement = __commonJS((exports, module) => {
6842
6842
  }
6843
6843
  });
6844
6844
 
6845
- // node_modules/@mixmark-io/domino/lib/htmlelts.js
6845
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/htmlelts.js
6846
6846
  var require_htmlelts = __commonJS((exports) => {
6847
6847
  var Node = require_Node();
6848
6848
  var Element = require_Element();
@@ -8306,7 +8306,7 @@ var require_htmlelts = __commonJS((exports) => {
8306
8306
  });
8307
8307
  });
8308
8308
 
8309
- // node_modules/@mixmark-io/domino/lib/svg.js
8309
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/svg.js
8310
8310
  var require_svg = __commonJS((exports) => {
8311
8311
  var Element = require_Element();
8312
8312
  var defineElement = require_defineElement();
@@ -8432,7 +8432,7 @@ var require_svg = __commonJS((exports) => {
8432
8432
  });
8433
8433
  });
8434
8434
 
8435
- // node_modules/@mixmark-io/domino/lib/MutationConstants.js
8435
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/MutationConstants.js
8436
8436
  var require_MutationConstants = __commonJS((exports, module) => {
8437
8437
  module.exports = {
8438
8438
  VALUE: 1,
@@ -8444,7 +8444,7 @@ var require_MutationConstants = __commonJS((exports, module) => {
8444
8444
  };
8445
8445
  });
8446
8446
 
8447
- // node_modules/@mixmark-io/domino/lib/Document.js
8447
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/Document.js
8448
8448
  var require_Document = __commonJS((exports, module) => {
8449
8449
  module.exports = Document;
8450
8450
  var Node = require_Node();
@@ -9156,7 +9156,7 @@ var require_Document = __commonJS((exports, module) => {
9156
9156
  };
9157
9157
  });
9158
9158
 
9159
- // node_modules/@mixmark-io/domino/lib/DocumentType.js
9159
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/DocumentType.js
9160
9160
  var require_DocumentType = __commonJS((exports, module) => {
9161
9161
  module.exports = DocumentType;
9162
9162
  var Node = require_Node();
@@ -9190,7 +9190,7 @@ var require_DocumentType = __commonJS((exports, module) => {
9190
9190
  Object.defineProperties(DocumentType.prototype, ChildNode);
9191
9191
  });
9192
9192
 
9193
- // node_modules/@mixmark-io/domino/lib/HTMLParser.js
9193
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/HTMLParser.js
9194
9194
  var require_HTMLParser = __commonJS((exports, module) => {
9195
9195
  module.exports = HTMLParser;
9196
9196
  var Document = require_Document();
@@ -17241,7 +17241,7 @@ var require_HTMLParser = __commonJS((exports, module) => {
17241
17241
  }
17242
17242
  });
17243
17243
 
17244
- // node_modules/@mixmark-io/domino/lib/DOMImplementation.js
17244
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/DOMImplementation.js
17245
17245
  var require_DOMImplementation = __commonJS((exports, module) => {
17246
17246
  module.exports = DOMImplementation;
17247
17247
  var Document = require_Document();
@@ -17315,7 +17315,7 @@ var require_DOMImplementation = __commonJS((exports, module) => {
17315
17315
  };
17316
17316
  });
17317
17317
 
17318
- // node_modules/@mixmark-io/domino/lib/Location.js
17318
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/Location.js
17319
17319
  var require_Location = __commonJS((exports, module) => {
17320
17320
  var URL4 = require_URL();
17321
17321
  var URLUtils = require_URLUtils();
@@ -17351,7 +17351,7 @@ var require_Location = __commonJS((exports, module) => {
17351
17351
  });
17352
17352
  });
17353
17353
 
17354
- // node_modules/@mixmark-io/domino/lib/NavigatorID.js
17354
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/NavigatorID.js
17355
17355
  var require_NavigatorID = __commonJS((exports, module) => {
17356
17356
  var NavigatorID = Object.create(null, {
17357
17357
  appCodeName: { value: "Mozilla" },
@@ -17370,7 +17370,7 @@ var require_NavigatorID = __commonJS((exports, module) => {
17370
17370
  module.exports = NavigatorID;
17371
17371
  });
17372
17372
 
17373
- // node_modules/@mixmark-io/domino/lib/WindowTimers.js
17373
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/WindowTimers.js
17374
17374
  var require_WindowTimers = __commonJS((exports, module) => {
17375
17375
  var WindowTimers = {
17376
17376
  setTimeout,
@@ -17381,7 +17381,7 @@ var require_WindowTimers = __commonJS((exports, module) => {
17381
17381
  module.exports = WindowTimers;
17382
17382
  });
17383
17383
 
17384
- // node_modules/@mixmark-io/domino/lib/impl.js
17384
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/impl.js
17385
17385
  var require_impl = __commonJS((exports, module) => {
17386
17386
  var utils = require_utils();
17387
17387
  exports = module.exports = {
@@ -17409,7 +17409,7 @@ var require_impl = __commonJS((exports, module) => {
17409
17409
  utils.merge(exports, require_svg().elements);
17410
17410
  });
17411
17411
 
17412
- // node_modules/@mixmark-io/domino/lib/Window.js
17412
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/Window.js
17413
17413
  var require_Window = __commonJS((exports, module) => {
17414
17414
  var DOMImplementation = require_DOMImplementation();
17415
17415
  var EventTarget = require_EventTarget();
@@ -17464,7 +17464,7 @@ var require_Window = __commonJS((exports, module) => {
17464
17464
  utils.expose(require_impl(), Window);
17465
17465
  });
17466
17466
 
17467
- // node_modules/@mixmark-io/domino/lib/index.js
17467
+ // node_modules/.pnpm/@mixmark-io+domino@2.2.0/node_modules/@mixmark-io/domino/lib/index.js
17468
17468
  var require_lib = __commonJS((exports) => {
17469
17469
  var DOMImplementation = require_DOMImplementation();
17470
17470
  var HTMLParser = require_HTMLParser();
@@ -17514,7 +17514,7 @@ var require_lib = __commonJS((exports) => {
17514
17514
  exports.impl = impl;
17515
17515
  });
17516
17516
 
17517
- // node_modules/turndown/lib/turndown.cjs.js
17517
+ // node_modules/.pnpm/turndown@7.2.4/node_modules/turndown/lib/turndown.cjs.js
17518
17518
  var require_turndown_cjs = __commonJS((exports, module) => {
17519
17519
  function extend(destination) {
17520
17520
  for (var i = 1;i < arguments.length; i++) {
@@ -18230,19 +18230,6 @@ var CUSTOM_SKILLS = [
18230
18230
  ];
18231
18231
 
18232
18232
  // src/cli/skills.ts
18233
- var RECOMMENDED_SKILLS = [
18234
- {
18235
- name: "agent-browser",
18236
- repo: "https://github.com/vercel-labs/agent-browser",
18237
- skillName: "agent-browser",
18238
- allowedAgents: ["designer"],
18239
- description: "High-performance browser automation",
18240
- postInstallCommands: [
18241
- "npm install -g agent-browser",
18242
- "agent-browser install"
18243
- ]
18244
- }
18245
- ];
18246
18233
  var PERMISSION_ONLY_SKILLS = [
18247
18234
  {
18248
18235
  name: "requesting-code-review",
@@ -18267,12 +18254,6 @@ function getSkillPermissionsForAgent(agentName, skillList) {
18267
18254
  }
18268
18255
  return permissions;
18269
18256
  }
18270
- for (const skill of RECOMMENDED_SKILLS) {
18271
- const isAllowed = skill.allowedAgents.includes("*") || skill.allowedAgents.includes(agentName);
18272
- if (isAllowed) {
18273
- permissions[skill.skillName] = "allow";
18274
- }
18275
- }
18276
18257
  for (const skill of CUSTOM_SKILLS) {
18277
18258
  const isAllowed = skill.allowedAgents.includes("*") || skill.allowedAgents.includes(agentName);
18278
18259
  if (isAllowed) {
@@ -18322,8 +18303,8 @@ var DEFAULT_TIMEOUT_MS = 2 * 60 * 1000;
18322
18303
  var MAX_POLL_TIME_MS = 5 * 60 * 1000;
18323
18304
  var DEFAULT_MAX_SUBAGENT_DEPTH = 3;
18324
18305
  var PHASE_REMINDER_TEXT = `!IMPORTANT! Recall the workflow rules:
18325
- Understand → choose the best parallelized path based on your capabilities and agents delegation rulesrecall session reuse rulesexecute → verify.
18326
- If delegating, launch the specialist in the same turn you mention it !END!`;
18306
+ Understand → build a short work graph with independent lanes, dependencies, and advisory ownership dispatch independent specialists as background tasks record task/session IDs continue orchestration poll task_status for terminal results reconcile → verify.
18307
+ Only consume outputs or advance dependent work when background results are terminal. !END!`;
18327
18308
  var TMUX_SPAWN_DELAY_MS = 500;
18328
18309
  var COUNCILLOR_STAGGER_MS = 250;
18329
18310
  var DEFAULT_DISABLED_AGENTS = ["observer"];
@@ -18670,7 +18651,9 @@ function loadConfigFromPath(configPath, options) {
18670
18651
  const content = fs.readFileSync(configPath, "utf-8");
18671
18652
  let rawConfig;
18672
18653
  try {
18673
- rawConfig = JSON.parse(stripJsonComments(content));
18654
+ const stripped = stripJsonComments(content);
18655
+ const interpolated = stripped.replace(/\{env:([^}]+)\}/g, (_, varName) => process.env[varName] ?? "");
18656
+ rawConfig = JSON.parse(interpolated);
18674
18657
  } catch (error) {
18675
18658
  const message = error instanceof Error ? error.message : String(error);
18676
18659
  options?.onWarning?.({
@@ -18977,6 +18960,7 @@ ${customAppendPrompt}`;
18977
18960
  }
18978
18961
  var AGENT_DESCRIPTIONS = {
18979
18962
  explorer: `@explorer
18963
+ - Lane: Codebase discovery and reconnaissance
18980
18964
  - Role: Parallel search specialist for discovering unknowns across the codebase
18981
18965
  - Permissions: Read files
18982
18966
  - Stats: 2x faster codebase search than orchestrator, 1/2 cost of orchestrator
@@ -18984,38 +18968,43 @@ var AGENT_DESCRIPTIONS = {
18984
18968
  - **Delegate when:** Need to discover what exists before planning • Parallel searches speed discovery • Need summarized map vs full contents • Broad/uncertain scope
18985
18969
  - **Don't delegate when:** Know the path and need actual content • Need full file anyway • Single specific lookup • About to edit the file`,
18986
18970
  librarian: `@librarian
18971
+ - Lane: External knowledge and library research
18987
18972
  - Role: Authoritative source for current library docs and API references
18988
18973
  - Permissions: External docs/search MCPs; no file edits
18989
18974
  - Stats: 10x better finding up-to-date library docs than orchestrator, 1/2 cost of orchestrator
18990
18975
  - Capabilities: Fetches latest official docs, examples, API signatures, version-specific behavior via grep_app MCP
18991
18976
  - **Delegate when:** Libraries with frequent API changes (React, Next.js, AI SDKs) • Complex APIs needing official examples (ORMs, auth) • Version-specific behavior matters • Unfamiliar library • Edge cases or advanced features • Nuanced best practices
18992
18977
  - **Don't delegate when:** Standard usage you're confident • Simple stable APIs • General programming knowledge • Info already in conversation • Built-in language features
18993
- - **Rule of thumb:** "How does this library work?" → @librarian. "How does programming work?" → yourself.`,
18978
+ - **Rule of thumb:** "How does this library work?" → @librarian. "How does programming work?" → answer directly.`,
18994
18979
  oracle: `@oracle
18980
+ - Lane: Architecture, risk, debugging strategy, and review
18995
18981
  - Role: Strategic advisor for high-stakes decisions and persistent problems, code reviewer
18996
18982
  - Permissions: Read files
18997
18983
  - Stats: 5x better decision maker, problem solver, investigator than orchestrator, 0.8x speed of orchestrator, same cost.
18998
18984
  - Capabilities: Deep architectural reasoning, system-level trade-offs, complex debugging, code review, simplification, maintainability review
18999
18985
  - **Delegate when:** Major architectural decisions with long-term impact • Problems persisting after 2+ fix attempts • High-risk multi-system refactors • Costly trade-offs (performance vs maintainability) • Complex debugging with unclear root cause • Security/scalability/data integrity decisions • Genuinely uncertain and cost of wrong choice is high • When a workflow calls for a **reviewer** subagent • Code needs simplification or YAGNI scrutiny
19000
18986
  - **Don't delegate when:** Routine decisions you're confident about • First bug fix attempt • Straightforward trade-offs • Tactical "how" vs strategic "should" • Time-sensitive good-enough decisions • Quick research/testing can answer
19001
- - **Rule of thumb:** Need senior architect review? → @oracle. Need code review or simplification? → @oracle. Just do it and PR? → yourself.`,
18987
+ - **Rule of thumb:** Need senior architect review? → @oracle. Need code review or simplification? → @oracle. Routine coordination or final synthesis? → handle directly.`,
19002
18988
  designer: `@designer
18989
+ - Lane: User-facing UI/UX design, polish, and review
19003
18990
  - Role: UI/UX specialist for intentional, polished experiences
19004
18991
  - Permissions: Read/write files
19005
18992
  - Stats: 10x better UI/UX than orchestrator
19006
18993
  - Capabilities: Visual relevant edits, interactions, responsive layouts, design systems with aesthetic intent, deep UI/UX knowledge.
19007
18994
  - **Delegate when:** User-facing interfaces needing polish • Responsive layouts • UX-critical components (forms, nav, dashboards) • Visual consistency systems • Animations/micro-interactions • Landing/marketing pages • Refining functional→delightful • Reviewing existing UI/UX quality
19008
18995
  - **Don't delegate when:** Backend/logic with no visual • Quick prototypes where design doesn't matter yet
19009
- - **Rule of thumb:** Users see it and polish matters? → @designer. Headless/functional? → yourself.`,
18996
+ - **Rule of thumb:** Users see it and polish matters? → @designer. Headless/functional implementation? → schedule @fixer.`,
19010
18997
  fixer: `@fixer
18998
+ - Lane: Bounded implementation and test execution
19011
18999
  - Role: Fast execution specialist for well-defined tasks, which empowers orchestrator with parallel, speedy executions
19012
19000
  - Permissions: Read/write files
19013
19001
  - Stats: 2x faster code edits, 1/2 cost of orchestrator, 0.8x quality of orchestrator
19014
19002
  - Tools/Constraints: Execution-focused—no research, no architectural decisions
19015
19003
  - **Delegate when:** For implementation work, think and triage first. If the change is non-trivial or multi-file, hand bounded execution to @fixer • Writing or updating tests • Tasks that touch test files, fixtures, mocks, or test helpers. Parallelization benefits: Task involves multiple folders and multiple files modificaiton, scoping work per folder and spawning parallel @fixers for each folder.
19016
19004
  - **Don't delegate when:** Needs discovery/research/decisions • Single small change (<20 lines, one file) • Unclear requirements needing iteration • Explaining to fixer > doing • Tight integration with your current work • Sequential dependencies
19017
- - **Rule of thumb:** Explaining > doing? yourself. Test file modifications and bounded implementation work usually go to @fixer. Bigger or lots of edits, splitting makes sense, parallelized by spawning @fixers per certain scope.`,
19005
+ - **Rule of thumb:** If implementation or tests are needed, schedule @fixer with clear scope. Bigger or lots of edits should be split by ownership and dispatched as parallel background fixer lanes when safe.`,
19018
19006
  council: `@council
19007
+ - Lane: High-stakes multi-model decision support
19019
19008
  - Role: Multi-LLM consensus engine that runs several councillors, synthesizes their views, and returns a structured council report.
19020
19009
  - Permissions: Read files
19021
19010
  - Stats: 3x slower than orchestrator, 3x or more cost of orchestrator
@@ -19024,15 +19013,16 @@ var AGENT_DESCRIPTIONS = {
19024
19013
  - **Don't delegate when:** Straightforward tasks you're confident about • Speed matters more than confidence • Routine implementation/debugging • A single specialist is clearly the right tool • You only need current docs/search/code review rather than multi-model consensus.
19025
19014
  - **How to call:** Send the full question/task and relevant context. Be explicit about what decision, trade-off, or answer the council should resolve. Do not ask council to do routine code edits.
19026
19015
  - **Result handling:** Council returns a structured response that may include: synthesized Council Response, individual Councillor Details, and Council Summary/confidence. Preserve that structure when the user asked for council output. Do not pretend the council only returned a final answer. If you need to act on the council result, first briefly state the council's recommendation, then proceed.
19027
- - **Rule of thumb:** Need second/third opinions from different models? → @council. Need one expert agent or direct execution? → use the specialist or yourself.`,
19016
+ - **Rule of thumb:** Need second/third opinions from different models? → @council. Need one expert lane? → use the specialist. Need final synthesis? → handle directly.`,
19028
19017
  observer: `@observer
19018
+ - Lane: Visual/media analysis isolated from orchestrator context
19029
19019
  - Role: Visual analysis specialist for images, PDFs, and diagrams
19030
19020
  - Permissions: Read files
19031
19021
  - Stats: Saves main context tokens — Observer processes raw files, returns structured observations
19032
19022
  - Capabilities: Interprets images, screenshots, PDFs, and diagrams via native read tool; extracts UI elements, layouts, text, relationships
19033
19023
  - **Delegate when:** Need to analyze a multimedia file• Extract information
19034
19024
  - **Don't delegate when:** Plain text files that Read can handle directly • Files that need editing afterward (need literal content from Read)
19035
- - **Rule of thumb:** Even if your model supports vision, delegate visual analysis to @observer — it isolates large image/PDF bytes from your context window, returning only concise structured text. Need exact file contents for editing? → Read it yourself.
19025
+ - **Rule of thumb:** Even if your model supports vision, delegate visual analysis to @observer — it isolates large image/PDF bytes from your context window, returning only concise structured text. Need exact file contents for routing? → Read only the minimal context yourself.
19036
19026
  - **IMPORTANT:** When delegating to @observer, always include the **full file path** in the prompt so it can read the file. Example: "Analyze the screenshot at /path/to/file.png — describe the UI elements and error messages."`
19037
19027
  };
19038
19028
  var VALIDATION_ROUTING = [
@@ -19067,7 +19057,9 @@ function buildOrchestratorPrompt(disabledAgents) {
19067
19057
  }).join(`
19068
19058
  `);
19069
19059
  return `<Role>
19070
- You are an AI coding orchestrator that optimizes for quality, speed, cost, and reliability by delegating to specialists when it provides net efficiency gains.
19060
+ You are a workflow manager for coding work. Your job is to plan, schedule, delegate, monitor, reconcile, and verify specialist-agent work. You are not the default implementation worker.
19061
+
19062
+ Optimize for quality, speed, cost, and reliability by dispatching the right specialist lanes, tracking background task state, and integrating terminal results into one coherent outcome.
19071
19063
  </Role>
19072
19064
 
19073
19065
  <Agents>
@@ -19085,22 +19077,31 @@ Parse request: explicit requirements + implicit needs.
19085
19077
  Evaluate approach by: quality, speed, cost, reliability.
19086
19078
  Choose the path that optimizes all four.
19087
19079
 
19080
+ Classify work into lanes: discovery, external knowledge, implementation, UI/UX, review/risk, visual analysis, and final verification.
19081
+
19088
19082
  ## 3. Delegation Check
19089
19083
  **STOP. Review specialists before acting.**
19090
19084
 
19091
- !!! Review available agents and delegation rules. Decide whether to delegate or do it yourself. !!!
19085
+ !!! Review available agents and lane rules. Decide what to schedule, what depends on what, and what minimal direct coordination is needed. !!!
19092
19086
 
19093
- **Delegation efficiency:**
19087
+ **Dispatch efficiency:**
19094
19088
  - Reference paths/lines, don't paste files (\`src/app.ts:42\` not full contents)
19095
19089
  - Provide context summaries, let specialists read what they need
19096
19090
  - Brief user on delegation goal before each call
19097
- - Skip delegation if overhead doing it yourself
19091
+ - Keep direct work limited to clarification, minimal routing context, todos, synthesis, and final checks
19092
+ - For trivial conversational answers or tiny mechanical edits, direct execution is allowed when scheduling overhead would clearly dominate
19093
+
19094
+ ## 4. Plan and Parallelize
19095
+ Build a short work graph before dispatching:
19096
+ - Independent lanes that can run now
19097
+ - Dependency-ordered lanes that must wait
19098
+ - Advisory ownership for write-capable lanes
19099
+ - Verification/review lanes that run after implementation
19098
19100
 
19099
- ## 4. Split and Parallelize
19100
- Can tasks be split into subtasks and run in parallel?
19101
+ Can tasks be split into background specialist work?
19101
19102
  ${enabledParallelExamples}
19102
19103
 
19103
- Balance: respect dependencies, avoid parallelizing what must be sequential.
19104
+ Balance: respect dependencies, avoid parallelizing what must be sequential, and avoid overlapping write ownership.
19104
19105
 
19105
19106
  ### Context Isolation
19106
19107
  If no specialist delegation is needed, consider \`subtask\` before doing
@@ -19113,6 +19114,8 @@ compact outcome.
19113
19114
  Use \`subtask\` for focused investigation, bounded analysis, cleanup, or
19114
19115
  verification across files/logs/messages.
19115
19116
 
19117
+ Prefer native background \`task(..., background: true)\` plus \`task_status\` for independent specialist lanes. Use \`subtask\` only for bounded parent-local context isolation when native background specialist scheduling is not the right fit.
19118
+
19116
19119
  Do not use \`subtask\` for tiny tasks, open-ended work, interactive decisions,
19117
19120
  work better handled by a named specialist, or cases where the parent must reason
19118
19121
  over the details.
@@ -19121,21 +19124,28 @@ When calling \`subtask\`, give a self-contained prompt with objective,
19121
19124
  constraints, relevant context, deliverable, and validation. Pass only clearly
19122
19125
  relevant files. Wait for the summary, then integrate and verify it.
19123
19126
 
19124
- ### OpenCode subagent execution model
19125
- - A delegated specialist runs in a separate child session.
19126
- - Delegation is blocking for the parent at that point: send work out, then continue that line after results return.
19127
- - Parallel delegation means launching multiple independent child-session branches.
19128
- - Only parallelize branches that are truly independent; reconcile dependent steps after delegated results come back.
19129
-
19130
- ## 5. Execute
19131
- 1. Break complex tasks into todos
19132
- 2. Fire parallel research/implementation
19133
- 3. Delegate to specialists or do it yourself based on step 3
19134
- 4. Integrate results
19135
- 5. Adjust if needed
19127
+ ### OpenCode scheduler model
19128
+ - Delegated specialists should be launched as background tasks whenever work can run independently: use \`task(..., background: true)\`.
19129
+ - A dispatch returns a task/session ID immediately; it does not mean completion.
19130
+ - Track each task ID with specialist, objective, state, and any advisory ownership/dependency labels from the dispatch plan.
19131
+ - Continue orchestration while tasks run: planning, scheduling independent lanes, preparing synthesis, and asking needed user questions.
19132
+ - Poll or wait with \`task_status(wait: true, timeout_ms: ...)\` before consuming outputs or starting dependent work.
19133
+ - Parallel background tasks are allowed only when their write scopes do not conflict.
19134
+ - Final response requires relevant tasks to be terminal and reconciled.
19135
+
19136
+ ## 5. Dispatch
19137
+ 1. Split work into independent and dependency-ordered lanes
19138
+ 2. Plan advisory ownership for write-capable lanes
19139
+ 3. Dispatch independent specialists as background tasks
19140
+ 4. Record task IDs, state, and advisory ownership/dependency labels
19141
+ 5. Continue only independent orchestration while jobs run
19142
+ 6. Poll/wait for terminal results with \`task_status(wait: true, timeout_ms: ...)\`
19143
+ 7. Reconcile results, resolve conflicts, and gate dependent lanes
19144
+ 8. Dispatch follow-up jobs if needed
19145
+ 9. Verify final state
19136
19146
 
19137
19147
  ### Session Reuse
19138
- - Smartly reuse an available specialist session - constext reuse saves time and tokens
19148
+ - Smartly reuse an available specialist session - context reuse saves time and tokens
19139
19149
  - When too much unrelated, and really needed, start a fresh session with the specialist
19140
19150
  - If multiple remembered sessions fit, prefer the most recently used matching session.
19141
19151
  - Prefer re-uses over creating new sessions all the time
@@ -19187,7 +19197,7 @@ When user's approach seems problematic:
19187
19197
  **Bad:** "Great question! Let me think about the best approach here. I'm going to delegate to @librarian to check the latest Next.js documentation for the App Router, and then I'll implement the solution for you."
19188
19198
 
19189
19199
  **Good:** "Checking Next.js App Router docs via @librarian..."
19190
- [proceeds with implementation]
19200
+ [continues scheduling or integration]
19191
19201
 
19192
19202
  </Communication>
19193
19203
  `;
@@ -22600,6 +22610,221 @@ function createDisplayNameMentionRewriter(config) {
22600
22610
  return rewritten;
22601
22611
  };
22602
22612
  }
22613
+ // src/utils/task.ts
22614
+ function parseTaskIdFromTaskOutput(output) {
22615
+ const lines = output.split(/\r?\n/);
22616
+ for (const line of lines) {
22617
+ const trimmed = line.trim();
22618
+ const match = /^task_id:\s*([^\s()]+)(?:\s*\(.*)?$/.exec(trimmed);
22619
+ if (!match) {
22620
+ continue;
22621
+ }
22622
+ return match[1];
22623
+ }
22624
+ return;
22625
+ }
22626
+ function parseTaskLaunchOutput(output) {
22627
+ const taskID = parseTaskIdFromTaskOutput(output);
22628
+ const state = parseTaskStateFromOutput(output);
22629
+ if (!taskID || state !== "running")
22630
+ return;
22631
+ return {
22632
+ taskID,
22633
+ state,
22634
+ result: parseTaskResultFromOutput(output)
22635
+ };
22636
+ }
22637
+ function parseTaskStatusOutput(output) {
22638
+ const taskID = parseTaskIdFromTaskOutput(output);
22639
+ const state = parseTaskStateFromOutput(output);
22640
+ if (!taskID || !state)
22641
+ return;
22642
+ return {
22643
+ taskID,
22644
+ state,
22645
+ timedOut: state === "running" && /Timed out after \d+ms/i.test(output),
22646
+ result: parseTaskResultFromOutput(output)
22647
+ };
22648
+ }
22649
+ function parseTaskStateFromOutput(output) {
22650
+ for (const line of getTaskHeader(output).split(/\r?\n/)) {
22651
+ const match = /^state:\s*(running|completed|error|cancelled)\s*$/i.exec(line.trim());
22652
+ if (match)
22653
+ return match[1].toLowerCase();
22654
+ }
22655
+ return;
22656
+ }
22657
+ function parseTaskResultFromOutput(output) {
22658
+ const match = /<task_(result|error)>\s*([\s\S]*?)\s*<\/task_\1>/m.exec(output);
22659
+ const result = match?.[2]?.trim();
22660
+ return result || undefined;
22661
+ }
22662
+ function getTaskHeader(output) {
22663
+ const resultIndex = output.search(/<task_(?:result|error)>/);
22664
+ if (resultIndex === -1)
22665
+ return output;
22666
+ return output.slice(0, resultIndex);
22667
+ }
22668
+
22669
+ // src/utils/background-job-board.ts
22670
+ var TERMINAL_STATES = new Set([
22671
+ "completed",
22672
+ "error",
22673
+ "cancelled"
22674
+ ]);
22675
+ var AGENT_PREFIX = {
22676
+ council: "cou",
22677
+ designer: "des",
22678
+ explorer: "exp",
22679
+ fixer: "fix",
22680
+ librarian: "lib",
22681
+ observer: "obs",
22682
+ oracle: "ora"
22683
+ };
22684
+
22685
+ class BackgroundJobBoard {
22686
+ jobs = new Map;
22687
+ counters = new Map;
22688
+ registerLaunch(input) {
22689
+ const now = input.now ?? Date.now();
22690
+ const existing = this.jobs.get(input.taskID);
22691
+ if (existing) {
22692
+ const updated = {
22693
+ ...existing,
22694
+ agent: input.agent || existing.agent,
22695
+ description: input.description || existing.description,
22696
+ objective: input.objective ?? existing.objective,
22697
+ state: "running",
22698
+ timedOut: false,
22699
+ terminalUnreconciled: false,
22700
+ completedAt: undefined,
22701
+ resultSummary: undefined,
22702
+ updatedAt: now
22703
+ };
22704
+ this.jobs.set(input.taskID, updated);
22705
+ return updated;
22706
+ }
22707
+ const record = {
22708
+ taskID: input.taskID,
22709
+ parentSessionID: input.parentSessionID,
22710
+ agent: input.agent,
22711
+ description: input.description || `background ${input.agent} task`,
22712
+ objective: input.objective,
22713
+ state: "running",
22714
+ timedOut: false,
22715
+ terminalUnreconciled: false,
22716
+ launchedAt: now,
22717
+ updatedAt: now,
22718
+ alias: this.nextAlias(input.parentSessionID, input.agent)
22719
+ };
22720
+ this.jobs.set(input.taskID, record);
22721
+ return record;
22722
+ }
22723
+ updateStatus(input) {
22724
+ const existing = this.jobs.get(input.taskID);
22725
+ if (!existing)
22726
+ return;
22727
+ const now = input.now ?? Date.now();
22728
+ const terminal = TERMINAL_STATES.has(input.state);
22729
+ const updated = {
22730
+ ...existing,
22731
+ state: input.state,
22732
+ timedOut: input.timedOut ?? false,
22733
+ terminalUnreconciled: terminal ? true : existing.terminalUnreconciled,
22734
+ updatedAt: now,
22735
+ completedAt: terminal ? existing.completedAt ?? now : existing.completedAt,
22736
+ resultSummary: input.resultSummary ?? existing.resultSummary
22737
+ };
22738
+ this.jobs.set(input.taskID, updated);
22739
+ return updated;
22740
+ }
22741
+ updateFromStatusOutput(output) {
22742
+ const status = parseTaskStatusOutput(output);
22743
+ if (!status)
22744
+ return;
22745
+ return this.updateStatus({
22746
+ taskID: status.taskID,
22747
+ state: status.state,
22748
+ timedOut: status.timedOut,
22749
+ resultSummary: status.result
22750
+ });
22751
+ }
22752
+ markReconciled(taskID, now = Date.now()) {
22753
+ const existing = this.jobs.get(taskID);
22754
+ if (!existing)
22755
+ return;
22756
+ if (!existing.terminalUnreconciled && !TERMINAL_STATES.has(existing.state)) {
22757
+ return;
22758
+ }
22759
+ const updated = {
22760
+ ...existing,
22761
+ state: "reconciled",
22762
+ terminalUnreconciled: false,
22763
+ updatedAt: now
22764
+ };
22765
+ this.jobs.set(taskID, updated);
22766
+ return updated;
22767
+ }
22768
+ get(taskID) {
22769
+ return this.jobs.get(taskID);
22770
+ }
22771
+ list(parentSessionID) {
22772
+ const jobs = [...this.jobs.values()];
22773
+ const filtered = parentSessionID ? jobs.filter((job) => job.parentSessionID === parentSessionID) : jobs;
22774
+ return filtered.sort((a, b) => a.launchedAt - b.launchedAt);
22775
+ }
22776
+ hasRunning(parentSessionID) {
22777
+ return this.list(parentSessionID).some((job) => job.state === "running");
22778
+ }
22779
+ hasTerminalUnreconciled(parentSessionID) {
22780
+ return this.list(parentSessionID).some((job) => job.terminalUnreconciled);
22781
+ }
22782
+ formatForPrompt(parentSessionID) {
22783
+ const jobs = this.list(parentSessionID).filter((job) => job.state === "running" || job.terminalUnreconciled);
22784
+ if (jobs.length === 0)
22785
+ return;
22786
+ return [
22787
+ "### Background Job Board",
22788
+ "Use task_status before consuming running jobs. Reconcile terminal jobs before final response.",
22789
+ "",
22790
+ ...jobs.map(formatJob)
22791
+ ].join(`
22792
+ `);
22793
+ }
22794
+ clearParent(parentSessionID) {
22795
+ for (const job of this.list(parentSessionID)) {
22796
+ this.jobs.delete(job.taskID);
22797
+ }
22798
+ }
22799
+ drop(taskID) {
22800
+ this.jobs.delete(taskID);
22801
+ }
22802
+ nextAlias(parentSessionID, agent) {
22803
+ const prefix2 = AGENT_PREFIX[agent] ?? (agent.slice(0, 3) || "job");
22804
+ const key = `${parentSessionID}:${prefix2}`;
22805
+ const next = (this.counters.get(key) ?? 0) + 1;
22806
+ this.counters.set(key, next);
22807
+ return `${prefix2}-${next}`;
22808
+ }
22809
+ }
22810
+ function formatJob(job) {
22811
+ const status = job.terminalUnreconciled ? `${job.state}, unreconciled` : job.timedOut ? `${job.state}, timed out` : job.state;
22812
+ const lines = [
22813
+ `- ${job.alias} / ${job.taskID} / ${job.agent} / ${status}`,
22814
+ ` Objective: ${job.objective || job.description}`
22815
+ ];
22816
+ if (job.resultSummary && job.terminalUnreconciled) {
22817
+ lines.push(` Result: ${singleLine(job.resultSummary)}`);
22818
+ }
22819
+ return lines.join(`
22820
+ `);
22821
+ }
22822
+ function singleLine(value) {
22823
+ const normalized = value.replace(/\s+/g, " ").trim();
22824
+ if (normalized.length <= 160)
22825
+ return normalized;
22826
+ return `${normalized.slice(0, 157)}...`;
22827
+ }
22603
22828
  // src/utils/internal-initiator.ts
22604
22829
  var SLIM_INTERNAL_INITIATOR_MARKER = "<!-- SLIM_INTERNAL_INITIATOR -->";
22605
22830
  function isRecord(value) {
@@ -22851,19 +23076,6 @@ function formatContextFiles(files, options) {
22851
23076
  const rendered = shown.map((file) => `${file.path} (${file.lineCount} lines)`);
22852
23077
  return `${rendered.join(", ")}${rest > 0 ? ` (+${rest} more)` : ""}`;
22853
23078
  }
22854
- // src/utils/task.ts
22855
- function parseTaskIdFromTaskOutput(output) {
22856
- const lines = output.split(/\r?\n/);
22857
- for (const line of lines) {
22858
- const trimmed = line.trim();
22859
- const match = /^task_id:\s*([^\s()]+)(?:\s*\(.*)?$/.exec(trimmed);
22860
- if (!match) {
22861
- continue;
22862
- }
22863
- return match[1];
22864
- }
22865
- return;
22866
- }
22867
23079
  // src/utils/zip-extractor.ts
22868
23080
  import { spawnSync } from "node:child_process";
22869
23081
  import { release } from "node:os";
@@ -23677,14 +23889,13 @@ function createPhaseReminderHook() {
23677
23889
  if (originalText.includes(SLIM_INTERNAL_INITIATOR_MARKER)) {
23678
23890
  return;
23679
23891
  }
23680
- if (originalText.includes(PHASE_REMINDER)) {
23892
+ if (lastUserMessage.parts.some((p) => p.text?.includes(PHASE_REMINDER))) {
23681
23893
  return;
23682
23894
  }
23683
- lastUserMessage.parts[textPartIndex].text = `${originalText}
23684
-
23685
- ---
23686
-
23687
- ${PHASE_REMINDER}`;
23895
+ lastUserMessage.parts.push({
23896
+ type: "text",
23897
+ text: PHASE_REMINDER
23898
+ });
23688
23899
  }
23689
23900
  };
23690
23901
  }
@@ -23720,8 +23931,338 @@ function createPostFileToolNudgeHook(options = {}) {
23720
23931
  }
23721
23932
  };
23722
23933
  }
23934
+ // src/hooks/session-goal/index.ts
23935
+ import * as fs7 from "node:fs/promises";
23936
+
23937
+ // src/interview/document.ts
23938
+ import * as fsSync from "node:fs";
23939
+ import * as fs6 from "node:fs/promises";
23940
+ import * as path9 from "node:path";
23941
+ var DEFAULT_OUTPUT_FOLDER = "interview";
23942
+ function normalizeOutputFolder(outputFolder) {
23943
+ const normalized = outputFolder.trim().replace(/^\/+|\/+$/g, "");
23944
+ return normalized || DEFAULT_OUTPUT_FOLDER;
23945
+ }
23946
+ function createInterviewDirectoryPath(directory, outputFolder) {
23947
+ return path9.join(directory, normalizeOutputFolder(outputFolder));
23948
+ }
23949
+ function createInterviewFilePath(directory, outputFolder, idea) {
23950
+ const fileName = `${slugify(idea) || "interview"}.md`;
23951
+ return path9.join(createInterviewDirectoryPath(directory, outputFolder), fileName);
23952
+ }
23953
+ function relativeInterviewPath(directory, filePath) {
23954
+ return path9.relative(directory, filePath) || path9.basename(filePath);
23955
+ }
23956
+ function resolveExistingInterviewPath(directory, outputFolder, value) {
23957
+ const trimmed = value.trim();
23958
+ if (!trimmed) {
23959
+ return null;
23960
+ }
23961
+ const outputDir = createInterviewDirectoryPath(directory, outputFolder);
23962
+ const candidates = new Set;
23963
+ const resolvedRoot = path9.resolve(directory);
23964
+ if (path9.isAbsolute(trimmed)) {
23965
+ candidates.add(trimmed);
23966
+ } else {
23967
+ candidates.add(path9.resolve(directory, trimmed));
23968
+ candidates.add(path9.join(outputDir, trimmed));
23969
+ if (!trimmed.endsWith(".md")) {
23970
+ candidates.add(path9.join(outputDir, `${trimmed}.md`));
23971
+ }
23972
+ }
23973
+ for (const candidate of candidates) {
23974
+ if (path9.extname(candidate) !== ".md") {
23975
+ continue;
23976
+ }
23977
+ const resolved = path9.resolve(candidate);
23978
+ if (!resolved.startsWith(resolvedRoot + path9.sep) && resolved !== resolvedRoot) {
23979
+ continue;
23980
+ }
23981
+ if (fsSync.existsSync(candidate)) {
23982
+ return candidate;
23983
+ }
23984
+ }
23985
+ return null;
23986
+ }
23987
+ function slugify(value) {
23988
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
23989
+ }
23990
+ function extractHistorySection(document) {
23991
+ const marker = `## Q&A history
23992
+
23993
+ `;
23994
+ const index = document.indexOf(marker);
23995
+ return index >= 0 ? document.slice(index + marker.length).trim() : "";
23996
+ }
23997
+ function extractSummarySection(document) {
23998
+ const marker = `## Current spec
23999
+
24000
+ `;
24001
+ const historyMarker = `
24002
+
24003
+ ## Q&A history`;
24004
+ const start = document.indexOf(marker);
24005
+ if (start < 0) {
24006
+ return "";
24007
+ }
24008
+ const summaryStart = start + marker.length;
24009
+ const summaryEnd = document.indexOf(historyMarker, summaryStart);
24010
+ return document.slice(summaryStart, summaryEnd >= 0 ? summaryEnd : undefined).trim();
24011
+ }
24012
+ function extractTitle(document) {
24013
+ const match = document.match(/^#\s+(.+)$/m);
24014
+ return match?.[1]?.trim() ?? "";
24015
+ }
24016
+ function buildInterviewDocument(idea, summary, history, meta) {
24017
+ const normalizedSummary = summary.trim() || "Waiting for interview answers.";
24018
+ const normalizedHistory = history.trim() || "No answers yet.";
24019
+ const frontmatter = meta?.sessionID ? [
24020
+ "---",
24021
+ `sessionID: ${meta.sessionID}`,
24022
+ `baseMessageCount: ${meta.baseMessageCount ?? 0}`,
24023
+ `updatedAt: ${new Date().toISOString()}`,
24024
+ "---",
24025
+ ""
24026
+ ].join(`
24027
+ `) : "";
24028
+ return [
24029
+ frontmatter,
24030
+ `# ${idea}`,
24031
+ "",
24032
+ "## Current spec",
24033
+ "",
24034
+ normalizedSummary,
24035
+ "",
24036
+ "## Q&A history",
24037
+ "",
24038
+ normalizedHistory,
24039
+ ""
24040
+ ].join(`
24041
+ `);
24042
+ }
24043
+ function parseFrontmatter(content) {
24044
+ const match = content.match(/^---\n([\s\S]*?)\n---\n/);
24045
+ if (!match)
24046
+ return null;
24047
+ const result = {};
24048
+ for (const line of match[1].split(`
24049
+ `)) {
24050
+ const colonIdx = line.indexOf(":");
24051
+ if (colonIdx > 0) {
24052
+ result[line.slice(0, colonIdx).trim()] = line.slice(colonIdx + 1).trim();
24053
+ }
24054
+ }
24055
+ return result;
24056
+ }
24057
+ async function ensureInterviewFile(record) {
24058
+ await fs6.mkdir(path9.dirname(record.markdownPath), { recursive: true });
24059
+ try {
24060
+ await fs6.access(record.markdownPath);
24061
+ } catch {
24062
+ await fs6.writeFile(record.markdownPath, buildInterviewDocument(record.idea, "", "", {
24063
+ sessionID: record.sessionID,
24064
+ baseMessageCount: record.baseMessageCount
24065
+ }), "utf8");
24066
+ }
24067
+ }
24068
+ async function readInterviewDocument(record) {
24069
+ try {
24070
+ return await fs6.readFile(record.markdownPath, "utf8");
24071
+ } catch {}
24072
+ await ensureInterviewFile(record);
24073
+ return fs6.readFile(record.markdownPath, "utf8");
24074
+ }
24075
+ async function rewriteInterviewDocument(record, summary) {
24076
+ const existing = await readInterviewDocument(record);
24077
+ const history = extractHistorySection(existing);
24078
+ const next = buildInterviewDocument(record.idea, summary, history, {
24079
+ sessionID: record.sessionID,
24080
+ baseMessageCount: record.baseMessageCount
24081
+ });
24082
+ await fs6.writeFile(record.markdownPath, next, "utf8");
24083
+ return next;
24084
+ }
24085
+ async function appendInterviewAnswers(record, questions, answers) {
24086
+ const existing = await readInterviewDocument(record);
24087
+ const summary = extractSummarySection(existing);
24088
+ const history = extractHistorySection(existing);
24089
+ const questionMap = new Map(questions.map((question) => [question.id, question]));
24090
+ const appended = answers.map((answer) => {
24091
+ const question = questionMap.get(answer.questionId);
24092
+ return question ? `Q: ${question.question}
24093
+ A: ${answer.answer.trim()}` : null;
24094
+ }).filter((value) => value !== null).join(`
24095
+
24096
+ `);
24097
+ const nextHistory = [history === "No answers yet." ? "" : history, appended].filter(Boolean).join(`
24098
+
24099
+ `);
24100
+ await fs6.writeFile(record.markdownPath, buildInterviewDocument(record.idea, summary, nextHistory, {
24101
+ sessionID: record.sessionID,
24102
+ baseMessageCount: record.baseMessageCount
24103
+ }), "utf8");
24104
+ }
24105
+
24106
+ // src/hooks/session-goal/index.ts
24107
+ var COMMAND_NAME = "goal";
24108
+ var MAX_GOAL_LENGTH = 4000;
24109
+ function normalizeGoalText(text) {
24110
+ return text.trim().replace(/\s+/g, " ").slice(0, MAX_GOAL_LENGTH);
24111
+ }
24112
+ function trimGoalText(text) {
24113
+ return text.trim().slice(0, MAX_GOAL_LENGTH);
24114
+ }
24115
+ function pushText(output, text) {
24116
+ output.parts.push(createInternalAgentTextPart(text));
24117
+ }
24118
+ function formatGoal(state, inherited) {
24119
+ const tag = inherited ? "parent_goal" : "active_goal";
24120
+ const guidance = inherited ? "This is context only. Your delegated prompt remains the bounded task." : "Use todos as the execution ledger. Keep planning, delegation, edits, and verification aligned to this goal. Do not broaden scope unless the user changes the goal.";
24121
+ return `<${tag}>
24122
+ Objective: ${state.text}
24123
+ ${guidance}
24124
+ </${tag}>`;
24125
+ }
24126
+ async function readInterviewGoal(directory, outputFolder, value) {
24127
+ try {
24128
+ const sourcePath = resolveExistingInterviewPath(directory, outputFolder, value);
24129
+ if (!sourcePath)
24130
+ return null;
24131
+ const content = await fs7.readFile(sourcePath, "utf8");
24132
+ const title = extractTitle(content);
24133
+ const summary = extractSummarySection(content);
24134
+ const text = trimGoalText([title ? `From interview: ${title}` : "", summary].filter(Boolean).join(`
24135
+
24136
+ `));
24137
+ return text ? { text, sourcePath } : null;
24138
+ } catch {
24139
+ return null;
24140
+ }
24141
+ }
24142
+ function resolveGoal(goals, sessionID) {
24143
+ const seen = new Set;
24144
+ let currentSessionID = sessionID;
24145
+ let inherited = false;
24146
+ while (true) {
24147
+ if (seen.has(currentSessionID)) {
24148
+ goals.delete(sessionID);
24149
+ return null;
24150
+ }
24151
+ seen.add(currentSessionID);
24152
+ const goal = goals.get(currentSessionID);
24153
+ if (!goal) {
24154
+ goals.delete(sessionID);
24155
+ return null;
24156
+ }
24157
+ if (!goal.inheritedFrom) {
24158
+ return { goal, inherited };
24159
+ }
24160
+ inherited = true;
24161
+ currentSessionID = goal.inheritedFrom;
24162
+ }
24163
+ }
24164
+ function createSessionGoalHook(ctx, config, options) {
24165
+ const goals = new Map;
24166
+ const outputFolder = config.interview?.outputFolder ?? "interview";
24167
+ return {
24168
+ registerCommand: (opencodeConfig) => {
24169
+ const commandConfig = opencodeConfig.command;
24170
+ if (commandConfig?.[COMMAND_NAME])
24171
+ return;
24172
+ if (!opencodeConfig.command)
24173
+ opencodeConfig.command = {};
24174
+ opencodeConfig.command[COMMAND_NAME] = {
24175
+ template: "Set or show the current session goal",
24176
+ description: "Pin a session objective that keeps todos, delegation, and verification aligned"
24177
+ };
24178
+ },
24179
+ handleCommandExecuteBefore: async (input, output) => {
24180
+ if (input.command !== COMMAND_NAME)
24181
+ return;
24182
+ output.parts.length = 0;
24183
+ const args = input.arguments.trim();
24184
+ if (!args) {
24185
+ const resolved = resolveGoal(goals, input.sessionID);
24186
+ pushText(output, resolved ? `Active goal:
24187
+ ${resolved.goal.text}
24188
+
24189
+ Use todos for execution steps. Auto-continuation continues only while todos remain.` : "No active goal. Set one with /goal <objective>.");
24190
+ return;
24191
+ }
24192
+ if (args === "clear") {
24193
+ goals.delete(input.sessionID);
24194
+ pushText(output, "Cleared the active goal for this session.");
24195
+ return;
24196
+ }
24197
+ if (args.startsWith("from ")) {
24198
+ const value = args.slice("from ".length).trim();
24199
+ const interviewGoal = await readInterviewGoal(ctx.directory, outputFolder, value);
24200
+ if (!interviewGoal) {
24201
+ pushText(output, `Could not find a readable interview spec for "${value}".`);
24202
+ return;
24203
+ }
24204
+ goals.set(input.sessionID, {
24205
+ text: interviewGoal.text,
24206
+ source: "interview",
24207
+ sourcePath: interviewGoal.sourcePath,
24208
+ createdAt: Date.now()
24209
+ });
24210
+ pushText(output, `Set active goal from interview:
24211
+ ${interviewGoal.text}`);
24212
+ return;
24213
+ }
24214
+ const text = normalizeGoalText(args);
24215
+ goals.set(input.sessionID, {
24216
+ text,
24217
+ source: "manual",
24218
+ createdAt: Date.now()
24219
+ });
24220
+ pushText(output, `Set active goal:
24221
+ ${text}`);
24222
+ },
24223
+ handleEvent: (input) => {
24224
+ const event = input.event;
24225
+ if (event.type === "session.created") {
24226
+ const info = event.properties?.info;
24227
+ if (!info?.id || !info.parentID)
24228
+ return;
24229
+ const parentGoal = goals.get(info.parentID);
24230
+ if (!parentGoal)
24231
+ return;
24232
+ goals.set(info.id, {
24233
+ inheritedFrom: info.parentID,
24234
+ createdAt: Date.now(),
24235
+ text: ""
24236
+ });
24237
+ return;
24238
+ }
24239
+ if (event.type === "session.deleted") {
24240
+ const props = event.properties;
24241
+ const sessionID = props?.info?.id ?? props?.sessionID;
24242
+ if (sessionID)
24243
+ goals.delete(sessionID);
24244
+ }
24245
+ },
24246
+ handleSystemTransform: (input, output) => {
24247
+ if (!input.sessionID)
24248
+ return;
24249
+ const resolved = resolveGoal(goals, input.sessionID);
24250
+ if (!resolved)
24251
+ return;
24252
+ const agentName = options?.getAgentName?.(input.sessionID);
24253
+ const { goal, inherited } = resolved;
24254
+ if (!inherited && agentName && agentName !== "orchestrator")
24255
+ return;
24256
+ const block = formatGoal(goal, inherited);
24257
+ if (output.system.some((entry) => entry.includes(block)))
24258
+ return;
24259
+ output.system.push(block);
24260
+ },
24261
+ getGoal: (sessionID) => resolveGoal(goals, sessionID)?.goal
24262
+ };
24263
+ }
23723
24264
  // src/hooks/task-session-manager/index.ts
23724
- import path9 from "node:path";
24265
+ import path10 from "node:path";
23725
24266
  var AGENT_NAME_SET = new Set([
23726
24267
  "orchestrator",
23727
24268
  "oracle",
@@ -23736,6 +24277,9 @@ var AGENT_NAME_SET = new Set([
23736
24277
  var MAX_PENDING_TASK_CALLS = 100;
23737
24278
  var RESUMABLE_SESSIONS_START = "<resumable_sessions>";
23738
24279
  var RESUMABLE_SESSIONS_END = "</resumable_sessions>";
24280
+ var BACKGROUND_COMPLETION_COMPLETED = /^Background task completed: /;
24281
+ var BACKGROUND_COMPLETION_FAILED = /^Background task failed: /;
24282
+ var MAX_PROCESSED_INJECTED_COMPLETIONS = 500;
23739
24283
  function isAgentName(value) {
23740
24284
  return typeof value === "string" && AGENT_NAME_SET.has(value);
23741
24285
  }
@@ -23746,11 +24290,11 @@ function extractPath(output) {
23746
24290
  return /<path>([^<]+)<\/path>/.exec(output)?.[1];
23747
24291
  }
23748
24292
  function normalizePath(root, file) {
23749
- const relative = path9.relative(root, file);
23750
- if (!relative || relative.startsWith("..") || path9.isAbsolute(relative)) {
24293
+ const relative2 = path10.relative(root, file);
24294
+ if (!relative2 || relative2.startsWith("..") || path10.isAbsolute(relative2)) {
23751
24295
  return file;
23752
24296
  }
23753
- return relative;
24297
+ return relative2;
23754
24298
  }
23755
24299
  function extractReadFiles(root, output) {
23756
24300
  if (typeof output.output !== "string")
@@ -23779,10 +24323,14 @@ function createTaskSessionManagerHook(_ctx, options) {
23779
24323
  readContextMinLines: options.readContextMinLines,
23780
24324
  readContextMaxFiles: options.readContextMaxFiles
23781
24325
  });
24326
+ const backgroundJobBoard = options.backgroundJobBoard ?? new BackgroundJobBoard;
23782
24327
  const pendingCalls = new Map;
23783
24328
  const pendingCallOrder = [];
23784
24329
  const contextByTask = new Map;
23785
24330
  const pendingManagedTaskIds = new Set;
24331
+ const terminalJobsInjectedByParent = new Map;
24332
+ const processedInjectedCompletions = new Set;
24333
+ const processedInjectedCompletionOrder = [];
23786
24334
  let anonymousPendingCallId = 0;
23787
24335
  function addTaskContext(taskId, files) {
23788
24336
  if (files.length === 0)
@@ -23826,6 +24374,62 @@ function createTaskSessionManagerHook(_ctx, options) {
23826
24374
  }
23827
24375
  }
23828
24376
  }
24377
+ function updateBackgroundJobFromOutput(output) {
24378
+ if (typeof output !== "string")
24379
+ return;
24380
+ const status = parseTaskStatusOutput(output);
24381
+ if (!status)
24382
+ return;
24383
+ const updated = backgroundJobBoard.updateStatus({
24384
+ taskID: status.taskID,
24385
+ state: status.state,
24386
+ timedOut: status.timedOut,
24387
+ resultSummary: status.result
24388
+ });
24389
+ if (!updated)
24390
+ return;
24391
+ if (updated.terminalUnreconciled) {
24392
+ pendingManagedTaskIds.delete(updated.taskID);
24393
+ contextByTask.delete(updated.taskID);
24394
+ pruneContext();
24395
+ }
24396
+ return updated;
24397
+ }
24398
+ function updateFromInjectedCompletion(part, message, messageIndex, partIndex) {
24399
+ if (part.type !== "text" || typeof part.text !== "string") {
24400
+ return;
24401
+ }
24402
+ const isCompleted = BACKGROUND_COMPLETION_COMPLETED.test(part.text);
24403
+ const isFailed = BACKGROUND_COMPLETION_FAILED.test(part.text);
24404
+ if (part.synthetic !== true || !isCompleted && !isFailed) {
24405
+ return;
24406
+ }
24407
+ const status = parseTaskStatusOutput(part.text);
24408
+ if (!status)
24409
+ return;
24410
+ if (isCompleted && status.state !== "completed")
24411
+ return;
24412
+ if (isFailed && status.state !== "error")
24413
+ return;
24414
+ const occurrenceId = typeof part.id === "string" ? part.id : typeof message.info.id === "string" ? `${message.info.id}:${partIndex}` : `${message.info.sessionID ?? "unknown"}:${messageIndex}:${partIndex}`;
24415
+ if (processedInjectedCompletions.has(occurrenceId))
24416
+ return;
24417
+ const updated = updateBackgroundJobFromOutput(part.text);
24418
+ if (!updated)
24419
+ return;
24420
+ rememberProcessedInjectedCompletion(occurrenceId);
24421
+ return updated;
24422
+ }
24423
+ function rememberProcessedInjectedCompletion(signature) {
24424
+ processedInjectedCompletions.add(signature);
24425
+ processedInjectedCompletionOrder.push(signature);
24426
+ while (processedInjectedCompletionOrder.length > MAX_PROCESSED_INJECTED_COMPLETIONS) {
24427
+ const evicted = processedInjectedCompletionOrder.shift();
24428
+ if (!evicted)
24429
+ break;
24430
+ processedInjectedCompletions.delete(evicted);
24431
+ }
24432
+ }
23829
24433
  function isMissingRememberedSessionError(output) {
23830
24434
  const firstLine = output.split(/\r?\n/, 1)[0]?.trim().toLowerCase() ?? "";
23831
24435
  return firstLine.startsWith("[error]") && firstLine.includes("session") && (firstLine.includes("not found") || firstLine.includes("no session"));
@@ -23865,6 +24469,25 @@ function createTaskSessionManagerHook(_ctx, options) {
23865
24469
  return;
23866
24470
  return pendingCallOrder.find((callId) => pendingCalls.get(callId)?.parentSessionId === parentSessionId);
23867
24471
  }
24472
+ function rememberInjectedTerminalJobs(parentSessionID) {
24473
+ const taskIDs = backgroundJobBoard.list(parentSessionID).filter((job) => job.terminalUnreconciled).map((job) => job.taskID);
24474
+ if (taskIDs.length === 0)
24475
+ return;
24476
+ const existing = terminalJobsInjectedByParent.get(parentSessionID) ?? new Set;
24477
+ for (const taskID of taskIDs) {
24478
+ existing.add(taskID);
24479
+ }
24480
+ terminalJobsInjectedByParent.set(parentSessionID, existing);
24481
+ }
24482
+ function reconcileInjectedTerminalJobs(parentSessionID) {
24483
+ const taskIDs = terminalJobsInjectedByParent.get(parentSessionID);
24484
+ if (!taskIDs)
24485
+ return;
24486
+ for (const taskID of taskIDs) {
24487
+ backgroundJobBoard.markReconciled(taskID);
24488
+ }
24489
+ terminalJobsInjectedByParent.delete(parentSessionID);
24490
+ }
23868
24491
  return {
23869
24492
  "tool.execute.before": async (input, output) => {
23870
24493
  if (input.tool.toLowerCase() !== "task")
@@ -23914,11 +24537,31 @@ function createTaskSessionManagerHook(_ctx, options) {
23914
24537
  }
23915
24538
  return;
23916
24539
  }
24540
+ if (input.tool.toLowerCase() === "task_status") {
24541
+ if (!input.sessionID || !options.shouldManageSession(input.sessionID)) {
24542
+ return;
24543
+ }
24544
+ updateBackgroundJobFromOutput(output.output);
24545
+ return;
24546
+ }
23917
24547
  if (input.tool.toLowerCase() !== "task")
23918
24548
  return;
23919
24549
  const pending = takePendingCall(input.callID, input.sessionID);
23920
24550
  if (!pending || typeof output.output !== "string")
23921
24551
  return;
24552
+ const launch = parseTaskLaunchOutput(output.output);
24553
+ if (launch) {
24554
+ backgroundJobBoard.registerLaunch({
24555
+ taskID: launch.taskID,
24556
+ parentSessionID: pending.parentSessionId,
24557
+ agent: pending.agentType,
24558
+ description: pending.label,
24559
+ objective: pending.label
24560
+ });
24561
+ sessionManager.drop(pending.parentSessionId, pending.agentType, pending.resumedTaskId ?? launch.taskID);
24562
+ pendingManagedTaskIds.add(launch.taskID);
24563
+ return;
24564
+ }
23922
24565
  const taskId = parseTaskIdFromTaskOutput(output.output);
23923
24566
  if (!taskId) {
23924
24567
  if (pending.resumedTaskId && isMissingRememberedSessionError(output.output)) {
@@ -23941,6 +24584,19 @@ function createTaskSessionManagerHook(_ctx, options) {
23941
24584
  pruneContext();
23942
24585
  },
23943
24586
  "experimental.chat.messages.transform": async (_input, output) => {
24587
+ for (const [messageIndex, message] of output.messages.entries()) {
24588
+ if (message.info.role !== "user")
24589
+ continue;
24590
+ if (message.info.agent && message.info.agent !== "orchestrator") {
24591
+ continue;
24592
+ }
24593
+ if (!message.info.sessionID || !options.shouldManageSession(message.info.sessionID)) {
24594
+ continue;
24595
+ }
24596
+ for (const [partIndex, part] of message.parts.entries()) {
24597
+ updateFromInjectedCompletion(part, message, messageIndex, partIndex);
24598
+ }
24599
+ }
23944
24600
  for (let i = output.messages.length - 1;i >= 0; i -= 1) {
23945
24601
  const message = output.messages[i];
23946
24602
  if (message.info.role !== "user")
@@ -23950,8 +24606,11 @@ function createTaskSessionManagerHook(_ctx, options) {
23950
24606
  if (!message.info.sessionID || !options.shouldManageSession(message.info.sessionID)) {
23951
24607
  return;
23952
24608
  }
23953
- const reminder = sessionManager.formatForPrompt(message.info.sessionID);
23954
- if (!reminder)
24609
+ const reminders = [
24610
+ backgroundJobBoard.formatForPrompt(message.info.sessionID),
24611
+ sessionManager.formatForPrompt(message.info.sessionID)
24612
+ ].filter((item) => Boolean(item));
24613
+ if (reminders.length === 0)
23955
24614
  return;
23956
24615
  const textPart = message.parts.find((part) => part.type === "text" && typeof part.text === "string");
23957
24616
  if (!textPart)
@@ -23960,11 +24619,14 @@ function createTaskSessionManagerHook(_ctx, options) {
23960
24619
  return;
23961
24620
  if (textPart.text?.includes(RESUMABLE_SESSIONS_START))
23962
24621
  return;
24622
+ rememberInjectedTerminalJobs(message.info.sessionID);
23963
24623
  textPart.text = [
23964
24624
  textPart.text ?? "",
23965
24625
  "",
23966
24626
  RESUMABLE_SESSIONS_START,
23967
- reminder,
24627
+ reminders.join(`
24628
+
24629
+ `),
23968
24630
  RESUMABLE_SESSIONS_END
23969
24631
  ].join(`
23970
24632
  `);
@@ -23979,13 +24641,30 @@ function createTaskSessionManagerHook(_ctx, options) {
23979
24641
  }
23980
24642
  return;
23981
24643
  }
24644
+ if (input.event.type === "session.idle" || input.event.type === "session.status" && input.event.properties?.status?.type === "idle") {
24645
+ const sessionId2 = input.event.properties?.info?.id ?? input.event.properties?.sessionID;
24646
+ if (sessionId2 && options.shouldManageSession(sessionId2)) {
24647
+ reconcileInjectedTerminalJobs(sessionId2);
24648
+ }
24649
+ return;
24650
+ }
24651
+ if (input.event.type === "session.error") {
24652
+ const sessionId2 = input.event.properties?.info?.id ?? input.event.properties?.sessionID;
24653
+ if (sessionId2 && options.shouldManageSession(sessionId2)) {
24654
+ terminalJobsInjectedByParent.delete(sessionId2);
24655
+ }
24656
+ return;
24657
+ }
23982
24658
  if (input.event.type !== "session.deleted")
23983
24659
  return;
23984
24660
  const sessionId = input.event.properties?.info?.id ?? input.event.properties?.sessionID;
23985
24661
  if (!sessionId)
23986
24662
  return;
23987
24663
  sessionManager.dropTask(sessionId);
24664
+ backgroundJobBoard.drop(sessionId);
23988
24665
  sessionManager.clearParent(sessionId);
24666
+ backgroundJobBoard.clearParent(sessionId);
24667
+ terminalJobsInjectedByParent.delete(sessionId);
23989
24668
  contextByTask.delete(sessionId);
23990
24669
  pendingManagedTaskIds.delete(sessionId);
23991
24670
  pruneContext();
@@ -24138,7 +24817,7 @@ function createTodoHygiene(options) {
24138
24817
 
24139
24818
  // src/hooks/todo-continuation/index.ts
24140
24819
  var HOOK_NAME = "todo-continuation";
24141
- var COMMAND_NAME = "auto-continue";
24820
+ var COMMAND_NAME2 = "auto-continue";
24142
24821
  var TODO_STATE_TIMEOUT_MS = 500;
24143
24822
  var CONTINUATION_PROMPT = "[Auto-continue: enabled - there are incomplete todos remaining. Continue with the next uncompleted item. Press Esc to cancel. If you need user input or review for the next item, ask instead of proceeding.]";
24144
24823
  var TODO_HYGIENE_INSTRUCTION_OPEN = '<instruction name="todo_hygiene">';
@@ -24214,6 +24893,7 @@ function createTodoContinuationHook(ctx, config) {
24214
24893
  const cooldownMs = config?.cooldownMs ?? 3000;
24215
24894
  const autoEnable = config?.autoEnable ?? false;
24216
24895
  const autoEnableThreshold = config?.autoEnableThreshold ?? 4;
24896
+ const backgroundJobBoard = config?.backgroundJobBoard;
24217
24897
  const requestSignatureBySession = new Map;
24218
24898
  const state = {
24219
24899
  enabled: false,
@@ -24325,8 +25005,10 @@ function createTodoContinuationHook(ctx, config) {
24325
25005
  }
24326
25006
  if (requestSignatureBySession.get(lastUserMessage.sessionID) === lastUserMessage.signature) {
24327
25007
  const reminder = hygiene.getPendingReminder(lastUserMessage.sessionID);
24328
- if (reminder) {
24329
- appendTodoHygieneInstruction(lastUserMessage.message, reminder);
25008
+ const guardrail = backgroundGuardrail(lastUserMessage.sessionID);
25009
+ const combinedReminder = [reminder, guardrail].filter((item) => Boolean(item)).join(" ");
25010
+ if (combinedReminder) {
25011
+ appendTodoHygieneInstruction(lastUserMessage.message, combinedReminder);
24330
25012
  } else {
24331
25013
  stripTodoHygieneInstructionFromMessage(lastUserMessage.message);
24332
25014
  }
@@ -24364,6 +25046,28 @@ function createTodoContinuationHook(ctx, config) {
24364
25046
  function registerOrchestratorSession(sessionID) {
24365
25047
  state.orchestratorSessionIds.add(sessionID);
24366
25048
  }
25049
+ function backgroundGuardrail(sessionID) {
25050
+ if (!backgroundJobBoard)
25051
+ return;
25052
+ const hasRunning = backgroundJobBoard.hasRunning(sessionID);
25053
+ const hasTerminal = backgroundJobBoard.hasTerminalUnreconciled(sessionID);
25054
+ if (hasRunning && hasTerminal) {
25055
+ return "Background jobs are still unresolved: call task_status for running jobs and reconcile terminal Background Job Board results before dependent work or finalizing.";
25056
+ }
25057
+ if (hasTerminal) {
25058
+ return "Background jobs have terminal results: reconcile the Background Job Board results before finalizing.";
25059
+ }
25060
+ if (hasRunning) {
25061
+ return "Background jobs are still running: call task_status before dependent work or finalizing.";
25062
+ }
25063
+ return;
25064
+ }
25065
+ function continuationPrompt(sessionID) {
25066
+ const guardrail = backgroundGuardrail(sessionID);
25067
+ if (!guardrail)
25068
+ return CONTINUATION_PROMPT;
25069
+ return `${CONTINUATION_PROMPT} ${guardrail}`;
25070
+ }
24367
25071
  function handleChatMessage(input) {
24368
25072
  if (!input.agent) {
24369
25073
  return;
@@ -24555,7 +25259,9 @@ function createTodoContinuationHook(ctx, config) {
24555
25259
  await ctx.client.session.prompt({
24556
25260
  path: { id: sessionID },
24557
25261
  body: {
24558
- parts: [createInternalAgentTextPart(CONTINUATION_PROMPT)]
25262
+ parts: [
25263
+ createInternalAgentTextPart(continuationPrompt(sessionID))
25264
+ ]
24559
25265
  }
24560
25266
  });
24561
25267
  state.consecutiveContinuations++;
@@ -24629,7 +25335,7 @@ function createTodoContinuationHook(ctx, config) {
24629
25335
  }
24630
25336
  }
24631
25337
  async function handleCommandExecuteBefore(input, output) {
24632
- if (input.command !== COMMAND_NAME) {
25338
+ if (input.command !== COMMAND_NAME2) {
24633
25339
  return;
24634
25340
  }
24635
25341
  registerOrchestratorSession(input.sessionID);
@@ -24648,11 +25354,11 @@ function createTodoContinuationHook(ctx, config) {
24648
25354
  if (!newEnabled) {
24649
25355
  cancelPendingTimer(state);
24650
25356
  output.parts.push(createInternalAgentTextPart("[Auto-continue: disabled by user command.]"));
24651
- log(`[${HOOK_NAME}] Disabled via /${COMMAND_NAME} command`);
25357
+ log(`[${HOOK_NAME}] Disabled via /${COMMAND_NAME2} command`);
24652
25358
  return;
24653
25359
  }
24654
25360
  state.suppressUntil = 0;
24655
- log(`[${HOOK_NAME}] Enabled via /${COMMAND_NAME} command`, {
25361
+ log(`[${HOOK_NAME}] Enabled via /${COMMAND_NAME2} command`, {
24656
25362
  maxContinuations
24657
25363
  });
24658
25364
  let hasIncompleteTodos = false;
@@ -24666,7 +25372,7 @@ function createTodoContinuationHook(ctx, config) {
24666
25372
  });
24667
25373
  }
24668
25374
  if (hasIncompleteTodos) {
24669
- output.parts.push(createInternalAgentTextPart(`${CONTINUATION_PROMPT} [Auto-continue enabled: up to ${maxContinuations} continuations.]`));
25375
+ output.parts.push(createInternalAgentTextPart(`${continuationPrompt(input.sessionID)} [Auto-continue enabled: up to ${maxContinuations} continuations.]`));
24670
25376
  } else {
24671
25377
  output.parts.push(createInternalAgentTextPart(`[Auto-continue: enabled for up to ${maxContinuations} continuations. No incomplete todos right now.]`));
24672
25378
  }
@@ -24686,7 +25392,7 @@ import path13 from "node:path";
24686
25392
  // src/interview/dashboard.ts
24687
25393
  import crypto from "node:crypto";
24688
25394
  import * as fsSync2 from "node:fs";
24689
- import fs7 from "node:fs/promises";
25395
+ import fs8 from "node:fs/promises";
24690
25396
  import {
24691
25397
  createServer
24692
25398
  } from "node:http";
@@ -24694,175 +25400,6 @@ import os4 from "node:os";
24694
25400
  import path11 from "node:path";
24695
25401
  import { URL as URL2 } from "node:url";
24696
25402
 
24697
- // src/interview/document.ts
24698
- import * as fsSync from "node:fs";
24699
- import * as fs6 from "node:fs/promises";
24700
- import * as path10 from "node:path";
24701
- var DEFAULT_OUTPUT_FOLDER = "interview";
24702
- function normalizeOutputFolder(outputFolder) {
24703
- const normalized = outputFolder.trim().replace(/^\/+|\/+$/g, "");
24704
- return normalized || DEFAULT_OUTPUT_FOLDER;
24705
- }
24706
- function createInterviewDirectoryPath(directory, outputFolder) {
24707
- return path10.join(directory, normalizeOutputFolder(outputFolder));
24708
- }
24709
- function createInterviewFilePath(directory, outputFolder, idea) {
24710
- const fileName = `${slugify(idea) || "interview"}.md`;
24711
- return path10.join(createInterviewDirectoryPath(directory, outputFolder), fileName);
24712
- }
24713
- function relativeInterviewPath(directory, filePath) {
24714
- return path10.relative(directory, filePath) || path10.basename(filePath);
24715
- }
24716
- function resolveExistingInterviewPath(directory, outputFolder, value) {
24717
- const trimmed = value.trim();
24718
- if (!trimmed) {
24719
- return null;
24720
- }
24721
- const outputDir = createInterviewDirectoryPath(directory, outputFolder);
24722
- const candidates = new Set;
24723
- const resolvedRoot = path10.resolve(directory);
24724
- if (path10.isAbsolute(trimmed)) {
24725
- candidates.add(trimmed);
24726
- } else {
24727
- candidates.add(path10.resolve(directory, trimmed));
24728
- candidates.add(path10.join(outputDir, trimmed));
24729
- if (!trimmed.endsWith(".md")) {
24730
- candidates.add(path10.join(outputDir, `${trimmed}.md`));
24731
- }
24732
- }
24733
- for (const candidate of candidates) {
24734
- if (path10.extname(candidate) !== ".md") {
24735
- continue;
24736
- }
24737
- const resolved = path10.resolve(candidate);
24738
- if (!resolved.startsWith(resolvedRoot + path10.sep) && resolved !== resolvedRoot) {
24739
- continue;
24740
- }
24741
- if (fsSync.existsSync(candidate)) {
24742
- return candidate;
24743
- }
24744
- }
24745
- return null;
24746
- }
24747
- function slugify(value) {
24748
- return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
24749
- }
24750
- function extractHistorySection(document) {
24751
- const marker = `## Q&A history
24752
-
24753
- `;
24754
- const index = document.indexOf(marker);
24755
- return index >= 0 ? document.slice(index + marker.length).trim() : "";
24756
- }
24757
- function extractSummarySection(document) {
24758
- const marker = `## Current spec
24759
-
24760
- `;
24761
- const historyMarker = `
24762
-
24763
- ## Q&A history`;
24764
- const start = document.indexOf(marker);
24765
- if (start < 0) {
24766
- return "";
24767
- }
24768
- const summaryStart = start + marker.length;
24769
- const summaryEnd = document.indexOf(historyMarker, summaryStart);
24770
- return document.slice(summaryStart, summaryEnd >= 0 ? summaryEnd : undefined).trim();
24771
- }
24772
- function extractTitle(document) {
24773
- const match = document.match(/^#\s+(.+)$/m);
24774
- return match?.[1]?.trim() ?? "";
24775
- }
24776
- function buildInterviewDocument(idea, summary, history, meta) {
24777
- const normalizedSummary = summary.trim() || "Waiting for interview answers.";
24778
- const normalizedHistory = history.trim() || "No answers yet.";
24779
- const frontmatter = meta?.sessionID ? [
24780
- "---",
24781
- `sessionID: ${meta.sessionID}`,
24782
- `baseMessageCount: ${meta.baseMessageCount ?? 0}`,
24783
- `updatedAt: ${new Date().toISOString()}`,
24784
- "---",
24785
- ""
24786
- ].join(`
24787
- `) : "";
24788
- return [
24789
- frontmatter,
24790
- `# ${idea}`,
24791
- "",
24792
- "## Current spec",
24793
- "",
24794
- normalizedSummary,
24795
- "",
24796
- "## Q&A history",
24797
- "",
24798
- normalizedHistory,
24799
- ""
24800
- ].join(`
24801
- `);
24802
- }
24803
- function parseFrontmatter(content) {
24804
- const match = content.match(/^---\n([\s\S]*?)\n---\n/);
24805
- if (!match)
24806
- return null;
24807
- const result = {};
24808
- for (const line of match[1].split(`
24809
- `)) {
24810
- const colonIdx = line.indexOf(":");
24811
- if (colonIdx > 0) {
24812
- result[line.slice(0, colonIdx).trim()] = line.slice(colonIdx + 1).trim();
24813
- }
24814
- }
24815
- return result;
24816
- }
24817
- async function ensureInterviewFile(record) {
24818
- await fs6.mkdir(path10.dirname(record.markdownPath), { recursive: true });
24819
- try {
24820
- await fs6.access(record.markdownPath);
24821
- } catch {
24822
- await fs6.writeFile(record.markdownPath, buildInterviewDocument(record.idea, "", "", {
24823
- sessionID: record.sessionID,
24824
- baseMessageCount: record.baseMessageCount
24825
- }), "utf8");
24826
- }
24827
- }
24828
- async function readInterviewDocument(record) {
24829
- try {
24830
- return await fs6.readFile(record.markdownPath, "utf8");
24831
- } catch {}
24832
- await ensureInterviewFile(record);
24833
- return fs6.readFile(record.markdownPath, "utf8");
24834
- }
24835
- async function rewriteInterviewDocument(record, summary) {
24836
- const existing = await readInterviewDocument(record);
24837
- const history = extractHistorySection(existing);
24838
- const next = buildInterviewDocument(record.idea, summary, history, {
24839
- sessionID: record.sessionID,
24840
- baseMessageCount: record.baseMessageCount
24841
- });
24842
- await fs6.writeFile(record.markdownPath, next, "utf8");
24843
- return next;
24844
- }
24845
- async function appendInterviewAnswers(record, questions, answers) {
24846
- const existing = await readInterviewDocument(record);
24847
- const summary = extractSummarySection(existing);
24848
- const history = extractHistorySection(existing);
24849
- const questionMap = new Map(questions.map((question) => [question.id, question]));
24850
- const appended = answers.map((answer) => {
24851
- const question = questionMap.get(answer.questionId);
24852
- return question ? `Q: ${question.question}
24853
- A: ${answer.answer.trim()}` : null;
24854
- }).filter((value) => value !== null).join(`
24855
-
24856
- `);
24857
- const nextHistory = [history === "No answers yet." ? "" : history, appended].filter(Boolean).join(`
24858
-
24859
- `);
24860
- await fs6.writeFile(record.markdownPath, buildInterviewDocument(record.idea, summary, nextHistory, {
24861
- sessionID: record.sessionID,
24862
- baseMessageCount: record.baseMessageCount
24863
- }), "utf8");
24864
- }
24865
-
24866
25403
  // src/interview/helpers.ts
24867
25404
  function sendJson(response, status, value) {
24868
25405
  response.statusCode = status;
@@ -26507,7 +27044,7 @@ function removeAuthFile(port) {
26507
27044
  }
26508
27045
  async function readDashboardAuthFile(port) {
26509
27046
  try {
26510
- const content = await fs7.readFile(getAuthFilePath(port), "utf8");
27047
+ const content = await fs8.readFile(getAuthFilePath(port), "utf8");
26511
27048
  const data = JSON.parse(content);
26512
27049
  try {
26513
27050
  process.kill(data.pid, 0);
@@ -26630,7 +27167,7 @@ function createDashboardServer(config) {
26630
27167
  const interviewDir = path11.join(dir, config.outputFolder);
26631
27168
  let entries;
26632
27169
  try {
26633
- entries = await fs7.readdir(interviewDir);
27170
+ entries = await fs8.readdir(interviewDir);
26634
27171
  } catch {
26635
27172
  continue;
26636
27173
  }
@@ -26639,7 +27176,7 @@ function createDashboardServer(config) {
26639
27176
  continue;
26640
27177
  let content;
26641
27178
  try {
26642
- content = await fs7.readFile(path11.join(interviewDir, entry), "utf8");
27179
+ content = await fs8.readFile(path11.join(interviewDir, entry), "utf8");
26643
27180
  } catch {
26644
27181
  continue;
26645
27182
  }
@@ -26668,7 +27205,7 @@ function createDashboardServer(config) {
26668
27205
  const interviewDir = path11.join(dir, config.outputFolder);
26669
27206
  let entries;
26670
27207
  try {
26671
- entries = await fs7.readdir(interviewDir);
27208
+ entries = await fs8.readdir(interviewDir);
26672
27209
  } catch {
26673
27210
  continue;
26674
27211
  }
@@ -26677,7 +27214,7 @@ function createDashboardServer(config) {
26677
27214
  continue;
26678
27215
  let content;
26679
27216
  try {
26680
- content = await fs7.readFile(path11.join(interviewDir, entry), "utf8");
27217
+ content = await fs8.readFile(path11.join(interviewDir, entry), "utf8");
26681
27218
  } catch {
26682
27219
  continue;
26683
27220
  }
@@ -26961,7 +27498,7 @@ function createDashboardServer(config) {
26961
27498
  let markdownPath = entry.filePath;
26962
27499
  if (entry.filePath) {
26963
27500
  try {
26964
- document = await fs7.readFile(entry.filePath, "utf8");
27501
+ document = await fs8.readFile(entry.filePath, "utf8");
26965
27502
  } catch {}
26966
27503
  } else {
26967
27504
  const dirs = getKnownDirectories();
@@ -26969,7 +27506,7 @@ function createDashboardServer(config) {
26969
27506
  const slug = extractResumeSlug(interviewId);
26970
27507
  const candidate = path11.join(dir, config.outputFolder, `${slug}.md`);
26971
27508
  try {
26972
- document = await fs7.readFile(candidate, "utf8");
27509
+ document = await fs8.readFile(candidate, "utf8");
26973
27510
  markdownPath = candidate;
26974
27511
  entry.filePath = candidate;
26975
27512
  break;
@@ -27494,7 +28031,7 @@ function createInterviewServer(deps) {
27494
28031
 
27495
28032
  // src/interview/service.ts
27496
28033
  import { spawn as spawn2 } from "node:child_process";
27497
- import * as fs8 from "node:fs/promises";
28034
+ import * as fs9 from "node:fs/promises";
27498
28035
  import * as path12 from "node:path";
27499
28036
 
27500
28037
  // src/interview/types.ts
@@ -27667,7 +28204,7 @@ function buildAnswerPrompt(answers, questions, maxQuestions) {
27667
28204
  }
27668
28205
 
27669
28206
  // src/interview/service.ts
27670
- var COMMAND_NAME2 = "interview";
28207
+ var COMMAND_NAME3 = "interview";
27671
28208
  var DEFAULT_MAX_QUESTIONS = 2;
27672
28209
  function isTruthyEnvFlag(value) {
27673
28210
  if (!value) {
@@ -27769,11 +28306,11 @@ function createInterviewService(ctx, config, deps) {
27769
28306
  const dir = path12.dirname(interview.markdownPath);
27770
28307
  const newPath = path12.join(dir, `${newSlug}.md`);
27771
28308
  try {
27772
- await fs8.access(newPath);
28309
+ await fs9.access(newPath);
27773
28310
  return;
27774
28311
  } catch {}
27775
28312
  try {
27776
- await fs8.rename(interview.markdownPath, newPath);
28313
+ await fs9.rename(interview.markdownPath, newPath);
27777
28314
  interview.markdownPath = newPath;
27778
28315
  log("[interview] renamed file with assistant title:", {
27779
28316
  from: currentFileName,
@@ -27839,7 +28376,7 @@ function createInterviewService(ctx, config, deps) {
27839
28376
  active.status = "abandoned";
27840
28377
  }
27841
28378
  }
27842
- const document = await fs8.readFile(markdownPath, "utf8");
28379
+ const document = await fs9.readFile(markdownPath, "utf8");
27843
28380
  const messages = await loadMessages(sessionID);
27844
28381
  const title = extractTitle(document);
27845
28382
  const record = {
@@ -27914,11 +28451,11 @@ function createInterviewService(ctx, config, deps) {
27914
28451
  }
27915
28452
  function registerCommand(opencodeConfig) {
27916
28453
  const configCommand = opencodeConfig.command;
27917
- if (!configCommand?.[COMMAND_NAME2]) {
28454
+ if (!configCommand?.[COMMAND_NAME3]) {
27918
28455
  if (!opencodeConfig.command) {
27919
28456
  opencodeConfig.command = {};
27920
28457
  }
27921
- opencodeConfig.command[COMMAND_NAME2] = {
28458
+ opencodeConfig.command[COMMAND_NAME3] = {
27922
28459
  template: "Start an interview and write a live markdown spec",
27923
28460
  description: "Open a localhost interview UI linked to the current OpenCode session"
27924
28461
  };
@@ -27992,7 +28529,7 @@ function createInterviewService(ctx, config, deps) {
27992
28529
  }
27993
28530
  }
27994
28531
  async function handleCommandExecuteBefore(input, output) {
27995
- if (input.command !== COMMAND_NAME2) {
28532
+ if (input.command !== COMMAND_NAME3) {
27996
28533
  return;
27997
28534
  }
27998
28535
  const idea = input.arguments.trim();
@@ -28011,7 +28548,7 @@ function createInterviewService(ctx, config, deps) {
28011
28548
  const resumePath = resolveExistingInterviewPath(ctx.directory, outputFolder, idea);
28012
28549
  if (resumePath) {
28013
28550
  const interview2 = await resumeInterview(input.sessionID, resumePath);
28014
- const document = await fs8.readFile(interview2.markdownPath, "utf8");
28551
+ const document = await fs9.readFile(interview2.markdownPath, "utf8");
28015
28552
  await notifyInterviewUrl(input.sessionID, interview2);
28016
28553
  output.parts.push(createInternalAgentTextPart(buildResumePrompt(document, maxQuestions)));
28017
28554
  return;
@@ -28075,7 +28612,7 @@ function createInterviewService(ctx, config, deps) {
28075
28612
  const activePaths = new Set([...interviewsById.values()].filter((i) => i.status === "active").map((i) => path12.resolve(i.markdownPath)));
28076
28613
  let entries;
28077
28614
  try {
28078
- entries = await fs8.readdir(outputDir);
28615
+ entries = await fs9.readdir(outputDir);
28079
28616
  } catch {
28080
28617
  return [];
28081
28618
  }
@@ -28088,7 +28625,7 @@ function createInterviewService(ctx, config, deps) {
28088
28625
  continue;
28089
28626
  let content;
28090
28627
  try {
28091
- content = await fs8.readFile(fullPath, "utf8");
28628
+ content = await fs9.readFile(fullPath, "utf8");
28092
28629
  } catch {
28093
28630
  continue;
28094
28631
  }
@@ -29161,29 +29698,46 @@ function startAvailabilityCheck(config) {
29161
29698
  // src/multiplexer/session-manager.ts
29162
29699
  var SESSION_TIMEOUT_MS = 10 * 60 * 1000;
29163
29700
  var SESSION_MISSING_GRACE_MS = POLL_INTERVAL_BACKGROUND_MS * 3;
29164
-
29701
+ var SHARED_STATE_KEY = Symbol.for("oh-my-opencode-slim.multiplexer-session-manager.state");
29702
+ function getSharedState() {
29703
+ const globalWithState = globalThis;
29704
+ globalWithState[SHARED_STATE_KEY] ??= {
29705
+ sessions: new Map,
29706
+ knownSessions: new Map,
29707
+ spawningSessions: new Set,
29708
+ closingSessions: new Map
29709
+ };
29710
+ return globalWithState[SHARED_STATE_KEY];
29711
+ }
29165
29712
  class MultiplexerSessionManager {
29166
- client;
29713
+ instanceId = Math.random().toString(36).slice(2, 8);
29167
29714
  serverUrl;
29168
29715
  directory;
29169
29716
  multiplexer = null;
29170
- sessions = new Map;
29171
- knownSessions = new Map;
29172
- spawningSessions = new Set;
29173
- closingSessions = new Map;
29717
+ sessions;
29718
+ knownSessions;
29719
+ spawningSessions;
29720
+ closingSessions;
29174
29721
  pollInterval;
29175
29722
  enabled = false;
29176
29723
  constructor(ctx, config) {
29177
- this.client = ctx.client;
29724
+ const sharedState = getSharedState();
29725
+ this.sessions = sharedState.sessions;
29726
+ this.knownSessions = sharedState.knownSessions;
29727
+ this.spawningSessions = sharedState.spawningSessions;
29728
+ this.closingSessions = sharedState.closingSessions;
29178
29729
  this.directory = ctx.directory;
29179
29730
  const defaultPort = process.env.OPENCODE_PORT ?? "4096";
29180
29731
  this.serverUrl = ctx.serverUrl?.toString() ?? `http://localhost:${defaultPort}`;
29181
29732
  this.multiplexer = getMultiplexer(config);
29182
29733
  this.enabled = config.type !== "none" && this.multiplexer !== null && this.multiplexer.isInsideSession();
29183
29734
  log("[multiplexer-session-manager] initialized", {
29735
+ instanceId: this.instanceId,
29184
29736
  enabled: this.enabled,
29185
29737
  type: config.type,
29186
- serverUrl: this.serverUrl
29738
+ serverUrl: this.serverUrl,
29739
+ trackedSessions: this.sessions.size,
29740
+ knownSessions: this.knownSessions.size
29187
29741
  });
29188
29742
  }
29189
29743
  async onSessionCreated(event) {
@@ -29201,6 +29755,7 @@ class MultiplexerSessionManager {
29201
29755
  const directory = info.directory ?? this.directory;
29202
29756
  if (this.isTrackedOrSpawning(sessionId)) {
29203
29757
  log("[multiplexer-session-manager] session already tracked or spawning", {
29758
+ instanceId: this.instanceId,
29204
29759
  sessionId
29205
29760
  });
29206
29761
  return;
@@ -29220,6 +29775,7 @@ class MultiplexerSessionManager {
29220
29775
  const serverRunning = await isServerRunning(this.serverUrl);
29221
29776
  if (!serverRunning) {
29222
29777
  log("[multiplexer-session-manager] server not running, skipping", {
29778
+ instanceId: this.instanceId,
29223
29779
  serverUrl: this.serverUrl
29224
29780
  });
29225
29781
  return;
@@ -29230,10 +29786,12 @@ class MultiplexerSessionManager {
29230
29786
  log("[multiplexer-session-manager] child session created, spawning pane", {
29231
29787
  sessionId,
29232
29788
  parentId,
29233
- title
29789
+ title,
29790
+ instanceId: this.instanceId
29234
29791
  });
29235
29792
  const paneResult = await this.multiplexer.spawnPane(sessionId, title, this.serverUrl, directory).catch((err) => {
29236
29793
  log("[multiplexer-session-manager] failed to spawn pane", {
29794
+ instanceId: this.instanceId,
29237
29795
  error: String(err)
29238
29796
  });
29239
29797
  return { success: false, paneId: undefined };
@@ -29244,6 +29802,7 @@ class MultiplexerSessionManager {
29244
29802
  await this.multiplexer.closePane(paneResult.paneId).catch((err) => log("[multiplexer-session-manager] closing stale spawned pane failed", {
29245
29803
  sessionId,
29246
29804
  paneId: paneResult.paneId,
29805
+ instanceId: this.instanceId,
29247
29806
  error: String(err)
29248
29807
  }));
29249
29808
  return;
@@ -29259,6 +29818,7 @@ class MultiplexerSessionManager {
29259
29818
  lastSeenAt: now
29260
29819
  });
29261
29820
  log("[multiplexer-session-manager] pane spawned", {
29821
+ instanceId: this.instanceId,
29262
29822
  sessionId,
29263
29823
  paneId: paneResult.paneId
29264
29824
  });
@@ -29270,6 +29830,19 @@ class MultiplexerSessionManager {
29270
29830
  async onSessionStatus(event) {
29271
29831
  if (!this.enabled)
29272
29832
  return;
29833
+ if (event.type === "session.idle") {
29834
+ const sessionId2 = event.properties?.sessionID;
29835
+ if (!sessionId2)
29836
+ return;
29837
+ log("[multiplexer-session-manager] session idle event received", {
29838
+ instanceId: this.instanceId,
29839
+ sessionId: sessionId2,
29840
+ tracked: this.sessions.has(sessionId2),
29841
+ known: this.knownSessions.has(sessionId2)
29842
+ });
29843
+ await this.closeSession(sessionId2, "idle");
29844
+ return;
29845
+ }
29273
29846
  if (event.type !== "session.status")
29274
29847
  return;
29275
29848
  const sessionId = event.properties?.sessionID;
@@ -29280,6 +29853,12 @@ class MultiplexerSessionManager {
29280
29853
  return;
29281
29854
  }
29282
29855
  if (event.properties?.status?.type === "busy") {
29856
+ log("[multiplexer-session-manager] session busy event received", {
29857
+ instanceId: this.instanceId,
29858
+ sessionId,
29859
+ tracked: this.sessions.has(sessionId),
29860
+ known: this.knownSessions.has(sessionId)
29861
+ });
29283
29862
  await this.respawnIfKnown(sessionId);
29284
29863
  }
29285
29864
  }
@@ -29292,6 +29871,7 @@ class MultiplexerSessionManager {
29292
29871
  if (!sessionId)
29293
29872
  return;
29294
29873
  log("[multiplexer-session-manager] session deleted, closing pane", {
29874
+ instanceId: this.instanceId,
29295
29875
  sessionId
29296
29876
  });
29297
29877
  await this.closeSession(sessionId, "deleted");
@@ -29300,13 +29880,17 @@ class MultiplexerSessionManager {
29300
29880
  if (this.pollInterval)
29301
29881
  return;
29302
29882
  this.pollInterval = setInterval(() => this.pollSessions(), POLL_INTERVAL_BACKGROUND_MS);
29303
- log("[multiplexer-session-manager] polling started");
29883
+ log("[multiplexer-session-manager] polling started", {
29884
+ instanceId: this.instanceId
29885
+ });
29304
29886
  }
29305
29887
  stopPolling() {
29306
29888
  if (this.pollInterval) {
29307
29889
  clearInterval(this.pollInterval);
29308
29890
  this.pollInterval = undefined;
29309
- log("[multiplexer-session-manager] polling stopped");
29891
+ log("[multiplexer-session-manager] polling stopped", {
29892
+ instanceId: this.instanceId
29893
+ });
29310
29894
  }
29311
29895
  }
29312
29896
  async pollSessions() {
@@ -29315,8 +29899,7 @@ class MultiplexerSessionManager {
29315
29899
  return;
29316
29900
  }
29317
29901
  try {
29318
- const statusResult = await this.client.session.status();
29319
- const allStatuses = statusResult.data ?? {};
29902
+ const allStatuses = await this.fetchSessionStatuses();
29320
29903
  const now = Date.now();
29321
29904
  const sessionsToClose = [];
29322
29905
  for (const [sessionId, tracked] of this.sessions.entries()) {
@@ -29344,6 +29927,14 @@ class MultiplexerSessionManager {
29344
29927
  log("[multiplexer-session-manager] poll error", { error: String(err) });
29345
29928
  }
29346
29929
  }
29930
+ async fetchSessionStatuses() {
29931
+ const url = new URL("/session/status", this.serverUrl);
29932
+ const response = await fetch(url, { signal: AbortSignal.timeout(2000) });
29933
+ if (!response.ok) {
29934
+ throw new Error(`session status request failed: ${response.status} ${response.statusText}`);
29935
+ }
29936
+ return await response.json();
29937
+ }
29347
29938
  async closeSession(sessionId, reason) {
29348
29939
  if (reason === "deleted") {
29349
29940
  this.knownSessions.delete(sessionId);
@@ -29352,10 +29943,19 @@ class MultiplexerSessionManager {
29352
29943
  if (existingClose)
29353
29944
  return existingClose;
29354
29945
  const tracked = this.sessions.get(sessionId);
29355
- if (!tracked || !this.multiplexer)
29946
+ if (!tracked || !this.multiplexer) {
29947
+ log("[multiplexer-session-manager] close skipped; session not tracked", {
29948
+ instanceId: this.instanceId,
29949
+ sessionId,
29950
+ reason,
29951
+ tracked: !!tracked,
29952
+ hasMultiplexer: !!this.multiplexer
29953
+ });
29356
29954
  return;
29955
+ }
29357
29956
  this.sessions.delete(sessionId);
29358
29957
  log("[multiplexer-session-manager] closing session pane", {
29958
+ instanceId: this.instanceId,
29359
29959
  sessionId,
29360
29960
  paneId: tracked.paneId,
29361
29961
  reason
@@ -29363,6 +29963,7 @@ class MultiplexerSessionManager {
29363
29963
  const closePromise = this.multiplexer.closePane(tracked.paneId).then(() => {
29364
29964
  return;
29365
29965
  }).catch((err) => log("[multiplexer-session-manager] failed to close session pane", {
29966
+ instanceId: this.instanceId,
29366
29967
  sessionId,
29367
29968
  paneId: tracked.paneId,
29368
29969
  reason,
@@ -29391,6 +29992,7 @@ class MultiplexerSessionManager {
29391
29992
  const serverRunning = await isServerRunning(this.serverUrl);
29392
29993
  if (!serverRunning) {
29393
29994
  log("[multiplexer-session-manager] server not running, skipping busy respawn", {
29995
+ instanceId: this.instanceId,
29394
29996
  serverUrl: this.serverUrl,
29395
29997
  sessionId
29396
29998
  });
@@ -29400,12 +30002,14 @@ class MultiplexerSessionManager {
29400
30002
  return;
29401
30003
  }
29402
30004
  log("[multiplexer-session-manager] child session busy again, respawning pane", {
30005
+ instanceId: this.instanceId,
29403
30006
  sessionId,
29404
30007
  parentId: known.parentId,
29405
30008
  title: known.title
29406
30009
  });
29407
30010
  const paneResult = await this.multiplexer.spawnPane(sessionId, known.title, this.serverUrl, known.directory).catch((err) => {
29408
30011
  log("[multiplexer-session-manager] failed to respawn pane", {
30012
+ instanceId: this.instanceId,
29409
30013
  error: String(err)
29410
30014
  });
29411
30015
  return { success: false, paneId: undefined };
@@ -29414,6 +30018,7 @@ class MultiplexerSessionManager {
29414
30018
  return;
29415
30019
  if (!this.knownSessions.has(sessionId) || this.closingSessions.has(sessionId)) {
29416
30020
  await this.multiplexer.closePane(paneResult.paneId).catch((err) => log("[multiplexer-session-manager] closing stale respawned pane failed", {
30021
+ instanceId: this.instanceId,
29417
30022
  sessionId,
29418
30023
  paneId: paneResult.paneId,
29419
30024
  error: String(err)
@@ -29431,6 +30036,7 @@ class MultiplexerSessionManager {
29431
30036
  lastSeenAt: now
29432
30037
  });
29433
30038
  log("[multiplexer-session-manager] pane respawned on busy", {
30039
+ instanceId: this.instanceId,
29434
30040
  sessionId,
29435
30041
  paneId: paneResult.paneId
29436
30042
  });
@@ -30109,7 +30715,7 @@ Returns the councillor responses with a summary footer.`,
30109
30715
  return { council_session };
30110
30716
  }
30111
30717
  // src/tui-state.ts
30112
- import * as fs9 from "node:fs";
30718
+ import * as fs10 from "node:fs";
30113
30719
  import * as os5 from "node:os";
30114
30720
  import * as path14 from "node:path";
30115
30721
  var STATE_DIR = "oh-my-opencode-slim";
@@ -30139,14 +30745,14 @@ function parseSnapshot(value) {
30139
30745
  }
30140
30746
  function readTuiSnapshot() {
30141
30747
  try {
30142
- return parseSnapshot(fs9.readFileSync(getTuiStatePath(), "utf8"));
30748
+ return parseSnapshot(fs10.readFileSync(getTuiStatePath(), "utf8"));
30143
30749
  } catch {
30144
30750
  return emptySnapshot();
30145
30751
  }
30146
30752
  }
30147
30753
  async function readTuiSnapshotAsync() {
30148
30754
  try {
30149
- return parseSnapshot(await fs9.promises.readFile(getTuiStatePath(), "utf8"));
30755
+ return parseSnapshot(await fs10.promises.readFile(getTuiStatePath(), "utf8"));
30150
30756
  } catch {
30151
30757
  return emptySnapshot();
30152
30758
  }
@@ -30154,8 +30760,8 @@ async function readTuiSnapshotAsync() {
30154
30760
  function writeTuiSnapshot(snapshot) {
30155
30761
  try {
30156
30762
  const filePath = getTuiStatePath();
30157
- fs9.mkdirSync(path14.dirname(filePath), { recursive: true });
30158
- fs9.writeFileSync(filePath, `${JSON.stringify(snapshot)}
30763
+ fs10.mkdirSync(path14.dirname(filePath), { recursive: true });
30764
+ fs10.writeFileSync(filePath, `${JSON.stringify(snapshot)}
30159
30765
  `);
30160
30766
  } catch {}
30161
30767
  }
@@ -30177,11 +30783,11 @@ function recordTuiAgentModel(input) {
30177
30783
  }
30178
30784
 
30179
30785
  // src/tools/preset-manager.ts
30180
- var COMMAND_NAME3 = "preset";
30786
+ var COMMAND_NAME4 = "preset";
30181
30787
  function createPresetManager(ctx, config) {
30182
30788
  let activePreset = getActiveRuntimePreset() ?? config.preset ?? null;
30183
30789
  async function handleCommandExecuteBefore(input, output) {
30184
- if (input.command !== COMMAND_NAME3) {
30790
+ if (input.command !== COMMAND_NAME4) {
30185
30791
  return;
30186
30792
  }
30187
30793
  output.parts.length = 0;
@@ -30200,11 +30806,11 @@ function createPresetManager(ctx, config) {
30200
30806
  }
30201
30807
  function registerCommand(opencodeConfig) {
30202
30808
  const configCommand = opencodeConfig.command;
30203
- if (!configCommand?.[COMMAND_NAME3]) {
30809
+ if (!configCommand?.[COMMAND_NAME4]) {
30204
30810
  if (!opencodeConfig.command) {
30205
30811
  opencodeConfig.command = {};
30206
30812
  }
30207
- opencodeConfig.command[COMMAND_NAME3] = {
30813
+ opencodeConfig.command[COMMAND_NAME4] = {
30208
30814
  template: "List available presets and switch between them",
30209
30815
  description: "Switch agent presets at runtime (e.g., /preset cheap, /preset powerful)"
30210
30816
  };
@@ -30416,21 +31022,21 @@ async function saveBinary(binaryDir, data, contentType, filename) {
30416
31022
  throw new Error("Unable to allocate unique filename for binary content");
30417
31023
  }
30418
31024
 
30419
- // node_modules/lru-cache/dist/esm/node/index.min.js
30420
- import { tracingChannel as j, channel as I } from "node:diagnostics_channel";
30421
- var S = I("lru-cache:metrics");
30422
- var W = j("lru-cache");
31025
+ // node_modules/.pnpm/lru-cache@11.3.6/node_modules/lru-cache/dist/esm/node/index.min.js
31026
+ import { tracingChannel as I, channel as G } from "node:diagnostics_channel";
31027
+ var S = G("lru-cache:metrics");
31028
+ var W = I("lru-cache");
31029
+ var C = typeof performance == "object" && performance && typeof performance.now == "function" ? performance : Date;
30423
31030
  var D = () => S.hasSubscribers || W.hasSubscribers;
30424
- var G = typeof performance == "object" && performance && typeof performance.now == "function" ? performance : Date;
30425
- var M = new Set;
30426
- var C = typeof process == "object" && process ? process : {};
31031
+ var U = new Set;
31032
+ var L = typeof process == "object" && process ? process : {};
30427
31033
  var P = (u, e, t, i) => {
30428
- typeof C.emitWarning == "function" ? C.emitWarning(u, e, t, i) : console.error(`[${t}] ${e}: ${u}`);
31034
+ typeof L.emitWarning == "function" ? L.emitWarning(u, e, t, i) : console.error(`[${t}] ${e}: ${u}`);
30429
31035
  };
30430
- var H = (u) => !M.has(u);
30431
- var $ = Symbol("type");
31036
+ var H = (u) => !U.has(u);
31037
+ var X = Symbol("type");
30432
31038
  var F = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u);
30433
- var U = (u) => F(u) ? u <= Math.pow(2, 8) ? Uint8Array : u <= Math.pow(2, 16) ? Uint16Array : u <= Math.pow(2, 32) ? Uint32Array : u <= Number.MAX_SAFE_INTEGER ? O : null : null;
31039
+ var j = (u) => F(u) ? u <= Math.pow(2, 8) ? Uint8Array : u <= Math.pow(2, 16) ? Uint16Array : u <= Math.pow(2, 32) ? Uint32Array : u <= Number.MAX_SAFE_INTEGER ? O : null : null;
30434
31040
  var O = class extends Array {
30435
31041
  constructor(e) {
30436
31042
  super(e), this.fill(0);
@@ -30441,7 +31047,7 @@ var R = class u {
30441
31047
  length;
30442
31048
  static #o = false;
30443
31049
  static create(e) {
30444
- let t = U(e);
31050
+ let t = j(e);
30445
31051
  if (!t)
30446
31052
  return [];
30447
31053
  u.#o = true;
@@ -30460,11 +31066,11 @@ var R = class u {
30460
31066
  return this.heap[--this.length];
30461
31067
  }
30462
31068
  };
30463
- var L = class u2 {
31069
+ var M = class u2 {
30464
31070
  #o;
30465
31071
  #u;
30466
31072
  #w;
30467
- #D;
31073
+ #x;
30468
31074
  #S;
30469
31075
  #M;
30470
31076
  #U;
@@ -30535,7 +31141,7 @@ var L = class u2 {
30535
31141
  return this.#w;
30536
31142
  }
30537
31143
  get onInsert() {
30538
- return this.#D;
31144
+ return this.#x;
30539
31145
  }
30540
31146
  get disposeAfter() {
30541
31147
  return this.#S;
@@ -30544,9 +31150,9 @@ var L = class u2 {
30544
31150
  let { max: t = 0, ttl: i, ttlResolution: s = 1, ttlAutopurge: n, updateAgeOnGet: o, updateAgeOnHas: r, allowStale: h, dispose: l, onInsert: c, disposeAfter: f, noDisposeOnSet: g, noUpdateTTL: p, maxSize: T = 0, maxEntrySize: w = 0, sizeCalculation: y, fetchMethod: a, memoMethod: m, noDeleteOnFetchRejection: _, noDeleteOnStaleGet: b, allowStaleOnFetchRejection: d, allowStaleOnFetchAbort: A, ignoreFetchAbort: z5, perf: x } = e;
30545
31151
  if (x !== undefined && typeof x?.now != "function")
30546
31152
  throw new TypeError("perf option must have a now() method if specified");
30547
- if (this.#m = x ?? G, t !== 0 && !F(t))
31153
+ if (this.#m = x ?? C, t !== 0 && !F(t))
30548
31154
  throw new TypeError("max option must be a nonnegative integer");
30549
- let v = t ? U(t) : Array;
31155
+ let v = t ? j(t) : Array;
30550
31156
  if (!v)
30551
31157
  throw new Error("invalid max value: " + t);
30552
31158
  if (this.#o = t, this.#u = T, this.maxEntrySize = w || this.#u, this.sizeCalculation = y, this.sizeCalculation) {
@@ -30559,7 +31165,7 @@ var L = class u2 {
30559
31165
  throw new TypeError("memoMethod must be a function if defined");
30560
31166
  if (this.#U = m, a !== undefined && typeof a != "function")
30561
31167
  throw new TypeError("fetchMethod must be a function if specified");
30562
- if (this.#M = a, this.#W = !!a, this.#s = new Map, this.#i = Array.from({ length: t }).fill(undefined), this.#t = Array.from({ length: t }).fill(undefined), this.#a = new v(t), this.#c = new v(t), this.#l = 0, this.#h = 0, this.#y = R.create(t), this.#n = 0, this.#b = 0, typeof l == "function" && (this.#w = l), typeof c == "function" && (this.#D = c), typeof f == "function" ? (this.#S = f, this.#r = []) : (this.#S = undefined, this.#r = undefined), this.#T = !!this.#w, this.#j = !!this.#D, this.#f = !!this.#S, this.noDisposeOnSet = !!g, this.noUpdateTTL = !!p, this.noDeleteOnFetchRejection = !!_, this.allowStaleOnFetchRejection = !!d, this.allowStaleOnFetchAbort = !!A, this.ignoreFetchAbort = !!z5, this.maxEntrySize !== 0) {
31168
+ if (this.#M = a, this.#W = !!a, this.#s = new Map, this.#i = Array.from({ length: t }).fill(undefined), this.#t = Array.from({ length: t }).fill(undefined), this.#a = new v(t), this.#c = new v(t), this.#l = 0, this.#h = 0, this.#y = R.create(t), this.#n = 0, this.#b = 0, typeof l == "function" && (this.#w = l), typeof c == "function" && (this.#x = c), typeof f == "function" ? (this.#S = f, this.#r = []) : (this.#S = undefined, this.#r = undefined), this.#T = !!this.#w, this.#j = !!this.#x, this.#f = !!this.#S, this.noDisposeOnSet = !!g, this.noUpdateTTL = !!p, this.noDeleteOnFetchRejection = !!_, this.allowStaleOnFetchRejection = !!d, this.allowStaleOnFetchAbort = !!A, this.ignoreFetchAbort = !!z5, this.maxEntrySize !== 0) {
30563
31169
  if (this.#u !== 0 && !F(this.#u))
30564
31170
  throw new TypeError("maxSize must be a positive integer if specified");
30565
31171
  if (!F(this.maxEntrySize))
@@ -30575,7 +31181,7 @@ var L = class u2 {
30575
31181
  throw new TypeError("At least one of max, maxSize, or ttl is required");
30576
31182
  if (!this.ttlAutopurge && !this.#o && !this.#u) {
30577
31183
  let E = "LRU_CACHE_UNBOUNDED";
30578
- H(E) && (M.add(E), P("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.", "UnboundedCacheWarning", E, u2));
31184
+ H(E) && (U.add(E), P("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.", "UnboundedCacheWarning", E, u2));
30579
31185
  }
30580
31186
  }
30581
31187
  getRemainingTTL(e) {
@@ -30587,7 +31193,7 @@ var L = class u2 {
30587
31193
  let i = this.ttlAutopurge ? Array.from({ length: this.#o }) : undefined;
30588
31194
  this.#g = i, this.#N = (r, h, l = this.#m.now()) => {
30589
31195
  t[r] = h !== 0 ? l : 0, e[r] = h, s(r, h);
30590
- }, this.#x = (r) => {
31196
+ }, this.#D = (r) => {
30591
31197
  t[r] = e[r] !== 0 ? this.#m.now() : 0, s(r, e[r]);
30592
31198
  };
30593
31199
  let s = this.ttlAutopurge ? (r, h) => {
@@ -30631,7 +31237,7 @@ var L = class u2 {
30631
31237
  return !!l && !!h && (n || o()) - h > l;
30632
31238
  };
30633
31239
  }
30634
- #x = () => {};
31240
+ #D = () => {};
30635
31241
  #E = () => {};
30636
31242
  #N = () => {};
30637
31243
  #p = () => false;
@@ -30797,7 +31403,7 @@ var L = class u2 {
30797
31403
  return this.#v(e, "set"), h && (h.set = "miss", h.maxEntrySizeExceeded = true), this;
30798
31404
  let f = this.#n === 0 ? undefined : this.#s.get(e);
30799
31405
  if (f === undefined)
30800
- f = this.#n === 0 ? this.#h : this.#y.length !== 0 ? this.#y.pop() : this.#n === this.#o ? this.#G(false) : this.#n, this.#i[f] = e, this.#t[f] = t, this.#s.set(e, f), this.#a[this.#h] = f, this.#c[f] = this.#h, this.#h = f, this.#n++, this.#I(f, c, h), h && (h.set = "add"), l = false, this.#j && this.#D?.(t, e, "add");
31406
+ f = this.#n === 0 ? this.#h : this.#y.length !== 0 ? this.#y.pop() : this.#n === this.#o ? this.#G(false) : this.#n, this.#i[f] = e, this.#t[f] = t, this.#s.set(e, f), this.#a[this.#h] = f, this.#c[f] = this.#h, this.#h = f, this.#n++, this.#I(f, c, h), h && (h.set = "add"), l = false, this.#j && this.#x?.(t, e, "add");
30801
31407
  else {
30802
31408
  this.#L(f);
30803
31409
  let g = this.#t[f];
@@ -30861,7 +31467,7 @@ var L = class u2 {
30861
31467
  if (this.#p(n))
30862
31468
  s && (s.has = "stale", this.#E(s, n));
30863
31469
  else
30864
- return i && this.#x(n), s && (s.has = "hit", this.#E(s, n)), true;
31470
+ return i && this.#D(n), s && (s.has = "hit", this.#E(s, n)), true;
30865
31471
  } else
30866
31472
  s && (s.has = "miss");
30867
31473
  return false;
@@ -30919,7 +31525,7 @@ var L = class u2 {
30919
31525
  let i = W.hasSubscribers, { status: s = D() ? {} : undefined } = t;
30920
31526
  t.status = s, s && t.context && (s.context = t.context);
30921
31527
  let n = this.#B(e, t);
30922
- return s && D() && i && (s.trace = true, W.tracePromise(() => n, s).catch(() => {})), n;
31528
+ return s && i && (s.trace = true, W.tracePromise(() => n, s).catch(() => {})), n;
30923
31529
  }
30924
31530
  async#B(e, t = {}) {
30925
31531
  let { allowStale: i = this.allowStale, updateAgeOnGet: s = this.updateAgeOnGet, noDeleteOnStaleGet: n = this.noDeleteOnStaleGet, ttl: o = this.ttl, noDisposeOnSet: r = this.noDisposeOnSet, size: h = 0, sizeCalculation: l = this.sizeCalculation, noUpdateTTL: c = this.noUpdateTTL, noDeleteOnFetchRejection: f = this.noDeleteOnFetchRejection, allowStaleOnFetchRejection: g = this.allowStaleOnFetchRejection, ignoreFetchAbort: p = this.ignoreFetchAbort, allowStaleOnFetchAbort: T = this.allowStaleOnFetchAbort, context: w, forceRefresh: y = false, status: a, signal: m } = t;
@@ -30938,7 +31544,7 @@ var L = class u2 {
30938
31544
  }
30939
31545
  let A = this.#p(b);
30940
31546
  if (!y && !A)
30941
- return a && (a.fetch = "hit"), this.#L(b), s && this.#x(b), a && this.#E(a, b), d;
31547
+ return a && (a.fetch = "hit"), this.#L(b), s && this.#D(b), a && this.#E(a, b), d;
30942
31548
  let z5 = this.#P(e, b, _, w), v = z5.__staleWhileFetching !== undefined && i;
30943
31549
  return a && (a.fetch = A ? "stale" : "refresh", v && A && (a.returnedStale = true)), v ? z5.__staleWhileFetching : z5.__returned = z5;
30944
31550
  }
@@ -30947,7 +31553,7 @@ var L = class u2 {
30947
31553
  let i = W.hasSubscribers, { status: s = D() ? {} : undefined } = t;
30948
31554
  t.status = s, s && t.context && (s.context = t.context);
30949
31555
  let n = this.#K(e, t);
30950
- return s && D() && i && (s.trace = true, W.tracePromise(() => n, s).catch(() => {})), n;
31556
+ return s && i && (s.trace = true, W.tracePromise(() => n, s).catch(() => {})), n;
30951
31557
  }
30952
31558
  async#K(e, t = {}) {
30953
31559
  let i = await this.#B(e, t);
@@ -30986,7 +31592,7 @@ var L = class u2 {
30986
31592
  return;
30987
31593
  }
30988
31594
  let h = this.#t[r], l = this.#e(h);
30989
- return o && this.#E(o, r), this.#p(r) ? l ? (o && (o.get = "stale-fetching"), i && h.__staleWhileFetching !== undefined ? (o && (o.returnedStale = true), h.__staleWhileFetching) : undefined) : (n || this.#v(e, "expire"), o && (o.get = "stale"), i ? (o && (o.returnedStale = true), h) : undefined) : (o && (o.get = l ? "fetching" : "hit"), this.#L(r), s && this.#x(r), l ? h.__staleWhileFetching : h);
31595
+ return o && this.#E(o, r), this.#p(r) ? l ? (o && (o.get = "stale-fetching"), i && h.__staleWhileFetching !== undefined ? (o && (o.returnedStale = true), h.__staleWhileFetching) : undefined) : (n || this.#v(e, "expire"), o && (o.get = "stale"), i ? (o && (o.returnedStale = true), h) : undefined) : (o && (o.get = l ? "fetching" : "hit"), this.#L(r), s && this.#D(r), l ? h.__staleWhileFetching : h);
30990
31596
  }
30991
31597
  #$(e, t) {
30992
31598
  this.#c[t] = e, this.#a[e] = t;
@@ -31154,7 +31760,7 @@ function extractStructuredText(root) {
31154
31760
  ]);
31155
31761
  const isText = (node) => node.nodeType === node.TEXT_NODE;
31156
31762
  const isElement = (node) => node.nodeType === node.ELEMENT_NODE;
31157
- const pushText = (value) => {
31763
+ const pushText2 = (value) => {
31158
31764
  const normalized = value.replace(/\s+/g, " ");
31159
31765
  if (!normalized.trim())
31160
31766
  return;
@@ -31180,7 +31786,7 @@ function extractStructuredText(root) {
31180
31786
  };
31181
31787
  const visit = (node) => {
31182
31788
  if (isText(node)) {
31183
- pushText(node.textContent || "");
31789
+ pushText2(node.textContent || "");
31184
31790
  return;
31185
31791
  }
31186
31792
  if (!isElement(node))
@@ -31891,7 +32497,7 @@ async function probeLlmsText(url, timeoutMs, signal, fallbackOrigin) {
31891
32497
  }
31892
32498
 
31893
32499
  // src/tools/smartfetch/cache.ts
31894
- var CACHE = new L({
32500
+ var CACHE = new M({
31895
32501
  maxSize: 50 * 1024 * 1024,
31896
32502
  ttl: 15 * 60 * 1000,
31897
32503
  sizeCalculation: (value) => {
@@ -31952,7 +32558,7 @@ function isInvalidLlmsResult(fetchResult) {
31952
32558
 
31953
32559
  // src/tools/smartfetch/secondary-model.ts
31954
32560
  import { existsSync as existsSync10 } from "node:fs";
31955
- import { readFile as readFile4 } from "node:fs/promises";
32561
+ import { readFile as readFile5 } from "node:fs/promises";
31956
32562
  import path17 from "node:path";
31957
32563
  function parseModelRef(value) {
31958
32564
  if (!value)
@@ -31989,7 +32595,7 @@ async function readOpenCodeConfigFile(configPath) {
31989
32595
  if (!configPath)
31990
32596
  return;
31991
32597
  try {
31992
- const content = await readFile4(configPath, "utf8");
32598
+ const content = await readFile5(configPath, "utf8");
31993
32599
  return JSON.parse(stripJsonComments(content));
31994
32600
  } catch {
31995
32601
  return;
@@ -32639,7 +33245,7 @@ function createWebfetchTool(pluginCtx, options = {}) {
32639
33245
  });
32640
33246
  }
32641
33247
  // src/tools/subtask/command.ts
32642
- var COMMAND_NAME4 = "subtask";
33248
+ var COMMAND_NAME5 = "subtask";
32643
33249
  var SUBTASK_COMMAND_TEMPLATE = `Start a focused subtask worker.
32644
33250
 
32645
33251
  The user's request below is the full scope for the worker. Do not broaden it.
@@ -32660,11 +33266,11 @@ Only include files that are clearly relevant. If no files are needed, omit files
32660
33266
  function createSubtaskCommandManager(_ctx, state) {
32661
33267
  function registerCommand(opencodeConfig) {
32662
33268
  const configCommand = opencodeConfig.command;
32663
- if (!configCommand?.[COMMAND_NAME4]) {
33269
+ if (!configCommand?.[COMMAND_NAME5]) {
32664
33270
  if (!opencodeConfig.command) {
32665
33271
  opencodeConfig.command = {};
32666
33272
  }
32667
- opencodeConfig.command[COMMAND_NAME4] = {
33273
+ opencodeConfig.command[COMMAND_NAME5] = {
32668
33274
  description: "Create a focused subtask prompt for a new session",
32669
33275
  template: SUBTASK_COMMAND_TEMPLATE
32670
33276
  };
@@ -32691,11 +33297,11 @@ function createSubtaskCommandManager(_ctx, state) {
32691
33297
  };
32692
33298
  }
32693
33299
  // src/tools/subtask/files.ts
32694
- import * as fs11 from "node:fs/promises";
33300
+ import * as fs12 from "node:fs/promises";
32695
33301
  import * as path20 from "node:path";
32696
33302
 
32697
33303
  // src/tools/subtask/vendor.ts
32698
- import * as fs10 from "node:fs/promises";
33304
+ import * as fs11 from "node:fs/promises";
32699
33305
  import * as path19 from "node:path";
32700
33306
  var DEFAULT_READ_LIMIT = 2000;
32701
33307
  var MAX_LINE_LENGTH = 2000;
@@ -32739,7 +33345,7 @@ async function isBinaryFile(filepath) {
32739
33345
  return true;
32740
33346
  }
32741
33347
  try {
32742
- const file = await fs10.open(filepath, "r");
33348
+ const file = await fs11.open(filepath, "r");
32743
33349
  try {
32744
33350
  const buffer = Buffer.alloc(SAMPLE_BYTES);
32745
33351
  const result = await file.read(buffer, 0, SAMPLE_BYTES, 0);
@@ -32825,24 +33431,24 @@ function parseFileReferences(text) {
32825
33431
  }
32826
33432
  async function buildSyntheticFileParts(directory, refs) {
32827
33433
  const parts = [];
32828
- const realDirectory = await fs11.realpath(directory);
33434
+ const realDirectory = await fs12.realpath(directory);
32829
33435
  for (const ref of refs) {
32830
33436
  const filepath = path20.resolve(directory, ref);
32831
33437
  const relative3 = path20.relative(directory, filepath);
32832
33438
  if (relative3.startsWith("..") || path20.isAbsolute(relative3))
32833
33439
  continue;
32834
33440
  try {
32835
- const realFilepath = await fs11.realpath(filepath);
33441
+ const realFilepath = await fs12.realpath(filepath);
32836
33442
  const realRelative = path20.relative(realDirectory, realFilepath);
32837
33443
  if (realRelative.startsWith("..") || path20.isAbsolute(realRelative)) {
32838
33444
  continue;
32839
33445
  }
32840
- const stats = await fs11.stat(realFilepath);
33446
+ const stats = await fs12.stat(realFilepath);
32841
33447
  if (!stats.isFile())
32842
33448
  continue;
32843
33449
  if (await isBinaryFile(realFilepath))
32844
33450
  continue;
32845
- const content = await fs11.readFile(realFilepath, "utf-8");
33451
+ const content = await fs12.readFile(realFilepath, "utf-8");
32846
33452
  parts.push({
32847
33453
  type: "text",
32848
33454
  synthetic: true,
@@ -33204,7 +33810,9 @@ var OhMyOpenCodeLite = async (ctx) => {
33204
33810
  let jsonErrorRecoveryHook;
33205
33811
  let foregroundFallback;
33206
33812
  let todoContinuationHook;
33813
+ let sessionGoalHook;
33207
33814
  let taskSessionManagerHook;
33815
+ let backgroundJobBoard;
33208
33816
  let interviewManager;
33209
33817
  let presetManager;
33210
33818
  let divoomManager;
@@ -33290,16 +33898,22 @@ var OhMyOpenCodeLite = async (ctx) => {
33290
33898
  applyPatchHook = createApplyPatchHook(ctx);
33291
33899
  jsonErrorRecoveryHook = createJsonErrorRecoveryHook(ctx);
33292
33900
  foregroundFallback = new ForegroundFallbackManager(ctx.client, runtimeChains, config.fallback?.enabled !== false && Object.keys(runtimeChains).length > 0);
33901
+ backgroundJobBoard = new BackgroundJobBoard;
33293
33902
  todoContinuationHook = createTodoContinuationHook(ctx, {
33294
33903
  maxContinuations: config.todoContinuation?.maxContinuations ?? 5,
33295
33904
  cooldownMs: config.todoContinuation?.cooldownMs ?? 3000,
33296
33905
  autoEnable: config.todoContinuation?.autoEnable ?? false,
33297
- autoEnableThreshold: config.todoContinuation?.autoEnableThreshold ?? 4
33906
+ autoEnableThreshold: config.todoContinuation?.autoEnableThreshold ?? 4,
33907
+ backgroundJobBoard
33908
+ });
33909
+ sessionGoalHook = createSessionGoalHook(ctx, config, {
33910
+ getAgentName: (sessionID) => sessionAgentMap.get(sessionID)
33298
33911
  });
33299
33912
  taskSessionManagerHook = createTaskSessionManagerHook(ctx, {
33300
33913
  maxSessionsPerAgent: config.sessionManager?.maxSessionsPerAgent ?? 2,
33301
33914
  readContextMinLines: config.sessionManager?.readContextMinLines ?? 10,
33302
33915
  readContextMaxFiles: config.sessionManager?.readContextMaxFiles ?? 8,
33916
+ backgroundJobBoard,
33303
33917
  shouldManageSession: (sessionID) => sessionAgentMap.get(sessionID) === "orchestrator"
33304
33918
  });
33305
33919
  interviewManager = createInterviewManager(ctx, config);
@@ -33550,6 +34164,7 @@ var OhMyOpenCodeLite = async (ctx) => {
33550
34164
  };
33551
34165
  }
33552
34166
  interviewManager.registerCommand(opencodeConfig);
34167
+ sessionGoalHook.registerCommand(opencodeConfig);
33553
34168
  presetManager.registerCommand(opencodeConfig);
33554
34169
  subtaskCommandManager.registerCommand(opencodeConfig);
33555
34170
  },
@@ -33571,12 +34186,13 @@ var OhMyOpenCodeLite = async (ctx) => {
33571
34186
  depthTracker.registerChild(parentSessionId, childSessionId);
33572
34187
  }
33573
34188
  }
33574
- await foregroundFallback.handleEvent(input.event);
33575
- await todoContinuationHook.handleEvent(input);
33576
- await autoUpdateChecker.event(input);
33577
34189
  await multiplexerSessionManager.onSessionCreated(event);
33578
34190
  await multiplexerSessionManager.onSessionStatus(event);
33579
34191
  await multiplexerSessionManager.onSessionDeleted(event);
34192
+ await foregroundFallback.handleEvent(input.event);
34193
+ await todoContinuationHook.handleEvent(input);
34194
+ sessionGoalHook.handleEvent(input);
34195
+ await autoUpdateChecker.event(input);
33580
34196
  await interviewManager.handleEvent(input);
33581
34197
  await taskSessionManagerHook.event(input);
33582
34198
  subtaskCommandManager.handleEvent(input);
@@ -33637,6 +34253,7 @@ var OhMyOpenCodeLite = async (ctx) => {
33637
34253
  await todoContinuationHook.handleCommandExecuteBefore(input, output);
33638
34254
  await interviewManager.handleCommandExecuteBefore(input, output);
33639
34255
  await presetManager.handleCommandExecuteBefore(input, output);
34256
+ await sessionGoalHook.handleCommandExecuteBefore(input, output);
33640
34257
  },
33641
34258
  "chat.headers": chatHeadersHook["chat.headers"],
33642
34259
  "chat.message": async (input, output) => {
@@ -33665,6 +34282,7 @@ var OhMyOpenCodeLite = async (ctx) => {
33665
34282
  ${output.system[0]}` : "");
33666
34283
  }
33667
34284
  }
34285
+ sessionGoalHook.handleSystemTransform(input, output);
33668
34286
  collapseSystemInPlace(output.system);
33669
34287
  },
33670
34288
  "experimental.chat.messages.transform": async (input, output) => {