@zcy2nn/agent-forge 1.1.3 → 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/README.md +247 -247
- package/agent-forge.schema.json +2 -133
- package/dist/cli/index.js +109 -204
- package/dist/cli/providers.d.ts +0 -44
- package/dist/config/constants.d.ts +3 -4
- package/dist/config/index.d.ts +0 -1
- package/dist/config/schema.d.ts +2 -72
- package/dist/index.js +191 -995
- package/dist/tools/index.d.ts +0 -1
- package/dist/tui.js +5 -18
- package/package.json +104 -104
- package/src/skills/brainstorming/SKILL.md +185 -186
- package/src/skills/brainstorming/scripts/frame-template.html +214 -214
- package/src/skills/brainstorming/scripts/server.cjs +354 -354
- package/src/skills/brainstorming/spec-document-reviewer-prompt.md +1 -1
- package/src/skills/codemap/README.md +3 -3
- package/src/skills/codemap/SKILL.md +5 -5
- package/src/skills/codemap/codemap.md +4 -4
- package/src/skills/codemap/scripts/codemap.mjs +1 -1
- package/src/skills/codemap/scripts/codemap.test.ts +1 -1
- package/src/skills/requesting-code-review/SKILL.md +1 -1
- package/src/skills/subagent-driven-development/SKILL.md +1 -1
- package/src/skills/systematic-debugging/SKILL.md +318 -318
- package/src/skills/test-driven-development/SKILL.md +392 -392
- package/src/skills/verification-before-completion/SKILL.md +153 -153
- package/src/skills/writing-plans/SKILL.md +2 -2
- package/src/skills/writing-skills/graphviz-conventions.dot +171 -171
- package/dist/agents/council.d.ts +0 -27
- package/dist/agents/councillor.d.ts +0 -2
- package/dist/agents/designer.d.ts +0 -2
- package/dist/agents/explorer.d.ts +0 -2
- package/dist/agents/fixer.d.ts +0 -2
- package/dist/agents/implementer.d.ts +0 -2
- package/dist/agents/librarian.d.ts +0 -2
- package/dist/agents/observer.d.ts +0 -2
- package/dist/agents/oracle.d.ts +0 -2
- package/dist/agents/reviewer.d.ts +0 -2
- package/dist/cli/migration.d.ts +0 -46
- package/dist/config/council-schema.d.ts +0 -127
- package/dist/council/council-manager.d.ts +0 -49
- package/dist/council/index.d.ts +0 -1
- package/dist/skills/systematic-debugging/condition-based-waiting-example.d.ts +0 -51
- package/dist/tools/council.d.ts +0 -10
- package/src/skills/using-git-worktrees/SKILL.md +0 -226
package/dist/index.js
CHANGED
|
@@ -18190,7 +18190,7 @@ var CUSTOM_SKILLS = [
|
|
|
18190
18190
|
{
|
|
18191
18191
|
name: "simplify",
|
|
18192
18192
|
description: "Code simplification and readability-focused refactoring",
|
|
18193
|
-
allowedAgents: ["
|
|
18193
|
+
allowedAgents: ["orchestrator"],
|
|
18194
18194
|
sourcePath: "src/skills/simplify"
|
|
18195
18195
|
},
|
|
18196
18196
|
{
|
|
@@ -18229,12 +18229,6 @@ var CUSTOM_SKILLS = [
|
|
|
18229
18229
|
allowedAgents: ["orchestrator"],
|
|
18230
18230
|
sourcePath: "src/skills/dispatching-parallel-agents"
|
|
18231
18231
|
},
|
|
18232
|
-
{
|
|
18233
|
-
name: "using-git-worktrees",
|
|
18234
|
-
description: "Create isolated git worktrees before executing implementation plans",
|
|
18235
|
-
allowedAgents: ["orchestrator"],
|
|
18236
|
-
sourcePath: "src/skills/using-git-worktrees"
|
|
18237
|
-
},
|
|
18238
18232
|
{
|
|
18239
18233
|
name: "finishing-a-development-branch",
|
|
18240
18234
|
description: "Guide completion of development work with structured merge/PR options",
|
|
@@ -18250,25 +18244,25 @@ var CUSTOM_SKILLS = [
|
|
|
18250
18244
|
{
|
|
18251
18245
|
name: "test-driven-development",
|
|
18252
18246
|
description: "Write failing tests first, then minimal code to pass, before any implementation",
|
|
18253
|
-
allowedAgents: ["
|
|
18247
|
+
allowedAgents: ["orchestrator"],
|
|
18254
18248
|
sourcePath: "src/skills/test-driven-development"
|
|
18255
18249
|
},
|
|
18256
18250
|
{
|
|
18257
18251
|
name: "verification-before-completion",
|
|
18258
18252
|
description: "Run verification commands and confirm output before claiming work is complete",
|
|
18259
|
-
allowedAgents: ["
|
|
18253
|
+
allowedAgents: ["orchestrator"],
|
|
18260
18254
|
sourcePath: "src/skills/verification-before-completion"
|
|
18261
18255
|
},
|
|
18262
18256
|
{
|
|
18263
18257
|
name: "systematic-debugging",
|
|
18264
18258
|
description: "Find root cause before attempting fixes for any bug or test failure",
|
|
18265
|
-
allowedAgents: ["
|
|
18259
|
+
allowedAgents: ["orchestrator"],
|
|
18266
18260
|
sourcePath: "src/skills/systematic-debugging"
|
|
18267
18261
|
},
|
|
18268
18262
|
{
|
|
18269
18263
|
name: "receiving-code-review",
|
|
18270
18264
|
description: "Evaluate code review feedback with technical rigor before implementing suggestions",
|
|
18271
|
-
allowedAgents: ["
|
|
18265
|
+
allowedAgents: ["orchestrator"],
|
|
18272
18266
|
sourcePath: "src/skills/receiving-code-review"
|
|
18273
18267
|
},
|
|
18274
18268
|
{
|
|
@@ -18285,7 +18279,7 @@ var RECOMMENDED_SKILLS = [
|
|
|
18285
18279
|
name: "agent-browser",
|
|
18286
18280
|
repo: "https://github.com/vercel-labs/agent-browser",
|
|
18287
18281
|
skillName: "agent-browser",
|
|
18288
|
-
allowedAgents: ["
|
|
18282
|
+
allowedAgents: ["orchestrator"],
|
|
18289
18283
|
description: "High-performance browser automation",
|
|
18290
18284
|
postInstallCommands: [
|
|
18291
18285
|
"npm install -g agent-browser",
|
|
@@ -18334,28 +18328,17 @@ function getSkillPermissionsForAgent(agentName, skillList) {
|
|
|
18334
18328
|
|
|
18335
18329
|
// src/config/constants.ts
|
|
18336
18330
|
var SUBAGENT_NAMES = [
|
|
18337
|
-
"researcher"
|
|
18338
|
-
"reviewer",
|
|
18339
|
-
"implementer",
|
|
18340
|
-
"council",
|
|
18341
|
-
"councillor"
|
|
18331
|
+
"researcher"
|
|
18342
18332
|
];
|
|
18343
18333
|
var ORCHESTRATOR_NAME = "orchestrator";
|
|
18344
18334
|
var ALL_AGENT_NAMES = [ORCHESTRATOR_NAME, ...SUBAGENT_NAMES];
|
|
18345
18335
|
var PROTECTED_AGENTS = new Set([
|
|
18346
18336
|
"orchestrator",
|
|
18347
|
-
"researcher"
|
|
18348
|
-
"reviewer",
|
|
18349
|
-
"implementer",
|
|
18350
|
-
"councillor"
|
|
18337
|
+
"researcher"
|
|
18351
18338
|
]);
|
|
18352
18339
|
var DEFAULT_MODELS = {
|
|
18353
18340
|
orchestrator: undefined,
|
|
18354
|
-
|
|
18355
|
-
researcher: "openai/gpt-5.4-mini",
|
|
18356
|
-
implementer: "openai/gpt-5.4-mini",
|
|
18357
|
-
council: "openai/gpt-5.4-mini",
|
|
18358
|
-
councillor: "openai/gpt-5.4-mini"
|
|
18341
|
+
researcher: "openai/gpt-5.4-mini"
|
|
18359
18342
|
};
|
|
18360
18343
|
var POLL_INTERVAL_BACKGROUND_MS = 2000;
|
|
18361
18344
|
var DEFAULT_TIMEOUT_MS = 2 * 60 * 1000;
|
|
@@ -18364,77 +18347,7 @@ var DEFAULT_MAX_SUBAGENT_DEPTH = 3;
|
|
|
18364
18347
|
var PHASE_REMINDER_TEXT = `!IMPORTANT! Recall the workflow rules:
|
|
18365
18348
|
Understand → choose the best parallelized path based on your capabilities and agents delegation rules → recall session reuse rules → execute → verify.
|
|
18366
18349
|
If delegating, launch the specialist in the same turn you mention it !END!`;
|
|
18367
|
-
var
|
|
18368
|
-
var COUNCILLOR_STAGGER_MS = 250;
|
|
18369
|
-
var DEFAULT_DISABLED_AGENTS = ["council"];
|
|
18370
|
-
// src/config/council-schema.ts
|
|
18371
|
-
import { z } from "zod";
|
|
18372
|
-
var ModelIdSchema = z.string().regex(/^[^/\s]+\/[^\s]+$/, 'Expected provider/model format (e.g. "openai/gpt-5.4-mini")');
|
|
18373
|
-
var CouncillorConfigSchema = z.object({
|
|
18374
|
-
model: ModelIdSchema.describe('Model ID in provider/model format (e.g. "openai/gpt-5.4-mini")'),
|
|
18375
|
-
variant: z.string().optional(),
|
|
18376
|
-
prompt: z.string().optional().describe("Optional role/guidance injected into the councillor user prompt")
|
|
18377
|
-
});
|
|
18378
|
-
var CouncilPresetSchema = z.record(z.string(), z.record(z.string(), z.unknown())).transform((entries, ctx) => {
|
|
18379
|
-
const councillors = {};
|
|
18380
|
-
for (const [key, raw] of Object.entries(entries)) {
|
|
18381
|
-
if (key === "master")
|
|
18382
|
-
continue;
|
|
18383
|
-
if (key === "councillors" && typeof raw === "object" && raw !== null) {
|
|
18384
|
-
for (const [innerKey, innerRaw] of Object.entries(raw)) {
|
|
18385
|
-
const innerParsed = CouncillorConfigSchema.safeParse(innerRaw);
|
|
18386
|
-
if (!innerParsed.success) {
|
|
18387
|
-
ctx.addIssue({
|
|
18388
|
-
code: z.ZodIssueCode.custom,
|
|
18389
|
-
message: `Invalid councillor "${innerKey}" (nested under legacy "councillors" key): ${innerParsed.error.issues.map((i) => i.message).join(", ")}`
|
|
18390
|
-
});
|
|
18391
|
-
return z.NEVER;
|
|
18392
|
-
}
|
|
18393
|
-
councillors[innerKey] = innerParsed.data;
|
|
18394
|
-
}
|
|
18395
|
-
continue;
|
|
18396
|
-
}
|
|
18397
|
-
const parsed = CouncillorConfigSchema.safeParse(raw);
|
|
18398
|
-
if (!parsed.success) {
|
|
18399
|
-
ctx.addIssue({
|
|
18400
|
-
code: z.ZodIssueCode.custom,
|
|
18401
|
-
message: `Invalid councillor "${key}": ${parsed.error.issues.map((i) => i.message).join(", ")}`
|
|
18402
|
-
});
|
|
18403
|
-
return z.NEVER;
|
|
18404
|
-
}
|
|
18405
|
-
councillors[key] = parsed.data;
|
|
18406
|
-
}
|
|
18407
|
-
return councillors;
|
|
18408
|
-
});
|
|
18409
|
-
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.');
|
|
18410
|
-
var CouncilConfigSchema = z.object({
|
|
18411
|
-
presets: z.record(z.string(), CouncilPresetSchema),
|
|
18412
|
-
timeout: z.number().min(0).default(180000),
|
|
18413
|
-
default_preset: z.string().default("default"),
|
|
18414
|
-
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).'),
|
|
18415
|
-
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."),
|
|
18416
|
-
master: z.unknown().optional().describe("DEPRECATED — ignored. Council agent synthesizes directly."),
|
|
18417
|
-
master_timeout: z.unknown().optional().describe('DEPRECATED — ignored. Use "timeout" instead.'),
|
|
18418
|
-
master_fallback: z.unknown().optional().describe("DEPRECATED — ignored. No separate master session.")
|
|
18419
|
-
}).transform((data) => {
|
|
18420
|
-
const deprecated = [];
|
|
18421
|
-
if (data.master !== undefined)
|
|
18422
|
-
deprecated.push("master");
|
|
18423
|
-
if (data.master_timeout !== undefined)
|
|
18424
|
-
deprecated.push("master_timeout");
|
|
18425
|
-
if (data.master_fallback !== undefined)
|
|
18426
|
-
deprecated.push("master_fallback");
|
|
18427
|
-
const legacyMasterModel = typeof data.master === "object" && data.master !== null && "model" in data.master && typeof data.master.model === "string" ? data.master.model : undefined;
|
|
18428
|
-
return {
|
|
18429
|
-
presets: data.presets,
|
|
18430
|
-
timeout: data.timeout,
|
|
18431
|
-
default_preset: data.default_preset,
|
|
18432
|
-
councillor_execution_mode: data.councillor_execution_mode,
|
|
18433
|
-
councillor_retries: data.councillor_retries,
|
|
18434
|
-
_deprecated: deprecated.length > 0 ? deprecated : undefined,
|
|
18435
|
-
_legacyMasterModel: legacyMasterModel
|
|
18436
|
-
};
|
|
18437
|
-
});
|
|
18350
|
+
var DEFAULT_DISABLED_AGENTS = [];
|
|
18438
18351
|
// src/config/loader.ts
|
|
18439
18352
|
import * as fs from "node:fs";
|
|
18440
18353
|
import * as path from "node:path";
|
|
@@ -18464,11 +18377,7 @@ function getOpenCodeConfigPaths() {
|
|
|
18464
18377
|
// src/config/agent-mcps.ts
|
|
18465
18378
|
var DEFAULT_AGENT_MCPS = {
|
|
18466
18379
|
orchestrator: ["*", "!context7"],
|
|
18467
|
-
researcher: ["websearch", "context7", "grep_app"]
|
|
18468
|
-
reviewer: [],
|
|
18469
|
-
implementer: [],
|
|
18470
|
-
council: [],
|
|
18471
|
-
councillor: []
|
|
18380
|
+
researcher: ["websearch", "context7", "grep_app"]
|
|
18472
18381
|
};
|
|
18473
18382
|
function parseList(items, allAvailable) {
|
|
18474
18383
|
if (!items || items.length === 0) {
|
|
@@ -18501,9 +18410,9 @@ function stripJsonComments(json) {
|
|
|
18501
18410
|
}
|
|
18502
18411
|
|
|
18503
18412
|
// src/config/schema.ts
|
|
18504
|
-
import { z
|
|
18505
|
-
var ProviderModelIdSchema =
|
|
18506
|
-
var ManualAgentPlanSchema =
|
|
18413
|
+
import { z } from "zod";
|
|
18414
|
+
var ProviderModelIdSchema = z.string().regex(/^[^/\s]+\/[^\s]+$/, "Expected provider/model format (provider/.../model)");
|
|
18415
|
+
var ManualAgentPlanSchema = z.object({
|
|
18507
18416
|
primary: ProviderModelIdSchema,
|
|
18508
18417
|
fallback1: ProviderModelIdSchema,
|
|
18509
18418
|
fallback2: ProviderModelIdSchema,
|
|
@@ -18517,46 +18426,42 @@ var ManualAgentPlanSchema = z2.object({
|
|
|
18517
18426
|
]);
|
|
18518
18427
|
if (unique.size !== 4) {
|
|
18519
18428
|
ctx.addIssue({
|
|
18520
|
-
code:
|
|
18429
|
+
code: z.ZodIssueCode.custom,
|
|
18521
18430
|
message: "primary and fallbacks must be unique per agent"
|
|
18522
18431
|
});
|
|
18523
18432
|
}
|
|
18524
18433
|
});
|
|
18525
|
-
var ManualPlanSchema =
|
|
18434
|
+
var ManualPlanSchema = z.object({
|
|
18526
18435
|
orchestrator: ManualAgentPlanSchema,
|
|
18527
|
-
researcher: ManualAgentPlanSchema
|
|
18528
|
-
reviewer: ManualAgentPlanSchema,
|
|
18529
|
-
implementer: ManualAgentPlanSchema
|
|
18436
|
+
researcher: ManualAgentPlanSchema
|
|
18530
18437
|
}).strict();
|
|
18531
|
-
var AgentModelChainSchema =
|
|
18532
|
-
var FallbackChainsSchema =
|
|
18438
|
+
var AgentModelChainSchema = z.array(z.string()).min(1);
|
|
18439
|
+
var FallbackChainsSchema = z.object({
|
|
18533
18440
|
orchestrator: AgentModelChainSchema.optional(),
|
|
18534
|
-
researcher: AgentModelChainSchema.optional()
|
|
18535
|
-
reviewer: AgentModelChainSchema.optional(),
|
|
18536
|
-
implementer: AgentModelChainSchema.optional()
|
|
18441
|
+
researcher: AgentModelChainSchema.optional()
|
|
18537
18442
|
}).catchall(AgentModelChainSchema);
|
|
18538
|
-
var AgentOverrideConfigSchema =
|
|
18539
|
-
model:
|
|
18540
|
-
|
|
18541
|
-
|
|
18542
|
-
|
|
18543
|
-
|
|
18544
|
-
id:
|
|
18545
|
-
variant:
|
|
18443
|
+
var AgentOverrideConfigSchema = z.object({
|
|
18444
|
+
model: z.union([
|
|
18445
|
+
z.string(),
|
|
18446
|
+
z.array(z.union([
|
|
18447
|
+
z.string(),
|
|
18448
|
+
z.object({
|
|
18449
|
+
id: z.string(),
|
|
18450
|
+
variant: z.string().optional()
|
|
18546
18451
|
})
|
|
18547
18452
|
])).min(1)
|
|
18548
18453
|
]).optional(),
|
|
18549
|
-
temperature:
|
|
18550
|
-
variant:
|
|
18551
|
-
skills:
|
|
18552
|
-
mcps:
|
|
18553
|
-
prompt:
|
|
18554
|
-
orchestratorPrompt:
|
|
18555
|
-
options:
|
|
18556
|
-
displayName:
|
|
18454
|
+
temperature: z.number().min(0).max(2).optional(),
|
|
18455
|
+
variant: z.string().optional().catch(undefined),
|
|
18456
|
+
skills: z.array(z.string()).optional(),
|
|
18457
|
+
mcps: z.array(z.string()).optional(),
|
|
18458
|
+
prompt: z.string().min(1).optional(),
|
|
18459
|
+
orchestratorPrompt: z.string().min(1).optional(),
|
|
18460
|
+
options: z.record(z.string(), z.unknown()).optional(),
|
|
18461
|
+
displayName: z.string().min(1).optional()
|
|
18557
18462
|
}).strict();
|
|
18558
|
-
var MultiplexerTypeSchema =
|
|
18559
|
-
var MultiplexerLayoutSchema =
|
|
18463
|
+
var MultiplexerTypeSchema = z.enum(["auto", "tmux", "zellij", "none"]);
|
|
18464
|
+
var MultiplexerLayoutSchema = z.enum([
|
|
18560
18465
|
"main-horizontal",
|
|
18561
18466
|
"main-vertical",
|
|
18562
18467
|
"tiled",
|
|
@@ -18564,56 +18469,56 @@ var MultiplexerLayoutSchema = z2.enum([
|
|
|
18564
18469
|
"even-vertical"
|
|
18565
18470
|
]);
|
|
18566
18471
|
var TmuxLayoutSchema = MultiplexerLayoutSchema;
|
|
18567
|
-
var MultiplexerConfigSchema =
|
|
18472
|
+
var MultiplexerConfigSchema = z.object({
|
|
18568
18473
|
type: MultiplexerTypeSchema.default("none"),
|
|
18569
18474
|
layout: MultiplexerLayoutSchema.default("main-vertical"),
|
|
18570
|
-
main_pane_size:
|
|
18475
|
+
main_pane_size: z.number().min(20).max(80).default(60)
|
|
18571
18476
|
});
|
|
18572
|
-
var TmuxConfigSchema =
|
|
18573
|
-
enabled:
|
|
18477
|
+
var TmuxConfigSchema = z.object({
|
|
18478
|
+
enabled: z.boolean().default(false),
|
|
18574
18479
|
layout: TmuxLayoutSchema.default("main-vertical"),
|
|
18575
|
-
main_pane_size:
|
|
18480
|
+
main_pane_size: z.number().min(20).max(80).default(60)
|
|
18576
18481
|
});
|
|
18577
|
-
var PresetSchema =
|
|
18578
|
-
var WebsearchConfigSchema =
|
|
18579
|
-
provider:
|
|
18482
|
+
var PresetSchema = z.record(z.string(), AgentOverrideConfigSchema);
|
|
18483
|
+
var WebsearchConfigSchema = z.object({
|
|
18484
|
+
provider: z.enum(["exa", "tavily"]).default("exa")
|
|
18580
18485
|
});
|
|
18581
|
-
var McpNameSchema =
|
|
18582
|
-
var InterviewConfigSchema =
|
|
18583
|
-
maxQuestions:
|
|
18584
|
-
outputFolder:
|
|
18585
|
-
autoOpenBrowser:
|
|
18586
|
-
port:
|
|
18587
|
-
dashboard:
|
|
18486
|
+
var McpNameSchema = z.enum(["websearch", "context7", "grep_app"]);
|
|
18487
|
+
var InterviewConfigSchema = z.object({
|
|
18488
|
+
maxQuestions: z.number().int().min(1).max(10).default(2),
|
|
18489
|
+
outputFolder: z.string().min(1).default("interview"),
|
|
18490
|
+
autoOpenBrowser: z.boolean().default(true).describe("Automatically open the interview UI in your default browser during interactive runs. Disabled automatically in tests and CI."),
|
|
18491
|
+
port: z.number().int().min(0).max(65535).default(0),
|
|
18492
|
+
dashboard: z.boolean().default(false)
|
|
18588
18493
|
});
|
|
18589
|
-
var SessionManagerConfigSchema =
|
|
18590
|
-
maxSessionsPerAgent:
|
|
18591
|
-
readContextMinLines:
|
|
18592
|
-
readContextMaxFiles:
|
|
18494
|
+
var SessionManagerConfigSchema = z.object({
|
|
18495
|
+
maxSessionsPerAgent: z.number().int().min(1).max(10).default(2),
|
|
18496
|
+
readContextMinLines: z.number().int().min(0).max(1000).default(10),
|
|
18497
|
+
readContextMaxFiles: z.number().int().min(0).max(50).default(8)
|
|
18593
18498
|
});
|
|
18594
|
-
var DivoomConfigSchema =
|
|
18595
|
-
enabled:
|
|
18596
|
-
python:
|
|
18597
|
-
script:
|
|
18598
|
-
size:
|
|
18599
|
-
fps:
|
|
18600
|
-
speed:
|
|
18601
|
-
maxFrames:
|
|
18602
|
-
posterizeBits:
|
|
18603
|
-
gifs:
|
|
18499
|
+
var DivoomConfigSchema = z.object({
|
|
18500
|
+
enabled: z.boolean().default(false),
|
|
18501
|
+
python: z.string().min(1).default("/Applications/Divoom MiniToo.app/Contents/Resources/.venv/bin/python"),
|
|
18502
|
+
script: z.string().min(1).default("/Applications/Divoom MiniToo.app/Contents/Resources/tools/divoom_send.py"),
|
|
18503
|
+
size: z.number().int().min(1).max(1024).default(128),
|
|
18504
|
+
fps: z.number().int().min(1).max(60).default(8),
|
|
18505
|
+
speed: z.number().int().min(1).max(1e4).default(125),
|
|
18506
|
+
maxFrames: z.number().int().min(1).max(500).default(24),
|
|
18507
|
+
posterizeBits: z.number().int().min(1).max(8).default(3),
|
|
18508
|
+
gifs: z.record(z.string(), z.string().min(1)).optional()
|
|
18604
18509
|
});
|
|
18605
|
-
var TodoContinuationConfigSchema =
|
|
18606
|
-
maxContinuations:
|
|
18607
|
-
cooldownMs:
|
|
18608
|
-
autoEnable:
|
|
18609
|
-
autoEnableThreshold:
|
|
18510
|
+
var TodoContinuationConfigSchema = z.object({
|
|
18511
|
+
maxContinuations: z.number().int().min(1).max(50).default(5).describe("Maximum consecutive auto-continuations before stopping to ask user"),
|
|
18512
|
+
cooldownMs: z.number().int().min(0).max(30000).default(3000).describe("Delay in ms before auto-continuing (gives user time to abort)"),
|
|
18513
|
+
autoEnable: z.boolean().default(false).describe("Automatically enable auto-continue when the orchestrator session has enough todos"),
|
|
18514
|
+
autoEnableThreshold: z.number().int().min(1).max(50).default(4).describe("Number of todos that triggers auto-enable (only used when autoEnable is true)")
|
|
18610
18515
|
});
|
|
18611
|
-
var FailoverConfigSchema =
|
|
18612
|
-
enabled:
|
|
18613
|
-
timeoutMs:
|
|
18614
|
-
retryDelayMs:
|
|
18516
|
+
var FailoverConfigSchema = z.object({
|
|
18517
|
+
enabled: z.boolean().default(true),
|
|
18518
|
+
timeoutMs: z.number().min(0).default(15000),
|
|
18519
|
+
retryDelayMs: z.number().min(0).default(500),
|
|
18615
18520
|
chains: FallbackChainsSchema.default({}),
|
|
18616
|
-
retry_on_empty:
|
|
18521
|
+
retry_on_empty: z.boolean().default(true).describe("When true (default), empty provider responses are treated as failures, " + "triggering fallback/retry. Set to false to treat them as successes.")
|
|
18617
18522
|
});
|
|
18618
18523
|
function validateCustomOnlyPromptFields(overrides, ctx, pathPrefix) {
|
|
18619
18524
|
for (const [name, override] of Object.entries(overrides)) {
|
|
@@ -18623,31 +18528,31 @@ function validateCustomOnlyPromptFields(overrides, ctx, pathPrefix) {
|
|
|
18623
18528
|
}
|
|
18624
18529
|
if (override.prompt !== undefined) {
|
|
18625
18530
|
ctx.addIssue({
|
|
18626
|
-
code:
|
|
18531
|
+
code: z.ZodIssueCode.custom,
|
|
18627
18532
|
path: [...pathPrefix, name, "prompt"],
|
|
18628
18533
|
message: "prompt is only supported for custom agents"
|
|
18629
18534
|
});
|
|
18630
18535
|
}
|
|
18631
18536
|
if (override.orchestratorPrompt !== undefined) {
|
|
18632
18537
|
ctx.addIssue({
|
|
18633
|
-
code:
|
|
18538
|
+
code: z.ZodIssueCode.custom,
|
|
18634
18539
|
path: [...pathPrefix, name, "orchestratorPrompt"],
|
|
18635
18540
|
message: "orchestratorPrompt is only supported for custom agents"
|
|
18636
18541
|
});
|
|
18637
18542
|
}
|
|
18638
18543
|
}
|
|
18639
18544
|
}
|
|
18640
|
-
var PluginConfigSchema =
|
|
18641
|
-
preset:
|
|
18642
|
-
setDefaultAgent:
|
|
18643
|
-
scoringEngineVersion:
|
|
18644
|
-
balanceProviderUsage:
|
|
18645
|
-
autoUpdate:
|
|
18545
|
+
var PluginConfigSchema = z.object({
|
|
18546
|
+
preset: z.string().optional(),
|
|
18547
|
+
setDefaultAgent: z.boolean().optional(),
|
|
18548
|
+
scoringEngineVersion: z.enum(["v1", "v2-shadow", "v2"]).optional(),
|
|
18549
|
+
balanceProviderUsage: z.boolean().optional(),
|
|
18550
|
+
autoUpdate: z.boolean().optional().describe("Disable automatic installation of plugin updates when false. Defaults to true."),
|
|
18646
18551
|
manualPlan: ManualPlanSchema.optional(),
|
|
18647
|
-
presets:
|
|
18648
|
-
agents:
|
|
18649
|
-
disabled_agents:
|
|
18650
|
-
disabled_mcps:
|
|
18552
|
+
presets: z.record(z.string(), PresetSchema).optional(),
|
|
18553
|
+
agents: z.record(z.string(), AgentOverrideConfigSchema).optional(),
|
|
18554
|
+
disabled_agents: z.array(z.string()).optional().describe("Agent names to disable completely. " + "Disabled agents are not instantiated and cannot be delegated to. " + "Orchestrator and researcher cannot be disabled."),
|
|
18555
|
+
disabled_mcps: z.array(z.string()).optional(),
|
|
18651
18556
|
multiplexer: MultiplexerConfigSchema.optional(),
|
|
18652
18557
|
tmux: TmuxConfigSchema.optional(),
|
|
18653
18558
|
websearch: WebsearchConfigSchema.optional(),
|
|
@@ -18655,8 +18560,7 @@ var PluginConfigSchema = z2.object({
|
|
|
18655
18560
|
sessionManager: SessionManagerConfigSchema.optional(),
|
|
18656
18561
|
divoom: DivoomConfigSchema.optional(),
|
|
18657
18562
|
todoContinuation: TodoContinuationConfigSchema.optional(),
|
|
18658
|
-
fallback: FailoverConfigSchema.optional()
|
|
18659
|
-
council: CouncilConfigSchema.optional()
|
|
18563
|
+
fallback: FailoverConfigSchema.optional()
|
|
18660
18564
|
}).superRefine((value, ctx) => {
|
|
18661
18565
|
if (value.agents) {
|
|
18662
18566
|
validateCustomOnlyPromptFields(value.agents, ctx, ["agents"]);
|
|
@@ -18724,8 +18628,7 @@ function mergePluginConfigs(base, override) {
|
|
|
18724
18628
|
interview: deepMerge(base.interview, override.interview),
|
|
18725
18629
|
sessionManager: deepMerge(base.sessionManager, override.sessionManager),
|
|
18726
18630
|
divoom: deepMerge(base.divoom, override.divoom),
|
|
18727
|
-
fallback: deepMerge(base.fallback, override.fallback)
|
|
18728
|
-
council: deepMerge(base.council, override.council)
|
|
18631
|
+
fallback: deepMerge(base.fallback, override.fallback)
|
|
18729
18632
|
};
|
|
18730
18633
|
}
|
|
18731
18634
|
function deepMerge(base, override) {
|
|
@@ -18821,99 +18724,6 @@ function getCustomAgentNames(config) {
|
|
|
18821
18724
|
return !ALL_AGENT_NAMES.includes(name);
|
|
18822
18725
|
});
|
|
18823
18726
|
}
|
|
18824
|
-
// src/utils/session.ts
|
|
18825
|
-
var SESSION_ABORT_TIMEOUT_MS = 1000;
|
|
18826
|
-
|
|
18827
|
-
class OperationTimeoutError extends Error {
|
|
18828
|
-
constructor(message) {
|
|
18829
|
-
super(message);
|
|
18830
|
-
this.name = "OperationTimeoutError";
|
|
18831
|
-
}
|
|
18832
|
-
}
|
|
18833
|
-
async function withTimeout(operation, timeoutMs, message) {
|
|
18834
|
-
if (timeoutMs <= 0)
|
|
18835
|
-
return operation;
|
|
18836
|
-
let timer;
|
|
18837
|
-
try {
|
|
18838
|
-
return await Promise.race([
|
|
18839
|
-
operation,
|
|
18840
|
-
new Promise((_, reject) => {
|
|
18841
|
-
timer = setTimeout(() => {
|
|
18842
|
-
reject(new OperationTimeoutError(message));
|
|
18843
|
-
}, timeoutMs);
|
|
18844
|
-
})
|
|
18845
|
-
]);
|
|
18846
|
-
} finally {
|
|
18847
|
-
clearTimeout(timer);
|
|
18848
|
-
}
|
|
18849
|
-
}
|
|
18850
|
-
async function abortSessionWithTimeout(client, sessionId, timeoutMs = SESSION_ABORT_TIMEOUT_MS) {
|
|
18851
|
-
await withTimeout(client.session.abort({ path: { id: sessionId } }), timeoutMs, `Session abort timed out after ${timeoutMs}ms`);
|
|
18852
|
-
}
|
|
18853
|
-
function shortModelLabel(model) {
|
|
18854
|
-
return model.split("/").pop() ?? model;
|
|
18855
|
-
}
|
|
18856
|
-
function parseModelReference(model) {
|
|
18857
|
-
const slashIndex = model.indexOf("/");
|
|
18858
|
-
if (slashIndex <= 0 || slashIndex >= model.length - 1) {
|
|
18859
|
-
return null;
|
|
18860
|
-
}
|
|
18861
|
-
return {
|
|
18862
|
-
providerID: model.slice(0, slashIndex),
|
|
18863
|
-
modelID: model.slice(slashIndex + 1)
|
|
18864
|
-
};
|
|
18865
|
-
}
|
|
18866
|
-
async function promptWithTimeout(client, args, timeoutMs) {
|
|
18867
|
-
if (timeoutMs <= 0) {
|
|
18868
|
-
await client.session.prompt(args);
|
|
18869
|
-
return;
|
|
18870
|
-
}
|
|
18871
|
-
const sessionId = args.path.id;
|
|
18872
|
-
let timer;
|
|
18873
|
-
try {
|
|
18874
|
-
const promptPromise = client.session.prompt(args);
|
|
18875
|
-
promptPromise.catch(() => {});
|
|
18876
|
-
await Promise.race([
|
|
18877
|
-
promptPromise,
|
|
18878
|
-
new Promise((_, reject) => {
|
|
18879
|
-
timer = setTimeout(() => {
|
|
18880
|
-
reject(new OperationTimeoutError(`Prompt timed out after ${timeoutMs}ms`));
|
|
18881
|
-
}, timeoutMs);
|
|
18882
|
-
})
|
|
18883
|
-
]);
|
|
18884
|
-
} catch (error) {
|
|
18885
|
-
if (error instanceof OperationTimeoutError) {
|
|
18886
|
-
try {
|
|
18887
|
-
await abortSessionWithTimeout(client, sessionId);
|
|
18888
|
-
} catch {}
|
|
18889
|
-
}
|
|
18890
|
-
throw error;
|
|
18891
|
-
} finally {
|
|
18892
|
-
clearTimeout(timer);
|
|
18893
|
-
}
|
|
18894
|
-
}
|
|
18895
|
-
async function extractSessionResult(client, sessionId, options) {
|
|
18896
|
-
const includeReasoning = options?.includeReasoning ?? true;
|
|
18897
|
-
const messagesResult = await client.session.messages({
|
|
18898
|
-
path: { id: sessionId }
|
|
18899
|
-
});
|
|
18900
|
-
const messages = messagesResult.data ?? [];
|
|
18901
|
-
const assistantMessages = messages.filter((m) => m.info?.role === "assistant");
|
|
18902
|
-
const extractedContent = [];
|
|
18903
|
-
for (const message of assistantMessages) {
|
|
18904
|
-
for (const part of message.parts ?? []) {
|
|
18905
|
-
const allowed = includeReasoning ? part.type === "text" || part.type === "reasoning" : part.type === "text";
|
|
18906
|
-
if (allowed && part.text) {
|
|
18907
|
-
extractedContent.push(part.text);
|
|
18908
|
-
}
|
|
18909
|
-
}
|
|
18910
|
-
}
|
|
18911
|
-
const text = extractedContent.filter((t) => t.length > 0).join(`
|
|
18912
|
-
|
|
18913
|
-
`);
|
|
18914
|
-
return { text, empty: text.length === 0 };
|
|
18915
|
-
}
|
|
18916
|
-
|
|
18917
18727
|
// src/agents/orchestrator.ts
|
|
18918
18728
|
function resolvePrompt(base, customPrompt, customAppendPrompt) {
|
|
18919
18729
|
if (customPrompt)
|
|
@@ -18930,33 +18740,13 @@ var AGENT_DESCRIPTIONS = {
|
|
|
18930
18740
|
- 权限:只读
|
|
18931
18741
|
- 能力:本地代码搜索(glob/grep/ast)+ 外部文档检索(websearch/context7/grep_app)
|
|
18932
18742
|
- 委派给它当:需要发现代码库中有什么 • 需要查外部库文档 • 并行搜索加速发现
|
|
18933
|
-
- 不委派当:知道路径需要实际内容 • 单次特定查找 •
|
|
18934
|
-
reviewer: `@reviewer
|
|
18935
|
-
- 角色:战略顾问、代码审查者、调试专家
|
|
18936
|
-
- 权限:只读(分析),写操作由 Orchestrator 协调 @implementer 执行
|
|
18937
|
-
- 能力:深度推理、架构分析、根因追踪、代码审查
|
|
18938
|
-
- 委派给它当:重大架构决策 • 复杂调试分析(Phase 1-3)• 代码审查 • 简化/YAGNI 审查
|
|
18939
|
-
- 不委派当:常规决策 • 首次 bug 修复 • 简单权衡
|
|
18940
|
-
- 协调模式:Reviewer 输出 <fix_plan> 时,委派 @implementer 执行修复`,
|
|
18941
|
-
implementer: `@implementer
|
|
18942
|
-
- 角色:快速执行专家
|
|
18943
|
-
- 权限:读写
|
|
18944
|
-
- 能力:代码实现、测试编写、UI/UX 实现
|
|
18945
|
-
- 委派给它当:非平凡的实现任务 • 测试编写/更新 • 多文件修改
|
|
18946
|
-
- 不委派当:需要研究/决策 • 单个小变更(<20 行)• 需求不清楚`,
|
|
18947
|
-
council: `@council(可选,默认禁用)
|
|
18948
|
-
- 角色:多 LLM 共识引擎`
|
|
18743
|
+
- 不委派当:知道路径需要实际内容 • 单次特定查找 • 即将编辑该文件`
|
|
18949
18744
|
};
|
|
18950
18745
|
var DELEGATION_RULES = [
|
|
18951
18746
|
"- 需要搜索代码库或外部文档 → @researcher",
|
|
18952
|
-
"-
|
|
18953
|
-
"-
|
|
18954
|
-
"-
|
|
18955
|
-
"- 知道路径需要内容 → 自己读",
|
|
18956
|
-
"- 单个小变更(<20 行)→ 自己做",
|
|
18957
|
-
"- 需求不清楚 → 问用户,不委派",
|
|
18958
|
-
"- 跳过委派如果开销 ≥ 自己做(Skill 定义的审查流程除外)",
|
|
18959
|
-
"- brainstorming HARD-GATE:设计未批准前,委派任务必须标注 [只读-搜索],禁止委派写入任务"
|
|
18747
|
+
"- 其他所有工作 → 加载对应 Skill,按 Skill 定义的流程执行",
|
|
18748
|
+
"- 单个小变更(<20行)且不涉及设计决策 → 可直接执行",
|
|
18749
|
+
"- 需求不清楚 → 问用户,不委派"
|
|
18960
18750
|
];
|
|
18961
18751
|
function buildOrchestratorPrompt(disabledAgents) {
|
|
18962
18752
|
const enabledAgents = Object.entries(AGENT_DESCRIPTIONS).filter(([name]) => !disabledAgents?.has(name)).map(([, desc]) => desc).join(`
|
|
@@ -18997,13 +18787,10 @@ ${enabledAgents}
|
|
|
18997
18787
|
<Workflow>
|
|
18998
18788
|
1. 理解需求 → 加载 brainstorming skill(如需要)
|
|
18999
18789
|
2. 制定计划 → 加载 writing-plans skill(如需要)
|
|
19000
|
-
3.
|
|
19001
|
-
├─ 实现任务 → 委派
|
|
19002
|
-
├─ 代码审查 → 委派 @reviewer(只读分析)
|
|
19003
|
-
│ └─ 需要修复 → 委派 @implementer(执行修复)
|
|
18790
|
+
3. 执行实现 → 加载 subagent-driven-development skill
|
|
18791
|
+
├─ 实现任务 → 委派 implementer subagent
|
|
19004
18792
|
├─ 代码搜索 → 委派 @researcher
|
|
19005
|
-
└─
|
|
19006
|
-
└─ 需要修复 → 委派 @implementer(Phase 4 执行)
|
|
18793
|
+
└─ 审查 → 委派 spec/code quality reviewer subagent
|
|
19007
18794
|
4. 验证完成 → 加载 verification-before-completion skill
|
|
19008
18795
|
5. 收尾 → 加载 finishing-a-development-branch skill
|
|
19009
18796
|
</Workflow>
|
|
@@ -19064,236 +18851,6 @@ function createOrchestratorAgent(model, customPrompt, customAppendPrompt, disabl
|
|
|
19064
18851
|
return definition;
|
|
19065
18852
|
}
|
|
19066
18853
|
|
|
19067
|
-
// src/agents/council.ts
|
|
19068
|
-
var COUNCIL_AGENT_PROMPT = `You are the Council agent — a multi-LLM orchestration system that runs consensus across multiple models.
|
|
19069
|
-
|
|
19070
|
-
**Tool**: You have access to the \`council_session\` tool.
|
|
19071
|
-
|
|
19072
|
-
**When to use**:
|
|
19073
|
-
- When invoked by a user with a request
|
|
19074
|
-
- When you want multiple expert opinions on a complex problem
|
|
19075
|
-
- When higher confidence is needed through model consensus
|
|
19076
|
-
|
|
19077
|
-
**Usage**:
|
|
19078
|
-
1. Call the \`council_session\` tool with the user's prompt
|
|
19079
|
-
2. Optionally specify a preset (default: "default")
|
|
19080
|
-
3. Receive the councillor responses formatted for synthesis
|
|
19081
|
-
4. Follow the Synthesis Process below
|
|
19082
|
-
5. Present the result to the user
|
|
19083
|
-
|
|
19084
|
-
**Synthesis Process** (MANDATORY — follow in order):
|
|
19085
|
-
1. Read the original user prompt
|
|
19086
|
-
2. Review each councillor's response individually — note each councillor's key insight and unique contribution by name
|
|
19087
|
-
3. Identify agreements and contradictions between councillors
|
|
19088
|
-
4. Resolve contradictions with explicit reasoning
|
|
19089
|
-
5. Synthesize the optimal final answer
|
|
19090
|
-
6. Format output per the Required Output Format below
|
|
19091
|
-
|
|
19092
|
-
**Behavior**:
|
|
19093
|
-
- Delegate requests directly to council_session
|
|
19094
|
-
- Don't pre-analyze or filter the prompt before calling council_session
|
|
19095
|
-
- Credit specific insights from individual councillors using their names
|
|
19096
|
-
- If councillors disagree, explain why you chose one approach over another
|
|
19097
|
-
- Do not omit per-councillor details from the final response
|
|
19098
|
-
- Do not collapse the output into only a final summary
|
|
19099
|
-
- Be transparent about trade-offs when different approaches have valid pros/cons
|
|
19100
|
-
- Don't just average responses — choose the best approach and improve upon it
|
|
19101
|
-
|
|
19102
|
-
**Required Output Format**:
|
|
19103
|
-
Always include these sections in your final response:
|
|
19104
|
-
|
|
19105
|
-
## Council Response
|
|
19106
|
-
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.
|
|
19107
|
-
|
|
19108
|
-
## Councillor Details
|
|
19109
|
-
Include each councillor's response separately.
|
|
19110
|
-
|
|
19111
|
-
Use each councillor name exactly as provided in the tool result.
|
|
19112
|
-
|
|
19113
|
-
Format each councillor like:
|
|
19114
|
-
|
|
19115
|
-
### <councillor name>
|
|
19116
|
-
<that councillor's response>
|
|
19117
|
-
|
|
19118
|
-
If a councillor failed or timed out, include that status briefly.
|
|
19119
|
-
|
|
19120
|
-
## Council Summary
|
|
19121
|
-
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.`;
|
|
19122
|
-
function createCouncilAgent(model, customPrompt, customAppendPrompt) {
|
|
19123
|
-
const prompt = resolvePrompt(COUNCIL_AGENT_PROMPT, customPrompt, customAppendPrompt);
|
|
19124
|
-
const definition = {
|
|
19125
|
-
name: "council",
|
|
19126
|
-
description: "Multi-LLM council agent that synthesizes responses from multiple models for higher-quality outputs",
|
|
19127
|
-
config: {
|
|
19128
|
-
temperature: 0.1,
|
|
19129
|
-
prompt
|
|
19130
|
-
}
|
|
19131
|
-
};
|
|
19132
|
-
if (model) {
|
|
19133
|
-
definition.config.model = model;
|
|
19134
|
-
}
|
|
19135
|
-
return definition;
|
|
19136
|
-
}
|
|
19137
|
-
function formatCouncillorPrompt(userPrompt, councillorPrompt) {
|
|
19138
|
-
if (!councillorPrompt)
|
|
19139
|
-
return userPrompt;
|
|
19140
|
-
return `${councillorPrompt}
|
|
19141
|
-
|
|
19142
|
-
---
|
|
19143
|
-
|
|
19144
|
-
${userPrompt}`;
|
|
19145
|
-
}
|
|
19146
|
-
function formatCouncillorResults(originalPrompt, councillorResults) {
|
|
19147
|
-
const completedWithResults = councillorResults.filter((cr) => cr.status === "completed" && cr.result);
|
|
19148
|
-
const councillorSection = completedWithResults.map((cr) => {
|
|
19149
|
-
const shortModel = shortModelLabel(cr.model);
|
|
19150
|
-
return `**${cr.name}** (${shortModel}):
|
|
19151
|
-
${cr.result}`;
|
|
19152
|
-
}).join(`
|
|
19153
|
-
|
|
19154
|
-
`);
|
|
19155
|
-
const failedSection = councillorResults.filter((cr) => cr.status !== "completed").map((cr) => `**${cr.name}**: ${cr.status} — ${cr.error ?? "Unknown"}`).join(`
|
|
19156
|
-
`);
|
|
19157
|
-
if (completedWithResults.length === 0) {
|
|
19158
|
-
const errorDetails = councillorResults.map((cr) => `**${cr.name}** (${shortModelLabel(cr.model)}): ${cr.status} — ${cr.error ?? "Unknown"}`).join(`
|
|
19159
|
-
`);
|
|
19160
|
-
return `---
|
|
19161
|
-
|
|
19162
|
-
**Original Prompt**:
|
|
19163
|
-
${originalPrompt}
|
|
19164
|
-
|
|
19165
|
-
---
|
|
19166
|
-
|
|
19167
|
-
**Councillor Responses**:
|
|
19168
|
-
All councillors failed to produce output:
|
|
19169
|
-
${errorDetails}
|
|
19170
|
-
|
|
19171
|
-
Please generate a response based on the original prompt alone.`;
|
|
19172
|
-
}
|
|
19173
|
-
let prompt = `---
|
|
19174
|
-
|
|
19175
|
-
**Original Prompt**:
|
|
19176
|
-
${originalPrompt}
|
|
19177
|
-
|
|
19178
|
-
---
|
|
19179
|
-
|
|
19180
|
-
**Councillor Responses**:
|
|
19181
|
-
${councillorSection}`;
|
|
19182
|
-
if (failedSection) {
|
|
19183
|
-
prompt += `
|
|
19184
|
-
|
|
19185
|
-
---
|
|
19186
|
-
|
|
19187
|
-
**Failed/Timed-out Councillors**:
|
|
19188
|
-
${failedSection}`;
|
|
19189
|
-
}
|
|
19190
|
-
prompt += `
|
|
19191
|
-
|
|
19192
|
-
---
|
|
19193
|
-
|
|
19194
|
-
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).`;
|
|
19195
|
-
return prompt;
|
|
19196
|
-
}
|
|
19197
|
-
|
|
19198
|
-
// src/agents/councillor.ts
|
|
19199
|
-
var COUNCILLOR_PROMPT = `You are a councillor in a multi-model council.
|
|
19200
|
-
|
|
19201
|
-
**Role**: Provide your best independent analysis and solution to the given problem.
|
|
19202
|
-
|
|
19203
|
-
**Capabilities**: You have read-only access to the codebase. You can:
|
|
19204
|
-
- Read files (read)
|
|
19205
|
-
- Search by name patterns (glob)
|
|
19206
|
-
- Search by content (grep)
|
|
19207
|
-
- Search code patterns (ast_grep_search)
|
|
19208
|
-
- Use OpenCode's built-in \`lsp\` tool when available
|
|
19209
|
-
- Search external docs (if MCPs are configured for this agent)
|
|
19210
|
-
|
|
19211
|
-
You CANNOT edit files, write files, run shell commands, or delegate to other agents. You are an advisor, not an implementer.
|
|
19212
|
-
|
|
19213
|
-
**Behavior**:
|
|
19214
|
-
- **Examine the codebase** before answering — your read access is what makes council valuable. Don't guess at code you can see.
|
|
19215
|
-
- Analyze the problem thoroughly
|
|
19216
|
-
- Provide a complete, well-reasoned response
|
|
19217
|
-
- Focus on the quality and correctness of your solution
|
|
19218
|
-
- Be direct and concise
|
|
19219
|
-
- Don't be influenced by what other councillors might say — you won't see their responses
|
|
19220
|
-
|
|
19221
|
-
**Output**:
|
|
19222
|
-
- Give your honest assessment
|
|
19223
|
-
- Reference specific files and line numbers when relevant
|
|
19224
|
-
- Include relevant reasoning
|
|
19225
|
-
- State any assumptions clearly
|
|
19226
|
-
- Note any uncertainties`;
|
|
19227
|
-
function createCouncillorAgent(model, customPrompt, customAppendPrompt) {
|
|
19228
|
-
const prompt = resolvePrompt(COUNCILLOR_PROMPT, customPrompt, customAppendPrompt);
|
|
19229
|
-
return {
|
|
19230
|
-
name: "councillor",
|
|
19231
|
-
description: "Read-only council advisor. Examines codebase and provides independent analysis. Spawned internally by the council system.",
|
|
19232
|
-
config: {
|
|
19233
|
-
model,
|
|
19234
|
-
temperature: 0.2,
|
|
19235
|
-
prompt,
|
|
19236
|
-
permission: {
|
|
19237
|
-
"*": "deny",
|
|
19238
|
-
question: "deny",
|
|
19239
|
-
read: "allow",
|
|
19240
|
-
glob: "allow",
|
|
19241
|
-
grep: "allow",
|
|
19242
|
-
lsp: "allow",
|
|
19243
|
-
list: "allow",
|
|
19244
|
-
codesearch: "allow",
|
|
19245
|
-
ast_grep_search: "allow"
|
|
19246
|
-
}
|
|
19247
|
-
}
|
|
19248
|
-
};
|
|
19249
|
-
}
|
|
19250
|
-
|
|
19251
|
-
// src/agents/implementer.ts
|
|
19252
|
-
var IMPLEMENTER_PROMPT = `You are Implementer — a fast execution specialist. Execute directly with complete context provided.
|
|
19253
|
-
|
|
19254
|
-
**Role**: Receive complete task specs from the Orchestrator and implement efficiently.
|
|
19255
|
-
|
|
19256
|
-
## Modes
|
|
19257
|
-
- **Execution Mode (default)**: Low-temperature precise execution. No divergence, no research. Implement the task directly.
|
|
19258
|
-
- **Design Mode**: When Orchestrator marks [设计模式] in the prompt, switch to creative design thinking:
|
|
19259
|
-
- Focus on aesthetics, layout, interaction details
|
|
19260
|
-
- Follow design principles: typography, color themes, motion, spatial composition, visual depth
|
|
19261
|
-
- Use Tailwind for responsive design
|
|
19262
|
-
|
|
19263
|
-
## Constraints
|
|
19264
|
-
- NO external research (no websearch, context7, grep_app)
|
|
19265
|
-
- NO delegation or spawning subagents
|
|
19266
|
-
- No multi-step planning; direct execution
|
|
19267
|
-
- When a loaded Skill indicates user input is needed, pause and request clarification
|
|
19268
|
-
- When TDD Skill is loaded, follow red-green-refactor cycle
|
|
19269
|
-
|
|
19270
|
-
## Loadable Skills
|
|
19271
|
-
You can load behavioral guides via the skill tool:
|
|
19272
|
-
- test-driven-development: Load when implementing features or fixing bugs
|
|
19273
|
-
- verification-before-completion: Load when verifying work before completion
|
|
19274
|
-
|
|
19275
|
-
## Output Format
|
|
19276
|
-
<summary>Brief summary of what was implemented</summary>
|
|
19277
|
-
<changes>
|
|
19278
|
-
<file>file1.ts: Changed X to Y</file>
|
|
19279
|
-
<file>file2.ts: Added Z function</file>
|
|
19280
|
-
</changes>
|
|
19281
|
-
<verification>
|
|
19282
|
-
Tests passed: [yes/no/skip reason]
|
|
19283
|
-
Validation: [passed/failed/skip reason]
|
|
19284
|
-
</verification>`;
|
|
19285
|
-
function createImplementerAgent(model, customPrompt, customAppendPrompt) {
|
|
19286
|
-
return {
|
|
19287
|
-
name: "implementer",
|
|
19288
|
-
description: "Fast implementation specialist. Receives complete context and task spec, executes code changes efficiently. Supports execution and design modes.",
|
|
19289
|
-
config: {
|
|
19290
|
-
model,
|
|
19291
|
-
temperature: 0.2,
|
|
19292
|
-
prompt: resolvePrompt(IMPLEMENTER_PROMPT, customPrompt, customAppendPrompt)
|
|
19293
|
-
}
|
|
19294
|
-
};
|
|
19295
|
-
}
|
|
19296
|
-
|
|
19297
18854
|
// src/agents/researcher.ts
|
|
19298
18855
|
var RESEARCHER_PROMPT = `You are Researcher — a codebase and external documentation search specialist.
|
|
19299
18856
|
|
|
@@ -19336,62 +18893,7 @@ function createResearcherAgent(model, customPrompt, customAppendPrompt) {
|
|
|
19336
18893
|
};
|
|
19337
18894
|
}
|
|
19338
18895
|
|
|
19339
|
-
// src/agents/reviewer.ts
|
|
19340
|
-
var REVIEWER_PROMPT = `You are Reviewer — a strategic advisor and code review expert. Analysis only, no execution.
|
|
19341
|
-
|
|
19342
|
-
**Role**: High-IQ debugging, architecture decisions, code review, simplification, and engineering guidance.
|
|
19343
|
-
|
|
19344
|
-
## Responsibilities
|
|
19345
|
-
- Architecture decisions and solution evaluation
|
|
19346
|
-
- Code review (review diffs, not self-review)
|
|
19347
|
-
- Root cause analysis for complex debugging (Phase 1-3)
|
|
19348
|
-
- Simplification and YAGNI review
|
|
19349
|
-
|
|
19350
|
-
## Execution Boundary
|
|
19351
|
-
You only analyze, never execute. When a Skill workflow requires writing code or running commands:
|
|
19352
|
-
- Complete the analysis phase, output structured analysis results and fix plans
|
|
19353
|
-
- Orchestrator coordinates Implementer to execute fixes
|
|
19354
|
-
- Specific rules:
|
|
19355
|
-
- systematic-debugging: You complete Phase 1-3, output fix plan for Phase 4
|
|
19356
|
-
- receiving-code-review: You complete READ → VERIFY → EVALUATE, output fix plan for IMPLEMENT
|
|
19357
|
-
- simplify: You analyze simplification opportunities, output plan for execution
|
|
19358
|
-
|
|
19359
|
-
## Principles
|
|
19360
|
-
- Hold dissenting opinions until convinced by technical arguments
|
|
19361
|
-
- Verify before agreeing — no performative agreement
|
|
19362
|
-
- 3+ fix failures → question the architecture, don't keep patching
|
|
19363
|
-
- 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
|
|
19364
|
-
|
|
19365
|
-
## Loadable Skills
|
|
19366
|
-
You can load behavioral guides via the skill tool:
|
|
19367
|
-
- systematic-debugging: Load when debugging complex bugs (Phase 1-3 analysis)
|
|
19368
|
-
- receiving-code-review: Load when evaluating external feedback (READ → VERIFY → EVALUATE)
|
|
19369
|
-
- simplify: Load when reviewing code for simplification (analyze opportunities, output plan)
|
|
19370
|
-
|
|
19371
|
-
## Output Format
|
|
19372
|
-
<assessment>Overall assessment</assessment>
|
|
19373
|
-
<strengths>What was done well</strengths>
|
|
19374
|
-
<issues>
|
|
19375
|
-
<issue severity="critical">Must-fix issues</issue>
|
|
19376
|
-
<issue severity="important">Should-fix issues</issue>
|
|
19377
|
-
<issue severity="minor">Nice-to-have improvements</issue>
|
|
19378
|
-
</issues>
|
|
19379
|
-
<fix_plan>Fix plan for Orchestrator to coordinate Implementer execution</fix_plan>
|
|
19380
|
-
<recommendation>Recommended next steps</recommendation>`;
|
|
19381
|
-
function createReviewerAgent(model, customPrompt, customAppendPrompt) {
|
|
19382
|
-
return {
|
|
19383
|
-
name: "reviewer",
|
|
19384
|
-
description: "Strategic technical advisor. Use for architecture decisions, complex debugging, code review, simplification, and engineering guidance.",
|
|
19385
|
-
config: {
|
|
19386
|
-
model,
|
|
19387
|
-
temperature: 0.1,
|
|
19388
|
-
prompt: resolvePrompt(REVIEWER_PROMPT, customPrompt, customAppendPrompt)
|
|
19389
|
-
}
|
|
19390
|
-
};
|
|
19391
|
-
}
|
|
19392
|
-
|
|
19393
18896
|
// src/agents/index.ts
|
|
19394
|
-
var COUNCIL_TOOL_ALLOWED_AGENTS = new Set(["council"]);
|
|
19395
18897
|
var SAFE_AGENT_ALIAS_RE = /^[a-z][a-z0-9_-]*$/i;
|
|
19396
18898
|
function normalizeDisplayName(displayName) {
|
|
19397
18899
|
const trimmed = displayName.trim();
|
|
@@ -19446,7 +18948,7 @@ function buildCustomAgentDefinition(name, override, filePrompt, fileAppendPrompt
|
|
|
19446
18948
|
return {
|
|
19447
18949
|
name,
|
|
19448
18950
|
config: {
|
|
19449
|
-
model: typeof override.model === "string" ? override.model : DEFAULT_MODELS.orchestrator ?? DEFAULT_MODELS.
|
|
18951
|
+
model: typeof override.model === "string" ? override.model : DEFAULT_MODELS.orchestrator ?? DEFAULT_MODELS.researcher,
|
|
19450
18952
|
temperature: 0.2,
|
|
19451
18953
|
prompt: resolvePrompt(basePrompt, filePrompt, fileAppendPrompt)
|
|
19452
18954
|
}
|
|
@@ -19467,11 +18969,9 @@ function applyDefaultPermissions(agent, configuredSkills) {
|
|
|
19467
18969
|
const existing = agent.config.permission ?? {};
|
|
19468
18970
|
const skillPermissions = getSkillPermissionsForAgent(agent.name, configuredSkills);
|
|
19469
18971
|
const questionPerm = existing.question === "deny" ? "deny" : "allow";
|
|
19470
|
-
const councilSessionPerm = COUNCIL_TOOL_ALLOWED_AGENTS.has(agent.name) ? existing.council_session ?? "allow" : "deny";
|
|
19471
18972
|
agent.config.permission = {
|
|
19472
18973
|
...existing,
|
|
19473
18974
|
question: questionPerm,
|
|
19474
|
-
council_session: councilSessionPerm,
|
|
19475
18975
|
skill: {
|
|
19476
18976
|
...typeof existing.skill === "object" ? existing.skill : {},
|
|
19477
18977
|
...skillPermissions
|
|
@@ -19482,17 +18982,10 @@ function isSubagent(name) {
|
|
|
19482
18982
|
return SUBAGENT_NAMES.includes(name);
|
|
19483
18983
|
}
|
|
19484
18984
|
var SUBAGENT_FACTORIES = {
|
|
19485
|
-
researcher: createResearcherAgent
|
|
19486
|
-
reviewer: createReviewerAgent,
|
|
19487
|
-
implementer: createImplementerAgent,
|
|
19488
|
-
council: createCouncilAgent,
|
|
19489
|
-
councillor: createCouncillorAgent
|
|
18985
|
+
researcher: createResearcherAgent
|
|
19490
18986
|
};
|
|
19491
18987
|
function createAgents(config) {
|
|
19492
18988
|
const disabled = getDisabledAgents(config);
|
|
19493
|
-
if (!config?.council) {
|
|
19494
|
-
disabled.add("council");
|
|
19495
|
-
}
|
|
19496
18989
|
const protoSubAgents = Object.entries(SUBAGENT_FACTORIES).filter(([name]) => !disabled.has(name)).map(([name, factory]) => {
|
|
19497
18990
|
const customPrompts = loadAgentPrompt(name, config?.preset);
|
|
19498
18991
|
const model = DEFAULT_MODELS[name];
|
|
@@ -19526,13 +19019,6 @@ function createAgents(config) {
|
|
|
19526
19019
|
applyDefaultPermissions(agent, override?.skills);
|
|
19527
19020
|
return agent;
|
|
19528
19021
|
});
|
|
19529
|
-
const legacyMasterModel = config?.council?._legacyMasterModel;
|
|
19530
|
-
if (legacyMasterModel) {
|
|
19531
|
-
const councilAgent = builtInSubAgents.find((a) => a.name === "council");
|
|
19532
|
-
if (councilAgent && !getAgentOverride(config, "council")?.model && councilAgent.config.model === DEFAULT_MODELS.council) {
|
|
19533
|
-
councilAgent.config.model = legacyMasterModel;
|
|
19534
|
-
}
|
|
19535
|
-
}
|
|
19536
19022
|
const customSubAgents = protoCustomAgents.map((agent) => {
|
|
19537
19023
|
const override = getAgentOverride(config, agent.name);
|
|
19538
19024
|
if (override) {
|
|
@@ -19599,12 +19085,7 @@ ${rewrittenPrompts.join(`
|
|
|
19599
19085
|
function getAgentConfigs(config) {
|
|
19600
19086
|
const agents = createAgents(config);
|
|
19601
19087
|
const applyClassification = (name, sdkConfig) => {
|
|
19602
|
-
if (name
|
|
19603
|
-
sdkConfig.mode = "all";
|
|
19604
|
-
} else if (name === "councillor") {
|
|
19605
|
-
sdkConfig.mode = "subagent";
|
|
19606
|
-
sdkConfig.hidden = true;
|
|
19607
|
-
} else if (isSubagent(name)) {
|
|
19088
|
+
if (isSubagent(name)) {
|
|
19608
19089
|
sdkConfig.mode = "subagent";
|
|
19609
19090
|
} else if (name === "orchestrator") {
|
|
19610
19091
|
sdkConfig.mode = "primary";
|
|
@@ -19612,7 +19093,6 @@ function getAgentConfigs(config) {
|
|
|
19612
19093
|
sdkConfig.mode = "subagent";
|
|
19613
19094
|
}
|
|
19614
19095
|
};
|
|
19615
|
-
const isInternalOnly = (name) => name === "councillor";
|
|
19616
19096
|
const entries = [];
|
|
19617
19097
|
for (const a of agents) {
|
|
19618
19098
|
const sdkConfig = {
|
|
@@ -19625,7 +19105,7 @@ function getAgentConfigs(config) {
|
|
|
19625
19105
|
}
|
|
19626
19106
|
applyClassification(a.name, sdkConfig);
|
|
19627
19107
|
const normalizedDisplayName = a.displayName ? normalizeDisplayName(a.displayName) : undefined;
|
|
19628
|
-
if (normalizedDisplayName
|
|
19108
|
+
if (normalizedDisplayName) {
|
|
19629
19109
|
entries.push([normalizedDisplayName, sdkConfig]);
|
|
19630
19110
|
entries.push([a.name, { ...sdkConfig, hidden: true }]);
|
|
19631
19111
|
continue;
|
|
@@ -19667,6 +19147,13 @@ function rollbackRuntimePreset(previous) {
|
|
|
19667
19147
|
previousRuntimePreset = null;
|
|
19668
19148
|
}
|
|
19669
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
|
+
|
|
19670
19157
|
// src/utils/logger.ts
|
|
19671
19158
|
import * as fs2 from "node:fs";
|
|
19672
19159
|
import { appendFile } from "node:fs/promises";
|
|
@@ -19744,263 +19231,7 @@ function log(message, data) {
|
|
|
19744
19231
|
} catch {}
|
|
19745
19232
|
}
|
|
19746
19233
|
|
|
19747
|
-
// src/council/council-manager.ts
|
|
19748
|
-
class CouncilManager {
|
|
19749
|
-
client;
|
|
19750
|
-
directory;
|
|
19751
|
-
config;
|
|
19752
|
-
depthTracker;
|
|
19753
|
-
tmuxEnabled;
|
|
19754
|
-
deprecatedFields;
|
|
19755
|
-
legacyMasterModel;
|
|
19756
|
-
constructor(ctx, config, depthTracker, tmuxEnabled = false) {
|
|
19757
|
-
this.client = ctx.client;
|
|
19758
|
-
this.directory = ctx.directory;
|
|
19759
|
-
this.config = config;
|
|
19760
|
-
this.deprecatedFields = config?.council?._deprecated;
|
|
19761
|
-
this.legacyMasterModel = config?.council?._legacyMasterModel;
|
|
19762
|
-
this.depthTracker = depthTracker;
|
|
19763
|
-
this.tmuxEnabled = tmuxEnabled;
|
|
19764
|
-
}
|
|
19765
|
-
getDeprecatedFields() {
|
|
19766
|
-
return this.deprecatedFields;
|
|
19767
|
-
}
|
|
19768
|
-
getLegacyMasterModel() {
|
|
19769
|
-
return this.legacyMasterModel;
|
|
19770
|
-
}
|
|
19771
|
-
async runCouncil(prompt, presetName, parentSessionId) {
|
|
19772
|
-
if (this.depthTracker) {
|
|
19773
|
-
const parentDepth = this.depthTracker.getDepth(parentSessionId);
|
|
19774
|
-
if (parentDepth + 1 > this.depthTracker.maxDepth) {
|
|
19775
|
-
log("[council-manager] spawn blocked: max depth exceeded", {
|
|
19776
|
-
parentSessionId,
|
|
19777
|
-
parentDepth,
|
|
19778
|
-
maxDepth: this.depthTracker.maxDepth
|
|
19779
|
-
});
|
|
19780
|
-
return {
|
|
19781
|
-
success: false,
|
|
19782
|
-
error: "Subagent depth exceeded",
|
|
19783
|
-
councillorResults: []
|
|
19784
|
-
};
|
|
19785
|
-
}
|
|
19786
|
-
}
|
|
19787
|
-
const councilConfig = this.config?.council;
|
|
19788
|
-
if (!councilConfig) {
|
|
19789
|
-
log("[council-manager] Council configuration not found");
|
|
19790
|
-
return {
|
|
19791
|
-
success: false,
|
|
19792
|
-
error: "Council not configured",
|
|
19793
|
-
councillorResults: []
|
|
19794
|
-
};
|
|
19795
|
-
}
|
|
19796
|
-
const resolvedPreset = presetName ?? councilConfig.default_preset ?? "default";
|
|
19797
|
-
const preset = councilConfig.presets[resolvedPreset];
|
|
19798
|
-
if (!preset) {
|
|
19799
|
-
const available = Object.keys(councilConfig.presets).join(", ");
|
|
19800
|
-
log(`[council-manager] Preset "${resolvedPreset}" not found`);
|
|
19801
|
-
return {
|
|
19802
|
-
success: false,
|
|
19803
|
-
error: `Preset "${resolvedPreset}" does not exist. Omit the preset parameter to use the default, or call again with one of: ${available}`,
|
|
19804
|
-
councillorResults: []
|
|
19805
|
-
};
|
|
19806
|
-
}
|
|
19807
|
-
if (Object.keys(preset).length === 0) {
|
|
19808
|
-
log(`[council-manager] Preset "${resolvedPreset}" has no councillors`);
|
|
19809
|
-
return {
|
|
19810
|
-
success: false,
|
|
19811
|
-
error: `Preset "${resolvedPreset}" has no councillors configured. Note: the reserved key "master" is ignored — use councillor names as keys`,
|
|
19812
|
-
councillorResults: []
|
|
19813
|
-
};
|
|
19814
|
-
}
|
|
19815
|
-
const timeout = councilConfig.timeout ?? 180000;
|
|
19816
|
-
const executionMode = councilConfig.councillor_execution_mode ?? "parallel";
|
|
19817
|
-
const maxRetries = councilConfig.councillor_retries ?? 3;
|
|
19818
|
-
const councillorCount = Object.keys(preset).length;
|
|
19819
|
-
log(`[council-manager] Starting council with preset "${resolvedPreset}"`, {
|
|
19820
|
-
councillors: Object.keys(preset)
|
|
19821
|
-
});
|
|
19822
|
-
this.sendStartNotification(parentSessionId, councillorCount).catch((err) => {
|
|
19823
|
-
log("[council-manager] Failed to send start notification", {
|
|
19824
|
-
error: err instanceof Error ? err.message : String(err)
|
|
19825
|
-
});
|
|
19826
|
-
});
|
|
19827
|
-
const councillorResults = await this.runCouncillors(prompt, preset, parentSessionId, timeout, executionMode, maxRetries);
|
|
19828
|
-
const completedCount = councillorResults.filter((r) => r.status === "completed").length;
|
|
19829
|
-
log(`[council-manager] Councillors completed: ${completedCount}/${councillorResults.length}`);
|
|
19830
|
-
if (completedCount === 0) {
|
|
19831
|
-
return {
|
|
19832
|
-
success: false,
|
|
19833
|
-
error: "All councillors failed or timed out",
|
|
19834
|
-
councillorResults
|
|
19835
|
-
};
|
|
19836
|
-
}
|
|
19837
|
-
const formattedCouncillorResults = formatCouncillorResults(prompt, councillorResults);
|
|
19838
|
-
log("[council-manager] Council completed successfully");
|
|
19839
|
-
return {
|
|
19840
|
-
success: true,
|
|
19841
|
-
result: formattedCouncillorResults,
|
|
19842
|
-
councillorResults
|
|
19843
|
-
};
|
|
19844
|
-
}
|
|
19845
|
-
async sendStartNotification(parentSessionId, councillorCount) {
|
|
19846
|
-
const message = [
|
|
19847
|
-
`⎔ Council starting — ${councillorCount} councillors launching — ctrl+x ↓ to watch`,
|
|
19848
|
-
"",
|
|
19849
|
-
"[system status: continue without acknowledging this notification]"
|
|
19850
|
-
].join(`
|
|
19851
|
-
`);
|
|
19852
|
-
await this.client.session.prompt({
|
|
19853
|
-
path: { id: parentSessionId },
|
|
19854
|
-
body: {
|
|
19855
|
-
noReply: true,
|
|
19856
|
-
parts: [{ type: "text", text: message }]
|
|
19857
|
-
}
|
|
19858
|
-
});
|
|
19859
|
-
}
|
|
19860
|
-
async runAgentSession(options) {
|
|
19861
|
-
const modelRef = parseModelReference(options.model);
|
|
19862
|
-
if (!modelRef) {
|
|
19863
|
-
throw new Error(`Invalid model format: ${options.model}`);
|
|
19864
|
-
}
|
|
19865
|
-
let sessionId;
|
|
19866
|
-
try {
|
|
19867
|
-
const session = await this.client.session.create({
|
|
19868
|
-
body: {
|
|
19869
|
-
parentID: options.parentSessionId,
|
|
19870
|
-
title: options.title
|
|
19871
|
-
},
|
|
19872
|
-
query: { directory: this.directory }
|
|
19873
|
-
});
|
|
19874
|
-
if (!session.data?.id) {
|
|
19875
|
-
throw new Error("Failed to create session");
|
|
19876
|
-
}
|
|
19877
|
-
sessionId = session.data.id;
|
|
19878
|
-
if (this.depthTracker) {
|
|
19879
|
-
const registered = this.depthTracker.registerChild(options.parentSessionId, sessionId);
|
|
19880
|
-
if (!registered) {
|
|
19881
|
-
throw new Error("Subagent depth exceeded");
|
|
19882
|
-
}
|
|
19883
|
-
}
|
|
19884
|
-
if (this.tmuxEnabled) {
|
|
19885
|
-
await new Promise((r) => setTimeout(r, TMUX_SPAWN_DELAY_MS));
|
|
19886
|
-
}
|
|
19887
|
-
const body = {
|
|
19888
|
-
agent: options.agent,
|
|
19889
|
-
model: modelRef,
|
|
19890
|
-
tools: { task: false },
|
|
19891
|
-
parts: [{ type: "text", text: options.promptText }]
|
|
19892
|
-
};
|
|
19893
|
-
if (options.variant) {
|
|
19894
|
-
body.variant = options.variant;
|
|
19895
|
-
}
|
|
19896
|
-
await promptWithTimeout(this.client, {
|
|
19897
|
-
path: { id: sessionId },
|
|
19898
|
-
body,
|
|
19899
|
-
query: { directory: this.directory }
|
|
19900
|
-
}, options.timeout);
|
|
19901
|
-
const extraction = await extractSessionResult(this.client, sessionId, {
|
|
19902
|
-
includeReasoning: options.includeReasoning
|
|
19903
|
-
});
|
|
19904
|
-
if (extraction.empty) {
|
|
19905
|
-
const retryOnEmpty = this.config?.fallback?.retry_on_empty ?? true;
|
|
19906
|
-
if (retryOnEmpty) {
|
|
19907
|
-
throw new Error("Empty response from provider");
|
|
19908
|
-
}
|
|
19909
|
-
}
|
|
19910
|
-
return extraction.text;
|
|
19911
|
-
} finally {
|
|
19912
|
-
if (sessionId) {
|
|
19913
|
-
this.client.session.abort({ path: { id: sessionId } }).catch(() => {});
|
|
19914
|
-
if (this.depthTracker) {
|
|
19915
|
-
this.depthTracker.cleanup(sessionId);
|
|
19916
|
-
}
|
|
19917
|
-
}
|
|
19918
|
-
}
|
|
19919
|
-
}
|
|
19920
|
-
async runCouncillors(prompt, councillors, parentSessionId, timeout, executionMode = "parallel", maxRetries) {
|
|
19921
|
-
const entries = Object.entries(councillors);
|
|
19922
|
-
const results = [];
|
|
19923
|
-
if (executionMode === "serial") {
|
|
19924
|
-
for (const [name, config] of entries) {
|
|
19925
|
-
results.push(await this.runCouncillorWithRetry(name, config, prompt, parentSessionId, timeout, maxRetries));
|
|
19926
|
-
}
|
|
19927
|
-
} else {
|
|
19928
|
-
const promises = entries.map(([name, config], index) => (async () => {
|
|
19929
|
-
if (this.tmuxEnabled && index > 0) {
|
|
19930
|
-
await new Promise((r) => setTimeout(r, index * COUNCILLOR_STAGGER_MS));
|
|
19931
|
-
}
|
|
19932
|
-
return this.runCouncillorWithRetry(name, config, prompt, parentSessionId, timeout, maxRetries);
|
|
19933
|
-
})());
|
|
19934
|
-
const settled = await Promise.allSettled(promises);
|
|
19935
|
-
for (let index = 0;index < settled.length; index++) {
|
|
19936
|
-
const result = settled[index];
|
|
19937
|
-
const [name, cfg] = entries[index];
|
|
19938
|
-
if (result.status === "fulfilled") {
|
|
19939
|
-
results.push(result.value);
|
|
19940
|
-
} else {
|
|
19941
|
-
results.push({
|
|
19942
|
-
name,
|
|
19943
|
-
model: cfg.model,
|
|
19944
|
-
status: "failed",
|
|
19945
|
-
error: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
19946
|
-
});
|
|
19947
|
-
}
|
|
19948
|
-
}
|
|
19949
|
-
}
|
|
19950
|
-
return results;
|
|
19951
|
-
}
|
|
19952
|
-
async runCouncillorWithRetry(name, config, prompt, parentSessionId, timeout, maxRetries) {
|
|
19953
|
-
const modelLabel = shortModelLabel(config.model);
|
|
19954
|
-
const totalAttempts = 1 + maxRetries;
|
|
19955
|
-
for (let attempt = 1;attempt <= totalAttempts; attempt++) {
|
|
19956
|
-
if (attempt > 1) {
|
|
19957
|
-
log(`[council-manager] Retrying councillor "${name}" (${modelLabel}), attempt ${attempt}/${totalAttempts}`);
|
|
19958
|
-
}
|
|
19959
|
-
try {
|
|
19960
|
-
const result = await this.runAgentSession({
|
|
19961
|
-
parentSessionId,
|
|
19962
|
-
title: `Council ${name} (${modelLabel})`,
|
|
19963
|
-
agent: "councillor",
|
|
19964
|
-
model: config.model,
|
|
19965
|
-
promptText: formatCouncillorPrompt(prompt, config.prompt),
|
|
19966
|
-
variant: config.variant,
|
|
19967
|
-
timeout,
|
|
19968
|
-
includeReasoning: false
|
|
19969
|
-
});
|
|
19970
|
-
return {
|
|
19971
|
-
name,
|
|
19972
|
-
model: config.model,
|
|
19973
|
-
status: "completed",
|
|
19974
|
-
result
|
|
19975
|
-
};
|
|
19976
|
-
} catch (error) {
|
|
19977
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
19978
|
-
const isEmptyResponse = msg.includes("Empty response from provider");
|
|
19979
|
-
const canRetry = attempt < totalAttempts && isEmptyResponse;
|
|
19980
|
-
if (!canRetry) {
|
|
19981
|
-
return {
|
|
19982
|
-
name,
|
|
19983
|
-
model: config.model,
|
|
19984
|
-
status: msg.includes("timed out") ? "timed_out" : "failed",
|
|
19985
|
-
error: `Councillor "${name}": ${msg}`
|
|
19986
|
-
};
|
|
19987
|
-
}
|
|
19988
|
-
}
|
|
19989
|
-
}
|
|
19990
|
-
return {
|
|
19991
|
-
name,
|
|
19992
|
-
model: config.model,
|
|
19993
|
-
status: "failed",
|
|
19994
|
-
error: `Councillor "${name}": max retries exhausted`
|
|
19995
|
-
};
|
|
19996
|
-
}
|
|
19997
|
-
}
|
|
19998
19234
|
// src/divoom/manager.ts
|
|
19999
|
-
import { spawn } from "node:child_process";
|
|
20000
|
-
import { existsSync as existsSync2, mkdirSync as mkdirSync2 } from "node:fs";
|
|
20001
|
-
import * as os2 from "node:os";
|
|
20002
|
-
import path3 from "node:path";
|
|
20003
|
-
import { fileURLToPath } from "node:url";
|
|
20004
19235
|
var AGENT_GIFS = {
|
|
20005
19236
|
council: "council.gif",
|
|
20006
19237
|
councillor: "council.gif",
|
|
@@ -22319,6 +21550,45 @@ function hasInternalInitiatorMarker(part) {
|
|
|
22319
21550
|
}
|
|
22320
21551
|
return part.text.includes(SLIM_INTERNAL_INITIATOR_MARKER);
|
|
22321
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
|
+
}
|
|
22322
21592
|
// src/utils/session-manager.ts
|
|
22323
21593
|
var MIN_CONTEXT_FILE_LINES = 10;
|
|
22324
21594
|
var MAX_CONTEXT_FILES_PER_SESSION = 8;
|
|
@@ -22326,14 +21596,6 @@ function aliasPrefix(agentType) {
|
|
|
22326
21596
|
switch (agentType) {
|
|
22327
21597
|
case "researcher":
|
|
22328
21598
|
return "res";
|
|
22329
|
-
case "reviewer":
|
|
22330
|
-
return "rev";
|
|
22331
|
-
case "implementer":
|
|
22332
|
-
return "imp";
|
|
22333
|
-
case "council":
|
|
22334
|
-
return "cnc";
|
|
22335
|
-
case "councillor":
|
|
22336
|
-
return "clr";
|
|
22337
21599
|
case "orchestrator":
|
|
22338
21600
|
return "orc";
|
|
22339
21601
|
}
|
|
@@ -23493,11 +22755,7 @@ ${originalText}`;
|
|
|
23493
22755
|
import path9 from "node:path";
|
|
23494
22756
|
var AGENT_NAME_SET = new Set([
|
|
23495
22757
|
"orchestrator",
|
|
23496
|
-
"researcher"
|
|
23497
|
-
"reviewer",
|
|
23498
|
-
"implementer",
|
|
23499
|
-
"council",
|
|
23500
|
-
"councillor"
|
|
22758
|
+
"researcher"
|
|
23501
22759
|
]);
|
|
23502
22760
|
var MAX_PENDING_TASK_CALLS = 100;
|
|
23503
22761
|
var RESUMABLE_SESSIONS_START = "<resumable_sessions>";
|
|
@@ -27264,17 +26522,17 @@ import * as fs8 from "node:fs/promises";
|
|
|
27264
26522
|
import * as path12 from "node:path";
|
|
27265
26523
|
|
|
27266
26524
|
// src/interview/types.ts
|
|
27267
|
-
import { z as
|
|
27268
|
-
var RawQuestionSchema =
|
|
27269
|
-
id:
|
|
27270
|
-
question:
|
|
27271
|
-
options:
|
|
27272
|
-
suggested:
|
|
26525
|
+
import { z as z2 } from "zod";
|
|
26526
|
+
var RawQuestionSchema = z2.object({
|
|
26527
|
+
id: z2.string().optional(),
|
|
26528
|
+
question: z2.string().optional(),
|
|
26529
|
+
options: z2.array(z2.unknown()).optional(),
|
|
26530
|
+
suggested: z2.unknown().optional()
|
|
27273
26531
|
});
|
|
27274
|
-
var RawInterviewStateSchema =
|
|
27275
|
-
summary:
|
|
27276
|
-
title:
|
|
27277
|
-
questions:
|
|
26532
|
+
var RawInterviewStateSchema = z2.object({
|
|
26533
|
+
summary: z2.unknown().optional(),
|
|
26534
|
+
title: z2.unknown().optional(),
|
|
26535
|
+
questions: z2.array(z2.unknown()).optional()
|
|
27278
26536
|
});
|
|
27279
26537
|
|
|
27280
26538
|
// src/interview/parser.ts
|
|
@@ -29763,72 +29021,6 @@ var ast_grep_replace = tool2({
|
|
|
29763
29021
|
}
|
|
29764
29022
|
}
|
|
29765
29023
|
});
|
|
29766
|
-
// src/tools/council.ts
|
|
29767
|
-
import {
|
|
29768
|
-
tool as tool3
|
|
29769
|
-
} from "@opencode-ai/plugin";
|
|
29770
|
-
var z4 = tool3.schema;
|
|
29771
|
-
function formatModelComposition(councillorResults) {
|
|
29772
|
-
return councillorResults.map((cr) => {
|
|
29773
|
-
const shortModel = shortModelLabel(cr.model);
|
|
29774
|
-
return `${cr.name}: ${shortModel}`;
|
|
29775
|
-
}).join(", ");
|
|
29776
|
-
}
|
|
29777
|
-
function createCouncilTool(_ctx, councilManager) {
|
|
29778
|
-
const council_session = tool3({
|
|
29779
|
-
description: `Launch a multi-LLM council session for consensus-based analysis.
|
|
29780
|
-
|
|
29781
|
-
Sends the prompt to multiple models (councillors) in parallel and returns their formatted responses for you to synthesize.
|
|
29782
|
-
|
|
29783
|
-
Returns the councillor responses with a summary footer.`,
|
|
29784
|
-
args: {
|
|
29785
|
-
prompt: z4.string().describe("The prompt to send to all councillors"),
|
|
29786
|
-
preset: z4.string().optional().describe('Council preset to use (default: "default"). Must match a preset in the council config.')
|
|
29787
|
-
},
|
|
29788
|
-
async execute(args, toolContext) {
|
|
29789
|
-
if (!toolContext || typeof toolContext !== "object" || !("sessionID" in toolContext)) {
|
|
29790
|
-
throw new Error("Invalid toolContext: missing sessionID");
|
|
29791
|
-
}
|
|
29792
|
-
const allowedAgents = ["council"];
|
|
29793
|
-
const callingAgent = toolContext.agent;
|
|
29794
|
-
if (callingAgent && !allowedAgents.includes(callingAgent)) {
|
|
29795
|
-
throw new Error(`Council sessions can only be invoked by the council agent. Current agent: ${callingAgent}`);
|
|
29796
|
-
}
|
|
29797
|
-
const prompt = String(args.prompt);
|
|
29798
|
-
const preset = typeof args.preset === "string" ? args.preset : undefined;
|
|
29799
|
-
const parentSessionId = toolContext.sessionID;
|
|
29800
|
-
const result = await councilManager.runCouncil(prompt, preset, parentSessionId);
|
|
29801
|
-
if (!result.success) {
|
|
29802
|
-
return `Council session failed: ${result.error}`;
|
|
29803
|
-
}
|
|
29804
|
-
let output = result.result ?? "(No output)";
|
|
29805
|
-
const completed = result.councillorResults.filter((cr) => cr.status === "completed").length;
|
|
29806
|
-
const total = result.councillorResults.length;
|
|
29807
|
-
const composition = formatModelComposition(result.councillorResults);
|
|
29808
|
-
output += `
|
|
29809
|
-
|
|
29810
|
-
---
|
|
29811
|
-
*Council: ${completed}/${total} councillors responded (${composition})*`;
|
|
29812
|
-
const deprecated = councilManager.getDeprecatedFields();
|
|
29813
|
-
if (deprecated && deprecated.length > 0) {
|
|
29814
|
-
const legacyMasterModel = councilManager.getLegacyMasterModel();
|
|
29815
|
-
const hasMaster = deprecated.includes("master");
|
|
29816
|
-
const trulyIgnored = hasMaster && !legacyMasterModel ? deprecated : deprecated.filter((f) => f !== "master");
|
|
29817
|
-
const parts = [];
|
|
29818
|
-
if (hasMaster && legacyMasterModel) {
|
|
29819
|
-
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.`);
|
|
29820
|
-
}
|
|
29821
|
-
if (trulyIgnored.length > 0) {
|
|
29822
|
-
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.`);
|
|
29823
|
-
}
|
|
29824
|
-
output += `
|
|
29825
|
-
⚠ Config warning: ${parts.join(" ")}`;
|
|
29826
|
-
}
|
|
29827
|
-
return output;
|
|
29828
|
-
}
|
|
29829
|
-
});
|
|
29830
|
-
return { council_session };
|
|
29831
|
-
}
|
|
29832
29024
|
// src/tui-state.ts
|
|
29833
29025
|
import * as fs9 from "node:fs";
|
|
29834
29026
|
import * as os5 from "node:os";
|
|
@@ -30064,13 +29256,19 @@ Usage: /preset <name> to switch.`);
|
|
|
30064
29256
|
// src/tools/skill.ts
|
|
30065
29257
|
import { existsSync as existsSync10, readFileSync as readFileSync5 } from "node:fs";
|
|
30066
29258
|
import { join as join13 } from "node:path";
|
|
30067
|
-
import { tool as
|
|
30068
|
-
var
|
|
29259
|
+
import { tool as tool3 } from "@opencode-ai/plugin/tool";
|
|
29260
|
+
var z3 = tool3.schema;
|
|
30069
29261
|
function resolveSkillPath(skillName) {
|
|
30070
|
-
|
|
30071
|
-
|
|
30072
|
-
|
|
30073
|
-
|
|
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;
|
|
30074
29272
|
}
|
|
30075
29273
|
return;
|
|
30076
29274
|
}
|
|
@@ -30084,14 +29282,14 @@ function isSkillAllowedForAgent(agentName, skillName, config) {
|
|
|
30084
29282
|
return permissions["*"] === "allow";
|
|
30085
29283
|
}
|
|
30086
29284
|
function createSkillTool(config) {
|
|
30087
|
-
const skill =
|
|
29285
|
+
const skill = tool3({
|
|
30088
29286
|
description: `Load a Skill behavior guide by name.
|
|
30089
29287
|
|
|
30090
29288
|
Returns the full SKILL.md content so you can follow its workflow.
|
|
30091
29289
|
Skills are temporary behavior overlays — they apply to the current turn only
|
|
30092
29290
|
and do not permanently modify your system prompt.`,
|
|
30093
29291
|
args: {
|
|
30094
|
-
name:
|
|
29292
|
+
name: z3.string().describe('Skill name (e.g. "brainstorming", "simplify", "codemap").')
|
|
30095
29293
|
},
|
|
30096
29294
|
execute: async (args, toolContext) => {
|
|
30097
29295
|
const skillName = args.name.trim();
|
|
@@ -30147,7 +29345,7 @@ var WEBFETCH_DESCRIPTION = "Fetch a URL with better extraction for static/docs p
|
|
|
30147
29345
|
import os6 from "node:os";
|
|
30148
29346
|
import path18 from "node:path";
|
|
30149
29347
|
import {
|
|
30150
|
-
tool as
|
|
29348
|
+
tool as tool4
|
|
30151
29349
|
} from "@opencode-ai/plugin";
|
|
30152
29350
|
|
|
30153
29351
|
// src/tools/smartfetch/binary.ts
|
|
@@ -30315,7 +29513,7 @@ var M = class u2 {
|
|
|
30315
29513
|
return this.#S;
|
|
30316
29514
|
}
|
|
30317
29515
|
constructor(e) {
|
|
30318
|
-
let { max: t = 0, ttl: i, ttlResolution: s = 1, ttlAutopurge: n, updateAgeOnGet: o, updateAgeOnHas: r, allowStale: h, dispose: l, onInsert: c, disposeAfter: f, noDisposeOnSet: g, noUpdateTTL: p, maxSize: T = 0, maxEntrySize: w = 0, sizeCalculation: y, fetchMethod: a, memoMethod: m, noDeleteOnFetchRejection: _, noDeleteOnStaleGet: b, allowStaleOnFetchRejection: d, allowStaleOnFetchAbort: A, ignoreFetchAbort:
|
|
29516
|
+
let { max: t = 0, ttl: i, ttlResolution: s = 1, ttlAutopurge: n, updateAgeOnGet: o, updateAgeOnHas: r, allowStale: h, dispose: l, onInsert: c, disposeAfter: f, noDisposeOnSet: g, noUpdateTTL: p, maxSize: T = 0, maxEntrySize: w = 0, sizeCalculation: y, fetchMethod: a, memoMethod: m, noDeleteOnFetchRejection: _, noDeleteOnStaleGet: b, allowStaleOnFetchRejection: d, allowStaleOnFetchAbort: A, ignoreFetchAbort: z4, perf: x } = e;
|
|
30319
29517
|
if (x !== undefined && typeof x?.now != "function")
|
|
30320
29518
|
throw new TypeError("perf option must have a now() method if specified");
|
|
30321
29519
|
if (this.#m = x ?? C, t !== 0 && !F(t))
|
|
@@ -30333,7 +29531,7 @@ var M = class u2 {
|
|
|
30333
29531
|
throw new TypeError("memoMethod must be a function if defined");
|
|
30334
29532
|
if (this.#U = m, a !== undefined && typeof a != "function")
|
|
30335
29533
|
throw new TypeError("fetchMethod must be a function if specified");
|
|
30336
|
-
if (this.#M = a, this.#W = !!a, this.#s = new Map, this.#i = Array.from({ length: t }).fill(undefined), this.#t = Array.from({ length: t }).fill(undefined), this.#a = new v(t), this.#c = new v(t), this.#l = 0, this.#h = 0, this.#y = R.create(t), this.#n = 0, this.#b = 0, typeof l == "function" && (this.#w = l), typeof c == "function" && (this.#x = c), typeof f == "function" ? (this.#S = f, this.#r = []) : (this.#S = undefined, this.#r = undefined), this.#T = !!this.#w, this.#j = !!this.#x, this.#f = !!this.#S, this.noDisposeOnSet = !!g, this.noUpdateTTL = !!p, this.noDeleteOnFetchRejection = !!_, this.allowStaleOnFetchRejection = !!d, this.allowStaleOnFetchAbort = !!A, this.ignoreFetchAbort = !!
|
|
29534
|
+
if (this.#M = a, this.#W = !!a, this.#s = new Map, this.#i = Array.from({ length: t }).fill(undefined), this.#t = Array.from({ length: t }).fill(undefined), this.#a = new v(t), this.#c = new v(t), this.#l = 0, this.#h = 0, this.#y = R.create(t), this.#n = 0, this.#b = 0, typeof l == "function" && (this.#w = l), typeof c == "function" && (this.#x = c), typeof f == "function" ? (this.#S = f, this.#r = []) : (this.#S = undefined, this.#r = undefined), this.#T = !!this.#w, this.#j = !!this.#x, this.#f = !!this.#S, this.noDisposeOnSet = !!g, this.noUpdateTTL = !!p, this.noDeleteOnFetchRejection = !!_, this.allowStaleOnFetchRejection = !!d, this.allowStaleOnFetchAbort = !!A, this.ignoreFetchAbort = !!z4, this.maxEntrySize !== 0) {
|
|
30337
29535
|
if (this.#u !== 0 && !F(this.#u))
|
|
30338
29536
|
throw new TypeError("maxSize must be a positive integer if specified");
|
|
30339
29537
|
if (!F(this.maxEntrySize))
|
|
@@ -30713,8 +29911,8 @@ var M = class u2 {
|
|
|
30713
29911
|
let A = this.#p(b);
|
|
30714
29912
|
if (!y && !A)
|
|
30715
29913
|
return a && (a.fetch = "hit"), this.#L(b), s && this.#D(b), a && this.#E(a, b), d;
|
|
30716
|
-
let
|
|
30717
|
-
return a && (a.fetch = A ? "stale" : "refresh", v && A && (a.returnedStale = true)), v ?
|
|
29914
|
+
let z4 = this.#P(e, b, _, w), v = z4.__staleWhileFetching !== undefined && i;
|
|
29915
|
+
return a && (a.fetch = A ? "stale" : "refresh", v && A && (a.returnedStale = true)), v ? z4.__staleWhileFetching : z4.__returned = z4;
|
|
30718
29916
|
}
|
|
30719
29917
|
}
|
|
30720
29918
|
forceFetch(e, t = {}) {
|
|
@@ -31929,20 +31127,20 @@ async function runSecondaryModelWithFallback(client, directory, models, prompt,
|
|
|
31929
31127
|
}
|
|
31930
31128
|
|
|
31931
31129
|
// src/tools/smartfetch/tool.ts
|
|
31932
|
-
var
|
|
31130
|
+
var z4 = tool4.schema;
|
|
31933
31131
|
function createWebfetchTool(pluginCtx, options = {}) {
|
|
31934
31132
|
const binaryDir = options.binaryDir || path18.join(os6.tmpdir(), "opencode-smartfetch");
|
|
31935
|
-
return
|
|
31133
|
+
return tool4({
|
|
31936
31134
|
description: WEBFETCH_DESCRIPTION,
|
|
31937
31135
|
args: {
|
|
31938
|
-
url:
|
|
31939
|
-
format:
|
|
31940
|
-
timeout:
|
|
31941
|
-
prompt:
|
|
31942
|
-
extract_main:
|
|
31943
|
-
prefer_llms_txt:
|
|
31944
|
-
include_metadata:
|
|
31945
|
-
save_binary:
|
|
31136
|
+
url: z4.httpUrl(),
|
|
31137
|
+
format: z4.enum(["text", "markdown", "html"]).default("markdown"),
|
|
31138
|
+
timeout: z4.number().positive().max(MAX_TIMEOUT_SECONDS).optional().describe("Timeout in seconds, max 120."),
|
|
31139
|
+
prompt: z4.string().optional().describe("Optional extraction task to run on the fetched content using a cheap secondary model."),
|
|
31140
|
+
extract_main: z4.boolean().default(true),
|
|
31141
|
+
prefer_llms_txt: z4.enum(["auto", "always", "never"]).default("auto"),
|
|
31142
|
+
include_metadata: z4.boolean().default(true),
|
|
31143
|
+
save_binary: z4.boolean().default(false).describe("Save binary payload to disk when it fits within the active download limit.")
|
|
31946
31144
|
},
|
|
31947
31145
|
async execute(args, ctx) {
|
|
31948
31146
|
const secondaryModels = await readSecondaryModelFromConfig(ctx.directory || pluginCtx.directory);
|
|
@@ -32486,7 +31684,7 @@ async function appLog(ctx, level, message) {
|
|
|
32486
31684
|
}
|
|
32487
31685
|
}
|
|
32488
31686
|
var HEALTH_CHECK = {
|
|
32489
|
-
minAgents:
|
|
31687
|
+
minAgents: 2,
|
|
32490
31688
|
minTools: 5,
|
|
32491
31689
|
minMcps: 1
|
|
32492
31690
|
};
|
|
@@ -32592,7 +31790,7 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
32592
31790
|
startAvailabilityCheck(multiplexerConfig);
|
|
32593
31791
|
}
|
|
32594
31792
|
depthTracker = new SubagentDepthTracker;
|
|
32595
|
-
councilTools =
|
|
31793
|
+
councilTools = {};
|
|
32596
31794
|
mcps = createBuiltinMcps(config.disabled_mcps, config.websearch);
|
|
32597
31795
|
webfetch = createWebfetchTool(ctx);
|
|
32598
31796
|
skillTools = createSkillTool(config);
|
|
@@ -32627,7 +31825,7 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
32627
31825
|
interviewManager = createInterviewManager(ctx, config);
|
|
32628
31826
|
presetManager = createPresetManager(ctx, config);
|
|
32629
31827
|
divoomManager = createDivoomManager(config.divoom);
|
|
32630
|
-
toolCount = Object.keys(
|
|
31828
|
+
toolCount = Object.keys(todoContinuationHook.tool).length + 1 + 1 + 2;
|
|
32631
31829
|
} catch (err) {
|
|
32632
31830
|
log("[plugin] FATAL: init failed", String(err));
|
|
32633
31831
|
await appLog(ctx, "error", `INIT FAILED: ${String(err)}. Report at cnb.cool/zcyoop/ai-assistant/agent-forge/issues/310`);
|
|
@@ -32821,8 +32019,6 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
32821
32019
|
}
|
|
32822
32020
|
const tuiAgentModels = {};
|
|
32823
32021
|
for (const agentDef of agentDefs) {
|
|
32824
|
-
if (agentDef.name === "councillor")
|
|
32825
|
-
continue;
|
|
32826
32022
|
const entry = configAgent[agentDef.name];
|
|
32827
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;
|
|
32828
32024
|
tuiAgentModels[agentDef.name] = resolvedModel ?? "default";
|