opencode-swarm 4.2.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -13575,12 +13575,27 @@ var SwarmConfigSchema = exports_external.object({
13575
13575
  name: exports_external.string().optional(),
13576
13576
  agents: exports_external.record(exports_external.string(), AgentOverrideConfigSchema).optional()
13577
13577
  });
13578
+ var HooksConfigSchema = exports_external.object({
13579
+ system_enhancer: exports_external.boolean().default(true),
13580
+ compaction: exports_external.boolean().default(true),
13581
+ agent_activity: exports_external.boolean().default(true),
13582
+ delegation_tracker: exports_external.boolean().default(false),
13583
+ agent_awareness_max_chars: exports_external.number().min(50).max(2000).default(300)
13584
+ });
13585
+ var ContextBudgetConfigSchema = exports_external.object({
13586
+ enabled: exports_external.boolean().default(true),
13587
+ warn_threshold: exports_external.number().min(0).max(1).default(0.7),
13588
+ critical_threshold: exports_external.number().min(0).max(1).default(0.9),
13589
+ model_limits: exports_external.record(exports_external.string(), exports_external.number().min(1000)).default({ default: 128000 })
13590
+ });
13578
13591
  var PluginConfigSchema = exports_external.object({
13579
13592
  agents: exports_external.record(exports_external.string(), AgentOverrideConfigSchema).optional(),
13580
13593
  swarms: exports_external.record(exports_external.string(), SwarmConfigSchema).optional(),
13581
13594
  max_iterations: exports_external.number().min(1).max(10).default(5),
13582
13595
  qa_retry_limit: exports_external.number().min(1).max(10).default(3),
13583
- inject_phase_reminders: exports_external.boolean().default(true)
13596
+ inject_phase_reminders: exports_external.boolean().default(true),
13597
+ hooks: HooksConfigSchema.optional(),
13598
+ context_budget: ContextBudgetConfigSchema.optional()
13584
13599
  });
13585
13600
  // src/config/loader.ts
13586
13601
  import * as fs from "fs";
@@ -14328,6 +14343,577 @@ function getAgentConfigs(config2) {
14328
14343
  }));
14329
14344
  }
14330
14345
 
14346
+ // src/commands/agents.ts
14347
+ function handleAgentsCommand(agents) {
14348
+ const entries = Object.entries(agents);
14349
+ if (entries.length === 0) {
14350
+ return "No agents registered.";
14351
+ }
14352
+ const lines = ["## Registered Agents", ""];
14353
+ for (const [key, agent] of entries) {
14354
+ const model = agent.config.model || "default";
14355
+ const temp = agent.config.temperature !== undefined ? agent.config.temperature.toString() : "default";
14356
+ const tools = agent.config.tools || {};
14357
+ const isReadOnly = tools.write === false || tools.edit === false;
14358
+ const access = isReadOnly ? "\uD83D\uDD12 read-only" : "\u270F\uFE0F read-write";
14359
+ const desc = agent.description || agent.config.description || "";
14360
+ lines.push(`- **${key}** | model: \`${model}\` | temp: ${temp} | ${access}`);
14361
+ if (desc) {
14362
+ lines.push(` ${desc}`);
14363
+ }
14364
+ }
14365
+ return lines.join(`
14366
+ `);
14367
+ }
14368
+
14369
+ // src/utils/logger.ts
14370
+ var DEBUG = process.env.OPENCODE_SWARM_DEBUG === "1";
14371
+ function log(message, data) {
14372
+ if (!DEBUG)
14373
+ return;
14374
+ const timestamp = new Date().toISOString();
14375
+ if (data !== undefined) {
14376
+ console.log(`[opencode-swarm ${timestamp}] ${message}`, data);
14377
+ } else {
14378
+ console.log(`[opencode-swarm ${timestamp}] ${message}`);
14379
+ }
14380
+ }
14381
+ function warn(message, data) {
14382
+ const timestamp = new Date().toISOString();
14383
+ if (data !== undefined) {
14384
+ console.warn(`[opencode-swarm ${timestamp}] WARN: ${message}`, data);
14385
+ } else {
14386
+ console.warn(`[opencode-swarm ${timestamp}] WARN: ${message}`);
14387
+ }
14388
+ }
14389
+ // src/hooks/utils.ts
14390
+ function safeHook(fn) {
14391
+ return async (input, output) => {
14392
+ try {
14393
+ await fn(input, output);
14394
+ } catch (_error) {
14395
+ const functionName = fn.name || "unknown";
14396
+ warn(`Hook function '${functionName}' failed:`, _error);
14397
+ }
14398
+ };
14399
+ }
14400
+ function composeHandlers(...fns) {
14401
+ if (fns.length === 0) {
14402
+ return async () => {};
14403
+ }
14404
+ return async (input, output) => {
14405
+ for (const fn of fns) {
14406
+ const safeFn = safeHook(fn);
14407
+ await safeFn(input, output);
14408
+ }
14409
+ };
14410
+ }
14411
+ async function readSwarmFileAsync(directory, filename) {
14412
+ const path2 = `${directory}/.swarm/${filename}`;
14413
+ try {
14414
+ const file2 = Bun.file(path2);
14415
+ const content = await file2.text();
14416
+ return content;
14417
+ } catch {
14418
+ return null;
14419
+ }
14420
+ }
14421
+ function estimateTokens(text) {
14422
+ if (!text) {
14423
+ return 0;
14424
+ }
14425
+ return Math.ceil(text.length * 0.33);
14426
+ }
14427
+
14428
+ // src/commands/plan.ts
14429
+ async function handlePlanCommand(directory, args) {
14430
+ const planContent = await readSwarmFileAsync(directory, "plan.md");
14431
+ if (!planContent) {
14432
+ return "No active swarm plan found.";
14433
+ }
14434
+ if (args.length === 0) {
14435
+ return planContent;
14436
+ }
14437
+ const phaseNum = parseInt(args[0], 10);
14438
+ if (Number.isNaN(phaseNum)) {
14439
+ return planContent;
14440
+ }
14441
+ const lines = planContent.split(`
14442
+ `);
14443
+ const phaseLines = [];
14444
+ let inTargetPhase = false;
14445
+ for (const line of lines) {
14446
+ const phaseMatch = line.match(/^## Phase (\d+)/);
14447
+ if (phaseMatch) {
14448
+ const num = parseInt(phaseMatch[1], 10);
14449
+ if (num === phaseNum) {
14450
+ inTargetPhase = true;
14451
+ phaseLines.push(line);
14452
+ continue;
14453
+ } else if (inTargetPhase) {
14454
+ break;
14455
+ }
14456
+ }
14457
+ if (inTargetPhase && line.trim() === "---" && phaseLines.length > 1) {
14458
+ break;
14459
+ }
14460
+ if (inTargetPhase) {
14461
+ phaseLines.push(line);
14462
+ }
14463
+ }
14464
+ if (phaseLines.length === 0) {
14465
+ return `Phase ${phaseNum} not found in plan.`;
14466
+ }
14467
+ return phaseLines.join(`
14468
+ `).trim();
14469
+ }
14470
+
14471
+ // src/hooks/extractors.ts
14472
+ function extractCurrentPhase(planContent) {
14473
+ if (!planContent) {
14474
+ return null;
14475
+ }
14476
+ const lines = planContent.split(`
14477
+ `);
14478
+ for (let i = 0;i < Math.min(20, lines.length); i++) {
14479
+ const line = lines[i].trim();
14480
+ const progressMatch = line.match(/^## Phase (\d+):?\s*(.*?)\s*\[IN PROGRESS\]/i);
14481
+ if (progressMatch) {
14482
+ const phaseNum = progressMatch[1];
14483
+ const description = progressMatch[2]?.trim() || "";
14484
+ return `Phase ${phaseNum}: ${description} [IN PROGRESS]`;
14485
+ }
14486
+ }
14487
+ for (let i = 0;i < Math.min(3, lines.length); i++) {
14488
+ const line = lines[i].trim();
14489
+ const phaseMatch = line.match(/Phase:\s*(\d+)/i);
14490
+ if (phaseMatch) {
14491
+ const phaseNum = phaseMatch[1];
14492
+ return `Phase ${phaseNum} [PENDING]`;
14493
+ }
14494
+ }
14495
+ return null;
14496
+ }
14497
+ function extractCurrentTask(planContent) {
14498
+ if (!planContent) {
14499
+ return null;
14500
+ }
14501
+ const lines = planContent.split(`
14502
+ `);
14503
+ let inCurrentPhase = false;
14504
+ for (const line of lines) {
14505
+ if (line.startsWith("## ") && /\[IN PROGRESS\]/i.test(line)) {
14506
+ inCurrentPhase = true;
14507
+ continue;
14508
+ }
14509
+ if (inCurrentPhase) {
14510
+ if (line.startsWith("## ") || line.trim() === "---") {
14511
+ break;
14512
+ }
14513
+ if (line.trim().startsWith("- [ ]")) {
14514
+ return line.trim();
14515
+ }
14516
+ }
14517
+ }
14518
+ return null;
14519
+ }
14520
+ function extractDecisions(contextContent, maxChars = 500) {
14521
+ if (!contextContent) {
14522
+ return null;
14523
+ }
14524
+ const lines = contextContent.split(`
14525
+ `);
14526
+ let decisionsText = "";
14527
+ let inDecisionsSection = false;
14528
+ for (const line of lines) {
14529
+ if (line.trim() === "## Decisions") {
14530
+ inDecisionsSection = true;
14531
+ continue;
14532
+ }
14533
+ if (inDecisionsSection) {
14534
+ if (line.startsWith("## ")) {
14535
+ break;
14536
+ }
14537
+ if (line.startsWith("- ")) {
14538
+ decisionsText += `${line}
14539
+ `;
14540
+ }
14541
+ }
14542
+ }
14543
+ if (!decisionsText.trim()) {
14544
+ return null;
14545
+ }
14546
+ const trimmed = decisionsText.trim();
14547
+ if (trimmed.length <= maxChars) {
14548
+ return trimmed;
14549
+ }
14550
+ return `${trimmed.slice(0, maxChars)}...`;
14551
+ }
14552
+ function extractIncompleteTasks(planContent, maxChars = 500) {
14553
+ if (!planContent) {
14554
+ return null;
14555
+ }
14556
+ const lines = planContent.split(`
14557
+ `);
14558
+ let tasksText = "";
14559
+ let inCurrentPhase = false;
14560
+ for (const line of lines) {
14561
+ if (line.startsWith("## ") && /\[IN PROGRESS\]/i.test(line)) {
14562
+ inCurrentPhase = true;
14563
+ continue;
14564
+ }
14565
+ if (inCurrentPhase) {
14566
+ if (line.startsWith("## ") || line.trim() === "---") {
14567
+ break;
14568
+ }
14569
+ if (line.trim().startsWith("- [ ]")) {
14570
+ tasksText += `${line.trim()}
14571
+ `;
14572
+ }
14573
+ }
14574
+ }
14575
+ if (!tasksText.trim()) {
14576
+ return null;
14577
+ }
14578
+ const trimmed = tasksText.trim();
14579
+ if (trimmed.length <= maxChars) {
14580
+ return trimmed;
14581
+ }
14582
+ return `${trimmed.slice(0, maxChars)}...`;
14583
+ }
14584
+ function extractPatterns(contextContent, maxChars = 500) {
14585
+ if (!contextContent) {
14586
+ return null;
14587
+ }
14588
+ const lines = contextContent.split(`
14589
+ `);
14590
+ let patternsText = "";
14591
+ let inPatternsSection = false;
14592
+ for (const line of lines) {
14593
+ if (line.trim() === "## Patterns") {
14594
+ inPatternsSection = true;
14595
+ continue;
14596
+ }
14597
+ if (inPatternsSection) {
14598
+ if (line.startsWith("## ")) {
14599
+ break;
14600
+ }
14601
+ if (line.startsWith("- ")) {
14602
+ patternsText += `${line}
14603
+ `;
14604
+ }
14605
+ }
14606
+ }
14607
+ if (!patternsText.trim()) {
14608
+ return null;
14609
+ }
14610
+ const trimmed = patternsText.trim();
14611
+ if (trimmed.length <= maxChars) {
14612
+ return trimmed;
14613
+ }
14614
+ return `${trimmed.slice(0, maxChars)}...`;
14615
+ }
14616
+
14617
+ // src/commands/status.ts
14618
+ async function handleStatusCommand(directory, agents) {
14619
+ const planContent = await readSwarmFileAsync(directory, "plan.md");
14620
+ if (!planContent) {
14621
+ return "No active swarm plan found.";
14622
+ }
14623
+ const currentPhase = extractCurrentPhase(planContent) || "Unknown";
14624
+ const completedTasks = (planContent.match(/^- \[x\]/gm) || []).length;
14625
+ const incompleteTasks = (planContent.match(/^- \[ \]/gm) || []).length;
14626
+ const totalTasks = completedTasks + incompleteTasks;
14627
+ const agentCount = Object.keys(agents).length;
14628
+ const lines = [
14629
+ "## Swarm Status",
14630
+ "",
14631
+ `**Current Phase**: ${currentPhase}`,
14632
+ `**Tasks**: ${completedTasks}/${totalTasks} complete`,
14633
+ `**Agents**: ${agentCount} registered`
14634
+ ];
14635
+ return lines.join(`
14636
+ `);
14637
+ }
14638
+
14639
+ // src/commands/index.ts
14640
+ var HELP_TEXT = [
14641
+ "## Swarm Commands",
14642
+ "",
14643
+ "- `/swarm status` \u2014 Show current swarm state",
14644
+ "- `/swarm plan [phase]` \u2014 Show plan (optionally filter by phase number)",
14645
+ "- `/swarm agents` \u2014 List registered agents"
14646
+ ].join(`
14647
+ `);
14648
+ function createSwarmCommandHandler(directory, agents) {
14649
+ return async (input, output) => {
14650
+ if (input.command !== "swarm") {
14651
+ return;
14652
+ }
14653
+ const tokens = input.arguments.trim().split(/\s+/).filter(Boolean);
14654
+ const [subcommand, ...args] = tokens;
14655
+ let text;
14656
+ switch (subcommand) {
14657
+ case "status":
14658
+ text = await handleStatusCommand(directory, agents);
14659
+ break;
14660
+ case "plan":
14661
+ text = await handlePlanCommand(directory, args);
14662
+ break;
14663
+ case "agents":
14664
+ text = handleAgentsCommand(agents);
14665
+ break;
14666
+ default:
14667
+ text = HELP_TEXT;
14668
+ break;
14669
+ }
14670
+ output.parts = [
14671
+ { type: "text", text }
14672
+ ];
14673
+ };
14674
+ }
14675
+
14676
+ // src/state.ts
14677
+ var swarmState = {
14678
+ activeToolCalls: new Map,
14679
+ toolAggregates: new Map,
14680
+ activeAgent: new Map,
14681
+ delegationChains: new Map,
14682
+ pendingEvents: 0
14683
+ };
14684
+
14685
+ // src/hooks/agent-activity.ts
14686
+ function createAgentActivityHooks(config2, directory) {
14687
+ if (config2.hooks?.agent_activity === false) {
14688
+ return {
14689
+ toolBefore: async () => {},
14690
+ toolAfter: async () => {}
14691
+ };
14692
+ }
14693
+ return {
14694
+ toolBefore: async (input) => {
14695
+ swarmState.activeToolCalls.set(input.callID, {
14696
+ tool: input.tool,
14697
+ sessionID: input.sessionID,
14698
+ callID: input.callID,
14699
+ startTime: Date.now()
14700
+ });
14701
+ },
14702
+ toolAfter: async (input, output) => {
14703
+ const entry = swarmState.activeToolCalls.get(input.callID);
14704
+ if (!entry)
14705
+ return;
14706
+ swarmState.activeToolCalls.delete(input.callID);
14707
+ const duration3 = Date.now() - entry.startTime;
14708
+ const success2 = output.output != null;
14709
+ const key = entry.tool;
14710
+ const existing = swarmState.toolAggregates.get(key) ?? {
14711
+ tool: key,
14712
+ count: 0,
14713
+ successCount: 0,
14714
+ failureCount: 0,
14715
+ totalDuration: 0
14716
+ };
14717
+ existing.count++;
14718
+ if (success2)
14719
+ existing.successCount++;
14720
+ else
14721
+ existing.failureCount++;
14722
+ existing.totalDuration += duration3;
14723
+ swarmState.toolAggregates.set(key, existing);
14724
+ swarmState.pendingEvents++;
14725
+ if (swarmState.pendingEvents >= 20) {
14726
+ flushActivityToFile(directory).catch((err) => warn("Agent activity flush trigger failed:", err));
14727
+ }
14728
+ }
14729
+ };
14730
+ }
14731
+ var flushPromise = null;
14732
+ async function flushActivityToFile(directory) {
14733
+ if (flushPromise) {
14734
+ flushPromise = flushPromise.then(() => doFlush(directory)).catch((err) => {
14735
+ warn("Queued agent activity flush failed:", err);
14736
+ });
14737
+ return flushPromise;
14738
+ }
14739
+ flushPromise = doFlush(directory);
14740
+ try {
14741
+ await flushPromise;
14742
+ } finally {
14743
+ flushPromise = null;
14744
+ }
14745
+ }
14746
+ async function doFlush(directory) {
14747
+ try {
14748
+ const content = await readSwarmFileAsync(directory, "context.md");
14749
+ const existing = content ?? "";
14750
+ const activitySection = renderActivitySection();
14751
+ const updated = replaceOrAppendSection(existing, "## Agent Activity", activitySection);
14752
+ const flushedCount = swarmState.pendingEvents;
14753
+ const path2 = `${directory}/.swarm/context.md`;
14754
+ await Bun.write(path2, updated);
14755
+ swarmState.pendingEvents = Math.max(0, swarmState.pendingEvents - flushedCount);
14756
+ } catch (error49) {
14757
+ warn("Agent activity flush failed:", error49);
14758
+ }
14759
+ }
14760
+ function renderActivitySection() {
14761
+ const lines = ["## Agent Activity", ""];
14762
+ if (swarmState.toolAggregates.size === 0) {
14763
+ lines.push("No tool activity recorded yet.");
14764
+ return lines.join(`
14765
+ `);
14766
+ }
14767
+ lines.push("| Tool | Calls | Success | Failed | Avg Duration |");
14768
+ lines.push("|------|-------|---------|--------|--------------|");
14769
+ const sorted = [...swarmState.toolAggregates.values()].sort((a, b) => b.count - a.count);
14770
+ for (const agg of sorted) {
14771
+ const avgDuration = agg.count > 0 ? Math.round(agg.totalDuration / agg.count) : 0;
14772
+ lines.push(`| ${agg.tool} | ${agg.count} | ${agg.successCount} | ${agg.failureCount} | ${avgDuration}ms |`);
14773
+ }
14774
+ return lines.join(`
14775
+ `);
14776
+ }
14777
+ function replaceOrAppendSection(content, heading, newSection) {
14778
+ const headingIndex = content.indexOf(heading);
14779
+ if (headingIndex === -1) {
14780
+ return content.trimEnd() + `
14781
+
14782
+ ` + newSection + `
14783
+ `;
14784
+ }
14785
+ const afterHeading = content.substring(headingIndex + heading.length);
14786
+ const nextHeadingMatch = afterHeading.match(/\n## /);
14787
+ if (nextHeadingMatch && nextHeadingMatch.index !== undefined) {
14788
+ const endIndex = headingIndex + heading.length + nextHeadingMatch.index;
14789
+ return content.substring(0, headingIndex) + newSection + `
14790
+ ` + content.substring(endIndex + 1);
14791
+ }
14792
+ return content.substring(0, headingIndex) + newSection + `
14793
+ `;
14794
+ }
14795
+ // src/hooks/compaction-customizer.ts
14796
+ function createCompactionCustomizerHook(config2, directory) {
14797
+ const enabled = config2.hooks?.compaction !== false;
14798
+ if (!enabled) {
14799
+ return {};
14800
+ }
14801
+ return {
14802
+ "experimental.session.compacting": safeHook(async (_input, output) => {
14803
+ const planContent = await readSwarmFileAsync(directory, "plan.md");
14804
+ const contextContent = await readSwarmFileAsync(directory, "context.md");
14805
+ if (planContent) {
14806
+ const currentPhase = extractCurrentPhase(planContent);
14807
+ if (currentPhase) {
14808
+ output.context.push(`[SWARM PLAN] ${currentPhase}`);
14809
+ }
14810
+ }
14811
+ if (contextContent) {
14812
+ const decisionsSummary = extractDecisions(contextContent);
14813
+ if (decisionsSummary) {
14814
+ output.context.push(`[SWARM DECISIONS] ${decisionsSummary}`);
14815
+ }
14816
+ }
14817
+ if (planContent) {
14818
+ const incompleteTasks = extractIncompleteTasks(planContent);
14819
+ if (incompleteTasks) {
14820
+ output.context.push(`[SWARM TASKS] ${incompleteTasks}`);
14821
+ }
14822
+ }
14823
+ if (contextContent) {
14824
+ const patterns = extractPatterns(contextContent);
14825
+ if (patterns) {
14826
+ output.context.push(`[SWARM PATTERNS] ${patterns}`);
14827
+ }
14828
+ }
14829
+ })
14830
+ };
14831
+ }
14832
+ // src/hooks/context-budget.ts
14833
+ function createContextBudgetHandler(config2) {
14834
+ const enabled = config2.context_budget?.enabled !== false;
14835
+ if (!enabled) {
14836
+ return async (_input, _output) => {};
14837
+ }
14838
+ const warnThreshold = config2.context_budget?.warn_threshold ?? 0.7;
14839
+ const criticalThreshold = config2.context_budget?.critical_threshold ?? 0.9;
14840
+ const modelLimits = config2.context_budget?.model_limits ?? {
14841
+ default: 128000
14842
+ };
14843
+ const modelLimit = modelLimits.default ?? 128000;
14844
+ return async (_input, output) => {
14845
+ const messages = output?.messages;
14846
+ if (!messages || messages.length === 0)
14847
+ return;
14848
+ let totalTokens = 0;
14849
+ for (const message of messages) {
14850
+ if (!message?.parts)
14851
+ continue;
14852
+ for (const part of message.parts) {
14853
+ if (part?.type === "text" && part.text) {
14854
+ totalTokens += estimateTokens(part.text);
14855
+ }
14856
+ }
14857
+ }
14858
+ const usagePercent = totalTokens / modelLimit;
14859
+ let lastUserMessageIndex = -1;
14860
+ for (let i = messages.length - 1;i >= 0; i--) {
14861
+ if (messages[i]?.info?.role === "user") {
14862
+ lastUserMessageIndex = i;
14863
+ break;
14864
+ }
14865
+ }
14866
+ if (lastUserMessageIndex === -1)
14867
+ return;
14868
+ const lastUserMessage = messages[lastUserMessageIndex];
14869
+ if (!lastUserMessage?.parts)
14870
+ return;
14871
+ const agent = lastUserMessage.info?.agent;
14872
+ if (agent && agent !== "architect")
14873
+ return;
14874
+ const textPartIndex = lastUserMessage.parts.findIndex((p) => p?.type === "text" && p.text !== undefined);
14875
+ if (textPartIndex === -1)
14876
+ return;
14877
+ const pct = Math.round(usagePercent * 100);
14878
+ let warningText = "";
14879
+ if (usagePercent > criticalThreshold) {
14880
+ warningText = `[CONTEXT CRITICAL: ~${pct}% of context budget used. Offload details to .swarm/context.md immediately]
14881
+
14882
+ `;
14883
+ } else if (usagePercent > warnThreshold) {
14884
+ warningText = `[CONTEXT WARNING: ~${pct}% of context budget used. Consider summarizing to .swarm/context.md]
14885
+
14886
+ `;
14887
+ }
14888
+ if (warningText) {
14889
+ const originalText = lastUserMessage.parts[textPartIndex].text ?? "";
14890
+ lastUserMessage.parts[textPartIndex].text = `${warningText}${originalText}`;
14891
+ }
14892
+ };
14893
+ }
14894
+ // src/hooks/delegation-tracker.ts
14895
+ function createDelegationTrackerHook(config2) {
14896
+ return async (input, _output) => {
14897
+ if (!input.agent || input.agent === "") {
14898
+ return;
14899
+ }
14900
+ const previousAgent = swarmState.activeAgent.get(input.sessionID);
14901
+ swarmState.activeAgent.set(input.sessionID, input.agent);
14902
+ if (config2.hooks?.delegation_tracker === true && previousAgent && previousAgent !== input.agent) {
14903
+ const entry = {
14904
+ from: previousAgent,
14905
+ to: input.agent,
14906
+ timestamp: Date.now()
14907
+ };
14908
+ if (!swarmState.delegationChains.has(input.sessionID)) {
14909
+ swarmState.delegationChains.set(input.sessionID, []);
14910
+ }
14911
+ const chain = swarmState.delegationChains.get(input.sessionID);
14912
+ chain?.push(entry);
14913
+ swarmState.pendingEvents++;
14914
+ }
14915
+ };
14916
+ }
14331
14917
  // src/hooks/pipeline-tracker.ts
14332
14918
  var PHASE_REMINDER = `<swarm_reminder>
14333
14919
  \u26A0\uFE0F ARCHITECT WORKFLOW REMINDER:
@@ -14345,44 +14931,116 @@ DELEGATION RULES:
14345
14931
  - Always wait for response before next delegation
14346
14932
  </swarm_reminder>`;
14347
14933
  function createPipelineTrackerHook(config2) {
14348
- const enabled = config2.inject_phase_reminders === true;
14934
+ const enabled = config2.inject_phase_reminders !== false;
14349
14935
  if (!enabled) {
14350
14936
  return {};
14351
14937
  }
14352
14938
  return {
14353
- "experimental.chat.messages.transform": async (_input, output) => {
14354
- try {
14355
- const messages = output?.messages;
14356
- if (!messages || messages.length === 0)
14357
- return;
14358
- let lastUserMessageIndex = -1;
14359
- for (let i = messages.length - 1;i >= 0; i--) {
14360
- if (messages[i]?.info?.role === "user") {
14361
- lastUserMessageIndex = i;
14362
- break;
14363
- }
14939
+ "experimental.chat.messages.transform": safeHook(async (_input, output) => {
14940
+ const messages = output?.messages;
14941
+ if (!messages || messages.length === 0)
14942
+ return;
14943
+ let lastUserMessageIndex = -1;
14944
+ for (let i = messages.length - 1;i >= 0; i--) {
14945
+ if (messages[i]?.info?.role === "user") {
14946
+ lastUserMessageIndex = i;
14947
+ break;
14364
14948
  }
14365
- if (lastUserMessageIndex === -1)
14366
- return;
14367
- const lastUserMessage = messages[lastUserMessageIndex];
14368
- if (!lastUserMessage?.parts)
14369
- return;
14370
- const agent = lastUserMessage.info?.agent;
14371
- if (agent && agent !== "architect")
14372
- return;
14373
- const textPartIndex = lastUserMessage.parts.findIndex((p) => p?.type === "text" && p.text !== undefined);
14374
- if (textPartIndex === -1)
14375
- return;
14376
- const originalText = lastUserMessage.parts[textPartIndex].text ?? "";
14377
- lastUserMessage.parts[textPartIndex].text = `${PHASE_REMINDER}
14949
+ }
14950
+ if (lastUserMessageIndex === -1)
14951
+ return;
14952
+ const lastUserMessage = messages[lastUserMessageIndex];
14953
+ if (!lastUserMessage?.parts)
14954
+ return;
14955
+ const agent = lastUserMessage.info?.agent;
14956
+ if (agent && agent !== "architect")
14957
+ return;
14958
+ const textPartIndex = lastUserMessage.parts.findIndex((p) => p?.type === "text" && p.text !== undefined);
14959
+ if (textPartIndex === -1)
14960
+ return;
14961
+ const originalText = lastUserMessage.parts[textPartIndex].text ?? "";
14962
+ lastUserMessage.parts[textPartIndex].text = `${PHASE_REMINDER}
14378
14963
 
14379
14964
  ---
14380
14965
 
14381
14966
  ${originalText}`;
14382
- } catch {}
14383
- }
14967
+ })
14968
+ };
14969
+ }
14970
+ // src/hooks/system-enhancer.ts
14971
+ function createSystemEnhancerHook(config2, directory) {
14972
+ const enabled = config2.hooks?.system_enhancer !== false;
14973
+ if (!enabled) {
14974
+ return {};
14975
+ }
14976
+ return {
14977
+ "experimental.chat.system.transform": safeHook(async (_input, output) => {
14978
+ try {
14979
+ const planContent = await readSwarmFileAsync(directory, "plan.md");
14980
+ const contextContent = await readSwarmFileAsync(directory, "context.md");
14981
+ if (planContent) {
14982
+ const currentPhase = extractCurrentPhase(planContent);
14983
+ if (currentPhase) {
14984
+ output.system.push(`[SWARM CONTEXT] Current phase: ${currentPhase}`);
14985
+ }
14986
+ const currentTask = extractCurrentTask(planContent);
14987
+ if (currentTask) {
14988
+ output.system.push(`[SWARM CONTEXT] Current task: ${currentTask}`);
14989
+ }
14990
+ }
14991
+ if (contextContent) {
14992
+ const decisions = extractDecisions(contextContent, 200);
14993
+ if (decisions) {
14994
+ output.system.push(`[SWARM CONTEXT] Key decisions: ${decisions}`);
14995
+ }
14996
+ if (config2.hooks?.agent_activity !== false && _input.sessionID) {
14997
+ const activeAgent = swarmState.activeAgent.get(_input.sessionID);
14998
+ if (activeAgent) {
14999
+ const agentContext = extractAgentContext(contextContent, activeAgent, config2.hooks?.agent_awareness_max_chars ?? 300);
15000
+ if (agentContext) {
15001
+ output.system.push(`[SWARM AGENT CONTEXT] ${agentContext}`);
15002
+ }
15003
+ }
15004
+ }
15005
+ }
15006
+ } catch (error49) {
15007
+ warn("System enhancer failed:", error49);
15008
+ }
15009
+ })
14384
15010
  };
14385
15011
  }
15012
+ function extractAgentContext(contextContent, activeAgent, maxChars) {
15013
+ const activityMatch = contextContent.match(/## Agent Activity\n([\s\S]*?)(?=\n## |$)/);
15014
+ if (!activityMatch)
15015
+ return null;
15016
+ const activitySection = activityMatch[1].trim();
15017
+ if (!activitySection || activitySection === "No tool activity recorded yet.")
15018
+ return null;
15019
+ const agentName = activeAgent.replace(/^(?:paid|local|mega|default)_/, "");
15020
+ let contextSummary;
15021
+ switch (agentName) {
15022
+ case "coder":
15023
+ contextSummary = `Recent tool activity for review context:
15024
+ ${activitySection}`;
15025
+ break;
15026
+ case "reviewer":
15027
+ contextSummary = `Tool usage to review:
15028
+ ${activitySection}`;
15029
+ break;
15030
+ case "test_engineer":
15031
+ contextSummary = `Tool activity for test context:
15032
+ ${activitySection}`;
15033
+ break;
15034
+ default:
15035
+ contextSummary = `Agent activity summary:
15036
+ ${activitySection}`;
15037
+ break;
15038
+ }
15039
+ if (contextSummary.length > maxChars) {
15040
+ return contextSummary.substring(0, maxChars - 3) + "...";
15041
+ }
15042
+ return contextSummary;
15043
+ }
14386
15044
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/classic/external.js
14387
15045
  var exports_external2 = {};
14388
15046
  __export(exports_external2, {
@@ -15592,10 +16250,10 @@ var initializer3 = (inst, def) => {
15592
16250
  };
15593
16251
  var $ZodError2 = $constructor2("$ZodError", initializer3);
15594
16252
  var $ZodRealError2 = $constructor2("$ZodError", initializer3, { Parent: Error });
15595
- function flattenError2(error48, mapper = (issue3) => issue3.message) {
16253
+ function flattenError2(error49, mapper = (issue3) => issue3.message) {
15596
16254
  const fieldErrors = {};
15597
16255
  const formErrors = [];
15598
- for (const sub of error48.issues) {
16256
+ for (const sub of error49.issues) {
15599
16257
  if (sub.path.length > 0) {
15600
16258
  fieldErrors[sub.path[0]] = fieldErrors[sub.path[0]] || [];
15601
16259
  fieldErrors[sub.path[0]].push(mapper(sub));
@@ -15605,13 +16263,13 @@ function flattenError2(error48, mapper = (issue3) => issue3.message) {
15605
16263
  }
15606
16264
  return { formErrors, fieldErrors };
15607
16265
  }
15608
- function formatError2(error48, _mapper) {
16266
+ function formatError2(error49, _mapper) {
15609
16267
  const mapper = _mapper || function(issue3) {
15610
16268
  return issue3.message;
15611
16269
  };
15612
16270
  const fieldErrors = { _errors: [] };
15613
- const processError = (error49) => {
15614
- for (const issue3 of error49.issues) {
16271
+ const processError = (error50) => {
16272
+ for (const issue3 of error50.issues) {
15615
16273
  if (issue3.code === "invalid_union" && issue3.errors.length) {
15616
16274
  issue3.errors.map((issues) => processError({ issues }));
15617
16275
  } else if (issue3.code === "invalid_key") {
@@ -15638,17 +16296,17 @@ function formatError2(error48, _mapper) {
15638
16296
  }
15639
16297
  }
15640
16298
  };
15641
- processError(error48);
16299
+ processError(error49);
15642
16300
  return fieldErrors;
15643
16301
  }
15644
- function treeifyError2(error48, _mapper) {
16302
+ function treeifyError2(error49, _mapper) {
15645
16303
  const mapper = _mapper || function(issue3) {
15646
16304
  return issue3.message;
15647
16305
  };
15648
16306
  const result = { errors: [] };
15649
- const processError = (error49, path2 = []) => {
16307
+ const processError = (error50, path2 = []) => {
15650
16308
  var _a2, _b;
15651
- for (const issue3 of error49.issues) {
16309
+ for (const issue3 of error50.issues) {
15652
16310
  if (issue3.code === "invalid_union" && issue3.errors.length) {
15653
16311
  issue3.errors.map((issues) => processError({ issues }, issue3.path));
15654
16312
  } else if (issue3.code === "invalid_key") {
@@ -15683,7 +16341,7 @@ function treeifyError2(error48, _mapper) {
15683
16341
  }
15684
16342
  }
15685
16343
  };
15686
- processError(error48);
16344
+ processError(error49);
15687
16345
  return result;
15688
16346
  }
15689
16347
  function toDotPath2(_path) {
@@ -15704,9 +16362,9 @@ function toDotPath2(_path) {
15704
16362
  }
15705
16363
  return segs.join("");
15706
16364
  }
15707
- function prettifyError2(error48) {
16365
+ function prettifyError2(error49) {
15708
16366
  const lines = [];
15709
- const issues = [...error48.issues].sort((a, b) => (a.path ?? []).length - (b.path ?? []).length);
16367
+ const issues = [...error49.issues].sort((a, b) => (a.path ?? []).length - (b.path ?? []).length);
15710
16368
  for (const issue3 of issues) {
15711
16369
  lines.push(`\u2716 ${issue3.message}`);
15712
16370
  if (issue3.path?.length)
@@ -18416,7 +19074,7 @@ __export(exports_locales2, {
18416
19074
  });
18417
19075
 
18418
19076
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/ar.js
18419
- var error48 = () => {
19077
+ var error49 = () => {
18420
19078
  const Sizable = {
18421
19079
  string: { unit: "\u062D\u0631\u0641", verb: "\u0623\u0646 \u064A\u062D\u0648\u064A" },
18422
19080
  file: { unit: "\u0628\u0627\u064A\u062A", verb: "\u0623\u0646 \u064A\u062D\u0648\u064A" },
@@ -18528,11 +19186,11 @@ var error48 = () => {
18528
19186
  };
18529
19187
  function ar_default2() {
18530
19188
  return {
18531
- localeError: error48()
19189
+ localeError: error49()
18532
19190
  };
18533
19191
  }
18534
19192
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/az.js
18535
- var error49 = () => {
19193
+ var error50 = () => {
18536
19194
  const Sizable = {
18537
19195
  string: { unit: "simvol", verb: "olmal\u0131d\u0131r" },
18538
19196
  file: { unit: "bayt", verb: "olmal\u0131d\u0131r" },
@@ -18643,7 +19301,7 @@ var error49 = () => {
18643
19301
  };
18644
19302
  function az_default2() {
18645
19303
  return {
18646
- localeError: error49()
19304
+ localeError: error50()
18647
19305
  };
18648
19306
  }
18649
19307
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/be.js
@@ -18662,7 +19320,7 @@ function getBelarusianPlural2(count, one, few, many) {
18662
19320
  }
18663
19321
  return many;
18664
19322
  }
18665
- var error50 = () => {
19323
+ var error51 = () => {
18666
19324
  const Sizable = {
18667
19325
  string: {
18668
19326
  unit: {
@@ -18807,11 +19465,11 @@ var error50 = () => {
18807
19465
  };
18808
19466
  function be_default2() {
18809
19467
  return {
18810
- localeError: error50()
19468
+ localeError: error51()
18811
19469
  };
18812
19470
  }
18813
19471
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/ca.js
18814
- var error51 = () => {
19472
+ var error52 = () => {
18815
19473
  const Sizable = {
18816
19474
  string: { unit: "car\xE0cters", verb: "contenir" },
18817
19475
  file: { unit: "bytes", verb: "contenir" },
@@ -18924,11 +19582,11 @@ var error51 = () => {
18924
19582
  };
18925
19583
  function ca_default2() {
18926
19584
  return {
18927
- localeError: error51()
19585
+ localeError: error52()
18928
19586
  };
18929
19587
  }
18930
19588
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/cs.js
18931
- var error52 = () => {
19589
+ var error53 = () => {
18932
19590
  const Sizable = {
18933
19591
  string: { unit: "znak\u016F", verb: "m\xEDt" },
18934
19592
  file: { unit: "bajt\u016F", verb: "m\xEDt" },
@@ -19059,11 +19717,11 @@ var error52 = () => {
19059
19717
  };
19060
19718
  function cs_default2() {
19061
19719
  return {
19062
- localeError: error52()
19720
+ localeError: error53()
19063
19721
  };
19064
19722
  }
19065
19723
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/da.js
19066
- var error53 = () => {
19724
+ var error54 = () => {
19067
19725
  const Sizable = {
19068
19726
  string: { unit: "tegn", verb: "havde" },
19069
19727
  file: { unit: "bytes", verb: "havde" },
@@ -19190,11 +19848,11 @@ var error53 = () => {
19190
19848
  };
19191
19849
  function da_default2() {
19192
19850
  return {
19193
- localeError: error53()
19851
+ localeError: error54()
19194
19852
  };
19195
19853
  }
19196
19854
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/de.js
19197
- var error54 = () => {
19855
+ var error55 = () => {
19198
19856
  const Sizable = {
19199
19857
  string: { unit: "Zeichen", verb: "zu haben" },
19200
19858
  file: { unit: "Bytes", verb: "zu haben" },
@@ -19306,7 +19964,7 @@ var error54 = () => {
19306
19964
  };
19307
19965
  function de_default2() {
19308
19966
  return {
19309
- localeError: error54()
19967
+ localeError: error55()
19310
19968
  };
19311
19969
  }
19312
19970
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/en.js
@@ -19330,7 +19988,7 @@ var parsedType2 = (data) => {
19330
19988
  }
19331
19989
  return t;
19332
19990
  };
19333
- var error55 = () => {
19991
+ var error56 = () => {
19334
19992
  const Sizable = {
19335
19993
  string: { unit: "characters", verb: "to have" },
19336
19994
  file: { unit: "bytes", verb: "to have" },
@@ -19423,7 +20081,7 @@ var error55 = () => {
19423
20081
  };
19424
20082
  function en_default2() {
19425
20083
  return {
19426
- localeError: error55()
20084
+ localeError: error56()
19427
20085
  };
19428
20086
  }
19429
20087
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/eo.js
@@ -19447,7 +20105,7 @@ var parsedType3 = (data) => {
19447
20105
  }
19448
20106
  return t;
19449
20107
  };
19450
- var error56 = () => {
20108
+ var error57 = () => {
19451
20109
  const Sizable = {
19452
20110
  string: { unit: "karaktrojn", verb: "havi" },
19453
20111
  file: { unit: "bajtojn", verb: "havi" },
@@ -19539,11 +20197,11 @@ var error56 = () => {
19539
20197
  };
19540
20198
  function eo_default2() {
19541
20199
  return {
19542
- localeError: error56()
20200
+ localeError: error57()
19543
20201
  };
19544
20202
  }
19545
20203
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/es.js
19546
- var error57 = () => {
20204
+ var error58 = () => {
19547
20205
  const Sizable = {
19548
20206
  string: { unit: "caracteres", verb: "tener" },
19549
20207
  file: { unit: "bytes", verb: "tener" },
@@ -19687,11 +20345,11 @@ var error57 = () => {
19687
20345
  };
19688
20346
  function es_default2() {
19689
20347
  return {
19690
- localeError: error57()
20348
+ localeError: error58()
19691
20349
  };
19692
20350
  }
19693
20351
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/fa.js
19694
- var error58 = () => {
20352
+ var error59 = () => {
19695
20353
  const Sizable = {
19696
20354
  string: { unit: "\u06A9\u0627\u0631\u0627\u06A9\u062A\u0631", verb: "\u062F\u0627\u0634\u062A\u0647 \u0628\u0627\u0634\u062F" },
19697
20355
  file: { unit: "\u0628\u0627\u06CC\u062A", verb: "\u062F\u0627\u0634\u062A\u0647 \u0628\u0627\u0634\u062F" },
@@ -19809,11 +20467,11 @@ var error58 = () => {
19809
20467
  };
19810
20468
  function fa_default2() {
19811
20469
  return {
19812
- localeError: error58()
20470
+ localeError: error59()
19813
20471
  };
19814
20472
  }
19815
20473
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/fi.js
19816
- var error59 = () => {
20474
+ var error60 = () => {
19817
20475
  const Sizable = {
19818
20476
  string: { unit: "merkki\xE4", subject: "merkkijonon" },
19819
20477
  file: { unit: "tavua", subject: "tiedoston" },
@@ -19931,11 +20589,11 @@ var error59 = () => {
19931
20589
  };
19932
20590
  function fi_default2() {
19933
20591
  return {
19934
- localeError: error59()
20592
+ localeError: error60()
19935
20593
  };
19936
20594
  }
19937
20595
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/fr.js
19938
- var error60 = () => {
20596
+ var error61 = () => {
19939
20597
  const Sizable = {
19940
20598
  string: { unit: "caract\xE8res", verb: "avoir" },
19941
20599
  file: { unit: "octets", verb: "avoir" },
@@ -20047,11 +20705,11 @@ var error60 = () => {
20047
20705
  };
20048
20706
  function fr_default2() {
20049
20707
  return {
20050
- localeError: error60()
20708
+ localeError: error61()
20051
20709
  };
20052
20710
  }
20053
20711
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/fr-CA.js
20054
- var error61 = () => {
20712
+ var error62 = () => {
20055
20713
  const Sizable = {
20056
20714
  string: { unit: "caract\xE8res", verb: "avoir" },
20057
20715
  file: { unit: "octets", verb: "avoir" },
@@ -20164,11 +20822,11 @@ var error61 = () => {
20164
20822
  };
20165
20823
  function fr_CA_default2() {
20166
20824
  return {
20167
- localeError: error61()
20825
+ localeError: error62()
20168
20826
  };
20169
20827
  }
20170
20828
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/he.js
20171
- var error62 = () => {
20829
+ var error63 = () => {
20172
20830
  const Sizable = {
20173
20831
  string: { unit: "\u05D0\u05D5\u05EA\u05D9\u05D5\u05EA", verb: "\u05DC\u05DB\u05DC\u05D5\u05DC" },
20174
20832
  file: { unit: "\u05D1\u05D9\u05D9\u05D8\u05D9\u05DD", verb: "\u05DC\u05DB\u05DC\u05D5\u05DC" },
@@ -20280,11 +20938,11 @@ var error62 = () => {
20280
20938
  };
20281
20939
  function he_default2() {
20282
20940
  return {
20283
- localeError: error62()
20941
+ localeError: error63()
20284
20942
  };
20285
20943
  }
20286
20944
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/hu.js
20287
- var error63 = () => {
20945
+ var error64 = () => {
20288
20946
  const Sizable = {
20289
20947
  string: { unit: "karakter", verb: "legyen" },
20290
20948
  file: { unit: "byte", verb: "legyen" },
@@ -20396,11 +21054,11 @@ var error63 = () => {
20396
21054
  };
20397
21055
  function hu_default2() {
20398
21056
  return {
20399
- localeError: error63()
21057
+ localeError: error64()
20400
21058
  };
20401
21059
  }
20402
21060
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/id.js
20403
- var error64 = () => {
21061
+ var error65 = () => {
20404
21062
  const Sizable = {
20405
21063
  string: { unit: "karakter", verb: "memiliki" },
20406
21064
  file: { unit: "byte", verb: "memiliki" },
@@ -20512,7 +21170,7 @@ var error64 = () => {
20512
21170
  };
20513
21171
  function id_default2() {
20514
21172
  return {
20515
- localeError: error64()
21173
+ localeError: error65()
20516
21174
  };
20517
21175
  }
20518
21176
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/is.js
@@ -20536,7 +21194,7 @@ var parsedType4 = (data) => {
20536
21194
  }
20537
21195
  return t;
20538
21196
  };
20539
- var error65 = () => {
21197
+ var error66 = () => {
20540
21198
  const Sizable = {
20541
21199
  string: { unit: "stafi", verb: "a\xF0 hafa" },
20542
21200
  file: { unit: "b\xE6ti", verb: "a\xF0 hafa" },
@@ -20629,11 +21287,11 @@ var error65 = () => {
20629
21287
  };
20630
21288
  function is_default2() {
20631
21289
  return {
20632
- localeError: error65()
21290
+ localeError: error66()
20633
21291
  };
20634
21292
  }
20635
21293
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/it.js
20636
- var error66 = () => {
21294
+ var error67 = () => {
20637
21295
  const Sizable = {
20638
21296
  string: { unit: "caratteri", verb: "avere" },
20639
21297
  file: { unit: "byte", verb: "avere" },
@@ -20745,11 +21403,11 @@ var error66 = () => {
20745
21403
  };
20746
21404
  function it_default2() {
20747
21405
  return {
20748
- localeError: error66()
21406
+ localeError: error67()
20749
21407
  };
20750
21408
  }
20751
21409
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/ja.js
20752
- var error67 = () => {
21410
+ var error68 = () => {
20753
21411
  const Sizable = {
20754
21412
  string: { unit: "\u6587\u5B57", verb: "\u3067\u3042\u308B" },
20755
21413
  file: { unit: "\u30D0\u30A4\u30C8", verb: "\u3067\u3042\u308B" },
@@ -20860,7 +21518,7 @@ var error67 = () => {
20860
21518
  };
20861
21519
  function ja_default2() {
20862
21520
  return {
20863
- localeError: error67()
21521
+ localeError: error68()
20864
21522
  };
20865
21523
  }
20866
21524
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/ka.js
@@ -20892,7 +21550,7 @@ var parsedType5 = (data) => {
20892
21550
  };
20893
21551
  return typeMap[t] ?? t;
20894
21552
  };
20895
- var error68 = () => {
21553
+ var error69 = () => {
20896
21554
  const Sizable = {
20897
21555
  string: { unit: "\u10E1\u10D8\u10DB\u10D1\u10DD\u10DA\u10DD", verb: "\u10E3\u10DC\u10D3\u10D0 \u10E8\u10D4\u10D8\u10EA\u10D0\u10D5\u10D3\u10D4\u10E1" },
20898
21556
  file: { unit: "\u10D1\u10D0\u10D8\u10E2\u10D8", verb: "\u10E3\u10DC\u10D3\u10D0 \u10E8\u10D4\u10D8\u10EA\u10D0\u10D5\u10D3\u10D4\u10E1" },
@@ -20985,11 +21643,11 @@ var error68 = () => {
20985
21643
  };
20986
21644
  function ka_default2() {
20987
21645
  return {
20988
- localeError: error68()
21646
+ localeError: error69()
20989
21647
  };
20990
21648
  }
20991
21649
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/km.js
20992
- var error69 = () => {
21650
+ var error70 = () => {
20993
21651
  const Sizable = {
20994
21652
  string: { unit: "\u178F\u17BD\u17A2\u1780\u17D2\u179F\u179A", verb: "\u1782\u17BD\u179A\u1798\u17B6\u1793" },
20995
21653
  file: { unit: "\u1794\u17C3", verb: "\u1782\u17BD\u179A\u1798\u17B6\u1793" },
@@ -21102,7 +21760,7 @@ var error69 = () => {
21102
21760
  };
21103
21761
  function km_default2() {
21104
21762
  return {
21105
- localeError: error69()
21763
+ localeError: error70()
21106
21764
  };
21107
21765
  }
21108
21766
 
@@ -21111,7 +21769,7 @@ function kh_default2() {
21111
21769
  return km_default2();
21112
21770
  }
21113
21771
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/ko.js
21114
- var error70 = () => {
21772
+ var error71 = () => {
21115
21773
  const Sizable = {
21116
21774
  string: { unit: "\uBB38\uC790", verb: "to have" },
21117
21775
  file: { unit: "\uBC14\uC774\uD2B8", verb: "to have" },
@@ -21228,7 +21886,7 @@ var error70 = () => {
21228
21886
  };
21229
21887
  function ko_default2() {
21230
21888
  return {
21231
- localeError: error70()
21889
+ localeError: error71()
21232
21890
  };
21233
21891
  }
21234
21892
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/lt.js
@@ -21291,7 +21949,7 @@ function getUnitTypeFromNumber2(number5) {
21291
21949
  return "one";
21292
21950
  return "few";
21293
21951
  }
21294
- var error71 = () => {
21952
+ var error72 = () => {
21295
21953
  const Sizable = {
21296
21954
  string: {
21297
21955
  unit: {
@@ -21457,11 +22115,11 @@ var error71 = () => {
21457
22115
  };
21458
22116
  function lt_default2() {
21459
22117
  return {
21460
- localeError: error71()
22118
+ localeError: error72()
21461
22119
  };
21462
22120
  }
21463
22121
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/mk.js
21464
- var error72 = () => {
22122
+ var error73 = () => {
21465
22123
  const Sizable = {
21466
22124
  string: { unit: "\u0437\u043D\u0430\u0446\u0438", verb: "\u0434\u0430 \u0438\u043C\u0430\u0430\u0442" },
21467
22125
  file: { unit: "\u0431\u0430\u0458\u0442\u0438", verb: "\u0434\u0430 \u0438\u043C\u0430\u0430\u0442" },
@@ -21574,11 +22232,11 @@ var error72 = () => {
21574
22232
  };
21575
22233
  function mk_default2() {
21576
22234
  return {
21577
- localeError: error72()
22235
+ localeError: error73()
21578
22236
  };
21579
22237
  }
21580
22238
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/ms.js
21581
- var error73 = () => {
22239
+ var error74 = () => {
21582
22240
  const Sizable = {
21583
22241
  string: { unit: "aksara", verb: "mempunyai" },
21584
22242
  file: { unit: "bait", verb: "mempunyai" },
@@ -21690,11 +22348,11 @@ var error73 = () => {
21690
22348
  };
21691
22349
  function ms_default2() {
21692
22350
  return {
21693
- localeError: error73()
22351
+ localeError: error74()
21694
22352
  };
21695
22353
  }
21696
22354
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/nl.js
21697
- var error74 = () => {
22355
+ var error75 = () => {
21698
22356
  const Sizable = {
21699
22357
  string: { unit: "tekens" },
21700
22358
  file: { unit: "bytes" },
@@ -21807,11 +22465,11 @@ var error74 = () => {
21807
22465
  };
21808
22466
  function nl_default2() {
21809
22467
  return {
21810
- localeError: error74()
22468
+ localeError: error75()
21811
22469
  };
21812
22470
  }
21813
22471
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/no.js
21814
- var error75 = () => {
22472
+ var error76 = () => {
21815
22473
  const Sizable = {
21816
22474
  string: { unit: "tegn", verb: "\xE5 ha" },
21817
22475
  file: { unit: "bytes", verb: "\xE5 ha" },
@@ -21923,11 +22581,11 @@ var error75 = () => {
21923
22581
  };
21924
22582
  function no_default2() {
21925
22583
  return {
21926
- localeError: error75()
22584
+ localeError: error76()
21927
22585
  };
21928
22586
  }
21929
22587
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/ota.js
21930
- var error76 = () => {
22588
+ var error77 = () => {
21931
22589
  const Sizable = {
21932
22590
  string: { unit: "harf", verb: "olmal\u0131d\u0131r" },
21933
22591
  file: { unit: "bayt", verb: "olmal\u0131d\u0131r" },
@@ -22039,11 +22697,11 @@ var error76 = () => {
22039
22697
  };
22040
22698
  function ota_default2() {
22041
22699
  return {
22042
- localeError: error76()
22700
+ localeError: error77()
22043
22701
  };
22044
22702
  }
22045
22703
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/ps.js
22046
- var error77 = () => {
22704
+ var error78 = () => {
22047
22705
  const Sizable = {
22048
22706
  string: { unit: "\u062A\u0648\u06A9\u064A", verb: "\u0648\u0644\u0631\u064A" },
22049
22707
  file: { unit: "\u0628\u0627\u06CC\u067C\u0633", verb: "\u0648\u0644\u0631\u064A" },
@@ -22161,11 +22819,11 @@ var error77 = () => {
22161
22819
  };
22162
22820
  function ps_default2() {
22163
22821
  return {
22164
- localeError: error77()
22822
+ localeError: error78()
22165
22823
  };
22166
22824
  }
22167
22825
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/pl.js
22168
- var error78 = () => {
22826
+ var error79 = () => {
22169
22827
  const Sizable = {
22170
22828
  string: { unit: "znak\xF3w", verb: "mie\u0107" },
22171
22829
  file: { unit: "bajt\xF3w", verb: "mie\u0107" },
@@ -22278,11 +22936,11 @@ var error78 = () => {
22278
22936
  };
22279
22937
  function pl_default2() {
22280
22938
  return {
22281
- localeError: error78()
22939
+ localeError: error79()
22282
22940
  };
22283
22941
  }
22284
22942
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/pt.js
22285
- var error79 = () => {
22943
+ var error80 = () => {
22286
22944
  const Sizable = {
22287
22945
  string: { unit: "caracteres", verb: "ter" },
22288
22946
  file: { unit: "bytes", verb: "ter" },
@@ -22394,7 +23052,7 @@ var error79 = () => {
22394
23052
  };
22395
23053
  function pt_default2() {
22396
23054
  return {
22397
- localeError: error79()
23055
+ localeError: error80()
22398
23056
  };
22399
23057
  }
22400
23058
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/ru.js
@@ -22413,7 +23071,7 @@ function getRussianPlural2(count, one, few, many) {
22413
23071
  }
22414
23072
  return many;
22415
23073
  }
22416
- var error80 = () => {
23074
+ var error81 = () => {
22417
23075
  const Sizable = {
22418
23076
  string: {
22419
23077
  unit: {
@@ -22558,11 +23216,11 @@ var error80 = () => {
22558
23216
  };
22559
23217
  function ru_default2() {
22560
23218
  return {
22561
- localeError: error80()
23219
+ localeError: error81()
22562
23220
  };
22563
23221
  }
22564
23222
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/sl.js
22565
- var error81 = () => {
23223
+ var error82 = () => {
22566
23224
  const Sizable = {
22567
23225
  string: { unit: "znakov", verb: "imeti" },
22568
23226
  file: { unit: "bajtov", verb: "imeti" },
@@ -22675,11 +23333,11 @@ var error81 = () => {
22675
23333
  };
22676
23334
  function sl_default2() {
22677
23335
  return {
22678
- localeError: error81()
23336
+ localeError: error82()
22679
23337
  };
22680
23338
  }
22681
23339
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/sv.js
22682
- var error82 = () => {
23340
+ var error83 = () => {
22683
23341
  const Sizable = {
22684
23342
  string: { unit: "tecken", verb: "att ha" },
22685
23343
  file: { unit: "bytes", verb: "att ha" },
@@ -22793,11 +23451,11 @@ var error82 = () => {
22793
23451
  };
22794
23452
  function sv_default2() {
22795
23453
  return {
22796
- localeError: error82()
23454
+ localeError: error83()
22797
23455
  };
22798
23456
  }
22799
23457
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/ta.js
22800
- var error83 = () => {
23458
+ var error84 = () => {
22801
23459
  const Sizable = {
22802
23460
  string: { unit: "\u0B8E\u0BB4\u0BC1\u0BA4\u0BCD\u0BA4\u0BC1\u0B95\u0BCD\u0B95\u0BB3\u0BCD", verb: "\u0B95\u0BCA\u0BA3\u0BCD\u0B9F\u0BBF\u0BB0\u0BC1\u0B95\u0BCD\u0B95 \u0BB5\u0BC7\u0BA3\u0BCD\u0B9F\u0BC1\u0BAE\u0BCD" },
22803
23461
  file: { unit: "\u0BAA\u0BC8\u0B9F\u0BCD\u0B9F\u0BC1\u0B95\u0BB3\u0BCD", verb: "\u0B95\u0BCA\u0BA3\u0BCD\u0B9F\u0BBF\u0BB0\u0BC1\u0B95\u0BCD\u0B95 \u0BB5\u0BC7\u0BA3\u0BCD\u0B9F\u0BC1\u0BAE\u0BCD" },
@@ -22910,11 +23568,11 @@ var error83 = () => {
22910
23568
  };
22911
23569
  function ta_default2() {
22912
23570
  return {
22913
- localeError: error83()
23571
+ localeError: error84()
22914
23572
  };
22915
23573
  }
22916
23574
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/th.js
22917
- var error84 = () => {
23575
+ var error85 = () => {
22918
23576
  const Sizable = {
22919
23577
  string: { unit: "\u0E15\u0E31\u0E27\u0E2D\u0E31\u0E01\u0E29\u0E23", verb: "\u0E04\u0E27\u0E23\u0E21\u0E35" },
22920
23578
  file: { unit: "\u0E44\u0E1A\u0E15\u0E4C", verb: "\u0E04\u0E27\u0E23\u0E21\u0E35" },
@@ -23027,7 +23685,7 @@ var error84 = () => {
23027
23685
  };
23028
23686
  function th_default2() {
23029
23687
  return {
23030
- localeError: error84()
23688
+ localeError: error85()
23031
23689
  };
23032
23690
  }
23033
23691
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/tr.js
@@ -23051,7 +23709,7 @@ var parsedType7 = (data) => {
23051
23709
  }
23052
23710
  return t;
23053
23711
  };
23054
- var error85 = () => {
23712
+ var error86 = () => {
23055
23713
  const Sizable = {
23056
23714
  string: { unit: "karakter", verb: "olmal\u0131" },
23057
23715
  file: { unit: "bayt", verb: "olmal\u0131" },
@@ -23142,11 +23800,11 @@ var error85 = () => {
23142
23800
  };
23143
23801
  function tr_default2() {
23144
23802
  return {
23145
- localeError: error85()
23803
+ localeError: error86()
23146
23804
  };
23147
23805
  }
23148
23806
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/uk.js
23149
- var error86 = () => {
23807
+ var error87 = () => {
23150
23808
  const Sizable = {
23151
23809
  string: { unit: "\u0441\u0438\u043C\u0432\u043E\u043B\u0456\u0432", verb: "\u043C\u0430\u0442\u0438\u043C\u0435" },
23152
23810
  file: { unit: "\u0431\u0430\u0439\u0442\u0456\u0432", verb: "\u043C\u0430\u0442\u0438\u043C\u0435" },
@@ -23258,7 +23916,7 @@ var error86 = () => {
23258
23916
  };
23259
23917
  function uk_default2() {
23260
23918
  return {
23261
- localeError: error86()
23919
+ localeError: error87()
23262
23920
  };
23263
23921
  }
23264
23922
 
@@ -23267,7 +23925,7 @@ function ua_default2() {
23267
23925
  return uk_default2();
23268
23926
  }
23269
23927
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/ur.js
23270
- var error87 = () => {
23928
+ var error88 = () => {
23271
23929
  const Sizable = {
23272
23930
  string: { unit: "\u062D\u0631\u0648\u0641", verb: "\u06C1\u0648\u0646\u0627" },
23273
23931
  file: { unit: "\u0628\u0627\u0626\u0679\u0633", verb: "\u06C1\u0648\u0646\u0627" },
@@ -23380,11 +24038,11 @@ var error87 = () => {
23380
24038
  };
23381
24039
  function ur_default2() {
23382
24040
  return {
23383
- localeError: error87()
24041
+ localeError: error88()
23384
24042
  };
23385
24043
  }
23386
24044
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/vi.js
23387
- var error88 = () => {
24045
+ var error89 = () => {
23388
24046
  const Sizable = {
23389
24047
  string: { unit: "k\xFD t\u1EF1", verb: "c\xF3" },
23390
24048
  file: { unit: "byte", verb: "c\xF3" },
@@ -23496,11 +24154,11 @@ var error88 = () => {
23496
24154
  };
23497
24155
  function vi_default2() {
23498
24156
  return {
23499
- localeError: error88()
24157
+ localeError: error89()
23500
24158
  };
23501
24159
  }
23502
24160
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/zh-CN.js
23503
- var error89 = () => {
24161
+ var error90 = () => {
23504
24162
  const Sizable = {
23505
24163
  string: { unit: "\u5B57\u7B26", verb: "\u5305\u542B" },
23506
24164
  file: { unit: "\u5B57\u8282", verb: "\u5305\u542B" },
@@ -23612,11 +24270,11 @@ var error89 = () => {
23612
24270
  };
23613
24271
  function zh_CN_default2() {
23614
24272
  return {
23615
- localeError: error89()
24273
+ localeError: error90()
23616
24274
  };
23617
24275
  }
23618
24276
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/zh-TW.js
23619
- var error90 = () => {
24277
+ var error91 = () => {
23620
24278
  const Sizable = {
23621
24279
  string: { unit: "\u5B57\u5143", verb: "\u64C1\u6709" },
23622
24280
  file: { unit: "\u4F4D\u5143\u7D44", verb: "\u64C1\u6709" },
@@ -23729,11 +24387,11 @@ var error90 = () => {
23729
24387
  };
23730
24388
  function zh_TW_default2() {
23731
24389
  return {
23732
- localeError: error90()
24390
+ localeError: error91()
23733
24391
  };
23734
24392
  }
23735
24393
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/locales/yo.js
23736
- var error91 = () => {
24394
+ var error92 = () => {
23737
24395
  const Sizable = {
23738
24396
  string: { unit: "\xE0mi", verb: "n\xED" },
23739
24397
  file: { unit: "bytes", verb: "n\xED" },
@@ -23844,7 +24502,7 @@ var error91 = () => {
23844
24502
  };
23845
24503
  function yo_default2() {
23846
24504
  return {
23847
- localeError: error91()
24505
+ localeError: error92()
23848
24506
  };
23849
24507
  }
23850
24508
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/core/registries.js
@@ -26706,17 +27364,158 @@ tool.schema = exports_external2;
26706
27364
 
26707
27365
  // src/tools/domain-detector.ts
26708
27366
  var DOMAIN_PATTERNS = {
26709
- windows: [/\bwindows\b/i, /\bwin32\b/i, /\bregistry\b/i, /\bregedit\b/i, /\bwmi\b/i, /\bcim\b/i, /\bservice\b/i, /\bevent\s*log\b/i, /\bscheduled\s*task\b/i, /\bgpo\b/i, /\bgroup\s*policy\b/i, /\bmsi\b/i, /\binstaller\b/i, /\bwinrm\b/i],
26710
- powershell: [/\bpowershell\b/i, /\bpwsh\b/i, /\bps1\b/i, /\bcmdlet\b/i, /\bget-\w+/i, /\bset-\w+/i, /\bnew-\w+/i, /\bremove-\w+/i, /\binvoke-\w+/i, /\bpester\b/i],
26711
- python: [/\bpython\b/i, /\bpip\b/i, /\bpypi\b/i, /\bdjango\b/i, /\bflask\b/i, /\bpandas\b/i, /\bnumpy\b/i, /\bpytest\b/i, /\bvenv\b/i, /\bconda\b/i],
26712
- oracle: [/\boracle\b/i, /\bsqlplus\b/i, /\bplsql\b/i, /\btnsnames\b/i, /\bpdb\b/i, /\bcdb\b/i, /\btablespace\b/i, /\brman\b/i, /\bdataguard\b/i, /\basm\b/i, /\brac\b/i, /\bora-\d+/i],
26713
- network: [/\bnetwork\b/i, /\bfirewall\b/i, /\bdns\b/i, /\bdhcp\b/i, /\btcp\b/i, /\budp\b/i, /\bip\s*address\b/i, /\bsubnet\b/i, /\bvlan\b/i, /\brouting\b/i, /\bswitch\b/i, /\bload\s*balanc/i, /\bproxy\b/i, /\bssl\b/i, /\btls\b/i, /\bcertificate\b/i],
26714
- security: [/\bstig\b/i, /\bdisa\b/i, /\bcve\b/i, /\bvulnerabil/i, /\bharden\b/i, /\baudit\b/i, /\bcompliance\b/i, /\bscap\b/i, /\bfips\b/i, /\bcac\b/i, /\bpki\b/i, /\bencrypt/i],
26715
- linux: [/\blinux\b/i, /\bubuntu\b/i, /\brhel\b/i, /\bcentos\b/i, /\bbash\b/i, /\bsystemd\b/i, /\bsystemctl\b/i, /\byum\b/i, /\bapt\b/i, /\bcron\b/i, /\bchmod\b/i, /\bchown\b/i],
26716
- vmware: [/\bvmware\b/i, /\bvsphere\b/i, /\besxi\b/i, /\bvcenter\b/i, /\bvsan\b/i, /\bnsx\b/i, /\bvmotion\b/i, /\bdatastore\b/i, /\bpowercli\b/i, /\bova\b/i, /\bovf\b/i],
26717
- azure: [/\bazure\b/i, /\baz\s+\w+/i, /\bentra\b/i, /\baad\b/i, /\bazure\s*ad\b/i, /\barm\s*template\b/i, /\bbicep\b/i, /\bazure\s*devops\b/i, /\bblob\b/i, /\bkeyvault\b/i],
26718
- active_directory: [/\bactive\s*directory\b/i, /\bad\s+\w+/i, /\bldap\b/i, /\bdomain\s*controller\b/i, /\bgpupdate\b/i, /\bdsquery\b/i, /\bdsmod\b/i, /\baduc\b/i, /\bkerberos\b/i, /\bspn\b/i],
26719
- ui_ux: [/\bui\b/i, /\bux\b/i, /\buser\s+experience\b/i, /\buser\s+interface\b/i, /\bvisual\s+design\b/i, /\binteraction\s+design\b/i, /\bdesign\s+system\b/i, /\bwireframe\b/i, /\bprototype\b/i, /\baccessibility\b/i, /\btypography\b/i, /\blayout\b/i, /\bresponsive\b/i]
27367
+ windows: [
27368
+ /\bwindows\b/i,
27369
+ /\bwin32\b/i,
27370
+ /\bregistry\b/i,
27371
+ /\bregedit\b/i,
27372
+ /\bwmi\b/i,
27373
+ /\bcim\b/i,
27374
+ /\bservice\b/i,
27375
+ /\bevent\s*log\b/i,
27376
+ /\bscheduled\s*task\b/i,
27377
+ /\bgpo\b/i,
27378
+ /\bgroup\s*policy\b/i,
27379
+ /\bmsi\b/i,
27380
+ /\binstaller\b/i,
27381
+ /\bwinrm\b/i
27382
+ ],
27383
+ powershell: [
27384
+ /\bpowershell\b/i,
27385
+ /\bpwsh\b/i,
27386
+ /\bps1\b/i,
27387
+ /\bcmdlet\b/i,
27388
+ /\bget-\w+/i,
27389
+ /\bset-\w+/i,
27390
+ /\bnew-\w+/i,
27391
+ /\bremove-\w+/i,
27392
+ /\binvoke-\w+/i,
27393
+ /\bpester\b/i
27394
+ ],
27395
+ python: [
27396
+ /\bpython\b/i,
27397
+ /\bpip\b/i,
27398
+ /\bpypi\b/i,
27399
+ /\bdjango\b/i,
27400
+ /\bflask\b/i,
27401
+ /\bpandas\b/i,
27402
+ /\bnumpy\b/i,
27403
+ /\bpytest\b/i,
27404
+ /\bvenv\b/i,
27405
+ /\bconda\b/i
27406
+ ],
27407
+ oracle: [
27408
+ /\boracle\b/i,
27409
+ /\bsqlplus\b/i,
27410
+ /\bplsql\b/i,
27411
+ /\btnsnames\b/i,
27412
+ /\bpdb\b/i,
27413
+ /\bcdb\b/i,
27414
+ /\btablespace\b/i,
27415
+ /\brman\b/i,
27416
+ /\bdataguard\b/i,
27417
+ /\basm\b/i,
27418
+ /\brac\b/i,
27419
+ /\bora-\d+/i
27420
+ ],
27421
+ network: [
27422
+ /\bnetwork\b/i,
27423
+ /\bfirewall\b/i,
27424
+ /\bdns\b/i,
27425
+ /\bdhcp\b/i,
27426
+ /\btcp\b/i,
27427
+ /\budp\b/i,
27428
+ /\bip\s*address\b/i,
27429
+ /\bsubnet\b/i,
27430
+ /\bvlan\b/i,
27431
+ /\brouting\b/i,
27432
+ /\bswitch\b/i,
27433
+ /\bload\s*balanc/i,
27434
+ /\bproxy\b/i,
27435
+ /\bssl\b/i,
27436
+ /\btls\b/i,
27437
+ /\bcertificate\b/i
27438
+ ],
27439
+ security: [
27440
+ /\bstig\b/i,
27441
+ /\bdisa\b/i,
27442
+ /\bcve\b/i,
27443
+ /\bvulnerabil/i,
27444
+ /\bharden\b/i,
27445
+ /\baudit\b/i,
27446
+ /\bcompliance\b/i,
27447
+ /\bscap\b/i,
27448
+ /\bfips\b/i,
27449
+ /\bcac\b/i,
27450
+ /\bpki\b/i,
27451
+ /\bencrypt/i
27452
+ ],
27453
+ linux: [
27454
+ /\blinux\b/i,
27455
+ /\bubuntu\b/i,
27456
+ /\brhel\b/i,
27457
+ /\bcentos\b/i,
27458
+ /\bbash\b/i,
27459
+ /\bsystemd\b/i,
27460
+ /\bsystemctl\b/i,
27461
+ /\byum\b/i,
27462
+ /\bapt\b/i,
27463
+ /\bcron\b/i,
27464
+ /\bchmod\b/i,
27465
+ /\bchown\b/i
27466
+ ],
27467
+ vmware: [
27468
+ /\bvmware\b/i,
27469
+ /\bvsphere\b/i,
27470
+ /\besxi\b/i,
27471
+ /\bvcenter\b/i,
27472
+ /\bvsan\b/i,
27473
+ /\bnsx\b/i,
27474
+ /\bvmotion\b/i,
27475
+ /\bdatastore\b/i,
27476
+ /\bpowercli\b/i,
27477
+ /\bova\b/i,
27478
+ /\bovf\b/i
27479
+ ],
27480
+ azure: [
27481
+ /\bazure\b/i,
27482
+ /\baz\s+\w+/i,
27483
+ /\bentra\b/i,
27484
+ /\baad\b/i,
27485
+ /\bazure\s*ad\b/i,
27486
+ /\barm\s*template\b/i,
27487
+ /\bbicep\b/i,
27488
+ /\bazure\s*devops\b/i,
27489
+ /\bblob\b/i,
27490
+ /\bkeyvault\b/i
27491
+ ],
27492
+ active_directory: [
27493
+ /\bactive\s*directory\b/i,
27494
+ /\bad\s+\w+/i,
27495
+ /\bldap\b/i,
27496
+ /\bdomain\s*controller\b/i,
27497
+ /\bgpupdate\b/i,
27498
+ /\bdsquery\b/i,
27499
+ /\bdsmod\b/i,
27500
+ /\baduc\b/i,
27501
+ /\bkerberos\b/i,
27502
+ /\bspn\b/i
27503
+ ],
27504
+ ui_ux: [
27505
+ /\bui\b/i,
27506
+ /\bux\b/i,
27507
+ /\buser\s+experience\b/i,
27508
+ /\buser\s+interface\b/i,
27509
+ /\bvisual\s+design\b/i,
27510
+ /\binteraction\s+design\b/i,
27511
+ /\bdesign\s+system\b/i,
27512
+ /\bwireframe\b/i,
27513
+ /\bprototype\b/i,
27514
+ /\baccessibility\b/i,
27515
+ /\btypography\b/i,
27516
+ /\blayout\b/i,
27517
+ /\bresponsive\b/i
27518
+ ]
26720
27519
  };
26721
27520
  var detect_domains = tool({
26722
27521
  description: "Detect which SME domains are relevant for a given text. " + "Returns a list of domain names (windows, powershell, python, oracle, " + "network, security, linux, vmware, azure, active_directory, ui_ux) " + "that match patterns in the input text.",
@@ -26833,8 +27632,8 @@ var extract_code_blocks = tool({
26833
27632
  try {
26834
27633
  fs2.writeFileSync(filepath, code.trim(), "utf-8");
26835
27634
  savedFiles.push(filepath);
26836
- } catch (error92) {
26837
- errors5.push(`Failed to save ${filename}: ${error92 instanceof Error ? error92.message : String(error92)}`);
27635
+ } catch (error93) {
27636
+ errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
26838
27637
  }
26839
27638
  }
26840
27639
  let result = `Extracted ${savedFiles.length} file(s):
@@ -26889,28 +27688,32 @@ var gitingest = tool({
26889
27688
  return fetchGitingest(args);
26890
27689
  }
26891
27690
  });
26892
- // src/utils/logger.ts
26893
- var DEBUG = process.env.OPENCODE_SWARM_DEBUG === "1";
26894
- function log(message, data) {
26895
- if (!DEBUG)
26896
- return;
26897
- const timestamp = new Date().toISOString();
26898
- if (data !== undefined) {
26899
- console.log(`[opencode-swarm ${timestamp}] ${message}`, data);
26900
- } else {
26901
- console.log(`[opencode-swarm ${timestamp}] ${message}`);
26902
- }
26903
- }
26904
27691
  // src/index.ts
26905
27692
  var OpenCodeSwarm = async (ctx) => {
26906
27693
  const config3 = loadPluginConfig(ctx.directory);
26907
27694
  const agents = getAgentConfigs(config3);
27695
+ const agentDefinitions = createAgents(config3);
26908
27696
  const pipelineHook = createPipelineTrackerHook(config3);
27697
+ const systemEnhancerHook = createSystemEnhancerHook(config3, ctx.directory);
27698
+ const compactionHook = createCompactionCustomizerHook(config3, ctx.directory);
27699
+ const contextBudgetHandler = createContextBudgetHandler(config3);
27700
+ const commandHandler = createSwarmCommandHandler(ctx.directory, Object.fromEntries(agentDefinitions.map((agent) => [agent.name, agent])));
27701
+ const activityHooks = createAgentActivityHooks(config3, ctx.directory);
27702
+ const delegationHandler = createDelegationTrackerHook(config3);
26909
27703
  log("Plugin initialized", {
26910
27704
  directory: ctx.directory,
26911
27705
  maxIterations: config3.max_iterations,
26912
27706
  agentCount: Object.keys(agents).length,
26913
- agentNames: Object.keys(agents)
27707
+ agentNames: Object.keys(agents),
27708
+ hooks: {
27709
+ pipeline: !!pipelineHook["experimental.chat.messages.transform"],
27710
+ systemEnhancer: !!systemEnhancerHook["experimental.chat.system.transform"],
27711
+ compaction: !!compactionHook["experimental.session.compacting"],
27712
+ contextBudget: !!contextBudgetHandler,
27713
+ commands: true,
27714
+ agentActivity: config3.hooks?.agent_activity !== false,
27715
+ delegationTracker: config3.hooks?.delegation_tracker === true
27716
+ }
26914
27717
  });
26915
27718
  return {
26916
27719
  name: "opencode-swarm",
@@ -26926,11 +27729,28 @@ var OpenCodeSwarm = async (ctx) => {
26926
27729
  } else {
26927
27730
  Object.assign(opencodeConfig.agent, agents);
26928
27731
  }
27732
+ opencodeConfig.command = {
27733
+ ...opencodeConfig.command || {},
27734
+ swarm: {
27735
+ template: "{{arguments}}",
27736
+ description: "Swarm management commands"
27737
+ }
27738
+ };
26929
27739
  log("Config applied", {
26930
- agents: Object.keys(agents)
27740
+ agents: Object.keys(agents),
27741
+ commands: ["swarm"]
26931
27742
  });
26932
27743
  },
26933
- "experimental.chat.messages.transform": pipelineHook["experimental.chat.messages.transform"]
27744
+ "experimental.chat.messages.transform": composeHandlers(...[
27745
+ pipelineHook["experimental.chat.messages.transform"],
27746
+ contextBudgetHandler
27747
+ ].filter((fn) => Boolean(fn))),
27748
+ "experimental.chat.system.transform": systemEnhancerHook["experimental.chat.system.transform"],
27749
+ "experimental.session.compacting": compactionHook["experimental.session.compacting"],
27750
+ "command.execute.before": safeHook(commandHandler),
27751
+ "tool.execute.before": safeHook(activityHooks.toolBefore),
27752
+ "tool.execute.after": safeHook(activityHooks.toolAfter),
27753
+ "chat.message": safeHook(delegationHandler)
26934
27754
  };
26935
27755
  };
26936
27756
  var src_default = OpenCodeSwarm;