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.
- package/CHANGELOG.md +25 -0
- package/README.md +32 -5
- package/dist/cli/args.d.ts +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +1 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-profiles.d.ts +1 -1
- package/dist/core/agent-profiles.d.ts.map +1 -1
- package/dist/core/agent-profiles.js +9 -0
- package/dist/core/agent-profiles.js.map +1 -1
- package/dist/core/agent-session.d.ts +7 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +58 -13
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/types.d.ts +1 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/orchestration-limits.d.ts +6 -0
- package/dist/core/orchestration-limits.d.ts.map +1 -0
- package/dist/core/orchestration-limits.js +6 -0
- package/dist/core/orchestration-limits.js.map +1 -0
- package/dist/core/sdk.d.ts +6 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +34 -6
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/subagents.d.ts.map +1 -1
- package/dist/core/subagents.js +21 -7
- package/dist/core/subagents.js.map +1 -1
- package/dist/core/tools/edit.d.ts +8 -4
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +18 -3
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/index.d.ts +9 -7
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/task.d.ts +10 -3
- package/dist/core/tools/task.d.ts.map +1 -1
- package/dist/core/tools/task.js +404 -149
- package/dist/core/tools/task.js.map +1 -1
- package/dist/core/tools/todo.d.ts +10 -10
- package/dist/core/tools/todo.d.ts.map +1 -1
- package/dist/core/tools/todo.js +135 -17
- package/dist/core/tools/todo.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +8 -8
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +9 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +214 -14
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/cli-reference.md +4 -0
- package/docs/configuration.md +5 -1
- package/docs/interactive-mode.md +5 -1
- 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
|
|
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
|
-
|
|
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 ?
|
|
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
|
-
|
|
8670
|
-
|
|
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 >
|
|
9141
|
-
this.showWarning(
|
|
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(
|
|
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(
|
|
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 >
|
|
9973
|
-
this.showWarning(
|
|
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 >
|
|
9984
|
-
this.showWarning(
|
|
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.",
|