oh-my-opencode-slim 1.1.0 → 1.1.2
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/README.ja-JP.md +638 -0
- package/README.ko-KR.md +634 -0
- package/README.md +48 -12
- package/README.zh-CN.md +627 -0
- package/dist/cli/background-subagents.d.ts +13 -0
- package/dist/cli/index.js +65 -92
- package/dist/cli/skills.d.ts +2 -30
- package/dist/cli/types.d.ts +0 -1
- package/dist/config/fallback-chains.d.ts +1 -0
- package/dist/config/schema.d.ts +7 -0
- package/dist/hooks/auto-update-checker/checker.d.ts +7 -1
- package/dist/hooks/auto-update-checker/constants.d.ts +1 -0
- package/dist/hooks/auto-update-checker/types.d.ts +10 -0
- package/dist/hooks/deepwork/index.d.ts +13 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/session-goal/index.d.ts +38 -0
- package/dist/index.js +852 -435
- package/dist/multiplexer/session-manager.d.ts +3 -1
- package/dist/tools/ast-grep/tools.d.ts +1 -1
- package/dist/tools/cancel-task.d.ts +16 -0
- package/dist/tools/preset-manager.d.ts +6 -7
- package/dist/tools/subtask/tools.d.ts +6 -1
- package/dist/tui.js +17 -62
- package/dist/utils/background-job-board.d.ts +90 -0
- package/oh-my-opencode-slim.schema.json +11 -0
- package/package.json +6 -3
- package/dist/agents/council-master.d.ts +0 -2
- package/dist/background/background-manager.d.ts +0 -203
- package/dist/background/index.d.ts +0 -3
- package/dist/background/multiplexer-session-manager.d.ts +0 -70
- package/dist/background/subagent-depth.d.ts +0 -35
- package/dist/cli/divoom.d.ts +0 -23
- package/dist/integrations/divoom/index.d.ts +0 -3
- package/dist/integrations/divoom/status-manager.d.ts +0 -31
- package/dist/integrations/divoom/swift-helper-source.d.ts +0 -1
- package/dist/integrations/divoom/swift-transport.d.ts +0 -26
- package/dist/integrations/divoom/types.d.ts +0 -41
- package/dist/tools/background.d.ts +0 -13
- package/dist/tools/fork/command.d.ts +0 -28
- package/dist/tools/fork/files.d.ts +0 -33
- package/dist/tools/fork/index.d.ts +0 -10
- package/dist/tools/fork/state.d.ts +0 -7
- package/dist/tools/fork/tools.d.ts +0 -23
- package/dist/tools/fork/vendor.d.ts +0 -28
- package/dist/tools/handoff/command.d.ts +0 -29
- package/dist/tools/handoff/files.d.ts +0 -33
- package/dist/tools/handoff/index.d.ts +0 -10
- package/dist/tools/handoff/state.d.ts +0 -7
- package/dist/tools/handoff/tools.d.ts +0 -23
- package/dist/tools/handoff/vendor.d.ts +0 -28
- package/dist/tools/lsp/client.d.ts +0 -81
- package/dist/tools/lsp/config-store.d.ts +0 -29
- package/dist/tools/lsp/config.d.ts +0 -5
- package/dist/tools/lsp/constants.d.ts +0 -24
- package/dist/tools/lsp/index.d.ts +0 -4
- package/dist/tools/lsp/tools.d.ts +0 -5
- package/dist/tools/lsp/types.d.ts +0 -45
- package/dist/tools/lsp/utils.d.ts +0 -34
- package/dist/utils/tmux-debug-log.d.ts +0 -2
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++) {
|
|
@@ -18196,6 +18196,13 @@ function getCustomOpenCodeConfigDir() {
|
|
|
18196
18196
|
const configDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
18197
18197
|
return configDir || undefined;
|
|
18198
18198
|
}
|
|
18199
|
+
function getConfigDir() {
|
|
18200
|
+
const customConfigDir = getCustomOpenCodeConfigDir();
|
|
18201
|
+
if (customConfigDir) {
|
|
18202
|
+
return customConfigDir;
|
|
18203
|
+
}
|
|
18204
|
+
return getDefaultOpenCodeConfigDir();
|
|
18205
|
+
}
|
|
18199
18206
|
function getConfigSearchDirs() {
|
|
18200
18207
|
const dirs = [getCustomOpenCodeConfigDir(), getDefaultOpenCodeConfigDir()];
|
|
18201
18208
|
return dirs.filter((dir, index) => {
|
|
@@ -18203,7 +18210,7 @@ function getConfigSearchDirs() {
|
|
|
18203
18210
|
});
|
|
18204
18211
|
}
|
|
18205
18212
|
function getOpenCodeConfigPaths() {
|
|
18206
|
-
const configDir =
|
|
18213
|
+
const configDir = getConfigDir();
|
|
18207
18214
|
return [join(configDir, "opencode.json"), join(configDir, "opencode.jsonc")];
|
|
18208
18215
|
}
|
|
18209
18216
|
|
|
@@ -18230,19 +18237,6 @@ var CUSTOM_SKILLS = [
|
|
|
18230
18237
|
];
|
|
18231
18238
|
|
|
18232
18239
|
// 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
18240
|
var PERMISSION_ONLY_SKILLS = [
|
|
18247
18241
|
{
|
|
18248
18242
|
name: "requesting-code-review",
|
|
@@ -18267,12 +18261,6 @@ function getSkillPermissionsForAgent(agentName, skillList) {
|
|
|
18267
18261
|
}
|
|
18268
18262
|
return permissions;
|
|
18269
18263
|
}
|
|
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
18264
|
for (const skill of CUSTOM_SKILLS) {
|
|
18277
18265
|
const isAllowed = skill.allowedAgents.includes("*") || skill.allowedAgents.includes(agentName);
|
|
18278
18266
|
if (isAllowed) {
|
|
@@ -18603,6 +18591,9 @@ var TodoContinuationConfigSchema = z2.object({
|
|
|
18603
18591
|
autoEnable: z2.boolean().default(false).describe("Automatically enable auto-continue when the orchestrator session has enough todos"),
|
|
18604
18592
|
autoEnableThreshold: z2.number().int().min(1).max(50).default(4).describe("Number of todos that triggers auto-enable (only used when autoEnable is true)")
|
|
18605
18593
|
});
|
|
18594
|
+
var SubtaskConfigSchema = z2.object({
|
|
18595
|
+
timeoutMs: z2.number().int().min(0).max(24 * 60 * 60 * 1000).optional().describe("Subtask worker timeout in ms. 0 disables the timeout. Defaults to 300000 (5 minutes).")
|
|
18596
|
+
});
|
|
18606
18597
|
var FailoverConfigSchema = z2.object({
|
|
18607
18598
|
enabled: z2.boolean().default(true),
|
|
18608
18599
|
timeoutMs: z2.number().min(0).default(15000),
|
|
@@ -18650,6 +18641,7 @@ var PluginConfigSchema = z2.object({
|
|
|
18650
18641
|
sessionManager: SessionManagerConfigSchema.optional(),
|
|
18651
18642
|
divoom: DivoomConfigSchema.optional(),
|
|
18652
18643
|
todoContinuation: TodoContinuationConfigSchema.optional(),
|
|
18644
|
+
subtask: SubtaskConfigSchema.optional(),
|
|
18653
18645
|
fallback: FailoverConfigSchema.optional(),
|
|
18654
18646
|
council: CouncilConfigSchema.optional()
|
|
18655
18647
|
}).superRefine((value, ctx) => {
|
|
@@ -18670,7 +18662,9 @@ function loadConfigFromPath(configPath, options) {
|
|
|
18670
18662
|
const content = fs.readFileSync(configPath, "utf-8");
|
|
18671
18663
|
let rawConfig;
|
|
18672
18664
|
try {
|
|
18673
|
-
|
|
18665
|
+
const stripped = stripJsonComments(content);
|
|
18666
|
+
const interpolated = stripped.replace(/\{env:([^}]+)\}/g, (_, varName) => process.env[varName] ?? "");
|
|
18667
|
+
rawConfig = JSON.parse(interpolated);
|
|
18674
18668
|
} catch (error) {
|
|
18675
18669
|
const message = error instanceof Error ? error.message : String(error);
|
|
18676
18670
|
options?.onWarning?.({
|
|
@@ -18749,7 +18743,8 @@ function mergePluginConfigs(base, override) {
|
|
|
18749
18743
|
sessionManager: deepMerge(base.sessionManager, override.sessionManager),
|
|
18750
18744
|
divoom: deepMerge(base.divoom, override.divoom),
|
|
18751
18745
|
fallback: deepMerge(base.fallback, override.fallback),
|
|
18752
|
-
council: deepMerge(base.council, override.council)
|
|
18746
|
+
council: deepMerge(base.council, override.council),
|
|
18747
|
+
subtask: deepMerge(base.subtask, override.subtask)
|
|
18753
18748
|
};
|
|
18754
18749
|
}
|
|
18755
18750
|
function deepMerge(base, override) {
|
|
@@ -18901,34 +18896,32 @@ function parseModelReference(model) {
|
|
|
18901
18896
|
async function promptWithTimeout(client, args, timeoutMs, signal) {
|
|
18902
18897
|
if (signal?.aborted)
|
|
18903
18898
|
throw new Error("Prompt cancelled");
|
|
18904
|
-
if (timeoutMs <= 0) {
|
|
18905
|
-
await client.session.prompt(args);
|
|
18906
|
-
return;
|
|
18907
|
-
}
|
|
18908
18899
|
const sessionId = args.path.id;
|
|
18900
|
+
const hasTimeout = timeoutMs > 0;
|
|
18909
18901
|
let timer;
|
|
18910
18902
|
let onAbort;
|
|
18911
18903
|
try {
|
|
18912
18904
|
const promptPromise = client.session.prompt(args);
|
|
18913
18905
|
promptPromise.catch(() => {});
|
|
18914
|
-
|
|
18915
|
-
|
|
18916
|
-
new Promise((_, reject) => {
|
|
18906
|
+
const racers = [promptPromise];
|
|
18907
|
+
if (hasTimeout) {
|
|
18908
|
+
racers.push(new Promise((_, reject) => {
|
|
18917
18909
|
timer = setTimeout(() => {
|
|
18918
18910
|
reject(new OperationTimeoutError(`Prompt timed out after ${timeoutMs}ms`));
|
|
18919
18911
|
}, timeoutMs);
|
|
18920
|
-
})
|
|
18921
|
-
|
|
18922
|
-
|
|
18923
|
-
|
|
18912
|
+
}));
|
|
18913
|
+
}
|
|
18914
|
+
if (signal) {
|
|
18915
|
+
racers.push(new Promise((_, reject) => {
|
|
18924
18916
|
if (signal.aborted) {
|
|
18925
18917
|
reject(new Error("Prompt cancelled"));
|
|
18926
18918
|
return;
|
|
18927
18919
|
}
|
|
18928
18920
|
onAbort = () => reject(new Error("Prompt cancelled"));
|
|
18929
18921
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
18930
|
-
})
|
|
18931
|
-
|
|
18922
|
+
}));
|
|
18923
|
+
}
|
|
18924
|
+
await Promise.race(racers);
|
|
18932
18925
|
} catch (error) {
|
|
18933
18926
|
if (error instanceof OperationTimeoutError) {
|
|
18934
18927
|
try {
|
|
@@ -19012,7 +19005,7 @@ var AGENT_DESCRIPTIONS = {
|
|
|
19012
19005
|
- Permissions: Read/write files
|
|
19013
19006
|
- Stats: 2x faster code edits, 1/2 cost of orchestrator, 0.8x quality of orchestrator
|
|
19014
19007
|
- Tools/Constraints: Execution-focused—no research, no architectural decisions
|
|
19015
|
-
- **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
|
|
19008
|
+
- **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 modification, scoping work per folder and spawning parallel @fixers for each folder.
|
|
19016
19009
|
- **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
19010
|
- **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.`,
|
|
19018
19011
|
council: `@council
|
|
@@ -19135,7 +19128,7 @@ relevant files. Wait for the summary, then integrate and verify it.
|
|
|
19135
19128
|
5. Adjust if needed
|
|
19136
19129
|
|
|
19137
19130
|
### Session Reuse
|
|
19138
|
-
- Smartly reuse an available specialist session -
|
|
19131
|
+
- Smartly reuse an available specialist session - context reuse saves time and tokens
|
|
19139
19132
|
- When too much unrelated, and really needed, start a fresh session with the specialist
|
|
19140
19133
|
- If multiple remembered sessions fit, prefer the most recently used matching session.
|
|
19141
19134
|
- Prefer re-uses over creating new sessions all the time
|
|
@@ -19982,6 +19975,35 @@ function getDisabledAgents(config) {
|
|
|
19982
19975
|
return disabled;
|
|
19983
19976
|
}
|
|
19984
19977
|
|
|
19978
|
+
// src/config/fallback-chains.ts
|
|
19979
|
+
function normalizeFallbackChainsForPreset(chains, presetName) {
|
|
19980
|
+
const normalized = {};
|
|
19981
|
+
for (const [rawKey, chainModels] of Object.entries(chains)) {
|
|
19982
|
+
if (!chainModels?.length)
|
|
19983
|
+
continue;
|
|
19984
|
+
const separatorIndex = rawKey.indexOf(":");
|
|
19985
|
+
const hasPresetScope = separatorIndex !== -1;
|
|
19986
|
+
const scopedPreset = hasPresetScope ? rawKey.slice(0, separatorIndex) : "";
|
|
19987
|
+
const agentName = hasPresetScope ? rawKey.slice(separatorIndex + 1) : rawKey;
|
|
19988
|
+
if (!agentName)
|
|
19989
|
+
continue;
|
|
19990
|
+
if (hasPresetScope && scopedPreset !== presetName)
|
|
19991
|
+
continue;
|
|
19992
|
+
const existing = normalized[agentName] ?? [];
|
|
19993
|
+
const seen = new Set(existing);
|
|
19994
|
+
for (const chainModel of chainModels) {
|
|
19995
|
+
if (seen.has(chainModel))
|
|
19996
|
+
continue;
|
|
19997
|
+
seen.add(chainModel);
|
|
19998
|
+
existing.push(chainModel);
|
|
19999
|
+
}
|
|
20000
|
+
if (existing.length > 0) {
|
|
20001
|
+
normalized[agentName] = existing;
|
|
20002
|
+
}
|
|
20003
|
+
}
|
|
20004
|
+
return normalized;
|
|
20005
|
+
}
|
|
20006
|
+
|
|
19985
20007
|
// src/config/runtime-preset.ts
|
|
19986
20008
|
var activeRuntimePreset = null;
|
|
19987
20009
|
function setActiveRuntimePreset(name) {
|
|
@@ -19998,10 +20020,6 @@ function setActiveRuntimePresetWithPrevious(name) {
|
|
|
19998
20020
|
previousRuntimePreset = activeRuntimePreset;
|
|
19999
20021
|
activeRuntimePreset = name;
|
|
20000
20022
|
}
|
|
20001
|
-
function rollbackRuntimePreset(previous) {
|
|
20002
|
-
activeRuntimePreset = previous;
|
|
20003
|
-
previousRuntimePreset = null;
|
|
20004
|
-
}
|
|
20005
20023
|
|
|
20006
20024
|
// src/utils/logger.ts
|
|
20007
20025
|
import * as fs2 from "node:fs";
|
|
@@ -20014,7 +20032,7 @@ var RETENTION_MS = 7 * 24 * 60 * 60 * 1000;
|
|
|
20014
20032
|
var logFile = null;
|
|
20015
20033
|
var writeChain = Promise.resolve();
|
|
20016
20034
|
function getLogDir() {
|
|
20017
|
-
return process.env.OPENCODE_LOG_DIR ?? path2.join(os.homedir(), ".local/share/opencode");
|
|
20035
|
+
return process.env.OPENCODE_LOG_DIR ?? path2.join(os.homedir(), ".local/share/opencode/log");
|
|
20018
20036
|
}
|
|
20019
20037
|
function cleanupOldLogs(logDir) {
|
|
20020
20038
|
try {
|
|
@@ -22139,6 +22157,7 @@ import * as os3 from "node:os";
|
|
|
22139
22157
|
import * as path6 from "node:path";
|
|
22140
22158
|
var PACKAGE_NAME = "oh-my-opencode-slim";
|
|
22141
22159
|
var NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME}/dist-tags`;
|
|
22160
|
+
var NPM_PACKAGE_URL = `https://registry.npmjs.org/${PACKAGE_NAME}`;
|
|
22142
22161
|
var NPM_FETCH_TIMEOUT = 5000;
|
|
22143
22162
|
function getCacheDir() {
|
|
22144
22163
|
if (process.platform === "win32") {
|
|
@@ -22165,6 +22184,83 @@ function isPrereleaseVersion(version) {
|
|
|
22165
22184
|
function isDistTag(version) {
|
|
22166
22185
|
return !/^\d/.test(version);
|
|
22167
22186
|
}
|
|
22187
|
+
function parseVersion(version) {
|
|
22188
|
+
const normalized = version.trim().replace(/^[~^=<>\s]+/, "");
|
|
22189
|
+
const match = normalized.match(/^(\d+)\.(\d+)\.(\d+)(?:-([\w.-]+))?/);
|
|
22190
|
+
if (!match)
|
|
22191
|
+
return null;
|
|
22192
|
+
return {
|
|
22193
|
+
major: Number(match[1]),
|
|
22194
|
+
minor: Number(match[2]),
|
|
22195
|
+
patch: Number(match[3]),
|
|
22196
|
+
prerelease: match[4] ?? null
|
|
22197
|
+
};
|
|
22198
|
+
}
|
|
22199
|
+
function compareVersions(a, b) {
|
|
22200
|
+
const parsedA = parseVersion(a);
|
|
22201
|
+
const parsedB = parseVersion(b);
|
|
22202
|
+
if (!parsedA || !parsedB)
|
|
22203
|
+
return a.localeCompare(b);
|
|
22204
|
+
const parts = [
|
|
22205
|
+
"major",
|
|
22206
|
+
"minor",
|
|
22207
|
+
"patch"
|
|
22208
|
+
];
|
|
22209
|
+
for (const part of parts) {
|
|
22210
|
+
if (parsedA[part] !== parsedB[part]) {
|
|
22211
|
+
return parsedA[part] - parsedB[part];
|
|
22212
|
+
}
|
|
22213
|
+
}
|
|
22214
|
+
if (parsedA.prerelease === parsedB.prerelease)
|
|
22215
|
+
return 0;
|
|
22216
|
+
if (!parsedA.prerelease)
|
|
22217
|
+
return 1;
|
|
22218
|
+
if (!parsedB.prerelease)
|
|
22219
|
+
return -1;
|
|
22220
|
+
return comparePrerelease(parsedA.prerelease, parsedB.prerelease);
|
|
22221
|
+
}
|
|
22222
|
+
function comparePrerelease(a, b) {
|
|
22223
|
+
const segmentsA = a.split(".");
|
|
22224
|
+
const segmentsB = b.split(".");
|
|
22225
|
+
const length = Math.max(segmentsA.length, segmentsB.length);
|
|
22226
|
+
for (let i = 0;i < length; i++) {
|
|
22227
|
+
const segmentA = segmentsA[i];
|
|
22228
|
+
const segmentB = segmentsB[i];
|
|
22229
|
+
if (segmentA === segmentB)
|
|
22230
|
+
continue;
|
|
22231
|
+
if (segmentA === undefined)
|
|
22232
|
+
return -1;
|
|
22233
|
+
if (segmentB === undefined)
|
|
22234
|
+
return 1;
|
|
22235
|
+
const numberA = Number(segmentA);
|
|
22236
|
+
const numberB = Number(segmentB);
|
|
22237
|
+
const numericA = Number.isInteger(numberA);
|
|
22238
|
+
const numericB = Number.isInteger(numberB);
|
|
22239
|
+
if (numericA && numericB)
|
|
22240
|
+
return numberA - numberB;
|
|
22241
|
+
if (numericA)
|
|
22242
|
+
return -1;
|
|
22243
|
+
if (numericB)
|
|
22244
|
+
return 1;
|
|
22245
|
+
const comparison = segmentA.localeCompare(segmentB);
|
|
22246
|
+
if (comparison !== 0)
|
|
22247
|
+
return comparison;
|
|
22248
|
+
}
|
|
22249
|
+
return 0;
|
|
22250
|
+
}
|
|
22251
|
+
function getPrereleaseChannel(version) {
|
|
22252
|
+
if (!version.prerelease)
|
|
22253
|
+
return null;
|
|
22254
|
+
return version.prerelease.split(".")[0] ?? null;
|
|
22255
|
+
}
|
|
22256
|
+
function isVersionInChannel(version, channel) {
|
|
22257
|
+
const parsed = parseVersion(version);
|
|
22258
|
+
if (!parsed)
|
|
22259
|
+
return false;
|
|
22260
|
+
if (channel === "latest")
|
|
22261
|
+
return parsed.prerelease === null;
|
|
22262
|
+
return getPrereleaseChannel(parsed) === channel;
|
|
22263
|
+
}
|
|
22168
22264
|
function extractChannel(version) {
|
|
22169
22265
|
if (!version)
|
|
22170
22266
|
return "latest";
|
|
@@ -22312,6 +22408,10 @@ function getCachedVersion() {
|
|
|
22312
22408
|
return null;
|
|
22313
22409
|
}
|
|
22314
22410
|
async function getLatestVersion(channel = "latest") {
|
|
22411
|
+
const distTags = await fetchDistTags();
|
|
22412
|
+
return distTags?.[channel] ?? distTags?.latest ?? null;
|
|
22413
|
+
}
|
|
22414
|
+
async function fetchDistTags() {
|
|
22315
22415
|
const controller = new AbortController;
|
|
22316
22416
|
const timeoutId = setTimeout(() => controller.abort(), NPM_FETCH_TIMEOUT);
|
|
22317
22417
|
try {
|
|
@@ -22322,13 +22422,84 @@ async function getLatestVersion(channel = "latest") {
|
|
|
22322
22422
|
if (!response.ok)
|
|
22323
22423
|
return null;
|
|
22324
22424
|
const data = await response.json();
|
|
22325
|
-
return data
|
|
22425
|
+
return data;
|
|
22326
22426
|
} catch {
|
|
22327
22427
|
return null;
|
|
22328
22428
|
} finally {
|
|
22329
22429
|
clearTimeout(timeoutId);
|
|
22330
22430
|
}
|
|
22331
22431
|
}
|
|
22432
|
+
async function getLatestCompatibleVersion(currentVersion, channel = "latest") {
|
|
22433
|
+
const current = parseVersion(currentVersion);
|
|
22434
|
+
if (!current) {
|
|
22435
|
+
const latestVersion = await getLatestVersion(channel);
|
|
22436
|
+
return {
|
|
22437
|
+
latestVersion: null,
|
|
22438
|
+
latestMajorVersion: latestVersion,
|
|
22439
|
+
blockedByMajor: latestVersion !== null,
|
|
22440
|
+
unsafeReason: latestVersion ? "unparseable-current-version" : undefined
|
|
22441
|
+
};
|
|
22442
|
+
}
|
|
22443
|
+
const controller = new AbortController;
|
|
22444
|
+
const timeoutId = setTimeout(() => controller.abort(), NPM_FETCH_TIMEOUT);
|
|
22445
|
+
try {
|
|
22446
|
+
const response = await fetch(NPM_PACKAGE_URL, {
|
|
22447
|
+
signal: controller.signal,
|
|
22448
|
+
headers: { Accept: "application/json" }
|
|
22449
|
+
});
|
|
22450
|
+
if (!response.ok)
|
|
22451
|
+
return await getCompatibleFromDistTags(current, channel);
|
|
22452
|
+
const data = await response.json();
|
|
22453
|
+
const distTags = data["dist-tags"] ?? { latest: "" };
|
|
22454
|
+
const taggedVersion = distTags[channel] ?? distTags.latest ?? null;
|
|
22455
|
+
const latestMajorVersion = getBlockingMajorVersion(current, [
|
|
22456
|
+
taggedVersion,
|
|
22457
|
+
distTags.latest
|
|
22458
|
+
]);
|
|
22459
|
+
const blockedByMajor = latestMajorVersion !== null;
|
|
22460
|
+
const versions = Object.keys(data.versions ?? {}).filter((version) => {
|
|
22461
|
+
const parsed = parseVersion(version);
|
|
22462
|
+
return parsed?.major === current.major && isVersionInChannel(version, channel);
|
|
22463
|
+
}).sort(compareVersions);
|
|
22464
|
+
const latestVersion = versions.at(-1) ?? null;
|
|
22465
|
+
return { latestVersion, latestMajorVersion, blockedByMajor };
|
|
22466
|
+
} catch {
|
|
22467
|
+
return await getCompatibleFromDistTags(current, channel);
|
|
22468
|
+
} finally {
|
|
22469
|
+
clearTimeout(timeoutId);
|
|
22470
|
+
}
|
|
22471
|
+
}
|
|
22472
|
+
async function getCompatibleFromDistTags(current, channel) {
|
|
22473
|
+
const distTags = await fetchDistTags();
|
|
22474
|
+
if (!distTags) {
|
|
22475
|
+
return {
|
|
22476
|
+
latestVersion: null,
|
|
22477
|
+
latestMajorVersion: null,
|
|
22478
|
+
blockedByMajor: false
|
|
22479
|
+
};
|
|
22480
|
+
}
|
|
22481
|
+
const latestVersion = distTags[channel] ?? distTags.latest ?? null;
|
|
22482
|
+
const latestMajorVersion = getBlockingMajorVersion(current, [
|
|
22483
|
+
latestVersion,
|
|
22484
|
+
distTags.latest
|
|
22485
|
+
]);
|
|
22486
|
+
const blockedByMajor = latestMajorVersion !== null;
|
|
22487
|
+
const parsedLatest = latestVersion ? parseVersion(latestVersion) : null;
|
|
22488
|
+
const compatibleLatestVersion = parsedLatest?.major === current.major && latestVersion && isVersionInChannel(latestVersion, channel) ? latestVersion : null;
|
|
22489
|
+
return {
|
|
22490
|
+
latestVersion: compatibleLatestVersion,
|
|
22491
|
+
latestMajorVersion,
|
|
22492
|
+
blockedByMajor
|
|
22493
|
+
};
|
|
22494
|
+
}
|
|
22495
|
+
function getBlockingMajorVersion(current, candidates) {
|
|
22496
|
+
for (const candidate of candidates) {
|
|
22497
|
+
const parsed = candidate ? parseVersion(candidate) : null;
|
|
22498
|
+
if (parsed && parsed.major > current.major)
|
|
22499
|
+
return candidate ?? null;
|
|
22500
|
+
}
|
|
22501
|
+
return null;
|
|
22502
|
+
}
|
|
22332
22503
|
|
|
22333
22504
|
// src/hooks/auto-update-checker/cache.ts
|
|
22334
22505
|
function removeFromBunLock(installDir, packageName) {
|
|
@@ -22472,7 +22643,20 @@ async function runBackgroundUpdateCheck(ctx, autoUpdate) {
|
|
|
22472
22643
|
return;
|
|
22473
22644
|
}
|
|
22474
22645
|
const channel = extractChannel(pluginInfo.pinnedVersion ?? currentVersion);
|
|
22475
|
-
const
|
|
22646
|
+
const latestInfo = await getLatestCompatibleVersion(currentVersion, channel);
|
|
22647
|
+
if (latestInfo.unsafeReason === "unparseable-current-version") {
|
|
22648
|
+
log(`[auto-update-checker] Current version is not semver; skipping auto-update: ${currentVersion}`);
|
|
22649
|
+
if (latestInfo.latestMajorVersion) {
|
|
22650
|
+
showToast(ctx, `OMO-Slim ${latestInfo.latestMajorVersion}`, `v${latestInfo.latestMajorVersion} available. Auto-update skipped because the current version could not be compared safely.`, "info", 8000);
|
|
22651
|
+
}
|
|
22652
|
+
return;
|
|
22653
|
+
}
|
|
22654
|
+
if (latestInfo.blockedByMajor && latestInfo.latestMajorVersion) {
|
|
22655
|
+
showMajorUpgradeToast(ctx, latestInfo.latestMajorVersion);
|
|
22656
|
+
log(`[auto-update-checker] Major update available; skipping auto-update: ${latestInfo.latestMajorVersion}`);
|
|
22657
|
+
return;
|
|
22658
|
+
}
|
|
22659
|
+
const latestVersion = latestInfo.latestVersion;
|
|
22476
22660
|
if (!latestVersion) {
|
|
22477
22661
|
log("[auto-update-checker] Failed to fetch latest version for channel:", channel);
|
|
22478
22662
|
return;
|
|
@@ -22509,6 +22693,10 @@ Restart OpenCode to apply.`, "success", 8000);
|
|
|
22509
22693
|
log("[auto-update-checker] bun install failed; update not installed");
|
|
22510
22694
|
}
|
|
22511
22695
|
}
|
|
22696
|
+
function showMajorUpgradeToast(ctx, version) {
|
|
22697
|
+
showToast(ctx, `oh-my-opencode-slim v${version} is available.`, `It requires OpenCode background subagents.
|
|
22698
|
+
Run: bunx oh-my-opencode-slim@latest install --background-subagents=yes`, "info", 12000);
|
|
22699
|
+
}
|
|
22512
22700
|
async function runBunInstallSafe(installDir) {
|
|
22513
22701
|
try {
|
|
22514
22702
|
const proc = crossSpawn(["bun", "install"], {
|
|
@@ -23194,7 +23382,7 @@ var RATE_LIMIT_PATTERNS = [
|
|
|
23194
23382
|
/usage limit/i,
|
|
23195
23383
|
/overloaded/i,
|
|
23196
23384
|
/resource.?exhausted/i,
|
|
23197
|
-
/insufficient.?quota/i,
|
|
23385
|
+
/insufficient.?(quota|balance)/i,
|
|
23198
23386
|
/high concurrency/i,
|
|
23199
23387
|
/reduce concurrency/i
|
|
23200
23388
|
];
|
|
@@ -23270,7 +23458,7 @@ class ForegroundFallbackManager {
|
|
|
23270
23458
|
if (!props?.sessionID || props.status?.type !== "retry")
|
|
23271
23459
|
break;
|
|
23272
23460
|
const msg = props.status.message?.toLowerCase() ?? "";
|
|
23273
|
-
if (msg.includes("rate limit") || msg.includes("usage limit") || msg.includes("usage exceeded") || msg.includes("quota exceeded") || msg.includes("exceededbudget") || msg.includes("over budget") || msg.includes("high concurrency") || msg.includes("reduce concurrency")) {
|
|
23461
|
+
if (msg.includes("rate limit") || msg.includes("usage limit") || msg.includes("usage exceeded") || msg.includes("quota exceeded") || msg.includes("exceededbudget") || msg.includes("over budget") || msg.includes("insufficient") || msg.includes("high concurrency") || msg.includes("reduce concurrency")) {
|
|
23274
23462
|
await this.tryFallback(props.sessionID);
|
|
23275
23463
|
}
|
|
23276
23464
|
break;
|
|
@@ -23677,14 +23865,13 @@ function createPhaseReminderHook() {
|
|
|
23677
23865
|
if (originalText.includes(SLIM_INTERNAL_INITIATOR_MARKER)) {
|
|
23678
23866
|
return;
|
|
23679
23867
|
}
|
|
23680
|
-
if (
|
|
23868
|
+
if (lastUserMessage.parts.some((p) => p.text?.includes(PHASE_REMINDER))) {
|
|
23681
23869
|
return;
|
|
23682
23870
|
}
|
|
23683
|
-
lastUserMessage.parts
|
|
23684
|
-
|
|
23685
|
-
|
|
23686
|
-
|
|
23687
|
-
${PHASE_REMINDER}`;
|
|
23871
|
+
lastUserMessage.parts.push({
|
|
23872
|
+
type: "text",
|
|
23873
|
+
text: PHASE_REMINDER
|
|
23874
|
+
});
|
|
23688
23875
|
}
|
|
23689
23876
|
};
|
|
23690
23877
|
}
|
|
@@ -23720,8 +23907,338 @@ function createPostFileToolNudgeHook(options = {}) {
|
|
|
23720
23907
|
}
|
|
23721
23908
|
};
|
|
23722
23909
|
}
|
|
23910
|
+
// src/hooks/session-goal/index.ts
|
|
23911
|
+
import * as fs7 from "node:fs/promises";
|
|
23912
|
+
|
|
23913
|
+
// src/interview/document.ts
|
|
23914
|
+
import * as fsSync from "node:fs";
|
|
23915
|
+
import * as fs6 from "node:fs/promises";
|
|
23916
|
+
import * as path9 from "node:path";
|
|
23917
|
+
var DEFAULT_OUTPUT_FOLDER = "interview";
|
|
23918
|
+
function normalizeOutputFolder(outputFolder) {
|
|
23919
|
+
const normalized = outputFolder.trim().replace(/^\/+|\/+$/g, "");
|
|
23920
|
+
return normalized || DEFAULT_OUTPUT_FOLDER;
|
|
23921
|
+
}
|
|
23922
|
+
function createInterviewDirectoryPath(directory, outputFolder) {
|
|
23923
|
+
return path9.join(directory, normalizeOutputFolder(outputFolder));
|
|
23924
|
+
}
|
|
23925
|
+
function createInterviewFilePath(directory, outputFolder, idea) {
|
|
23926
|
+
const fileName = `${slugify(idea) || "interview"}.md`;
|
|
23927
|
+
return path9.join(createInterviewDirectoryPath(directory, outputFolder), fileName);
|
|
23928
|
+
}
|
|
23929
|
+
function relativeInterviewPath(directory, filePath) {
|
|
23930
|
+
return path9.relative(directory, filePath) || path9.basename(filePath);
|
|
23931
|
+
}
|
|
23932
|
+
function resolveExistingInterviewPath(directory, outputFolder, value) {
|
|
23933
|
+
const trimmed = value.trim();
|
|
23934
|
+
if (!trimmed) {
|
|
23935
|
+
return null;
|
|
23936
|
+
}
|
|
23937
|
+
const outputDir = createInterviewDirectoryPath(directory, outputFolder);
|
|
23938
|
+
const candidates = new Set;
|
|
23939
|
+
const resolvedRoot = path9.resolve(directory);
|
|
23940
|
+
if (path9.isAbsolute(trimmed)) {
|
|
23941
|
+
candidates.add(trimmed);
|
|
23942
|
+
} else {
|
|
23943
|
+
candidates.add(path9.resolve(directory, trimmed));
|
|
23944
|
+
candidates.add(path9.join(outputDir, trimmed));
|
|
23945
|
+
if (!trimmed.endsWith(".md")) {
|
|
23946
|
+
candidates.add(path9.join(outputDir, `${trimmed}.md`));
|
|
23947
|
+
}
|
|
23948
|
+
}
|
|
23949
|
+
for (const candidate of candidates) {
|
|
23950
|
+
if (path9.extname(candidate) !== ".md") {
|
|
23951
|
+
continue;
|
|
23952
|
+
}
|
|
23953
|
+
const resolved = path9.resolve(candidate);
|
|
23954
|
+
if (!resolved.startsWith(resolvedRoot + path9.sep) && resolved !== resolvedRoot) {
|
|
23955
|
+
continue;
|
|
23956
|
+
}
|
|
23957
|
+
if (fsSync.existsSync(candidate)) {
|
|
23958
|
+
return candidate;
|
|
23959
|
+
}
|
|
23960
|
+
}
|
|
23961
|
+
return null;
|
|
23962
|
+
}
|
|
23963
|
+
function slugify(value) {
|
|
23964
|
+
return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
23965
|
+
}
|
|
23966
|
+
function extractHistorySection(document) {
|
|
23967
|
+
const marker = `## Q&A history
|
|
23968
|
+
|
|
23969
|
+
`;
|
|
23970
|
+
const index = document.indexOf(marker);
|
|
23971
|
+
return index >= 0 ? document.slice(index + marker.length).trim() : "";
|
|
23972
|
+
}
|
|
23973
|
+
function extractSummarySection(document) {
|
|
23974
|
+
const marker = `## Current spec
|
|
23975
|
+
|
|
23976
|
+
`;
|
|
23977
|
+
const historyMarker = `
|
|
23978
|
+
|
|
23979
|
+
## Q&A history`;
|
|
23980
|
+
const start = document.indexOf(marker);
|
|
23981
|
+
if (start < 0) {
|
|
23982
|
+
return "";
|
|
23983
|
+
}
|
|
23984
|
+
const summaryStart = start + marker.length;
|
|
23985
|
+
const summaryEnd = document.indexOf(historyMarker, summaryStart);
|
|
23986
|
+
return document.slice(summaryStart, summaryEnd >= 0 ? summaryEnd : undefined).trim();
|
|
23987
|
+
}
|
|
23988
|
+
function extractTitle(document) {
|
|
23989
|
+
const match = document.match(/^#\s+(.+)$/m);
|
|
23990
|
+
return match?.[1]?.trim() ?? "";
|
|
23991
|
+
}
|
|
23992
|
+
function buildInterviewDocument(idea, summary, history, meta) {
|
|
23993
|
+
const normalizedSummary = summary.trim() || "Waiting for interview answers.";
|
|
23994
|
+
const normalizedHistory = history.trim() || "No answers yet.";
|
|
23995
|
+
const frontmatter = meta?.sessionID ? [
|
|
23996
|
+
"---",
|
|
23997
|
+
`sessionID: ${meta.sessionID}`,
|
|
23998
|
+
`baseMessageCount: ${meta.baseMessageCount ?? 0}`,
|
|
23999
|
+
`updatedAt: ${new Date().toISOString()}`,
|
|
24000
|
+
"---",
|
|
24001
|
+
""
|
|
24002
|
+
].join(`
|
|
24003
|
+
`) : "";
|
|
24004
|
+
return [
|
|
24005
|
+
frontmatter,
|
|
24006
|
+
`# ${idea}`,
|
|
24007
|
+
"",
|
|
24008
|
+
"## Current spec",
|
|
24009
|
+
"",
|
|
24010
|
+
normalizedSummary,
|
|
24011
|
+
"",
|
|
24012
|
+
"## Q&A history",
|
|
24013
|
+
"",
|
|
24014
|
+
normalizedHistory,
|
|
24015
|
+
""
|
|
24016
|
+
].join(`
|
|
24017
|
+
`);
|
|
24018
|
+
}
|
|
24019
|
+
function parseFrontmatter(content) {
|
|
24020
|
+
const match = content.match(/^---\n([\s\S]*?)\n---\n/);
|
|
24021
|
+
if (!match)
|
|
24022
|
+
return null;
|
|
24023
|
+
const result = {};
|
|
24024
|
+
for (const line of match[1].split(`
|
|
24025
|
+
`)) {
|
|
24026
|
+
const colonIdx = line.indexOf(":");
|
|
24027
|
+
if (colonIdx > 0) {
|
|
24028
|
+
result[line.slice(0, colonIdx).trim()] = line.slice(colonIdx + 1).trim();
|
|
24029
|
+
}
|
|
24030
|
+
}
|
|
24031
|
+
return result;
|
|
24032
|
+
}
|
|
24033
|
+
async function ensureInterviewFile(record) {
|
|
24034
|
+
await fs6.mkdir(path9.dirname(record.markdownPath), { recursive: true });
|
|
24035
|
+
try {
|
|
24036
|
+
await fs6.access(record.markdownPath);
|
|
24037
|
+
} catch {
|
|
24038
|
+
await fs6.writeFile(record.markdownPath, buildInterviewDocument(record.idea, "", "", {
|
|
24039
|
+
sessionID: record.sessionID,
|
|
24040
|
+
baseMessageCount: record.baseMessageCount
|
|
24041
|
+
}), "utf8");
|
|
24042
|
+
}
|
|
24043
|
+
}
|
|
24044
|
+
async function readInterviewDocument(record) {
|
|
24045
|
+
try {
|
|
24046
|
+
return await fs6.readFile(record.markdownPath, "utf8");
|
|
24047
|
+
} catch {}
|
|
24048
|
+
await ensureInterviewFile(record);
|
|
24049
|
+
return fs6.readFile(record.markdownPath, "utf8");
|
|
24050
|
+
}
|
|
24051
|
+
async function rewriteInterviewDocument(record, summary) {
|
|
24052
|
+
const existing = await readInterviewDocument(record);
|
|
24053
|
+
const history = extractHistorySection(existing);
|
|
24054
|
+
const next = buildInterviewDocument(record.idea, summary, history, {
|
|
24055
|
+
sessionID: record.sessionID,
|
|
24056
|
+
baseMessageCount: record.baseMessageCount
|
|
24057
|
+
});
|
|
24058
|
+
await fs6.writeFile(record.markdownPath, next, "utf8");
|
|
24059
|
+
return next;
|
|
24060
|
+
}
|
|
24061
|
+
async function appendInterviewAnswers(record, questions, answers) {
|
|
24062
|
+
const existing = await readInterviewDocument(record);
|
|
24063
|
+
const summary = extractSummarySection(existing);
|
|
24064
|
+
const history = extractHistorySection(existing);
|
|
24065
|
+
const questionMap = new Map(questions.map((question) => [question.id, question]));
|
|
24066
|
+
const appended = answers.map((answer) => {
|
|
24067
|
+
const question = questionMap.get(answer.questionId);
|
|
24068
|
+
return question ? `Q: ${question.question}
|
|
24069
|
+
A: ${answer.answer.trim()}` : null;
|
|
24070
|
+
}).filter((value) => value !== null).join(`
|
|
24071
|
+
|
|
24072
|
+
`);
|
|
24073
|
+
const nextHistory = [history === "No answers yet." ? "" : history, appended].filter(Boolean).join(`
|
|
24074
|
+
|
|
24075
|
+
`);
|
|
24076
|
+
await fs6.writeFile(record.markdownPath, buildInterviewDocument(record.idea, summary, nextHistory, {
|
|
24077
|
+
sessionID: record.sessionID,
|
|
24078
|
+
baseMessageCount: record.baseMessageCount
|
|
24079
|
+
}), "utf8");
|
|
24080
|
+
}
|
|
24081
|
+
|
|
24082
|
+
// src/hooks/session-goal/index.ts
|
|
24083
|
+
var COMMAND_NAME = "goal";
|
|
24084
|
+
var MAX_GOAL_LENGTH = 4000;
|
|
24085
|
+
function normalizeGoalText(text) {
|
|
24086
|
+
return text.trim().replace(/\s+/g, " ").slice(0, MAX_GOAL_LENGTH);
|
|
24087
|
+
}
|
|
24088
|
+
function trimGoalText(text) {
|
|
24089
|
+
return text.trim().slice(0, MAX_GOAL_LENGTH);
|
|
24090
|
+
}
|
|
24091
|
+
function pushText(output, text) {
|
|
24092
|
+
output.parts.push(createInternalAgentTextPart(text));
|
|
24093
|
+
}
|
|
24094
|
+
function formatGoal(state, inherited) {
|
|
24095
|
+
const tag = inherited ? "parent_goal" : "active_goal";
|
|
24096
|
+
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.";
|
|
24097
|
+
return `<${tag}>
|
|
24098
|
+
Objective: ${state.text}
|
|
24099
|
+
${guidance}
|
|
24100
|
+
</${tag}>`;
|
|
24101
|
+
}
|
|
24102
|
+
async function readInterviewGoal(directory, outputFolder, value) {
|
|
24103
|
+
try {
|
|
24104
|
+
const sourcePath = resolveExistingInterviewPath(directory, outputFolder, value);
|
|
24105
|
+
if (!sourcePath)
|
|
24106
|
+
return null;
|
|
24107
|
+
const content = await fs7.readFile(sourcePath, "utf8");
|
|
24108
|
+
const title = extractTitle(content);
|
|
24109
|
+
const summary = extractSummarySection(content);
|
|
24110
|
+
const text = trimGoalText([title ? `From interview: ${title}` : "", summary].filter(Boolean).join(`
|
|
24111
|
+
|
|
24112
|
+
`));
|
|
24113
|
+
return text ? { text, sourcePath } : null;
|
|
24114
|
+
} catch {
|
|
24115
|
+
return null;
|
|
24116
|
+
}
|
|
24117
|
+
}
|
|
24118
|
+
function resolveGoal(goals, sessionID) {
|
|
24119
|
+
const seen = new Set;
|
|
24120
|
+
let currentSessionID = sessionID;
|
|
24121
|
+
let inherited = false;
|
|
24122
|
+
while (true) {
|
|
24123
|
+
if (seen.has(currentSessionID)) {
|
|
24124
|
+
goals.delete(sessionID);
|
|
24125
|
+
return null;
|
|
24126
|
+
}
|
|
24127
|
+
seen.add(currentSessionID);
|
|
24128
|
+
const goal = goals.get(currentSessionID);
|
|
24129
|
+
if (!goal) {
|
|
24130
|
+
goals.delete(sessionID);
|
|
24131
|
+
return null;
|
|
24132
|
+
}
|
|
24133
|
+
if (!goal.inheritedFrom) {
|
|
24134
|
+
return { goal, inherited };
|
|
24135
|
+
}
|
|
24136
|
+
inherited = true;
|
|
24137
|
+
currentSessionID = goal.inheritedFrom;
|
|
24138
|
+
}
|
|
24139
|
+
}
|
|
24140
|
+
function createSessionGoalHook(ctx, config, options) {
|
|
24141
|
+
const goals = new Map;
|
|
24142
|
+
const outputFolder = config.interview?.outputFolder ?? "interview";
|
|
24143
|
+
return {
|
|
24144
|
+
registerCommand: (opencodeConfig) => {
|
|
24145
|
+
const commandConfig = opencodeConfig.command;
|
|
24146
|
+
if (commandConfig?.[COMMAND_NAME])
|
|
24147
|
+
return;
|
|
24148
|
+
if (!opencodeConfig.command)
|
|
24149
|
+
opencodeConfig.command = {};
|
|
24150
|
+
opencodeConfig.command[COMMAND_NAME] = {
|
|
24151
|
+
template: "Set or show the current session goal",
|
|
24152
|
+
description: "Pin a session objective that keeps todos, delegation, and verification aligned"
|
|
24153
|
+
};
|
|
24154
|
+
},
|
|
24155
|
+
handleCommandExecuteBefore: async (input, output) => {
|
|
24156
|
+
if (input.command !== COMMAND_NAME)
|
|
24157
|
+
return;
|
|
24158
|
+
output.parts.length = 0;
|
|
24159
|
+
const args = input.arguments.trim();
|
|
24160
|
+
if (!args) {
|
|
24161
|
+
const resolved = resolveGoal(goals, input.sessionID);
|
|
24162
|
+
pushText(output, resolved ? `Active goal:
|
|
24163
|
+
${resolved.goal.text}
|
|
24164
|
+
|
|
24165
|
+
Use todos for execution steps. Auto-continuation continues only while todos remain.` : "No active goal. Set one with /goal <objective>.");
|
|
24166
|
+
return;
|
|
24167
|
+
}
|
|
24168
|
+
if (args === "clear") {
|
|
24169
|
+
goals.delete(input.sessionID);
|
|
24170
|
+
pushText(output, "Cleared the active goal for this session.");
|
|
24171
|
+
return;
|
|
24172
|
+
}
|
|
24173
|
+
if (args.startsWith("from ")) {
|
|
24174
|
+
const value = args.slice("from ".length).trim();
|
|
24175
|
+
const interviewGoal = await readInterviewGoal(ctx.directory, outputFolder, value);
|
|
24176
|
+
if (!interviewGoal) {
|
|
24177
|
+
pushText(output, `Could not find a readable interview spec for "${value}".`);
|
|
24178
|
+
return;
|
|
24179
|
+
}
|
|
24180
|
+
goals.set(input.sessionID, {
|
|
24181
|
+
text: interviewGoal.text,
|
|
24182
|
+
source: "interview",
|
|
24183
|
+
sourcePath: interviewGoal.sourcePath,
|
|
24184
|
+
createdAt: Date.now()
|
|
24185
|
+
});
|
|
24186
|
+
pushText(output, `Set active goal from interview:
|
|
24187
|
+
${interviewGoal.text}`);
|
|
24188
|
+
return;
|
|
24189
|
+
}
|
|
24190
|
+
const text = normalizeGoalText(args);
|
|
24191
|
+
goals.set(input.sessionID, {
|
|
24192
|
+
text,
|
|
24193
|
+
source: "manual",
|
|
24194
|
+
createdAt: Date.now()
|
|
24195
|
+
});
|
|
24196
|
+
pushText(output, `Set active goal:
|
|
24197
|
+
${text}`);
|
|
24198
|
+
},
|
|
24199
|
+
handleEvent: (input) => {
|
|
24200
|
+
const event = input.event;
|
|
24201
|
+
if (event.type === "session.created") {
|
|
24202
|
+
const info = event.properties?.info;
|
|
24203
|
+
if (!info?.id || !info.parentID)
|
|
24204
|
+
return;
|
|
24205
|
+
const parentGoal = goals.get(info.parentID);
|
|
24206
|
+
if (!parentGoal)
|
|
24207
|
+
return;
|
|
24208
|
+
goals.set(info.id, {
|
|
24209
|
+
inheritedFrom: info.parentID,
|
|
24210
|
+
createdAt: Date.now(),
|
|
24211
|
+
text: ""
|
|
24212
|
+
});
|
|
24213
|
+
return;
|
|
24214
|
+
}
|
|
24215
|
+
if (event.type === "session.deleted") {
|
|
24216
|
+
const props = event.properties;
|
|
24217
|
+
const sessionID = props?.info?.id ?? props?.sessionID;
|
|
24218
|
+
if (sessionID)
|
|
24219
|
+
goals.delete(sessionID);
|
|
24220
|
+
}
|
|
24221
|
+
},
|
|
24222
|
+
handleSystemTransform: (input, output) => {
|
|
24223
|
+
if (!input.sessionID)
|
|
24224
|
+
return;
|
|
24225
|
+
const resolved = resolveGoal(goals, input.sessionID);
|
|
24226
|
+
if (!resolved)
|
|
24227
|
+
return;
|
|
24228
|
+
const agentName = options?.getAgentName?.(input.sessionID);
|
|
24229
|
+
const { goal, inherited } = resolved;
|
|
24230
|
+
if (!inherited && agentName && agentName !== "orchestrator")
|
|
24231
|
+
return;
|
|
24232
|
+
const block = formatGoal(goal, inherited);
|
|
24233
|
+
if (output.system.some((entry) => entry.includes(block)))
|
|
24234
|
+
return;
|
|
24235
|
+
output.system.push(block);
|
|
24236
|
+
},
|
|
24237
|
+
getGoal: (sessionID) => resolveGoal(goals, sessionID)?.goal
|
|
24238
|
+
};
|
|
24239
|
+
}
|
|
23723
24240
|
// src/hooks/task-session-manager/index.ts
|
|
23724
|
-
import
|
|
24241
|
+
import path10 from "node:path";
|
|
23725
24242
|
var AGENT_NAME_SET = new Set([
|
|
23726
24243
|
"orchestrator",
|
|
23727
24244
|
"oracle",
|
|
@@ -23746,11 +24263,11 @@ function extractPath(output) {
|
|
|
23746
24263
|
return /<path>([^<]+)<\/path>/.exec(output)?.[1];
|
|
23747
24264
|
}
|
|
23748
24265
|
function normalizePath(root, file) {
|
|
23749
|
-
const
|
|
23750
|
-
if (!
|
|
24266
|
+
const relative2 = path10.relative(root, file);
|
|
24267
|
+
if (!relative2 || relative2.startsWith("..") || path10.isAbsolute(relative2)) {
|
|
23751
24268
|
return file;
|
|
23752
24269
|
}
|
|
23753
|
-
return
|
|
24270
|
+
return relative2;
|
|
23754
24271
|
}
|
|
23755
24272
|
function extractReadFiles(root, output) {
|
|
23756
24273
|
if (typeof output.output !== "string")
|
|
@@ -23999,7 +24516,7 @@ function createTaskSessionManagerHook(_ctx, options) {
|
|
|
23999
24516
|
};
|
|
24000
24517
|
}
|
|
24001
24518
|
// src/hooks/todo-continuation/index.ts
|
|
24002
|
-
import { tool } from "@opencode-ai/plugin
|
|
24519
|
+
import { tool } from "@opencode-ai/plugin";
|
|
24003
24520
|
|
|
24004
24521
|
// src/hooks/todo-continuation/todo-hygiene.ts
|
|
24005
24522
|
var TODO_HYGIENE_REMINDER = "If the active task changed or finished, update the todo list to match the current work state.";
|
|
@@ -24138,7 +24655,7 @@ function createTodoHygiene(options) {
|
|
|
24138
24655
|
|
|
24139
24656
|
// src/hooks/todo-continuation/index.ts
|
|
24140
24657
|
var HOOK_NAME = "todo-continuation";
|
|
24141
|
-
var
|
|
24658
|
+
var COMMAND_NAME2 = "auto-continue";
|
|
24142
24659
|
var TODO_STATE_TIMEOUT_MS = 500;
|
|
24143
24660
|
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
24661
|
var TODO_HYGIENE_INSTRUCTION_OPEN = '<instruction name="todo_hygiene">';
|
|
@@ -24629,7 +25146,7 @@ function createTodoContinuationHook(ctx, config) {
|
|
|
24629
25146
|
}
|
|
24630
25147
|
}
|
|
24631
25148
|
async function handleCommandExecuteBefore(input, output) {
|
|
24632
|
-
if (input.command !==
|
|
25149
|
+
if (input.command !== COMMAND_NAME2) {
|
|
24633
25150
|
return;
|
|
24634
25151
|
}
|
|
24635
25152
|
registerOrchestratorSession(input.sessionID);
|
|
@@ -24648,11 +25165,11 @@ function createTodoContinuationHook(ctx, config) {
|
|
|
24648
25165
|
if (!newEnabled) {
|
|
24649
25166
|
cancelPendingTimer(state);
|
|
24650
25167
|
output.parts.push(createInternalAgentTextPart("[Auto-continue: disabled by user command.]"));
|
|
24651
|
-
log(`[${HOOK_NAME}] Disabled via /${
|
|
25168
|
+
log(`[${HOOK_NAME}] Disabled via /${COMMAND_NAME2} command`);
|
|
24652
25169
|
return;
|
|
24653
25170
|
}
|
|
24654
25171
|
state.suppressUntil = 0;
|
|
24655
|
-
log(`[${HOOK_NAME}] Enabled via /${
|
|
25172
|
+
log(`[${HOOK_NAME}] Enabled via /${COMMAND_NAME2} command`, {
|
|
24656
25173
|
maxContinuations
|
|
24657
25174
|
});
|
|
24658
25175
|
let hasIncompleteTodos = false;
|
|
@@ -24686,7 +25203,7 @@ import path13 from "node:path";
|
|
|
24686
25203
|
// src/interview/dashboard.ts
|
|
24687
25204
|
import crypto from "node:crypto";
|
|
24688
25205
|
import * as fsSync2 from "node:fs";
|
|
24689
|
-
import
|
|
25206
|
+
import fs8 from "node:fs/promises";
|
|
24690
25207
|
import {
|
|
24691
25208
|
createServer
|
|
24692
25209
|
} from "node:http";
|
|
@@ -24694,175 +25211,6 @@ import os4 from "node:os";
|
|
|
24694
25211
|
import path11 from "node:path";
|
|
24695
25212
|
import { URL as URL2 } from "node:url";
|
|
24696
25213
|
|
|
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
25214
|
// src/interview/helpers.ts
|
|
24867
25215
|
function sendJson(response, status, value) {
|
|
24868
25216
|
response.statusCode = status;
|
|
@@ -26507,7 +26855,7 @@ function removeAuthFile(port) {
|
|
|
26507
26855
|
}
|
|
26508
26856
|
async function readDashboardAuthFile(port) {
|
|
26509
26857
|
try {
|
|
26510
|
-
const content = await
|
|
26858
|
+
const content = await fs8.readFile(getAuthFilePath(port), "utf8");
|
|
26511
26859
|
const data = JSON.parse(content);
|
|
26512
26860
|
try {
|
|
26513
26861
|
process.kill(data.pid, 0);
|
|
@@ -26630,7 +26978,7 @@ function createDashboardServer(config) {
|
|
|
26630
26978
|
const interviewDir = path11.join(dir, config.outputFolder);
|
|
26631
26979
|
let entries;
|
|
26632
26980
|
try {
|
|
26633
|
-
entries = await
|
|
26981
|
+
entries = await fs8.readdir(interviewDir);
|
|
26634
26982
|
} catch {
|
|
26635
26983
|
continue;
|
|
26636
26984
|
}
|
|
@@ -26639,7 +26987,7 @@ function createDashboardServer(config) {
|
|
|
26639
26987
|
continue;
|
|
26640
26988
|
let content;
|
|
26641
26989
|
try {
|
|
26642
|
-
content = await
|
|
26990
|
+
content = await fs8.readFile(path11.join(interviewDir, entry), "utf8");
|
|
26643
26991
|
} catch {
|
|
26644
26992
|
continue;
|
|
26645
26993
|
}
|
|
@@ -26668,7 +27016,7 @@ function createDashboardServer(config) {
|
|
|
26668
27016
|
const interviewDir = path11.join(dir, config.outputFolder);
|
|
26669
27017
|
let entries;
|
|
26670
27018
|
try {
|
|
26671
|
-
entries = await
|
|
27019
|
+
entries = await fs8.readdir(interviewDir);
|
|
26672
27020
|
} catch {
|
|
26673
27021
|
continue;
|
|
26674
27022
|
}
|
|
@@ -26677,7 +27025,7 @@ function createDashboardServer(config) {
|
|
|
26677
27025
|
continue;
|
|
26678
27026
|
let content;
|
|
26679
27027
|
try {
|
|
26680
|
-
content = await
|
|
27028
|
+
content = await fs8.readFile(path11.join(interviewDir, entry), "utf8");
|
|
26681
27029
|
} catch {
|
|
26682
27030
|
continue;
|
|
26683
27031
|
}
|
|
@@ -26961,7 +27309,7 @@ function createDashboardServer(config) {
|
|
|
26961
27309
|
let markdownPath = entry.filePath;
|
|
26962
27310
|
if (entry.filePath) {
|
|
26963
27311
|
try {
|
|
26964
|
-
document = await
|
|
27312
|
+
document = await fs8.readFile(entry.filePath, "utf8");
|
|
26965
27313
|
} catch {}
|
|
26966
27314
|
} else {
|
|
26967
27315
|
const dirs = getKnownDirectories();
|
|
@@ -26969,7 +27317,7 @@ function createDashboardServer(config) {
|
|
|
26969
27317
|
const slug = extractResumeSlug(interviewId);
|
|
26970
27318
|
const candidate = path11.join(dir, config.outputFolder, `${slug}.md`);
|
|
26971
27319
|
try {
|
|
26972
|
-
document = await
|
|
27320
|
+
document = await fs8.readFile(candidate, "utf8");
|
|
26973
27321
|
markdownPath = candidate;
|
|
26974
27322
|
entry.filePath = candidate;
|
|
26975
27323
|
break;
|
|
@@ -27494,7 +27842,7 @@ function createInterviewServer(deps) {
|
|
|
27494
27842
|
|
|
27495
27843
|
// src/interview/service.ts
|
|
27496
27844
|
import { spawn as spawn2 } from "node:child_process";
|
|
27497
|
-
import * as
|
|
27845
|
+
import * as fs9 from "node:fs/promises";
|
|
27498
27846
|
import * as path12 from "node:path";
|
|
27499
27847
|
|
|
27500
27848
|
// src/interview/types.ts
|
|
@@ -27667,7 +28015,7 @@ function buildAnswerPrompt(answers, questions, maxQuestions) {
|
|
|
27667
28015
|
}
|
|
27668
28016
|
|
|
27669
28017
|
// src/interview/service.ts
|
|
27670
|
-
var
|
|
28018
|
+
var COMMAND_NAME3 = "interview";
|
|
27671
28019
|
var DEFAULT_MAX_QUESTIONS = 2;
|
|
27672
28020
|
function isTruthyEnvFlag(value) {
|
|
27673
28021
|
if (!value) {
|
|
@@ -27769,11 +28117,11 @@ function createInterviewService(ctx, config, deps) {
|
|
|
27769
28117
|
const dir = path12.dirname(interview.markdownPath);
|
|
27770
28118
|
const newPath = path12.join(dir, `${newSlug}.md`);
|
|
27771
28119
|
try {
|
|
27772
|
-
await
|
|
28120
|
+
await fs9.access(newPath);
|
|
27773
28121
|
return;
|
|
27774
28122
|
} catch {}
|
|
27775
28123
|
try {
|
|
27776
|
-
await
|
|
28124
|
+
await fs9.rename(interview.markdownPath, newPath);
|
|
27777
28125
|
interview.markdownPath = newPath;
|
|
27778
28126
|
log("[interview] renamed file with assistant title:", {
|
|
27779
28127
|
from: currentFileName,
|
|
@@ -27839,7 +28187,7 @@ function createInterviewService(ctx, config, deps) {
|
|
|
27839
28187
|
active.status = "abandoned";
|
|
27840
28188
|
}
|
|
27841
28189
|
}
|
|
27842
|
-
const document = await
|
|
28190
|
+
const document = await fs9.readFile(markdownPath, "utf8");
|
|
27843
28191
|
const messages = await loadMessages(sessionID);
|
|
27844
28192
|
const title = extractTitle(document);
|
|
27845
28193
|
const record = {
|
|
@@ -27914,11 +28262,11 @@ function createInterviewService(ctx, config, deps) {
|
|
|
27914
28262
|
}
|
|
27915
28263
|
function registerCommand(opencodeConfig) {
|
|
27916
28264
|
const configCommand = opencodeConfig.command;
|
|
27917
|
-
if (!configCommand?.[
|
|
28265
|
+
if (!configCommand?.[COMMAND_NAME3]) {
|
|
27918
28266
|
if (!opencodeConfig.command) {
|
|
27919
28267
|
opencodeConfig.command = {};
|
|
27920
28268
|
}
|
|
27921
|
-
opencodeConfig.command[
|
|
28269
|
+
opencodeConfig.command[COMMAND_NAME3] = {
|
|
27922
28270
|
template: "Start an interview and write a live markdown spec",
|
|
27923
28271
|
description: "Open a localhost interview UI linked to the current OpenCode session"
|
|
27924
28272
|
};
|
|
@@ -27992,7 +28340,7 @@ function createInterviewService(ctx, config, deps) {
|
|
|
27992
28340
|
}
|
|
27993
28341
|
}
|
|
27994
28342
|
async function handleCommandExecuteBefore(input, output) {
|
|
27995
|
-
if (input.command !==
|
|
28343
|
+
if (input.command !== COMMAND_NAME3) {
|
|
27996
28344
|
return;
|
|
27997
28345
|
}
|
|
27998
28346
|
const idea = input.arguments.trim();
|
|
@@ -28011,7 +28359,7 @@ function createInterviewService(ctx, config, deps) {
|
|
|
28011
28359
|
const resumePath = resolveExistingInterviewPath(ctx.directory, outputFolder, idea);
|
|
28012
28360
|
if (resumePath) {
|
|
28013
28361
|
const interview2 = await resumeInterview(input.sessionID, resumePath);
|
|
28014
|
-
const document = await
|
|
28362
|
+
const document = await fs9.readFile(interview2.markdownPath, "utf8");
|
|
28015
28363
|
await notifyInterviewUrl(input.sessionID, interview2);
|
|
28016
28364
|
output.parts.push(createInternalAgentTextPart(buildResumePrompt(document, maxQuestions)));
|
|
28017
28365
|
return;
|
|
@@ -28075,7 +28423,7 @@ function createInterviewService(ctx, config, deps) {
|
|
|
28075
28423
|
const activePaths = new Set([...interviewsById.values()].filter((i) => i.status === "active").map((i) => path12.resolve(i.markdownPath)));
|
|
28076
28424
|
let entries;
|
|
28077
28425
|
try {
|
|
28078
|
-
entries = await
|
|
28426
|
+
entries = await fs9.readdir(outputDir);
|
|
28079
28427
|
} catch {
|
|
28080
28428
|
return [];
|
|
28081
28429
|
}
|
|
@@ -28088,7 +28436,7 @@ function createInterviewService(ctx, config, deps) {
|
|
|
28088
28436
|
continue;
|
|
28089
28437
|
let content;
|
|
28090
28438
|
try {
|
|
28091
|
-
content = await
|
|
28439
|
+
content = await fs9.readFile(fullPath, "utf8");
|
|
28092
28440
|
} catch {
|
|
28093
28441
|
continue;
|
|
28094
28442
|
}
|
|
@@ -29161,29 +29509,46 @@ function startAvailabilityCheck(config) {
|
|
|
29161
29509
|
// src/multiplexer/session-manager.ts
|
|
29162
29510
|
var SESSION_TIMEOUT_MS = 10 * 60 * 1000;
|
|
29163
29511
|
var SESSION_MISSING_GRACE_MS = POLL_INTERVAL_BACKGROUND_MS * 3;
|
|
29164
|
-
|
|
29512
|
+
var SHARED_STATE_KEY = Symbol.for("oh-my-opencode-slim.multiplexer-session-manager.state");
|
|
29513
|
+
function getSharedState() {
|
|
29514
|
+
const globalWithState = globalThis;
|
|
29515
|
+
globalWithState[SHARED_STATE_KEY] ??= {
|
|
29516
|
+
sessions: new Map,
|
|
29517
|
+
knownSessions: new Map,
|
|
29518
|
+
spawningSessions: new Set,
|
|
29519
|
+
closingSessions: new Map
|
|
29520
|
+
};
|
|
29521
|
+
return globalWithState[SHARED_STATE_KEY];
|
|
29522
|
+
}
|
|
29165
29523
|
class MultiplexerSessionManager {
|
|
29166
|
-
|
|
29524
|
+
instanceId = Math.random().toString(36).slice(2, 8);
|
|
29167
29525
|
serverUrl;
|
|
29168
29526
|
directory;
|
|
29169
29527
|
multiplexer = null;
|
|
29170
|
-
sessions
|
|
29171
|
-
knownSessions
|
|
29172
|
-
spawningSessions
|
|
29173
|
-
closingSessions
|
|
29528
|
+
sessions;
|
|
29529
|
+
knownSessions;
|
|
29530
|
+
spawningSessions;
|
|
29531
|
+
closingSessions;
|
|
29174
29532
|
pollInterval;
|
|
29175
29533
|
enabled = false;
|
|
29176
29534
|
constructor(ctx, config) {
|
|
29177
|
-
|
|
29535
|
+
const sharedState = getSharedState();
|
|
29536
|
+
this.sessions = sharedState.sessions;
|
|
29537
|
+
this.knownSessions = sharedState.knownSessions;
|
|
29538
|
+
this.spawningSessions = sharedState.spawningSessions;
|
|
29539
|
+
this.closingSessions = sharedState.closingSessions;
|
|
29178
29540
|
this.directory = ctx.directory;
|
|
29179
29541
|
const defaultPort = process.env.OPENCODE_PORT ?? "4096";
|
|
29180
29542
|
this.serverUrl = ctx.serverUrl?.toString() ?? `http://localhost:${defaultPort}`;
|
|
29181
29543
|
this.multiplexer = getMultiplexer(config);
|
|
29182
29544
|
this.enabled = config.type !== "none" && this.multiplexer !== null && this.multiplexer.isInsideSession();
|
|
29183
29545
|
log("[multiplexer-session-manager] initialized", {
|
|
29546
|
+
instanceId: this.instanceId,
|
|
29184
29547
|
enabled: this.enabled,
|
|
29185
29548
|
type: config.type,
|
|
29186
|
-
serverUrl: this.serverUrl
|
|
29549
|
+
serverUrl: this.serverUrl,
|
|
29550
|
+
trackedSessions: this.sessions.size,
|
|
29551
|
+
knownSessions: this.knownSessions.size
|
|
29187
29552
|
});
|
|
29188
29553
|
}
|
|
29189
29554
|
async onSessionCreated(event) {
|
|
@@ -29201,6 +29566,7 @@ class MultiplexerSessionManager {
|
|
|
29201
29566
|
const directory = info.directory ?? this.directory;
|
|
29202
29567
|
if (this.isTrackedOrSpawning(sessionId)) {
|
|
29203
29568
|
log("[multiplexer-session-manager] session already tracked or spawning", {
|
|
29569
|
+
instanceId: this.instanceId,
|
|
29204
29570
|
sessionId
|
|
29205
29571
|
});
|
|
29206
29572
|
return;
|
|
@@ -29220,6 +29586,7 @@ class MultiplexerSessionManager {
|
|
|
29220
29586
|
const serverRunning = await isServerRunning(this.serverUrl);
|
|
29221
29587
|
if (!serverRunning) {
|
|
29222
29588
|
log("[multiplexer-session-manager] server not running, skipping", {
|
|
29589
|
+
instanceId: this.instanceId,
|
|
29223
29590
|
serverUrl: this.serverUrl
|
|
29224
29591
|
});
|
|
29225
29592
|
return;
|
|
@@ -29230,10 +29597,12 @@ class MultiplexerSessionManager {
|
|
|
29230
29597
|
log("[multiplexer-session-manager] child session created, spawning pane", {
|
|
29231
29598
|
sessionId,
|
|
29232
29599
|
parentId,
|
|
29233
|
-
title
|
|
29600
|
+
title,
|
|
29601
|
+
instanceId: this.instanceId
|
|
29234
29602
|
});
|
|
29235
29603
|
const paneResult = await this.multiplexer.spawnPane(sessionId, title, this.serverUrl, directory).catch((err) => {
|
|
29236
29604
|
log("[multiplexer-session-manager] failed to spawn pane", {
|
|
29605
|
+
instanceId: this.instanceId,
|
|
29237
29606
|
error: String(err)
|
|
29238
29607
|
});
|
|
29239
29608
|
return { success: false, paneId: undefined };
|
|
@@ -29244,6 +29613,7 @@ class MultiplexerSessionManager {
|
|
|
29244
29613
|
await this.multiplexer.closePane(paneResult.paneId).catch((err) => log("[multiplexer-session-manager] closing stale spawned pane failed", {
|
|
29245
29614
|
sessionId,
|
|
29246
29615
|
paneId: paneResult.paneId,
|
|
29616
|
+
instanceId: this.instanceId,
|
|
29247
29617
|
error: String(err)
|
|
29248
29618
|
}));
|
|
29249
29619
|
return;
|
|
@@ -29256,9 +29626,11 @@ class MultiplexerSessionManager {
|
|
|
29256
29626
|
title,
|
|
29257
29627
|
directory,
|
|
29258
29628
|
createdAt: now,
|
|
29259
|
-
lastSeenAt: now
|
|
29629
|
+
lastSeenAt: now,
|
|
29630
|
+
seenInStatus: false
|
|
29260
29631
|
});
|
|
29261
29632
|
log("[multiplexer-session-manager] pane spawned", {
|
|
29633
|
+
instanceId: this.instanceId,
|
|
29262
29634
|
sessionId,
|
|
29263
29635
|
paneId: paneResult.paneId
|
|
29264
29636
|
});
|
|
@@ -29270,6 +29642,19 @@ class MultiplexerSessionManager {
|
|
|
29270
29642
|
async onSessionStatus(event) {
|
|
29271
29643
|
if (!this.enabled)
|
|
29272
29644
|
return;
|
|
29645
|
+
if (event.type === "session.idle") {
|
|
29646
|
+
const sessionId2 = event.properties?.sessionID;
|
|
29647
|
+
if (!sessionId2)
|
|
29648
|
+
return;
|
|
29649
|
+
log("[multiplexer-session-manager] session idle event received", {
|
|
29650
|
+
instanceId: this.instanceId,
|
|
29651
|
+
sessionId: sessionId2,
|
|
29652
|
+
tracked: this.sessions.has(sessionId2),
|
|
29653
|
+
known: this.knownSessions.has(sessionId2)
|
|
29654
|
+
});
|
|
29655
|
+
await this.closeSession(sessionId2, "idle");
|
|
29656
|
+
return;
|
|
29657
|
+
}
|
|
29273
29658
|
if (event.type !== "session.status")
|
|
29274
29659
|
return;
|
|
29275
29660
|
const sessionId = event.properties?.sessionID;
|
|
@@ -29280,6 +29665,12 @@ class MultiplexerSessionManager {
|
|
|
29280
29665
|
return;
|
|
29281
29666
|
}
|
|
29282
29667
|
if (event.properties?.status?.type === "busy") {
|
|
29668
|
+
log("[multiplexer-session-manager] session busy event received", {
|
|
29669
|
+
instanceId: this.instanceId,
|
|
29670
|
+
sessionId,
|
|
29671
|
+
tracked: this.sessions.has(sessionId),
|
|
29672
|
+
known: this.knownSessions.has(sessionId)
|
|
29673
|
+
});
|
|
29283
29674
|
await this.respawnIfKnown(sessionId);
|
|
29284
29675
|
}
|
|
29285
29676
|
}
|
|
@@ -29292,6 +29683,7 @@ class MultiplexerSessionManager {
|
|
|
29292
29683
|
if (!sessionId)
|
|
29293
29684
|
return;
|
|
29294
29685
|
log("[multiplexer-session-manager] session deleted, closing pane", {
|
|
29686
|
+
instanceId: this.instanceId,
|
|
29295
29687
|
sessionId
|
|
29296
29688
|
});
|
|
29297
29689
|
await this.closeSession(sessionId, "deleted");
|
|
@@ -29300,13 +29692,17 @@ class MultiplexerSessionManager {
|
|
|
29300
29692
|
if (this.pollInterval)
|
|
29301
29693
|
return;
|
|
29302
29694
|
this.pollInterval = setInterval(() => this.pollSessions(), POLL_INTERVAL_BACKGROUND_MS);
|
|
29303
|
-
log("[multiplexer-session-manager] polling started"
|
|
29695
|
+
log("[multiplexer-session-manager] polling started", {
|
|
29696
|
+
instanceId: this.instanceId
|
|
29697
|
+
});
|
|
29304
29698
|
}
|
|
29305
29699
|
stopPolling() {
|
|
29306
29700
|
if (this.pollInterval) {
|
|
29307
29701
|
clearInterval(this.pollInterval);
|
|
29308
29702
|
this.pollInterval = undefined;
|
|
29309
|
-
log("[multiplexer-session-manager] polling stopped"
|
|
29703
|
+
log("[multiplexer-session-manager] polling stopped", {
|
|
29704
|
+
instanceId: this.instanceId
|
|
29705
|
+
});
|
|
29310
29706
|
}
|
|
29311
29707
|
}
|
|
29312
29708
|
async pollSessions() {
|
|
@@ -29315,8 +29711,7 @@ class MultiplexerSessionManager {
|
|
|
29315
29711
|
return;
|
|
29316
29712
|
}
|
|
29317
29713
|
try {
|
|
29318
|
-
const
|
|
29319
|
-
const allStatuses = statusResult.data ?? {};
|
|
29714
|
+
const allStatuses = await this.fetchSessionStatuses();
|
|
29320
29715
|
const now = Date.now();
|
|
29321
29716
|
const sessionsToClose = [];
|
|
29322
29717
|
for (const [sessionId, tracked] of this.sessions.entries()) {
|
|
@@ -29324,11 +29719,12 @@ class MultiplexerSessionManager {
|
|
|
29324
29719
|
const isIdle = status?.type === "idle";
|
|
29325
29720
|
if (status) {
|
|
29326
29721
|
tracked.lastSeenAt = now;
|
|
29722
|
+
tracked.seenInStatus = true;
|
|
29327
29723
|
tracked.missingSince = undefined;
|
|
29328
29724
|
} else if (!tracked.missingSince) {
|
|
29329
29725
|
tracked.missingSince = now;
|
|
29330
29726
|
}
|
|
29331
|
-
const missingTooLong = !!tracked.missingSince && now - tracked.missingSince >= SESSION_MISSING_GRACE_MS;
|
|
29727
|
+
const missingTooLong = tracked.seenInStatus && !!tracked.missingSince && now - tracked.missingSince >= SESSION_MISSING_GRACE_MS;
|
|
29332
29728
|
const isTimedOut = now - tracked.createdAt > SESSION_TIMEOUT_MS;
|
|
29333
29729
|
if (isIdle || missingTooLong || isTimedOut) {
|
|
29334
29730
|
sessionsToClose.push({
|
|
@@ -29344,6 +29740,14 @@ class MultiplexerSessionManager {
|
|
|
29344
29740
|
log("[multiplexer-session-manager] poll error", { error: String(err) });
|
|
29345
29741
|
}
|
|
29346
29742
|
}
|
|
29743
|
+
async fetchSessionStatuses() {
|
|
29744
|
+
const url = new URL("/session/status", this.serverUrl);
|
|
29745
|
+
const response = await fetch(url, { signal: AbortSignal.timeout(2000) });
|
|
29746
|
+
if (!response.ok) {
|
|
29747
|
+
throw new Error(`session status request failed: ${response.status} ${response.statusText}`);
|
|
29748
|
+
}
|
|
29749
|
+
return await response.json();
|
|
29750
|
+
}
|
|
29347
29751
|
async closeSession(sessionId, reason) {
|
|
29348
29752
|
if (reason === "deleted") {
|
|
29349
29753
|
this.knownSessions.delete(sessionId);
|
|
@@ -29352,10 +29756,19 @@ class MultiplexerSessionManager {
|
|
|
29352
29756
|
if (existingClose)
|
|
29353
29757
|
return existingClose;
|
|
29354
29758
|
const tracked = this.sessions.get(sessionId);
|
|
29355
|
-
if (!tracked || !this.multiplexer)
|
|
29759
|
+
if (!tracked || !this.multiplexer) {
|
|
29760
|
+
log("[multiplexer-session-manager] close skipped; session not tracked", {
|
|
29761
|
+
instanceId: this.instanceId,
|
|
29762
|
+
sessionId,
|
|
29763
|
+
reason,
|
|
29764
|
+
tracked: !!tracked,
|
|
29765
|
+
hasMultiplexer: !!this.multiplexer
|
|
29766
|
+
});
|
|
29356
29767
|
return;
|
|
29768
|
+
}
|
|
29357
29769
|
this.sessions.delete(sessionId);
|
|
29358
29770
|
log("[multiplexer-session-manager] closing session pane", {
|
|
29771
|
+
instanceId: this.instanceId,
|
|
29359
29772
|
sessionId,
|
|
29360
29773
|
paneId: tracked.paneId,
|
|
29361
29774
|
reason
|
|
@@ -29363,6 +29776,7 @@ class MultiplexerSessionManager {
|
|
|
29363
29776
|
const closePromise = this.multiplexer.closePane(tracked.paneId).then(() => {
|
|
29364
29777
|
return;
|
|
29365
29778
|
}).catch((err) => log("[multiplexer-session-manager] failed to close session pane", {
|
|
29779
|
+
instanceId: this.instanceId,
|
|
29366
29780
|
sessionId,
|
|
29367
29781
|
paneId: tracked.paneId,
|
|
29368
29782
|
reason,
|
|
@@ -29391,6 +29805,7 @@ class MultiplexerSessionManager {
|
|
|
29391
29805
|
const serverRunning = await isServerRunning(this.serverUrl);
|
|
29392
29806
|
if (!serverRunning) {
|
|
29393
29807
|
log("[multiplexer-session-manager] server not running, skipping busy respawn", {
|
|
29808
|
+
instanceId: this.instanceId,
|
|
29394
29809
|
serverUrl: this.serverUrl,
|
|
29395
29810
|
sessionId
|
|
29396
29811
|
});
|
|
@@ -29400,12 +29815,14 @@ class MultiplexerSessionManager {
|
|
|
29400
29815
|
return;
|
|
29401
29816
|
}
|
|
29402
29817
|
log("[multiplexer-session-manager] child session busy again, respawning pane", {
|
|
29818
|
+
instanceId: this.instanceId,
|
|
29403
29819
|
sessionId,
|
|
29404
29820
|
parentId: known.parentId,
|
|
29405
29821
|
title: known.title
|
|
29406
29822
|
});
|
|
29407
29823
|
const paneResult = await this.multiplexer.spawnPane(sessionId, known.title, this.serverUrl, known.directory).catch((err) => {
|
|
29408
29824
|
log("[multiplexer-session-manager] failed to respawn pane", {
|
|
29825
|
+
instanceId: this.instanceId,
|
|
29409
29826
|
error: String(err)
|
|
29410
29827
|
});
|
|
29411
29828
|
return { success: false, paneId: undefined };
|
|
@@ -29414,6 +29831,7 @@ class MultiplexerSessionManager {
|
|
|
29414
29831
|
return;
|
|
29415
29832
|
if (!this.knownSessions.has(sessionId) || this.closingSessions.has(sessionId)) {
|
|
29416
29833
|
await this.multiplexer.closePane(paneResult.paneId).catch((err) => log("[multiplexer-session-manager] closing stale respawned pane failed", {
|
|
29834
|
+
instanceId: this.instanceId,
|
|
29417
29835
|
sessionId,
|
|
29418
29836
|
paneId: paneResult.paneId,
|
|
29419
29837
|
error: String(err)
|
|
@@ -29428,9 +29846,11 @@ class MultiplexerSessionManager {
|
|
|
29428
29846
|
title: known.title,
|
|
29429
29847
|
directory: known.directory,
|
|
29430
29848
|
createdAt: now,
|
|
29431
|
-
lastSeenAt: now
|
|
29849
|
+
lastSeenAt: now,
|
|
29850
|
+
seenInStatus: false
|
|
29432
29851
|
});
|
|
29433
29852
|
log("[multiplexer-session-manager] pane respawned on busy", {
|
|
29853
|
+
instanceId: this.instanceId,
|
|
29434
29854
|
sessionId,
|
|
29435
29855
|
paneId: paneResult.paneId
|
|
29436
29856
|
});
|
|
@@ -29497,7 +29917,7 @@ async function isServerRunning(serverUrl, timeoutMs = 3000, maxAttempts = 2) {
|
|
|
29497
29917
|
return false;
|
|
29498
29918
|
}
|
|
29499
29919
|
// src/tools/ast-grep/tools.ts
|
|
29500
|
-
import { tool as tool2 } from "@opencode-ai/plugin
|
|
29920
|
+
import { tool as tool2 } from "@opencode-ai/plugin";
|
|
29501
29921
|
|
|
29502
29922
|
// src/tools/ast-grep/cli.ts
|
|
29503
29923
|
import { existsSync as existsSync9 } from "node:fs";
|
|
@@ -30108,8 +30528,11 @@ Returns the councillor responses with a summary footer.`,
|
|
|
30108
30528
|
});
|
|
30109
30529
|
return { council_session };
|
|
30110
30530
|
}
|
|
30531
|
+
// src/tools/preset-manager.ts
|
|
30532
|
+
import * as fs11 from "node:fs";
|
|
30533
|
+
|
|
30111
30534
|
// src/tui-state.ts
|
|
30112
|
-
import * as
|
|
30535
|
+
import * as fs10 from "node:fs";
|
|
30113
30536
|
import * as os5 from "node:os";
|
|
30114
30537
|
import * as path14 from "node:path";
|
|
30115
30538
|
var STATE_DIR = "oh-my-opencode-slim";
|
|
@@ -30139,14 +30562,14 @@ function parseSnapshot(value) {
|
|
|
30139
30562
|
}
|
|
30140
30563
|
function readTuiSnapshot() {
|
|
30141
30564
|
try {
|
|
30142
|
-
return parseSnapshot(
|
|
30565
|
+
return parseSnapshot(fs10.readFileSync(getTuiStatePath(), "utf8"));
|
|
30143
30566
|
} catch {
|
|
30144
30567
|
return emptySnapshot();
|
|
30145
30568
|
}
|
|
30146
30569
|
}
|
|
30147
30570
|
async function readTuiSnapshotAsync() {
|
|
30148
30571
|
try {
|
|
30149
|
-
return parseSnapshot(await
|
|
30572
|
+
return parseSnapshot(await fs10.promises.readFile(getTuiStatePath(), "utf8"));
|
|
30150
30573
|
} catch {
|
|
30151
30574
|
return emptySnapshot();
|
|
30152
30575
|
}
|
|
@@ -30154,8 +30577,8 @@ async function readTuiSnapshotAsync() {
|
|
|
30154
30577
|
function writeTuiSnapshot(snapshot) {
|
|
30155
30578
|
try {
|
|
30156
30579
|
const filePath = getTuiStatePath();
|
|
30157
|
-
|
|
30158
|
-
|
|
30580
|
+
fs10.mkdirSync(path14.dirname(filePath), { recursive: true });
|
|
30581
|
+
fs10.writeFileSync(filePath, `${JSON.stringify(snapshot)}
|
|
30159
30582
|
`);
|
|
30160
30583
|
} catch {}
|
|
30161
30584
|
}
|
|
@@ -30177,11 +30600,11 @@ function recordTuiAgentModel(input) {
|
|
|
30177
30600
|
}
|
|
30178
30601
|
|
|
30179
30602
|
// src/tools/preset-manager.ts
|
|
30180
|
-
var
|
|
30603
|
+
var COMMAND_NAME4 = "preset";
|
|
30181
30604
|
function createPresetManager(ctx, config) {
|
|
30182
30605
|
let activePreset = getActiveRuntimePreset() ?? config.preset ?? null;
|
|
30183
30606
|
async function handleCommandExecuteBefore(input, output) {
|
|
30184
|
-
if (input.command !==
|
|
30607
|
+
if (input.command !== COMMAND_NAME4) {
|
|
30185
30608
|
return;
|
|
30186
30609
|
}
|
|
30187
30610
|
output.parts.length = 0;
|
|
@@ -30200,11 +30623,11 @@ function createPresetManager(ctx, config) {
|
|
|
30200
30623
|
}
|
|
30201
30624
|
function registerCommand(opencodeConfig) {
|
|
30202
30625
|
const configCommand = opencodeConfig.command;
|
|
30203
|
-
if (!configCommand?.[
|
|
30626
|
+
if (!configCommand?.[COMMAND_NAME4]) {
|
|
30204
30627
|
if (!opencodeConfig.command) {
|
|
30205
30628
|
opencodeConfig.command = {};
|
|
30206
30629
|
}
|
|
30207
|
-
opencodeConfig.command[
|
|
30630
|
+
opencodeConfig.command[COMMAND_NAME4] = {
|
|
30208
30631
|
template: "List available presets and switch between them",
|
|
30209
30632
|
description: "Switch agent presets at runtime (e.g., /preset cheap, /preset powerful)"
|
|
30210
30633
|
};
|
|
@@ -30226,64 +30649,47 @@ function createPresetManager(ctx, config) {
|
|
|
30226
30649
|
agentUpdates[resolvedName] = agentConfig;
|
|
30227
30650
|
}
|
|
30228
30651
|
}
|
|
30229
|
-
const currentRuntimePreset = getActiveRuntimePreset();
|
|
30230
|
-
const resetUpdates = {};
|
|
30231
|
-
if (currentRuntimePreset && config.presets?.[currentRuntimePreset]) {
|
|
30232
|
-
const oldPreset = config.presets[currentRuntimePreset];
|
|
30233
|
-
for (const rawName of Object.keys(oldPreset)) {
|
|
30234
|
-
const resolvedOld = AGENT_ALIASES[rawName] ?? rawName;
|
|
30235
|
-
if (resolvedOld in agentUpdates)
|
|
30236
|
-
continue;
|
|
30237
|
-
const baseline = config.agents?.[resolvedOld];
|
|
30238
|
-
if (baseline) {
|
|
30239
|
-
resetUpdates[resolvedOld] = mapOverrideToAgentConfig(baseline);
|
|
30240
|
-
}
|
|
30241
|
-
}
|
|
30242
|
-
}
|
|
30243
30652
|
const hasAgentUpdates = Object.keys(agentUpdates).length > 0;
|
|
30244
|
-
const allUpdates = { ...resetUpdates, ...agentUpdates };
|
|
30245
30653
|
if (!hasAgentUpdates) {
|
|
30246
30654
|
output.parts.push(createInternalAgentTextPart(`Preset "${presetName}" is empty (no agent overrides defined).`));
|
|
30247
30655
|
return;
|
|
30248
30656
|
}
|
|
30249
|
-
const previousPreset = activePreset;
|
|
30250
30657
|
setActiveRuntimePresetWithPrevious(presetName);
|
|
30251
30658
|
try {
|
|
30252
|
-
|
|
30253
|
-
|
|
30254
|
-
|
|
30255
|
-
|
|
30256
|
-
|
|
30257
|
-
|
|
30258
|
-
|
|
30259
|
-
|
|
30260
|
-
|
|
30261
|
-
|
|
30262
|
-
|
|
30263
|
-
|
|
30264
|
-
|
|
30265
|
-
|
|
30266
|
-
|
|
30267
|
-
|
|
30268
|
-
|
|
30269
|
-
|
|
30270
|
-
|
|
30271
|
-
|
|
30272
|
-
|
|
30273
|
-
|
|
30274
|
-
|
|
30275
|
-
|
|
30276
|
-
|
|
30277
|
-
if (
|
|
30278
|
-
|
|
30279
|
-
|
|
30280
|
-
|
|
30659
|
+
const { userConfigPath } = findPluginConfigPaths(ctx.directory);
|
|
30660
|
+
if (userConfigPath) {
|
|
30661
|
+
const raw = fs11.readFileSync(userConfigPath, "utf-8");
|
|
30662
|
+
const persisted = JSON.parse(stripJsonComments(raw));
|
|
30663
|
+
persisted.preset = presetName;
|
|
30664
|
+
fs11.writeFileSync(userConfigPath, `${JSON.stringify(persisted, null, 2)}
|
|
30665
|
+
`);
|
|
30666
|
+
}
|
|
30667
|
+
} catch {}
|
|
30668
|
+
const snapshot = readTuiSnapshot();
|
|
30669
|
+
const agentModels = { ...snapshot.agentModels };
|
|
30670
|
+
for (const [agentName, agentConfig] of Object.entries(agentUpdates)) {
|
|
30671
|
+
if (typeof agentConfig.model === "string") {
|
|
30672
|
+
agentModels[agentName] = agentConfig.model;
|
|
30673
|
+
}
|
|
30674
|
+
}
|
|
30675
|
+
recordTuiAgentModels({ agentModels });
|
|
30676
|
+
activePreset = presetName;
|
|
30677
|
+
const summaryParts = [];
|
|
30678
|
+
for (const [name, cfg] of Object.entries(agentUpdates)) {
|
|
30679
|
+
const parts = [name];
|
|
30680
|
+
if (cfg.model)
|
|
30681
|
+
parts.push(`model: ${cfg.model}`);
|
|
30682
|
+
if (cfg.variant)
|
|
30683
|
+
parts.push(`variant: ${cfg.variant}`);
|
|
30684
|
+
if (cfg.temperature !== undefined)
|
|
30685
|
+
parts.push(`temp: ${cfg.temperature}`);
|
|
30686
|
+
if (cfg.options)
|
|
30687
|
+
parts.push("options: yes");
|
|
30688
|
+
summaryParts.push(parts.join(" → "));
|
|
30689
|
+
}
|
|
30690
|
+
output.parts.push(createInternalAgentTextPart(`Saved preset "${presetName}". Restart or reload OpenCode to apply it to agent configuration. The current session was not reloaded to avoid interrupting the active conversation.
|
|
30281
30691
|
${summaryParts.join(`
|
|
30282
30692
|
`)}`));
|
|
30283
|
-
} catch (err) {
|
|
30284
|
-
rollbackRuntimePreset(previousPreset);
|
|
30285
|
-
output.parts.push(createInternalAgentTextPart(`Failed to switch preset "${presetName}": ${String(err)}`));
|
|
30286
|
-
}
|
|
30287
30693
|
}
|
|
30288
30694
|
function mapOverrideToAgentConfig(override) {
|
|
30289
30695
|
const agentConfig = {};
|
|
@@ -30416,21 +30822,21 @@ async function saveBinary(binaryDir, data, contentType, filename) {
|
|
|
30416
30822
|
throw new Error("Unable to allocate unique filename for binary content");
|
|
30417
30823
|
}
|
|
30418
30824
|
|
|
30419
|
-
// node_modules/lru-cache/dist/esm/node/index.min.js
|
|
30420
|
-
import { tracingChannel as
|
|
30421
|
-
var S =
|
|
30422
|
-
var W =
|
|
30825
|
+
// node_modules/.pnpm/lru-cache@11.3.6/node_modules/lru-cache/dist/esm/node/index.min.js
|
|
30826
|
+
import { tracingChannel as I, channel as G } from "node:diagnostics_channel";
|
|
30827
|
+
var S = G("lru-cache:metrics");
|
|
30828
|
+
var W = I("lru-cache");
|
|
30829
|
+
var C = typeof performance == "object" && performance && typeof performance.now == "function" ? performance : Date;
|
|
30423
30830
|
var D = () => S.hasSubscribers || W.hasSubscribers;
|
|
30424
|
-
var
|
|
30425
|
-
var
|
|
30426
|
-
var C = typeof process == "object" && process ? process : {};
|
|
30831
|
+
var U = new Set;
|
|
30832
|
+
var L = typeof process == "object" && process ? process : {};
|
|
30427
30833
|
var P = (u, e, t, i) => {
|
|
30428
|
-
typeof
|
|
30834
|
+
typeof L.emitWarning == "function" ? L.emitWarning(u, e, t, i) : console.error(`[${t}] ${e}: ${u}`);
|
|
30429
30835
|
};
|
|
30430
|
-
var H = (u) => !
|
|
30431
|
-
var
|
|
30836
|
+
var H = (u) => !U.has(u);
|
|
30837
|
+
var X = Symbol("type");
|
|
30432
30838
|
var F = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u);
|
|
30433
|
-
var
|
|
30839
|
+
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
30840
|
var O = class extends Array {
|
|
30435
30841
|
constructor(e) {
|
|
30436
30842
|
super(e), this.fill(0);
|
|
@@ -30441,7 +30847,7 @@ var R = class u {
|
|
|
30441
30847
|
length;
|
|
30442
30848
|
static #o = false;
|
|
30443
30849
|
static create(e) {
|
|
30444
|
-
let t =
|
|
30850
|
+
let t = j(e);
|
|
30445
30851
|
if (!t)
|
|
30446
30852
|
return [];
|
|
30447
30853
|
u.#o = true;
|
|
@@ -30460,11 +30866,11 @@ var R = class u {
|
|
|
30460
30866
|
return this.heap[--this.length];
|
|
30461
30867
|
}
|
|
30462
30868
|
};
|
|
30463
|
-
var
|
|
30869
|
+
var M = class u2 {
|
|
30464
30870
|
#o;
|
|
30465
30871
|
#u;
|
|
30466
30872
|
#w;
|
|
30467
|
-
#
|
|
30873
|
+
#x;
|
|
30468
30874
|
#S;
|
|
30469
30875
|
#M;
|
|
30470
30876
|
#U;
|
|
@@ -30535,7 +30941,7 @@ var L = class u2 {
|
|
|
30535
30941
|
return this.#w;
|
|
30536
30942
|
}
|
|
30537
30943
|
get onInsert() {
|
|
30538
|
-
return this.#
|
|
30944
|
+
return this.#x;
|
|
30539
30945
|
}
|
|
30540
30946
|
get disposeAfter() {
|
|
30541
30947
|
return this.#S;
|
|
@@ -30544,9 +30950,9 @@ var L = class u2 {
|
|
|
30544
30950
|
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
30951
|
if (x !== undefined && typeof x?.now != "function")
|
|
30546
30952
|
throw new TypeError("perf option must have a now() method if specified");
|
|
30547
|
-
if (this.#m = x ??
|
|
30953
|
+
if (this.#m = x ?? C, t !== 0 && !F(t))
|
|
30548
30954
|
throw new TypeError("max option must be a nonnegative integer");
|
|
30549
|
-
let v = t ?
|
|
30955
|
+
let v = t ? j(t) : Array;
|
|
30550
30956
|
if (!v)
|
|
30551
30957
|
throw new Error("invalid max value: " + t);
|
|
30552
30958
|
if (this.#o = t, this.#u = T, this.maxEntrySize = w || this.#u, this.sizeCalculation = y, this.sizeCalculation) {
|
|
@@ -30559,7 +30965,7 @@ var L = class u2 {
|
|
|
30559
30965
|
throw new TypeError("memoMethod must be a function if defined");
|
|
30560
30966
|
if (this.#U = m, a !== undefined && typeof a != "function")
|
|
30561
30967
|
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.#
|
|
30968
|
+
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
30969
|
if (this.#u !== 0 && !F(this.#u))
|
|
30564
30970
|
throw new TypeError("maxSize must be a positive integer if specified");
|
|
30565
30971
|
if (!F(this.maxEntrySize))
|
|
@@ -30575,7 +30981,7 @@ var L = class u2 {
|
|
|
30575
30981
|
throw new TypeError("At least one of max, maxSize, or ttl is required");
|
|
30576
30982
|
if (!this.ttlAutopurge && !this.#o && !this.#u) {
|
|
30577
30983
|
let E = "LRU_CACHE_UNBOUNDED";
|
|
30578
|
-
H(E) && (
|
|
30984
|
+
H(E) && (U.add(E), P("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.", "UnboundedCacheWarning", E, u2));
|
|
30579
30985
|
}
|
|
30580
30986
|
}
|
|
30581
30987
|
getRemainingTTL(e) {
|
|
@@ -30587,7 +30993,7 @@ var L = class u2 {
|
|
|
30587
30993
|
let i = this.ttlAutopurge ? Array.from({ length: this.#o }) : undefined;
|
|
30588
30994
|
this.#g = i, this.#N = (r, h, l = this.#m.now()) => {
|
|
30589
30995
|
t[r] = h !== 0 ? l : 0, e[r] = h, s(r, h);
|
|
30590
|
-
}, this.#
|
|
30996
|
+
}, this.#D = (r) => {
|
|
30591
30997
|
t[r] = e[r] !== 0 ? this.#m.now() : 0, s(r, e[r]);
|
|
30592
30998
|
};
|
|
30593
30999
|
let s = this.ttlAutopurge ? (r, h) => {
|
|
@@ -30631,7 +31037,7 @@ var L = class u2 {
|
|
|
30631
31037
|
return !!l && !!h && (n || o()) - h > l;
|
|
30632
31038
|
};
|
|
30633
31039
|
}
|
|
30634
|
-
#
|
|
31040
|
+
#D = () => {};
|
|
30635
31041
|
#E = () => {};
|
|
30636
31042
|
#N = () => {};
|
|
30637
31043
|
#p = () => false;
|
|
@@ -30797,7 +31203,7 @@ var L = class u2 {
|
|
|
30797
31203
|
return this.#v(e, "set"), h && (h.set = "miss", h.maxEntrySizeExceeded = true), this;
|
|
30798
31204
|
let f = this.#n === 0 ? undefined : this.#s.get(e);
|
|
30799
31205
|
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.#
|
|
31206
|
+
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
31207
|
else {
|
|
30802
31208
|
this.#L(f);
|
|
30803
31209
|
let g = this.#t[f];
|
|
@@ -30861,7 +31267,7 @@ var L = class u2 {
|
|
|
30861
31267
|
if (this.#p(n))
|
|
30862
31268
|
s && (s.has = "stale", this.#E(s, n));
|
|
30863
31269
|
else
|
|
30864
|
-
return i && this.#
|
|
31270
|
+
return i && this.#D(n), s && (s.has = "hit", this.#E(s, n)), true;
|
|
30865
31271
|
} else
|
|
30866
31272
|
s && (s.has = "miss");
|
|
30867
31273
|
return false;
|
|
@@ -30919,7 +31325,7 @@ var L = class u2 {
|
|
|
30919
31325
|
let i = W.hasSubscribers, { status: s = D() ? {} : undefined } = t;
|
|
30920
31326
|
t.status = s, s && t.context && (s.context = t.context);
|
|
30921
31327
|
let n = this.#B(e, t);
|
|
30922
|
-
return s &&
|
|
31328
|
+
return s && i && (s.trace = true, W.tracePromise(() => n, s).catch(() => {})), n;
|
|
30923
31329
|
}
|
|
30924
31330
|
async#B(e, t = {}) {
|
|
30925
31331
|
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 +31344,7 @@ var L = class u2 {
|
|
|
30938
31344
|
}
|
|
30939
31345
|
let A = this.#p(b);
|
|
30940
31346
|
if (!y && !A)
|
|
30941
|
-
return a && (a.fetch = "hit"), this.#L(b), s && this.#
|
|
31347
|
+
return a && (a.fetch = "hit"), this.#L(b), s && this.#D(b), a && this.#E(a, b), d;
|
|
30942
31348
|
let z5 = this.#P(e, b, _, w), v = z5.__staleWhileFetching !== undefined && i;
|
|
30943
31349
|
return a && (a.fetch = A ? "stale" : "refresh", v && A && (a.returnedStale = true)), v ? z5.__staleWhileFetching : z5.__returned = z5;
|
|
30944
31350
|
}
|
|
@@ -30947,7 +31353,7 @@ var L = class u2 {
|
|
|
30947
31353
|
let i = W.hasSubscribers, { status: s = D() ? {} : undefined } = t;
|
|
30948
31354
|
t.status = s, s && t.context && (s.context = t.context);
|
|
30949
31355
|
let n = this.#K(e, t);
|
|
30950
|
-
return s &&
|
|
31356
|
+
return s && i && (s.trace = true, W.tracePromise(() => n, s).catch(() => {})), n;
|
|
30951
31357
|
}
|
|
30952
31358
|
async#K(e, t = {}) {
|
|
30953
31359
|
let i = await this.#B(e, t);
|
|
@@ -30986,7 +31392,7 @@ var L = class u2 {
|
|
|
30986
31392
|
return;
|
|
30987
31393
|
}
|
|
30988
31394
|
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.#
|
|
31395
|
+
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
31396
|
}
|
|
30991
31397
|
#$(e, t) {
|
|
30992
31398
|
this.#c[t] = e, this.#a[e] = t;
|
|
@@ -31154,7 +31560,7 @@ function extractStructuredText(root) {
|
|
|
31154
31560
|
]);
|
|
31155
31561
|
const isText = (node) => node.nodeType === node.TEXT_NODE;
|
|
31156
31562
|
const isElement = (node) => node.nodeType === node.ELEMENT_NODE;
|
|
31157
|
-
const
|
|
31563
|
+
const pushText2 = (value) => {
|
|
31158
31564
|
const normalized = value.replace(/\s+/g, " ");
|
|
31159
31565
|
if (!normalized.trim())
|
|
31160
31566
|
return;
|
|
@@ -31180,7 +31586,7 @@ function extractStructuredText(root) {
|
|
|
31180
31586
|
};
|
|
31181
31587
|
const visit = (node) => {
|
|
31182
31588
|
if (isText(node)) {
|
|
31183
|
-
|
|
31589
|
+
pushText2(node.textContent || "");
|
|
31184
31590
|
return;
|
|
31185
31591
|
}
|
|
31186
31592
|
if (!isElement(node))
|
|
@@ -31891,7 +32297,7 @@ async function probeLlmsText(url, timeoutMs, signal, fallbackOrigin) {
|
|
|
31891
32297
|
}
|
|
31892
32298
|
|
|
31893
32299
|
// src/tools/smartfetch/cache.ts
|
|
31894
|
-
var CACHE = new
|
|
32300
|
+
var CACHE = new M({
|
|
31895
32301
|
maxSize: 50 * 1024 * 1024,
|
|
31896
32302
|
ttl: 15 * 60 * 1000,
|
|
31897
32303
|
sizeCalculation: (value) => {
|
|
@@ -31952,7 +32358,7 @@ function isInvalidLlmsResult(fetchResult) {
|
|
|
31952
32358
|
|
|
31953
32359
|
// src/tools/smartfetch/secondary-model.ts
|
|
31954
32360
|
import { existsSync as existsSync10 } from "node:fs";
|
|
31955
|
-
import { readFile as
|
|
32361
|
+
import { readFile as readFile5 } from "node:fs/promises";
|
|
31956
32362
|
import path17 from "node:path";
|
|
31957
32363
|
function parseModelRef(value) {
|
|
31958
32364
|
if (!value)
|
|
@@ -31989,7 +32395,7 @@ async function readOpenCodeConfigFile(configPath) {
|
|
|
31989
32395
|
if (!configPath)
|
|
31990
32396
|
return;
|
|
31991
32397
|
try {
|
|
31992
|
-
const content = await
|
|
32398
|
+
const content = await readFile5(configPath, "utf8");
|
|
31993
32399
|
return JSON.parse(stripJsonComments(content));
|
|
31994
32400
|
} catch {
|
|
31995
32401
|
return;
|
|
@@ -32639,7 +33045,7 @@ function createWebfetchTool(pluginCtx, options = {}) {
|
|
|
32639
33045
|
});
|
|
32640
33046
|
}
|
|
32641
33047
|
// src/tools/subtask/command.ts
|
|
32642
|
-
var
|
|
33048
|
+
var COMMAND_NAME5 = "subtask";
|
|
32643
33049
|
var SUBTASK_COMMAND_TEMPLATE = `Start a focused subtask worker.
|
|
32644
33050
|
|
|
32645
33051
|
The user's request below is the full scope for the worker. Do not broaden it.
|
|
@@ -32660,11 +33066,11 @@ Only include files that are clearly relevant. If no files are needed, omit files
|
|
|
32660
33066
|
function createSubtaskCommandManager(_ctx, state) {
|
|
32661
33067
|
function registerCommand(opencodeConfig) {
|
|
32662
33068
|
const configCommand = opencodeConfig.command;
|
|
32663
|
-
if (!configCommand?.[
|
|
33069
|
+
if (!configCommand?.[COMMAND_NAME5]) {
|
|
32664
33070
|
if (!opencodeConfig.command) {
|
|
32665
33071
|
opencodeConfig.command = {};
|
|
32666
33072
|
}
|
|
32667
|
-
opencodeConfig.command[
|
|
33073
|
+
opencodeConfig.command[COMMAND_NAME5] = {
|
|
32668
33074
|
description: "Create a focused subtask prompt for a new session",
|
|
32669
33075
|
template: SUBTASK_COMMAND_TEMPLATE
|
|
32670
33076
|
};
|
|
@@ -32691,11 +33097,11 @@ function createSubtaskCommandManager(_ctx, state) {
|
|
|
32691
33097
|
};
|
|
32692
33098
|
}
|
|
32693
33099
|
// src/tools/subtask/files.ts
|
|
32694
|
-
import * as
|
|
33100
|
+
import * as fs13 from "node:fs/promises";
|
|
32695
33101
|
import * as path20 from "node:path";
|
|
32696
33102
|
|
|
32697
33103
|
// src/tools/subtask/vendor.ts
|
|
32698
|
-
import * as
|
|
33104
|
+
import * as fs12 from "node:fs/promises";
|
|
32699
33105
|
import * as path19 from "node:path";
|
|
32700
33106
|
var DEFAULT_READ_LIMIT = 2000;
|
|
32701
33107
|
var MAX_LINE_LENGTH = 2000;
|
|
@@ -32739,7 +33145,7 @@ async function isBinaryFile(filepath) {
|
|
|
32739
33145
|
return true;
|
|
32740
33146
|
}
|
|
32741
33147
|
try {
|
|
32742
|
-
const file = await
|
|
33148
|
+
const file = await fs12.open(filepath, "r");
|
|
32743
33149
|
try {
|
|
32744
33150
|
const buffer = Buffer.alloc(SAMPLE_BYTES);
|
|
32745
33151
|
const result = await file.read(buffer, 0, SAMPLE_BYTES, 0);
|
|
@@ -32825,24 +33231,24 @@ function parseFileReferences(text) {
|
|
|
32825
33231
|
}
|
|
32826
33232
|
async function buildSyntheticFileParts(directory, refs) {
|
|
32827
33233
|
const parts = [];
|
|
32828
|
-
const realDirectory = await
|
|
33234
|
+
const realDirectory = await fs13.realpath(directory);
|
|
32829
33235
|
for (const ref of refs) {
|
|
32830
33236
|
const filepath = path20.resolve(directory, ref);
|
|
32831
33237
|
const relative3 = path20.relative(directory, filepath);
|
|
32832
33238
|
if (relative3.startsWith("..") || path20.isAbsolute(relative3))
|
|
32833
33239
|
continue;
|
|
32834
33240
|
try {
|
|
32835
|
-
const realFilepath = await
|
|
33241
|
+
const realFilepath = await fs13.realpath(filepath);
|
|
32836
33242
|
const realRelative = path20.relative(realDirectory, realFilepath);
|
|
32837
33243
|
if (realRelative.startsWith("..") || path20.isAbsolute(realRelative)) {
|
|
32838
33244
|
continue;
|
|
32839
33245
|
}
|
|
32840
|
-
const stats = await
|
|
33246
|
+
const stats = await fs13.stat(realFilepath);
|
|
32841
33247
|
if (!stats.isFile())
|
|
32842
33248
|
continue;
|
|
32843
33249
|
if (await isBinaryFile(realFilepath))
|
|
32844
33250
|
continue;
|
|
32845
|
-
const content = await
|
|
33251
|
+
const content = await fs13.readFile(realFilepath, "utf-8");
|
|
32846
33252
|
parts.push({
|
|
32847
33253
|
type: "text",
|
|
32848
33254
|
synthetic: true,
|
|
@@ -32877,7 +33283,7 @@ function createSubtaskState() {
|
|
|
32877
33283
|
}
|
|
32878
33284
|
// src/tools/subtask/tools.ts
|
|
32879
33285
|
import { tool as tool5 } from "@opencode-ai/plugin";
|
|
32880
|
-
var
|
|
33286
|
+
var DEFAULT_SUBTASK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
32881
33287
|
var SUBTASK_SUMMARY_TAG_REGEX = /<\/?subtask_summary>/g;
|
|
32882
33288
|
function normalizeSubtaskSummary(text) {
|
|
32883
33289
|
return text.replace(SUBTASK_SUMMARY_TAG_REGEX, "").trim();
|
|
@@ -32889,8 +33295,9 @@ function getAbortSignal(context) {
|
|
|
32889
33295
|
const signal = context.abort;
|
|
32890
33296
|
return signal && typeof signal === "object" && "addEventListener" in signal && "removeEventListener" in signal && "aborted" in signal ? signal : undefined;
|
|
32891
33297
|
}
|
|
32892
|
-
function createSubtaskTool(ctx, state, depthTracker) {
|
|
33298
|
+
function createSubtaskTool(ctx, state, depthTracker, options = {}) {
|
|
32893
33299
|
const client = ctx.client;
|
|
33300
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_SUBTASK_TIMEOUT_MS;
|
|
32894
33301
|
return tool5({
|
|
32895
33302
|
description: "Run a child worker session and return its completion summary to the caller",
|
|
32896
33303
|
args: {
|
|
@@ -32988,7 +33395,7 @@ Risks / follow-up:
|
|
|
32988
33395
|
...await buildSyntheticFileParts(directory, files)
|
|
32989
33396
|
]
|
|
32990
33397
|
}
|
|
32991
|
-
},
|
|
33398
|
+
}, timeoutMs, abortSignal);
|
|
32992
33399
|
const extraction = await extractSessionResult(client, childSessionID, {
|
|
32993
33400
|
directory,
|
|
32994
33401
|
includeReasoning: false
|
|
@@ -33204,6 +33611,7 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
33204
33611
|
let jsonErrorRecoveryHook;
|
|
33205
33612
|
let foregroundFallback;
|
|
33206
33613
|
let todoContinuationHook;
|
|
33614
|
+
let sessionGoalHook;
|
|
33207
33615
|
let taskSessionManagerHook;
|
|
33208
33616
|
let interviewManager;
|
|
33209
33617
|
let presetManager;
|
|
@@ -33240,11 +33648,10 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
33240
33648
|
runtimeChains[agentDef.name] = agentDef._modelArray.map((m) => m.id);
|
|
33241
33649
|
}
|
|
33242
33650
|
}
|
|
33651
|
+
const activePresetForFallback = getActiveRuntimePreset() ?? config.preset ?? null;
|
|
33243
33652
|
if (config.fallback?.enabled !== false) {
|
|
33244
|
-
const chains = config.fallback?.chains ?? {};
|
|
33653
|
+
const chains = normalizeFallbackChainsForPreset(config.fallback?.chains ?? {}, activePresetForFallback);
|
|
33245
33654
|
for (const [agentName, chainModels] of Object.entries(chains)) {
|
|
33246
|
-
if (!chainModels?.length)
|
|
33247
|
-
continue;
|
|
33248
33655
|
const existing = runtimeChains[agentName] ?? [];
|
|
33249
33656
|
const seen = new Set(existing);
|
|
33250
33657
|
for (const m of chainModels) {
|
|
@@ -33296,6 +33703,9 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
33296
33703
|
autoEnable: config.todoContinuation?.autoEnable ?? false,
|
|
33297
33704
|
autoEnableThreshold: config.todoContinuation?.autoEnableThreshold ?? 4
|
|
33298
33705
|
});
|
|
33706
|
+
sessionGoalHook = createSessionGoalHook(ctx, config, {
|
|
33707
|
+
getAgentName: (sessionID) => sessionAgentMap.get(sessionID)
|
|
33708
|
+
});
|
|
33299
33709
|
taskSessionManagerHook = createTaskSessionManagerHook(ctx, {
|
|
33300
33710
|
maxSessionsPerAgent: config.sessionManager?.maxSessionsPerAgent ?? 2,
|
|
33301
33711
|
readContextMinLines: config.sessionManager?.readContextMinLines ?? 10,
|
|
@@ -33353,7 +33763,9 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
33353
33763
|
...todoContinuationHook.tool,
|
|
33354
33764
|
ast_grep_search,
|
|
33355
33765
|
ast_grep_replace,
|
|
33356
|
-
subtask: createSubtaskTool(ctx, subtaskState, depthTracker
|
|
33766
|
+
subtask: createSubtaskTool(ctx, subtaskState, depthTracker, {
|
|
33767
|
+
timeoutMs: config.subtask?.timeoutMs
|
|
33768
|
+
}),
|
|
33357
33769
|
read_session: createReadSessionTool(ctx.client, subtaskState)
|
|
33358
33770
|
},
|
|
33359
33771
|
mcp: mcps,
|
|
@@ -33379,8 +33791,9 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
33379
33791
|
}
|
|
33380
33792
|
}
|
|
33381
33793
|
const configAgent = opencodeConfig.agent;
|
|
33794
|
+
const activePresetForFallback = getActiveRuntimePreset() ?? config.preset ?? null;
|
|
33382
33795
|
const fallbackChainsEnabled = config.fallback?.enabled !== false;
|
|
33383
|
-
const fallbackChains = fallbackChainsEnabled ? config.fallback?.chains ?? {} : {};
|
|
33796
|
+
const fallbackChains = fallbackChainsEnabled ? normalizeFallbackChainsForPreset(config.fallback?.chains ?? {}, activePresetForFallback) : {};
|
|
33384
33797
|
const effectiveArrays = {};
|
|
33385
33798
|
for (const [agentName, models] of Object.entries(modelArrayMap)) {
|
|
33386
33799
|
effectiveArrays[agentName] = [...models];
|
|
@@ -33550,6 +33963,7 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
33550
33963
|
};
|
|
33551
33964
|
}
|
|
33552
33965
|
interviewManager.registerCommand(opencodeConfig);
|
|
33966
|
+
sessionGoalHook.registerCommand(opencodeConfig);
|
|
33553
33967
|
presetManager.registerCommand(opencodeConfig);
|
|
33554
33968
|
subtaskCommandManager.registerCommand(opencodeConfig);
|
|
33555
33969
|
},
|
|
@@ -33571,12 +33985,13 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
33571
33985
|
depthTracker.registerChild(parentSessionId, childSessionId);
|
|
33572
33986
|
}
|
|
33573
33987
|
}
|
|
33574
|
-
await foregroundFallback.handleEvent(input.event);
|
|
33575
|
-
await todoContinuationHook.handleEvent(input);
|
|
33576
|
-
await autoUpdateChecker.event(input);
|
|
33577
33988
|
await multiplexerSessionManager.onSessionCreated(event);
|
|
33578
33989
|
await multiplexerSessionManager.onSessionStatus(event);
|
|
33579
33990
|
await multiplexerSessionManager.onSessionDeleted(event);
|
|
33991
|
+
await foregroundFallback.handleEvent(input.event);
|
|
33992
|
+
await todoContinuationHook.handleEvent(input);
|
|
33993
|
+
sessionGoalHook.handleEvent(input);
|
|
33994
|
+
await autoUpdateChecker.event(input);
|
|
33580
33995
|
await interviewManager.handleEvent(input);
|
|
33581
33996
|
await taskSessionManagerHook.event(input);
|
|
33582
33997
|
subtaskCommandManager.handleEvent(input);
|
|
@@ -33637,6 +34052,7 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
33637
34052
|
await todoContinuationHook.handleCommandExecuteBefore(input, output);
|
|
33638
34053
|
await interviewManager.handleCommandExecuteBefore(input, output);
|
|
33639
34054
|
await presetManager.handleCommandExecuteBefore(input, output);
|
|
34055
|
+
await sessionGoalHook.handleCommandExecuteBefore(input, output);
|
|
33640
34056
|
},
|
|
33641
34057
|
"chat.headers": chatHeadersHook["chat.headers"],
|
|
33642
34058
|
"chat.message": async (input, output) => {
|
|
@@ -33665,6 +34081,7 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
33665
34081
|
${output.system[0]}` : "");
|
|
33666
34082
|
}
|
|
33667
34083
|
}
|
|
34084
|
+
sessionGoalHook.handleSystemTransform(input, output);
|
|
33668
34085
|
collapseSystemInPlace(output.system);
|
|
33669
34086
|
},
|
|
33670
34087
|
"experimental.chat.messages.transform": async (input, output) => {
|