@wrongstack/cli 0.299.0 → 0.300.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.
Files changed (49) hide show
  1. package/dist/{acp-S4LZQB66.js → acp-IDNS2YVE.js} +3 -3
  2. package/dist/{auth-G5YKKSRH.js → auth-6T6ZOT2R.js} +5 -5
  3. package/dist/auth-menu/loopback-server.d.ts +41 -55
  4. package/dist/auth-menu/openai-codex-oauth.d.ts +36 -123
  5. package/dist/auto-discover-providers-DRW4OZHG.js +8 -0
  6. package/dist/boot/dispatch-webui.d.ts +3 -0
  7. package/dist/{chunk-PEKUKUCH.js → chunk-3MWUZMOL.js} +19 -12
  8. package/dist/{chunk-TGDHN4LM.js → chunk-4GVH7V3S.js} +4 -24
  9. package/dist/{chunk-4U3DMA2Y.js → chunk-4WJKVQJY.js} +15 -20
  10. package/dist/{chunk-2SLSUDYS.js → chunk-GYDQABMA.js} +269 -180
  11. package/dist/{chunk-4HH3YGG4.js → chunk-MRLYDHQ7.js} +8 -5
  12. package/dist/{chunk-66T43Q4Y.js → chunk-N7ULWBO5.js} +4 -3
  13. package/dist/{chunk-ZNZJ34RF.js → chunk-PEMN4T5O.js} +2 -2
  14. package/dist/chunk-PYTFS4MC.js +238 -0
  15. package/dist/{chunk-L5CE52XW.js → chunk-V76R7DC5.js} +25 -19
  16. package/dist/{cli-main-3MQDFSYK.js → cli-main-7B3G2YSG.js} +528 -156
  17. package/dist/{execution-ANOYMWPO.js → execution-SHGM7BVC.js} +50 -5
  18. package/dist/fleet/budget-source.d.ts +18 -0
  19. package/dist/fleet/host-status.d.ts +31 -0
  20. package/dist/fleet/host-types.d.ts +8 -0
  21. package/dist/fleet/host.d.ts +5 -0
  22. package/dist/{hq-BDO56CX6.js → hq-DVDD4XPV.js} +22 -3
  23. package/dist/hq-server/auth-state.d.ts +29 -1
  24. package/dist/hq-server/auth.d.ts +16 -0
  25. package/dist/hq-server/client-address.d.ts +56 -0
  26. package/dist/hq-server/login-attempt-store.d.ts +30 -10
  27. package/dist/hq-server/routes/auth-handlers.d.ts +66 -26
  28. package/dist/hq-server/routes.d.ts +13 -0
  29. package/dist/hq-server/types.d.ts +10 -0
  30. package/dist/{hq-server-RJLJJZU7.js → hq-server-DQHLNHDL.js} +2 -2
  31. package/dist/hq-server.d.ts +19 -0
  32. package/dist/index.js +20 -20
  33. package/dist/{modeldiag-HENYJ4N7.js → modeldiag-YOQZHBQV.js} +2 -2
  34. package/dist/{plugin-usage-VTL7ZTVC.js → plugin-usage-EOG4ET4S.js} +2 -2
  35. package/dist/{plugins-ETY6W3DC.js → plugins-56CMWMPR.js} +3 -3
  36. package/dist/{providers-models-GDELBHZK.js → providers-models-K6RT7ABI.js} +34 -9
  37. package/dist/slash-commands/command-context.d.ts +19 -0
  38. package/dist/webui-server/setup-events.d.ts +17 -0
  39. package/dist/webui-server/terminal-log-view.d.ts +29 -12
  40. package/dist/{webui-server-PCLSXX6L.js → webui-server-G3EKFXLL.js} +109 -38
  41. package/dist/webui-server-options.d.ts +16 -0
  42. package/dist/wiring/brain-and-orchestration.d.ts +3 -0
  43. package/dist/wiring/director-setup.d.ts +4 -0
  44. package/dist/wiring/fallback-gate.d.ts +31 -0
  45. package/dist/wiring/fleet-command-handlers.d.ts +1 -1
  46. package/dist/wiring/plugins.d.ts +2 -8
  47. package/dist/wiring/provider-utility-tools.d.ts +26 -1
  48. package/package.json +23 -23
  49. package/dist/chunk-GO3TJICK.js +0 -489
@@ -1,3 +1,6 @@
1
+ import {
2
+ setupPlugins
3
+ } from "./chunk-4WJKVQJY.js";
1
4
  import {
2
5
  runProjectPicker
3
6
  } from "./chunk-5N34EWJR.js";
@@ -37,13 +40,10 @@ import {
37
40
  matchTaskNode,
38
41
  sddState
39
42
  } from "./chunk-XTIXVJXP.js";
40
- import {
41
- setupPlugins
42
- } from "./chunk-4U3DMA2Y.js";
43
43
  import {
44
44
  PLUGIN_AUDIT_ENTRIES,
45
45
  runPluginManagementCommand
46
- } from "./chunk-PEKUKUCH.js";
46
+ } from "./chunk-3MWUZMOL.js";
47
47
  import {
48
48
  configureSimpleUiRuntimeContext,
49
49
  detectProjectFacts,
@@ -70,7 +70,7 @@ import {
70
70
  loadCachedAcpRegistry,
71
71
  refreshAcpRegistry,
72
72
  setupProvider
73
- } from "./chunk-4HH3YGG4.js";
73
+ } from "./chunk-MRLYDHQ7.js";
74
74
  import {
75
75
  addCustomProvider,
76
76
  addKeyForCatalogProvider,
@@ -80,17 +80,18 @@ import {
80
80
  runClaudeOAuthLogin,
81
81
  runCopilotOAuthLogin,
82
82
  validateFamily
83
- } from "./chunk-L5CE52XW.js";
83
+ } from "./chunk-V76R7DC5.js";
84
84
  import {
85
85
  LOCAL_LLM_PRESETS,
86
86
  parseSpawnFlags
87
- } from "./chunk-ZNZJ34RF.js";
87
+ } from "./chunk-PEMN4T5O.js";
88
88
  import {
89
- buildPickableProviders
90
- } from "./chunk-66T43Q4Y.js";
89
+ buildPickableProviders,
90
+ visibleModelIds
91
+ } from "./chunk-N7ULWBO5.js";
91
92
  import {
92
93
  runCodexOAuthLogin
93
- } from "./chunk-GO3TJICK.js";
94
+ } from "./chunk-PYTFS4MC.js";
94
95
  import {
95
96
  activeLabel,
96
97
  loadConfigProviders,
@@ -3263,6 +3264,10 @@ function registerDirectorStatsBridge(input) {
3263
3264
  ...u.toolCalls !== void 0 ? { toolCalls: u.toolCalls } : {}
3264
3265
  };
3265
3266
  });
3267
+ const budgetSnap = director.fleetManager?.budgetSnapshot?.();
3268
+ const maxSpawns = budgetSnap?.maxSpawns ?? director.maxSpawns;
3269
+ const usedSpawns = budgetSnap?.usedSpawns ?? director.spawnCount;
3270
+ const remainingSpawns = budgetSnap?.remainingSpawns ?? Math.max(0, (Number.isFinite(maxSpawns) ? maxSpawns : Number.POSITIVE_INFINITY) - usedSpawns);
3266
3271
  events.emit("coordinator.stats", {
3267
3272
  sessionId,
3268
3273
  total: payload.total,
@@ -3273,6 +3278,11 @@ function registerDirectorStatsBridge(input) {
3273
3278
  pending: payload.pending,
3274
3279
  completed: payload.completed,
3275
3280
  ...usage?.total?.cost !== void 0 ? { totalCostUsd: usage.total.cost } : {},
3281
+ maxSpawns,
3282
+ usedSpawns,
3283
+ remainingSpawns,
3284
+ ...budgetSnap?.checkpointMaxSpawns !== void 0 ? { checkpointMaxSpawns: budgetSnap.checkpointMaxSpawns } : {},
3285
+ ...budgetSnap?.ceilingMismatch ? { ceilingMismatch: true } : {},
3276
3286
  subagentStatuses
3277
3287
  });
3278
3288
  });
@@ -4366,7 +4376,47 @@ function buildFleetHostStatus(input) {
4366
4376
  const completedCount = completed.length;
4367
4377
  const liveCount = live.filter((s) => s.status === "running" || s.status === "idle").length;
4368
4378
  const summary = !input.coordinatorStatus && !input.completedResults ? "No subagents have been spawned." : liveCount > 0 ? `${pending.length} pending, ${liveCount} active, ${completedCount} completed.` : `${pending.length} pending, ${completedCount} completed.`;
4369
- return { pending, completed, live, summary };
4379
+ return {
4380
+ pending,
4381
+ completed,
4382
+ live,
4383
+ summary,
4384
+ ...input.budget ? { budget: input.budget } : {}
4385
+ };
4386
+ }
4387
+ function formatFleetBudgetLines(budget, colorize) {
4388
+ const bold = colorize?.bold ?? ((s) => s);
4389
+ const dim = colorize?.dim ?? ((s) => s);
4390
+ const amber = colorize?.amber ?? ((s) => s);
4391
+ const fmtNum = (n) => Number.isFinite(n) ? String(n) : "\u221E";
4392
+ const sourceSuffix = budget.effectiveSource ? ` ${dim(`(source: ${budget.effectiveSource})`)}` : "";
4393
+ const lines = [
4394
+ bold("Budget"),
4395
+ ` maxConcurrent: ${budget.maxConcurrent} \xB7 activeAgents: ${budget.activeAgents}`,
4396
+ ` maxSpawns: ${fmtNum(budget.maxSpawns)} \xB7 usedSpawns: ${budget.usedSpawns} \xB7 remainingSpawns: ${fmtNum(budget.remainingSpawns)}${sourceSuffix}`
4397
+ ];
4398
+ if (budget.maxTokens !== void 0 && Number.isFinite(budget.maxTokens) && budget.maxTokens < Number.POSITIVE_INFINITY) {
4399
+ lines.push(
4400
+ ` tokens: ${budget.usedTokens ?? 0} / ${fmtNum(budget.maxTokens)} remaining ${fmtNum(budget.remainingTokens ?? 0)}`
4401
+ );
4402
+ }
4403
+ if (budget.maxCostUsd !== void 0 && Number.isFinite(budget.maxCostUsd) && budget.maxCostUsd < Number.POSITIVE_INFINITY) {
4404
+ const used = budget.usedCostUsd ?? 0;
4405
+ const rem = budget.remainingCostUsd ?? 0;
4406
+ lines.push(
4407
+ ` costUsd: ${used.toFixed(4)} / ${budget.maxCostUsd.toFixed(4)} remaining ${rem.toFixed(4)}`
4408
+ );
4409
+ }
4410
+ if (budget.ceilingMismatch && budget.checkpointMaxSpawns !== void 0) {
4411
+ lines.push(
4412
+ amber(
4413
+ ` \u26A0 checkpoint maxSpawns was ${budget.checkpointMaxSpawns}; live ceiling is ${fmtNum(budget.maxSpawns)}`
4414
+ )
4415
+ );
4416
+ } else if (budget.checkpointMaxSpawns !== void 0) {
4417
+ lines.push(dim(` checkpointMaxSpawns: ${budget.checkpointMaxSpawns}`));
4418
+ }
4419
+ return lines;
4370
4420
  }
4371
4421
  function aggregateFleetUsage(completed) {
4372
4422
  const bySubagent = /* @__PURE__ */ new Map();
@@ -5074,9 +5124,44 @@ var MultiAgentHost = class {
5074
5124
  coordinatorStatus: this.director ? this.getCoordinator().getStatus() : null,
5075
5125
  fleetStatus: this.fleetManager?.getFleetStatus() ?? null,
5076
5126
  completedResults: this.director ? this.director.completedResults() : null,
5077
- shadowTaskIds: this.shadowTaskIds
5127
+ shadowTaskIds: this.shadowTaskIds,
5128
+ budget: this.budgetView()
5078
5129
  });
5079
5130
  }
5131
+ /**
5132
+ * Read-only concurrency + lifetime spawn budget for `/fleet status` and
5133
+ * resume diagnostics. Safe when no director/fleet is active yet.
5134
+ */
5135
+ budgetView() {
5136
+ const snap = this.fleetManager?.budgetSnapshot?.();
5137
+ const maxSpawns = snap?.maxSpawns ?? this.opts.maxSpawns ?? this.director?.maxSpawns ?? Number.POSITIVE_INFINITY;
5138
+ const usedSpawns = snap?.usedSpawns ?? this.director?.spawnCount ?? 0;
5139
+ const remainingSpawns = snap?.remainingSpawns ?? Math.max(0, (Number.isFinite(maxSpawns) ? maxSpawns : Number.POSITIVE_INFINITY) - usedSpawns);
5140
+ const live = this.director ? this.getCoordinator().getStatus().subagents.filter((s) => s.status === "running" || s.status === "idle").length : 0;
5141
+ const maxConcurrentSource = this.opts.budgetSources?.maxConcurrent ?? "default";
5142
+ const maxSpawnsSource = this.opts.budgetSources?.maxSpawns ?? "default";
5143
+ const effectiveSource = `maxConcurrent=${maxConcurrentSource}, maxSpawns=${maxSpawnsSource}`;
5144
+ return {
5145
+ maxConcurrent: this.getMaxConcurrent(),
5146
+ activeAgents: live,
5147
+ maxSpawns,
5148
+ usedSpawns,
5149
+ remainingSpawns,
5150
+ maxConcurrentSource,
5151
+ maxSpawnsSource,
5152
+ effectiveSource,
5153
+ ...snap ? {
5154
+ maxTokens: snap.maxTokens,
5155
+ usedTokens: snap.usedTokens,
5156
+ remainingTokens: snap.remainingTokens,
5157
+ maxCostUsd: snap.maxCostUsd,
5158
+ usedCostUsd: snap.usedCostUsd,
5159
+ remainingCostUsd: snap.remainingCostUsd,
5160
+ ...snap.checkpointMaxSpawns !== void 0 ? { checkpointMaxSpawns: snap.checkpointMaxSpawns } : {},
5161
+ ...snap.ceilingMismatch ? { ceilingMismatch: true } : {}
5162
+ } : {}
5163
+ };
5164
+ }
5080
5165
  usage() {
5081
5166
  const completed = this.director ? this.director.completedResults().filter((r) => !this.shadowTaskIds.has(r.taskId)) : [];
5082
5167
  return aggregateFleetUsage(completed);
@@ -5176,7 +5261,10 @@ function resolveProviderCfg(config, providerId) {
5176
5261
  function buildProviderForId(args, providerId) {
5177
5262
  const { cfg, factoryType } = resolveProviderCfg(args.config, providerId);
5178
5263
  const useRegistry = !!args.config.features.modelsRegistry && args.providerRegistry.has(factoryType);
5179
- return useRegistry ? args.providerRegistry.create(cfg, factoryType) : makeProviderFromConfig2(providerId, cfg);
5264
+ return useRegistry ? args.providerRegistry.create(cfg, factoryType) : makeProviderFromConfig2(
5265
+ providerId,
5266
+ factoryType === "ai-gateway" ? { ...cfg, type: factoryType } : cfg
5267
+ );
5180
5268
  }
5181
5269
 
5182
5270
  // src/wiring/brain-and-orchestration.ts
@@ -5415,8 +5503,12 @@ function setupBrainAndOrchestration(deps) {
5415
5503
  maxCostUsd: config.fleet.budget.maxCostUsd
5416
5504
  }
5417
5505
  } : {},
5418
- maxSpawns: config.fleet?.budget?.maxSpawns,
5506
+ maxSpawns: deps.maxSpawns ?? config.fleet?.budget?.maxSpawns,
5419
5507
  maxConcurrent,
5508
+ budgetSources: {
5509
+ maxConcurrent: deps.maxConcurrentSource ?? "default",
5510
+ maxSpawns: deps.maxSpawnsSource ?? "default"
5511
+ },
5420
5512
  getLeaderMaxContext: () => effectiveMaxContextRef.current,
5421
5513
  brain,
5422
5514
  agentMonitor,
@@ -5933,13 +6025,78 @@ import * as path10 from "node:path";
5933
6025
  import { expectDefined as expectDefined2 } from "@wrongstack/core/utils";
5934
6026
  import { createAgentMonitorService } from "@wrongstack/core/coordination";
5935
6027
  import { sessionScopedPath as sessionScopedPath2 } from "@wrongstack/core/utils";
6028
+
6029
+ // src/fleet/budget-source.ts
6030
+ import { DEFAULT_MAX_FLEET_SPAWNS as DEFAULT_MAX_FLEET_SPAWNS3 } from "@wrongstack/core/coordination";
6031
+ function positiveInt(raw) {
6032
+ if (typeof raw === "number" && Number.isFinite(raw) && raw > 0) return Math.floor(raw);
6033
+ if (typeof raw === "string" && raw.trim() !== "") {
6034
+ const n = Number.parseInt(raw, 10);
6035
+ if (Number.isFinite(n) && n > 0) return n;
6036
+ }
6037
+ return void 0;
6038
+ }
6039
+ function resolveFleetBudgetSources(input) {
6040
+ const flags = input.flags ?? {};
6041
+ const env = input.env ?? process.env;
6042
+ const config = input.config;
6043
+ const defaultMaxConcurrent = input.defaultMaxConcurrent ?? 4;
6044
+ const defaultMaxSpawns = input.defaultMaxSpawns ?? DEFAULT_MAX_FLEET_SPAWNS3;
6045
+ const maxConcurrentFlag = positiveInt(flags["max-concurrent"]);
6046
+ const maxConcurrentEnv = positiveInt(env["WRONGSTACK_MAX_CONCURRENT"]);
6047
+ const maxConcurrentProfile = positiveInt(config?.maxConcurrent);
6048
+ let maxConcurrent;
6049
+ let maxConcurrentSource;
6050
+ if (maxConcurrentFlag !== void 0) {
6051
+ maxConcurrent = maxConcurrentFlag;
6052
+ maxConcurrentSource = "cli-flag";
6053
+ } else if (maxConcurrentEnv !== void 0) {
6054
+ maxConcurrent = maxConcurrentEnv;
6055
+ maxConcurrentSource = "env";
6056
+ } else if (maxConcurrentProfile !== void 0) {
6057
+ maxConcurrent = maxConcurrentProfile;
6058
+ maxConcurrentSource = "profile";
6059
+ } else {
6060
+ maxConcurrent = defaultMaxConcurrent;
6061
+ maxConcurrentSource = "default";
6062
+ }
6063
+ const maxSpawnsFlag = positiveInt(flags["max-spawns"]);
6064
+ const maxSpawnsEnv = positiveInt(env["WRONGSTACK_MAX_SPAWNS"]);
6065
+ const maxSpawnsProfile = positiveInt(config?.fleet?.budget?.maxSpawns);
6066
+ let maxSpawns;
6067
+ let maxSpawnsSource;
6068
+ if (maxSpawnsFlag !== void 0) {
6069
+ maxSpawns = maxSpawnsFlag;
6070
+ maxSpawnsSource = "cli-flag";
6071
+ } else if (maxSpawnsEnv !== void 0) {
6072
+ maxSpawns = maxSpawnsEnv;
6073
+ maxSpawnsSource = "env";
6074
+ } else if (maxSpawnsProfile !== void 0) {
6075
+ maxSpawns = maxSpawnsProfile;
6076
+ maxSpawnsSource = "profile";
6077
+ } else {
6078
+ maxSpawns = defaultMaxSpawns;
6079
+ maxSpawnsSource = "default";
6080
+ }
6081
+ return {
6082
+ maxConcurrent,
6083
+ maxConcurrentSource,
6084
+ maxSpawns,
6085
+ maxSpawnsSource
6086
+ };
6087
+ }
6088
+
6089
+ // src/wiring/director-setup.ts
5936
6090
  function setupDirectorAndAutonomy(deps) {
5937
6091
  const { flags, config, wpaths, session, events, autonomyModeRef } = deps;
5938
6092
  const directorMode = true;
5939
- const maxConcurrentFromFlag = typeof flags["max-concurrent"] === "string" ? Number.parseInt(flags["max-concurrent"], 10) : void 0;
5940
- const maxConcurrentFromEnv = typeof process.env["WRONGSTACK_MAX_CONCURRENT"] === "string" ? Number.parseInt(process.env["WRONGSTACK_MAX_CONCURRENT"], 10) : void 0;
5941
- const maxConcurrentFromConfig = typeof config.maxConcurrent === "number" && config.maxConcurrent > 0 ? config.maxConcurrent : void 0;
5942
- const maxConcurrent = Number.isFinite(maxConcurrentFromFlag) && maxConcurrentFromFlag > 0 ? maxConcurrentFromFlag : Number.isFinite(maxConcurrentFromEnv) && maxConcurrentFromEnv > 0 ? maxConcurrentFromEnv : Number.isFinite(maxConcurrentFromConfig) && maxConcurrentFromConfig > 0 ? maxConcurrentFromConfig : void 0;
6093
+ const {
6094
+ maxConcurrent: resolvedMaxConcurrent,
6095
+ maxConcurrentSource,
6096
+ maxSpawns,
6097
+ maxSpawnsSource
6098
+ } = resolveFleetBudgetSources({ flags, config });
6099
+ const maxConcurrent = maxConcurrentSource === "default" ? void 0 : resolvedMaxConcurrent;
5943
6100
  const autonomyMode = (() => {
5944
6101
  const v = flags["autonomy"];
5945
6102
  if (v === "auto" || v === "suggest" || v === "eternal" || v === "eternal-parallel") return v;
@@ -5986,6 +6143,9 @@ function setupDirectorAndAutonomy(deps) {
5986
6143
  director: null,
5987
6144
  directorMode,
5988
6145
  maxConcurrent,
6146
+ maxSpawns,
6147
+ maxConcurrentSource,
6148
+ maxSpawnsSource,
5989
6149
  autonomyMode,
5990
6150
  nextPredictEnabled,
5991
6151
  currentSuggestions,
@@ -6105,6 +6265,7 @@ ${color6.dim("\u2500".repeat(40))}` : "";
6105
6265
  onAgents: (subagentId) => formatAgents(input, subagentId),
6106
6266
  onFleet: (action, target) => handleFleetAction(input, action, target),
6107
6267
  onFleetStatus: () => input.getDirector()?.status() ?? null,
6268
+ onFleetBudget: () => input.multiAgentHost.budgetView(),
6108
6269
  onFleetUsage: () => input.getDirector()?.snapshot() ?? null,
6109
6270
  onFleetKill: () => killFleet2(input.getDirector()),
6110
6271
  onFleetTerminate: async (subagentId) => {
@@ -6223,6 +6384,15 @@ async function handleFleetAction(input, action, target) {
6223
6384
  function formatFleetStatus(host) {
6224
6385
  const status = host.status();
6225
6386
  const lines = [color6.bold("Fleet status"), ` ${status.summary}`];
6387
+ const budget = status.budget ?? host.budgetView();
6388
+ lines.push(
6389
+ "",
6390
+ ...formatFleetBudgetLines(budget, {
6391
+ bold: color6.bold,
6392
+ dim: color6.dim,
6393
+ amber: color6.amber
6394
+ })
6395
+ );
6226
6396
  const icons = { running: "\u25CF", idle: "\u25CB", stopped: "\u2298" };
6227
6397
  const active2 = status.live.filter((agent) => agent.status === "running" || agent.status === "idle");
6228
6398
  if (active2.length > 0) {
@@ -6762,6 +6932,7 @@ function setupHqTelemetry(deps) {
6762
6932
  // src/wiring/lifecycle-plugins.ts
6763
6933
  import * as path15 from "node:path";
6764
6934
  import { getSharedProjectMailbox as getSharedProjectMailbox8 } from "@wrongstack/core/coordination";
6935
+ import { CouncilOrchestrator, OneShotOrchestrator as OneShotOrchestrator2 } from "@wrongstack/core/execution";
6765
6936
  import { countShellHooks, HookRegistry, HookRunner, shellHooksEqual } from "@wrongstack/core/hooks";
6766
6937
  import { allServers } from "@wrongstack/core/infrastructure";
6767
6938
  import { TOKENS as TOKENS8 } from "@wrongstack/core/kernel";
@@ -7350,6 +7521,130 @@ function createAgent(params) {
7350
7521
  });
7351
7522
  }
7352
7523
 
7524
+ // src/wiring/provider-utility-tools.ts
7525
+ import { createContextManagerTool as createContextManagerTool2 } from "@wrongstack/core/infrastructure";
7526
+ import { createCouncilTool, createOneShotLLMTool } from "@wrongstack/core/tools";
7527
+ import {
7528
+ createCouncilPersonaRegistry,
7529
+ createCouncilProfileRegistry,
7530
+ OneShotOrchestrator
7531
+ } from "@wrongstack/core/execution";
7532
+ import { ModelRouter } from "@wrongstack/core/models";
7533
+ async function adoptResumedProvider(input) {
7534
+ if (!input.resumedProvider && !input.resumedModel) return;
7535
+ const config = input.getConfig();
7536
+ const provider = input.resumedProvider?.trim() || config.provider;
7537
+ const model = input.resumedModel?.trim() || config.model;
7538
+ if (provider === config.provider && model === config.model) return;
7539
+ const error = await input.switchProviderAndModel(provider, model);
7540
+ if (error) {
7541
+ const current = input.getConfig();
7542
+ input.logger.warn(
7543
+ `Resume: could not switch to the session's model ${provider}/${model} (${error}); continuing with ${current.provider}/${current.model}.`
7544
+ );
7545
+ }
7546
+ }
7547
+ function createLiveModelRouter(getConfig) {
7548
+ return {
7549
+ pickForTask(role, description) {
7550
+ const config = getConfig();
7551
+ const router = new ModelRouter({
7552
+ ...config.modelMatrix ? { matrix: config.modelMatrix } : {},
7553
+ config: {
7554
+ provider: config.provider,
7555
+ model: config.model,
7556
+ ...config.providers ? { providers: config.providers } : {}
7557
+ }
7558
+ });
7559
+ return router.pickForTask(role, description);
7560
+ }
7561
+ };
7562
+ }
7563
+ function buildCouncilRegistries(cfg) {
7564
+ const base = {
7565
+ ...cfg?.defaultProfile ? { defaultProfile: cfg.defaultProfile } : {},
7566
+ ...cfg?.maxConcurrency !== void 0 ? { maxConcurrency: cfg.maxConcurrency } : {}
7567
+ };
7568
+ if (!cfg?.personas?.length && !cfg?.profiles?.length) return base;
7569
+ try {
7570
+ const personas = createCouncilPersonaRegistry(cfg.personas ?? []);
7571
+ const profiles = createCouncilProfileRegistry(
7572
+ cfg.profiles ?? [],
7573
+ personas
7574
+ );
7575
+ return { ...base, personas, profiles };
7576
+ } catch (error) {
7577
+ console.warn(
7578
+ `Council tool: ignoring tools.council personas/profiles \u2014 ${error instanceof Error ? error.message : String(error)}. Falling back to the built-in lenses and panels.`
7579
+ );
7580
+ return base;
7581
+ }
7582
+ }
7583
+ function registerProviderUtilityTools(input) {
7584
+ const config = input.getConfig();
7585
+ const llmTool = createOneShotLLMTool({
7586
+ buildProvider: input.buildProvider,
7587
+ getConfig: input.getConfig,
7588
+ fallbackProfileManager: input.fallbackProfileManager,
7589
+ defaultProvider: config.provider,
7590
+ defaultModel: config.model
7591
+ });
7592
+ registerOrOverride(input.toolRegistry, "llm", llmTool);
7593
+ const councilOrchestrator = new OneShotOrchestrator({
7594
+ buildProvider: input.buildProvider,
7595
+ getConfig: input.getConfig,
7596
+ fallbackProfileManager: input.fallbackProfileManager,
7597
+ statusTracker: input.statusTracker,
7598
+ // Council profiles route each seat by ROLE ('planner', 'critic',
7599
+ // 'analyst', 'security-reviewer'…) rather than pinning models. Without a
7600
+ // router those hints were inert: every seat fell through to the session
7601
+ // provider/model, so a three-seat panel asked one model three times and
7602
+ // reported a distinctness warning on every single call.
7603
+ modelRouter: createLiveModelRouter(input.getConfig)
7604
+ });
7605
+ registerOrOverride(
7606
+ input.toolRegistry,
7607
+ "council",
7608
+ createCouncilTool({
7609
+ caller: councilOrchestrator,
7610
+ fallbackProfileManager: input.fallbackProfileManager,
7611
+ ...buildCouncilRegistries(config.tools?.council)
7612
+ })
7613
+ );
7614
+ try {
7615
+ const summarizer = new OneShotOrchestrator({
7616
+ buildProvider: input.buildProvider,
7617
+ getConfig: input.getConfig,
7618
+ fallbackProfileManager: input.fallbackProfileManager,
7619
+ statusTracker: input.statusTracker
7620
+ });
7621
+ input.toolRegistry.override(
7622
+ "context_manager",
7623
+ createContextManagerTool2({
7624
+ compactor: input.compactor,
7625
+ summarizer: async (messages) => {
7626
+ const result = await summarizer.call({
7627
+ system: "Summarize concisely. Keep decisions and key facts.",
7628
+ messages,
7629
+ model: "deepseek-chat",
7630
+ maxTokens: 1024,
7631
+ timeoutMs: 3e4
7632
+ });
7633
+ return result.text || "(summary unavailable)";
7634
+ }
7635
+ })
7636
+ );
7637
+ } catch {
7638
+ }
7639
+ }
7640
+ function registerOrOverride(registry, name, tool) {
7641
+ try {
7642
+ registry.register(tool);
7643
+ } catch {
7644
+ registry.override(name, tool);
7645
+ }
7646
+ }
7647
+
7353
7648
  // src/wiring/lifecycle-plugins.ts
7354
7649
  async function setupLifecycleAndPlugins(deps) {
7355
7650
  const {
@@ -7532,6 +7827,23 @@ async function setupLifecycleAndPlugins(deps) {
7532
7827
  () => hqPublisherRef.current
7533
7828
  );
7534
7829
  const notifier = new NotifierImpl();
7830
+ const getLiveConfig = () => configStore.get();
7831
+ const fallbackProfileManager = container.resolve(TOKENS8.FallbackProfileManager);
7832
+ const statusTracker = container.resolve(TOKENS8.ProviderModelStatusTracker);
7833
+ const buildUtilityProvider = (providerId) => buildProviderForIdRuntimeFn({ config: getLiveConfig(), providerRegistry }, providerId);
7834
+ const pluginOneShot = new OneShotOrchestrator2({
7835
+ buildProvider: buildUtilityProvider,
7836
+ getConfig: getLiveConfig,
7837
+ fallbackProfileManager,
7838
+ statusTracker,
7839
+ modelRouter: createLiveModelRouter(getLiveConfig),
7840
+ logger
7841
+ });
7842
+ const pluginCouncil = new CouncilOrchestrator({
7843
+ caller: pluginOneShot,
7844
+ fallbackProfileManager,
7845
+ ...buildCouncilRegistries(getLiveConfig().tools?.council)
7846
+ });
7535
7847
  const pluginHost = await setupPlugins({
7536
7848
  config,
7537
7849
  container,
@@ -7572,7 +7884,9 @@ async function setupLifecycleAndPlugins(deps) {
7572
7884
  model: config.model,
7573
7885
  getProvider: () => context.provider,
7574
7886
  getModel: () => context.model,
7575
- createProvider: (name) => buildProviderForIdRuntimeFn({ config: configStore.get(), providerRegistry }, name)
7887
+ createProvider: (name) => buildProviderForIdRuntimeFn({ config: configStore.get(), providerRegistry }, name),
7888
+ oneShot: (input) => pluginOneShot.call(input),
7889
+ council: (question) => pluginCouncil.ask(question)
7576
7890
  }
7577
7891
  });
7578
7892
  return {
@@ -7672,6 +7986,61 @@ import {
7672
7986
  } from "@wrongstack/core/storage";
7673
7987
  import { withCatalogCapabilities as withCatalogCapabilities2 } from "@wrongstack/providers";
7674
7988
  import { getSageService } from "@wrongstack/sage";
7989
+
7990
+ // src/wiring/fallback-gate.ts
7991
+ function createFallbackGate(_events) {
7992
+ const gateFn = (params) => {
7993
+ const { events: bus, sessionId, from, status, candidates, autoSwitchSeconds, requestId } = params;
7994
+ return runGate(bus, { sessionId, from, status, candidates, autoSwitchSeconds, requestId });
7995
+ };
7996
+ return gateFn;
7997
+ }
7998
+ function runGate(events, gateParams) {
7999
+ const { sessionId, from, status, candidates, autoSwitchSeconds, requestId } = gateParams;
8000
+ if (events.listenerCount("provider.fallback_pending") === 0) {
8001
+ return Promise.resolve(null);
8002
+ }
8003
+ return new Promise((resolve8) => {
8004
+ let settled = false;
8005
+ let timer;
8006
+ let deadline;
8007
+ const cleanup = () => {
8008
+ if (timer) clearTimeout(timer);
8009
+ if (deadline) clearTimeout(deadline);
8010
+ events.off("provider.fallback_choice", handler);
8011
+ };
8012
+ const finish = (result) => {
8013
+ if (settled) return;
8014
+ settled = true;
8015
+ cleanup();
8016
+ resolve8(result);
8017
+ };
8018
+ const handler = (payload) => {
8019
+ const p = payload;
8020
+ if (p?.requestId !== requestId) return;
8021
+ if (p.autoSwitch === true) {
8022
+ finish(null);
8023
+ return;
8024
+ }
8025
+ if (typeof p.providerId === "string" && typeof p.model === "string") {
8026
+ finish({ providerId: p.providerId, model: p.model });
8027
+ }
8028
+ };
8029
+ events.on("provider.fallback_choice", handler);
8030
+ deadline = setTimeout(() => finish(null), Math.round(autoSwitchSeconds * 1500));
8031
+ events.emit("provider.fallback_pending", {
8032
+ ...sessionId ? { sessionId } : {},
8033
+ from,
8034
+ status,
8035
+ candidates,
8036
+ autoSwitchSeconds,
8037
+ requestId,
8038
+ timestamp: Date.now()
8039
+ });
8040
+ });
8041
+ }
8042
+
8043
+ // src/wiring/provider-runtime-setup.ts
7675
8044
  function serializeProviderRuntimeSnapshot(snapshot) {
7676
8045
  return JSON.stringify(snapshot);
7677
8046
  }
@@ -7736,6 +8105,12 @@ function setupProviderRuntime(deps) {
7736
8105
  events,
7737
8106
  logger,
7738
8107
  statusTracker,
8108
+ // Fallback gate — shows a modal with countdown + manual pick in every
8109
+ // UI surface (TUI/WebUI/SimpleUI) before switching models. The gate
8110
+ // emits provider.fallback_pending and waits for provider.fallback_choice
8111
+ // or the auto-switch countdown.
8112
+ fallbackGate: createFallbackGate(events),
8113
+ fallbackGateSeconds: 7,
7739
8114
  ...cfg.fallbackStickiness?.primaryProbeInterval !== void 0 ? { primaryCooldownMs: cfg.fallbackStickiness.primaryProbeInterval } : {},
7740
8115
  ...cfg.fallbackStickiness?.stickyFallbackTurns !== void 0 ? { stickyFallbackTurns: cfg.fallbackStickiness.stickyFallbackTurns } : {}
7741
8116
  })
@@ -7977,130 +8352,6 @@ function warnUnlessMissing(logger, operation, error) {
7977
8352
  }
7978
8353
  }
7979
8354
 
7980
- // src/wiring/provider-utility-tools.ts
7981
- import { createContextManagerTool as createContextManagerTool2 } from "@wrongstack/core/infrastructure";
7982
- import { createCouncilTool, createOneShotLLMTool } from "@wrongstack/core/tools";
7983
- import {
7984
- createCouncilPersonaRegistry,
7985
- createCouncilProfileRegistry,
7986
- OneShotOrchestrator
7987
- } from "@wrongstack/core/execution";
7988
- import { ModelRouter } from "@wrongstack/core/models";
7989
- async function adoptResumedProvider(input) {
7990
- if (!input.resumedProvider && !input.resumedModel) return;
7991
- const config = input.getConfig();
7992
- const provider = input.resumedProvider?.trim() || config.provider;
7993
- const model = input.resumedModel?.trim() || config.model;
7994
- if (provider === config.provider && model === config.model) return;
7995
- const error = await input.switchProviderAndModel(provider, model);
7996
- if (error) {
7997
- const current = input.getConfig();
7998
- input.logger.warn(
7999
- `Resume: could not switch to the session's model ${provider}/${model} (${error}); continuing with ${current.provider}/${current.model}.`
8000
- );
8001
- }
8002
- }
8003
- function createLiveModelRouter(getConfig) {
8004
- return {
8005
- pickForTask(role, description) {
8006
- const config = getConfig();
8007
- const router = new ModelRouter({
8008
- ...config.modelMatrix ? { matrix: config.modelMatrix } : {},
8009
- config: {
8010
- provider: config.provider,
8011
- model: config.model,
8012
- ...config.providers ? { providers: config.providers } : {}
8013
- }
8014
- });
8015
- return router.pickForTask(role, description);
8016
- }
8017
- };
8018
- }
8019
- function buildCouncilRegistries(cfg) {
8020
- const base = {
8021
- ...cfg?.defaultProfile ? { defaultProfile: cfg.defaultProfile } : {},
8022
- ...cfg?.maxConcurrency !== void 0 ? { maxConcurrency: cfg.maxConcurrency } : {}
8023
- };
8024
- if (!cfg?.personas?.length && !cfg?.profiles?.length) return base;
8025
- try {
8026
- const personas = createCouncilPersonaRegistry(cfg.personas ?? []);
8027
- const profiles = createCouncilProfileRegistry(
8028
- cfg.profiles ?? [],
8029
- personas
8030
- );
8031
- return { ...base, personas, profiles };
8032
- } catch (error) {
8033
- console.warn(
8034
- `Council tool: ignoring tools.council personas/profiles \u2014 ${error instanceof Error ? error.message : String(error)}. Falling back to the built-in lenses and panels.`
8035
- );
8036
- return base;
8037
- }
8038
- }
8039
- function registerProviderUtilityTools(input) {
8040
- const config = input.getConfig();
8041
- const llmTool = createOneShotLLMTool({
8042
- buildProvider: input.buildProvider,
8043
- getConfig: input.getConfig,
8044
- fallbackProfileManager: input.fallbackProfileManager,
8045
- defaultProvider: config.provider,
8046
- defaultModel: config.model
8047
- });
8048
- registerOrOverride(input.toolRegistry, "llm", llmTool);
8049
- const councilOrchestrator = new OneShotOrchestrator({
8050
- buildProvider: input.buildProvider,
8051
- getConfig: input.getConfig,
8052
- fallbackProfileManager: input.fallbackProfileManager,
8053
- statusTracker: input.statusTracker,
8054
- // Council profiles route each seat by ROLE ('planner', 'critic',
8055
- // 'analyst', 'security-reviewer'…) rather than pinning models. Without a
8056
- // router those hints were inert: every seat fell through to the session
8057
- // provider/model, so a three-seat panel asked one model three times and
8058
- // reported a distinctness warning on every single call.
8059
- modelRouter: createLiveModelRouter(input.getConfig)
8060
- });
8061
- registerOrOverride(
8062
- input.toolRegistry,
8063
- "council",
8064
- createCouncilTool({
8065
- caller: councilOrchestrator,
8066
- fallbackProfileManager: input.fallbackProfileManager,
8067
- ...buildCouncilRegistries(config.tools?.council)
8068
- })
8069
- );
8070
- try {
8071
- const summarizer = new OneShotOrchestrator({
8072
- buildProvider: input.buildProvider,
8073
- getConfig: input.getConfig,
8074
- fallbackProfileManager: input.fallbackProfileManager,
8075
- statusTracker: input.statusTracker
8076
- });
8077
- input.toolRegistry.override(
8078
- "context_manager",
8079
- createContextManagerTool2({
8080
- compactor: input.compactor,
8081
- summarizer: async (messages) => {
8082
- const result = await summarizer.call({
8083
- system: "Summarize concisely. Keep decisions and key facts.",
8084
- messages,
8085
- model: "deepseek-chat",
8086
- maxTokens: 1024,
8087
- timeoutMs: 3e4
8088
- });
8089
- return result.text || "(summary unavailable)";
8090
- }
8091
- })
8092
- );
8093
- } catch {
8094
- }
8095
- }
8096
- function registerOrOverride(registry, name, tool) {
8097
- try {
8098
- registry.register(tool);
8099
- } catch {
8100
- registry.override(name, tool);
8101
- }
8102
- }
8103
-
8104
8355
  // src/wiring/runtime-controller-deps.ts
8105
8356
  import { resolveConfiguredRefinerRef, resolveEnhanceFallbackRef } from "@wrongstack/core/execution";
8106
8357
  function createRuntimeControllerDeps(input) {
@@ -9055,8 +9306,9 @@ async function setupSession(params) {
9055
9306
  const tCounts = {};
9056
9307
  for (const t of dirState.tasks) tCounts[t.status] = (tCounts[t.status] ?? 0) + 1;
9057
9308
  const summary = Object.entries(tCounts).map(([k, v]) => `${v} ${k}`).join(", ");
9309
+ const spawnPart = typeof dirState.maxSpawns === "number" && Number.isFinite(dirState.maxSpawns) ? `, spawns ${dirState.spawnCount}/${dirState.maxSpawns} (checkpoint ceiling; live profile may differ)` : `, spawns used ${dirState.spawnCount}`;
9058
9310
  renderer.writeInfo(
9059
- `Prior fleet state: ${dirState.subagents.length} subagent${dirState.subagents.length === 1 ? "" : "s"}, tasks ${summary || "(none)"}.`
9311
+ `Prior fleet state: ${dirState.subagents.length} subagent${dirState.subagents.length === 1 ? "" : "s"}, tasks ${summary || "(none)"}${spawnPart}.`
9060
9312
  );
9061
9313
  }
9062
9314
  } catch {
@@ -12095,6 +12347,7 @@ function cacheMechanismLabel(providerId, cacheControl) {
12095
12347
  if (id.includes("google") || id.includes("gemini")) {
12096
12348
  return "implicit (auto) + explicit cachedContents (opt-in)";
12097
12349
  }
12350
+ if (id.includes("gateway")) return "automatic (Gateway-managed, per routed upstream)";
12098
12351
  if (cacheControl === "auto") return "automatic + prompt_cache_key routing";
12099
12352
  return "none / provider-managed";
12100
12353
  }
@@ -13097,6 +13350,58 @@ function diagnoseConfig(cfg, plugins = []) {
13097
13350
  }
13098
13351
  }
13099
13352
  }
13353
+ if ("fleet" in fixed) {
13354
+ if (!isPlainObject(fixed["fleet"])) {
13355
+ findings.push({
13356
+ path: "fleet",
13357
+ problem: `expected object, got ${JSON.stringify(fixed["fleet"])}`,
13358
+ severity: "error",
13359
+ fix: "removed (built-in defaults apply)"
13360
+ });
13361
+ delete fixed["fleet"];
13362
+ } else {
13363
+ const fleet = fixed["fleet"];
13364
+ if ("budget" in fleet) {
13365
+ if (!isPlainObject(fleet["budget"])) {
13366
+ findings.push({
13367
+ path: "fleet.budget",
13368
+ problem: `expected object, got ${JSON.stringify(fleet["budget"])}`,
13369
+ severity: "error",
13370
+ fix: "removed (built-in defaults apply)"
13371
+ });
13372
+ delete fleet["budget"];
13373
+ } else {
13374
+ const budget = fleet["budget"];
13375
+ for (const key of ["maxSpawns", "maxTokens", "maxCostUsd"]) {
13376
+ if (!(key in budget)) continue;
13377
+ const v = budget[key];
13378
+ const n = coerceNumber(v);
13379
+ if (n === void 0) {
13380
+ delete budget[key];
13381
+ findings.push({
13382
+ path: `fleet.budget.${key}`,
13383
+ problem: `expected a non-negative number, got ${JSON.stringify(v)}`,
13384
+ severity: "error",
13385
+ fix: "removed (built-in default applies)"
13386
+ });
13387
+ } else {
13388
+ const clamped = Math.max(0, n);
13389
+ const next = key === "maxCostUsd" ? clamped : Math.floor(clamped);
13390
+ if (next !== v) {
13391
+ budget[key] = next;
13392
+ findings.push({
13393
+ path: `fleet.budget.${key}`,
13394
+ problem: `expected a non-negative ${key === "maxCostUsd" ? "number" : "integer"}, got ${JSON.stringify(v)}`,
13395
+ severity: "error",
13396
+ fix: `set to ${next}`
13397
+ });
13398
+ }
13399
+ }
13400
+ }
13401
+ }
13402
+ }
13403
+ }
13404
+ }
13100
13405
  for (const key of ["provider", "model"]) {
13101
13406
  if (key in fixed && typeof fixed[key] !== "string") {
13102
13407
  findings.push({
@@ -13380,7 +13685,7 @@ function buildDoctorCommand(opts) {
13380
13685
  ].join("\n");
13381
13686
  async function loadPluginSchemas() {
13382
13687
  try {
13383
- const { BUILTIN_PLUGIN_FACTORIES } = await import("./plugins-ETY6W3DC.js");
13688
+ const { BUILTIN_PLUGIN_FACTORIES } = await import("./plugins-56CMWMPR.js");
13384
13689
  const settled = await Promise.allSettled(BUILTIN_PLUGIN_FACTORIES.map((f) => f()));
13385
13690
  const loaded = [];
13386
13691
  for (const s of settled) {
@@ -15297,6 +15602,17 @@ async function handleStatus(opts, cmd) {
15297
15602
  lines.push(` ${id} ${name} ${statusColor} ${ext}${task}`);
15298
15603
  }
15299
15604
  }
15605
+ const budget = opts.onFleetBudget?.();
15606
+ if (budget) {
15607
+ lines.push(
15608
+ "",
15609
+ ...formatFleetBudgetLines(budget, {
15610
+ bold: color26.bold,
15611
+ dim: color26.dim,
15612
+ amber: color26.amber
15613
+ })
15614
+ );
15615
+ }
15300
15616
  const msg2 = lines.join("\n");
15301
15617
  opts.renderer.write(msg2);
15302
15618
  return { message: msg2 };
@@ -23502,6 +23818,26 @@ import { fallbackProfileChain } from "@wrongstack/core/agent";
23502
23818
  import { decryptConfigSecrets as decryptConfigSecrets4, encryptConfigSecrets as encryptConfigSecrets4, noOpVault as noOpVault6 } from "@wrongstack/core/security";
23503
23819
  import { MATRIX_PHASE_KEYS, matrixKeyKind, phaseForRole, resolveModelMatrix, resolveModelTargetFromEntry } from "@wrongstack/core/coordination";
23504
23820
  import { parseModelRef as parseModelRef3 } from "@wrongstack/core/agent";
23821
+ import { catalogProviderIdFor } from "@wrongstack/providers";
23822
+ async function resolveCatalogModelIds(registry, config, providerIds) {
23823
+ const out = /* @__PURE__ */ new Map();
23824
+ if (!registry) return out;
23825
+ await Promise.all(
23826
+ providerIds.map(async (id) => {
23827
+ try {
23828
+ const catalogId = catalogProviderIdFor(id, config.providers?.[id]?.type);
23829
+ const provider = await registry.getProvider(catalogId);
23830
+ if (provider) out.set(id, provider.models.map((m) => m.id));
23831
+ } catch {
23832
+ }
23833
+ })
23834
+ );
23835
+ return out;
23836
+ }
23837
+ function summarizeModelIds(ids, limit = 8) {
23838
+ if (ids.length <= limit) return ids.join(", ");
23839
+ return `${ids.slice(0, limit).join(", ")} ${color44.dim(`\u2026 +${ids.length - limit} more`)}`;
23840
+ }
23505
23841
  function providerHasKey(entry) {
23506
23842
  if (!entry) return false;
23507
23843
  if (typeof entry.apiKey === "string" && entry.apiKey.length > 0) return true;
@@ -23703,9 +24039,10 @@ function buildSetModelCommand(opts) {
23703
24039
  );
23704
24040
  const matrix = config.modelMatrix ?? {};
23705
24041
  if (sub === "list") {
24042
+ const catalogModels = await resolveCatalogModelIds(opts.modelsRegistry, config, keyed);
23706
24043
  const provLines = keyed.map((id) => {
23707
- const models = config.providers?.[id]?.models ?? [];
23708
- const ms = models.length ? models.join(", ") : color44.dim("(any model id accepted)");
24044
+ const models = visibleModelIds(id, config, catalogModels.get(id) ?? []);
24045
+ const ms = models.length ? summarizeModelIds(models) : color44.dim("(any model id accepted)");
23709
24046
  return ` ${color44.cyan(id.padEnd(16))} ${ms}`;
23710
24047
  });
23711
24048
  const roles = Object.keys(AGENT_CATALOG2).sort();
@@ -23781,6 +24118,11 @@ function buildSetModelCommand(opts) {
23781
24118
  if (sub === "doctor") {
23782
24119
  const issues = [];
23783
24120
  const warnings = [];
24121
+ const doctorCatalogModels = await resolveCatalogModelIds(
24122
+ opts.modelsRegistry,
24123
+ config,
24124
+ keyed
24125
+ );
23784
24126
  for (const [key, entry] of Object.entries(matrix)) {
23785
24127
  const kind = matrixKeyKind(key);
23786
24128
  if (kind === "unknown") {
@@ -23803,9 +24145,14 @@ function buildSetModelCommand(opts) {
23803
24145
  const effectiveProvider = entry.provider ?? config.provider;
23804
24146
  const provCfg = config.providers?.[effectiveProvider];
23805
24147
  if (entry.model && provCfg?.models && provCfg.models.length > 0) {
23806
- if (!provCfg.models.includes(entry.model)) {
24148
+ const reachable = visibleModelIds(
24149
+ effectiveProvider,
24150
+ config,
24151
+ doctorCatalogModels.get(effectiveProvider) ?? []
24152
+ );
24153
+ if (!reachable.includes(entry.model)) {
23807
24154
  warnings.push(
23808
- `${color44.amber("\u26A0")} ${color44.amber(key)}: model "${entry.model}" not in ${effectiveProvider}'s model list (${provCfg.models.join(", ")})`
24155
+ `${color44.amber("\u26A0")} ${color44.amber(key)}: model "${entry.model}" not in ${effectiveProvider}'s model list (${summarizeModelIds(reachable)})`
23809
24156
  );
23810
24157
  }
23811
24158
  }
@@ -30084,6 +30431,9 @@ async function runInteractive(cliCtx) {
30084
30431
  let {
30085
30432
  director,
30086
30433
  maxConcurrent,
30434
+ maxSpawns,
30435
+ maxConcurrentSource,
30436
+ maxSpawnsSource,
30087
30437
  autonomyMode,
30088
30438
  nextPredictEnabled,
30089
30439
  currentSuggestions,
@@ -30136,6 +30486,9 @@ async function runInteractive(cliCtx) {
30136
30486
  stateCheckpointPath,
30137
30487
  fleetRootForPromotion,
30138
30488
  maxConcurrent,
30489
+ maxSpawns,
30490
+ maxConcurrentSource,
30491
+ maxSpawnsSource,
30139
30492
  effectiveMaxContextRef,
30140
30493
  mcpRegistry,
30141
30494
  sessResult,
@@ -30176,11 +30529,30 @@ async function runInteractive(cliCtx) {
30176
30529
  for (const tool of director.tools(FLEET_ROSTER5)) {
30177
30530
  toolRegistry.register(tool);
30178
30531
  }
30179
- renderer.writeInfo(`Director mode enabled. Roster: ${Object.keys(FLEET_ROSTER5).join(", ")}`);
30180
- renderer.writeInfo(` fleet root \u2192 ${fleetRoot}`);
30181
- renderer.writeInfo(` manifest \u2192 ${manifestPath}`);
30182
- renderer.writeInfo(` scratchpad \u2192 ${sharedScratchpadPath}`);
30183
- renderer.writeInfo(` subagents \u2192 ${subagentSessionsRoot}`);
30532
+ const browserSurface = flags.webui === true || flags.simpleui === true;
30533
+ if (browserSurface) {
30534
+ renderer.writeInfo(
30535
+ `Director mode enabled (${Object.keys(FLEET_ROSTER5).length} roles) \u2192 ${fleetRoot}`
30536
+ );
30537
+ } else {
30538
+ renderer.writeInfo(`Director mode enabled. Roster: ${Object.keys(FLEET_ROSTER5).join(", ")}`);
30539
+ renderer.writeInfo(` fleet root \u2192 ${fleetRoot}`);
30540
+ renderer.writeInfo(` manifest \u2192 ${manifestPath}`);
30541
+ renderer.writeInfo(` scratchpad \u2192 ${sharedScratchpadPath}`);
30542
+ renderer.writeInfo(` subagents \u2192 ${subagentSessionsRoot}`);
30543
+ }
30544
+ if (priorFleetState) {
30545
+ const budget = multiAgentHost.budgetView();
30546
+ const fmt = (n) => Number.isFinite(n) ? String(n) : "\u221E";
30547
+ renderer.writeInfo(
30548
+ ` fleet budget \u2192 ${budget.usedSpawns}/${fmt(budget.maxSpawns)} spawns used (${fmt(budget.remainingSpawns)} remaining; maxConcurrent ${budget.maxConcurrent})`
30549
+ );
30550
+ if (budget.ceilingMismatch && budget.checkpointMaxSpawns !== void 0) {
30551
+ renderer.writeInfo(
30552
+ ` \u26A0 checkpoint maxSpawns was ${budget.checkpointMaxSpawns}; live ceiling is ${fmt(budget.maxSpawns)}`
30553
+ );
30554
+ }
30555
+ }
30184
30556
  } else {
30185
30557
  renderer.writeInfo(`Running without Director \u2014 fleet orchestration tools disabled.`);
30186
30558
  }
@@ -30404,7 +30776,7 @@ async function runInteractive(cliCtx) {
30404
30776
  onEvent: evOn
30405
30777
  });
30406
30778
  const savedProviderCfg = config.providers?.[config.provider];
30407
- const { execute } = await import("./execution-ANOYMWPO.js");
30779
+ const { execute } = await import("./execution-SHGM7BVC.js");
30408
30780
  const stopHeapWatchdog = startSharedHeapWatchdog({
30409
30781
  collectStats: () => {
30410
30782
  const hqQueue = hqPublisherRef.current?.getQueueStats();
@@ -30636,4 +31008,4 @@ export {
30636
31008
  CLI_VERSION,
30637
31009
  runInteractive
30638
31010
  };
30639
- //# sourceMappingURL=cli-main-3MQDFSYK.js.map
31011
+ //# sourceMappingURL=cli-main-7B3G2YSG.js.map