oh-my-opencode-serverlocal 0.1.2 → 0.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/cli/index.js +94 -186
- package/dist/config/constants.d.ts +2 -2
- package/dist/config/index.d.ts +0 -1
- package/dist/config/schema.d.ts +0 -41
- package/dist/index.js +546 -1268
- package/dist/tools/index.d.ts +0 -1
- package/dist/tui.js +94 -194
- package/dist/utils/session.d.ts +1 -1
- package/dist/utils/subagent-depth.d.ts +2 -2
- package/package.json +1 -1
- package/dist/agents/council.d.ts +0 -27
- package/dist/agents/councillor.d.ts +0 -2
- package/dist/config/council-schema.d.ts +0 -137
- package/dist/council/council-manager.d.ts +0 -53
- package/dist/council/index.d.ts +0 -1
- package/dist/tools/council.d.ts +0 -10
- package/dist/utils/councillor-models.d.ts +0 -20
package/dist/index.js
CHANGED
|
@@ -18476,12 +18476,10 @@ var SUBAGENT_NAMES = [
|
|
|
18476
18476
|
"oracle",
|
|
18477
18477
|
"designer",
|
|
18478
18478
|
"fixer",
|
|
18479
|
-
"observer"
|
|
18480
|
-
"council",
|
|
18481
|
-
"councillor"
|
|
18479
|
+
"observer"
|
|
18482
18480
|
];
|
|
18483
18481
|
var ALL_AGENT_NAMES = ["orchestrator", ...SUBAGENT_NAMES];
|
|
18484
|
-
var PROTECTED_AGENTS = new Set(["orchestrator"
|
|
18482
|
+
var PROTECTED_AGENTS = new Set(["orchestrator"]);
|
|
18485
18483
|
var DEFAULT_MODELS = {
|
|
18486
18484
|
orchestrator: undefined,
|
|
18487
18485
|
oracle: undefined,
|
|
@@ -18489,9 +18487,7 @@ var DEFAULT_MODELS = {
|
|
|
18489
18487
|
explorer: undefined,
|
|
18490
18488
|
designer: undefined,
|
|
18491
18489
|
fixer: undefined,
|
|
18492
|
-
observer: undefined
|
|
18493
|
-
council: undefined,
|
|
18494
|
-
councillor: undefined
|
|
18490
|
+
observer: undefined
|
|
18495
18491
|
};
|
|
18496
18492
|
var POLL_INTERVAL_BACKGROUND_MS = 2000;
|
|
18497
18493
|
var MAX_POLL_TIME_MS = 5 * 60 * 1000;
|
|
@@ -18514,12 +18510,6 @@ var READONLY_FILE_OPERATIONS_RULES = `**File Operations Rules**:
|
|
|
18514
18510
|
- Prefer dedicated file tools for codebase inspection: glob/grep/ast_grep_search for discovery and read for file contents.
|
|
18515
18511
|
- Bash is allowed for non-mutating diagnostics and shell-native inspection when it is the clearest tool, but not for modifying files.
|
|
18516
18512
|
- Do not use cat/head/tail/sed/awk only to read code into context; use read/grep unless a shell pipeline is genuinely the better diagnostic.`;
|
|
18517
|
-
var NO_SHELL_READONLY_FILE_OPERATIONS_RULES = `**File Operations Rules**:
|
|
18518
|
-
- READ-ONLY: inspect and report; do not modify files.
|
|
18519
|
-
- Use glob/grep/ast_grep_search for discovery and read for file contents.
|
|
18520
|
-
- Do not use bash or shell commands.`;
|
|
18521
|
-
var TMUX_SPAWN_DELAY_MS = 500;
|
|
18522
|
-
var COUNCILLOR_STAGGER_MS = 250;
|
|
18523
18513
|
var DEFAULT_DISABLED_AGENTS = ["observer"];
|
|
18524
18514
|
var DEFAULT_MAX_SESSIONS_PER_AGENT = 2;
|
|
18525
18515
|
var DEFAULT_READ_CONTEXT_MIN_LINES = 10;
|
|
@@ -18528,92 +18518,6 @@ var DEFAULT_IMAGE_ROUTING = "auto";
|
|
|
18528
18518
|
function resolveImageRouting(imageRouting) {
|
|
18529
18519
|
return imageRouting ?? DEFAULT_IMAGE_ROUTING;
|
|
18530
18520
|
}
|
|
18531
|
-
// src/config/council-schema.ts
|
|
18532
|
-
import { z } from "zod";
|
|
18533
|
-
|
|
18534
|
-
// src/utils/councillor-models.ts
|
|
18535
|
-
function normalizeCouncillorModels(model, fallbackVariant) {
|
|
18536
|
-
const raw = Array.isArray(model) ? model : [model];
|
|
18537
|
-
return raw.map((entry) => typeof entry === "string" ? { id: entry, variant: fallbackVariant } : { id: entry.id, variant: entry.variant ?? fallbackVariant });
|
|
18538
|
-
}
|
|
18539
|
-
|
|
18540
|
-
// src/config/council-schema.ts
|
|
18541
|
-
var ModelIdSchema = z.string().regex(/^[^/\s]+\/[^\s]+$/, 'Expected provider/model format (e.g. "openai/gpt-5.6-luna")');
|
|
18542
|
-
var CouncillorModelEntrySchema = z.object({
|
|
18543
|
-
id: ModelIdSchema,
|
|
18544
|
-
variant: z.string().optional()
|
|
18545
|
-
});
|
|
18546
|
-
var CouncillorModelSchema = z.union([
|
|
18547
|
-
ModelIdSchema,
|
|
18548
|
-
z.array(z.union([ModelIdSchema, CouncillorModelEntrySchema])).min(1)
|
|
18549
|
-
]).describe('Model ID in provider/model format (e.g. "openai/gpt-5.6-luna"), or an ' + "ordered fallback chain (array of model IDs or { id, variant } entries) " + "tried in order until one responds.");
|
|
18550
|
-
var CouncillorConfigSchema = z.object({
|
|
18551
|
-
model: CouncillorModelSchema,
|
|
18552
|
-
variant: z.string().optional(),
|
|
18553
|
-
prompt: z.string().optional().describe("Optional role/guidance injected into the councillor user prompt")
|
|
18554
|
-
}).transform((c) => {
|
|
18555
|
-
const models = normalizeCouncillorModels(c.model, c.variant);
|
|
18556
|
-
return {
|
|
18557
|
-
model: models[0].id,
|
|
18558
|
-
variant: c.variant,
|
|
18559
|
-
prompt: c.prompt,
|
|
18560
|
-
models
|
|
18561
|
-
};
|
|
18562
|
-
});
|
|
18563
|
-
var CouncilPresetSchema = z.record(z.string(), z.record(z.string(), z.unknown())).transform((entries, ctx) => {
|
|
18564
|
-
const councillors = {};
|
|
18565
|
-
for (const [key, raw] of Object.entries(entries)) {
|
|
18566
|
-
if (key === "master")
|
|
18567
|
-
continue;
|
|
18568
|
-
if (key === "councillors" && typeof raw === "object" && raw !== null) {
|
|
18569
|
-
for (const [innerKey, innerRaw] of Object.entries(raw)) {
|
|
18570
|
-
const innerParsed = CouncillorConfigSchema.safeParse(innerRaw);
|
|
18571
|
-
if (!innerParsed.success) {
|
|
18572
|
-
ctx.addIssue({
|
|
18573
|
-
code: z.ZodIssueCode.custom,
|
|
18574
|
-
message: `Invalid councillor "${innerKey}" (nested under legacy "councillors" key): ${innerParsed.error.issues.map((i) => i.message).join(", ")}`
|
|
18575
|
-
});
|
|
18576
|
-
return z.NEVER;
|
|
18577
|
-
}
|
|
18578
|
-
councillors[innerKey] = innerParsed.data;
|
|
18579
|
-
}
|
|
18580
|
-
continue;
|
|
18581
|
-
}
|
|
18582
|
-
const parsed = CouncillorConfigSchema.safeParse(raw);
|
|
18583
|
-
if (!parsed.success) {
|
|
18584
|
-
ctx.addIssue({
|
|
18585
|
-
code: z.ZodIssueCode.custom,
|
|
18586
|
-
message: `Invalid councillor "${key}": ${parsed.error.issues.map((i) => i.message).join(", ")}`
|
|
18587
|
-
});
|
|
18588
|
-
return z.NEVER;
|
|
18589
|
-
}
|
|
18590
|
-
councillors[key] = parsed.data;
|
|
18591
|
-
}
|
|
18592
|
-
return councillors;
|
|
18593
|
-
});
|
|
18594
|
-
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.');
|
|
18595
|
-
var CouncilConfigSchema = z.object({
|
|
18596
|
-
presets: z.record(z.string(), CouncilPresetSchema),
|
|
18597
|
-
timeout: z.number().min(0).default(180000),
|
|
18598
|
-
default_preset: z.string().default("default"),
|
|
18599
|
-
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).'),
|
|
18600
|
-
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."),
|
|
18601
|
-
master: z.unknown().optional().describe("DEPRECATED - ignored. Council agent synthesizes directly.")
|
|
18602
|
-
}).transform((data) => {
|
|
18603
|
-
const deprecated = [];
|
|
18604
|
-
if (data.master !== undefined)
|
|
18605
|
-
deprecated.push("master");
|
|
18606
|
-
const legacyMasterModel = typeof data.master === "object" && data.master !== null && "model" in data.master && typeof data.master.model === "string" ? data.master.model : undefined;
|
|
18607
|
-
return {
|
|
18608
|
-
presets: data.presets,
|
|
18609
|
-
timeout: data.timeout,
|
|
18610
|
-
default_preset: data.default_preset,
|
|
18611
|
-
councillor_execution_mode: data.councillor_execution_mode,
|
|
18612
|
-
councillor_retries: data.councillor_retries,
|
|
18613
|
-
_deprecated: deprecated.length > 0 ? deprecated : undefined,
|
|
18614
|
-
_legacyMasterModel: legacyMasterModel
|
|
18615
|
-
};
|
|
18616
|
-
});
|
|
18617
18521
|
// src/config/loader.ts
|
|
18618
18522
|
import * as fs from "node:fs";
|
|
18619
18523
|
import * as path from "node:path";
|
|
@@ -18629,9 +18533,7 @@ var DEFAULT_AGENT_MCPS = {
|
|
|
18629
18533
|
librarian: ["websearch", "context7", "gh_grep"],
|
|
18630
18534
|
explorer: [],
|
|
18631
18535
|
fixer: [],
|
|
18632
|
-
observer: []
|
|
18633
|
-
council: [],
|
|
18634
|
-
councillor: []
|
|
18536
|
+
observer: []
|
|
18635
18537
|
};
|
|
18636
18538
|
function parseList(items, allAvailable) {
|
|
18637
18539
|
if (!items || items.length === 0) {
|
|
@@ -18664,9 +18566,9 @@ function stripJsonComments(json) {
|
|
|
18664
18566
|
}
|
|
18665
18567
|
|
|
18666
18568
|
// src/config/schema.ts
|
|
18667
|
-
import { z
|
|
18668
|
-
var ProviderModelIdSchema =
|
|
18669
|
-
var ManualAgentPlanSchema =
|
|
18569
|
+
import { z } from "zod";
|
|
18570
|
+
var ProviderModelIdSchema = z.string().regex(/^[^/\s]+\/[^\s]+$/, "Expected provider/model format (provider/.../model)");
|
|
18571
|
+
var ManualAgentPlanSchema = z.object({
|
|
18670
18572
|
primary: ProviderModelIdSchema,
|
|
18671
18573
|
fallback1: ProviderModelIdSchema,
|
|
18672
18574
|
fallback2: ProviderModelIdSchema,
|
|
@@ -18680,12 +18582,12 @@ var ManualAgentPlanSchema = z2.object({
|
|
|
18680
18582
|
]);
|
|
18681
18583
|
if (unique.size !== 4) {
|
|
18682
18584
|
ctx.addIssue({
|
|
18683
|
-
code:
|
|
18585
|
+
code: z.ZodIssueCode.custom,
|
|
18684
18586
|
message: "primary and fallbacks must be unique per agent"
|
|
18685
18587
|
});
|
|
18686
18588
|
}
|
|
18687
18589
|
});
|
|
18688
|
-
var ManualPlanSchema =
|
|
18590
|
+
var ManualPlanSchema = z.object({
|
|
18689
18591
|
orchestrator: ManualAgentPlanSchema,
|
|
18690
18592
|
oracle: ManualAgentPlanSchema,
|
|
18691
18593
|
designer: ManualAgentPlanSchema,
|
|
@@ -18693,12 +18595,12 @@ var ManualPlanSchema = z2.object({
|
|
|
18693
18595
|
librarian: ManualAgentPlanSchema,
|
|
18694
18596
|
fixer: ManualAgentPlanSchema
|
|
18695
18597
|
}).strict();
|
|
18696
|
-
var PermissionActionSchema =
|
|
18697
|
-
var PermissionRuleSchema =
|
|
18598
|
+
var PermissionActionSchema = z.enum(["ask", "allow", "deny"]);
|
|
18599
|
+
var PermissionRuleSchema = z.union([
|
|
18698
18600
|
PermissionActionSchema,
|
|
18699
|
-
|
|
18601
|
+
z.record(z.string(), PermissionActionSchema)
|
|
18700
18602
|
]);
|
|
18701
|
-
var PermissionObjectSchema =
|
|
18603
|
+
var PermissionObjectSchema = z.object({
|
|
18702
18604
|
read: PermissionRuleSchema.optional(),
|
|
18703
18605
|
edit: PermissionRuleSchema.optional(),
|
|
18704
18606
|
glob: PermissionRuleSchema.optional(),
|
|
@@ -18716,32 +18618,32 @@ var PermissionObjectSchema = z2.object({
|
|
|
18716
18618
|
codesearch: PermissionActionSchema.optional(),
|
|
18717
18619
|
doom_loop: PermissionActionSchema.optional()
|
|
18718
18620
|
}).catchall(PermissionRuleSchema);
|
|
18719
|
-
var PermissionConfigSchema =
|
|
18621
|
+
var PermissionConfigSchema = z.union([
|
|
18720
18622
|
PermissionActionSchema,
|
|
18721
18623
|
PermissionObjectSchema
|
|
18722
18624
|
]);
|
|
18723
|
-
var AgentOverrideConfigSchema =
|
|
18724
|
-
model:
|
|
18725
|
-
|
|
18726
|
-
|
|
18727
|
-
|
|
18728
|
-
|
|
18729
|
-
id:
|
|
18730
|
-
variant:
|
|
18625
|
+
var AgentOverrideConfigSchema = z.object({
|
|
18626
|
+
model: z.union([
|
|
18627
|
+
z.string(),
|
|
18628
|
+
z.array(z.union([
|
|
18629
|
+
z.string(),
|
|
18630
|
+
z.object({
|
|
18631
|
+
id: z.string(),
|
|
18632
|
+
variant: z.string().optional()
|
|
18731
18633
|
})
|
|
18732
18634
|
])).min(1)
|
|
18733
18635
|
]).optional(),
|
|
18734
|
-
temperature:
|
|
18735
|
-
variant:
|
|
18736
|
-
skills:
|
|
18737
|
-
mcps:
|
|
18738
|
-
prompt:
|
|
18739
|
-
orchestratorPrompt:
|
|
18740
|
-
options:
|
|
18741
|
-
displayName:
|
|
18636
|
+
temperature: z.number().min(0).max(2).optional(),
|
|
18637
|
+
variant: z.string().optional().catch(undefined),
|
|
18638
|
+
skills: z.array(z.string()).optional(),
|
|
18639
|
+
mcps: z.array(z.string()).optional(),
|
|
18640
|
+
prompt: z.string().min(1).optional(),
|
|
18641
|
+
orchestratorPrompt: z.string().min(1).optional(),
|
|
18642
|
+
options: z.record(z.string(), z.unknown()).optional(),
|
|
18643
|
+
displayName: z.string().min(1).optional(),
|
|
18742
18644
|
permission: PermissionConfigSchema.optional()
|
|
18743
18645
|
}).strict();
|
|
18744
|
-
var MultiplexerTypeSchema =
|
|
18646
|
+
var MultiplexerTypeSchema = z.enum([
|
|
18745
18647
|
"auto",
|
|
18746
18648
|
"tmux",
|
|
18747
18649
|
"zellij",
|
|
@@ -18749,107 +18651,106 @@ var MultiplexerTypeSchema = z2.enum([
|
|
|
18749
18651
|
"cmux",
|
|
18750
18652
|
"none"
|
|
18751
18653
|
]);
|
|
18752
|
-
var MultiplexerLayoutSchema =
|
|
18654
|
+
var MultiplexerLayoutSchema = z.enum([
|
|
18753
18655
|
"main-horizontal",
|
|
18754
18656
|
"main-vertical",
|
|
18755
18657
|
"tiled",
|
|
18756
18658
|
"even-horizontal",
|
|
18757
18659
|
"even-vertical"
|
|
18758
18660
|
]);
|
|
18759
|
-
var ZellijPaneModeSchema =
|
|
18661
|
+
var ZellijPaneModeSchema = z.enum(["agent-tab", "current-tab"]);
|
|
18760
18662
|
var TmuxLayoutSchema = MultiplexerLayoutSchema;
|
|
18761
|
-
var MultiplexerConfigSchema =
|
|
18663
|
+
var MultiplexerConfigSchema = z.object({
|
|
18762
18664
|
type: MultiplexerTypeSchema.default("none"),
|
|
18763
18665
|
layout: MultiplexerLayoutSchema.default("main-vertical"),
|
|
18764
|
-
main_pane_size:
|
|
18666
|
+
main_pane_size: z.number().min(20).max(80).default(60),
|
|
18765
18667
|
zellij_pane_mode: ZellijPaneModeSchema.default("agent-tab")
|
|
18766
18668
|
});
|
|
18767
|
-
var TmuxConfigSchema =
|
|
18768
|
-
enabled:
|
|
18669
|
+
var TmuxConfigSchema = z.object({
|
|
18670
|
+
enabled: z.boolean().default(false),
|
|
18769
18671
|
layout: TmuxLayoutSchema.default("main-vertical"),
|
|
18770
|
-
main_pane_size:
|
|
18672
|
+
main_pane_size: z.number().min(20).max(80).default(60)
|
|
18771
18673
|
});
|
|
18772
|
-
var PresetSchema =
|
|
18773
|
-
var WebsearchConfigSchema =
|
|
18774
|
-
provider:
|
|
18674
|
+
var PresetSchema = z.record(z.string(), AgentOverrideConfigSchema);
|
|
18675
|
+
var WebsearchConfigSchema = z.object({
|
|
18676
|
+
provider: z.enum(["exa", "tavily"]).default("exa")
|
|
18775
18677
|
});
|
|
18776
|
-
var McpNameSchema =
|
|
18777
|
-
var InterviewConfigSchema =
|
|
18778
|
-
maxQuestions:
|
|
18779
|
-
outputFolder:
|
|
18780
|
-
autoOpenBrowser:
|
|
18781
|
-
port:
|
|
18782
|
-
dashboard:
|
|
18678
|
+
var McpNameSchema = z.enum(["websearch", "context7", "gh_grep"]);
|
|
18679
|
+
var InterviewConfigSchema = z.object({
|
|
18680
|
+
maxQuestions: z.number().int().min(1).max(10).default(2),
|
|
18681
|
+
outputFolder: z.string().min(1).default("interview"),
|
|
18682
|
+
autoOpenBrowser: z.boolean().default(true).describe("Automatically open the interview UI in your default browser during interactive runs. Disabled automatically in tests and CI."),
|
|
18683
|
+
port: z.number().int().min(0).max(65535).default(0),
|
|
18684
|
+
dashboard: z.boolean().default(false)
|
|
18783
18685
|
});
|
|
18784
|
-
var BackgroundJobsConfigSchema =
|
|
18785
|
-
maxSessionsPerAgent:
|
|
18786
|
-
readContextMinLines:
|
|
18787
|
-
readContextMaxFiles:
|
|
18686
|
+
var BackgroundJobsConfigSchema = z.object({
|
|
18687
|
+
maxSessionsPerAgent: z.number().int().min(1).max(10).default(2),
|
|
18688
|
+
readContextMinLines: z.number().int().min(0).max(1000).default(10),
|
|
18689
|
+
readContextMaxFiles: z.number().int().min(0).max(50).default(8)
|
|
18788
18690
|
});
|
|
18789
|
-
var FailoverConfigSchema =
|
|
18790
|
-
enabled:
|
|
18791
|
-
timeoutMs:
|
|
18792
|
-
retryDelayMs:
|
|
18793
|
-
maxRetries:
|
|
18794
|
-
retry_on_empty:
|
|
18795
|
-
runtimeOverride:
|
|
18691
|
+
var FailoverConfigSchema = z.object({
|
|
18692
|
+
enabled: z.boolean().default(true),
|
|
18693
|
+
timeoutMs: z.number().min(0).default(15000),
|
|
18694
|
+
retryDelayMs: z.number().min(0).default(500),
|
|
18695
|
+
maxRetries: z.number().int().min(0).default(3).describe("Number of consecutive 429/rate-limit responses tolerated on the " + "same model before aborting (or swapping to the next fallback " + "model when a chain is configured)."),
|
|
18696
|
+
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."),
|
|
18697
|
+
runtimeOverride: z.boolean().optional().describe("DEPRECATED: no longer used. Previously controlled whether out-of-chain " + "runtime model picks triggered fallback. Fallback is now always " + "disabled when a user explicitly selects a model via /model.")
|
|
18796
18698
|
}).strict();
|
|
18797
|
-
var CompanionConfigSchema =
|
|
18798
|
-
enabled:
|
|
18799
|
-
binaryPath:
|
|
18800
|
-
position:
|
|
18801
|
-
size:
|
|
18802
|
-
gifPack:
|
|
18803
|
-
loopStyle:
|
|
18804
|
-
speed:
|
|
18805
|
-
debug:
|
|
18699
|
+
var CompanionConfigSchema = z.object({
|
|
18700
|
+
enabled: z.boolean().optional(),
|
|
18701
|
+
binaryPath: z.string().min(1).optional().describe("Path to a custom companion binary to launch."),
|
|
18702
|
+
position: z.enum(["bottom-right", "bottom-left", "top-right", "top-left"]).optional(),
|
|
18703
|
+
size: z.enum(["small", "medium", "large"]).optional(),
|
|
18704
|
+
gifPack: z.enum(["default"]).optional().describe("Bundled companion animation pack to use."),
|
|
18705
|
+
loopStyle: z.enum(["classic", "smooth"]).optional().describe("Companion animation playback style: classic loops or smooth ping-pong playback."),
|
|
18706
|
+
speed: z.number().min(0.25).max(4).optional().describe("Companion animation playback speed multiplier. Defaults to 1."),
|
|
18707
|
+
debug: z.boolean().optional().describe("Enable verbose native companion debug logs.")
|
|
18806
18708
|
});
|
|
18807
|
-
var AcpAgentPermissionModeSchema =
|
|
18709
|
+
var AcpAgentPermissionModeSchema = z.enum(["ask", "allow", "reject"]);
|
|
18808
18710
|
var MAX_ACP_TIMEOUT_MS = 2147483647;
|
|
18809
|
-
var AcpAgentConfigSchema =
|
|
18810
|
-
command:
|
|
18811
|
-
args:
|
|
18812
|
-
env:
|
|
18813
|
-
cwd:
|
|
18814
|
-
description:
|
|
18815
|
-
prompt:
|
|
18816
|
-
orchestratorPrompt:
|
|
18711
|
+
var AcpAgentConfigSchema = z.object({
|
|
18712
|
+
command: z.string().min(1),
|
|
18713
|
+
args: z.array(z.string()).default([]),
|
|
18714
|
+
env: z.record(z.string(), z.string()).default({}),
|
|
18715
|
+
cwd: z.string().min(1).optional(),
|
|
18716
|
+
description: z.string().min(1).optional(),
|
|
18717
|
+
prompt: z.string().min(1).optional(),
|
|
18718
|
+
orchestratorPrompt: z.string().min(1).optional(),
|
|
18817
18719
|
wrapperModel: ProviderModelIdSchema.optional(),
|
|
18818
|
-
timeoutMs:
|
|
18720
|
+
timeoutMs: z.number().int().min(0).max(MAX_ACP_TIMEOUT_MS).default(0).describe("Timeout for a single ACP run in milliseconds. Set to 0 to disable the timeout."),
|
|
18819
18721
|
permissionMode: AcpAgentPermissionModeSchema.default("ask")
|
|
18820
18722
|
}).strict();
|
|
18821
|
-
var AcpAgentsConfigSchema =
|
|
18723
|
+
var AcpAgentsConfigSchema = z.record(z.string(), AcpAgentConfigSchema);
|
|
18822
18724
|
function rejectOrchestratorPromptOnOrchestrator(overrides, ctx, pathPrefix) {
|
|
18823
18725
|
for (const [name, override] of Object.entries(overrides)) {
|
|
18824
18726
|
if (name === "orchestrator" && override.orchestratorPrompt !== undefined) {
|
|
18825
18727
|
ctx.addIssue({
|
|
18826
|
-
code:
|
|
18728
|
+
code: z.ZodIssueCode.custom,
|
|
18827
18729
|
path: [...pathPrefix, name, "orchestratorPrompt"],
|
|
18828
18730
|
message: "orchestratorPrompt is not supported for the orchestrator agent"
|
|
18829
18731
|
});
|
|
18830
18732
|
}
|
|
18831
18733
|
}
|
|
18832
18734
|
}
|
|
18833
|
-
var PluginConfigSchema =
|
|
18834
|
-
preset:
|
|
18835
|
-
setDefaultAgent:
|
|
18836
|
-
compactSidebar:
|
|
18837
|
-
stripOrchestratorModel:
|
|
18838
|
-
autoUpdate:
|
|
18839
|
-
presets:
|
|
18840
|
-
agents:
|
|
18841
|
-
disabled_agents:
|
|
18842
|
-
image_routing:
|
|
18843
|
-
disabled_mcps:
|
|
18844
|
-
disabled_tools:
|
|
18845
|
-
disabled_skills:
|
|
18735
|
+
var PluginConfigSchema = z.object({
|
|
18736
|
+
preset: z.string().optional(),
|
|
18737
|
+
setDefaultAgent: z.boolean().optional(),
|
|
18738
|
+
compactSidebar: z.boolean().optional().describe("Use the compact TUI sidebar layout. Defaults to true; set false to use the expanded layout."),
|
|
18739
|
+
stripOrchestratorModel: z.boolean().optional().describe("When true, omit orchestrator.model and orchestrator.variant from the SDK config so OpenCode uses the session model selected with /model after subagent dispatch. An explicitly selected preset that sets orchestrator.model is preserved. Defaults to false."),
|
|
18740
|
+
autoUpdate: z.boolean().optional().describe("Disable automatic installation of plugin updates when false. Defaults to true."),
|
|
18741
|
+
presets: z.record(z.string(), PresetSchema).optional(),
|
|
18742
|
+
agents: z.record(z.string(), AgentOverrideConfigSchema).optional(),
|
|
18743
|
+
disabled_agents: z.array(z.string()).optional().describe("Agent names to disable completely. " + "Disabled agents are not instantiated and cannot be delegated to. " + "Orchestrator cannot be disabled. " + "By default, 'observer' is disabled. Remove it from this list and configure a vision-capable model to enable."),
|
|
18744
|
+
image_routing: z.enum(["auto", "direct"]).optional().describe("How image attachments are handled. " + "When omitted, preserves legacy conditional behavior: intercept " + 'attachments only when observer is enabled. "auto": requires ' + "observer to be enabled and saves attachments to disk before " + 'nudging delegation to @observer. "direct": always passes ' + "attachments to the orchestrator untouched."),
|
|
18745
|
+
disabled_mcps: z.array(z.string()).optional().describe("MCP server names to disable completely. Disabled servers are not " + "started and cannot be used by agents."),
|
|
18746
|
+
disabled_tools: z.array(z.string()).optional().describe("Tool names to disable completely. Disabled tools are not registered with OpenCode and cannot be used by agents."),
|
|
18747
|
+
disabled_skills: z.array(z.string()).optional().describe("Skill names to disable completely. Disabled skills are not granted to agents, even when referenced by presets or agent overrides."),
|
|
18846
18748
|
multiplexer: MultiplexerConfigSchema.optional(),
|
|
18847
18749
|
tmux: TmuxConfigSchema.optional(),
|
|
18848
18750
|
websearch: WebsearchConfigSchema.optional(),
|
|
18849
18751
|
interview: InterviewConfigSchema.optional(),
|
|
18850
18752
|
backgroundJobs: BackgroundJobsConfigSchema.optional(),
|
|
18851
18753
|
fallback: FailoverConfigSchema.optional(),
|
|
18852
|
-
council: CouncilConfigSchema.optional(),
|
|
18853
18754
|
companion: CompanionConfigSchema.optional(),
|
|
18854
18755
|
acpAgents: AcpAgentsConfigSchema.optional()
|
|
18855
18756
|
}).superRefine((value, ctx) => {
|
|
@@ -18971,7 +18872,6 @@ function mergePluginConfigs(base, override) {
|
|
|
18971
18872
|
interview: deepMerge(base.interview, override.interview),
|
|
18972
18873
|
backgroundJobs: deepMerge(base.backgroundJobs, override.backgroundJobs),
|
|
18973
18874
|
fallback: deepMerge(base.fallback, override.fallback),
|
|
18974
|
-
council: deepMerge(base.council, override.council),
|
|
18975
18875
|
acpAgents: deepMerge(base.acpAgents, override.acpAgents),
|
|
18976
18876
|
companion: deepMerge(base.companion, override.companion)
|
|
18977
18877
|
};
|
|
@@ -19116,641 +19016,87 @@ function getCustomAgentNames(config) {
|
|
|
19116
19016
|
function getAcpAgentNames(config) {
|
|
19117
19017
|
return Object.keys(config?.acpAgents ?? {});
|
|
19118
19018
|
}
|
|
19119
|
-
// src/
|
|
19120
|
-
var
|
|
19019
|
+
// src/agents/designer.ts
|
|
19020
|
+
var DESIGNER_PROMPT = `You are a Designer - a frontend UI/UX specialist who creates and reviews intentional, polished experiences.
|
|
19121
19021
|
|
|
19122
|
-
|
|
19123
|
-
constructor(message) {
|
|
19124
|
-
super(message);
|
|
19125
|
-
this.name = "OperationTimeoutError";
|
|
19126
|
-
}
|
|
19127
|
-
}
|
|
19128
|
-
async function withTimeout(operation, timeoutMs, message) {
|
|
19129
|
-
if (timeoutMs <= 0)
|
|
19130
|
-
return operation;
|
|
19131
|
-
let timer;
|
|
19132
|
-
try {
|
|
19133
|
-
return await Promise.race([
|
|
19134
|
-
operation,
|
|
19135
|
-
new Promise((_, reject) => {
|
|
19136
|
-
timer = setTimeout(() => {
|
|
19137
|
-
reject(new OperationTimeoutError(message));
|
|
19138
|
-
}, timeoutMs);
|
|
19139
|
-
})
|
|
19140
|
-
]);
|
|
19141
|
-
} finally {
|
|
19142
|
-
clearTimeout(timer);
|
|
19143
|
-
}
|
|
19144
|
-
}
|
|
19145
|
-
async function abortSessionWithTimeout(client, sessionId, timeoutMs = SESSION_ABORT_TIMEOUT_MS) {
|
|
19146
|
-
await withTimeout(client.session.abort({ path: { id: sessionId } }), timeoutMs, `Session abort timed out after ${timeoutMs}ms`);
|
|
19147
|
-
}
|
|
19148
|
-
function shortModelLabel(model) {
|
|
19149
|
-
return model.split("/").pop() ?? model;
|
|
19150
|
-
}
|
|
19151
|
-
function parseModelReference(model) {
|
|
19152
|
-
const slashIndex = model.indexOf("/");
|
|
19153
|
-
if (slashIndex <= 0 || slashIndex >= model.length - 1) {
|
|
19154
|
-
return null;
|
|
19155
|
-
}
|
|
19156
|
-
return {
|
|
19157
|
-
providerID: model.slice(0, slashIndex),
|
|
19158
|
-
modelID: model.slice(slashIndex + 1)
|
|
19159
|
-
};
|
|
19160
|
-
}
|
|
19161
|
-
async function promptWithTimeout(client, args, timeoutMs, signal) {
|
|
19162
|
-
if (signal?.aborted)
|
|
19163
|
-
throw new Error("Prompt cancelled");
|
|
19164
|
-
const sessionId = args.path.id;
|
|
19165
|
-
const hasTimeout = timeoutMs > 0;
|
|
19166
|
-
let timer;
|
|
19167
|
-
let onAbort;
|
|
19168
|
-
try {
|
|
19169
|
-
const promptPromise = client.session.prompt(args);
|
|
19170
|
-
promptPromise.catch(() => {});
|
|
19171
|
-
const racers = [promptPromise];
|
|
19172
|
-
if (hasTimeout) {
|
|
19173
|
-
racers.push(new Promise((_, reject) => {
|
|
19174
|
-
timer = setTimeout(() => {
|
|
19175
|
-
reject(new OperationTimeoutError(`Prompt timed out after ${timeoutMs}ms`));
|
|
19176
|
-
}, timeoutMs);
|
|
19177
|
-
}));
|
|
19178
|
-
}
|
|
19179
|
-
if (signal) {
|
|
19180
|
-
racers.push(new Promise((_, reject) => {
|
|
19181
|
-
if (signal.aborted) {
|
|
19182
|
-
reject(new Error("Prompt cancelled"));
|
|
19183
|
-
return;
|
|
19184
|
-
}
|
|
19185
|
-
onAbort = () => reject(new Error("Prompt cancelled"));
|
|
19186
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
19187
|
-
}));
|
|
19188
|
-
}
|
|
19189
|
-
await Promise.race(racers);
|
|
19190
|
-
} catch (error) {
|
|
19191
|
-
if (error instanceof OperationTimeoutError) {
|
|
19192
|
-
try {
|
|
19193
|
-
await abortSessionWithTimeout(client, sessionId);
|
|
19194
|
-
} catch {}
|
|
19195
|
-
}
|
|
19196
|
-
throw error;
|
|
19197
|
-
} finally {
|
|
19198
|
-
clearTimeout(timer);
|
|
19199
|
-
if (onAbort)
|
|
19200
|
-
signal?.removeEventListener("abort", onAbort);
|
|
19201
|
-
}
|
|
19202
|
-
}
|
|
19203
|
-
async function extractSessionResult(client, sessionId, options) {
|
|
19204
|
-
const includeReasoning = options?.includeReasoning ?? true;
|
|
19205
|
-
const messagesResult = await client.session.messages({
|
|
19206
|
-
path: { id: sessionId },
|
|
19207
|
-
...options?.directory ? { query: { directory: options.directory } } : {}
|
|
19208
|
-
});
|
|
19209
|
-
const messages = messagesResult.data ?? [];
|
|
19210
|
-
const assistantMessages = messages.filter((m) => m.info?.role === "assistant");
|
|
19211
|
-
const extractedContent = [];
|
|
19212
|
-
for (const message of assistantMessages) {
|
|
19213
|
-
for (const part of message.parts ?? []) {
|
|
19214
|
-
const allowed = includeReasoning ? part.type === "text" || part.type === "reasoning" : part.type === "text";
|
|
19215
|
-
if (allowed && part.text) {
|
|
19216
|
-
extractedContent.push(part.text);
|
|
19217
|
-
}
|
|
19218
|
-
}
|
|
19219
|
-
}
|
|
19220
|
-
const text = extractedContent.filter((t) => t.length > 0).join(`
|
|
19022
|
+
**Role**: Craft and review cohesive UI/UX that balances visual impact with usability.
|
|
19221
19023
|
|
|
19222
|
-
|
|
19223
|
-
return { text, empty: text.length === 0 };
|
|
19224
|
-
}
|
|
19024
|
+
## Design Principles
|
|
19225
19025
|
|
|
19226
|
-
|
|
19227
|
-
|
|
19228
|
-
|
|
19229
|
-
|
|
19026
|
+
**Typography**
|
|
19027
|
+
- Choose distinctive, characterful fonts that elevate aesthetics
|
|
19028
|
+
- Avoid generic defaults (Arial, Inter)-opt for unexpected, beautiful choices
|
|
19029
|
+
- Pair display fonts with refined body fonts for hierarchy
|
|
19230
19030
|
|
|
19231
|
-
|
|
19232
|
-
|
|
19233
|
-
|
|
19234
|
-
|
|
19235
|
-
- Lane: Fast codebase recon that returns compressed context
|
|
19236
|
-
- Permissions: read_files
|
|
19237
|
-
- Stats: 2x faster codebase search than orchestrator, 1/2 cost of orchestrator
|
|
19238
|
-
- Capabilities: Glob, grep, AST queries to locate files, symbols, patterns
|
|
19239
|
-
- **Delegate when:** Need to discover what exists before planning • Parallel searches speed discovery • Need summarized map vs full contents • Broad/uncertain scope
|
|
19240
|
-
- **Don't delegate when:** Know the path and need actual content • Need full file anyway • Single specific lookup • About to edit the file`,
|
|
19241
|
-
librarian: `@librarian
|
|
19242
|
-
- Lane: External knowledge and library research, fast web research
|
|
19243
|
-
- Role: Authoritative source for current library docs, API references, examples, bug investigations, and web retrieval
|
|
19244
|
-
- Stats: 2x faster web research than orchestrator, 1/2 cost of orchestrator
|
|
19245
|
-
- **Delegate when:** Libraries with frequent API changes (React, Next.js, AI SDKs) • Complex APIs needing official examples (ORMs, auth) • Version-specific behavior matters • Unfamiliar library • Edge cases or advanced features • Nuanced best practices • Working on fixing tricky bug or problem and need latest web research information
|
|
19246
|
-
- **Don't delegate when:** Standard usage you're confident • Simple stable APIs • General programming knowledge • Info already in conversation • Built-in language features
|
|
19247
|
-
- **Rule of thumb:** "How does this library work?" → @librarian. "How does programming work?" → answer directly. How does others solve or workaround this tricky issue?" → @librarian.`,
|
|
19248
|
-
oracle: `@oracle
|
|
19249
|
-
- Lane: Architecture, risk, debugging strategy, and review
|
|
19250
|
-
- Role: Strategic advisor for high-stakes decisions and persistent problems, code reviewer
|
|
19251
|
-
- Permissions: read_files
|
|
19252
|
-
- Stats: 5x better decision maker, problem solver, investigator than orchestrator, 0.8x speed of orchestrator, same cost.
|
|
19253
|
-
- Capabilities: Deep architectural reasoning, system-level trade-offs, complex debugging, code review, simplification, maintainability review
|
|
19254
|
-
- **Delegate when:** Major architectural decisions with long-term impact • Problems persisting after 2+ fix attempts • High-risk multi-system refactors • Costly trade-offs (performance vs maintainability) • Complex debugging with unclear root cause • Security/scalability/data integrity decisions • Genuinely uncertain and cost of wrong choice is high • Code needs simplification or YAGNI scrutiny
|
|
19255
|
-
- **Review use:** Oracle is an escalation, not a default verification step. Request independent Oracle review only when its analysis is expected to materially reduce risk or uncertainty.
|
|
19256
|
-
- **Don't delegate when:** Routine decisions you're confident about • First bug fix attempt • Straightforward trade-offs • Tactical "how" vs strategic "should" • Time-sensitive good-enough decisions • Quick research/testing can answer
|
|
19257
|
-
- **Rule of thumb:** Need senior architect review? → @oracle. Need code review or simplification? → @oracle. Routine coordination or final synthesis? → handle directly.`,
|
|
19258
|
-
designer: `@designer
|
|
19259
|
-
- Lane: UI/UX design, related edits, design polish and review
|
|
19260
|
-
- Permissions: read_files, write_files
|
|
19261
|
-
- Stats: 10x better UI/UX than orchestrator
|
|
19262
|
-
- Capabilities: Good design taste, visual relevant edits, interactions, responsive layouts, design systems with aesthetic intent, deep UI/UX knowledge.
|
|
19263
|
-
- Owns visual and interaction quality: layout, hierarchy, spacing, motion, affordances, responsive behavior, and overall feel.
|
|
19264
|
-
- Weakness: copywriting. Ask designer to use grounded, normal wording, then have orchestrator review/fix copy after design work without changing visual or interaction intent.
|
|
19265
|
-
- Avoid: "Let me us designer how it should look and implement yourself" → instead: "Let me ask designer to design and implement the UI/UX changes for me"
|
|
19266
|
-
- **Delegate when:** User-facing interfaces needing polish • Responsive layouts • UX-critical components (forms, nav, dashboards) • Visual consistency systems • Animations/micro-interactions • Landing/marketing pages • Refining functional→delightful • Reviewing existing UI/UX quality
|
|
19267
|
-
- **Don't delegate when:** Backend/logic with no visual • Quick prototypes where design doesn't matter yet.
|
|
19268
|
-
- **Rule of thumb:** Users see it and polish matters? → @designer. Headless/functional implementation? → schedule @fixer.`,
|
|
19269
|
-
fixer: `@fixer
|
|
19270
|
-
- Lane: Bounded implementation and executioner
|
|
19271
|
-
- Role: Fast execution specialist for well-defined tasks
|
|
19272
|
-
- Permissions: read_files, write_files
|
|
19273
|
-
- Stats: 2x faster code edits, 1/2 cost of orchestrator
|
|
19274
|
-
- Weakness: design, taste
|
|
19275
|
-
- Tools/Constraints: Execution-focused-no research, no architectural decisions
|
|
19276
|
-
- **Delegate when:** For implementation work, think and triage first. If the change is non-trivial or multi-file, hand bounded execution to @fixer • Parallelization benefits: Task involves multiple folders and multiple files modification, scoping work per folder and spawning parallel @fixers for each folder.
|
|
19277
|
-
- **Don't delegate when:** Needs discovery/research/decisions • Single small change (<20 lines, one file) • Unclear requirements needing iteration • Explaining to fixer > doing • Tight integration with your current work • Requires design taste, visual hierarchy, interaction polish, responsive layout decisions, animation/motion, component feel, or UI copy/design trade-offs
|
|
19278
|
-
- **Rule of thumb:** Headless/mechanical implementation → @fixer. User-visible design or polish → @designer. If @designer already set direction, @fixer may only do bounded mechanical follow-up that preserves that design exactly.`,
|
|
19279
|
-
council: `@council
|
|
19280
|
-
- Lane: High-stakes multi-model decision support
|
|
19281
|
-
- Role: Multi-LLM consensus engine that runs several councillors, synthesizes their views, and returns a structured council report.
|
|
19282
|
-
- Permissions: Read files
|
|
19283
|
-
- Stats: 3x slower than orchestrator, 3x or more cost of orchestrator
|
|
19284
|
-
- Capabilities: Runs multiple models in parallel, compares their answers, resolves disagreements, and produces a final synthesized answer plus councillor details and consensus summary.
|
|
19285
|
-
- **Delegate when:** Critical decisions need multiple independent perspectives • High-stakes architectural/security/data-integrity choices • Ambiguous problems where disagreement is useful signal • You want confidence beyond a single model • The user explicitly asks for council/consensus/multiple opinions.
|
|
19286
|
-
- **Don't delegate when:** Straightforward tasks you're confident about • Speed matters more than confidence • Routine implementation/debugging • A single specialist is clearly the right tool • You only need current docs/search/code review rather than multi-model consensus.
|
|
19287
|
-
- **How to call:** Send the full question/task and relevant context. Be explicit about what decision, trade-off, or answer the council should resolve. Do not ask council to do routine code edits.
|
|
19288
|
-
- **Result handling:** Council returns a structured response that may include: synthesized Council Response, individual Councillor Details, and Council Summary/confidence. Preserve that structure when the user asked for council output. Do not pretend the council only returned a final answer. If you need to act on the council result, first briefly state the council's recommendation, then proceed.
|
|
19289
|
-
- **Rule of thumb:** Need second/third opinions from different models? → @council. Need one expert lane? → use the specialist. Need final synthesis? → handle directly.`,
|
|
19290
|
-
observer: `@observer
|
|
19291
|
-
- Lane: Visual/media analysis isolated from orchestrator context
|
|
19292
|
-
- Role: Visual analysis specialist for images, PDFs, and diagrams
|
|
19293
|
-
- Permissions: Read files
|
|
19294
|
-
- Stats: Saves main context tokens - Observer processes raw files, returns structured observations
|
|
19295
|
-
- Capabilities: Interprets images, screenshots, PDFs, and diagrams via native read tool; extracts UI elements, layouts, text, relationships
|
|
19296
|
-
- **Delegate when:** Need to analyze a multimedia file• Extract information
|
|
19297
|
-
- **Don't delegate when:** Plain text files that Read can handle directly • Files that need editing afterward (need literal content from Read)
|
|
19298
|
-
- **Rule of thumb:** Even if your model supports vision, delegate visual analysis to @observer - it isolates large image/PDF bytes from your context window, returning only concise structured text. Need exact file contents for routing? → Read only the minimal context yourself.
|
|
19299
|
-
- **IMPORTANT:** When delegating to @observer, always include the **full file path** in the prompt so it can read the file. Example: "Analyze the screenshot at /path/to/file.png - describe the UI elements and error messages."`
|
|
19300
|
-
};
|
|
19301
|
-
var PARALLEL_DELEGATION_EXAMPLES = [
|
|
19302
|
-
"- Multiple @explorer searches across different domains?",
|
|
19303
|
-
"- @explorer + @librarian research in parallel?",
|
|
19304
|
-
"- Multiple @fixer instances for faster, scoped implementation?",
|
|
19305
|
-
"- @observer + @explorer in parallel (visual analysis + code search)?"
|
|
19306
|
-
];
|
|
19307
|
-
function buildOrchestratorPrompt(disabledAgents) {
|
|
19308
|
-
const enabledAgents = Object.entries(AGENT_DESCRIPTIONS).filter(([name]) => !disabledAgents?.has(name)).map(([, desc]) => desc).join(`
|
|
19031
|
+
**Color & Theme**
|
|
19032
|
+
- Commit to a cohesive aesthetic with clear color variables
|
|
19033
|
+
- Dominant colors with sharp accents > timid, evenly-distributed palettes
|
|
19034
|
+
- Create atmosphere through intentional color relationships
|
|
19309
19035
|
|
|
19310
|
-
|
|
19311
|
-
|
|
19312
|
-
|
|
19313
|
-
|
|
19314
|
-
|
|
19315
|
-
|
|
19316
|
-
}).join(`
|
|
19317
|
-
`);
|
|
19318
|
-
return `<Role>
|
|
19319
|
-
You are a workflow manager for coding work. Your job is to plan, schedule, delegate, monitor, reconcile, and verify specialist-agent work. You are not the default implementation worker.
|
|
19036
|
+
**Motion & Interaction**
|
|
19037
|
+
- Leverage framework animation utilities when available (Tailwind's transition/animation classes)
|
|
19038
|
+
- Focus on high-impact moments: orchestrated page loads with staggered reveals
|
|
19039
|
+
- Use scroll-triggers and hover states that surprise and delight
|
|
19040
|
+
- One well-timed animation > scattered micro-interactions
|
|
19041
|
+
- Drop to custom CSS/JS only when utilities can't achieve the vision
|
|
19320
19042
|
|
|
19321
|
-
|
|
19043
|
+
**Spatial Composition**
|
|
19044
|
+
- Break conventions: asymmetry, overlap, diagonal flow, grid-breaking
|
|
19045
|
+
- Generous negative space OR controlled density-commit to the choice
|
|
19046
|
+
- Unexpected layouts that guide the eye
|
|
19322
19047
|
|
|
19323
|
-
|
|
19048
|
+
**Visual Depth**
|
|
19049
|
+
- Create atmosphere beyond solid colors: gradient meshes, noise textures, geometric patterns
|
|
19050
|
+
- Layer transparencies, dramatic shadows, decorative borders
|
|
19051
|
+
- Contextual effects that match the aesthetic (grain overlays, custom cursors)
|
|
19324
19052
|
|
|
19325
|
-
|
|
19326
|
-
|
|
19327
|
-
|
|
19053
|
+
**Styling Approach**
|
|
19054
|
+
- Default to Tailwind CSS utility classes when available-fast, maintainable, consistent
|
|
19055
|
+
- Use custom CSS when the vision requires it: complex animations, unique effects, advanced compositions
|
|
19056
|
+
- Balance utility-first speed with creative freedom where it matters
|
|
19328
19057
|
|
|
19329
|
-
|
|
19058
|
+
**Match Vision to Execution**
|
|
19059
|
+
- Maximalist designs → elaborate implementation, extensive animations, rich effects
|
|
19060
|
+
- Minimalist designs → restraint, precision, careful spacing and typography
|
|
19061
|
+
- Elegance comes from executing the chosen vision fully, not halfway
|
|
19330
19062
|
|
|
19331
|
-
|
|
19063
|
+
## Constraints
|
|
19064
|
+
- Respect existing design systems when present
|
|
19065
|
+
- Leverage component libraries where available
|
|
19066
|
+
- Prioritize visual excellence-code perfection comes second
|
|
19067
|
+
- Use grounded, normal, regular english - don't use jargon or overly technical language
|
|
19332
19068
|
|
|
19333
|
-
|
|
19069
|
+
${WRITABLE_FILE_OPERATIONS_RULES}
|
|
19334
19070
|
|
|
19335
|
-
|
|
19071
|
+
## Review Responsibilities
|
|
19072
|
+
- Review existing UI for usability, responsiveness, visual consistency, and polish when asked
|
|
19073
|
+
- Call out concrete UX issues and improvements, not just abstract design advice
|
|
19074
|
+
- When validating, focus on what users actually see and feel
|
|
19336
19075
|
|
|
19337
|
-
##
|
|
19338
|
-
|
|
19076
|
+
## Output Quality
|
|
19077
|
+
You're capable of extraordinary creative work. Commit fully to distinctive visions and show what's possible when breaking conventions thoughtfully.`;
|
|
19078
|
+
function createDesignerAgent(model, customPrompt, customAppendPrompt) {
|
|
19079
|
+
let prompt = DESIGNER_PROMPT;
|
|
19080
|
+
if (customPrompt) {
|
|
19081
|
+
prompt = customPrompt;
|
|
19082
|
+
} else if (customAppendPrompt) {
|
|
19083
|
+
prompt = `${DESIGNER_PROMPT}
|
|
19339
19084
|
|
|
19340
|
-
|
|
19341
|
-
|
|
19342
|
-
|
|
19085
|
+
${customAppendPrompt}`;
|
|
19086
|
+
}
|
|
19087
|
+
return {
|
|
19088
|
+
name: "designer",
|
|
19089
|
+
description: "UI/UX design, review, and implementation. Use for styling, responsive design, component architecture and visual polish.",
|
|
19090
|
+
config: {
|
|
19091
|
+
model,
|
|
19092
|
+
temperature: 0.7,
|
|
19093
|
+
prompt
|
|
19094
|
+
}
|
|
19095
|
+
};
|
|
19096
|
+
}
|
|
19343
19097
|
|
|
19344
|
-
|
|
19345
|
-
|
|
19346
|
-
|
|
19347
|
-
**Routing threshold:**
|
|
19348
|
-
- Handle directly only for one isolated, clear, low-risk action where delegation would cost more than execution.
|
|
19349
|
-
- For multi-step implementation, broad discovery, external research, visual work, or complex debugging, delegate to the suitable specialist.
|
|
19350
|
-
- If two or more parts can proceed independently, dispatch them in parallel before starting dependent work.
|
|
19351
|
-
- Do not delegate merely because an agent exists. Do not keep substantive work entirely in the orchestrator merely because each individual step seems easy.
|
|
19352
|
-
|
|
19353
|
-
**Dispatch efficiency:**
|
|
19354
|
-
- Reference paths/lines, don't paste files (\`src/app.ts:42\` not full contents)
|
|
19355
|
-
- Brief user on delegation goal before each call
|
|
19356
|
-
- Record task IDs, state, and advisory ownership/dependency labels
|
|
19357
|
-
- Do not immediately wait after spawning independent background tasks unless the next step truly depends on their result
|
|
19358
|
-
- Reconcile results, resolve conflicts, and gate dependent lanes
|
|
19359
|
-
|
|
19360
|
-
${WRITABLE_FILE_OPERATIONS_RULES}
|
|
19361
|
-
|
|
19362
|
-
## 4. Plan and Parallelize
|
|
19363
|
-
When the routing threshold calls for delegation, build a short work graph before dispatching:
|
|
19364
|
-
- Independent lanes that can run now
|
|
19365
|
-
- Dependency-ordered lanes that must wait
|
|
19366
|
-
- Advisory ownership for write-capable lanes
|
|
19367
|
-
- Verification/review lanes that run after implementation
|
|
19368
|
-
|
|
19369
|
-
### Todo Continuity
|
|
19370
|
-
- When the user adds a new task while a todo list exists, append the new task to the end of the existing todo list instead of replacing the list.
|
|
19371
|
-
- Preserve existing todo order, statuses, and priorities unless the user explicitly asks to reprioritize, cancel, or replace them.
|
|
19372
|
-
- Finish the current in-progress task before starting the newly appended task unless the current task is blocked or the user explicitly overrides the order.
|
|
19373
|
-
|
|
19374
|
-
Can tasks be split into background specialist work?
|
|
19375
|
-
${enabledParallelExamples}
|
|
19376
|
-
|
|
19377
|
-
Balance: respect dependencies, avoid parallelizing what must be sequential, and avoid overlapping write ownership.
|
|
19378
|
-
|
|
19379
|
-
### Background Task Discipline
|
|
19380
|
-
- Prefer \`task(..., background: true)\` for delegated work that can run independently.
|
|
19381
|
-
- For work already chosen for delegation, launch independent specialist lanes in the background so the orchestrator stays unblocked and can reconcile results when they return.
|
|
19382
|
-
- Track each task's specialist, objective, task/session ID, and file/topic ownership.
|
|
19383
|
-
- Continue orchestration only on non-overlapping work; otherwise briefly report what was launched and stop.
|
|
19384
|
-
- Before local edits or another writer task, compare against running task scopes.
|
|
19385
|
-
- Parallel background tasks are allowed only when their write scopes do not conflict.
|
|
19386
|
-
- Before final response, reconcile any terminal jobs shown in the Background Job Board.
|
|
19387
|
-
- Use \`cancel_task\` only when the user asks, or when a running lane is obsolete, wrong, or conflicts with a safer replacement plan.
|
|
19388
|
-
- Cancellation is not rollback: if cancelling a writer, inspect and reconcile partial file changes before launching a replacement lane.
|
|
19389
|
-
|
|
19390
|
-
### Design Handoff Discipline
|
|
19391
|
-
- When @designer completes UI/UX work, treat layout, spacing, hierarchy, motion, color, affordances, and component feel as intentional design output.
|
|
19392
|
-
- Do not later simplify, normalize, or refactor it in ways that flatten the design.
|
|
19393
|
-
- The orchestrator should review and improve user-facing copy after designer work, because designer copy may be weak.
|
|
19394
|
-
- Copy edits must preserve the designer's visual structure and interaction intent.
|
|
19395
|
-
- If follow-up work is purely mechanical and preserves the design exactly, @fixer can handle it. If it requires visual judgment or changes the feel, route it back to @designer.
|
|
19396
|
-
|
|
19397
|
-
### Session Reuse
|
|
19398
|
-
- Smartly reuse an available specialist session - context reuse saves time and tokens
|
|
19399
|
-
- When too much unrelated, and really needed, start a fresh session with the specialist
|
|
19400
|
-
- If multiple remembered sessions fit, prefer the most recently used matching session.
|
|
19401
|
-
- Prefer re-uses over creating new sessions all the time
|
|
19402
|
-
- When reusing a specialist session, you MUST pass the existing session or alias in the task tool's \`task_id\` argument. Saying "reuse" in prose is not enough.
|
|
19403
|
-
- If the Background Job Board lists \`fix-1 / ses_abc / fixer\`, call task with \`subagent_type: "fixer"\` and \`task_id: "fix-1"\` or \`task_id: "ses_abc"\`.
|
|
19404
|
-
- Do not leave \`task_id\` empty when intending to reuse; omitted or empty \`task_id\` creates a new specialist session.
|
|
19405
|
-
|
|
19406
|
-
## 6. Verify
|
|
19407
|
-
- Define the observable success criteria from the user's request.
|
|
19408
|
-
- Choose the minimum verification that produces meaningful evidence for the change's scope, risk, uncertainty, and potential impact.
|
|
19409
|
-
- Start with the narrowest relevant validation. Broaden verification only when integration scope, uncertainty, risk, or a failed focused check justifies it.
|
|
19410
|
-
- Do not run project-wide checks by habit or merely because files changed.
|
|
19411
|
-
- Do not treat verification as a fixed checklist; select evidence that can actually confirm the requested behavior.
|
|
19412
|
-
- Request independent review only when its expected risk reduction justifies its coordination cost.
|
|
19413
|
-
- Report what was verified and any material remaining uncertainty.
|
|
19414
|
-
|
|
19415
|
-
</Workflow>
|
|
19416
|
-
|
|
19417
|
-
<Communication>
|
|
19418
|
-
|
|
19419
|
-
## Clarity Over Assumptions
|
|
19420
|
-
- If request is vague or has multiple valid interpretations, ask a targeted question before proceeding
|
|
19421
|
-
- Don't guess at critical details (file paths, API choices, architectural decisions)
|
|
19422
|
-
- Do make reasonable assumptions for minor details and state them briefly
|
|
19423
|
-
|
|
19424
|
-
## Concise Execution
|
|
19425
|
-
- Answer directly, no preamble
|
|
19426
|
-
- Don't summarize what you did unless asked
|
|
19427
|
-
- Don't explain code unless asked
|
|
19428
|
-
- One-word answers are fine when appropriate
|
|
19429
|
-
- Default to the minimum response that fully resolves the user's request; expand only when detail is necessary or the user asks for it.
|
|
19430
|
-
- Do not restate the user's request or narrate routine work.
|
|
19431
|
-
- Brief delegation notices: "Checking docs via @librarian..." not "I'm going to delegate to @librarian because..."
|
|
19432
|
-
|
|
19433
|
-
## No Flattery
|
|
19434
|
-
Never: "Great question!" "Excellent idea!" "Smart choice!" or any praise of user input.
|
|
19435
|
-
|
|
19436
|
-
## Honest Pushback
|
|
19437
|
-
When user's approach seems problematic:
|
|
19438
|
-
- State concern + alternative concisely
|
|
19439
|
-
- Ask if they want to proceed anyway
|
|
19440
|
-
- Don't lecture, don't blindly implement
|
|
19441
|
-
|
|
19442
|
-
## Example
|
|
19443
|
-
**Bad:** "Great question! Let me think about the best approach here. I'm going to delegate to @librarian to check the latest Next.js documentation for the App Router, and then I'll implement the solution for you."
|
|
19444
|
-
|
|
19445
|
-
**Good:** "Checking Next.js App Router docs via @librarian..."
|
|
19446
|
-
[continues scheduling or integration]
|
|
19447
|
-
|
|
19448
|
-
</Communication>
|
|
19449
|
-
`;
|
|
19450
|
-
}
|
|
19451
|
-
function createOrchestratorAgent(model, customPrompt, customAppendPrompt, disabledAgents) {
|
|
19452
|
-
const basePrompt = buildOrchestratorPrompt(disabledAgents);
|
|
19453
|
-
const prompt = resolvePrompt(basePrompt, customPrompt, customAppendPrompt);
|
|
19454
|
-
const definition = {
|
|
19455
|
-
name: "orchestrator",
|
|
19456
|
-
description: "AI coding orchestrator that delegates tasks to specialist agents for optimal quality, speed, and cost",
|
|
19457
|
-
config: {
|
|
19458
|
-
temperature: 0.1,
|
|
19459
|
-
prompt
|
|
19460
|
-
}
|
|
19461
|
-
};
|
|
19462
|
-
if (Array.isArray(model)) {
|
|
19463
|
-
definition._modelArray = model.map((m) => typeof m === "string" ? { id: m } : m);
|
|
19464
|
-
} else if (typeof model === "string" && model) {
|
|
19465
|
-
definition.config.model = model;
|
|
19466
|
-
}
|
|
19467
|
-
return definition;
|
|
19468
|
-
}
|
|
19469
|
-
|
|
19470
|
-
// src/agents/permissions.ts
|
|
19471
|
-
function createReadOnlyAgentPermission() {
|
|
19472
|
-
return {
|
|
19473
|
-
"*": "deny",
|
|
19474
|
-
bash: "deny",
|
|
19475
|
-
edit: "deny",
|
|
19476
|
-
write: "deny",
|
|
19477
|
-
apply_patch: "deny",
|
|
19478
|
-
ast_grep_replace: "deny",
|
|
19479
|
-
task: "deny",
|
|
19480
|
-
question: "deny",
|
|
19481
|
-
read: "allow",
|
|
19482
|
-
glob: "allow",
|
|
19483
|
-
grep: "allow",
|
|
19484
|
-
lsp: "allow",
|
|
19485
|
-
list: "allow",
|
|
19486
|
-
codesearch: "allow",
|
|
19487
|
-
ast_grep_search: "allow"
|
|
19488
|
-
};
|
|
19489
|
-
}
|
|
19490
|
-
|
|
19491
|
-
// src/agents/council.ts
|
|
19492
|
-
var COUNCIL_AGENT_PROMPT = `You are the Council agent - a multi-LLM orchestration system that runs consensus across multiple models.
|
|
19493
|
-
|
|
19494
|
-
**Tool**: You have access to the \`council_session\` tool. You also have read-only codebase inspection tools. You do not have write, edit, shell, or subagent-delegation tools.
|
|
19495
|
-
|
|
19496
|
-
**When to use**:
|
|
19497
|
-
- When invoked by a user with a request
|
|
19498
|
-
- When you want multiple expert opinions on a complex problem
|
|
19499
|
-
- When higher confidence is needed through model consensus
|
|
19500
|
-
|
|
19501
|
-
**Usage**:
|
|
19502
|
-
1. Call the \`council_session\` tool with the user's prompt
|
|
19503
|
-
2. Optionally specify a preset (omit to use the configured default)
|
|
19504
|
-
3. Receive the councillor responses formatted for synthesis
|
|
19505
|
-
4. Follow the Synthesis Process below
|
|
19506
|
-
5. Present the result to the user
|
|
19507
|
-
|
|
19508
|
-
**Synthesis Process** (MANDATORY - follow in order):
|
|
19509
|
-
1. Read the original user prompt
|
|
19510
|
-
2. Review each councillor's response individually - note each councillor's key insight and unique contribution by name
|
|
19511
|
-
3. Identify agreements and contradictions between councillors
|
|
19512
|
-
4. Resolve contradictions with explicit reasoning
|
|
19513
|
-
5. Synthesize the optimal final answer
|
|
19514
|
-
6. Format output per the Required Output Format below
|
|
19515
|
-
|
|
19516
|
-
**Behavior**:
|
|
19517
|
-
- Delegate requests directly to council_session
|
|
19518
|
-
- Don't pre-analyze or filter the prompt before calling council_session
|
|
19519
|
-
- Credit specific insights from individual councillors using their names
|
|
19520
|
-
- If councillors disagree, explain why you chose one approach over another
|
|
19521
|
-
- Do not omit per-councillor details from the final response
|
|
19522
|
-
- Do not collapse the output into only a final summary
|
|
19523
|
-
- Be transparent about trade-offs when different approaches have valid pros/cons
|
|
19524
|
-
- Don't just average responses - choose the best approach and improve upon it
|
|
19525
|
-
|
|
19526
|
-
${READONLY_FILE_OPERATIONS_RULES}
|
|
19527
|
-
|
|
19528
|
-
**Required Output Format**:
|
|
19529
|
-
Always include these sections in your final response:
|
|
19530
|
-
|
|
19531
|
-
## Council Response
|
|
19532
|
-
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.
|
|
19533
|
-
|
|
19534
|
-
## Councillor Details
|
|
19535
|
-
Include each councillor's response separately.
|
|
19536
|
-
|
|
19537
|
-
Use each councillor name exactly as provided in the tool result.
|
|
19538
|
-
|
|
19539
|
-
Format each councillor like:
|
|
19540
|
-
|
|
19541
|
-
### <councillor name>
|
|
19542
|
-
<that councillor's response>
|
|
19543
|
-
|
|
19544
|
-
If a councillor failed or timed out, include that status briefly.
|
|
19545
|
-
|
|
19546
|
-
## Council Summary
|
|
19547
|
-
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.`;
|
|
19548
|
-
function createCouncilAgent(model, customPrompt, customAppendPrompt) {
|
|
19549
|
-
const prompt = resolvePrompt(COUNCIL_AGENT_PROMPT, customPrompt, customAppendPrompt);
|
|
19550
|
-
const definition = {
|
|
19551
|
-
name: "council",
|
|
19552
|
-
description: "Multi-LLM council agent that synthesizes responses from multiple models for higher-quality outputs",
|
|
19553
|
-
config: {
|
|
19554
|
-
temperature: 0.1,
|
|
19555
|
-
prompt,
|
|
19556
|
-
permission: {
|
|
19557
|
-
...createReadOnlyAgentPermission(),
|
|
19558
|
-
council_session: "allow"
|
|
19559
|
-
}
|
|
19560
|
-
}
|
|
19561
|
-
};
|
|
19562
|
-
if (model) {
|
|
19563
|
-
definition.config.model = model;
|
|
19564
|
-
}
|
|
19565
|
-
return definition;
|
|
19566
|
-
}
|
|
19567
|
-
function formatCouncillorPrompt(userPrompt, councillorPrompt) {
|
|
19568
|
-
if (!councillorPrompt)
|
|
19569
|
-
return userPrompt;
|
|
19570
|
-
return `${councillorPrompt}
|
|
19571
|
-
|
|
19572
|
-
---
|
|
19573
|
-
|
|
19574
|
-
${userPrompt}`;
|
|
19575
|
-
}
|
|
19576
|
-
function formatCouncillorResults(originalPrompt, councillorResults) {
|
|
19577
|
-
const completedWithResults = councillorResults.filter((cr) => cr.status === "completed" && cr.result);
|
|
19578
|
-
const councillorSection = completedWithResults.map((cr) => {
|
|
19579
|
-
const shortModel = shortModelLabel(cr.model);
|
|
19580
|
-
return `**${cr.name}** (${shortModel}):
|
|
19581
|
-
${cr.result}`;
|
|
19582
|
-
}).join(`
|
|
19583
|
-
|
|
19584
|
-
`);
|
|
19585
|
-
const failedSection = councillorResults.filter((cr) => cr.status !== "completed").map((cr) => `**${cr.name}**: ${cr.status} - ${cr.error ?? "Unknown"}`).join(`
|
|
19586
|
-
`);
|
|
19587
|
-
if (completedWithResults.length === 0) {
|
|
19588
|
-
const errorDetails = councillorResults.map((cr) => `**${cr.name}** (${shortModelLabel(cr.model)}): ${cr.status} - ${cr.error ?? "Unknown"}`).join(`
|
|
19589
|
-
`);
|
|
19590
|
-
return `---
|
|
19591
|
-
|
|
19592
|
-
**Original Prompt**:
|
|
19593
|
-
${originalPrompt}
|
|
19594
|
-
|
|
19595
|
-
---
|
|
19596
|
-
|
|
19597
|
-
**Councillor Responses**:
|
|
19598
|
-
All councillors failed to produce output:
|
|
19599
|
-
${errorDetails}
|
|
19600
|
-
|
|
19601
|
-
Please generate a response based on the original prompt alone.`;
|
|
19602
|
-
}
|
|
19603
|
-
let prompt = `---
|
|
19604
|
-
|
|
19605
|
-
**Original Prompt**:
|
|
19606
|
-
${originalPrompt}
|
|
19607
|
-
|
|
19608
|
-
---
|
|
19609
|
-
|
|
19610
|
-
**Councillor Responses**:
|
|
19611
|
-
${councillorSection}`;
|
|
19612
|
-
if (failedSection) {
|
|
19613
|
-
prompt += `
|
|
19614
|
-
|
|
19615
|
-
---
|
|
19616
|
-
|
|
19617
|
-
**Failed/Timed-out Councillors**:
|
|
19618
|
-
${failedSection}`;
|
|
19619
|
-
}
|
|
19620
|
-
prompt += `
|
|
19621
|
-
|
|
19622
|
-
---
|
|
19623
|
-
|
|
19624
|
-
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).`;
|
|
19625
|
-
return prompt;
|
|
19626
|
-
}
|
|
19627
|
-
|
|
19628
|
-
// src/agents/councillor.ts
|
|
19629
|
-
var COUNCILLOR_PROMPT = `You are a councillor in a multi-model council.
|
|
19630
|
-
|
|
19631
|
-
**Role**: Provide your best independent analysis and solution to the given problem.
|
|
19632
|
-
|
|
19633
|
-
**Capabilities**: You have read-only access to the codebase. You can:
|
|
19634
|
-
- Read files (read)
|
|
19635
|
-
- Search by name patterns (glob)
|
|
19636
|
-
- Search by content (grep)
|
|
19637
|
-
- Search code patterns (ast_grep_search)
|
|
19638
|
-
- Use OpenCode's built-in \`lsp\` tool when available
|
|
19639
|
-
- Search external docs (if MCPs are configured for this agent)
|
|
19640
|
-
|
|
19641
|
-
You CANNOT edit files, write files, run shell commands, or delegate to other agents. You are an advisor, not an implementer.
|
|
19642
|
-
|
|
19643
|
-
${NO_SHELL_READONLY_FILE_OPERATIONS_RULES}
|
|
19644
|
-
|
|
19645
|
-
**Behavior**:
|
|
19646
|
-
- **Examine the codebase** before answering - your read access is what makes council valuable. Don't guess at code you can see.
|
|
19647
|
-
- Analyze the problem thoroughly
|
|
19648
|
-
- Provide a complete, well-reasoned response
|
|
19649
|
-
- Focus on the quality and correctness of your solution
|
|
19650
|
-
- Be direct and concise
|
|
19651
|
-
- Don't be influenced by what other councillors might say - you won't see their responses
|
|
19652
|
-
|
|
19653
|
-
**Output**:
|
|
19654
|
-
- Give your honest assessment
|
|
19655
|
-
- Reference specific files and line numbers when relevant
|
|
19656
|
-
- Include relevant reasoning
|
|
19657
|
-
- State any assumptions clearly
|
|
19658
|
-
- Note any uncertainties`;
|
|
19659
|
-
function createCouncillorAgent(model, customPrompt, customAppendPrompt) {
|
|
19660
|
-
const prompt = resolvePrompt(COUNCILLOR_PROMPT, customPrompt, customAppendPrompt);
|
|
19661
|
-
return {
|
|
19662
|
-
name: "councillor",
|
|
19663
|
-
description: "Read-only council advisor. Examines codebase and provides independent analysis. Spawned internally by the council system.",
|
|
19664
|
-
config: {
|
|
19665
|
-
model,
|
|
19666
|
-
temperature: 0.2,
|
|
19667
|
-
prompt,
|
|
19668
|
-
permission: createReadOnlyAgentPermission()
|
|
19669
|
-
}
|
|
19670
|
-
};
|
|
19671
|
-
}
|
|
19672
|
-
|
|
19673
|
-
// src/agents/designer.ts
|
|
19674
|
-
var DESIGNER_PROMPT = `You are a Designer - a frontend UI/UX specialist who creates and reviews intentional, polished experiences.
|
|
19675
|
-
|
|
19676
|
-
**Role**: Craft and review cohesive UI/UX that balances visual impact with usability.
|
|
19677
|
-
|
|
19678
|
-
## Design Principles
|
|
19679
|
-
|
|
19680
|
-
**Typography**
|
|
19681
|
-
- Choose distinctive, characterful fonts that elevate aesthetics
|
|
19682
|
-
- Avoid generic defaults (Arial, Inter)-opt for unexpected, beautiful choices
|
|
19683
|
-
- Pair display fonts with refined body fonts for hierarchy
|
|
19684
|
-
|
|
19685
|
-
**Color & Theme**
|
|
19686
|
-
- Commit to a cohesive aesthetic with clear color variables
|
|
19687
|
-
- Dominant colors with sharp accents > timid, evenly-distributed palettes
|
|
19688
|
-
- Create atmosphere through intentional color relationships
|
|
19689
|
-
|
|
19690
|
-
**Motion & Interaction**
|
|
19691
|
-
- Leverage framework animation utilities when available (Tailwind's transition/animation classes)
|
|
19692
|
-
- Focus on high-impact moments: orchestrated page loads with staggered reveals
|
|
19693
|
-
- Use scroll-triggers and hover states that surprise and delight
|
|
19694
|
-
- One well-timed animation > scattered micro-interactions
|
|
19695
|
-
- Drop to custom CSS/JS only when utilities can't achieve the vision
|
|
19696
|
-
|
|
19697
|
-
**Spatial Composition**
|
|
19698
|
-
- Break conventions: asymmetry, overlap, diagonal flow, grid-breaking
|
|
19699
|
-
- Generous negative space OR controlled density-commit to the choice
|
|
19700
|
-
- Unexpected layouts that guide the eye
|
|
19701
|
-
|
|
19702
|
-
**Visual Depth**
|
|
19703
|
-
- Create atmosphere beyond solid colors: gradient meshes, noise textures, geometric patterns
|
|
19704
|
-
- Layer transparencies, dramatic shadows, decorative borders
|
|
19705
|
-
- Contextual effects that match the aesthetic (grain overlays, custom cursors)
|
|
19706
|
-
|
|
19707
|
-
**Styling Approach**
|
|
19708
|
-
- Default to Tailwind CSS utility classes when available-fast, maintainable, consistent
|
|
19709
|
-
- Use custom CSS when the vision requires it: complex animations, unique effects, advanced compositions
|
|
19710
|
-
- Balance utility-first speed with creative freedom where it matters
|
|
19711
|
-
|
|
19712
|
-
**Match Vision to Execution**
|
|
19713
|
-
- Maximalist designs → elaborate implementation, extensive animations, rich effects
|
|
19714
|
-
- Minimalist designs → restraint, precision, careful spacing and typography
|
|
19715
|
-
- Elegance comes from executing the chosen vision fully, not halfway
|
|
19716
|
-
|
|
19717
|
-
## Constraints
|
|
19718
|
-
- Respect existing design systems when present
|
|
19719
|
-
- Leverage component libraries where available
|
|
19720
|
-
- Prioritize visual excellence-code perfection comes second
|
|
19721
|
-
- Use grounded, normal, regular english - don't use jargon or overly technical language
|
|
19722
|
-
|
|
19723
|
-
${WRITABLE_FILE_OPERATIONS_RULES}
|
|
19724
|
-
|
|
19725
|
-
## Review Responsibilities
|
|
19726
|
-
- Review existing UI for usability, responsiveness, visual consistency, and polish when asked
|
|
19727
|
-
- Call out concrete UX issues and improvements, not just abstract design advice
|
|
19728
|
-
- When validating, focus on what users actually see and feel
|
|
19729
|
-
|
|
19730
|
-
## Output Quality
|
|
19731
|
-
You're capable of extraordinary creative work. Commit fully to distinctive visions and show what's possible when breaking conventions thoughtfully.`;
|
|
19732
|
-
function createDesignerAgent(model, customPrompt, customAppendPrompt) {
|
|
19733
|
-
let prompt = DESIGNER_PROMPT;
|
|
19734
|
-
if (customPrompt) {
|
|
19735
|
-
prompt = customPrompt;
|
|
19736
|
-
} else if (customAppendPrompt) {
|
|
19737
|
-
prompt = `${DESIGNER_PROMPT}
|
|
19738
|
-
|
|
19739
|
-
${customAppendPrompt}`;
|
|
19740
|
-
}
|
|
19741
|
-
return {
|
|
19742
|
-
name: "designer",
|
|
19743
|
-
description: "UI/UX design, review, and implementation. Use for styling, responsive design, component architecture and visual polish.",
|
|
19744
|
-
config: {
|
|
19745
|
-
model,
|
|
19746
|
-
temperature: 0.7,
|
|
19747
|
-
prompt
|
|
19748
|
-
}
|
|
19749
|
-
};
|
|
19750
|
-
}
|
|
19751
|
-
|
|
19752
|
-
// src/agents/explorer.ts
|
|
19753
|
-
var EXPLORER_PROMPT = `You are Explorer - a fast codebase navigation specialist.
|
|
19098
|
+
// src/agents/explorer.ts
|
|
19099
|
+
var EXPLORER_PROMPT = `You are Explorer - a fast codebase navigation specialist.
|
|
19754
19100
|
|
|
19755
19101
|
**Role**: Quick contextual grep for codebases. Answer "Where is X?", "Find Y", "Which file has Z".
|
|
19756
19102
|
|
|
@@ -19915,90 +19261,333 @@ var OBSERVER_PROMPT = `You are Observer - a visual analysis specialist.
|
|
|
19915
19261
|
|
|
19916
19262
|
**Role**: Interpret images, screenshots, PDFs, and diagrams. Extract structured observations for the Orchestrator to act on.
|
|
19917
19263
|
|
|
19918
|
-
**Behavior**:
|
|
19919
|
-
- Read the file(s) specified in the prompt
|
|
19920
|
-
- Analyze visual content - layouts, UI elements, text, relationships, flows
|
|
19921
|
-
- For screenshots with text/code/errors: extract the **exact text** via OCR - never paraphrase error messages or code
|
|
19922
|
-
- For multiple files: analyze each, then compare or relate as requested
|
|
19923
|
-
- Return ONLY the extracted information relevant to the goal
|
|
19924
|
-
- If the image is unclear, blurry, or partially visible: state what you CAN see and explicitly note what is uncertain - never guess or fabricate details
|
|
19264
|
+
**Behavior**:
|
|
19265
|
+
- Read the file(s) specified in the prompt
|
|
19266
|
+
- Analyze visual content - layouts, UI elements, text, relationships, flows
|
|
19267
|
+
- For screenshots with text/code/errors: extract the **exact text** via OCR - never paraphrase error messages or code
|
|
19268
|
+
- For multiple files: analyze each, then compare or relate as requested
|
|
19269
|
+
- Return ONLY the extracted information relevant to the goal
|
|
19270
|
+
- If the image is unclear, blurry, or partially visible: state what you CAN see and explicitly note what is uncertain - never guess or fabricate details
|
|
19271
|
+
|
|
19272
|
+
**Constraints**:
|
|
19273
|
+
- READ-ONLY: Analyze and report, don't modify files
|
|
19274
|
+
- Save context tokens - the Orchestrator never processes the raw file
|
|
19275
|
+
- Match the language of the request
|
|
19276
|
+
- If info not found, state clearly what's missing
|
|
19277
|
+
|
|
19278
|
+
${READONLY_FILE_OPERATIONS_RULES}
|
|
19279
|
+
`;
|
|
19280
|
+
function createObserverAgent(model, customPrompt, customAppendPrompt) {
|
|
19281
|
+
let prompt = OBSERVER_PROMPT;
|
|
19282
|
+
if (customPrompt) {
|
|
19283
|
+
prompt = customPrompt;
|
|
19284
|
+
} else if (customAppendPrompt) {
|
|
19285
|
+
prompt = `${OBSERVER_PROMPT}
|
|
19286
|
+
|
|
19287
|
+
${customAppendPrompt}`;
|
|
19288
|
+
}
|
|
19289
|
+
return {
|
|
19290
|
+
name: "observer",
|
|
19291
|
+
description: "Visual analysis. Use for interpreting images, screenshots, PDFs, and diagrams - extracts structured observations without loading raw files into main context. Requires a vision-capable model.",
|
|
19292
|
+
config: {
|
|
19293
|
+
model,
|
|
19294
|
+
temperature: 0.1,
|
|
19295
|
+
prompt
|
|
19296
|
+
}
|
|
19297
|
+
};
|
|
19298
|
+
}
|
|
19299
|
+
|
|
19300
|
+
// src/agents/oracle.ts
|
|
19301
|
+
var ORACLE_PROMPT = `You are Oracle - a strategic technical advisor and code reviewer.
|
|
19302
|
+
|
|
19303
|
+
**Role**: High-IQ debugging, architecture decisions, code review, simplification, and engineering guidance.
|
|
19304
|
+
|
|
19305
|
+
**Capabilities**:
|
|
19306
|
+
- Analyze complex codebases and identify root causes
|
|
19307
|
+
- Propose architectural solutions with tradeoffs
|
|
19308
|
+
- Review code for correctness, performance, maintainability, and unnecessary complexity
|
|
19309
|
+
- Enforce YAGNI and suggest simpler designs when abstractions are not pulling their weight
|
|
19310
|
+
- Guide debugging when standard approaches fail
|
|
19311
|
+
|
|
19312
|
+
**Behavior**:
|
|
19313
|
+
- Be direct and concise
|
|
19314
|
+
- Provide actionable recommendations
|
|
19315
|
+
- Explain reasoning briefly
|
|
19316
|
+
- Acknowledge uncertainty when present
|
|
19317
|
+
- Prefer simpler designs unless complexity clearly earns its keep
|
|
19318
|
+
|
|
19319
|
+
**Constraints**:
|
|
19320
|
+
- READ-ONLY: You advise, you don't implement
|
|
19321
|
+
- Focus on strategy, not execution
|
|
19322
|
+
- Point to specific files/lines when relevant
|
|
19323
|
+
|
|
19324
|
+
${READONLY_FILE_OPERATIONS_RULES}
|
|
19325
|
+
`;
|
|
19326
|
+
function createOracleAgent(model, customPrompt, customAppendPrompt) {
|
|
19327
|
+
let prompt = ORACLE_PROMPT;
|
|
19328
|
+
if (customPrompt) {
|
|
19329
|
+
prompt = customPrompt;
|
|
19330
|
+
} else if (customAppendPrompt) {
|
|
19331
|
+
prompt = `${ORACLE_PROMPT}
|
|
19332
|
+
|
|
19333
|
+
${customAppendPrompt}`;
|
|
19334
|
+
}
|
|
19335
|
+
return {
|
|
19336
|
+
name: "oracle",
|
|
19337
|
+
description: "Strategic technical advisor. Use for architecture decisions, complex debugging, code review, simplification, and engineering guidance.",
|
|
19338
|
+
config: {
|
|
19339
|
+
model,
|
|
19340
|
+
temperature: 0.1,
|
|
19341
|
+
prompt
|
|
19342
|
+
}
|
|
19343
|
+
};
|
|
19344
|
+
}
|
|
19345
|
+
|
|
19346
|
+
// src/agents/orchestrator.ts
|
|
19347
|
+
function resolvePrompt(base, customPrompt, customAppendPrompt) {
|
|
19348
|
+
const effectiveBase = customPrompt !== undefined ? customPrompt : base;
|
|
19349
|
+
return customAppendPrompt !== undefined ? `${effectiveBase}
|
|
19350
|
+
|
|
19351
|
+
${customAppendPrompt}` : effectiveBase;
|
|
19352
|
+
}
|
|
19353
|
+
var AGENT_DESCRIPTIONS = {
|
|
19354
|
+
explorer: `@explorer
|
|
19355
|
+
- Lane: Fast codebase recon that returns compressed context
|
|
19356
|
+
- Permissions: read_files
|
|
19357
|
+
- Stats: 2x faster codebase search than orchestrator, 1/2 cost of orchestrator
|
|
19358
|
+
- Capabilities: Glob, grep, AST queries to locate files, symbols, patterns
|
|
19359
|
+
- **Delegate when:** Need to discover what exists before planning • Parallel searches speed discovery • Need summarized map vs full contents • Broad/uncertain scope
|
|
19360
|
+
- **Don't delegate when:** Know the path and need actual content • Need full file anyway • Single specific lookup • About to edit the file`,
|
|
19361
|
+
librarian: `@librarian
|
|
19362
|
+
- Lane: External knowledge and library research, fast web research
|
|
19363
|
+
- Role: Authoritative source for current library docs, API references, examples, bug investigations, and web retrieval
|
|
19364
|
+
- Stats: 2x faster web research than orchestrator, 1/2 cost of orchestrator
|
|
19365
|
+
- **Delegate when:** Libraries with frequent API changes (React, Next.js, AI SDKs) • Complex APIs needing official examples (ORMs, auth) • Version-specific behavior matters • Unfamiliar library • Edge cases or advanced features • Nuanced best practices • Working on fixing tricky bug or problem and need latest web research information
|
|
19366
|
+
- **Don't delegate when:** Standard usage you're confident • Simple stable APIs • General programming knowledge • Info already in conversation • Built-in language features
|
|
19367
|
+
- **Rule of thumb:** "How does this library work?" → @librarian. "How does programming work?" → answer directly. How does others solve or workaround this tricky issue?" → @librarian.`,
|
|
19368
|
+
oracle: `@oracle
|
|
19369
|
+
- Lane: Architecture, risk, debugging strategy, and review
|
|
19370
|
+
- Role: Strategic advisor for high-stakes decisions and persistent problems, code reviewer
|
|
19371
|
+
- Permissions: read_files
|
|
19372
|
+
- Stats: 5x better decision maker, problem solver, investigator than orchestrator, 0.8x speed of orchestrator, same cost.
|
|
19373
|
+
- Capabilities: Deep architectural reasoning, system-level trade-offs, complex debugging, code review, simplification, maintainability review
|
|
19374
|
+
- **Delegate when:** Major architectural decisions with long-term impact • Problems persisting after 2+ fix attempts • High-risk multi-system refactors • Costly trade-offs (performance vs maintainability) • Complex debugging with unclear root cause • Security/scalability/data integrity decisions • Genuinely uncertain and cost of wrong choice is high • Code needs simplification or YAGNI scrutiny
|
|
19375
|
+
- **Review use:** Oracle is an escalation, not a default verification step. Request independent Oracle review only when its analysis is expected to materially reduce risk or uncertainty.
|
|
19376
|
+
- **Don't delegate when:** Routine decisions you're confident about • First bug fix attempt • Straightforward trade-offs • Tactical "how" vs strategic "should" • Time-sensitive good-enough decisions • Quick research/testing can answer
|
|
19377
|
+
- **Rule of thumb:** Need senior architect review? → @oracle. Need code review or simplification? → @oracle. Routine coordination or final synthesis? → handle directly.`,
|
|
19378
|
+
designer: `@designer
|
|
19379
|
+
- Lane: UI/UX design, related edits, design polish and review
|
|
19380
|
+
- Permissions: read_files, write_files
|
|
19381
|
+
- Stats: 10x better UI/UX than orchestrator
|
|
19382
|
+
- Capabilities: Good design taste, visual relevant edits, interactions, responsive layouts, design systems with aesthetic intent, deep UI/UX knowledge.
|
|
19383
|
+
- Owns visual and interaction quality: layout, hierarchy, spacing, motion, affordances, responsive behavior, and overall feel.
|
|
19384
|
+
- Weakness: copywriting. Ask designer to use grounded, normal wording, then have orchestrator review/fix copy after design work without changing visual or interaction intent.
|
|
19385
|
+
- Avoid: "Let me us designer how it should look and implement yourself" → instead: "Let me ask designer to design and implement the UI/UX changes for me"
|
|
19386
|
+
- **Delegate when:** User-facing interfaces needing polish • Responsive layouts • UX-critical components (forms, nav, dashboards) • Visual consistency systems • Animations/micro-interactions • Landing/marketing pages • Refining functional→delightful • Reviewing existing UI/UX quality
|
|
19387
|
+
- **Don't delegate when:** Backend/logic with no visual • Quick prototypes where design doesn't matter yet.
|
|
19388
|
+
- **Rule of thumb:** Users see it and polish matters? → @designer. Headless/functional implementation? → schedule @fixer.`,
|
|
19389
|
+
fixer: `@fixer
|
|
19390
|
+
- Lane: Bounded implementation and executioner
|
|
19391
|
+
- Role: Fast execution specialist for well-defined tasks
|
|
19392
|
+
- Permissions: read_files, write_files
|
|
19393
|
+
- Stats: 2x faster code edits, 1/2 cost of orchestrator
|
|
19394
|
+
- Weakness: design, taste
|
|
19395
|
+
- Tools/Constraints: Execution-focused-no research, no architectural decisions
|
|
19396
|
+
- **Delegate when:** For implementation work, think and triage first. If the change is non-trivial or multi-file, hand bounded execution to @fixer • Parallelization benefits: Task involves multiple folders and multiple files modification, scoping work per folder and spawning parallel @fixers for each folder.
|
|
19397
|
+
- **Don't delegate when:** Needs discovery/research/decisions • Single small change (<20 lines, one file) • Unclear requirements needing iteration • Explaining to fixer > doing • Tight integration with your current work • Requires design taste, visual hierarchy, interaction polish, responsive layout decisions, animation/motion, component feel, or UI copy/design trade-offs
|
|
19398
|
+
- **Rule of thumb:** Headless/mechanical implementation → @fixer. User-visible design or polish → @designer. If @designer already set direction, @fixer may only do bounded mechanical follow-up that preserves that design exactly.`,
|
|
19399
|
+
roundtable: `roundtable tool
|
|
19400
|
+
- Lane: Multi-model adversarial debate with consensus scoring
|
|
19401
|
+
- Role: Launches a structured round-table debate with 3 independent debaters (skeptic, pragmatist, architect) and a critic. Runs multiple rounds of cross-examination. Debunkers see each other's arguments and must explicitly address weaknesses. Critic scores consensus and quality after each round. Returns a 5-section council report with dissents, debate summary, and open questions.
|
|
19402
|
+
- Permissions: Read files (runs independently — no user interaction)
|
|
19403
|
+
- Stats: 1-5 rounds, 60-260s, tokens cost roughly proportional to rounds
|
|
19404
|
+
- Capabilities: Real cross-examination (not parallel/parallel synthesis), consensus-based early stop, divergence detection, quality threshold gating. Produces honest dissent section.
|
|
19405
|
+
- **Delegate when:** Critical architectural decisions • Tech stack trade-offs • Security/safety decisions • Cost analysis of changes • "Should I use X or Y?" questions • Migrations or deprecations • Designers vs Engineers conflicts
|
|
19406
|
+
- **Don't delegate when:** Simple yes/no answers • Features where speed > thoroughness • Single opinion is obvious • Routine code edits
|
|
19407
|
+
- **How to call:** Call the \`roundtable\` tool with \`{ query: "Specific question with enough context", maxRounds: optional, debug: optional }\`. Provide real constraints (e.g., hardware specs, budget, current tech stack). The more context, the better the debate.
|
|
19408
|
+
- **Result handling:** The tool returns a structured report with Council Decision (verdict), Dissent (where disagreement persisted), Debate Summary (rounds, scores), Open Questions, and Models Used. Present all 5 sections unless the user asked for a summary. If the dissent is strong, note it explicitly.
|
|
19409
|
+
- **Rule of thumb:** Need independent perspectives that actually challenge each other? → roundtable tool. Need one confidence estimate? → ask @oracle. Need to quickly ship? → make the call yourself.`,
|
|
19410
|
+
observer: `@observer
|
|
19411
|
+
- Lane: Visual/media analysis isolated from orchestrator context
|
|
19412
|
+
- Role: Visual analysis specialist for images, PDFs, and diagrams
|
|
19413
|
+
- Permissions: Read files
|
|
19414
|
+
- Stats: Saves main context tokens - Observer processes raw files, returns structured observations
|
|
19415
|
+
- Capabilities: Interprets images, screenshots, PDFs, and diagrams via native read tool; extracts UI elements, layouts, text, relationships
|
|
19416
|
+
- **Delegate when:** Need to analyze a multimedia file• Extract information
|
|
19417
|
+
- **Don't delegate when:** Plain text files that Read can handle directly • Files that need editing afterward (need literal content from Read)
|
|
19418
|
+
- **Rule of thumb:** Even if your model supports vision, delegate visual analysis to @observer - it isolates large image/PDF bytes from your context window, returning only concise structured text. Need exact file contents for routing? → Read only the minimal context yourself.
|
|
19419
|
+
- **IMPORTANT:** When delegating to @observer, always include the **full file path** in the prompt so it can read the file. Example: "Analyze the screenshot at /path/to/file.png - describe the UI elements and error messages."`
|
|
19420
|
+
};
|
|
19421
|
+
var PARALLEL_DELEGATION_EXAMPLES = [
|
|
19422
|
+
"- Multiple @explorer searches across different domains?",
|
|
19423
|
+
"- @explorer + @librarian research in parallel?",
|
|
19424
|
+
"- Multiple @fixer instances for faster, scoped implementation?",
|
|
19425
|
+
"- @observer + @explorer in parallel (visual analysis + code search)?"
|
|
19426
|
+
];
|
|
19427
|
+
function buildOrchestratorPrompt(disabledAgents) {
|
|
19428
|
+
const enabledAgents = Object.entries(AGENT_DESCRIPTIONS).filter(([name]) => !disabledAgents?.has(name)).map(([, desc]) => desc).join(`
|
|
19429
|
+
|
|
19430
|
+
`);
|
|
19431
|
+
const enabledParallelExamples = PARALLEL_DELEGATION_EXAMPLES.filter((line) => {
|
|
19432
|
+
const mentions = [...line.matchAll(/@(\w+)/g)].map((m) => m[1]);
|
|
19433
|
+
if (mentions.length === 0)
|
|
19434
|
+
return true;
|
|
19435
|
+
return mentions.every((name) => !disabledAgents?.has(name));
|
|
19436
|
+
}).join(`
|
|
19437
|
+
`);
|
|
19438
|
+
return `<Role>
|
|
19439
|
+
You are a workflow manager for coding work. Your job is to plan, schedule, delegate, monitor, reconcile, and verify specialist-agent work. You are not the default implementation worker.
|
|
19440
|
+
|
|
19441
|
+
For non-trivial coding work, identify separable lanes first and delegate bounded work to the appropriate specialist. Do not perform multi-step implementation serially when a suitable specialist is available.
|
|
19442
|
+
|
|
19443
|
+
Handle work directly only when it is one isolated, clear, low-risk action and delegation overhead exceeds doing it yourself.
|
|
19444
|
+
|
|
19445
|
+
Optimize for quality, speed, cost, and reliability by dispatching the right specialist lanes, tracking background task state, and integrating terminal results into one coherent outcome.
|
|
19446
|
+
You have perfect understanding of agent's context management, understand well the cost of building content and reusing context of existing agents when it's best or when it's best to spawn a new agent.
|
|
19447
|
+
</Role>
|
|
19448
|
+
|
|
19449
|
+
<Agents>
|
|
19450
|
+
|
|
19451
|
+
${enabledAgents}
|
|
19452
|
+
|
|
19453
|
+
</Agents>
|
|
19454
|
+
|
|
19455
|
+
<Workflow>
|
|
19456
|
+
|
|
19457
|
+
## 1. Understand
|
|
19458
|
+
Parse request: explicit requirements + implicit needs.
|
|
19459
|
+
|
|
19460
|
+
## 2. Path Selection
|
|
19461
|
+
Evaluate approach by: quality, speed and cost.
|
|
19462
|
+
Choose the path that optimizes all four.
|
|
19463
|
+
|
|
19464
|
+
## 3. Delegation Check
|
|
19465
|
+
Review available agents and lane rules. Before beginning non-trivial work, identify which parts can proceed independently.
|
|
19466
|
+
|
|
19467
|
+
**Routing threshold:**
|
|
19468
|
+
- Handle directly only for one isolated, clear, low-risk action where delegation would cost more than execution.
|
|
19469
|
+
- For multi-step implementation, broad discovery, external research, visual work, or complex debugging, delegate to the suitable specialist.
|
|
19470
|
+
- If two or more parts can proceed independently, dispatch them in parallel before starting dependent work.
|
|
19471
|
+
- Do not delegate merely because an agent exists. Do not keep substantive work entirely in the orchestrator merely because each individual step seems easy.
|
|
19472
|
+
|
|
19473
|
+
**Dispatch efficiency:**
|
|
19474
|
+
- Reference paths/lines, don't paste files (\`src/app.ts:42\` not full contents)
|
|
19475
|
+
- Brief user on delegation goal before each call
|
|
19476
|
+
- Record task IDs, state, and advisory ownership/dependency labels
|
|
19477
|
+
- Do not immediately wait after spawning independent background tasks unless the next step truly depends on their result
|
|
19478
|
+
- Reconcile results, resolve conflicts, and gate dependent lanes
|
|
19479
|
+
|
|
19480
|
+
${WRITABLE_FILE_OPERATIONS_RULES}
|
|
19481
|
+
|
|
19482
|
+
## 4. Plan and Parallelize
|
|
19483
|
+
When the routing threshold calls for delegation, build a short work graph before dispatching:
|
|
19484
|
+
- Independent lanes that can run now
|
|
19485
|
+
- Dependency-ordered lanes that must wait
|
|
19486
|
+
- Advisory ownership for write-capable lanes
|
|
19487
|
+
- Verification/review lanes that run after implementation
|
|
19488
|
+
|
|
19489
|
+
### Todo Continuity
|
|
19490
|
+
- When the user adds a new task while a todo list exists, append the new task to the end of the existing todo list instead of replacing the list.
|
|
19491
|
+
- Preserve existing todo order, statuses, and priorities unless the user explicitly asks to reprioritize, cancel, or replace them.
|
|
19492
|
+
- Finish the current in-progress task before starting the newly appended task unless the current task is blocked or the user explicitly overrides the order.
|
|
19493
|
+
|
|
19494
|
+
Can tasks be split into background specialist work?
|
|
19495
|
+
${enabledParallelExamples}
|
|
19496
|
+
|
|
19497
|
+
Balance: respect dependencies, avoid parallelizing what must be sequential, and avoid overlapping write ownership.
|
|
19498
|
+
|
|
19499
|
+
### Background Task Discipline
|
|
19500
|
+
- Prefer \`task(..., background: true)\` for delegated work that can run independently.
|
|
19501
|
+
- For work already chosen for delegation, launch independent specialist lanes in the background so the orchestrator stays unblocked and can reconcile results when they return.
|
|
19502
|
+
- Track each task's specialist, objective, task/session ID, and file/topic ownership.
|
|
19503
|
+
- Continue orchestration only on non-overlapping work; otherwise briefly report what was launched and stop.
|
|
19504
|
+
- Before local edits or another writer task, compare against running task scopes.
|
|
19505
|
+
- Parallel background tasks are allowed only when their write scopes do not conflict.
|
|
19506
|
+
- Before final response, reconcile any terminal jobs shown in the Background Job Board.
|
|
19507
|
+
- Use \`cancel_task\` only when the user asks, or when a running lane is obsolete, wrong, or conflicts with a safer replacement plan.
|
|
19508
|
+
- Cancellation is not rollback: if cancelling a writer, inspect and reconcile partial file changes before launching a replacement lane.
|
|
19509
|
+
|
|
19510
|
+
### Design Handoff Discipline
|
|
19511
|
+
- When @designer completes UI/UX work, treat layout, spacing, hierarchy, motion, color, affordances, and component feel as intentional design output.
|
|
19512
|
+
- Do not later simplify, normalize, or refactor it in ways that flatten the design.
|
|
19513
|
+
- The orchestrator should review and improve user-facing copy after designer work, because designer copy may be weak.
|
|
19514
|
+
- Copy edits must preserve the designer's visual structure and interaction intent.
|
|
19515
|
+
- If follow-up work is purely mechanical and preserves the design exactly, @fixer can handle it. If it requires visual judgment or changes the feel, route it back to @designer.
|
|
19516
|
+
|
|
19517
|
+
### Session Reuse
|
|
19518
|
+
- Smartly reuse an available specialist session - context reuse saves time and tokens
|
|
19519
|
+
- When too much unrelated, and really needed, start a fresh session with the specialist
|
|
19520
|
+
- If multiple remembered sessions fit, prefer the most recently used matching session.
|
|
19521
|
+
- Prefer re-uses over creating new sessions all the time
|
|
19522
|
+
- When reusing a specialist session, you MUST pass the existing session or alias in the task tool's \`task_id\` argument. Saying "reuse" in prose is not enough.
|
|
19523
|
+
- If the Background Job Board lists \`fix-1 / ses_abc / fixer\`, call task with \`subagent_type: "fixer"\` and \`task_id: "fix-1"\` or \`task_id: "ses_abc"\`.
|
|
19524
|
+
- Do not leave \`task_id\` empty when intending to reuse; omitted or empty \`task_id\` creates a new specialist session.
|
|
19525
|
+
|
|
19526
|
+
## 6. Verify
|
|
19527
|
+
- Define the observable success criteria from the user's request.
|
|
19528
|
+
- Choose the minimum verification that produces meaningful evidence for the change's scope, risk, uncertainty, and potential impact.
|
|
19529
|
+
- Start with the narrowest relevant validation. Broaden verification only when integration scope, uncertainty, risk, or a failed focused check justifies it.
|
|
19530
|
+
- Do not run project-wide checks by habit or merely because files changed.
|
|
19531
|
+
- Do not treat verification as a fixed checklist; select evidence that can actually confirm the requested behavior.
|
|
19532
|
+
- Request independent review only when its expected risk reduction justifies its coordination cost.
|
|
19533
|
+
- Report what was verified and any material remaining uncertainty.
|
|
19925
19534
|
|
|
19926
|
-
|
|
19927
|
-
- READ-ONLY: Analyze and report, don't modify files
|
|
19928
|
-
- Save context tokens - the Orchestrator never processes the raw file
|
|
19929
|
-
- Match the language of the request
|
|
19930
|
-
- If info not found, state clearly what's missing
|
|
19535
|
+
</Workflow>
|
|
19931
19536
|
|
|
19932
|
-
|
|
19933
|
-
`;
|
|
19934
|
-
function createObserverAgent(model, customPrompt, customAppendPrompt) {
|
|
19935
|
-
let prompt = OBSERVER_PROMPT;
|
|
19936
|
-
if (customPrompt) {
|
|
19937
|
-
prompt = customPrompt;
|
|
19938
|
-
} else if (customAppendPrompt) {
|
|
19939
|
-
prompt = `${OBSERVER_PROMPT}
|
|
19537
|
+
<Communication>
|
|
19940
19538
|
|
|
19941
|
-
|
|
19942
|
-
|
|
19943
|
-
|
|
19944
|
-
|
|
19945
|
-
description: "Visual analysis. Use for interpreting images, screenshots, PDFs, and diagrams - extracts structured observations without loading raw files into main context. Requires a vision-capable model.",
|
|
19946
|
-
config: {
|
|
19947
|
-
model,
|
|
19948
|
-
temperature: 0.1,
|
|
19949
|
-
prompt
|
|
19950
|
-
}
|
|
19951
|
-
};
|
|
19952
|
-
}
|
|
19539
|
+
## Clarity Over Assumptions
|
|
19540
|
+
- If request is vague or has multiple valid interpretations, ask a targeted question before proceeding
|
|
19541
|
+
- Don't guess at critical details (file paths, API choices, architectural decisions)
|
|
19542
|
+
- Do make reasonable assumptions for minor details and state them briefly
|
|
19953
19543
|
|
|
19954
|
-
|
|
19955
|
-
|
|
19544
|
+
## Concise Execution
|
|
19545
|
+
- Answer directly, no preamble
|
|
19546
|
+
- Don't summarize what you did unless asked
|
|
19547
|
+
- Don't explain code unless asked
|
|
19548
|
+
- One-word answers are fine when appropriate
|
|
19549
|
+
- Default to the minimum response that fully resolves the user's request; expand only when detail is necessary or the user asks for it.
|
|
19550
|
+
- Do not restate the user's request or narrate routine work.
|
|
19551
|
+
- Brief delegation notices: "Checking docs via @librarian..." not "I'm going to delegate to @librarian because..."
|
|
19956
19552
|
|
|
19957
|
-
|
|
19553
|
+
## No Flattery
|
|
19554
|
+
Never: "Great question!" "Excellent idea!" "Smart choice!" or any praise of user input.
|
|
19958
19555
|
|
|
19959
|
-
|
|
19960
|
-
|
|
19961
|
-
-
|
|
19962
|
-
-
|
|
19963
|
-
-
|
|
19964
|
-
- Guide debugging when standard approaches fail
|
|
19556
|
+
## Honest Pushback
|
|
19557
|
+
When user's approach seems problematic:
|
|
19558
|
+
- State concern + alternative concisely
|
|
19559
|
+
- Ask if they want to proceed anyway
|
|
19560
|
+
- Don't lecture, don't blindly implement
|
|
19965
19561
|
|
|
19966
|
-
|
|
19967
|
-
|
|
19968
|
-
- Provide actionable recommendations
|
|
19969
|
-
- Explain reasoning briefly
|
|
19970
|
-
- Acknowledge uncertainty when present
|
|
19971
|
-
- Prefer simpler designs unless complexity clearly earns its keep
|
|
19562
|
+
## Example
|
|
19563
|
+
**Bad:** "Great question! Let me think about the best approach here. I'm going to delegate to @librarian to check the latest Next.js documentation for the App Router, and then I'll implement the solution for you."
|
|
19972
19564
|
|
|
19973
|
-
**
|
|
19974
|
-
|
|
19975
|
-
- Focus on strategy, not execution
|
|
19976
|
-
- Point to specific files/lines when relevant
|
|
19565
|
+
**Good:** "Checking Next.js App Router docs via @librarian..."
|
|
19566
|
+
[continues scheduling or integration]
|
|
19977
19567
|
|
|
19978
|
-
|
|
19568
|
+
</Communication>
|
|
19979
19569
|
`;
|
|
19980
|
-
|
|
19981
|
-
|
|
19982
|
-
|
|
19983
|
-
|
|
19984
|
-
|
|
19985
|
-
|
|
19986
|
-
|
|
19987
|
-
${customAppendPrompt}`;
|
|
19988
|
-
}
|
|
19989
|
-
return {
|
|
19990
|
-
name: "oracle",
|
|
19991
|
-
description: "Strategic technical advisor. Use for architecture decisions, complex debugging, code review, simplification, and engineering guidance.",
|
|
19570
|
+
}
|
|
19571
|
+
function createOrchestratorAgent(model, customPrompt, customAppendPrompt, disabledAgents) {
|
|
19572
|
+
const basePrompt = buildOrchestratorPrompt(disabledAgents);
|
|
19573
|
+
const prompt = resolvePrompt(basePrompt, customPrompt, customAppendPrompt);
|
|
19574
|
+
const definition = {
|
|
19575
|
+
name: "orchestrator",
|
|
19576
|
+
description: "AI coding orchestrator that delegates tasks to specialist agents for optimal quality, speed, and cost",
|
|
19992
19577
|
config: {
|
|
19993
|
-
model,
|
|
19994
19578
|
temperature: 0.1,
|
|
19995
19579
|
prompt
|
|
19996
19580
|
}
|
|
19997
19581
|
};
|
|
19582
|
+
if (Array.isArray(model)) {
|
|
19583
|
+
definition._modelArray = model.map((m) => typeof m === "string" ? { id: m } : m);
|
|
19584
|
+
} else if (typeof model === "string" && model) {
|
|
19585
|
+
definition.config.model = model;
|
|
19586
|
+
}
|
|
19587
|
+
return definition;
|
|
19998
19588
|
}
|
|
19999
19589
|
|
|
20000
19590
|
// src/agents/index.ts
|
|
20001
|
-
var COUNCIL_TOOL_ALLOWED_AGENTS = new Set(["council"]);
|
|
20002
19591
|
var CANCEL_TASK_ALLOWED_AGENTS = new Set(["orchestrator"]);
|
|
20003
19592
|
var SAFE_AGENT_ALIAS_RE = /^[a-z][a-z0-9_-]*$/i;
|
|
20004
19593
|
function normalizeDisplayName(displayName) {
|
|
@@ -20146,12 +19735,10 @@ function applyDefaultPermissions(agent, configuredSkills, disabledSkills) {
|
|
|
20146
19735
|
const existing = agent.config.permission ?? {};
|
|
20147
19736
|
const skillPermissions = getSkillPermissionsForAgent(agent.name, configuredSkills, disabledSkills);
|
|
20148
19737
|
const questionPerm = existing.question === "deny" ? "deny" : "allow";
|
|
20149
|
-
const councilSessionPerm = COUNCIL_TOOL_ALLOWED_AGENTS.has(agent.name) ? existing.council_session ?? "allow" : "deny";
|
|
20150
19738
|
const cancelTaskPerm = CANCEL_TASK_ALLOWED_AGENTS.has(agent.name) ? existing.cancel_task ?? "allow" : "deny";
|
|
20151
19739
|
agent.config.permission = {
|
|
20152
19740
|
...existing,
|
|
20153
19741
|
question: questionPerm,
|
|
20154
|
-
council_session: councilSessionPerm,
|
|
20155
19742
|
cancel_task: cancelTaskPerm,
|
|
20156
19743
|
skill: {
|
|
20157
19744
|
...typeof existing.skill === "object" ? existing.skill : {},
|
|
@@ -20168,15 +19755,10 @@ var SUBAGENT_FACTORIES = {
|
|
|
20168
19755
|
oracle: createOracleAgent,
|
|
20169
19756
|
designer: createDesignerAgent,
|
|
20170
19757
|
fixer: createFixerAgent,
|
|
20171
|
-
observer: createObserverAgent
|
|
20172
|
-
council: createCouncilAgent,
|
|
20173
|
-
councillor: createCouncillorAgent
|
|
19758
|
+
observer: createObserverAgent
|
|
20174
19759
|
};
|
|
20175
19760
|
function createAgents(config, options) {
|
|
20176
19761
|
const disabled = getDisabledAgents(config);
|
|
20177
|
-
if (!config?.council) {
|
|
20178
|
-
disabled.add("council");
|
|
20179
|
-
}
|
|
20180
19762
|
const primaryModel = getConfigPrimaryModel(config);
|
|
20181
19763
|
const getModelForAgent = (name) => {
|
|
20182
19764
|
if (name === "fixer" && !getAgentOverride(config, "fixer")?.model) {
|
|
@@ -20254,13 +19836,6 @@ function createAgents(config, options) {
|
|
|
20254
19836
|
applyDefaultPermissions(agent, override?.skills, config?.disabled_skills);
|
|
20255
19837
|
return agent;
|
|
20256
19838
|
});
|
|
20257
|
-
const legacyMasterModel = config?.council?._legacyMasterModel;
|
|
20258
|
-
if (legacyMasterModel) {
|
|
20259
|
-
const councilAgent = builtInSubAgents.find((a) => a.name === "council");
|
|
20260
|
-
if (councilAgent && !getAgentOverride(config, "council")?.model && councilAgent.config.model === DEFAULT_MODELS.council) {
|
|
20261
|
-
councilAgent.config.model = legacyMasterModel;
|
|
20262
|
-
}
|
|
20263
|
-
}
|
|
20264
19839
|
const customSubAgents = protoCustomAgents.map((agent) => {
|
|
20265
19840
|
const override = getAgentOverride(config, agent.name);
|
|
20266
19841
|
if (override) {
|
|
@@ -20369,12 +19944,7 @@ ${rewrittenAcps.join(`
|
|
|
20369
19944
|
function getAgentConfigs(config, options) {
|
|
20370
19945
|
const agents = createAgents(config, options);
|
|
20371
19946
|
const applyClassification = (name, sdkConfig) => {
|
|
20372
|
-
if (name
|
|
20373
|
-
sdkConfig.mode = "all";
|
|
20374
|
-
} else if (name === "councillor") {
|
|
20375
|
-
sdkConfig.mode = "subagent";
|
|
20376
|
-
sdkConfig.hidden = true;
|
|
20377
|
-
} else if (isSubagent(name)) {
|
|
19947
|
+
if (isSubagent(name)) {
|
|
20378
19948
|
sdkConfig.mode = "subagent";
|
|
20379
19949
|
} else if (name === "orchestrator") {
|
|
20380
19950
|
sdkConfig.mode = "primary";
|
|
@@ -20382,7 +19952,7 @@ function getAgentConfigs(config, options) {
|
|
|
20382
19952
|
sdkConfig.mode = "subagent";
|
|
20383
19953
|
}
|
|
20384
19954
|
};
|
|
20385
|
-
const isInternalOnly = (
|
|
19955
|
+
const isInternalOnly = (_name) => false;
|
|
20386
19956
|
const entries = [];
|
|
20387
19957
|
for (const a of agents) {
|
|
20388
19958
|
const sdkConfig = {
|
|
@@ -21282,270 +20852,6 @@ function applyOrchestratorModelConfig(input) {
|
|
|
21282
20852
|
stripOrchestratorModel(input.agents, input.enabled, presetName ? input.presets?.[presetName] : undefined);
|
|
21283
20853
|
}
|
|
21284
20854
|
|
|
21285
|
-
// src/council/council-manager.ts
|
|
21286
|
-
class CouncilManager {
|
|
21287
|
-
client;
|
|
21288
|
-
directory;
|
|
21289
|
-
config;
|
|
21290
|
-
depthTracker;
|
|
21291
|
-
tmuxEnabled;
|
|
21292
|
-
deprecatedFields;
|
|
21293
|
-
legacyMasterModel;
|
|
21294
|
-
constructor(ctx, config, depthTracker, tmuxEnabled = false) {
|
|
21295
|
-
this.client = ctx.client;
|
|
21296
|
-
this.directory = ctx.directory;
|
|
21297
|
-
this.config = config;
|
|
21298
|
-
this.deprecatedFields = config?.council?._deprecated;
|
|
21299
|
-
this.legacyMasterModel = config?.council?._legacyMasterModel;
|
|
21300
|
-
this.depthTracker = depthTracker;
|
|
21301
|
-
this.tmuxEnabled = tmuxEnabled;
|
|
21302
|
-
}
|
|
21303
|
-
getDeprecatedFields() {
|
|
21304
|
-
return this.deprecatedFields;
|
|
21305
|
-
}
|
|
21306
|
-
getLegacyMasterModel() {
|
|
21307
|
-
return this.legacyMasterModel;
|
|
21308
|
-
}
|
|
21309
|
-
async runCouncil(prompt, presetName, parentSessionId) {
|
|
21310
|
-
if (this.depthTracker) {
|
|
21311
|
-
const parentDepth = this.depthTracker.getDepth(parentSessionId);
|
|
21312
|
-
if (parentDepth + 1 > this.depthTracker.maxDepth) {
|
|
21313
|
-
log("[council-manager] spawn blocked: max depth exceeded", {
|
|
21314
|
-
parentSessionId,
|
|
21315
|
-
parentDepth,
|
|
21316
|
-
maxDepth: this.depthTracker.maxDepth
|
|
21317
|
-
});
|
|
21318
|
-
return {
|
|
21319
|
-
success: false,
|
|
21320
|
-
error: "Subagent depth exceeded",
|
|
21321
|
-
councillorResults: []
|
|
21322
|
-
};
|
|
21323
|
-
}
|
|
21324
|
-
}
|
|
21325
|
-
const councilConfig = this.config?.council;
|
|
21326
|
-
if (!councilConfig) {
|
|
21327
|
-
log("[council-manager] Council configuration not found");
|
|
21328
|
-
return {
|
|
21329
|
-
success: false,
|
|
21330
|
-
error: "Council not configured",
|
|
21331
|
-
councillorResults: []
|
|
21332
|
-
};
|
|
21333
|
-
}
|
|
21334
|
-
const resolvedPreset = presetName ?? councilConfig.default_preset ?? "default";
|
|
21335
|
-
const preset = councilConfig.presets[resolvedPreset];
|
|
21336
|
-
if (!preset) {
|
|
21337
|
-
const available = Object.keys(councilConfig.presets).join(", ");
|
|
21338
|
-
log(`[council-manager] Preset "${resolvedPreset}" not found`);
|
|
21339
|
-
return {
|
|
21340
|
-
success: false,
|
|
21341
|
-
error: `Preset "${resolvedPreset}" does not exist. Omit the preset parameter to use the default, or call again with one of: ${available}`,
|
|
21342
|
-
councillorResults: []
|
|
21343
|
-
};
|
|
21344
|
-
}
|
|
21345
|
-
if (Object.keys(preset).length === 0) {
|
|
21346
|
-
log(`[council-manager] Preset "${resolvedPreset}" has no councillors`);
|
|
21347
|
-
return {
|
|
21348
|
-
success: false,
|
|
21349
|
-
error: `Preset "${resolvedPreset}" has no councillors configured. Note: the reserved key "master" is ignored - use councillor names as keys`,
|
|
21350
|
-
councillorResults: []
|
|
21351
|
-
};
|
|
21352
|
-
}
|
|
21353
|
-
const timeout = councilConfig.timeout ?? 180000;
|
|
21354
|
-
const executionMode = councilConfig.councillor_execution_mode ?? "parallel";
|
|
21355
|
-
const maxRetries = councilConfig.councillor_retries ?? 3;
|
|
21356
|
-
const councillorCount = Object.keys(preset).length;
|
|
21357
|
-
log(`[council-manager] Starting council with preset "${resolvedPreset}"`, {
|
|
21358
|
-
councillors: Object.keys(preset)
|
|
21359
|
-
});
|
|
21360
|
-
this.sendStartNotification(parentSessionId, councillorCount).catch((err) => {
|
|
21361
|
-
log("[council-manager] Failed to send start notification", {
|
|
21362
|
-
error: err instanceof Error ? err.message : String(err)
|
|
21363
|
-
});
|
|
21364
|
-
});
|
|
21365
|
-
const councillorResults = await this.runCouncillors(prompt, preset, parentSessionId, timeout, executionMode, maxRetries);
|
|
21366
|
-
const completedCount = councillorResults.filter((r) => r.status === "completed").length;
|
|
21367
|
-
log(`[council-manager] Councillors completed: ${completedCount}/${councillorResults.length}`);
|
|
21368
|
-
if (completedCount === 0) {
|
|
21369
|
-
return {
|
|
21370
|
-
success: false,
|
|
21371
|
-
error: "All councillors failed or timed out",
|
|
21372
|
-
councillorResults
|
|
21373
|
-
};
|
|
21374
|
-
}
|
|
21375
|
-
const formattedCouncillorResults = formatCouncillorResults(prompt, councillorResults);
|
|
21376
|
-
log("[council-manager] Council completed successfully");
|
|
21377
|
-
return {
|
|
21378
|
-
success: true,
|
|
21379
|
-
result: formattedCouncillorResults,
|
|
21380
|
-
councillorResults
|
|
21381
|
-
};
|
|
21382
|
-
}
|
|
21383
|
-
async sendStartNotification(parentSessionId, councillorCount) {
|
|
21384
|
-
const message = [
|
|
21385
|
-
`⎔ Council starting - ${councillorCount} councillors launching - ctrl+x ↓ to watch`,
|
|
21386
|
-
"",
|
|
21387
|
-
"[system status: continue without acknowledging this notification]"
|
|
21388
|
-
].join(`
|
|
21389
|
-
`);
|
|
21390
|
-
await this.client.session.prompt({
|
|
21391
|
-
path: { id: parentSessionId },
|
|
21392
|
-
body: {
|
|
21393
|
-
noReply: true,
|
|
21394
|
-
parts: [{ type: "text", text: message }]
|
|
21395
|
-
}
|
|
21396
|
-
});
|
|
21397
|
-
}
|
|
21398
|
-
async runAgentSession(options) {
|
|
21399
|
-
const modelRef = parseModelReference(options.model);
|
|
21400
|
-
if (!modelRef) {
|
|
21401
|
-
throw new Error(`Invalid model format: ${options.model}`);
|
|
21402
|
-
}
|
|
21403
|
-
let sessionId;
|
|
21404
|
-
try {
|
|
21405
|
-
const session = await this.client.session.create({
|
|
21406
|
-
body: {
|
|
21407
|
-
parentID: options.parentSessionId,
|
|
21408
|
-
title: options.title
|
|
21409
|
-
},
|
|
21410
|
-
query: { directory: this.directory }
|
|
21411
|
-
});
|
|
21412
|
-
if (!session.data?.id) {
|
|
21413
|
-
throw new Error("Failed to create session");
|
|
21414
|
-
}
|
|
21415
|
-
sessionId = session.data.id;
|
|
21416
|
-
if (this.depthTracker) {
|
|
21417
|
-
const registered = this.depthTracker.registerChild(options.parentSessionId, sessionId);
|
|
21418
|
-
if (!registered) {
|
|
21419
|
-
throw new Error("Subagent depth exceeded");
|
|
21420
|
-
}
|
|
21421
|
-
}
|
|
21422
|
-
if (this.tmuxEnabled) {
|
|
21423
|
-
await new Promise((r) => setTimeout(r, TMUX_SPAWN_DELAY_MS));
|
|
21424
|
-
}
|
|
21425
|
-
const body = {
|
|
21426
|
-
agent: options.agent,
|
|
21427
|
-
model: modelRef,
|
|
21428
|
-
tools: {
|
|
21429
|
-
task: false,
|
|
21430
|
-
question: false,
|
|
21431
|
-
edit: false,
|
|
21432
|
-
write: false,
|
|
21433
|
-
apply_patch: false,
|
|
21434
|
-
ast_grep_replace: false,
|
|
21435
|
-
bash: false
|
|
21436
|
-
},
|
|
21437
|
-
parts: [{ type: "text", text: options.promptText }]
|
|
21438
|
-
};
|
|
21439
|
-
if (options.variant) {
|
|
21440
|
-
body.variant = options.variant;
|
|
21441
|
-
}
|
|
21442
|
-
await promptWithTimeout(this.client, {
|
|
21443
|
-
path: { id: sessionId },
|
|
21444
|
-
body,
|
|
21445
|
-
query: { directory: this.directory }
|
|
21446
|
-
}, options.timeout);
|
|
21447
|
-
const extraction = await extractSessionResult(this.client, sessionId, {
|
|
21448
|
-
includeReasoning: options.includeReasoning
|
|
21449
|
-
});
|
|
21450
|
-
if (extraction.empty) {
|
|
21451
|
-
const retryOnEmpty = this.config?.fallback?.retry_on_empty ?? true;
|
|
21452
|
-
if (retryOnEmpty) {
|
|
21453
|
-
throw new Error("Empty response from provider");
|
|
21454
|
-
}
|
|
21455
|
-
}
|
|
21456
|
-
return extraction.text;
|
|
21457
|
-
} finally {
|
|
21458
|
-
if (sessionId) {
|
|
21459
|
-
this.client.session.abort({ path: { id: sessionId } }).catch(() => {});
|
|
21460
|
-
if (this.depthTracker) {
|
|
21461
|
-
this.depthTracker.cleanup(sessionId);
|
|
21462
|
-
}
|
|
21463
|
-
}
|
|
21464
|
-
}
|
|
21465
|
-
}
|
|
21466
|
-
async runCouncillors(prompt, councillors, parentSessionId, timeout, executionMode = "parallel", maxRetries) {
|
|
21467
|
-
const entries = Object.entries(councillors);
|
|
21468
|
-
const results = [];
|
|
21469
|
-
if (executionMode === "serial") {
|
|
21470
|
-
for (const [name, config] of entries) {
|
|
21471
|
-
results.push(await this.runCouncillorWithRetry(name, config, prompt, parentSessionId, timeout, maxRetries));
|
|
21472
|
-
}
|
|
21473
|
-
} else {
|
|
21474
|
-
const promises = entries.map(([name, config], index) => (async () => {
|
|
21475
|
-
if (this.tmuxEnabled && index > 0) {
|
|
21476
|
-
await new Promise((r) => setTimeout(r, index * COUNCILLOR_STAGGER_MS));
|
|
21477
|
-
}
|
|
21478
|
-
return this.runCouncillorWithRetry(name, config, prompt, parentSessionId, timeout, maxRetries);
|
|
21479
|
-
})());
|
|
21480
|
-
const settled = await Promise.allSettled(promises);
|
|
21481
|
-
for (let index = 0;index < settled.length; index++) {
|
|
21482
|
-
const result = settled[index];
|
|
21483
|
-
const [name, cfg] = entries[index];
|
|
21484
|
-
if (result.status === "fulfilled") {
|
|
21485
|
-
results.push(result.value);
|
|
21486
|
-
} else {
|
|
21487
|
-
results.push({
|
|
21488
|
-
name,
|
|
21489
|
-
model: cfg.model,
|
|
21490
|
-
status: "failed",
|
|
21491
|
-
error: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
21492
|
-
});
|
|
21493
|
-
}
|
|
21494
|
-
}
|
|
21495
|
-
}
|
|
21496
|
-
return results;
|
|
21497
|
-
}
|
|
21498
|
-
async runCouncillorWithRetry(name, config, prompt, parentSessionId, timeout, maxRetries) {
|
|
21499
|
-
const models = config.models ?? normalizeCouncillorModels(config.model, config.variant);
|
|
21500
|
-
const totalAttempts = 1 + maxRetries;
|
|
21501
|
-
let lastModel = models[0].id;
|
|
21502
|
-
let lastStatus = "failed";
|
|
21503
|
-
let lastError = `Councillor "${name}": no model responded`;
|
|
21504
|
-
for (let modelIndex = 0;modelIndex < models.length; modelIndex++) {
|
|
21505
|
-
const entry = models[modelIndex];
|
|
21506
|
-
const modelLabel = shortModelLabel(entry.id);
|
|
21507
|
-
lastModel = entry.id;
|
|
21508
|
-
for (let attempt = 1;attempt <= totalAttempts; attempt++) {
|
|
21509
|
-
if (attempt > 1) {
|
|
21510
|
-
log(`[council-manager] Retrying councillor "${name}" (${modelLabel}), attempt ${attempt}/${totalAttempts}`);
|
|
21511
|
-
} else if (modelIndex > 0) {
|
|
21512
|
-
log(`[council-manager] Councillor "${name}" falling back to ${modelLabel} (model ${modelIndex + 1}/${models.length})`);
|
|
21513
|
-
}
|
|
21514
|
-
try {
|
|
21515
|
-
const result = await this.runAgentSession({
|
|
21516
|
-
parentSessionId,
|
|
21517
|
-
title: `Council ${name} (${modelLabel})`,
|
|
21518
|
-
agent: "councillor",
|
|
21519
|
-
model: entry.id,
|
|
21520
|
-
promptText: formatCouncillorPrompt(prompt, config.prompt),
|
|
21521
|
-
variant: entry.variant,
|
|
21522
|
-
timeout,
|
|
21523
|
-
includeReasoning: false
|
|
21524
|
-
});
|
|
21525
|
-
return {
|
|
21526
|
-
name,
|
|
21527
|
-
model: entry.id,
|
|
21528
|
-
status: "completed",
|
|
21529
|
-
result
|
|
21530
|
-
};
|
|
21531
|
-
} catch (error) {
|
|
21532
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
21533
|
-
lastStatus = msg.includes("timed out") ? "timed_out" : "failed";
|
|
21534
|
-
lastError = `Councillor "${name}": ${msg}`;
|
|
21535
|
-
const isEmptyResponse = msg.includes("Empty response from provider");
|
|
21536
|
-
if (!(attempt < totalAttempts && isEmptyResponse))
|
|
21537
|
-
break;
|
|
21538
|
-
}
|
|
21539
|
-
}
|
|
21540
|
-
}
|
|
21541
|
-
return {
|
|
21542
|
-
name,
|
|
21543
|
-
model: lastModel,
|
|
21544
|
-
status: lastStatus,
|
|
21545
|
-
error: lastError
|
|
21546
|
-
};
|
|
21547
|
-
}
|
|
21548
|
-
}
|
|
21549
20855
|
// src/hooks/apply-patch/errors.ts
|
|
21550
20856
|
var APPLY_PATCH_ERROR_PREFIX = {
|
|
21551
20857
|
blocked: "apply_patch blocked",
|
|
@@ -24776,7 +24082,6 @@ var TERMINAL_STATES = new Set([
|
|
|
24776
24082
|
"cancelled"
|
|
24777
24083
|
]);
|
|
24778
24084
|
var AGENT_PREFIX = {
|
|
24779
|
-
council: "cou",
|
|
24780
24085
|
designer: "des",
|
|
24781
24086
|
explorer: "exp",
|
|
24782
24087
|
fixer: "fix",
|
|
@@ -25360,6 +24665,45 @@ function isInternalInitiatorPart(part) {
|
|
|
25360
24665
|
}
|
|
25361
24666
|
return part.metadata[INTERNAL_INITIATOR_METADATA_KEY] === true;
|
|
25362
24667
|
}
|
|
24668
|
+
// src/utils/session.ts
|
|
24669
|
+
var SESSION_ABORT_TIMEOUT_MS = 1000;
|
|
24670
|
+
|
|
24671
|
+
class OperationTimeoutError extends Error {
|
|
24672
|
+
constructor(message) {
|
|
24673
|
+
super(message);
|
|
24674
|
+
this.name = "OperationTimeoutError";
|
|
24675
|
+
}
|
|
24676
|
+
}
|
|
24677
|
+
async function withTimeout(operation, timeoutMs, message) {
|
|
24678
|
+
if (timeoutMs <= 0)
|
|
24679
|
+
return operation;
|
|
24680
|
+
let timer;
|
|
24681
|
+
try {
|
|
24682
|
+
return await Promise.race([
|
|
24683
|
+
operation,
|
|
24684
|
+
new Promise((_, reject) => {
|
|
24685
|
+
timer = setTimeout(() => {
|
|
24686
|
+
reject(new OperationTimeoutError(message));
|
|
24687
|
+
}, timeoutMs);
|
|
24688
|
+
})
|
|
24689
|
+
]);
|
|
24690
|
+
} finally {
|
|
24691
|
+
clearTimeout(timer);
|
|
24692
|
+
}
|
|
24693
|
+
}
|
|
24694
|
+
async function abortSessionWithTimeout(client, sessionId, timeoutMs = SESSION_ABORT_TIMEOUT_MS) {
|
|
24695
|
+
await withTimeout(client.session.abort({ path: { id: sessionId } }), timeoutMs, `Session abort timed out after ${timeoutMs}ms`);
|
|
24696
|
+
}
|
|
24697
|
+
function parseModelReference(model) {
|
|
24698
|
+
const slashIndex = model.indexOf("/");
|
|
24699
|
+
if (slashIndex <= 0 || slashIndex >= model.length - 1) {
|
|
24700
|
+
return null;
|
|
24701
|
+
}
|
|
24702
|
+
return {
|
|
24703
|
+
providerID: model.slice(0, slashIndex),
|
|
24704
|
+
modelID: model.slice(slashIndex + 1)
|
|
24705
|
+
};
|
|
24706
|
+
}
|
|
25363
24707
|
|
|
25364
24708
|
// src/utils/index.ts
|
|
25365
24709
|
init_zip_extractor();
|
|
@@ -30855,17 +30199,17 @@ import * as fs8 from "node:fs/promises";
|
|
|
30855
30199
|
import * as path15 from "node:path";
|
|
30856
30200
|
|
|
30857
30201
|
// src/interview/types.ts
|
|
30858
|
-
import { z as
|
|
30859
|
-
var RawQuestionSchema =
|
|
30860
|
-
id:
|
|
30861
|
-
question:
|
|
30862
|
-
options:
|
|
30863
|
-
suggested:
|
|
30202
|
+
import { z as z2 } from "zod";
|
|
30203
|
+
var RawQuestionSchema = z2.object({
|
|
30204
|
+
id: z2.string().optional(),
|
|
30205
|
+
question: z2.string().optional(),
|
|
30206
|
+
options: z2.array(z2.unknown()).optional(),
|
|
30207
|
+
suggested: z2.unknown().optional()
|
|
30864
30208
|
});
|
|
30865
|
-
var RawInterviewStateSchema =
|
|
30866
|
-
summary:
|
|
30867
|
-
title:
|
|
30868
|
-
questions:
|
|
30209
|
+
var RawInterviewStateSchema = z2.object({
|
|
30210
|
+
summary: z2.unknown().optional(),
|
|
30211
|
+
title: z2.unknown().optional(),
|
|
30212
|
+
questions: z2.array(z2.unknown()).optional()
|
|
30869
30213
|
});
|
|
30870
30214
|
|
|
30871
30215
|
// src/interview/parser.ts
|
|
@@ -34940,7 +34284,7 @@ class MultiplexerSessionManager {
|
|
|
34940
34284
|
import { spawn as spawn3 } from "node:child_process";
|
|
34941
34285
|
import { createInterface } from "node:readline";
|
|
34942
34286
|
import { tool } from "@opencode-ai/plugin";
|
|
34943
|
-
var
|
|
34287
|
+
var z3 = tool.schema;
|
|
34944
34288
|
|
|
34945
34289
|
class AcpClient {
|
|
34946
34290
|
name;
|
|
@@ -35160,10 +34504,10 @@ function createAcpRunTool(agents = {}) {
|
|
|
35160
34504
|
return tool({
|
|
35161
34505
|
description: "Run a configured external ACP-compatible coding agent and return its streamed result. Use for configured ACP agents such as Claude Code ACP, Gemini ACP, or custom ACP servers.",
|
|
35162
34506
|
args: {
|
|
35163
|
-
agent:
|
|
35164
|
-
prompt:
|
|
35165
|
-
cwd:
|
|
35166
|
-
timeout_ms:
|
|
34507
|
+
agent: z3.string().describe("Configured ACP agent name"),
|
|
34508
|
+
prompt: z3.string().describe("Task or question to send to the ACP agent"),
|
|
34509
|
+
cwd: z3.string().optional().describe("Optional absolute working directory override"),
|
|
34510
|
+
timeout_ms: z3.number().int().min(0).max(MAX_ACP_TIMEOUT_MS).optional().describe("Optional timeout override in milliseconds. Set to 0 to disable the timeout.")
|
|
35167
34511
|
},
|
|
35168
34512
|
async execute(args, ctx) {
|
|
35169
34513
|
if (ctx.agent !== args.agent) {
|
|
@@ -35824,7 +35168,7 @@ var ast_grep_replace = tool2({
|
|
|
35824
35168
|
import {
|
|
35825
35169
|
tool as tool3
|
|
35826
35170
|
} from "@opencode-ai/plugin";
|
|
35827
|
-
var
|
|
35171
|
+
var z4 = tool3.schema;
|
|
35828
35172
|
|
|
35829
35173
|
class SessionStillRunningError extends Error {
|
|
35830
35174
|
}
|
|
@@ -35834,8 +35178,8 @@ function createCancelTaskTool(options) {
|
|
|
35834
35178
|
|
|
35835
35179
|
Use only for obsolete, wrong, conflicting, or user-requested cancellation. Accepts either the native task_id/session ID or the parent-scoped alias shown in the Background Job Board. Cancellation is not rollback: if cancelling a writer, inspect and reconcile partial file changes before replacing the lane.`,
|
|
35836
35180
|
args: {
|
|
35837
|
-
task_id:
|
|
35838
|
-
reason:
|
|
35181
|
+
task_id: z4.string().describe("Tracked background task ID or Background Job Board alias"),
|
|
35182
|
+
reason: z4.string().optional().describe("Short cancellation reason")
|
|
35839
35183
|
},
|
|
35840
35184
|
async execute(args, toolContext) {
|
|
35841
35185
|
const parentSessionID = toolContext?.sessionID;
|
|
@@ -36217,72 +35561,6 @@ function unknownTaskOutput(taskID, message) {
|
|
|
36217
35561
|
].join(`
|
|
36218
35562
|
`);
|
|
36219
35563
|
}
|
|
36220
|
-
// src/tools/council.ts
|
|
36221
|
-
import {
|
|
36222
|
-
tool as tool4
|
|
36223
|
-
} from "@opencode-ai/plugin";
|
|
36224
|
-
var z6 = tool4.schema;
|
|
36225
|
-
function formatModelComposition(councillorResults) {
|
|
36226
|
-
return councillorResults.map((cr) => {
|
|
36227
|
-
const shortModel = shortModelLabel(cr.model);
|
|
36228
|
-
return `${cr.name}: ${shortModel}`;
|
|
36229
|
-
}).join(", ");
|
|
36230
|
-
}
|
|
36231
|
-
function createCouncilTool(_ctx, councilManager) {
|
|
36232
|
-
const council_session = tool4({
|
|
36233
|
-
description: `Launch a multi-LLM council session for consensus-based analysis.
|
|
36234
|
-
|
|
36235
|
-
Sends the prompt to multiple models (councillors) in parallel and returns their formatted responses for you to synthesize.
|
|
36236
|
-
|
|
36237
|
-
Returns the councillor responses with a summary footer.`,
|
|
36238
|
-
args: {
|
|
36239
|
-
prompt: z6.string().describe("The prompt to send to all councillors"),
|
|
36240
|
-
preset: z6.string().optional().describe("Council preset to use. Omit to use the configured default. Must match a preset in the council config.")
|
|
36241
|
-
},
|
|
36242
|
-
async execute(args, toolContext) {
|
|
36243
|
-
if (!toolContext || typeof toolContext !== "object" || !("sessionID" in toolContext)) {
|
|
36244
|
-
throw new Error("Invalid toolContext: missing sessionID");
|
|
36245
|
-
}
|
|
36246
|
-
const allowedAgents = ["council"];
|
|
36247
|
-
const callingAgent = toolContext.agent;
|
|
36248
|
-
if (callingAgent && !allowedAgents.includes(callingAgent)) {
|
|
36249
|
-
throw new Error(`Council sessions can only be invoked by the council agent. Current agent: ${callingAgent}`);
|
|
36250
|
-
}
|
|
36251
|
-
const prompt = String(args.prompt);
|
|
36252
|
-
const preset = typeof args.preset === "string" ? args.preset : undefined;
|
|
36253
|
-
const parentSessionId = toolContext.sessionID;
|
|
36254
|
-
const result = await councilManager.runCouncil(prompt, preset, parentSessionId);
|
|
36255
|
-
if (!result.success) {
|
|
36256
|
-
return `Council session failed: ${result.error}`;
|
|
36257
|
-
}
|
|
36258
|
-
let output = result.result ?? "(No output)";
|
|
36259
|
-
const completed = result.councillorResults.filter((cr) => cr.status === "completed").length;
|
|
36260
|
-
const total = result.councillorResults.length;
|
|
36261
|
-
const composition = formatModelComposition(result.councillorResults);
|
|
36262
|
-
output += `
|
|
36263
|
-
|
|
36264
|
-
---
|
|
36265
|
-
*Council: ${completed}/${total} councillors responded (${composition})*`;
|
|
36266
|
-
const deprecated = councilManager.getDeprecatedFields();
|
|
36267
|
-
if (deprecated && deprecated.length > 0) {
|
|
36268
|
-
const legacyMasterModel = councilManager.getLegacyMasterModel();
|
|
36269
|
-
const hasMaster = deprecated.includes("master");
|
|
36270
|
-
const trulyIgnored = hasMaster && !legacyMasterModel ? deprecated : deprecated.filter((f) => f !== "master");
|
|
36271
|
-
const parts = [];
|
|
36272
|
-
if (hasMaster && legacyMasterModel) {
|
|
36273
|
-
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.`);
|
|
36274
|
-
}
|
|
36275
|
-
if (trulyIgnored.length > 0) {
|
|
36276
|
-
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.`);
|
|
36277
|
-
}
|
|
36278
|
-
output += `
|
|
36279
|
-
⚠ Config warning: ${parts.join(" ")}`;
|
|
36280
|
-
}
|
|
36281
|
-
return output;
|
|
36282
|
-
}
|
|
36283
|
-
});
|
|
36284
|
-
return { council_session };
|
|
36285
|
-
}
|
|
36286
35564
|
// src/tools/preset-manager.ts
|
|
36287
35565
|
import * as fs10 from "node:fs";
|
|
36288
35566
|
|
|
@@ -36554,7 +35832,7 @@ var WEBFETCH_DESCRIPTION = "Fetch a URL with better extraction for static/docs p
|
|
|
36554
35832
|
import os7 from "node:os";
|
|
36555
35833
|
import path22 from "node:path";
|
|
36556
35834
|
import {
|
|
36557
|
-
tool as
|
|
35835
|
+
tool as tool4
|
|
36558
35836
|
} from "@opencode-ai/plugin";
|
|
36559
35837
|
|
|
36560
35838
|
// src/tools/smartfetch/binary.ts
|
|
@@ -36722,7 +36000,7 @@ var L = class u2 {
|
|
|
36722
36000
|
return this.#S;
|
|
36723
36001
|
}
|
|
36724
36002
|
constructor(e) {
|
|
36725
|
-
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:
|
|
36003
|
+
let { max: t = 0, ttl: i, ttlResolution: s = 1, ttlAutopurge: n, updateAgeOnGet: o, updateAgeOnHas: r, allowStale: h, dispose: l, onInsert: c, disposeAfter: f, noDisposeOnSet: g, noUpdateTTL: p, maxSize: T = 0, maxEntrySize: w = 0, sizeCalculation: y, fetchMethod: a, memoMethod: m, noDeleteOnFetchRejection: _, noDeleteOnStaleGet: b, allowStaleOnFetchRejection: d, allowStaleOnFetchAbort: A, ignoreFetchAbort: z5, perf: x } = e;
|
|
36726
36004
|
if (x !== undefined && typeof x?.now != "function")
|
|
36727
36005
|
throw new TypeError("perf option must have a now() method if specified");
|
|
36728
36006
|
if (this.#m = x ?? G, t !== 0 && !F(t))
|
|
@@ -36740,7 +36018,7 @@ var L = class u2 {
|
|
|
36740
36018
|
throw new TypeError("memoMethod must be a function if defined");
|
|
36741
36019
|
if (this.#U = m, a !== undefined && typeof a != "function")
|
|
36742
36020
|
throw new TypeError("fetchMethod must be a function if specified");
|
|
36743
|
-
if (this.#M = a, this.#W = !!a, this.#s = new Map, this.#i = Array.from({ length: t }).fill(undefined), this.#t = Array.from({ length: t }).fill(undefined), this.#a = new v(t), this.#c = new v(t), this.#l = 0, this.#h = 0, this.#y = R.create(t), this.#n = 0, this.#b = 0, typeof l == "function" && (this.#w = l), typeof c == "function" && (this.#D = c), typeof f == "function" ? (this.#S = f, this.#r = []) : (this.#S = undefined, this.#r = undefined), this.#T = !!this.#w, this.#j = !!this.#D, this.#f = !!this.#S, this.noDisposeOnSet = !!g, this.noUpdateTTL = !!p, this.noDeleteOnFetchRejection = !!_, this.allowStaleOnFetchRejection = !!d, this.allowStaleOnFetchAbort = !!A, this.ignoreFetchAbort = !!
|
|
36021
|
+
if (this.#M = a, this.#W = !!a, this.#s = new Map, this.#i = Array.from({ length: t }).fill(undefined), this.#t = Array.from({ length: t }).fill(undefined), this.#a = new v(t), this.#c = new v(t), this.#l = 0, this.#h = 0, this.#y = R.create(t), this.#n = 0, this.#b = 0, typeof l == "function" && (this.#w = l), typeof c == "function" && (this.#D = c), typeof f == "function" ? (this.#S = f, this.#r = []) : (this.#S = undefined, this.#r = undefined), this.#T = !!this.#w, this.#j = !!this.#D, this.#f = !!this.#S, this.noDisposeOnSet = !!g, this.noUpdateTTL = !!p, this.noDeleteOnFetchRejection = !!_, this.allowStaleOnFetchRejection = !!d, this.allowStaleOnFetchAbort = !!A, this.ignoreFetchAbort = !!z5, this.maxEntrySize !== 0) {
|
|
36744
36022
|
if (this.#u !== 0 && !F(this.#u))
|
|
36745
36023
|
throw new TypeError("maxSize must be a positive integer if specified");
|
|
36746
36024
|
if (!F(this.maxEntrySize))
|
|
@@ -37120,8 +36398,8 @@ var L = class u2 {
|
|
|
37120
36398
|
let A = this.#p(b);
|
|
37121
36399
|
if (!y && !A)
|
|
37122
36400
|
return a && (a.fetch = "hit"), this.#L(b), s && this.#x(b), a && this.#E(a, b), d;
|
|
37123
|
-
let
|
|
37124
|
-
return a && (a.fetch = A ? "stale" : "refresh", v && A && (a.returnedStale = true)), v ?
|
|
36401
|
+
let z5 = this.#P(e, b, _, w), v = z5.__staleWhileFetching !== undefined && i;
|
|
36402
|
+
return a && (a.fetch = A ? "stale" : "refresh", v && A && (a.returnedStale = true)), v ? z5.__staleWhileFetching : z5.__returned = z5;
|
|
37125
36403
|
}
|
|
37126
36404
|
}
|
|
37127
36405
|
forceFetch(e, t = {}) {
|
|
@@ -38341,20 +37619,20 @@ async function runSecondaryModelWithFallback(client, directory, models, prompt,
|
|
|
38341
37619
|
}
|
|
38342
37620
|
|
|
38343
37621
|
// src/tools/smartfetch/tool.ts
|
|
38344
|
-
var
|
|
37622
|
+
var z5 = tool4.schema;
|
|
38345
37623
|
function createWebfetchTool(pluginCtx, options = {}) {
|
|
38346
37624
|
const binaryDir = options.binaryDir || path22.join(os7.tmpdir(), "opencode-smartfetch");
|
|
38347
|
-
return
|
|
37625
|
+
return tool4({
|
|
38348
37626
|
description: WEBFETCH_DESCRIPTION,
|
|
38349
37627
|
args: {
|
|
38350
|
-
url:
|
|
38351
|
-
format:
|
|
38352
|
-
timeout:
|
|
38353
|
-
prompt:
|
|
38354
|
-
extract_main:
|
|
38355
|
-
prefer_llms_txt:
|
|
38356
|
-
include_metadata:
|
|
38357
|
-
save_binary:
|
|
37628
|
+
url: z5.httpUrl(),
|
|
37629
|
+
format: z5.enum(["text", "markdown", "html"]).default("markdown"),
|
|
37630
|
+
timeout: z5.number().positive().max(MAX_TIMEOUT_SECONDS).optional().describe("Timeout in seconds, max 120."),
|
|
37631
|
+
prompt: z5.string().optional().describe("Optional extraction task to run on the fetched content using a cheap secondary model."),
|
|
37632
|
+
extract_main: z5.boolean().default(true),
|
|
37633
|
+
prefer_llms_txt: z5.enum(["auto", "always", "never"]).default("auto"),
|
|
37634
|
+
include_metadata: z5.boolean().default(true),
|
|
37635
|
+
save_binary: z5.boolean().default(false).describe("Save binary payload to disk when it fits within the active download limit.")
|
|
38358
37636
|
},
|
|
38359
37637
|
async execute(args, ctx) {
|
|
38360
37638
|
const secondaryModels = await readSecondaryModelFromConfig(ctx.directory || pluginCtx.directory);
|
|
@@ -38964,7 +38242,7 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
38964
38242
|
let interviewManager;
|
|
38965
38243
|
let presetManager;
|
|
38966
38244
|
let companionManager;
|
|
38967
|
-
let councilTools;
|
|
38245
|
+
let councilTools = {};
|
|
38968
38246
|
let cancelTaskTools;
|
|
38969
38247
|
let acpRunTools;
|
|
38970
38248
|
let webfetch;
|
|
@@ -39011,7 +38289,7 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
39011
38289
|
startAvailabilityCheck(multiplexerConfig);
|
|
39012
38290
|
}
|
|
39013
38291
|
depthTracker = new SubagentDepthTracker;
|
|
39014
|
-
councilTools =
|
|
38292
|
+
councilTools = {};
|
|
39015
38293
|
mcps = createBuiltinMcps(config.disabled_mcps, config.websearch);
|
|
39016
38294
|
acpRunTools = Object.keys(config.acpAgents ?? {}).length > 0 ? { acp_run: createAcpRunTool(config.acpAgents) } : {};
|
|
39017
38295
|
webfetch = createWebfetchTool(ctx);
|
|
@@ -39310,7 +38588,7 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
39310
38588
|
const tuiAgentModels = {};
|
|
39311
38589
|
const tuiAgentVariants = {};
|
|
39312
38590
|
for (const agentDef of agentDefs) {
|
|
39313
|
-
if (agentDef.name === "councillor")
|
|
38591
|
+
if (agentDef.name === "councillor" || agentDef.name === "council")
|
|
39314
38592
|
continue;
|
|
39315
38593
|
const entry = configAgent[agentDef.name];
|
|
39316
38594
|
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;
|