@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/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 join15(output, replacement);
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 = join15(output, rule.append(self.options));
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 join15(output, replacement) {
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/skill-sync.ts
18356
- var exports_skill_sync = {};
18357
- __export(exports_skill_sync, {
18358
- syncBuiltinSkills: () => syncBuiltinSkills
18359
- });
18360
- import {
18361
- cpSync,
18362
- existsSync as existsSync13,
18363
- lstatSync,
18364
- mkdirSync as mkdirSync7,
18365
- readlinkSync,
18366
- rmSync as rmSync2,
18367
- symlinkSync
18368
- } from "node:fs";
18369
- import { join as join15 } from "node:path";
18370
- function syncBuiltinSkills(packageRoot, skillsDirOverride) {
18371
- const resolvedPackageRoot = packageRoot ?? resolvePackageRoot();
18372
- const skillsDir = skillsDirOverride ?? join15(getConfigDir(), "skills");
18373
- mkdirSync7(skillsDir, { recursive: true });
18374
- let installed = 0;
18375
- let skipped = 0;
18376
- let unchanged = 0;
18377
- let copied = 0;
18378
- for (const skill of CUSTOM_SKILLS) {
18379
- const sourcePath = join15(resolvedPackageRoot, skill.sourcePath);
18380
- const linkPath = join15(skillsDir, skill.name);
18381
- if (!existsSync13(sourcePath)) {
18382
- skipped++;
18383
- continue;
18384
- }
18385
- try {
18386
- if (lstatSync(linkPath).isSymbolicLink()) {
18387
- const currentTarget = getSymlinkTarget(linkPath);
18388
- if (currentTarget === sourcePath) {
18389
- unchanged++;
18390
- continue;
18391
- }
18392
- rmSync2(linkPath, { recursive: true, force: true });
18393
- } else if (existsSync13(linkPath)) {
18394
- rmSync2(linkPath, { recursive: true, force: true });
18395
- }
18396
- } catch {
18397
- try {
18398
- rmSync2(linkPath, { recursive: true, force: true });
18399
- } catch {}
18400
- }
18401
- try {
18402
- symlinkSync(sourcePath, linkPath, "junction");
18403
- installed++;
18404
- } catch {
18405
- try {
18406
- cpSync(sourcePath, linkPath, { recursive: true, force: true });
18407
- copied++;
18408
- } catch {
18409
- skipped++;
18410
- }
18411
- }
18412
- }
18413
- return { installed, skipped, unchanged, copied };
18414
- }
18415
- function getSymlinkTarget(linkPath) {
18416
- try {
18417
- return readlinkSync(linkPath, "utf-8");
18418
- } catch {
18419
- return "";
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: ["implementer"],
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
- reviewer: "openai/gpt-5.5",
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 TMUX_SPAWN_DELAY_MS = 500;
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/config-io.ts
18590
- init_paths();
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 as z2 } from "zod";
18639
- var ProviderModelIdSchema = z2.string().regex(/^[^/\s]+\/[^\s]+$/, "Expected provider/model format (provider/.../model)");
18640
- var ManualAgentPlanSchema = z2.object({
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: z2.ZodIssueCode.custom,
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 = z2.object({
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 = z2.array(z2.string()).min(1);
18666
- var FallbackChainsSchema = z2.object({
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 = z2.object({
18673
- model: z2.union([
18674
- z2.string(),
18675
- z2.array(z2.union([
18676
- z2.string(),
18677
- z2.object({
18678
- id: z2.string(),
18679
- variant: z2.string().optional()
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: z2.number().min(0).max(2).optional(),
18684
- variant: z2.string().optional().catch(undefined),
18685
- skills: z2.array(z2.string()).optional(),
18686
- mcps: z2.array(z2.string()).optional(),
18687
- prompt: z2.string().min(1).optional(),
18688
- orchestratorPrompt: z2.string().min(1).optional(),
18689
- options: z2.record(z2.string(), z2.unknown()).optional(),
18690
- displayName: z2.string().min(1).optional()
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 = z2.enum(["auto", "tmux", "zellij", "none"]);
18693
- var MultiplexerLayoutSchema = z2.enum([
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 = z2.object({
18472
+ var MultiplexerConfigSchema = z.object({
18702
18473
  type: MultiplexerTypeSchema.default("none"),
18703
18474
  layout: MultiplexerLayoutSchema.default("main-vertical"),
18704
- main_pane_size: z2.number().min(20).max(80).default(60)
18475
+ main_pane_size: z.number().min(20).max(80).default(60)
18705
18476
  });
18706
- var TmuxConfigSchema = z2.object({
18707
- enabled: z2.boolean().default(false),
18477
+ var TmuxConfigSchema = z.object({
18478
+ enabled: z.boolean().default(false),
18708
18479
  layout: TmuxLayoutSchema.default("main-vertical"),
18709
- main_pane_size: z2.number().min(20).max(80).default(60)
18480
+ main_pane_size: z.number().min(20).max(80).default(60)
18710
18481
  });
18711
- var PresetSchema = z2.record(z2.string(), AgentOverrideConfigSchema);
18712
- var WebsearchConfigSchema = z2.object({
18713
- provider: z2.enum(["exa", "tavily"]).default("exa")
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 = z2.enum(["websearch", "context7", "grep_app"]);
18716
- var InterviewConfigSchema = z2.object({
18717
- maxQuestions: z2.number().int().min(1).max(10).default(2),
18718
- outputFolder: z2.string().min(1).default("interview"),
18719
- autoOpenBrowser: z2.boolean().default(true).describe("Automatically open the interview UI in your default browser during interactive runs. Disabled automatically in tests and CI."),
18720
- port: z2.number().int().min(0).max(65535).default(0),
18721
- dashboard: z2.boolean().default(false)
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 = z2.object({
18724
- maxSessionsPerAgent: z2.number().int().min(1).max(10).default(2),
18725
- readContextMinLines: z2.number().int().min(0).max(1000).default(10),
18726
- readContextMaxFiles: z2.number().int().min(0).max(50).default(8)
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 = z2.object({
18729
- enabled: z2.boolean().default(false),
18730
- python: z2.string().min(1).default("/Applications/Divoom MiniToo.app/Contents/Resources/.venv/bin/python"),
18731
- script: z2.string().min(1).default("/Applications/Divoom MiniToo.app/Contents/Resources/tools/divoom_send.py"),
18732
- size: z2.number().int().min(1).max(1024).default(128),
18733
- fps: z2.number().int().min(1).max(60).default(8),
18734
- speed: z2.number().int().min(1).max(1e4).default(125),
18735
- maxFrames: z2.number().int().min(1).max(500).default(24),
18736
- posterizeBits: z2.number().int().min(1).max(8).default(3),
18737
- gifs: z2.record(z2.string(), z2.string().min(1)).optional()
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 = z2.object({
18740
- maxContinuations: z2.number().int().min(1).max(50).default(5).describe("Maximum consecutive auto-continuations before stopping to ask user"),
18741
- cooldownMs: z2.number().int().min(0).max(30000).default(3000).describe("Delay in ms before auto-continuing (gives user time to abort)"),
18742
- autoEnable: z2.boolean().default(false).describe("Automatically enable auto-continue when the orchestrator session has enough todos"),
18743
- autoEnableThreshold: z2.number().int().min(1).max(50).default(4).describe("Number of todos that triggers auto-enable (only used when autoEnable is true)")
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 = z2.object({
18746
- enabled: z2.boolean().default(true),
18747
- timeoutMs: z2.number().min(0).default(15000),
18748
- retryDelayMs: z2.number().min(0).default(500),
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: z2.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.")
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: z2.ZodIssueCode.custom,
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: z2.ZodIssueCode.custom,
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 = z2.object({
18775
- preset: z2.string().optional(),
18776
- setDefaultAgent: z2.boolean().optional(),
18777
- scoringEngineVersion: z2.enum(["v1", "v2-shadow", "v2"]).optional(),
18778
- balanceProviderUsage: z2.boolean().optional(),
18779
- autoUpdate: z2.boolean().optional().describe("Disable automatic installation of plugin updates when false. Defaults to true."),
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: z2.record(z2.string(), PresetSchema).optional(),
18782
- agents: z2.record(z2.string(), AgentOverrideConfigSchema).optional(),
18783
- disabled_agents: z2.array(z2.string()).optional().describe("Agent names to disable completely. " + "Disabled agents are not instantiated and cannot be delegated to. " + "Orchestrator, researcher, reviewer, implementer and council internal agents (councillor) cannot be disabled. " + "By default, only council is disabled."),
18784
- disabled_mcps: z2.array(z2.string()).optional(),
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
- "- 需要代码审查、架构决策、调试分析@reviewer(只读,修复方案由 @implementer 执行)",
19087
- "- 非平凡的实现任务@implementer(UI 任务注明 [设计模式])",
19088
- "- Reviewer 输出 fix_plan 时 委派 @implementer 执行修复",
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. 委派执行 → 加载 subagent-driven-development skill
19135
- ├─ 实现任务 → 委派 @implementer
19136
- ├─ 代码审查 → 委派 @reviewer(只读分析)
19137
- │ └─ 需要修复 → 委派 @implementer(执行修复)
18790
+ 3. 执行实现 → 加载 subagent-driven-development skill
18791
+ ├─ 实现任务 → 委派 implementer subagent
19138
18792
  ├─ 代码搜索 → 委派 @researcher
19139
- └─ 调试分析 → 委派 @reviewer(Phase 1-3)
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.reviewer,
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 === "council") {
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 && !isInternalOnly(a.name)) {
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
- let allEntries = extractSkillEntries(blockContent);
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 z3 } from "zod";
27449
- var RawQuestionSchema = z3.object({
27450
- id: z3.string().optional(),
27451
- question: z3.string().optional(),
27452
- options: z3.array(z3.unknown()).optional(),
27453
- suggested: z3.unknown().optional()
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 = z3.object({
27456
- summary: z3.unknown().optional(),
27457
- title: z3.unknown().optional(),
27458
- questions: z3.array(z3.unknown()).optional()
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 existsSync11, readFileSync as readFileSync5 } from "node:fs";
30247
- import { join as join14 } from "node:path";
30248
- import { tool as tool4 } from "@opencode-ai/plugin/tool";
30249
- init_package_root();
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
- const packageRoot = resolvePackageRoot();
30253
- const bundledPath = join14(packageRoot, "src", "skills", skillName, "SKILL.md");
30254
- if (existsSync11(bundledPath)) {
30255
- return bundledPath;
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 = tool4({
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: z5.string().describe('Skill name (e.g. "brainstorming", "simplify", "codemap").')
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 tool5
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: z6, perf: x } = e;
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 = !!z6, this.maxEntrySize !== 0) {
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 z6 = this.#P(e, b, _, w), v = z6.__staleWhileFetching !== undefined && i;
30899
- return a && (a.fetch = A ? "stale" : "refresh", v && A && (a.returnedStale = true)), v ? z6.__staleWhileFetching : z6.__returned = z6;
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 existsSync12 } from "node:fs";
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 (existsSync12(fullPath))
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 z6 = tool5.schema;
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 tool5({
31133
+ return tool4({
32119
31134
  description: WEBFETCH_DESCRIPTION,
32120
31135
  args: {
32121
- url: z6.httpUrl(),
32122
- format: z6.enum(["text", "markdown", "html"]).default("markdown"),
32123
- timeout: z6.number().positive().max(MAX_TIMEOUT_SECONDS).optional().describe("Timeout in seconds, max 120."),
32124
- prompt: z6.string().optional().describe("Optional extraction task to run on the fetched content using a cheap secondary model."),
32125
- extract_main: z6.boolean().default(true),
32126
- prefer_llms_txt: z6.enum(["auto", "always", "never"]).default("auto"),
32127
- include_metadata: z6.boolean().default(true),
32128
- save_binary: z6.boolean().default(false).describe("Save binary payload to disk when it fits within the active download limit.")
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: 5,
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 = config.council ? createCouncilTool(ctx, new CouncilManager(ctx, config, depthTracker, multiplexerEnabled)) : {};
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(councilTools).length + Object.keys(todoContinuationHook.tool).length + 1 + 1 + 2;
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";