@zcy2nn/agent-forge 1.1.2 → 1.1.4
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/agent-forge.schema.json +2 -133
- package/dist/cli/index.js +99 -317
- package/dist/cli/providers.d.ts +0 -44
- package/dist/config/constants.d.ts +3 -4
- package/dist/config/index.d.ts +0 -1
- package/dist/config/schema.d.ts +2 -72
- package/dist/hooks/filter-available-skills/index.d.ts +4 -13
- package/dist/index.js +301 -1297
- package/dist/tools/index.d.ts +0 -1
- package/dist/tui.js +5 -32
- package/package.json +1 -1
- package/src/skills/brainstorming/SKILL.md +5 -6
- package/src/skills/brainstorming/spec-document-reviewer-prompt.md +1 -1
- package/src/skills/codemap/README.md +3 -3
- package/src/skills/codemap/SKILL.md +5 -5
- package/src/skills/codemap/codemap.md +4 -4
- package/src/skills/codemap/scripts/codemap.mjs +1 -1
- package/src/skills/codemap/scripts/codemap.test.ts +1 -1
- package/src/skills/requesting-code-review/SKILL.md +1 -1
- package/src/skills/subagent-driven-development/SKILL.md +1 -1
- package/src/skills/writing-plans/SKILL.md +2 -2
- package/dist/agents/council.d.ts +0 -27
- package/dist/agents/councillor.d.ts +0 -2
- package/dist/agents/implementer.d.ts +0 -2
- package/dist/agents/reviewer.d.ts +0 -2
- package/dist/cli/skill-sync.d.ts +0 -23
- package/dist/config/council-schema.d.ts +0 -127
- package/dist/council/council-manager.d.ts +0 -49
- package/dist/council/index.d.ts +0 -1
- package/dist/tools/council.d.ts +0 -10
- package/dist/utils/package-root.d.ts +0 -1
- package/src/skills/using-git-worktrees/SKILL.md +0 -226
package/dist/index.js
CHANGED
|
@@ -30,175 +30,8 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
30
30
|
return to;
|
|
31
31
|
};
|
|
32
32
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
33
|
-
var __returnValue = (v) => v;
|
|
34
|
-
function __exportSetter(name, newValue) {
|
|
35
|
-
this[name] = __returnValue.bind(null, newValue);
|
|
36
|
-
}
|
|
37
|
-
var __export = (target, all) => {
|
|
38
|
-
for (var name in all)
|
|
39
|
-
__defProp(target, name, {
|
|
40
|
-
get: all[name],
|
|
41
|
-
enumerable: true,
|
|
42
|
-
configurable: true,
|
|
43
|
-
set: __exportSetter.bind(all, name)
|
|
44
|
-
});
|
|
45
|
-
};
|
|
46
|
-
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
47
33
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
48
34
|
|
|
49
|
-
// src/cli/custom-skills.ts
|
|
50
|
-
var CUSTOM_SKILLS;
|
|
51
|
-
var init_custom_skills = __esm(() => {
|
|
52
|
-
CUSTOM_SKILLS = [
|
|
53
|
-
{
|
|
54
|
-
name: "simplify",
|
|
55
|
-
description: "Code simplification and readability-focused refactoring",
|
|
56
|
-
allowedAgents: ["reviewer"],
|
|
57
|
-
sourcePath: "src/skills/simplify"
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
name: "codemap",
|
|
61
|
-
description: "Repository understanding and hierarchical codemap generation",
|
|
62
|
-
allowedAgents: ["orchestrator"],
|
|
63
|
-
sourcePath: "src/skills/codemap"
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
name: "brainstorming",
|
|
67
|
-
description: "Turn ideas into designs through collaborative dialogue before implementation",
|
|
68
|
-
allowedAgents: ["orchestrator"],
|
|
69
|
-
sourcePath: "src/skills/brainstorming"
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
name: "writing-plans",
|
|
73
|
-
description: "Create comprehensive implementation plans from specs before touching code",
|
|
74
|
-
allowedAgents: ["orchestrator"],
|
|
75
|
-
sourcePath: "src/skills/writing-plans"
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
name: "executing-plans",
|
|
79
|
-
description: "Execute written implementation plans with review checkpoints",
|
|
80
|
-
allowedAgents: ["orchestrator"],
|
|
81
|
-
sourcePath: "src/skills/executing-plans"
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
name: "subagent-driven-development",
|
|
85
|
-
description: "Execute plans by dispatching fresh subagent per task with two-stage review",
|
|
86
|
-
allowedAgents: ["orchestrator"],
|
|
87
|
-
sourcePath: "src/skills/subagent-driven-development"
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
name: "dispatching-parallel-agents",
|
|
91
|
-
description: "Dispatch parallel agents for independent tasks without shared state",
|
|
92
|
-
allowedAgents: ["orchestrator"],
|
|
93
|
-
sourcePath: "src/skills/dispatching-parallel-agents"
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
name: "using-git-worktrees",
|
|
97
|
-
description: "Create isolated git worktrees before executing implementation plans",
|
|
98
|
-
allowedAgents: ["orchestrator"],
|
|
99
|
-
sourcePath: "src/skills/using-git-worktrees"
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
name: "finishing-a-development-branch",
|
|
103
|
-
description: "Guide completion of development work with structured merge/PR options",
|
|
104
|
-
allowedAgents: ["orchestrator"],
|
|
105
|
-
sourcePath: "src/skills/finishing-a-development-branch"
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
name: "requesting-code-review",
|
|
109
|
-
description: "Dispatch code reviewer subagent to catch issues before merging",
|
|
110
|
-
allowedAgents: ["orchestrator"],
|
|
111
|
-
sourcePath: "src/skills/requesting-code-review"
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
name: "test-driven-development",
|
|
115
|
-
description: "Write failing tests first, then minimal code to pass, before any implementation",
|
|
116
|
-
allowedAgents: ["implementer"],
|
|
117
|
-
sourcePath: "src/skills/test-driven-development"
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
name: "verification-before-completion",
|
|
121
|
-
description: "Run verification commands and confirm output before claiming work is complete",
|
|
122
|
-
allowedAgents: ["implementer"],
|
|
123
|
-
sourcePath: "src/skills/verification-before-completion"
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
name: "systematic-debugging",
|
|
127
|
-
description: "Find root cause before attempting fixes for any bug or test failure",
|
|
128
|
-
allowedAgents: ["reviewer"],
|
|
129
|
-
sourcePath: "src/skills/systematic-debugging"
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
name: "receiving-code-review",
|
|
133
|
-
description: "Evaluate code review feedback with technical rigor before implementing suggestions",
|
|
134
|
-
allowedAgents: ["reviewer"],
|
|
135
|
-
sourcePath: "src/skills/receiving-code-review"
|
|
136
|
-
},
|
|
137
|
-
{
|
|
138
|
-
name: "writing-skills",
|
|
139
|
-
description: "Create and edit skills using TDD methodology for process documentation",
|
|
140
|
-
allowedAgents: ["orchestrator"],
|
|
141
|
-
sourcePath: "src/skills/writing-skills"
|
|
142
|
-
}
|
|
143
|
-
];
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
// src/cli/paths.ts
|
|
147
|
-
import { homedir } from "node:os";
|
|
148
|
-
import { dirname, join } from "node:path";
|
|
149
|
-
function getDefaultOpenCodeConfigDir() {
|
|
150
|
-
const userConfigDir = process.env.XDG_CONFIG_HOME ? process.env.XDG_CONFIG_HOME : join(homedir(), ".config");
|
|
151
|
-
return join(userConfigDir, "opencode");
|
|
152
|
-
}
|
|
153
|
-
function getCustomOpenCodeConfigDir() {
|
|
154
|
-
const configDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
155
|
-
return configDir || undefined;
|
|
156
|
-
}
|
|
157
|
-
function getConfigDir() {
|
|
158
|
-
const customConfigDir = getCustomOpenCodeConfigDir();
|
|
159
|
-
if (customConfigDir) {
|
|
160
|
-
return customConfigDir;
|
|
161
|
-
}
|
|
162
|
-
return getDefaultOpenCodeConfigDir();
|
|
163
|
-
}
|
|
164
|
-
function getConfigSearchDirs() {
|
|
165
|
-
const dirs = [getCustomOpenCodeConfigDir(), getDefaultOpenCodeConfigDir()];
|
|
166
|
-
return dirs.filter((dir, index) => {
|
|
167
|
-
return Boolean(dir) && dirs.indexOf(dir) === index;
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
function getOpenCodeConfigPaths() {
|
|
171
|
-
const configDir = getDefaultOpenCodeConfigDir();
|
|
172
|
-
return [join(configDir, "opencode.json"), join(configDir, "opencode.jsonc")];
|
|
173
|
-
}
|
|
174
|
-
var init_paths = () => {};
|
|
175
|
-
|
|
176
|
-
// src/utils/package-root.ts
|
|
177
|
-
import { existsSync as existsSync10 } from "node:fs";
|
|
178
|
-
import { join as join13 } from "node:path";
|
|
179
|
-
function resolvePackageRoot() {
|
|
180
|
-
if (_cachedPackageRoot)
|
|
181
|
-
return _cachedPackageRoot;
|
|
182
|
-
const distDir = import.meta.dirname;
|
|
183
|
-
if (!distDir) {
|
|
184
|
-
throw new Error("import.meta.dirname is not available");
|
|
185
|
-
}
|
|
186
|
-
const npmRoot = join13(distDir, "..", "..");
|
|
187
|
-
if (existsSync10(join13(npmRoot, "src", "skills"))) {
|
|
188
|
-
_cachedPackageRoot = npmRoot;
|
|
189
|
-
return npmRoot;
|
|
190
|
-
}
|
|
191
|
-
const localRoot = join13(distDir, "..");
|
|
192
|
-
if (existsSync10(join13(localRoot, "src", "skills"))) {
|
|
193
|
-
_cachedPackageRoot = localRoot;
|
|
194
|
-
return localRoot;
|
|
195
|
-
}
|
|
196
|
-
_cachedPackageRoot = npmRoot;
|
|
197
|
-
return npmRoot;
|
|
198
|
-
}
|
|
199
|
-
var _cachedPackageRoot;
|
|
200
|
-
var init_package_root = () => {};
|
|
201
|
-
|
|
202
35
|
// node_modules/@mozilla/readability/Readability.js
|
|
203
36
|
var require_Readability = __commonJS((exports, module) => {
|
|
204
37
|
function Readability(doc, options) {
|
|
@@ -18317,14 +18150,14 @@ var require_turndown_cjs = __commonJS((exports, module) => {
|
|
|
18317
18150
|
} else if (node.nodeType === 1) {
|
|
18318
18151
|
replacement = replacementForNode.call(self, node);
|
|
18319
18152
|
}
|
|
18320
|
-
return
|
|
18153
|
+
return join14(output, replacement);
|
|
18321
18154
|
}, "");
|
|
18322
18155
|
}
|
|
18323
18156
|
function postProcess(output) {
|
|
18324
18157
|
var self = this;
|
|
18325
18158
|
this.rules.forEach(function(rule) {
|
|
18326
18159
|
if (typeof rule.append === "function") {
|
|
18327
|
-
output =
|
|
18160
|
+
output = join14(output, rule.append(self.options));
|
|
18328
18161
|
}
|
|
18329
18162
|
});
|
|
18330
18163
|
return output.replace(/^[\t\r\n]+/, "").replace(/[\t\r\n\s]+$/, "");
|
|
@@ -18337,7 +18170,7 @@ var require_turndown_cjs = __commonJS((exports, module) => {
|
|
|
18337
18170
|
content = content.trim();
|
|
18338
18171
|
return whitespace.leading + rule.replacement(content, node, this.options) + whitespace.trailing;
|
|
18339
18172
|
}
|
|
18340
|
-
function
|
|
18173
|
+
function join14(output, replacement) {
|
|
18341
18174
|
var s1 = trimTrailingNewlines(output);
|
|
18342
18175
|
var s2 = trimLeadingNewlines(replacement);
|
|
18343
18176
|
var nls = Math.max(output.length - s1.length, replacement.length - s2.length);
|
|
@@ -18352,87 +18185,101 @@ var require_turndown_cjs = __commonJS((exports, module) => {
|
|
|
18352
18185
|
module.exports = TurndownService;
|
|
18353
18186
|
});
|
|
18354
18187
|
|
|
18355
|
-
// src/cli/
|
|
18356
|
-
var
|
|
18357
|
-
|
|
18358
|
-
|
|
18359
|
-
|
|
18360
|
-
|
|
18361
|
-
|
|
18362
|
-
|
|
18363
|
-
|
|
18364
|
-
|
|
18365
|
-
|
|
18366
|
-
|
|
18367
|
-
|
|
18368
|
-
}
|
|
18369
|
-
|
|
18370
|
-
|
|
18371
|
-
|
|
18372
|
-
|
|
18373
|
-
|
|
18374
|
-
|
|
18375
|
-
|
|
18376
|
-
|
|
18377
|
-
|
|
18378
|
-
|
|
18379
|
-
|
|
18380
|
-
|
|
18381
|
-
|
|
18382
|
-
|
|
18383
|
-
|
|
18384
|
-
|
|
18385
|
-
|
|
18386
|
-
|
|
18387
|
-
|
|
18388
|
-
|
|
18389
|
-
|
|
18390
|
-
|
|
18391
|
-
|
|
18392
|
-
|
|
18393
|
-
|
|
18394
|
-
|
|
18395
|
-
|
|
18396
|
-
|
|
18397
|
-
|
|
18398
|
-
|
|
18399
|
-
|
|
18400
|
-
|
|
18401
|
-
|
|
18402
|
-
|
|
18403
|
-
|
|
18404
|
-
|
|
18405
|
-
|
|
18406
|
-
|
|
18407
|
-
|
|
18408
|
-
|
|
18409
|
-
|
|
18410
|
-
|
|
18411
|
-
|
|
18412
|
-
|
|
18413
|
-
|
|
18414
|
-
|
|
18415
|
-
|
|
18416
|
-
|
|
18417
|
-
|
|
18418
|
-
|
|
18419
|
-
|
|
18188
|
+
// src/cli/custom-skills.ts
|
|
18189
|
+
var CUSTOM_SKILLS = [
|
|
18190
|
+
{
|
|
18191
|
+
name: "simplify",
|
|
18192
|
+
description: "Code simplification and readability-focused refactoring",
|
|
18193
|
+
allowedAgents: ["orchestrator"],
|
|
18194
|
+
sourcePath: "src/skills/simplify"
|
|
18195
|
+
},
|
|
18196
|
+
{
|
|
18197
|
+
name: "codemap",
|
|
18198
|
+
description: "Repository understanding and hierarchical codemap generation",
|
|
18199
|
+
allowedAgents: ["orchestrator"],
|
|
18200
|
+
sourcePath: "src/skills/codemap"
|
|
18201
|
+
},
|
|
18202
|
+
{
|
|
18203
|
+
name: "brainstorming",
|
|
18204
|
+
description: "Turn ideas into designs through collaborative dialogue before implementation",
|
|
18205
|
+
allowedAgents: ["orchestrator"],
|
|
18206
|
+
sourcePath: "src/skills/brainstorming"
|
|
18207
|
+
},
|
|
18208
|
+
{
|
|
18209
|
+
name: "writing-plans",
|
|
18210
|
+
description: "Create comprehensive implementation plans from specs before touching code",
|
|
18211
|
+
allowedAgents: ["orchestrator"],
|
|
18212
|
+
sourcePath: "src/skills/writing-plans"
|
|
18213
|
+
},
|
|
18214
|
+
{
|
|
18215
|
+
name: "executing-plans",
|
|
18216
|
+
description: "Execute written implementation plans with review checkpoints",
|
|
18217
|
+
allowedAgents: ["orchestrator"],
|
|
18218
|
+
sourcePath: "src/skills/executing-plans"
|
|
18219
|
+
},
|
|
18220
|
+
{
|
|
18221
|
+
name: "subagent-driven-development",
|
|
18222
|
+
description: "Execute plans by dispatching fresh subagent per task with two-stage review",
|
|
18223
|
+
allowedAgents: ["orchestrator"],
|
|
18224
|
+
sourcePath: "src/skills/subagent-driven-development"
|
|
18225
|
+
},
|
|
18226
|
+
{
|
|
18227
|
+
name: "dispatching-parallel-agents",
|
|
18228
|
+
description: "Dispatch parallel agents for independent tasks without shared state",
|
|
18229
|
+
allowedAgents: ["orchestrator"],
|
|
18230
|
+
sourcePath: "src/skills/dispatching-parallel-agents"
|
|
18231
|
+
},
|
|
18232
|
+
{
|
|
18233
|
+
name: "finishing-a-development-branch",
|
|
18234
|
+
description: "Guide completion of development work with structured merge/PR options",
|
|
18235
|
+
allowedAgents: ["orchestrator"],
|
|
18236
|
+
sourcePath: "src/skills/finishing-a-development-branch"
|
|
18237
|
+
},
|
|
18238
|
+
{
|
|
18239
|
+
name: "requesting-code-review",
|
|
18240
|
+
description: "Dispatch code reviewer subagent to catch issues before merging",
|
|
18241
|
+
allowedAgents: ["orchestrator"],
|
|
18242
|
+
sourcePath: "src/skills/requesting-code-review"
|
|
18243
|
+
},
|
|
18244
|
+
{
|
|
18245
|
+
name: "test-driven-development",
|
|
18246
|
+
description: "Write failing tests first, then minimal code to pass, before any implementation",
|
|
18247
|
+
allowedAgents: ["orchestrator"],
|
|
18248
|
+
sourcePath: "src/skills/test-driven-development"
|
|
18249
|
+
},
|
|
18250
|
+
{
|
|
18251
|
+
name: "verification-before-completion",
|
|
18252
|
+
description: "Run verification commands and confirm output before claiming work is complete",
|
|
18253
|
+
allowedAgents: ["orchestrator"],
|
|
18254
|
+
sourcePath: "src/skills/verification-before-completion"
|
|
18255
|
+
},
|
|
18256
|
+
{
|
|
18257
|
+
name: "systematic-debugging",
|
|
18258
|
+
description: "Find root cause before attempting fixes for any bug or test failure",
|
|
18259
|
+
allowedAgents: ["orchestrator"],
|
|
18260
|
+
sourcePath: "src/skills/systematic-debugging"
|
|
18261
|
+
},
|
|
18262
|
+
{
|
|
18263
|
+
name: "receiving-code-review",
|
|
18264
|
+
description: "Evaluate code review feedback with technical rigor before implementing suggestions",
|
|
18265
|
+
allowedAgents: ["orchestrator"],
|
|
18266
|
+
sourcePath: "src/skills/receiving-code-review"
|
|
18267
|
+
},
|
|
18268
|
+
{
|
|
18269
|
+
name: "writing-skills",
|
|
18270
|
+
description: "Create and edit skills using TDD methodology for process documentation",
|
|
18271
|
+
allowedAgents: ["orchestrator"],
|
|
18272
|
+
sourcePath: "src/skills/writing-skills"
|
|
18420
18273
|
}
|
|
18421
|
-
|
|
18422
|
-
var init_skill_sync = __esm(() => {
|
|
18423
|
-
init_package_root();
|
|
18424
|
-
init_custom_skills();
|
|
18425
|
-
init_paths();
|
|
18426
|
-
});
|
|
18274
|
+
];
|
|
18427
18275
|
|
|
18428
18276
|
// src/cli/skills.ts
|
|
18429
|
-
init_custom_skills();
|
|
18430
18277
|
var RECOMMENDED_SKILLS = [
|
|
18431
18278
|
{
|
|
18432
18279
|
name: "agent-browser",
|
|
18433
18280
|
repo: "https://github.com/vercel-labs/agent-browser",
|
|
18434
18281
|
skillName: "agent-browser",
|
|
18435
|
-
allowedAgents: ["
|
|
18282
|
+
allowedAgents: ["orchestrator"],
|
|
18436
18283
|
description: "High-performance browser automation",
|
|
18437
18284
|
postInstallCommands: [
|
|
18438
18285
|
"npm install -g agent-browser",
|
|
@@ -18481,28 +18328,17 @@ function getSkillPermissionsForAgent(agentName, skillList) {
|
|
|
18481
18328
|
|
|
18482
18329
|
// src/config/constants.ts
|
|
18483
18330
|
var SUBAGENT_NAMES = [
|
|
18484
|
-
"researcher"
|
|
18485
|
-
"reviewer",
|
|
18486
|
-
"implementer",
|
|
18487
|
-
"council",
|
|
18488
|
-
"councillor"
|
|
18331
|
+
"researcher"
|
|
18489
18332
|
];
|
|
18490
18333
|
var ORCHESTRATOR_NAME = "orchestrator";
|
|
18491
18334
|
var ALL_AGENT_NAMES = [ORCHESTRATOR_NAME, ...SUBAGENT_NAMES];
|
|
18492
18335
|
var PROTECTED_AGENTS = new Set([
|
|
18493
18336
|
"orchestrator",
|
|
18494
|
-
"researcher"
|
|
18495
|
-
"reviewer",
|
|
18496
|
-
"implementer",
|
|
18497
|
-
"councillor"
|
|
18337
|
+
"researcher"
|
|
18498
18338
|
]);
|
|
18499
18339
|
var DEFAULT_MODELS = {
|
|
18500
18340
|
orchestrator: undefined,
|
|
18501
|
-
|
|
18502
|
-
researcher: "openai/gpt-5.4-mini",
|
|
18503
|
-
implementer: "openai/gpt-5.4-mini",
|
|
18504
|
-
council: "openai/gpt-5.4-mini",
|
|
18505
|
-
councillor: "openai/gpt-5.4-mini"
|
|
18341
|
+
researcher: "openai/gpt-5.4-mini"
|
|
18506
18342
|
};
|
|
18507
18343
|
var POLL_INTERVAL_BACKGROUND_MS = 2000;
|
|
18508
18344
|
var DEFAULT_TIMEOUT_MS = 2 * 60 * 1000;
|
|
@@ -18511,92 +18347,37 @@ var DEFAULT_MAX_SUBAGENT_DEPTH = 3;
|
|
|
18511
18347
|
var PHASE_REMINDER_TEXT = `!IMPORTANT! Recall the workflow rules:
|
|
18512
18348
|
Understand → choose the best parallelized path based on your capabilities and agents delegation rules → recall session reuse rules → execute → verify.
|
|
18513
18349
|
If delegating, launch the specialist in the same turn you mention it !END!`;
|
|
18514
|
-
var
|
|
18515
|
-
var COUNCILLOR_STAGGER_MS = 250;
|
|
18516
|
-
var DEFAULT_DISABLED_AGENTS = ["council"];
|
|
18517
|
-
// src/config/council-schema.ts
|
|
18518
|
-
import { z } from "zod";
|
|
18519
|
-
var ModelIdSchema = z.string().regex(/^[^/\s]+\/[^\s]+$/, 'Expected provider/model format (e.g. "openai/gpt-5.4-mini")');
|
|
18520
|
-
var CouncillorConfigSchema = z.object({
|
|
18521
|
-
model: ModelIdSchema.describe('Model ID in provider/model format (e.g. "openai/gpt-5.4-mini")'),
|
|
18522
|
-
variant: z.string().optional(),
|
|
18523
|
-
prompt: z.string().optional().describe("Optional role/guidance injected into the councillor user prompt")
|
|
18524
|
-
});
|
|
18525
|
-
var CouncilPresetSchema = z.record(z.string(), z.record(z.string(), z.unknown())).transform((entries, ctx) => {
|
|
18526
|
-
const councillors = {};
|
|
18527
|
-
for (const [key, raw] of Object.entries(entries)) {
|
|
18528
|
-
if (key === "master")
|
|
18529
|
-
continue;
|
|
18530
|
-
if (key === "councillors" && typeof raw === "object" && raw !== null) {
|
|
18531
|
-
for (const [innerKey, innerRaw] of Object.entries(raw)) {
|
|
18532
|
-
const innerParsed = CouncillorConfigSchema.safeParse(innerRaw);
|
|
18533
|
-
if (!innerParsed.success) {
|
|
18534
|
-
ctx.addIssue({
|
|
18535
|
-
code: z.ZodIssueCode.custom,
|
|
18536
|
-
message: `Invalid councillor "${innerKey}" (nested under legacy "councillors" key): ${innerParsed.error.issues.map((i) => i.message).join(", ")}`
|
|
18537
|
-
});
|
|
18538
|
-
return z.NEVER;
|
|
18539
|
-
}
|
|
18540
|
-
councillors[innerKey] = innerParsed.data;
|
|
18541
|
-
}
|
|
18542
|
-
continue;
|
|
18543
|
-
}
|
|
18544
|
-
const parsed = CouncillorConfigSchema.safeParse(raw);
|
|
18545
|
-
if (!parsed.success) {
|
|
18546
|
-
ctx.addIssue({
|
|
18547
|
-
code: z.ZodIssueCode.custom,
|
|
18548
|
-
message: `Invalid councillor "${key}": ${parsed.error.issues.map((i) => i.message).join(", ")}`
|
|
18549
|
-
});
|
|
18550
|
-
return z.NEVER;
|
|
18551
|
-
}
|
|
18552
|
-
councillors[key] = parsed.data;
|
|
18553
|
-
}
|
|
18554
|
-
return councillors;
|
|
18555
|
-
});
|
|
18556
|
-
var CouncillorExecutionModeSchema = z.enum(["parallel", "serial"]).default("parallel").describe('Execution mode for councillors. Use "serial" for single-model systems to avoid conflicts. ' + 'Use "parallel" for multi-model systems for faster execution.');
|
|
18557
|
-
var CouncilConfigSchema = z.object({
|
|
18558
|
-
presets: z.record(z.string(), CouncilPresetSchema),
|
|
18559
|
-
timeout: z.number().min(0).default(180000),
|
|
18560
|
-
default_preset: z.string().default("default"),
|
|
18561
|
-
councillor_execution_mode: CouncillorExecutionModeSchema.describe('Execution mode for councillors. "serial" runs them one at a time (required for single-model systems). "parallel" runs them concurrently (default, faster for multi-model systems).'),
|
|
18562
|
-
councillor_retries: z.number().int().min(0).max(5).default(3).describe("Number of retry attempts for councillors that return empty responses " + "(e.g. due to provider rate limiting). Default: 3 retries."),
|
|
18563
|
-
master: z.unknown().optional().describe("DEPRECATED — ignored. Council agent synthesizes directly."),
|
|
18564
|
-
master_timeout: z.unknown().optional().describe('DEPRECATED — ignored. Use "timeout" instead.'),
|
|
18565
|
-
master_fallback: z.unknown().optional().describe("DEPRECATED — ignored. No separate master session.")
|
|
18566
|
-
}).transform((data) => {
|
|
18567
|
-
const deprecated = [];
|
|
18568
|
-
if (data.master !== undefined)
|
|
18569
|
-
deprecated.push("master");
|
|
18570
|
-
if (data.master_timeout !== undefined)
|
|
18571
|
-
deprecated.push("master_timeout");
|
|
18572
|
-
if (data.master_fallback !== undefined)
|
|
18573
|
-
deprecated.push("master_fallback");
|
|
18574
|
-
const legacyMasterModel = typeof data.master === "object" && data.master !== null && "model" in data.master && typeof data.master.model === "string" ? data.master.model : undefined;
|
|
18575
|
-
return {
|
|
18576
|
-
presets: data.presets,
|
|
18577
|
-
timeout: data.timeout,
|
|
18578
|
-
default_preset: data.default_preset,
|
|
18579
|
-
councillor_execution_mode: data.councillor_execution_mode,
|
|
18580
|
-
councillor_retries: data.councillor_retries,
|
|
18581
|
-
_deprecated: deprecated.length > 0 ? deprecated : undefined,
|
|
18582
|
-
_legacyMasterModel: legacyMasterModel
|
|
18583
|
-
};
|
|
18584
|
-
});
|
|
18350
|
+
var DEFAULT_DISABLED_AGENTS = [];
|
|
18585
18351
|
// src/config/loader.ts
|
|
18586
18352
|
import * as fs from "node:fs";
|
|
18587
18353
|
import * as path from "node:path";
|
|
18588
18354
|
|
|
18589
|
-
// src/cli/
|
|
18590
|
-
|
|
18355
|
+
// src/cli/paths.ts
|
|
18356
|
+
import { homedir } from "node:os";
|
|
18357
|
+
import { dirname, join } from "node:path";
|
|
18358
|
+
function getDefaultOpenCodeConfigDir() {
|
|
18359
|
+
const userConfigDir = process.env.XDG_CONFIG_HOME ? process.env.XDG_CONFIG_HOME : join(homedir(), ".config");
|
|
18360
|
+
return join(userConfigDir, "opencode");
|
|
18361
|
+
}
|
|
18362
|
+
function getCustomOpenCodeConfigDir() {
|
|
18363
|
+
const configDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
18364
|
+
return configDir || undefined;
|
|
18365
|
+
}
|
|
18366
|
+
function getConfigSearchDirs() {
|
|
18367
|
+
const dirs = [getCustomOpenCodeConfigDir(), getDefaultOpenCodeConfigDir()];
|
|
18368
|
+
return dirs.filter((dir, index) => {
|
|
18369
|
+
return Boolean(dir) && dirs.indexOf(dir) === index;
|
|
18370
|
+
});
|
|
18371
|
+
}
|
|
18372
|
+
function getOpenCodeConfigPaths() {
|
|
18373
|
+
const configDir = getDefaultOpenCodeConfigDir();
|
|
18374
|
+
return [join(configDir, "opencode.json"), join(configDir, "opencode.jsonc")];
|
|
18375
|
+
}
|
|
18591
18376
|
|
|
18592
18377
|
// src/config/agent-mcps.ts
|
|
18593
18378
|
var DEFAULT_AGENT_MCPS = {
|
|
18594
18379
|
orchestrator: ["*", "!context7"],
|
|
18595
|
-
researcher: ["websearch", "context7", "grep_app"]
|
|
18596
|
-
reviewer: [],
|
|
18597
|
-
implementer: [],
|
|
18598
|
-
council: [],
|
|
18599
|
-
councillor: []
|
|
18380
|
+
researcher: ["websearch", "context7", "grep_app"]
|
|
18600
18381
|
};
|
|
18601
18382
|
function parseList(items, allAvailable) {
|
|
18602
18383
|
if (!items || items.length === 0) {
|
|
@@ -18621,9 +18402,6 @@ function getAgentMcpList(agentName, config) {
|
|
|
18621
18402
|
return defaultMcps ?? [];
|
|
18622
18403
|
}
|
|
18623
18404
|
|
|
18624
|
-
// src/cli/providers.ts
|
|
18625
|
-
init_custom_skills();
|
|
18626
|
-
|
|
18627
18405
|
// src/cli/config-io.ts
|
|
18628
18406
|
function stripJsonComments(json) {
|
|
18629
18407
|
const commentPattern = /\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g;
|
|
@@ -18631,13 +18409,10 @@ function stripJsonComments(json) {
|
|
|
18631
18409
|
return json.replace(commentPattern, (match, commentGroup) => commentGroup ? "" : match).replace(trailingCommaPattern, (match, comma, closing) => comma ? closing : match);
|
|
18632
18410
|
}
|
|
18633
18411
|
|
|
18634
|
-
// src/config/loader.ts
|
|
18635
|
-
init_paths();
|
|
18636
|
-
|
|
18637
18412
|
// src/config/schema.ts
|
|
18638
|
-
import { z
|
|
18639
|
-
var ProviderModelIdSchema =
|
|
18640
|
-
var ManualAgentPlanSchema =
|
|
18413
|
+
import { z } from "zod";
|
|
18414
|
+
var ProviderModelIdSchema = z.string().regex(/^[^/\s]+\/[^\s]+$/, "Expected provider/model format (provider/.../model)");
|
|
18415
|
+
var ManualAgentPlanSchema = z.object({
|
|
18641
18416
|
primary: ProviderModelIdSchema,
|
|
18642
18417
|
fallback1: ProviderModelIdSchema,
|
|
18643
18418
|
fallback2: ProviderModelIdSchema,
|
|
@@ -18651,46 +18426,42 @@ var ManualAgentPlanSchema = z2.object({
|
|
|
18651
18426
|
]);
|
|
18652
18427
|
if (unique.size !== 4) {
|
|
18653
18428
|
ctx.addIssue({
|
|
18654
|
-
code:
|
|
18429
|
+
code: z.ZodIssueCode.custom,
|
|
18655
18430
|
message: "primary and fallbacks must be unique per agent"
|
|
18656
18431
|
});
|
|
18657
18432
|
}
|
|
18658
18433
|
});
|
|
18659
|
-
var ManualPlanSchema =
|
|
18434
|
+
var ManualPlanSchema = z.object({
|
|
18660
18435
|
orchestrator: ManualAgentPlanSchema,
|
|
18661
|
-
researcher: ManualAgentPlanSchema
|
|
18662
|
-
reviewer: ManualAgentPlanSchema,
|
|
18663
|
-
implementer: ManualAgentPlanSchema
|
|
18436
|
+
researcher: ManualAgentPlanSchema
|
|
18664
18437
|
}).strict();
|
|
18665
|
-
var AgentModelChainSchema =
|
|
18666
|
-
var FallbackChainsSchema =
|
|
18438
|
+
var AgentModelChainSchema = z.array(z.string()).min(1);
|
|
18439
|
+
var FallbackChainsSchema = z.object({
|
|
18667
18440
|
orchestrator: AgentModelChainSchema.optional(),
|
|
18668
|
-
researcher: AgentModelChainSchema.optional()
|
|
18669
|
-
reviewer: AgentModelChainSchema.optional(),
|
|
18670
|
-
implementer: AgentModelChainSchema.optional()
|
|
18441
|
+
researcher: AgentModelChainSchema.optional()
|
|
18671
18442
|
}).catchall(AgentModelChainSchema);
|
|
18672
|
-
var AgentOverrideConfigSchema =
|
|
18673
|
-
model:
|
|
18674
|
-
|
|
18675
|
-
|
|
18676
|
-
|
|
18677
|
-
|
|
18678
|
-
id:
|
|
18679
|
-
variant:
|
|
18443
|
+
var AgentOverrideConfigSchema = z.object({
|
|
18444
|
+
model: z.union([
|
|
18445
|
+
z.string(),
|
|
18446
|
+
z.array(z.union([
|
|
18447
|
+
z.string(),
|
|
18448
|
+
z.object({
|
|
18449
|
+
id: z.string(),
|
|
18450
|
+
variant: z.string().optional()
|
|
18680
18451
|
})
|
|
18681
18452
|
])).min(1)
|
|
18682
18453
|
]).optional(),
|
|
18683
|
-
temperature:
|
|
18684
|
-
variant:
|
|
18685
|
-
skills:
|
|
18686
|
-
mcps:
|
|
18687
|
-
prompt:
|
|
18688
|
-
orchestratorPrompt:
|
|
18689
|
-
options:
|
|
18690
|
-
displayName:
|
|
18454
|
+
temperature: z.number().min(0).max(2).optional(),
|
|
18455
|
+
variant: z.string().optional().catch(undefined),
|
|
18456
|
+
skills: z.array(z.string()).optional(),
|
|
18457
|
+
mcps: z.array(z.string()).optional(),
|
|
18458
|
+
prompt: z.string().min(1).optional(),
|
|
18459
|
+
orchestratorPrompt: z.string().min(1).optional(),
|
|
18460
|
+
options: z.record(z.string(), z.unknown()).optional(),
|
|
18461
|
+
displayName: z.string().min(1).optional()
|
|
18691
18462
|
}).strict();
|
|
18692
|
-
var MultiplexerTypeSchema =
|
|
18693
|
-
var MultiplexerLayoutSchema =
|
|
18463
|
+
var MultiplexerTypeSchema = z.enum(["auto", "tmux", "zellij", "none"]);
|
|
18464
|
+
var MultiplexerLayoutSchema = z.enum([
|
|
18694
18465
|
"main-horizontal",
|
|
18695
18466
|
"main-vertical",
|
|
18696
18467
|
"tiled",
|
|
@@ -18698,56 +18469,56 @@ var MultiplexerLayoutSchema = z2.enum([
|
|
|
18698
18469
|
"even-vertical"
|
|
18699
18470
|
]);
|
|
18700
18471
|
var TmuxLayoutSchema = MultiplexerLayoutSchema;
|
|
18701
|
-
var MultiplexerConfigSchema =
|
|
18472
|
+
var MultiplexerConfigSchema = z.object({
|
|
18702
18473
|
type: MultiplexerTypeSchema.default("none"),
|
|
18703
18474
|
layout: MultiplexerLayoutSchema.default("main-vertical"),
|
|
18704
|
-
main_pane_size:
|
|
18475
|
+
main_pane_size: z.number().min(20).max(80).default(60)
|
|
18705
18476
|
});
|
|
18706
|
-
var TmuxConfigSchema =
|
|
18707
|
-
enabled:
|
|
18477
|
+
var TmuxConfigSchema = z.object({
|
|
18478
|
+
enabled: z.boolean().default(false),
|
|
18708
18479
|
layout: TmuxLayoutSchema.default("main-vertical"),
|
|
18709
|
-
main_pane_size:
|
|
18480
|
+
main_pane_size: z.number().min(20).max(80).default(60)
|
|
18710
18481
|
});
|
|
18711
|
-
var PresetSchema =
|
|
18712
|
-
var WebsearchConfigSchema =
|
|
18713
|
-
provider:
|
|
18482
|
+
var PresetSchema = z.record(z.string(), AgentOverrideConfigSchema);
|
|
18483
|
+
var WebsearchConfigSchema = z.object({
|
|
18484
|
+
provider: z.enum(["exa", "tavily"]).default("exa")
|
|
18714
18485
|
});
|
|
18715
|
-
var McpNameSchema =
|
|
18716
|
-
var InterviewConfigSchema =
|
|
18717
|
-
maxQuestions:
|
|
18718
|
-
outputFolder:
|
|
18719
|
-
autoOpenBrowser:
|
|
18720
|
-
port:
|
|
18721
|
-
dashboard:
|
|
18486
|
+
var McpNameSchema = z.enum(["websearch", "context7", "grep_app"]);
|
|
18487
|
+
var InterviewConfigSchema = z.object({
|
|
18488
|
+
maxQuestions: z.number().int().min(1).max(10).default(2),
|
|
18489
|
+
outputFolder: z.string().min(1).default("interview"),
|
|
18490
|
+
autoOpenBrowser: z.boolean().default(true).describe("Automatically open the interview UI in your default browser during interactive runs. Disabled automatically in tests and CI."),
|
|
18491
|
+
port: z.number().int().min(0).max(65535).default(0),
|
|
18492
|
+
dashboard: z.boolean().default(false)
|
|
18722
18493
|
});
|
|
18723
|
-
var SessionManagerConfigSchema =
|
|
18724
|
-
maxSessionsPerAgent:
|
|
18725
|
-
readContextMinLines:
|
|
18726
|
-
readContextMaxFiles:
|
|
18494
|
+
var SessionManagerConfigSchema = z.object({
|
|
18495
|
+
maxSessionsPerAgent: z.number().int().min(1).max(10).default(2),
|
|
18496
|
+
readContextMinLines: z.number().int().min(0).max(1000).default(10),
|
|
18497
|
+
readContextMaxFiles: z.number().int().min(0).max(50).default(8)
|
|
18727
18498
|
});
|
|
18728
|
-
var DivoomConfigSchema =
|
|
18729
|
-
enabled:
|
|
18730
|
-
python:
|
|
18731
|
-
script:
|
|
18732
|
-
size:
|
|
18733
|
-
fps:
|
|
18734
|
-
speed:
|
|
18735
|
-
maxFrames:
|
|
18736
|
-
posterizeBits:
|
|
18737
|
-
gifs:
|
|
18499
|
+
var DivoomConfigSchema = z.object({
|
|
18500
|
+
enabled: z.boolean().default(false),
|
|
18501
|
+
python: z.string().min(1).default("/Applications/Divoom MiniToo.app/Contents/Resources/.venv/bin/python"),
|
|
18502
|
+
script: z.string().min(1).default("/Applications/Divoom MiniToo.app/Contents/Resources/tools/divoom_send.py"),
|
|
18503
|
+
size: z.number().int().min(1).max(1024).default(128),
|
|
18504
|
+
fps: z.number().int().min(1).max(60).default(8),
|
|
18505
|
+
speed: z.number().int().min(1).max(1e4).default(125),
|
|
18506
|
+
maxFrames: z.number().int().min(1).max(500).default(24),
|
|
18507
|
+
posterizeBits: z.number().int().min(1).max(8).default(3),
|
|
18508
|
+
gifs: z.record(z.string(), z.string().min(1)).optional()
|
|
18738
18509
|
});
|
|
18739
|
-
var TodoContinuationConfigSchema =
|
|
18740
|
-
maxContinuations:
|
|
18741
|
-
cooldownMs:
|
|
18742
|
-
autoEnable:
|
|
18743
|
-
autoEnableThreshold:
|
|
18510
|
+
var TodoContinuationConfigSchema = z.object({
|
|
18511
|
+
maxContinuations: z.number().int().min(1).max(50).default(5).describe("Maximum consecutive auto-continuations before stopping to ask user"),
|
|
18512
|
+
cooldownMs: z.number().int().min(0).max(30000).default(3000).describe("Delay in ms before auto-continuing (gives user time to abort)"),
|
|
18513
|
+
autoEnable: z.boolean().default(false).describe("Automatically enable auto-continue when the orchestrator session has enough todos"),
|
|
18514
|
+
autoEnableThreshold: z.number().int().min(1).max(50).default(4).describe("Number of todos that triggers auto-enable (only used when autoEnable is true)")
|
|
18744
18515
|
});
|
|
18745
|
-
var FailoverConfigSchema =
|
|
18746
|
-
enabled:
|
|
18747
|
-
timeoutMs:
|
|
18748
|
-
retryDelayMs:
|
|
18516
|
+
var FailoverConfigSchema = z.object({
|
|
18517
|
+
enabled: z.boolean().default(true),
|
|
18518
|
+
timeoutMs: z.number().min(0).default(15000),
|
|
18519
|
+
retryDelayMs: z.number().min(0).default(500),
|
|
18749
18520
|
chains: FallbackChainsSchema.default({}),
|
|
18750
|
-
retry_on_empty:
|
|
18521
|
+
retry_on_empty: z.boolean().default(true).describe("When true (default), empty provider responses are treated as failures, " + "triggering fallback/retry. Set to false to treat them as successes.")
|
|
18751
18522
|
});
|
|
18752
18523
|
function validateCustomOnlyPromptFields(overrides, ctx, pathPrefix) {
|
|
18753
18524
|
for (const [name, override] of Object.entries(overrides)) {
|
|
@@ -18757,31 +18528,31 @@ function validateCustomOnlyPromptFields(overrides, ctx, pathPrefix) {
|
|
|
18757
18528
|
}
|
|
18758
18529
|
if (override.prompt !== undefined) {
|
|
18759
18530
|
ctx.addIssue({
|
|
18760
|
-
code:
|
|
18531
|
+
code: z.ZodIssueCode.custom,
|
|
18761
18532
|
path: [...pathPrefix, name, "prompt"],
|
|
18762
18533
|
message: "prompt is only supported for custom agents"
|
|
18763
18534
|
});
|
|
18764
18535
|
}
|
|
18765
18536
|
if (override.orchestratorPrompt !== undefined) {
|
|
18766
18537
|
ctx.addIssue({
|
|
18767
|
-
code:
|
|
18538
|
+
code: z.ZodIssueCode.custom,
|
|
18768
18539
|
path: [...pathPrefix, name, "orchestratorPrompt"],
|
|
18769
18540
|
message: "orchestratorPrompt is only supported for custom agents"
|
|
18770
18541
|
});
|
|
18771
18542
|
}
|
|
18772
18543
|
}
|
|
18773
18544
|
}
|
|
18774
|
-
var PluginConfigSchema =
|
|
18775
|
-
preset:
|
|
18776
|
-
setDefaultAgent:
|
|
18777
|
-
scoringEngineVersion:
|
|
18778
|
-
balanceProviderUsage:
|
|
18779
|
-
autoUpdate:
|
|
18545
|
+
var PluginConfigSchema = z.object({
|
|
18546
|
+
preset: z.string().optional(),
|
|
18547
|
+
setDefaultAgent: z.boolean().optional(),
|
|
18548
|
+
scoringEngineVersion: z.enum(["v1", "v2-shadow", "v2"]).optional(),
|
|
18549
|
+
balanceProviderUsage: z.boolean().optional(),
|
|
18550
|
+
autoUpdate: z.boolean().optional().describe("Disable automatic installation of plugin updates when false. Defaults to true."),
|
|
18780
18551
|
manualPlan: ManualPlanSchema.optional(),
|
|
18781
|
-
presets:
|
|
18782
|
-
agents:
|
|
18783
|
-
disabled_agents:
|
|
18784
|
-
disabled_mcps:
|
|
18552
|
+
presets: z.record(z.string(), PresetSchema).optional(),
|
|
18553
|
+
agents: z.record(z.string(), AgentOverrideConfigSchema).optional(),
|
|
18554
|
+
disabled_agents: z.array(z.string()).optional().describe("Agent names to disable completely. " + "Disabled agents are not instantiated and cannot be delegated to. " + "Orchestrator and researcher cannot be disabled."),
|
|
18555
|
+
disabled_mcps: z.array(z.string()).optional(),
|
|
18785
18556
|
multiplexer: MultiplexerConfigSchema.optional(),
|
|
18786
18557
|
tmux: TmuxConfigSchema.optional(),
|
|
18787
18558
|
websearch: WebsearchConfigSchema.optional(),
|
|
@@ -18789,8 +18560,7 @@ var PluginConfigSchema = z2.object({
|
|
|
18789
18560
|
sessionManager: SessionManagerConfigSchema.optional(),
|
|
18790
18561
|
divoom: DivoomConfigSchema.optional(),
|
|
18791
18562
|
todoContinuation: TodoContinuationConfigSchema.optional(),
|
|
18792
|
-
fallback: FailoverConfigSchema.optional()
|
|
18793
|
-
council: CouncilConfigSchema.optional()
|
|
18563
|
+
fallback: FailoverConfigSchema.optional()
|
|
18794
18564
|
}).superRefine((value, ctx) => {
|
|
18795
18565
|
if (value.agents) {
|
|
18796
18566
|
validateCustomOnlyPromptFields(value.agents, ctx, ["agents"]);
|
|
@@ -18858,8 +18628,7 @@ function mergePluginConfigs(base, override) {
|
|
|
18858
18628
|
interview: deepMerge(base.interview, override.interview),
|
|
18859
18629
|
sessionManager: deepMerge(base.sessionManager, override.sessionManager),
|
|
18860
18630
|
divoom: deepMerge(base.divoom, override.divoom),
|
|
18861
|
-
fallback: deepMerge(base.fallback, override.fallback)
|
|
18862
|
-
council: deepMerge(base.council, override.council)
|
|
18631
|
+
fallback: deepMerge(base.fallback, override.fallback)
|
|
18863
18632
|
};
|
|
18864
18633
|
}
|
|
18865
18634
|
function deepMerge(base, override) {
|
|
@@ -18955,99 +18724,6 @@ function getCustomAgentNames(config) {
|
|
|
18955
18724
|
return !ALL_AGENT_NAMES.includes(name);
|
|
18956
18725
|
});
|
|
18957
18726
|
}
|
|
18958
|
-
// src/utils/session.ts
|
|
18959
|
-
var SESSION_ABORT_TIMEOUT_MS = 1000;
|
|
18960
|
-
|
|
18961
|
-
class OperationTimeoutError extends Error {
|
|
18962
|
-
constructor(message) {
|
|
18963
|
-
super(message);
|
|
18964
|
-
this.name = "OperationTimeoutError";
|
|
18965
|
-
}
|
|
18966
|
-
}
|
|
18967
|
-
async function withTimeout(operation, timeoutMs, message) {
|
|
18968
|
-
if (timeoutMs <= 0)
|
|
18969
|
-
return operation;
|
|
18970
|
-
let timer;
|
|
18971
|
-
try {
|
|
18972
|
-
return await Promise.race([
|
|
18973
|
-
operation,
|
|
18974
|
-
new Promise((_, reject) => {
|
|
18975
|
-
timer = setTimeout(() => {
|
|
18976
|
-
reject(new OperationTimeoutError(message));
|
|
18977
|
-
}, timeoutMs);
|
|
18978
|
-
})
|
|
18979
|
-
]);
|
|
18980
|
-
} finally {
|
|
18981
|
-
clearTimeout(timer);
|
|
18982
|
-
}
|
|
18983
|
-
}
|
|
18984
|
-
async function abortSessionWithTimeout(client, sessionId, timeoutMs = SESSION_ABORT_TIMEOUT_MS) {
|
|
18985
|
-
await withTimeout(client.session.abort({ path: { id: sessionId } }), timeoutMs, `Session abort timed out after ${timeoutMs}ms`);
|
|
18986
|
-
}
|
|
18987
|
-
function shortModelLabel(model) {
|
|
18988
|
-
return model.split("/").pop() ?? model;
|
|
18989
|
-
}
|
|
18990
|
-
function parseModelReference(model) {
|
|
18991
|
-
const slashIndex = model.indexOf("/");
|
|
18992
|
-
if (slashIndex <= 0 || slashIndex >= model.length - 1) {
|
|
18993
|
-
return null;
|
|
18994
|
-
}
|
|
18995
|
-
return {
|
|
18996
|
-
providerID: model.slice(0, slashIndex),
|
|
18997
|
-
modelID: model.slice(slashIndex + 1)
|
|
18998
|
-
};
|
|
18999
|
-
}
|
|
19000
|
-
async function promptWithTimeout(client, args, timeoutMs) {
|
|
19001
|
-
if (timeoutMs <= 0) {
|
|
19002
|
-
await client.session.prompt(args);
|
|
19003
|
-
return;
|
|
19004
|
-
}
|
|
19005
|
-
const sessionId = args.path.id;
|
|
19006
|
-
let timer;
|
|
19007
|
-
try {
|
|
19008
|
-
const promptPromise = client.session.prompt(args);
|
|
19009
|
-
promptPromise.catch(() => {});
|
|
19010
|
-
await Promise.race([
|
|
19011
|
-
promptPromise,
|
|
19012
|
-
new Promise((_, reject) => {
|
|
19013
|
-
timer = setTimeout(() => {
|
|
19014
|
-
reject(new OperationTimeoutError(`Prompt timed out after ${timeoutMs}ms`));
|
|
19015
|
-
}, timeoutMs);
|
|
19016
|
-
})
|
|
19017
|
-
]);
|
|
19018
|
-
} catch (error) {
|
|
19019
|
-
if (error instanceof OperationTimeoutError) {
|
|
19020
|
-
try {
|
|
19021
|
-
await abortSessionWithTimeout(client, sessionId);
|
|
19022
|
-
} catch {}
|
|
19023
|
-
}
|
|
19024
|
-
throw error;
|
|
19025
|
-
} finally {
|
|
19026
|
-
clearTimeout(timer);
|
|
19027
|
-
}
|
|
19028
|
-
}
|
|
19029
|
-
async function extractSessionResult(client, sessionId, options) {
|
|
19030
|
-
const includeReasoning = options?.includeReasoning ?? true;
|
|
19031
|
-
const messagesResult = await client.session.messages({
|
|
19032
|
-
path: { id: sessionId }
|
|
19033
|
-
});
|
|
19034
|
-
const messages = messagesResult.data ?? [];
|
|
19035
|
-
const assistantMessages = messages.filter((m) => m.info?.role === "assistant");
|
|
19036
|
-
const extractedContent = [];
|
|
19037
|
-
for (const message of assistantMessages) {
|
|
19038
|
-
for (const part of message.parts ?? []) {
|
|
19039
|
-
const allowed = includeReasoning ? part.type === "text" || part.type === "reasoning" : part.type === "text";
|
|
19040
|
-
if (allowed && part.text) {
|
|
19041
|
-
extractedContent.push(part.text);
|
|
19042
|
-
}
|
|
19043
|
-
}
|
|
19044
|
-
}
|
|
19045
|
-
const text = extractedContent.filter((t) => t.length > 0).join(`
|
|
19046
|
-
|
|
19047
|
-
`);
|
|
19048
|
-
return { text, empty: text.length === 0 };
|
|
19049
|
-
}
|
|
19050
|
-
|
|
19051
18727
|
// src/agents/orchestrator.ts
|
|
19052
18728
|
function resolvePrompt(base, customPrompt, customAppendPrompt) {
|
|
19053
18729
|
if (customPrompt)
|
|
@@ -19064,33 +18740,13 @@ var AGENT_DESCRIPTIONS = {
|
|
|
19064
18740
|
- 权限:只读
|
|
19065
18741
|
- 能力:本地代码搜索(glob/grep/ast)+ 外部文档检索(websearch/context7/grep_app)
|
|
19066
18742
|
- 委派给它当:需要发现代码库中有什么 • 需要查外部库文档 • 并行搜索加速发现
|
|
19067
|
-
- 不委派当:知道路径需要实际内容 • 单次特定查找 •
|
|
19068
|
-
reviewer: `@reviewer
|
|
19069
|
-
- 角色:战略顾问、代码审查者、调试专家
|
|
19070
|
-
- 权限:只读(分析),写操作由 Orchestrator 协调 @implementer 执行
|
|
19071
|
-
- 能力:深度推理、架构分析、根因追踪、代码审查
|
|
19072
|
-
- 委派给它当:重大架构决策 • 复杂调试分析(Phase 1-3)• 代码审查 • 简化/YAGNI 审查
|
|
19073
|
-
- 不委派当:常规决策 • 首次 bug 修复 • 简单权衡
|
|
19074
|
-
- 协调模式:Reviewer 输出 <fix_plan> 时,委派 @implementer 执行修复`,
|
|
19075
|
-
implementer: `@implementer
|
|
19076
|
-
- 角色:快速执行专家
|
|
19077
|
-
- 权限:读写
|
|
19078
|
-
- 能力:代码实现、测试编写、UI/UX 实现
|
|
19079
|
-
- 委派给它当:非平凡的实现任务 • 测试编写/更新 • 多文件修改
|
|
19080
|
-
- 不委派当:需要研究/决策 • 单个小变更(<20 行)• 需求不清楚`,
|
|
19081
|
-
council: `@council(可选,默认禁用)
|
|
19082
|
-
- 角色:多 LLM 共识引擎`
|
|
18743
|
+
- 不委派当:知道路径需要实际内容 • 单次特定查找 • 即将编辑该文件`
|
|
19083
18744
|
};
|
|
19084
18745
|
var DELEGATION_RULES = [
|
|
19085
18746
|
"- 需要搜索代码库或外部文档 → @researcher",
|
|
19086
|
-
"-
|
|
19087
|
-
"-
|
|
19088
|
-
"-
|
|
19089
|
-
"- 知道路径需要内容 → 自己读",
|
|
19090
|
-
"- 单个小变更(<20 行)→ 自己做",
|
|
19091
|
-
"- 需求不清楚 → 问用户,不委派",
|
|
19092
|
-
"- 跳过委派如果开销 ≥ 自己做(Skill 定义的审查流程除外)",
|
|
19093
|
-
"- brainstorming HARD-GATE:设计未批准前,委派任务必须标注 [只读-搜索],禁止委派写入任务"
|
|
18747
|
+
"- 其他所有工作 → 加载对应 Skill,按 Skill 定义的流程执行",
|
|
18748
|
+
"- 单个小变更(<20行)且不涉及设计决策 → 可直接执行",
|
|
18749
|
+
"- 需求不清楚 → 问用户,不委派"
|
|
19094
18750
|
];
|
|
19095
18751
|
function buildOrchestratorPrompt(disabledAgents) {
|
|
19096
18752
|
const enabledAgents = Object.entries(AGENT_DESCRIPTIONS).filter(([name]) => !disabledAgents?.has(name)).map(([, desc]) => desc).join(`
|
|
@@ -19131,13 +18787,10 @@ ${enabledAgents}
|
|
|
19131
18787
|
<Workflow>
|
|
19132
18788
|
1. 理解需求 → 加载 brainstorming skill(如需要)
|
|
19133
18789
|
2. 制定计划 → 加载 writing-plans skill(如需要)
|
|
19134
|
-
3.
|
|
19135
|
-
├─ 实现任务 → 委派
|
|
19136
|
-
├─ 代码审查 → 委派 @reviewer(只读分析)
|
|
19137
|
-
│ └─ 需要修复 → 委派 @implementer(执行修复)
|
|
18790
|
+
3. 执行实现 → 加载 subagent-driven-development skill
|
|
18791
|
+
├─ 实现任务 → 委派 implementer subagent
|
|
19138
18792
|
├─ 代码搜索 → 委派 @researcher
|
|
19139
|
-
└─
|
|
19140
|
-
└─ 需要修复 → 委派 @implementer(Phase 4 执行)
|
|
18793
|
+
└─ 审查 → 委派 spec/code quality reviewer subagent
|
|
19141
18794
|
4. 验证完成 → 加载 verification-before-completion skill
|
|
19142
18795
|
5. 收尾 → 加载 finishing-a-development-branch skill
|
|
19143
18796
|
</Workflow>
|
|
@@ -19198,236 +18851,6 @@ function createOrchestratorAgent(model, customPrompt, customAppendPrompt, disabl
|
|
|
19198
18851
|
return definition;
|
|
19199
18852
|
}
|
|
19200
18853
|
|
|
19201
|
-
// src/agents/council.ts
|
|
19202
|
-
var COUNCIL_AGENT_PROMPT = `You are the Council agent — a multi-LLM orchestration system that runs consensus across multiple models.
|
|
19203
|
-
|
|
19204
|
-
**Tool**: You have access to the \`council_session\` tool.
|
|
19205
|
-
|
|
19206
|
-
**When to use**:
|
|
19207
|
-
- When invoked by a user with a request
|
|
19208
|
-
- When you want multiple expert opinions on a complex problem
|
|
19209
|
-
- When higher confidence is needed through model consensus
|
|
19210
|
-
|
|
19211
|
-
**Usage**:
|
|
19212
|
-
1. Call the \`council_session\` tool with the user's prompt
|
|
19213
|
-
2. Optionally specify a preset (default: "default")
|
|
19214
|
-
3. Receive the councillor responses formatted for synthesis
|
|
19215
|
-
4. Follow the Synthesis Process below
|
|
19216
|
-
5. Present the result to the user
|
|
19217
|
-
|
|
19218
|
-
**Synthesis Process** (MANDATORY — follow in order):
|
|
19219
|
-
1. Read the original user prompt
|
|
19220
|
-
2. Review each councillor's response individually — note each councillor's key insight and unique contribution by name
|
|
19221
|
-
3. Identify agreements and contradictions between councillors
|
|
19222
|
-
4. Resolve contradictions with explicit reasoning
|
|
19223
|
-
5. Synthesize the optimal final answer
|
|
19224
|
-
6. Format output per the Required Output Format below
|
|
19225
|
-
|
|
19226
|
-
**Behavior**:
|
|
19227
|
-
- Delegate requests directly to council_session
|
|
19228
|
-
- Don't pre-analyze or filter the prompt before calling council_session
|
|
19229
|
-
- Credit specific insights from individual councillors using their names
|
|
19230
|
-
- If councillors disagree, explain why you chose one approach over another
|
|
19231
|
-
- Do not omit per-councillor details from the final response
|
|
19232
|
-
- Do not collapse the output into only a final summary
|
|
19233
|
-
- Be transparent about trade-offs when different approaches have valid pros/cons
|
|
19234
|
-
- Don't just average responses — choose the best approach and improve upon it
|
|
19235
|
-
|
|
19236
|
-
**Required Output Format**:
|
|
19237
|
-
Always include these sections in your final response:
|
|
19238
|
-
|
|
19239
|
-
## Council Response
|
|
19240
|
-
Provide the best synthesized answer. Integrate the strongest points from the councillors, resolve disagreements, and give the user a clear final recommendation or answer. Include relevant code examples and concrete details.
|
|
19241
|
-
|
|
19242
|
-
## Councillor Details
|
|
19243
|
-
Include each councillor's response separately.
|
|
19244
|
-
|
|
19245
|
-
Use each councillor name exactly as provided in the tool result.
|
|
19246
|
-
|
|
19247
|
-
Format each councillor like:
|
|
19248
|
-
|
|
19249
|
-
### <councillor name>
|
|
19250
|
-
<that councillor's response>
|
|
19251
|
-
|
|
19252
|
-
If a councillor failed or timed out, include that status briefly.
|
|
19253
|
-
|
|
19254
|
-
## Council Summary
|
|
19255
|
-
Summarize where councillors agreed, where they disagreed, why you chose the final answer, and any remaining uncertainty. Include a consensus confidence rating: unanimous, majority, or split.`;
|
|
19256
|
-
function createCouncilAgent(model, customPrompt, customAppendPrompt) {
|
|
19257
|
-
const prompt = resolvePrompt(COUNCIL_AGENT_PROMPT, customPrompt, customAppendPrompt);
|
|
19258
|
-
const definition = {
|
|
19259
|
-
name: "council",
|
|
19260
|
-
description: "Multi-LLM council agent that synthesizes responses from multiple models for higher-quality outputs",
|
|
19261
|
-
config: {
|
|
19262
|
-
temperature: 0.1,
|
|
19263
|
-
prompt
|
|
19264
|
-
}
|
|
19265
|
-
};
|
|
19266
|
-
if (model) {
|
|
19267
|
-
definition.config.model = model;
|
|
19268
|
-
}
|
|
19269
|
-
return definition;
|
|
19270
|
-
}
|
|
19271
|
-
function formatCouncillorPrompt(userPrompt, councillorPrompt) {
|
|
19272
|
-
if (!councillorPrompt)
|
|
19273
|
-
return userPrompt;
|
|
19274
|
-
return `${councillorPrompt}
|
|
19275
|
-
|
|
19276
|
-
---
|
|
19277
|
-
|
|
19278
|
-
${userPrompt}`;
|
|
19279
|
-
}
|
|
19280
|
-
function formatCouncillorResults(originalPrompt, councillorResults) {
|
|
19281
|
-
const completedWithResults = councillorResults.filter((cr) => cr.status === "completed" && cr.result);
|
|
19282
|
-
const councillorSection = completedWithResults.map((cr) => {
|
|
19283
|
-
const shortModel = shortModelLabel(cr.model);
|
|
19284
|
-
return `**${cr.name}** (${shortModel}):
|
|
19285
|
-
${cr.result}`;
|
|
19286
|
-
}).join(`
|
|
19287
|
-
|
|
19288
|
-
`);
|
|
19289
|
-
const failedSection = councillorResults.filter((cr) => cr.status !== "completed").map((cr) => `**${cr.name}**: ${cr.status} — ${cr.error ?? "Unknown"}`).join(`
|
|
19290
|
-
`);
|
|
19291
|
-
if (completedWithResults.length === 0) {
|
|
19292
|
-
const errorDetails = councillorResults.map((cr) => `**${cr.name}** (${shortModelLabel(cr.model)}): ${cr.status} — ${cr.error ?? "Unknown"}`).join(`
|
|
19293
|
-
`);
|
|
19294
|
-
return `---
|
|
19295
|
-
|
|
19296
|
-
**Original Prompt**:
|
|
19297
|
-
${originalPrompt}
|
|
19298
|
-
|
|
19299
|
-
---
|
|
19300
|
-
|
|
19301
|
-
**Councillor Responses**:
|
|
19302
|
-
All councillors failed to produce output:
|
|
19303
|
-
${errorDetails}
|
|
19304
|
-
|
|
19305
|
-
Please generate a response based on the original prompt alone.`;
|
|
19306
|
-
}
|
|
19307
|
-
let prompt = `---
|
|
19308
|
-
|
|
19309
|
-
**Original Prompt**:
|
|
19310
|
-
${originalPrompt}
|
|
19311
|
-
|
|
19312
|
-
---
|
|
19313
|
-
|
|
19314
|
-
**Councillor Responses**:
|
|
19315
|
-
${councillorSection}`;
|
|
19316
|
-
if (failedSection) {
|
|
19317
|
-
prompt += `
|
|
19318
|
-
|
|
19319
|
-
---
|
|
19320
|
-
|
|
19321
|
-
**Failed/Timed-out Councillors**:
|
|
19322
|
-
${failedSection}`;
|
|
19323
|
-
}
|
|
19324
|
-
prompt += `
|
|
19325
|
-
|
|
19326
|
-
---
|
|
19327
|
-
|
|
19328
|
-
You MUST follow the Synthesis Process steps before producing output: review each councillor response individually, then produce the required output with a synthesized Council Response, per-councillor details using their exact names, and a Council Summary with consensus confidence rating (unanimous, majority, or split).`;
|
|
19329
|
-
return prompt;
|
|
19330
|
-
}
|
|
19331
|
-
|
|
19332
|
-
// src/agents/councillor.ts
|
|
19333
|
-
var COUNCILLOR_PROMPT = `You are a councillor in a multi-model council.
|
|
19334
|
-
|
|
19335
|
-
**Role**: Provide your best independent analysis and solution to the given problem.
|
|
19336
|
-
|
|
19337
|
-
**Capabilities**: You have read-only access to the codebase. You can:
|
|
19338
|
-
- Read files (read)
|
|
19339
|
-
- Search by name patterns (glob)
|
|
19340
|
-
- Search by content (grep)
|
|
19341
|
-
- Search code patterns (ast_grep_search)
|
|
19342
|
-
- Use OpenCode's built-in \`lsp\` tool when available
|
|
19343
|
-
- Search external docs (if MCPs are configured for this agent)
|
|
19344
|
-
|
|
19345
|
-
You CANNOT edit files, write files, run shell commands, or delegate to other agents. You are an advisor, not an implementer.
|
|
19346
|
-
|
|
19347
|
-
**Behavior**:
|
|
19348
|
-
- **Examine the codebase** before answering — your read access is what makes council valuable. Don't guess at code you can see.
|
|
19349
|
-
- Analyze the problem thoroughly
|
|
19350
|
-
- Provide a complete, well-reasoned response
|
|
19351
|
-
- Focus on the quality and correctness of your solution
|
|
19352
|
-
- Be direct and concise
|
|
19353
|
-
- Don't be influenced by what other councillors might say — you won't see their responses
|
|
19354
|
-
|
|
19355
|
-
**Output**:
|
|
19356
|
-
- Give your honest assessment
|
|
19357
|
-
- Reference specific files and line numbers when relevant
|
|
19358
|
-
- Include relevant reasoning
|
|
19359
|
-
- State any assumptions clearly
|
|
19360
|
-
- Note any uncertainties`;
|
|
19361
|
-
function createCouncillorAgent(model, customPrompt, customAppendPrompt) {
|
|
19362
|
-
const prompt = resolvePrompt(COUNCILLOR_PROMPT, customPrompt, customAppendPrompt);
|
|
19363
|
-
return {
|
|
19364
|
-
name: "councillor",
|
|
19365
|
-
description: "Read-only council advisor. Examines codebase and provides independent analysis. Spawned internally by the council system.",
|
|
19366
|
-
config: {
|
|
19367
|
-
model,
|
|
19368
|
-
temperature: 0.2,
|
|
19369
|
-
prompt,
|
|
19370
|
-
permission: {
|
|
19371
|
-
"*": "deny",
|
|
19372
|
-
question: "deny",
|
|
19373
|
-
read: "allow",
|
|
19374
|
-
glob: "allow",
|
|
19375
|
-
grep: "allow",
|
|
19376
|
-
lsp: "allow",
|
|
19377
|
-
list: "allow",
|
|
19378
|
-
codesearch: "allow",
|
|
19379
|
-
ast_grep_search: "allow"
|
|
19380
|
-
}
|
|
19381
|
-
}
|
|
19382
|
-
};
|
|
19383
|
-
}
|
|
19384
|
-
|
|
19385
|
-
// src/agents/implementer.ts
|
|
19386
|
-
var IMPLEMENTER_PROMPT = `You are Implementer — a fast execution specialist. Execute directly with complete context provided.
|
|
19387
|
-
|
|
19388
|
-
**Role**: Receive complete task specs from the Orchestrator and implement efficiently.
|
|
19389
|
-
|
|
19390
|
-
## Modes
|
|
19391
|
-
- **Execution Mode (default)**: Low-temperature precise execution. No divergence, no research. Implement the task directly.
|
|
19392
|
-
- **Design Mode**: When Orchestrator marks [设计模式] in the prompt, switch to creative design thinking:
|
|
19393
|
-
- Focus on aesthetics, layout, interaction details
|
|
19394
|
-
- Follow design principles: typography, color themes, motion, spatial composition, visual depth
|
|
19395
|
-
- Use Tailwind for responsive design
|
|
19396
|
-
|
|
19397
|
-
## Constraints
|
|
19398
|
-
- NO external research (no websearch, context7, grep_app)
|
|
19399
|
-
- NO delegation or spawning subagents
|
|
19400
|
-
- No multi-step planning; direct execution
|
|
19401
|
-
- When a loaded Skill indicates user input is needed, pause and request clarification
|
|
19402
|
-
- When TDD Skill is loaded, follow red-green-refactor cycle
|
|
19403
|
-
|
|
19404
|
-
## Loadable Skills
|
|
19405
|
-
You can load behavioral guides via the skill tool:
|
|
19406
|
-
- test-driven-development: Load when implementing features or fixing bugs
|
|
19407
|
-
- verification-before-completion: Load when verifying work before completion
|
|
19408
|
-
|
|
19409
|
-
## Output Format
|
|
19410
|
-
<summary>Brief summary of what was implemented</summary>
|
|
19411
|
-
<changes>
|
|
19412
|
-
<file>file1.ts: Changed X to Y</file>
|
|
19413
|
-
<file>file2.ts: Added Z function</file>
|
|
19414
|
-
</changes>
|
|
19415
|
-
<verification>
|
|
19416
|
-
Tests passed: [yes/no/skip reason]
|
|
19417
|
-
Validation: [passed/failed/skip reason]
|
|
19418
|
-
</verification>`;
|
|
19419
|
-
function createImplementerAgent(model, customPrompt, customAppendPrompt) {
|
|
19420
|
-
return {
|
|
19421
|
-
name: "implementer",
|
|
19422
|
-
description: "Fast implementation specialist. Receives complete context and task spec, executes code changes efficiently. Supports execution and design modes.",
|
|
19423
|
-
config: {
|
|
19424
|
-
model,
|
|
19425
|
-
temperature: 0.2,
|
|
19426
|
-
prompt: resolvePrompt(IMPLEMENTER_PROMPT, customPrompt, customAppendPrompt)
|
|
19427
|
-
}
|
|
19428
|
-
};
|
|
19429
|
-
}
|
|
19430
|
-
|
|
19431
18854
|
// src/agents/researcher.ts
|
|
19432
18855
|
var RESEARCHER_PROMPT = `You are Researcher — a codebase and external documentation search specialist.
|
|
19433
18856
|
|
|
@@ -19470,62 +18893,7 @@ function createResearcherAgent(model, customPrompt, customAppendPrompt) {
|
|
|
19470
18893
|
};
|
|
19471
18894
|
}
|
|
19472
18895
|
|
|
19473
|
-
// src/agents/reviewer.ts
|
|
19474
|
-
var REVIEWER_PROMPT = `You are Reviewer — a strategic advisor and code review expert. Analysis only, no execution.
|
|
19475
|
-
|
|
19476
|
-
**Role**: High-IQ debugging, architecture decisions, code review, simplification, and engineering guidance.
|
|
19477
|
-
|
|
19478
|
-
## Responsibilities
|
|
19479
|
-
- Architecture decisions and solution evaluation
|
|
19480
|
-
- Code review (review diffs, not self-review)
|
|
19481
|
-
- Root cause analysis for complex debugging (Phase 1-3)
|
|
19482
|
-
- Simplification and YAGNI review
|
|
19483
|
-
|
|
19484
|
-
## Execution Boundary
|
|
19485
|
-
You only analyze, never execute. When a Skill workflow requires writing code or running commands:
|
|
19486
|
-
- Complete the analysis phase, output structured analysis results and fix plans
|
|
19487
|
-
- Orchestrator coordinates Implementer to execute fixes
|
|
19488
|
-
- Specific rules:
|
|
19489
|
-
- systematic-debugging: You complete Phase 1-3, output fix plan for Phase 4
|
|
19490
|
-
- receiving-code-review: You complete READ → VERIFY → EVALUATE, output fix plan for IMPLEMENT
|
|
19491
|
-
- simplify: You analyze simplification opportunities, output plan for execution
|
|
19492
|
-
|
|
19493
|
-
## Principles
|
|
19494
|
-
- Hold dissenting opinions until convinced by technical arguments
|
|
19495
|
-
- Verify before agreeing — no performative agreement
|
|
19496
|
-
- 3+ fix failures → question the architecture, don't keep patching
|
|
19497
|
-
- receiving-code-review: explicitly forbidden from expressions of gratitude (e.g., "You're absolutely right!", "Great point!") — avoid performative agreement, go straight to technical verification
|
|
19498
|
-
|
|
19499
|
-
## Loadable Skills
|
|
19500
|
-
You can load behavioral guides via the skill tool:
|
|
19501
|
-
- systematic-debugging: Load when debugging complex bugs (Phase 1-3 analysis)
|
|
19502
|
-
- receiving-code-review: Load when evaluating external feedback (READ → VERIFY → EVALUATE)
|
|
19503
|
-
- simplify: Load when reviewing code for simplification (analyze opportunities, output plan)
|
|
19504
|
-
|
|
19505
|
-
## Output Format
|
|
19506
|
-
<assessment>Overall assessment</assessment>
|
|
19507
|
-
<strengths>What was done well</strengths>
|
|
19508
|
-
<issues>
|
|
19509
|
-
<issue severity="critical">Must-fix issues</issue>
|
|
19510
|
-
<issue severity="important">Should-fix issues</issue>
|
|
19511
|
-
<issue severity="minor">Nice-to-have improvements</issue>
|
|
19512
|
-
</issues>
|
|
19513
|
-
<fix_plan>Fix plan for Orchestrator to coordinate Implementer execution</fix_plan>
|
|
19514
|
-
<recommendation>Recommended next steps</recommendation>`;
|
|
19515
|
-
function createReviewerAgent(model, customPrompt, customAppendPrompt) {
|
|
19516
|
-
return {
|
|
19517
|
-
name: "reviewer",
|
|
19518
|
-
description: "Strategic technical advisor. Use for architecture decisions, complex debugging, code review, simplification, and engineering guidance.",
|
|
19519
|
-
config: {
|
|
19520
|
-
model,
|
|
19521
|
-
temperature: 0.1,
|
|
19522
|
-
prompt: resolvePrompt(REVIEWER_PROMPT, customPrompt, customAppendPrompt)
|
|
19523
|
-
}
|
|
19524
|
-
};
|
|
19525
|
-
}
|
|
19526
|
-
|
|
19527
18896
|
// src/agents/index.ts
|
|
19528
|
-
var COUNCIL_TOOL_ALLOWED_AGENTS = new Set(["council"]);
|
|
19529
18897
|
var SAFE_AGENT_ALIAS_RE = /^[a-z][a-z0-9_-]*$/i;
|
|
19530
18898
|
function normalizeDisplayName(displayName) {
|
|
19531
18899
|
const trimmed = displayName.trim();
|
|
@@ -19580,7 +18948,7 @@ function buildCustomAgentDefinition(name, override, filePrompt, fileAppendPrompt
|
|
|
19580
18948
|
return {
|
|
19581
18949
|
name,
|
|
19582
18950
|
config: {
|
|
19583
|
-
model: typeof override.model === "string" ? override.model : DEFAULT_MODELS.orchestrator ?? DEFAULT_MODELS.
|
|
18951
|
+
model: typeof override.model === "string" ? override.model : DEFAULT_MODELS.orchestrator ?? DEFAULT_MODELS.researcher,
|
|
19584
18952
|
temperature: 0.2,
|
|
19585
18953
|
prompt: resolvePrompt(basePrompt, filePrompt, fileAppendPrompt)
|
|
19586
18954
|
}
|
|
@@ -19601,11 +18969,9 @@ function applyDefaultPermissions(agent, configuredSkills) {
|
|
|
19601
18969
|
const existing = agent.config.permission ?? {};
|
|
19602
18970
|
const skillPermissions = getSkillPermissionsForAgent(agent.name, configuredSkills);
|
|
19603
18971
|
const questionPerm = existing.question === "deny" ? "deny" : "allow";
|
|
19604
|
-
const councilSessionPerm = COUNCIL_TOOL_ALLOWED_AGENTS.has(agent.name) ? existing.council_session ?? "allow" : "deny";
|
|
19605
18972
|
agent.config.permission = {
|
|
19606
18973
|
...existing,
|
|
19607
18974
|
question: questionPerm,
|
|
19608
|
-
council_session: councilSessionPerm,
|
|
19609
18975
|
skill: {
|
|
19610
18976
|
...typeof existing.skill === "object" ? existing.skill : {},
|
|
19611
18977
|
...skillPermissions
|
|
@@ -19616,17 +18982,10 @@ function isSubagent(name) {
|
|
|
19616
18982
|
return SUBAGENT_NAMES.includes(name);
|
|
19617
18983
|
}
|
|
19618
18984
|
var SUBAGENT_FACTORIES = {
|
|
19619
|
-
researcher: createResearcherAgent
|
|
19620
|
-
reviewer: createReviewerAgent,
|
|
19621
|
-
implementer: createImplementerAgent,
|
|
19622
|
-
council: createCouncilAgent,
|
|
19623
|
-
councillor: createCouncillorAgent
|
|
18985
|
+
researcher: createResearcherAgent
|
|
19624
18986
|
};
|
|
19625
18987
|
function createAgents(config) {
|
|
19626
18988
|
const disabled = getDisabledAgents(config);
|
|
19627
|
-
if (!config?.council) {
|
|
19628
|
-
disabled.add("council");
|
|
19629
|
-
}
|
|
19630
18989
|
const protoSubAgents = Object.entries(SUBAGENT_FACTORIES).filter(([name]) => !disabled.has(name)).map(([name, factory]) => {
|
|
19631
18990
|
const customPrompts = loadAgentPrompt(name, config?.preset);
|
|
19632
18991
|
const model = DEFAULT_MODELS[name];
|
|
@@ -19660,13 +19019,6 @@ function createAgents(config) {
|
|
|
19660
19019
|
applyDefaultPermissions(agent, override?.skills);
|
|
19661
19020
|
return agent;
|
|
19662
19021
|
});
|
|
19663
|
-
const legacyMasterModel = config?.council?._legacyMasterModel;
|
|
19664
|
-
if (legacyMasterModel) {
|
|
19665
|
-
const councilAgent = builtInSubAgents.find((a) => a.name === "council");
|
|
19666
|
-
if (councilAgent && !getAgentOverride(config, "council")?.model && councilAgent.config.model === DEFAULT_MODELS.council) {
|
|
19667
|
-
councilAgent.config.model = legacyMasterModel;
|
|
19668
|
-
}
|
|
19669
|
-
}
|
|
19670
19022
|
const customSubAgents = protoCustomAgents.map((agent) => {
|
|
19671
19023
|
const override = getAgentOverride(config, agent.name);
|
|
19672
19024
|
if (override) {
|
|
@@ -19733,12 +19085,7 @@ ${rewrittenPrompts.join(`
|
|
|
19733
19085
|
function getAgentConfigs(config) {
|
|
19734
19086
|
const agents = createAgents(config);
|
|
19735
19087
|
const applyClassification = (name, sdkConfig) => {
|
|
19736
|
-
if (name
|
|
19737
|
-
sdkConfig.mode = "all";
|
|
19738
|
-
} else if (name === "councillor") {
|
|
19739
|
-
sdkConfig.mode = "subagent";
|
|
19740
|
-
sdkConfig.hidden = true;
|
|
19741
|
-
} else if (isSubagent(name)) {
|
|
19088
|
+
if (isSubagent(name)) {
|
|
19742
19089
|
sdkConfig.mode = "subagent";
|
|
19743
19090
|
} else if (name === "orchestrator") {
|
|
19744
19091
|
sdkConfig.mode = "primary";
|
|
@@ -19746,7 +19093,6 @@ function getAgentConfigs(config) {
|
|
|
19746
19093
|
sdkConfig.mode = "subagent";
|
|
19747
19094
|
}
|
|
19748
19095
|
};
|
|
19749
|
-
const isInternalOnly = (name) => name === "councillor";
|
|
19750
19096
|
const entries = [];
|
|
19751
19097
|
for (const a of agents) {
|
|
19752
19098
|
const sdkConfig = {
|
|
@@ -19759,7 +19105,7 @@ function getAgentConfigs(config) {
|
|
|
19759
19105
|
}
|
|
19760
19106
|
applyClassification(a.name, sdkConfig);
|
|
19761
19107
|
const normalizedDisplayName = a.displayName ? normalizeDisplayName(a.displayName) : undefined;
|
|
19762
|
-
if (normalizedDisplayName
|
|
19108
|
+
if (normalizedDisplayName) {
|
|
19763
19109
|
entries.push([normalizedDisplayName, sdkConfig]);
|
|
19764
19110
|
entries.push([a.name, { ...sdkConfig, hidden: true }]);
|
|
19765
19111
|
continue;
|
|
@@ -19801,6 +19147,13 @@ function rollbackRuntimePreset(previous) {
|
|
|
19801
19147
|
previousRuntimePreset = null;
|
|
19802
19148
|
}
|
|
19803
19149
|
|
|
19150
|
+
// src/divoom/manager.ts
|
|
19151
|
+
import { spawn } from "node:child_process";
|
|
19152
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2 } from "node:fs";
|
|
19153
|
+
import * as os2 from "node:os";
|
|
19154
|
+
import path3 from "node:path";
|
|
19155
|
+
import { fileURLToPath } from "node:url";
|
|
19156
|
+
|
|
19804
19157
|
// src/utils/logger.ts
|
|
19805
19158
|
import * as fs2 from "node:fs";
|
|
19806
19159
|
import { appendFile } from "node:fs/promises";
|
|
@@ -19878,263 +19231,7 @@ function log(message, data) {
|
|
|
19878
19231
|
} catch {}
|
|
19879
19232
|
}
|
|
19880
19233
|
|
|
19881
|
-
// src/council/council-manager.ts
|
|
19882
|
-
class CouncilManager {
|
|
19883
|
-
client;
|
|
19884
|
-
directory;
|
|
19885
|
-
config;
|
|
19886
|
-
depthTracker;
|
|
19887
|
-
tmuxEnabled;
|
|
19888
|
-
deprecatedFields;
|
|
19889
|
-
legacyMasterModel;
|
|
19890
|
-
constructor(ctx, config, depthTracker, tmuxEnabled = false) {
|
|
19891
|
-
this.client = ctx.client;
|
|
19892
|
-
this.directory = ctx.directory;
|
|
19893
|
-
this.config = config;
|
|
19894
|
-
this.deprecatedFields = config?.council?._deprecated;
|
|
19895
|
-
this.legacyMasterModel = config?.council?._legacyMasterModel;
|
|
19896
|
-
this.depthTracker = depthTracker;
|
|
19897
|
-
this.tmuxEnabled = tmuxEnabled;
|
|
19898
|
-
}
|
|
19899
|
-
getDeprecatedFields() {
|
|
19900
|
-
return this.deprecatedFields;
|
|
19901
|
-
}
|
|
19902
|
-
getLegacyMasterModel() {
|
|
19903
|
-
return this.legacyMasterModel;
|
|
19904
|
-
}
|
|
19905
|
-
async runCouncil(prompt, presetName, parentSessionId) {
|
|
19906
|
-
if (this.depthTracker) {
|
|
19907
|
-
const parentDepth = this.depthTracker.getDepth(parentSessionId);
|
|
19908
|
-
if (parentDepth + 1 > this.depthTracker.maxDepth) {
|
|
19909
|
-
log("[council-manager] spawn blocked: max depth exceeded", {
|
|
19910
|
-
parentSessionId,
|
|
19911
|
-
parentDepth,
|
|
19912
|
-
maxDepth: this.depthTracker.maxDepth
|
|
19913
|
-
});
|
|
19914
|
-
return {
|
|
19915
|
-
success: false,
|
|
19916
|
-
error: "Subagent depth exceeded",
|
|
19917
|
-
councillorResults: []
|
|
19918
|
-
};
|
|
19919
|
-
}
|
|
19920
|
-
}
|
|
19921
|
-
const councilConfig = this.config?.council;
|
|
19922
|
-
if (!councilConfig) {
|
|
19923
|
-
log("[council-manager] Council configuration not found");
|
|
19924
|
-
return {
|
|
19925
|
-
success: false,
|
|
19926
|
-
error: "Council not configured",
|
|
19927
|
-
councillorResults: []
|
|
19928
|
-
};
|
|
19929
|
-
}
|
|
19930
|
-
const resolvedPreset = presetName ?? councilConfig.default_preset ?? "default";
|
|
19931
|
-
const preset = councilConfig.presets[resolvedPreset];
|
|
19932
|
-
if (!preset) {
|
|
19933
|
-
const available = Object.keys(councilConfig.presets).join(", ");
|
|
19934
|
-
log(`[council-manager] Preset "${resolvedPreset}" not found`);
|
|
19935
|
-
return {
|
|
19936
|
-
success: false,
|
|
19937
|
-
error: `Preset "${resolvedPreset}" does not exist. Omit the preset parameter to use the default, or call again with one of: ${available}`,
|
|
19938
|
-
councillorResults: []
|
|
19939
|
-
};
|
|
19940
|
-
}
|
|
19941
|
-
if (Object.keys(preset).length === 0) {
|
|
19942
|
-
log(`[council-manager] Preset "${resolvedPreset}" has no councillors`);
|
|
19943
|
-
return {
|
|
19944
|
-
success: false,
|
|
19945
|
-
error: `Preset "${resolvedPreset}" has no councillors configured. Note: the reserved key "master" is ignored — use councillor names as keys`,
|
|
19946
|
-
councillorResults: []
|
|
19947
|
-
};
|
|
19948
|
-
}
|
|
19949
|
-
const timeout = councilConfig.timeout ?? 180000;
|
|
19950
|
-
const executionMode = councilConfig.councillor_execution_mode ?? "parallel";
|
|
19951
|
-
const maxRetries = councilConfig.councillor_retries ?? 3;
|
|
19952
|
-
const councillorCount = Object.keys(preset).length;
|
|
19953
|
-
log(`[council-manager] Starting council with preset "${resolvedPreset}"`, {
|
|
19954
|
-
councillors: Object.keys(preset)
|
|
19955
|
-
});
|
|
19956
|
-
this.sendStartNotification(parentSessionId, councillorCount).catch((err) => {
|
|
19957
|
-
log("[council-manager] Failed to send start notification", {
|
|
19958
|
-
error: err instanceof Error ? err.message : String(err)
|
|
19959
|
-
});
|
|
19960
|
-
});
|
|
19961
|
-
const councillorResults = await this.runCouncillors(prompt, preset, parentSessionId, timeout, executionMode, maxRetries);
|
|
19962
|
-
const completedCount = councillorResults.filter((r) => r.status === "completed").length;
|
|
19963
|
-
log(`[council-manager] Councillors completed: ${completedCount}/${councillorResults.length}`);
|
|
19964
|
-
if (completedCount === 0) {
|
|
19965
|
-
return {
|
|
19966
|
-
success: false,
|
|
19967
|
-
error: "All councillors failed or timed out",
|
|
19968
|
-
councillorResults
|
|
19969
|
-
};
|
|
19970
|
-
}
|
|
19971
|
-
const formattedCouncillorResults = formatCouncillorResults(prompt, councillorResults);
|
|
19972
|
-
log("[council-manager] Council completed successfully");
|
|
19973
|
-
return {
|
|
19974
|
-
success: true,
|
|
19975
|
-
result: formattedCouncillorResults,
|
|
19976
|
-
councillorResults
|
|
19977
|
-
};
|
|
19978
|
-
}
|
|
19979
|
-
async sendStartNotification(parentSessionId, councillorCount) {
|
|
19980
|
-
const message = [
|
|
19981
|
-
`⎔ Council starting — ${councillorCount} councillors launching — ctrl+x ↓ to watch`,
|
|
19982
|
-
"",
|
|
19983
|
-
"[system status: continue without acknowledging this notification]"
|
|
19984
|
-
].join(`
|
|
19985
|
-
`);
|
|
19986
|
-
await this.client.session.prompt({
|
|
19987
|
-
path: { id: parentSessionId },
|
|
19988
|
-
body: {
|
|
19989
|
-
noReply: true,
|
|
19990
|
-
parts: [{ type: "text", text: message }]
|
|
19991
|
-
}
|
|
19992
|
-
});
|
|
19993
|
-
}
|
|
19994
|
-
async runAgentSession(options) {
|
|
19995
|
-
const modelRef = parseModelReference(options.model);
|
|
19996
|
-
if (!modelRef) {
|
|
19997
|
-
throw new Error(`Invalid model format: ${options.model}`);
|
|
19998
|
-
}
|
|
19999
|
-
let sessionId;
|
|
20000
|
-
try {
|
|
20001
|
-
const session = await this.client.session.create({
|
|
20002
|
-
body: {
|
|
20003
|
-
parentID: options.parentSessionId,
|
|
20004
|
-
title: options.title
|
|
20005
|
-
},
|
|
20006
|
-
query: { directory: this.directory }
|
|
20007
|
-
});
|
|
20008
|
-
if (!session.data?.id) {
|
|
20009
|
-
throw new Error("Failed to create session");
|
|
20010
|
-
}
|
|
20011
|
-
sessionId = session.data.id;
|
|
20012
|
-
if (this.depthTracker) {
|
|
20013
|
-
const registered = this.depthTracker.registerChild(options.parentSessionId, sessionId);
|
|
20014
|
-
if (!registered) {
|
|
20015
|
-
throw new Error("Subagent depth exceeded");
|
|
20016
|
-
}
|
|
20017
|
-
}
|
|
20018
|
-
if (this.tmuxEnabled) {
|
|
20019
|
-
await new Promise((r) => setTimeout(r, TMUX_SPAWN_DELAY_MS));
|
|
20020
|
-
}
|
|
20021
|
-
const body = {
|
|
20022
|
-
agent: options.agent,
|
|
20023
|
-
model: modelRef,
|
|
20024
|
-
tools: { task: false },
|
|
20025
|
-
parts: [{ type: "text", text: options.promptText }]
|
|
20026
|
-
};
|
|
20027
|
-
if (options.variant) {
|
|
20028
|
-
body.variant = options.variant;
|
|
20029
|
-
}
|
|
20030
|
-
await promptWithTimeout(this.client, {
|
|
20031
|
-
path: { id: sessionId },
|
|
20032
|
-
body,
|
|
20033
|
-
query: { directory: this.directory }
|
|
20034
|
-
}, options.timeout);
|
|
20035
|
-
const extraction = await extractSessionResult(this.client, sessionId, {
|
|
20036
|
-
includeReasoning: options.includeReasoning
|
|
20037
|
-
});
|
|
20038
|
-
if (extraction.empty) {
|
|
20039
|
-
const retryOnEmpty = this.config?.fallback?.retry_on_empty ?? true;
|
|
20040
|
-
if (retryOnEmpty) {
|
|
20041
|
-
throw new Error("Empty response from provider");
|
|
20042
|
-
}
|
|
20043
|
-
}
|
|
20044
|
-
return extraction.text;
|
|
20045
|
-
} finally {
|
|
20046
|
-
if (sessionId) {
|
|
20047
|
-
this.client.session.abort({ path: { id: sessionId } }).catch(() => {});
|
|
20048
|
-
if (this.depthTracker) {
|
|
20049
|
-
this.depthTracker.cleanup(sessionId);
|
|
20050
|
-
}
|
|
20051
|
-
}
|
|
20052
|
-
}
|
|
20053
|
-
}
|
|
20054
|
-
async runCouncillors(prompt, councillors, parentSessionId, timeout, executionMode = "parallel", maxRetries) {
|
|
20055
|
-
const entries = Object.entries(councillors);
|
|
20056
|
-
const results = [];
|
|
20057
|
-
if (executionMode === "serial") {
|
|
20058
|
-
for (const [name, config] of entries) {
|
|
20059
|
-
results.push(await this.runCouncillorWithRetry(name, config, prompt, parentSessionId, timeout, maxRetries));
|
|
20060
|
-
}
|
|
20061
|
-
} else {
|
|
20062
|
-
const promises = entries.map(([name, config], index) => (async () => {
|
|
20063
|
-
if (this.tmuxEnabled && index > 0) {
|
|
20064
|
-
await new Promise((r) => setTimeout(r, index * COUNCILLOR_STAGGER_MS));
|
|
20065
|
-
}
|
|
20066
|
-
return this.runCouncillorWithRetry(name, config, prompt, parentSessionId, timeout, maxRetries);
|
|
20067
|
-
})());
|
|
20068
|
-
const settled = await Promise.allSettled(promises);
|
|
20069
|
-
for (let index = 0;index < settled.length; index++) {
|
|
20070
|
-
const result = settled[index];
|
|
20071
|
-
const [name, cfg] = entries[index];
|
|
20072
|
-
if (result.status === "fulfilled") {
|
|
20073
|
-
results.push(result.value);
|
|
20074
|
-
} else {
|
|
20075
|
-
results.push({
|
|
20076
|
-
name,
|
|
20077
|
-
model: cfg.model,
|
|
20078
|
-
status: "failed",
|
|
20079
|
-
error: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
20080
|
-
});
|
|
20081
|
-
}
|
|
20082
|
-
}
|
|
20083
|
-
}
|
|
20084
|
-
return results;
|
|
20085
|
-
}
|
|
20086
|
-
async runCouncillorWithRetry(name, config, prompt, parentSessionId, timeout, maxRetries) {
|
|
20087
|
-
const modelLabel = shortModelLabel(config.model);
|
|
20088
|
-
const totalAttempts = 1 + maxRetries;
|
|
20089
|
-
for (let attempt = 1;attempt <= totalAttempts; attempt++) {
|
|
20090
|
-
if (attempt > 1) {
|
|
20091
|
-
log(`[council-manager] Retrying councillor "${name}" (${modelLabel}), attempt ${attempt}/${totalAttempts}`);
|
|
20092
|
-
}
|
|
20093
|
-
try {
|
|
20094
|
-
const result = await this.runAgentSession({
|
|
20095
|
-
parentSessionId,
|
|
20096
|
-
title: `Council ${name} (${modelLabel})`,
|
|
20097
|
-
agent: "councillor",
|
|
20098
|
-
model: config.model,
|
|
20099
|
-
promptText: formatCouncillorPrompt(prompt, config.prompt),
|
|
20100
|
-
variant: config.variant,
|
|
20101
|
-
timeout,
|
|
20102
|
-
includeReasoning: false
|
|
20103
|
-
});
|
|
20104
|
-
return {
|
|
20105
|
-
name,
|
|
20106
|
-
model: config.model,
|
|
20107
|
-
status: "completed",
|
|
20108
|
-
result
|
|
20109
|
-
};
|
|
20110
|
-
} catch (error) {
|
|
20111
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
20112
|
-
const isEmptyResponse = msg.includes("Empty response from provider");
|
|
20113
|
-
const canRetry = attempt < totalAttempts && isEmptyResponse;
|
|
20114
|
-
if (!canRetry) {
|
|
20115
|
-
return {
|
|
20116
|
-
name,
|
|
20117
|
-
model: config.model,
|
|
20118
|
-
status: msg.includes("timed out") ? "timed_out" : "failed",
|
|
20119
|
-
error: `Councillor "${name}": ${msg}`
|
|
20120
|
-
};
|
|
20121
|
-
}
|
|
20122
|
-
}
|
|
20123
|
-
}
|
|
20124
|
-
return {
|
|
20125
|
-
name,
|
|
20126
|
-
model: config.model,
|
|
20127
|
-
status: "failed",
|
|
20128
|
-
error: `Councillor "${name}": max retries exhausted`
|
|
20129
|
-
};
|
|
20130
|
-
}
|
|
20131
|
-
}
|
|
20132
19234
|
// src/divoom/manager.ts
|
|
20133
|
-
import { spawn } from "node:child_process";
|
|
20134
|
-
import { existsSync as existsSync2, mkdirSync as mkdirSync2 } from "node:fs";
|
|
20135
|
-
import * as os2 from "node:os";
|
|
20136
|
-
import path3 from "node:path";
|
|
20137
|
-
import { fileURLToPath } from "node:url";
|
|
20138
19235
|
var AGENT_GIFS = {
|
|
20139
19236
|
council: "council.gif",
|
|
20140
19237
|
councillor: "council.gif",
|
|
@@ -21958,10 +21055,6 @@ async function crossWrite(path6, data) {
|
|
|
21958
21055
|
// src/hooks/auto-update-checker/cache.ts
|
|
21959
21056
|
import * as fs5 from "node:fs";
|
|
21960
21057
|
import * as path8 from "node:path";
|
|
21961
|
-
|
|
21962
|
-
// src/cli/config-manager.ts
|
|
21963
|
-
init_paths();
|
|
21964
|
-
|
|
21965
21058
|
// src/hooks/auto-update-checker/checker.ts
|
|
21966
21059
|
import * as fs4 from "node:fs";
|
|
21967
21060
|
import * as path7 from "node:path";
|
|
@@ -22457,6 +21550,45 @@ function hasInternalInitiatorMarker(part) {
|
|
|
22457
21550
|
}
|
|
22458
21551
|
return part.text.includes(SLIM_INTERNAL_INITIATOR_MARKER);
|
|
22459
21552
|
}
|
|
21553
|
+
// src/utils/session.ts
|
|
21554
|
+
var SESSION_ABORT_TIMEOUT_MS = 1000;
|
|
21555
|
+
|
|
21556
|
+
class OperationTimeoutError extends Error {
|
|
21557
|
+
constructor(message) {
|
|
21558
|
+
super(message);
|
|
21559
|
+
this.name = "OperationTimeoutError";
|
|
21560
|
+
}
|
|
21561
|
+
}
|
|
21562
|
+
async function withTimeout(operation, timeoutMs, message) {
|
|
21563
|
+
if (timeoutMs <= 0)
|
|
21564
|
+
return operation;
|
|
21565
|
+
let timer;
|
|
21566
|
+
try {
|
|
21567
|
+
return await Promise.race([
|
|
21568
|
+
operation,
|
|
21569
|
+
new Promise((_, reject) => {
|
|
21570
|
+
timer = setTimeout(() => {
|
|
21571
|
+
reject(new OperationTimeoutError(message));
|
|
21572
|
+
}, timeoutMs);
|
|
21573
|
+
})
|
|
21574
|
+
]);
|
|
21575
|
+
} finally {
|
|
21576
|
+
clearTimeout(timer);
|
|
21577
|
+
}
|
|
21578
|
+
}
|
|
21579
|
+
async function abortSessionWithTimeout(client, sessionId, timeoutMs = SESSION_ABORT_TIMEOUT_MS) {
|
|
21580
|
+
await withTimeout(client.session.abort({ path: { id: sessionId } }), timeoutMs, `Session abort timed out after ${timeoutMs}ms`);
|
|
21581
|
+
}
|
|
21582
|
+
function parseModelReference(model) {
|
|
21583
|
+
const slashIndex = model.indexOf("/");
|
|
21584
|
+
if (slashIndex <= 0 || slashIndex >= model.length - 1) {
|
|
21585
|
+
return null;
|
|
21586
|
+
}
|
|
21587
|
+
return {
|
|
21588
|
+
providerID: model.slice(0, slashIndex),
|
|
21589
|
+
modelID: model.slice(slashIndex + 1)
|
|
21590
|
+
};
|
|
21591
|
+
}
|
|
22460
21592
|
// src/utils/session-manager.ts
|
|
22461
21593
|
var MIN_CONTEXT_FILE_LINES = 10;
|
|
22462
21594
|
var MAX_CONTEXT_FILES_PER_SESSION = 8;
|
|
@@ -22464,14 +21596,6 @@ function aliasPrefix(agentType) {
|
|
|
22464
21596
|
switch (agentType) {
|
|
22465
21597
|
case "researcher":
|
|
22466
21598
|
return "res";
|
|
22467
|
-
case "reviewer":
|
|
22468
|
-
return "rev";
|
|
22469
|
-
case "implementer":
|
|
22470
|
-
return "imp";
|
|
22471
|
-
case "council":
|
|
22472
|
-
return "cnc";
|
|
22473
|
-
case "councillor":
|
|
22474
|
-
return "clr";
|
|
22475
21599
|
case "orchestrator":
|
|
22476
21600
|
return "orc";
|
|
22477
21601
|
}
|
|
@@ -22933,22 +22057,8 @@ ${buildRetryGuidance(detected)}`;
|
|
|
22933
22057
|
};
|
|
22934
22058
|
}
|
|
22935
22059
|
// src/hooks/filter-available-skills/index.ts
|
|
22936
|
-
init_custom_skills();
|
|
22937
22060
|
var AVAILABLE_SKILLS_BLOCK_REGEX = /<available_skills>\s*([\s\S]*?)\s*<\/available_skills>/g;
|
|
22938
22061
|
var SKILL_NAME_REGEX = /<name>([^<]+)<\/name>/;
|
|
22939
|
-
function builtinSkillBlock(name, description) {
|
|
22940
|
-
return `<skill>
|
|
22941
|
-
<name>${name}</name>
|
|
22942
|
-
<description>${description}</description>
|
|
22943
|
-
<location>builtin</location>
|
|
22944
|
-
</skill>`;
|
|
22945
|
-
}
|
|
22946
|
-
function getBuiltinSkillEntries() {
|
|
22947
|
-
return CUSTOM_SKILLS.map((skill) => ({
|
|
22948
|
-
name: skill.name,
|
|
22949
|
-
block: builtinSkillBlock(skill.name, skill.description)
|
|
22950
|
-
}));
|
|
22951
|
-
}
|
|
22952
22062
|
function getCurrentAgent(messages) {
|
|
22953
22063
|
for (let index = messages.length - 1;index >= 0; index -= 1) {
|
|
22954
22064
|
const message = messages[index];
|
|
@@ -22981,20 +22091,9 @@ function isSkillAllowed(skillName, permissionRules) {
|
|
|
22981
22091
|
}
|
|
22982
22092
|
return permissionRules["*"] === "allow";
|
|
22983
22093
|
}
|
|
22984
|
-
function mergeWithBuiltinSkills(installedEntries) {
|
|
22985
|
-
const builtinEntries = getBuiltinSkillEntries();
|
|
22986
|
-
const installedNames = new Set(installedEntries.map((e) => e.name));
|
|
22987
|
-
for (const entry of builtinEntries) {
|
|
22988
|
-
if (!installedNames.has(entry.name)) {
|
|
22989
|
-
installedEntries.push(entry);
|
|
22990
|
-
}
|
|
22991
|
-
}
|
|
22992
|
-
return installedEntries;
|
|
22993
|
-
}
|
|
22994
22094
|
function filterAvailableSkillsText(text, permissionRules) {
|
|
22995
22095
|
return text.replace(AVAILABLE_SKILLS_BLOCK_REGEX, (_fullMatch, blockContent) => {
|
|
22996
|
-
|
|
22997
|
-
allEntries = mergeWithBuiltinSkills(allEntries);
|
|
22096
|
+
const allEntries = extractSkillEntries(blockContent);
|
|
22998
22097
|
const allowedEntries = allEntries.filter((entry) => isSkillAllowed(entry.name, permissionRules));
|
|
22999
22098
|
if (allowedEntries.length === 0) {
|
|
23000
22099
|
return `<available_skills>
|
|
@@ -23007,22 +22106,6 @@ ${allowedEntries.map((entry) => entry.block).join(`
|
|
|
23007
22106
|
</available_skills>`;
|
|
23008
22107
|
});
|
|
23009
22108
|
}
|
|
23010
|
-
function injectBuiltinSkillsIfMissing(text, permissionRules) {
|
|
23011
|
-
if (text.includes("<available_skills>")) {
|
|
23012
|
-
return text;
|
|
23013
|
-
}
|
|
23014
|
-
const builtinEntries = getBuiltinSkillEntries();
|
|
23015
|
-
const allowedEntries = builtinEntries.filter((entry) => isSkillAllowed(entry.name, permissionRules));
|
|
23016
|
-
if (allowedEntries.length === 0) {
|
|
23017
|
-
return text;
|
|
23018
|
-
}
|
|
23019
|
-
const block = `<available_skills>
|
|
23020
|
-
${allowedEntries.map((entry) => entry.block).join(`
|
|
23021
|
-
`)}
|
|
23022
|
-
</available_skills>`;
|
|
23023
|
-
return `${text}
|
|
23024
|
-
${block}`;
|
|
23025
|
-
}
|
|
23026
22109
|
function createFilterAvailableSkillsHook(_ctx, config) {
|
|
23027
22110
|
const permissionRulesByAgent = new Map;
|
|
23028
22111
|
const getPermissionRules = (agentName) => {
|
|
@@ -23050,8 +22133,6 @@ function createFilterAvailableSkillsHook(_ctx, config) {
|
|
|
23050
22133
|
}
|
|
23051
22134
|
if (part.text.includes("<available_skills>")) {
|
|
23052
22135
|
part.text = filterAvailableSkillsText(part.text, permissionRules);
|
|
23053
|
-
} else {
|
|
23054
|
-
part.text = injectBuiltinSkillsIfMissing(part.text, permissionRules);
|
|
23055
22136
|
}
|
|
23056
22137
|
}
|
|
23057
22138
|
}
|
|
@@ -23674,11 +22755,7 @@ ${originalText}`;
|
|
|
23674
22755
|
import path9 from "node:path";
|
|
23675
22756
|
var AGENT_NAME_SET = new Set([
|
|
23676
22757
|
"orchestrator",
|
|
23677
|
-
"researcher"
|
|
23678
|
-
"reviewer",
|
|
23679
|
-
"implementer",
|
|
23680
|
-
"council",
|
|
23681
|
-
"councillor"
|
|
22758
|
+
"researcher"
|
|
23682
22759
|
]);
|
|
23683
22760
|
var MAX_PENDING_TASK_CALLS = 100;
|
|
23684
22761
|
var RESUMABLE_SESSIONS_START = "<resumable_sessions>";
|
|
@@ -27445,17 +26522,17 @@ import * as fs8 from "node:fs/promises";
|
|
|
27445
26522
|
import * as path12 from "node:path";
|
|
27446
26523
|
|
|
27447
26524
|
// src/interview/types.ts
|
|
27448
|
-
import { z as
|
|
27449
|
-
var RawQuestionSchema =
|
|
27450
|
-
id:
|
|
27451
|
-
question:
|
|
27452
|
-
options:
|
|
27453
|
-
suggested:
|
|
26525
|
+
import { z as z2 } from "zod";
|
|
26526
|
+
var RawQuestionSchema = z2.object({
|
|
26527
|
+
id: z2.string().optional(),
|
|
26528
|
+
question: z2.string().optional(),
|
|
26529
|
+
options: z2.array(z2.unknown()).optional(),
|
|
26530
|
+
suggested: z2.unknown().optional()
|
|
27454
26531
|
});
|
|
27455
|
-
var RawInterviewStateSchema =
|
|
27456
|
-
summary:
|
|
27457
|
-
title:
|
|
27458
|
-
questions:
|
|
26532
|
+
var RawInterviewStateSchema = z2.object({
|
|
26533
|
+
summary: z2.unknown().optional(),
|
|
26534
|
+
title: z2.unknown().optional(),
|
|
26535
|
+
questions: z2.array(z2.unknown()).optional()
|
|
27459
26536
|
});
|
|
27460
26537
|
|
|
27461
26538
|
// src/interview/parser.ts
|
|
@@ -29944,72 +29021,6 @@ var ast_grep_replace = tool2({
|
|
|
29944
29021
|
}
|
|
29945
29022
|
}
|
|
29946
29023
|
});
|
|
29947
|
-
// src/tools/council.ts
|
|
29948
|
-
import {
|
|
29949
|
-
tool as tool3
|
|
29950
|
-
} from "@opencode-ai/plugin";
|
|
29951
|
-
var z4 = tool3.schema;
|
|
29952
|
-
function formatModelComposition(councillorResults) {
|
|
29953
|
-
return councillorResults.map((cr) => {
|
|
29954
|
-
const shortModel = shortModelLabel(cr.model);
|
|
29955
|
-
return `${cr.name}: ${shortModel}`;
|
|
29956
|
-
}).join(", ");
|
|
29957
|
-
}
|
|
29958
|
-
function createCouncilTool(_ctx, councilManager) {
|
|
29959
|
-
const council_session = tool3({
|
|
29960
|
-
description: `Launch a multi-LLM council session for consensus-based analysis.
|
|
29961
|
-
|
|
29962
|
-
Sends the prompt to multiple models (councillors) in parallel and returns their formatted responses for you to synthesize.
|
|
29963
|
-
|
|
29964
|
-
Returns the councillor responses with a summary footer.`,
|
|
29965
|
-
args: {
|
|
29966
|
-
prompt: z4.string().describe("The prompt to send to all councillors"),
|
|
29967
|
-
preset: z4.string().optional().describe('Council preset to use (default: "default"). Must match a preset in the council config.')
|
|
29968
|
-
},
|
|
29969
|
-
async execute(args, toolContext) {
|
|
29970
|
-
if (!toolContext || typeof toolContext !== "object" || !("sessionID" in toolContext)) {
|
|
29971
|
-
throw new Error("Invalid toolContext: missing sessionID");
|
|
29972
|
-
}
|
|
29973
|
-
const allowedAgents = ["council"];
|
|
29974
|
-
const callingAgent = toolContext.agent;
|
|
29975
|
-
if (callingAgent && !allowedAgents.includes(callingAgent)) {
|
|
29976
|
-
throw new Error(`Council sessions can only be invoked by the council agent. Current agent: ${callingAgent}`);
|
|
29977
|
-
}
|
|
29978
|
-
const prompt = String(args.prompt);
|
|
29979
|
-
const preset = typeof args.preset === "string" ? args.preset : undefined;
|
|
29980
|
-
const parentSessionId = toolContext.sessionID;
|
|
29981
|
-
const result = await councilManager.runCouncil(prompt, preset, parentSessionId);
|
|
29982
|
-
if (!result.success) {
|
|
29983
|
-
return `Council session failed: ${result.error}`;
|
|
29984
|
-
}
|
|
29985
|
-
let output = result.result ?? "(No output)";
|
|
29986
|
-
const completed = result.councillorResults.filter((cr) => cr.status === "completed").length;
|
|
29987
|
-
const total = result.councillorResults.length;
|
|
29988
|
-
const composition = formatModelComposition(result.councillorResults);
|
|
29989
|
-
output += `
|
|
29990
|
-
|
|
29991
|
-
---
|
|
29992
|
-
*Council: ${completed}/${total} councillors responded (${composition})*`;
|
|
29993
|
-
const deprecated = councilManager.getDeprecatedFields();
|
|
29994
|
-
if (deprecated && deprecated.length > 0) {
|
|
29995
|
-
const legacyMasterModel = councilManager.getLegacyMasterModel();
|
|
29996
|
-
const hasMaster = deprecated.includes("master");
|
|
29997
|
-
const trulyIgnored = hasMaster && !legacyMasterModel ? deprecated : deprecated.filter((f) => f !== "master");
|
|
29998
|
-
const parts = [];
|
|
29999
|
-
if (hasMaster && legacyMasterModel) {
|
|
30000
|
-
parts.push(`\`council.master\` is deprecated and will be removed in a future version. Its \`model\` is currently used as a fallback for the council agent — add a \`council\` entry to your preset to make this explicit.`);
|
|
30001
|
-
}
|
|
30002
|
-
if (trulyIgnored.length > 0) {
|
|
30003
|
-
parts.push(`${trulyIgnored.map((f) => `\`council.${f}\``).join(", ")} ${trulyIgnored.length === 1 ? "is" : "are"} deprecated and ignored — remove ${trulyIgnored.length === 1 ? "it" : "them"} from your config.`);
|
|
30004
|
-
}
|
|
30005
|
-
output += `
|
|
30006
|
-
⚠ Config warning: ${parts.join(" ")}`;
|
|
30007
|
-
}
|
|
30008
|
-
return output;
|
|
30009
|
-
}
|
|
30010
|
-
});
|
|
30011
|
-
return { council_session };
|
|
30012
|
-
}
|
|
30013
29024
|
// src/tui-state.ts
|
|
30014
29025
|
import * as fs9 from "node:fs";
|
|
30015
29026
|
import * as os5 from "node:os";
|
|
@@ -30243,16 +29254,21 @@ Usage: /preset <name> to switch.`);
|
|
|
30243
29254
|
};
|
|
30244
29255
|
}
|
|
30245
29256
|
// src/tools/skill.ts
|
|
30246
|
-
import { existsSync as
|
|
30247
|
-
import { join as
|
|
30248
|
-
import { tool as
|
|
30249
|
-
|
|
30250
|
-
var z5 = tool4.schema;
|
|
29257
|
+
import { existsSync as existsSync10, readFileSync as readFileSync5 } from "node:fs";
|
|
29258
|
+
import { join as join13 } from "node:path";
|
|
29259
|
+
import { tool as tool3 } from "@opencode-ai/plugin/tool";
|
|
29260
|
+
var z3 = tool3.schema;
|
|
30251
29261
|
function resolveSkillPath(skillName) {
|
|
30252
|
-
|
|
30253
|
-
|
|
30254
|
-
|
|
30255
|
-
|
|
29262
|
+
let dir = import.meta.dirname;
|
|
29263
|
+
for (let i = 0;i < 5; i++) {
|
|
29264
|
+
const candidate = join13(dir, "src", "skills", skillName, "SKILL.md");
|
|
29265
|
+
if (existsSync10(candidate)) {
|
|
29266
|
+
return candidate;
|
|
29267
|
+
}
|
|
29268
|
+
const parent = join13(dir, "..");
|
|
29269
|
+
if (parent === dir)
|
|
29270
|
+
break;
|
|
29271
|
+
dir = parent;
|
|
30256
29272
|
}
|
|
30257
29273
|
return;
|
|
30258
29274
|
}
|
|
@@ -30266,14 +29282,14 @@ function isSkillAllowedForAgent(agentName, skillName, config) {
|
|
|
30266
29282
|
return permissions["*"] === "allow";
|
|
30267
29283
|
}
|
|
30268
29284
|
function createSkillTool(config) {
|
|
30269
|
-
const skill =
|
|
29285
|
+
const skill = tool3({
|
|
30270
29286
|
description: `Load a Skill behavior guide by name.
|
|
30271
29287
|
|
|
30272
29288
|
Returns the full SKILL.md content so you can follow its workflow.
|
|
30273
29289
|
Skills are temporary behavior overlays — they apply to the current turn only
|
|
30274
29290
|
and do not permanently modify your system prompt.`,
|
|
30275
29291
|
args: {
|
|
30276
|
-
name:
|
|
29292
|
+
name: z3.string().describe('Skill name (e.g. "brainstorming", "simplify", "codemap").')
|
|
30277
29293
|
},
|
|
30278
29294
|
execute: async (args, toolContext) => {
|
|
30279
29295
|
const skillName = args.name.trim();
|
|
@@ -30329,7 +29345,7 @@ var WEBFETCH_DESCRIPTION = "Fetch a URL with better extraction for static/docs p
|
|
|
30329
29345
|
import os6 from "node:os";
|
|
30330
29346
|
import path18 from "node:path";
|
|
30331
29347
|
import {
|
|
30332
|
-
tool as
|
|
29348
|
+
tool as tool4
|
|
30333
29349
|
} from "@opencode-ai/plugin";
|
|
30334
29350
|
|
|
30335
29351
|
// src/tools/smartfetch/binary.ts
|
|
@@ -30497,7 +29513,7 @@ var M = class u2 {
|
|
|
30497
29513
|
return this.#S;
|
|
30498
29514
|
}
|
|
30499
29515
|
constructor(e) {
|
|
30500
|
-
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:
|
|
29516
|
+
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: z4, perf: x } = e;
|
|
30501
29517
|
if (x !== undefined && typeof x?.now != "function")
|
|
30502
29518
|
throw new TypeError("perf option must have a now() method if specified");
|
|
30503
29519
|
if (this.#m = x ?? C, t !== 0 && !F(t))
|
|
@@ -30515,7 +29531,7 @@ var M = class u2 {
|
|
|
30515
29531
|
throw new TypeError("memoMethod must be a function if defined");
|
|
30516
29532
|
if (this.#U = m, a !== undefined && typeof a != "function")
|
|
30517
29533
|
throw new TypeError("fetchMethod must be a function if specified");
|
|
30518
|
-
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 = !!
|
|
29534
|
+
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 = !!z4, this.maxEntrySize !== 0) {
|
|
30519
29535
|
if (this.#u !== 0 && !F(this.#u))
|
|
30520
29536
|
throw new TypeError("maxSize must be a positive integer if specified");
|
|
30521
29537
|
if (!F(this.maxEntrySize))
|
|
@@ -30895,8 +29911,8 @@ var M = class u2 {
|
|
|
30895
29911
|
let A = this.#p(b);
|
|
30896
29912
|
if (!y && !A)
|
|
30897
29913
|
return a && (a.fetch = "hit"), this.#L(b), s && this.#D(b), a && this.#E(a, b), d;
|
|
30898
|
-
let
|
|
30899
|
-
return a && (a.fetch = A ? "stale" : "refresh", v && A && (a.returnedStale = true)), v ?
|
|
29914
|
+
let z4 = this.#P(e, b, _, w), v = z4.__staleWhileFetching !== undefined && i;
|
|
29915
|
+
return a && (a.fetch = A ? "stale" : "refresh", v && A && (a.returnedStale = true)), v ? z4.__staleWhileFetching : z4.__returned = z4;
|
|
30900
29916
|
}
|
|
30901
29917
|
}
|
|
30902
29918
|
forceFetch(e, t = {}) {
|
|
@@ -31907,10 +30923,9 @@ function isInvalidLlmsResult(fetchResult) {
|
|
|
31907
30923
|
}
|
|
31908
30924
|
|
|
31909
30925
|
// src/tools/smartfetch/secondary-model.ts
|
|
31910
|
-
import { existsSync as
|
|
30926
|
+
import { existsSync as existsSync11 } from "node:fs";
|
|
31911
30927
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
31912
30928
|
import path17 from "node:path";
|
|
31913
|
-
init_paths();
|
|
31914
30929
|
function parseModelRef(value) {
|
|
31915
30930
|
if (!value)
|
|
31916
30931
|
return;
|
|
@@ -31937,7 +30952,7 @@ function pickAgentModelRef(value) {
|
|
|
31937
30952
|
function findPreferredOpenCodeConfigPath(baseDir) {
|
|
31938
30953
|
for (const file of ["opencode.jsonc", "opencode.json"]) {
|
|
31939
30954
|
const fullPath = path17.join(baseDir, file);
|
|
31940
|
-
if (
|
|
30955
|
+
if (existsSync11(fullPath))
|
|
31941
30956
|
return fullPath;
|
|
31942
30957
|
}
|
|
31943
30958
|
return;
|
|
@@ -32112,20 +31127,20 @@ async function runSecondaryModelWithFallback(client, directory, models, prompt,
|
|
|
32112
31127
|
}
|
|
32113
31128
|
|
|
32114
31129
|
// src/tools/smartfetch/tool.ts
|
|
32115
|
-
var
|
|
31130
|
+
var z4 = tool4.schema;
|
|
32116
31131
|
function createWebfetchTool(pluginCtx, options = {}) {
|
|
32117
31132
|
const binaryDir = options.binaryDir || path18.join(os6.tmpdir(), "opencode-smartfetch");
|
|
32118
|
-
return
|
|
31133
|
+
return tool4({
|
|
32119
31134
|
description: WEBFETCH_DESCRIPTION,
|
|
32120
31135
|
args: {
|
|
32121
|
-
url:
|
|
32122
|
-
format:
|
|
32123
|
-
timeout:
|
|
32124
|
-
prompt:
|
|
32125
|
-
extract_main:
|
|
32126
|
-
prefer_llms_txt:
|
|
32127
|
-
include_metadata:
|
|
32128
|
-
save_binary:
|
|
31136
|
+
url: z4.httpUrl(),
|
|
31137
|
+
format: z4.enum(["text", "markdown", "html"]).default("markdown"),
|
|
31138
|
+
timeout: z4.number().positive().max(MAX_TIMEOUT_SECONDS).optional().describe("Timeout in seconds, max 120."),
|
|
31139
|
+
prompt: z4.string().optional().describe("Optional extraction task to run on the fetched content using a cheap secondary model."),
|
|
31140
|
+
extract_main: z4.boolean().default(true),
|
|
31141
|
+
prefer_llms_txt: z4.enum(["auto", "always", "never"]).default("auto"),
|
|
31142
|
+
include_metadata: z4.boolean().default(true),
|
|
31143
|
+
save_binary: z4.boolean().default(false).describe("Save binary payload to disk when it fits within the active download limit.")
|
|
32129
31144
|
},
|
|
32130
31145
|
async execute(args, ctx) {
|
|
32131
31146
|
const secondaryModels = await readSecondaryModelFromConfig(ctx.directory || pluginCtx.directory);
|
|
@@ -32669,7 +31684,7 @@ async function appLog(ctx, level, message) {
|
|
|
32669
31684
|
}
|
|
32670
31685
|
}
|
|
32671
31686
|
var HEALTH_CHECK = {
|
|
32672
|
-
minAgents:
|
|
31687
|
+
minAgents: 2,
|
|
32673
31688
|
minTools: 5,
|
|
32674
31689
|
minMcps: 1
|
|
32675
31690
|
};
|
|
@@ -32775,19 +31790,10 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
32775
31790
|
startAvailabilityCheck(multiplexerConfig);
|
|
32776
31791
|
}
|
|
32777
31792
|
depthTracker = new SubagentDepthTracker;
|
|
32778
|
-
councilTools =
|
|
31793
|
+
councilTools = {};
|
|
32779
31794
|
mcps = createBuiltinMcps(config.disabled_mcps, config.websearch);
|
|
32780
31795
|
webfetch = createWebfetchTool(ctx);
|
|
32781
31796
|
skillTools = createSkillTool(config);
|
|
32782
|
-
try {
|
|
32783
|
-
const { syncBuiltinSkills: syncBuiltinSkills2 } = await Promise.resolve().then(() => (init_skill_sync(), exports_skill_sync));
|
|
32784
|
-
const syncResult = syncBuiltinSkills2();
|
|
32785
|
-
if (syncResult.installed > 0 || syncResult.skipped > 0) {
|
|
32786
|
-
log("[plugin] skill sync:", syncResult);
|
|
32787
|
-
}
|
|
32788
|
-
} catch (err) {
|
|
32789
|
-
log("[plugin] skill sync failed (non-fatal):", err);
|
|
32790
|
-
}
|
|
32791
31797
|
multiplexerSessionManager = new MultiplexerSessionManager(ctx, multiplexerConfig);
|
|
32792
31798
|
autoUpdateChecker = createAutoUpdateCheckerHook(ctx, {
|
|
32793
31799
|
autoUpdate: config.autoUpdate ?? true
|
|
@@ -32819,7 +31825,7 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
32819
31825
|
interviewManager = createInterviewManager(ctx, config);
|
|
32820
31826
|
presetManager = createPresetManager(ctx, config);
|
|
32821
31827
|
divoomManager = createDivoomManager(config.divoom);
|
|
32822
|
-
toolCount = Object.keys(
|
|
31828
|
+
toolCount = Object.keys(todoContinuationHook.tool).length + 1 + 1 + 2;
|
|
32823
31829
|
} catch (err) {
|
|
32824
31830
|
log("[plugin] FATAL: init failed", String(err));
|
|
32825
31831
|
await appLog(ctx, "error", `INIT FAILED: ${String(err)}. Report at cnb.cool/zcyoop/ai-assistant/agent-forge/issues/310`);
|
|
@@ -33013,8 +32019,6 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
33013
32019
|
}
|
|
33014
32020
|
const tuiAgentModels = {};
|
|
33015
32021
|
for (const agentDef of agentDefs) {
|
|
33016
|
-
if (agentDef.name === "councillor")
|
|
33017
|
-
continue;
|
|
33018
32022
|
const entry = configAgent[agentDef.name];
|
|
33019
32023
|
const resolvedModel = typeof entry?.model === "string" ? entry.model : runtimeChains[agentDef.name]?.[0] ? runtimeChains[agentDef.name][0] : typeof agentDef.config.model === "string" ? agentDef.config.model : undefined;
|
|
33020
32024
|
tuiAgentModels[agentDef.name] = resolvedModel ?? "default";
|