iosm-cli 0.2.3 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +32 -5
  3. package/dist/cli/args.d.ts +1 -1
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +1 -1
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/core/agent-profiles.d.ts +1 -1
  8. package/dist/core/agent-profiles.d.ts.map +1 -1
  9. package/dist/core/agent-profiles.js +9 -0
  10. package/dist/core/agent-profiles.js.map +1 -1
  11. package/dist/core/agent-session.d.ts +7 -0
  12. package/dist/core/agent-session.d.ts.map +1 -1
  13. package/dist/core/agent-session.js +58 -13
  14. package/dist/core/agent-session.js.map +1 -1
  15. package/dist/core/extensions/types.d.ts +1 -1
  16. package/dist/core/extensions/types.d.ts.map +1 -1
  17. package/dist/core/extensions/types.js.map +1 -1
  18. package/dist/core/orchestration-limits.d.ts +6 -0
  19. package/dist/core/orchestration-limits.d.ts.map +1 -0
  20. package/dist/core/orchestration-limits.js +6 -0
  21. package/dist/core/orchestration-limits.js.map +1 -0
  22. package/dist/core/sdk.d.ts +6 -1
  23. package/dist/core/sdk.d.ts.map +1 -1
  24. package/dist/core/sdk.js +34 -6
  25. package/dist/core/sdk.js.map +1 -1
  26. package/dist/core/subagents.d.ts.map +1 -1
  27. package/dist/core/subagents.js +21 -7
  28. package/dist/core/subagents.js.map +1 -1
  29. package/dist/core/tools/edit.d.ts +8 -4
  30. package/dist/core/tools/edit.d.ts.map +1 -1
  31. package/dist/core/tools/edit.js +18 -3
  32. package/dist/core/tools/edit.js.map +1 -1
  33. package/dist/core/tools/index.d.ts +9 -7
  34. package/dist/core/tools/index.d.ts.map +1 -1
  35. package/dist/core/tools/task.d.ts +10 -3
  36. package/dist/core/tools/task.d.ts.map +1 -1
  37. package/dist/core/tools/task.js +404 -149
  38. package/dist/core/tools/task.js.map +1 -1
  39. package/dist/core/tools/todo.d.ts +10 -10
  40. package/dist/core/tools/todo.d.ts.map +1 -1
  41. package/dist/core/tools/todo.js +135 -17
  42. package/dist/core/tools/todo.js.map +1 -1
  43. package/dist/modes/interactive/components/footer.d.ts +1 -1
  44. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  45. package/dist/modes/interactive/components/footer.js +8 -8
  46. package/dist/modes/interactive/components/footer.js.map +1 -1
  47. package/dist/modes/interactive/interactive-mode.d.ts +9 -0
  48. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  49. package/dist/modes/interactive/interactive-mode.js +214 -14
  50. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  51. package/docs/cli-reference.md +4 -0
  52. package/docs/configuration.md +5 -1
  53. package/docs/interactive-mode.md +5 -1
  54. package/package.json +1 -1
@@ -15,6 +15,7 @@ import { parseSkillBlock } from "../../core/agent-session.js";
15
15
  import { FooterDataProvider } from "../../core/footer-data-provider.js";
16
16
  import { KeybindingsManager } from "../../core/keybindings.js";
17
17
  import { createCompactionSummaryMessage, INTERNAL_UI_META_CUSTOM_TYPE, isInternalUiMetaDetails, } from "../../core/messages.js";
18
+ import { MAX_ORCHESTRATION_AGENTS, MAX_ORCHESTRATION_PARALLEL, MAX_SUBAGENT_DELEGATE_PARALLEL, } from "../../core/orchestration-limits.js";
18
19
  import { loadModelsDevProviderCatalog, } from "../../core/models-dev-provider-catalog.js";
19
20
  import { ModelRegistry } from "../../core/model-registry.js";
20
21
  import { MODELS_DEV_PROVIDERS } from "../../core/models-dev-providers.js";
@@ -75,6 +76,152 @@ import { getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMar
75
76
  function isExpandable(obj) {
76
77
  return typeof obj === "object" && obj !== null && "setExpanded" in obj && typeof obj.setExpanded === "function";
77
78
  }
79
+ export function resolveStreamingSubmissionMode(input) {
80
+ if (input.configuredMode === "meta" &&
81
+ input.activeProfileName === "meta" &&
82
+ (input.activeSubagentCount > 0 || input.activeAssistantOrchestrationContext)) {
83
+ return "followUp";
84
+ }
85
+ return input.configuredMode;
86
+ }
87
+ function parseRequestedParallelAgentCount(text) {
88
+ const patterns = [
89
+ /(\d+)\s+(?:parallel|concurrent)\s+agents?/i,
90
+ /(\d+)\s+agents?/i,
91
+ /(\d+)\s+паралл\w*\s+агент\w*/i,
92
+ /(\d+)\s+агент\w*/i,
93
+ ];
94
+ for (const pattern of patterns) {
95
+ const match = text.match(pattern);
96
+ const parsed = match?.[1] ? Number.parseInt(match[1], 10) : Number.NaN;
97
+ if (Number.isInteger(parsed) && parsed >= 1) {
98
+ return Math.max(1, Math.min(MAX_ORCHESTRATION_AGENTS, parsed));
99
+ }
100
+ }
101
+ return undefined;
102
+ }
103
+ function deriveMetaRequiredTopLevelTaskCalls(userInput, taskPlanSnapshot) {
104
+ const requested = parseRequestedParallelAgentCount(userInput);
105
+ if (requested)
106
+ return requested;
107
+ if (!taskPlanSnapshot)
108
+ return undefined;
109
+ return Math.max(2, Math.min(3, taskPlanSnapshot.totalSteps));
110
+ }
111
+ function extractTaskToolErrorText(result) {
112
+ if (!result || typeof result !== "object")
113
+ return undefined;
114
+ const candidate = result;
115
+ if (typeof candidate.error === "string" && candidate.error.trim())
116
+ return candidate.error.trim();
117
+ if (typeof candidate.output === "string" && candidate.output.trim())
118
+ return candidate.output.trim();
119
+ return undefined;
120
+ }
121
+ function buildMetaParallelismCorrection(input) {
122
+ const validationFailure = input.taskToolError && /Validation failed for tool "task"/i.test(input.taskToolError)
123
+ ? input.taskToolError.split("\n").slice(0, 3).join("\n")
124
+ : undefined;
125
+ return [
126
+ "[META_PARALLELISM_CORRECTION]",
127
+ `Meta runtime correction: this run currently has ${input.launchedTopLevelTasks} top-level task call(s), but it should have at least ${input.requiredTopLevelTasks}.`,
128
+ "Stop manual sequential execution in the main agent and convert the execution graph into parallel task calls now.",
129
+ "Emit the missing top-level task calls in the same assistant response when branches are independent.",
130
+ "Each task tool call MUST include description and prompt.",
131
+ 'If you want a custom subagent, pass it via agent="name"; keep profile set to the capability profile, not the custom subagent name.',
132
+ input.rawRootDelegateBlocks && input.rawRootDelegateBlocks > 0
133
+ ? `You emitted ${input.rawRootDelegateBlocks} raw root-level <delegate_task> block(s). Those are not executed automatically in the parent session. Convert each one into an actual top-level task tool call now.`
134
+ : undefined,
135
+ "If a child workstream is still broad, require nested <delegate_task> fan-out instead of letting one child do everything alone.",
136
+ input.taskPlanSnapshot
137
+ ? `You already produced a complex plan with ${input.taskPlanSnapshot.totalSteps} steps. Turn that plan into parallel execution now.`
138
+ : undefined,
139
+ validationFailure ? `Previous task validation failure:\n${validationFailure}` : undefined,
140
+ "If you truly cannot split safely, output exactly one line: DELEGATION_IMPOSSIBLE: <precise reason>.",
141
+ "[/META_PARALLELISM_CORRECTION]",
142
+ ]
143
+ .filter((line) => typeof line === "string" && line.trim().length > 0)
144
+ .join("\n");
145
+ }
146
+ async function promptMetaWithParallelismGuard(input) {
147
+ let taskToolCalls = 0;
148
+ let nonTaskToolCalls = 0;
149
+ let taskPlanSnapshot;
150
+ let taskToolError;
151
+ let rawRootDelegateBlocks = 0;
152
+ let delegationImpossibleDeclared = false;
153
+ let correctionText;
154
+ const maybeScheduleCorrection = () => {
155
+ const requiredTopLevelTasks = deriveMetaRequiredTopLevelTaskCalls(input.userInput, taskPlanSnapshot);
156
+ if (!requiredTopLevelTasks || taskToolCalls >= requiredTopLevelTasks || delegationImpossibleDeclared) {
157
+ return;
158
+ }
159
+ const hasComplexPlan = !!taskPlanSnapshot;
160
+ const hasTaskFailure = !!taskToolError;
161
+ const hasRawRootDelegates = rawRootDelegateBlocks > 0;
162
+ if (!hasTaskFailure && !hasRawRootDelegates && nonTaskToolCalls < 1) {
163
+ return;
164
+ }
165
+ if (!hasComplexPlan && !hasTaskFailure && !hasRawRootDelegates && nonTaskToolCalls < 2) {
166
+ return;
167
+ }
168
+ correctionText = buildMetaParallelismCorrection({
169
+ requiredTopLevelTasks,
170
+ launchedTopLevelTasks: taskToolCalls,
171
+ taskPlanSnapshot,
172
+ taskToolError,
173
+ rawRootDelegateBlocks,
174
+ });
175
+ };
176
+ const unsubscribe = input.session.subscribe((event) => {
177
+ if (event.type === "message_end" && event.message.role === "custom") {
178
+ if (event.message.customType === TASK_PLAN_CUSTOM_TYPE && isTaskPlanSnapshot(event.message.details)) {
179
+ taskPlanSnapshot = event.message.details;
180
+ maybeScheduleCorrection();
181
+ }
182
+ return;
183
+ }
184
+ if (event.type === "message_end" && event.message.role === "assistant") {
185
+ const rawText = extractAssistantText(event.message);
186
+ rawRootDelegateBlocks += (rawText.match(/<delegate_task\b/gi) ?? []).length;
187
+ delegationImpossibleDeclared =
188
+ delegationImpossibleDeclared || /^\s*DELEGATION_IMPOSSIBLE\s*:/im.test(rawText);
189
+ maybeScheduleCorrection();
190
+ return;
191
+ }
192
+ if (event.type === "tool_execution_start") {
193
+ if (event.toolName === "task") {
194
+ taskToolCalls += 1;
195
+ }
196
+ else {
197
+ nonTaskToolCalls += 1;
198
+ }
199
+ maybeScheduleCorrection();
200
+ return;
201
+ }
202
+ if (event.type === "tool_execution_end" && event.toolName === "task" && event.isError) {
203
+ taskToolError = extractTaskToolErrorText(event.result) ?? taskToolError;
204
+ maybeScheduleCorrection();
205
+ }
206
+ });
207
+ try {
208
+ await input.session.prompt(input.userInput);
209
+ const requiredTopLevelTasks = deriveMetaRequiredTopLevelTaskCalls(input.userInput, taskPlanSnapshot);
210
+ if (correctionText &&
211
+ requiredTopLevelTasks &&
212
+ taskToolCalls < requiredTopLevelTasks &&
213
+ !delegationImpossibleDeclared) {
214
+ await input.session.prompt(correctionText, {
215
+ expandPromptTemplates: false,
216
+ skipOrchestrationDirective: true,
217
+ source: "interactive",
218
+ });
219
+ }
220
+ }
221
+ finally {
222
+ unsubscribe();
223
+ }
224
+ }
78
225
  const IOSM_PROFILE_ONLY_COMMANDS = new Set(["iosm", "cycle-list", "cycle-plan", "cycle-status", "cycle-report"]);
79
226
  const CHECKPOINT_LABEL_PREFIX = "checkpoint:";
80
227
  const INTERRUPT_ABORT_TIMEOUT_MS = 8_000;
@@ -411,6 +558,7 @@ export class InteractiveMode {
411
558
  // Streaming message tracking
412
559
  this.streamingComponent = undefined;
413
560
  this.streamingMessage = undefined;
561
+ this.currentTurnSawAssistantMessage = false;
414
562
  // Tool execution tracking: toolCallId -> component
415
563
  this.pendingTools = new Map();
416
564
  // Subagent execution tracking with live progress/metadata for task tool calls.
@@ -2917,9 +3065,18 @@ export class InteractiveMode {
2917
3065
  // If streaming, use configured stream input mode (meta/followUp/steer)
2918
3066
  // This handles extension commands (execute immediately), prompt template expansion, and queueing
2919
3067
  if (this.session.isStreaming) {
3068
+ const streamingBehavior = resolveStreamingSubmissionMode({
3069
+ configuredMode: this.session.streamInputMode,
3070
+ activeProfileName: this.activeProfileName,
3071
+ activeSubagentCount: this.subagentComponents.size,
3072
+ activeAssistantOrchestrationContext: this.activeAssistantOrchestrationContext,
3073
+ });
2920
3074
  this.editor.addToHistory?.(text);
2921
3075
  this.editor.setText("");
2922
- await this.session.prompt(text, { streamingBehavior: this.session.streamInputMode });
3076
+ await this.session.prompt(text, { streamingBehavior });
3077
+ if (streamingBehavior !== this.session.streamInputMode) {
3078
+ this.showStatus("Queued follow-up until meta orchestration completes");
3079
+ }
2923
3080
  this.updatePendingMessagesDisplay();
2924
3081
  this.ui.requestRender();
2925
3082
  return;
@@ -2998,6 +3155,7 @@ export class InteractiveMode {
2998
3155
  this.footer.invalidate();
2999
3156
  switch (event.type) {
3000
3157
  case "agent_start":
3158
+ this.currentTurnSawAssistantMessage = false;
3001
3159
  // Restore main escape handler if retry handler is still active
3002
3160
  // (retry success event fires later, but we need main handler now)
3003
3161
  if (this.retryEscapeHandler) {
@@ -3034,6 +3192,7 @@ export class InteractiveMode {
3034
3192
  this.ui.requestRender();
3035
3193
  }
3036
3194
  else if (event.message.role === "assistant") {
3195
+ this.currentTurnSawAssistantMessage = true;
3037
3196
  this.activeAssistantOrchestrationContext = this.pendingAssistantOrchestrationContexts > 0;
3038
3197
  if (this.activeAssistantOrchestrationContext) {
3039
3198
  this.pendingAssistantOrchestrationContexts -= 1;
@@ -3084,6 +3243,7 @@ export class InteractiveMode {
3084
3243
  if (this.streamingComponent && event.message.role === "assistant") {
3085
3244
  this.streamingMessage = event.message;
3086
3245
  let errorMessage;
3246
+ let interruptedStopReason;
3087
3247
  if (this.streamingMessage.stopReason === "aborted") {
3088
3248
  const retryAttempt = this.session.retryAttempt;
3089
3249
  errorMessage =
@@ -3091,9 +3251,13 @@ export class InteractiveMode {
3091
3251
  ? `Aborted after ${retryAttempt} retry attempt${retryAttempt > 1 ? "s" : ""}`
3092
3252
  : "Operation aborted";
3093
3253
  this.streamingMessage.errorMessage = errorMessage;
3254
+ interruptedStopReason = "aborted";
3094
3255
  }
3095
3256
  this.streamingComponent.updateContent(this.sanitizeAssistantDisplayMessage(this.streamingMessage));
3096
3257
  if (this.streamingMessage.stopReason === "aborted" || this.streamingMessage.stopReason === "error") {
3258
+ if (this.streamingMessage.stopReason === "error") {
3259
+ interruptedStopReason = "error";
3260
+ }
3097
3261
  if (!errorMessage) {
3098
3262
  errorMessage = this.streamingMessage.errorMessage || "Error";
3099
3263
  }
@@ -3111,6 +3275,9 @@ export class InteractiveMode {
3111
3275
  component.setArgsComplete();
3112
3276
  }
3113
3277
  }
3278
+ if (interruptedStopReason) {
3279
+ this.showMetaModeInterruptionHint(interruptedStopReason);
3280
+ }
3114
3281
  this.streamingComponent = undefined;
3115
3282
  this.streamingMessage = undefined;
3116
3283
  this.activeAssistantOrchestrationContext = false;
@@ -3330,6 +3497,9 @@ export class InteractiveMode {
3330
3497
  break;
3331
3498
  }
3332
3499
  case "agent_end":
3500
+ if (this.activeProfileName === "meta" && !this.currentTurnSawAssistantMessage) {
3501
+ this.showMetaModeInterruptionHint("error");
3502
+ }
3333
3503
  if (this.loadingAnimation) {
3334
3504
  this.loadingAnimation.stop();
3335
3505
  this.loadingAnimation = undefined;
@@ -3343,6 +3513,7 @@ export class InteractiveMode {
3343
3513
  this.pendingTools.clear();
3344
3514
  this.subagentComponents.clear();
3345
3515
  this.clearSubagentElapsedTimer();
3516
+ this.currentTurnSawAssistantMessage = false;
3346
3517
  await this.checkShutdownRequested();
3347
3518
  this.ui.requestRender();
3348
3519
  break;
@@ -3459,7 +3630,12 @@ export class InteractiveMode {
3459
3630
  return;
3460
3631
  if (message.details.kind !== "orchestration_context")
3461
3632
  return;
3462
- this.pendingAssistantOrchestrationContexts += 1;
3633
+ // Hide assistant prose only for explicit legacy orchestration contracts.
3634
+ // META profile guidance should not suppress normal chat/task responses.
3635
+ const rawPrompt = message.details.rawPrompt ?? "";
3636
+ if (rawPrompt.includes("[ORCHESTRATION_DIRECTIVE]")) {
3637
+ this.pendingAssistantOrchestrationContexts += 1;
3638
+ }
3463
3639
  if (message.details.rawPrompt && message.details.displayText) {
3464
3640
  this.pendingInternalUserDisplayAliases.push({
3465
3641
  rawPrompt: message.details.rawPrompt,
@@ -3490,6 +3666,21 @@ export class InteractiveMode {
3490
3666
  this.lastStatusText = text;
3491
3667
  this.ui.requestRender();
3492
3668
  }
3669
+ showMetaModeInterruptionHint(reason) {
3670
+ if (this.activeProfileName !== "meta")
3671
+ return;
3672
+ const reasonText = reason === "error" ? "response failed unexpectedly" : "response was interrupted";
3673
+ this.showWarning(`META mode ${reasonText}. ` +
3674
+ "Please repeat your request following META profile rules: concrete repository task (goal + scope + constraints + expected output). " +
3675
+ "For conversational chat, switch profile to `full` (Shift+Tab).");
3676
+ }
3677
+ showMetaModeProfileHint() {
3678
+ if (this.activeProfileName !== "meta")
3679
+ return;
3680
+ this.showWarning("META mode is orchestration-first. " +
3681
+ "Send concrete repository tasks (goal + scope + constraints + expected output). " +
3682
+ "For conversational chat, switch profile to `full` (Shift+Tab).");
3683
+ }
3493
3684
  showProgressLine(message) {
3494
3685
  this.chatContainer.addChild(new Spacer(1));
3495
3686
  this.chatContainer.addChild(new Text(theme.fg("dim", message), 1, 0));
@@ -3890,6 +4081,7 @@ export class InteractiveMode {
3890
4081
  const nextActiveTools = this.getProfileToolNames(profile.name);
3891
4082
  this.session.setActiveToolsByName(nextActiveTools);
3892
4083
  this.session.setThinkingLevel(profile.thinkingLevel);
4084
+ this.session.setProfileName(profile.name);
3893
4085
  this.profilePromptSuffix = profile.systemPromptAppend || undefined;
3894
4086
  this.syncRuntimePromptSuffix();
3895
4087
  this.session.setIosmAutopilotEnabled(profile.name === "iosm");
@@ -3901,6 +4093,7 @@ export class InteractiveMode {
3901
4093
  this.updateEditorBorderColor();
3902
4094
  this.refreshBuiltInHeader();
3903
4095
  this.showStatus(`Profile: ${profile.name}`);
4096
+ this.showMetaModeProfileHint();
3904
4097
  }
3905
4098
  cycleProfile(direction) {
3906
4099
  if (this.session.isStreaming || this.session.isCompacting || this.iosmAutomationRun || this.iosmVerificationSession) {
@@ -8655,7 +8848,7 @@ export class InteractiveMode {
8655
8848
  const mentionTask = cleaned.length > 0 ? cleaned : userInput;
8656
8849
  const orchestrationAwareAgent = /orchestrator/i.test(mentionedAgent);
8657
8850
  const mentionMode = orchestrationAwareAgent ? "parallel" : "sequential";
8658
- const mentionMaxParallel = orchestrationAwareAgent ? 20 : undefined;
8851
+ const mentionMaxParallel = orchestrationAwareAgent ? MAX_ORCHESTRATION_PARALLEL : undefined;
8659
8852
  const mentionPrompt = [
8660
8853
  `<orchestrate mode="${mentionMode}" agents="1"${mentionMaxParallel ? ` max_parallel="${mentionMaxParallel}"` : ""}>`,
8661
8854
  `- agent 1: profile=${this.activeProfileName} cwd=${this.sessionManager.getCwd()} agent=${mentionedAgent}`,
@@ -8666,8 +8859,8 @@ export class InteractiveMode {
8666
8859
  ...(orchestrationAwareAgent
8667
8860
  ? [
8668
8861
  "- Include delegate_parallel_hint in the task call.",
8669
- "- If user explicitly requested an agent count, set delegate_parallel_hint to that count (clamp 1..10).",
8670
- "- Otherwise set delegate_parallel_hint based on complexity: simple=1, medium=3-6, complex/risky=7-10.",
8862
+ `- If user explicitly requested an agent count, set delegate_parallel_hint to that count (clamp 1..${MAX_SUBAGENT_DELEGATE_PARALLEL}).`,
8863
+ `- Otherwise set delegate_parallel_hint based on complexity: simple=1, medium=3-6, complex/risky=7-${MAX_SUBAGENT_DELEGATE_PARALLEL}.`,
8671
8864
  "- For non-trivial tasks, prefer delegate_parallel_hint >= 2 and split into independent <delegate_task> workstreams.",
8672
8865
  '- Prefer existing custom agents for delegated work when suitable (use <delegate_task agent="name" ...>).',
8673
8866
  "- If no existing custom agent fits, create focused delegate streams via profile-based <delegate_task> blocks.",
@@ -8682,6 +8875,13 @@ export class InteractiveMode {
8682
8875
  });
8683
8876
  return;
8684
8877
  }
8878
+ if (this.activeProfileName === "meta") {
8879
+ await promptMetaWithParallelismGuard({
8880
+ session: this.session,
8881
+ userInput,
8882
+ });
8883
+ return;
8884
+ }
8685
8885
  await this.session.prompt(userInput);
8686
8886
  }
8687
8887
  createIosmVerificationEventBridge(options) {
@@ -9137,8 +9337,8 @@ export class InteractiveMode {
9137
9337
  if (token === "--max-parallel") {
9138
9338
  const next = rest[index + 1];
9139
9339
  const parsed = next ? Number.parseInt(next, 10) : Number.NaN;
9140
- if (!Number.isInteger(parsed) || parsed < 1 || parsed > 20) {
9141
- this.showWarning("Invalid --max-parallel value (expected 1..20).");
9340
+ if (!Number.isInteger(parsed) || parsed < 1 || parsed > MAX_ORCHESTRATION_PARALLEL) {
9341
+ this.showWarning(`Invalid --max-parallel value (expected 1..${MAX_ORCHESTRATION_PARALLEL}).`);
9142
9342
  return undefined;
9143
9343
  }
9144
9344
  maxParallel = parsed;
@@ -9655,7 +9855,7 @@ export class InteractiveMode {
9655
9855
  index: indexInfo.index,
9656
9856
  });
9657
9857
  const runId = `swarm_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
9658
- const maxParallel = Math.max(1, Math.min(20, options.maxParallel ?? 3));
9858
+ const maxParallel = Math.max(1, Math.min(MAX_ORCHESTRATION_PARALLEL, options.maxParallel ?? 3));
9659
9859
  const meta = this.buildSwarmRunMeta({
9660
9860
  runId,
9661
9861
  source: "plain",
@@ -9699,7 +9899,7 @@ export class InteractiveMode {
9699
9899
  index: indexInfo.index,
9700
9900
  });
9701
9901
  const runId = `swarm_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
9702
- const maxParallel = Math.max(1, Math.min(20, input.maxParallel ?? 3));
9902
+ const maxParallel = Math.max(1, Math.min(MAX_ORCHESTRATION_PARALLEL, input.maxParallel ?? 3));
9703
9903
  const meta = this.buildSwarmRunMeta({
9704
9904
  runId,
9705
9905
  source: "singular",
@@ -9969,8 +10169,8 @@ export class InteractiveMode {
9969
10169
  if (arg === "--agents") {
9970
10170
  const value = args[index + 1];
9971
10171
  const parsed = value ? Number.parseInt(value, 10) : Number.NaN;
9972
- if (!Number.isInteger(parsed) || parsed < 1 || parsed > 20) {
9973
- this.showWarning("Invalid --agents value (expected 1..20).");
10172
+ if (!Number.isInteger(parsed) || parsed < 1 || parsed > MAX_ORCHESTRATION_AGENTS) {
10173
+ this.showWarning(`Invalid --agents value (expected 1..${MAX_ORCHESTRATION_AGENTS}).`);
9974
10174
  return undefined;
9975
10175
  }
9976
10176
  agents = parsed;
@@ -9980,8 +10180,8 @@ export class InteractiveMode {
9980
10180
  if (arg === "--max-parallel") {
9981
10181
  const value = args[index + 1];
9982
10182
  const parsed = value ? Number.parseInt(value, 10) : Number.NaN;
9983
- if (!Number.isInteger(parsed) || parsed < 1 || parsed > 20) {
9984
- this.showWarning("Invalid --max-parallel value (expected 1..20).");
10183
+ if (!Number.isInteger(parsed) || parsed < 1 || parsed > MAX_ORCHESTRATION_PARALLEL) {
10184
+ this.showWarning(`Invalid --max-parallel value (expected 1..${MAX_ORCHESTRATION_PARALLEL}).`);
9985
10185
  return undefined;
9986
10186
  }
9987
10187
  maxParallel = parsed;
@@ -10512,7 +10712,7 @@ export class InteractiveMode {
10512
10712
  "You are generating a custom IOSM subagent specification.",
10513
10713
  "Return ONLY a single JSON object and no additional text.",
10514
10714
  'Allowed JSON keys: name, description, profile, tools, disallowed_tools, system_prompt, cwd, background, instructions.',
10515
- 'profile must be one of: full, plan, iosm, explore, iosm_analyst, iosm_verifier, cycle_planner.',
10715
+ 'profile must be one of: full, plan, iosm, meta, explore, iosm_analyst, iosm_verifier, cycle_planner.',
10516
10716
  "name must be short snake/kebab case, suitable for @mention.",
10517
10717
  "tools/disallowed_tools must be arrays of tool names when present.",
10518
10718
  "instructions must be a concise markdown body for the agent file.",