iosm-cli 0.2.17 → 0.3.1
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 +46 -0
- package/README.md +7 -4
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +3 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/settings-manager.d.ts +3 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +11 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/settings.schema.json +21 -0
- package/dist/core/subagents.d.ts.map +1 -1
- package/dist/core/subagents.js +4 -0
- package/dist/core/subagents.js.map +1 -1
- package/dist/core/tools/task.d.ts.map +1 -1
- package/dist/core/tools/task.js +48 -26
- package/dist/core/tools/task.js.map +1 -1
- package/dist/iosm/guide.d.ts +14 -0
- package/dist/iosm/guide.d.ts.map +1 -1
- package/dist/iosm/guide.js +72 -1
- package/dist/iosm/guide.js.map +1 -1
- package/dist/iosm/index.d.ts +1 -1
- package/dist/iosm/index.d.ts.map +1 -1
- package/dist/iosm/index.js +1 -1
- package/dist/iosm/index.js.map +1 -1
- package/dist/iosm/init.d.ts.map +1 -1
- package/dist/iosm/init.js +20 -2
- package/dist/iosm/init.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +16 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +7 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +77 -5
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +7 -0
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +95 -10
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +2 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +49 -32
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/message-frame-border.d.ts +22 -0
- package/dist/modes/interactive/components/message-frame-border.d.ts.map +1 -0
- package/dist/modes/interactive/components/message-frame-border.js +51 -0
- package/dist/modes/interactive/components/message-frame-border.js.map +1 -0
- package/dist/modes/interactive/components/message-window.d.ts +25 -0
- package/dist/modes/interactive/components/message-window.d.ts.map +1 -0
- package/dist/modes/interactive/components/message-window.js +66 -0
- package/dist/modes/interactive/components/message-window.js.map +1 -0
- package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +12 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/subagent-message.d.ts +12 -9
- package/dist/modes/interactive/components/subagent-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/subagent-message.js +138 -136
- package/dist/modes/interactive/components/subagent-message.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +2 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +33 -28
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +10 -3
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +12 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +551 -161
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/getting-started.md +3 -3
- package/docs/interactive-mode.md +1 -1
- package/package.json +1 -1
|
@@ -15,7 +15,6 @@ 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";
|
|
19
18
|
import { loadModelsDevProviderCatalog, } from "../../core/models-dev-provider-catalog.js";
|
|
20
19
|
import { ModelRegistry } from "../../core/model-registry.js";
|
|
21
20
|
import { MODELS_DEV_PROVIDERS } from "../../core/models-dev-providers.js";
|
|
@@ -67,6 +66,7 @@ import { ExtensionSelectorComponent } from "./components/extension-selector.js";
|
|
|
67
66
|
import { FooterComponent } from "./components/footer.js";
|
|
68
67
|
import { appKey, appKeyHint, editorKey } from "./components/keybinding-hints.js";
|
|
69
68
|
import { LoginDialogComponent } from "./components/login-dialog.js";
|
|
69
|
+
import { MessageWindow } from "./components/message-window.js";
|
|
70
70
|
import { McpSelectorComponent } from "./components/mcp-selector.js";
|
|
71
71
|
import { ModelSelectorComponent } from "./components/model-selector.js";
|
|
72
72
|
import { OAuthSelectorComponent } from "./components/oauth-selector.js";
|
|
@@ -74,7 +74,6 @@ import { ScopedModelsSelectorComponent } from "./components/scoped-models-select
|
|
|
74
74
|
import { SessionSelectorComponent } from "./components/session-selector.js";
|
|
75
75
|
import { SettingsSelectorComponent } from "./components/settings-selector.js";
|
|
76
76
|
import { SkillInvocationMessageComponent } from "./components/skill-invocation-message.js";
|
|
77
|
-
import { SubagentMessageComponent, } from "./components/subagent-message.js";
|
|
78
77
|
import { TaskPlanMessageComponent } from "./components/task-plan-message.js";
|
|
79
78
|
import { ToolExecutionComponent } from "./components/tool-execution.js";
|
|
80
79
|
import { TreeSelectorComponent } from "./components/tree-selector.js";
|
|
@@ -94,16 +93,16 @@ export function resolveStreamingSubmissionMode(input) {
|
|
|
94
93
|
}
|
|
95
94
|
function parseRequestedParallelAgentCount(text) {
|
|
96
95
|
const patterns = [
|
|
97
|
-
|
|
98
|
-
/(\d+)\
|
|
99
|
-
|
|
100
|
-
/(\d+)
|
|
96
|
+
/--agents\s+(\d+)\b/i,
|
|
97
|
+
/(?:^|\s)agents\s*[:=]\s*(\d+)\b/i,
|
|
98
|
+
/<orchestrate[^>]*\bagents\s*=\s*["']?(\d+)["']?/i,
|
|
99
|
+
/"agents"\s*:\s*(\d+)/i,
|
|
101
100
|
];
|
|
102
101
|
for (const pattern of patterns) {
|
|
103
102
|
const match = text.match(pattern);
|
|
104
103
|
const parsed = match?.[1] ? Number.parseInt(match[1], 10) : Number.NaN;
|
|
105
104
|
if (Number.isInteger(parsed) && parsed >= 1) {
|
|
106
|
-
return
|
|
105
|
+
return parsed;
|
|
107
106
|
}
|
|
108
107
|
}
|
|
109
108
|
return undefined;
|
|
@@ -871,11 +870,125 @@ function parseSubagentDelegateItems(value) {
|
|
|
871
870
|
if (!index || !description || !profile || !status)
|
|
872
871
|
continue;
|
|
873
872
|
parsed.push({ index, description, profile, status });
|
|
874
|
-
if (parsed.length >= 20)
|
|
875
|
-
break;
|
|
876
873
|
}
|
|
877
874
|
return parsed;
|
|
878
875
|
}
|
|
876
|
+
function summarizeDelegateProgress(input) {
|
|
877
|
+
if (Array.isArray(input.delegateItems) && input.delegateItems.length > 0) {
|
|
878
|
+
let done = 0;
|
|
879
|
+
let failed = 0;
|
|
880
|
+
let running = 0;
|
|
881
|
+
let pending = 0;
|
|
882
|
+
for (const item of input.delegateItems) {
|
|
883
|
+
switch (item.status) {
|
|
884
|
+
case "done":
|
|
885
|
+
done += 1;
|
|
886
|
+
break;
|
|
887
|
+
case "failed":
|
|
888
|
+
failed += 1;
|
|
889
|
+
break;
|
|
890
|
+
case "running":
|
|
891
|
+
running += 1;
|
|
892
|
+
break;
|
|
893
|
+
default:
|
|
894
|
+
pending += 1;
|
|
895
|
+
break;
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
return { total: input.delegateItems.length, done, failed, running, pending };
|
|
899
|
+
}
|
|
900
|
+
if (typeof input.delegatedTasks === "number" && Number.isFinite(input.delegatedTasks) && input.delegatedTasks > 0) {
|
|
901
|
+
const total = Math.max(0, Math.floor(input.delegatedTasks));
|
|
902
|
+
const done = typeof input.delegatedSucceeded === "number" && Number.isFinite(input.delegatedSucceeded)
|
|
903
|
+
? Math.max(0, Math.floor(input.delegatedSucceeded))
|
|
904
|
+
: 0;
|
|
905
|
+
const failed = typeof input.delegatedFailed === "number" && Number.isFinite(input.delegatedFailed)
|
|
906
|
+
? Math.max(0, Math.floor(input.delegatedFailed))
|
|
907
|
+
: 0;
|
|
908
|
+
const running = Math.max(0, total - done - failed);
|
|
909
|
+
return { total, done, failed, running, pending: 0 };
|
|
910
|
+
}
|
|
911
|
+
return { total: 0, done: 0, failed: 0, running: 0, pending: 0 };
|
|
912
|
+
}
|
|
913
|
+
function formatOrchestrationToolProgress(started, completed) {
|
|
914
|
+
if (started <= 0)
|
|
915
|
+
return "tools -";
|
|
916
|
+
return `tools ${Math.max(0, completed)}/${Math.max(0, started)}`;
|
|
917
|
+
}
|
|
918
|
+
function formatDelegateStatusMarker(status) {
|
|
919
|
+
switch (status) {
|
|
920
|
+
case "done":
|
|
921
|
+
return "[x]";
|
|
922
|
+
case "running":
|
|
923
|
+
return "[>]";
|
|
924
|
+
case "failed":
|
|
925
|
+
return "[!]";
|
|
926
|
+
default:
|
|
927
|
+
return "[ ]";
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
function compactOneLineText(text, maxLength = 96) {
|
|
931
|
+
const normalized = text.replace(/\s+/g, " ").trim();
|
|
932
|
+
if (normalized.length <= maxLength)
|
|
933
|
+
return normalized;
|
|
934
|
+
return `${normalized.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;
|
|
935
|
+
}
|
|
936
|
+
function appendDelegateTreeRows(rows, input, options = {}) {
|
|
937
|
+
const indent = options.indent ?? " ";
|
|
938
|
+
if (Array.isArray(input.delegateItems) && input.delegateItems.length > 0) {
|
|
939
|
+
const hasRowLimit = typeof options.maxRows === "number" && Number.isFinite(options.maxRows) && options.maxRows > 0;
|
|
940
|
+
const visibleItems = hasRowLimit
|
|
941
|
+
? input.delegateItems.slice(0, Math.max(1, Math.floor(options.maxRows)))
|
|
942
|
+
: input.delegateItems;
|
|
943
|
+
for (const [index, item] of visibleItems.entries()) {
|
|
944
|
+
const isLastVisible = index === visibleItems.length - 1;
|
|
945
|
+
const hasMoreHidden = input.delegateItems.length > visibleItems.length;
|
|
946
|
+
const branch = isLastVisible && !hasMoreHidden ? "└─" : "├─";
|
|
947
|
+
rows.push(`${indent}${branch} ${formatDelegateStatusMarker(item.status)} #${item.index} ${compactOneLineText(item.description, 56)} (${item.profile})`);
|
|
948
|
+
}
|
|
949
|
+
if (input.delegateItems.length > visibleItems.length) {
|
|
950
|
+
rows.push(`${indent}└─ … +${input.delegateItems.length - visibleItems.length} more delegate(s)`);
|
|
951
|
+
}
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
954
|
+
const summary = summarizeDelegateProgress({
|
|
955
|
+
delegateItems: input.delegateItems,
|
|
956
|
+
delegatedTasks: input.delegatedTasks,
|
|
957
|
+
delegatedSucceeded: input.delegatedSucceeded,
|
|
958
|
+
delegatedFailed: input.delegatedFailed,
|
|
959
|
+
});
|
|
960
|
+
if (summary.total === 0)
|
|
961
|
+
return;
|
|
962
|
+
const summaryParts = [`${summary.done}/${summary.total} done`];
|
|
963
|
+
if (summary.failed > 0)
|
|
964
|
+
summaryParts.push(`${summary.failed} failed`);
|
|
965
|
+
if (summary.running > 0)
|
|
966
|
+
summaryParts.push(`${summary.running} running`);
|
|
967
|
+
if (summary.pending > 0)
|
|
968
|
+
summaryParts.push(`${summary.pending} pending`);
|
|
969
|
+
rows.push(`${indent}└─ delegates ${summaryParts.join(", ")}`);
|
|
970
|
+
if (typeof input.delegateIndex === "number" &&
|
|
971
|
+
input.delegateIndex > 0 &&
|
|
972
|
+
typeof input.delegateDescription === "string" &&
|
|
973
|
+
input.delegateDescription.trim().length > 0) {
|
|
974
|
+
const totalText = typeof input.delegateTotal === "number" && input.delegateTotal > 0 ? `/${Math.floor(input.delegateTotal)}` : "";
|
|
975
|
+
const profileText = typeof input.delegateProfile === "string" && input.delegateProfile.trim().length > 0
|
|
976
|
+
? ` (${input.delegateProfile.trim()})`
|
|
977
|
+
: "";
|
|
978
|
+
rows.push(`${indent} └─ [>] active #${Math.floor(input.delegateIndex)}${totalText} ${compactOneLineText(input.delegateDescription, 56)}${profileText}`);
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
function formatElapsedClock(ms) {
|
|
982
|
+
const totalSeconds = Math.max(0, Math.floor(ms / 1000));
|
|
983
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
984
|
+
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
985
|
+
const seconds = totalSeconds % 60;
|
|
986
|
+
const pad2 = (value) => value.toString().padStart(2, "0");
|
|
987
|
+
if (hours > 0) {
|
|
988
|
+
return `${pad2(hours)}:${pad2(minutes)}:${pad2(seconds)}`;
|
|
989
|
+
}
|
|
990
|
+
return `${pad2(minutes)}:${pad2(seconds)}`;
|
|
991
|
+
}
|
|
879
992
|
function hasDependencyCycle(agents, dependencies) {
|
|
880
993
|
const graph = new Map();
|
|
881
994
|
for (let agent = 1; agent <= agents; agent++) {
|
|
@@ -925,6 +1038,16 @@ export class InteractiveMode {
|
|
|
925
1038
|
get settingsManager() {
|
|
926
1039
|
return this.session.settingsManager;
|
|
927
1040
|
}
|
|
1041
|
+
getCompactFooterSetting() {
|
|
1042
|
+
const manager = this.settingsManager;
|
|
1043
|
+
return typeof manager.getCompactFooter === "function" ? manager.getCompactFooter() : false;
|
|
1044
|
+
}
|
|
1045
|
+
setCompactFooterSetting(enabled) {
|
|
1046
|
+
const manager = this.settingsManager;
|
|
1047
|
+
if (typeof manager.setCompactFooter === "function") {
|
|
1048
|
+
manager.setCompactFooter(enabled);
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
928
1051
|
constructor(session, options = {}) {
|
|
929
1052
|
this.options = options;
|
|
930
1053
|
this.isInitialized = false;
|
|
@@ -959,6 +1082,8 @@ export class InteractiveMode {
|
|
|
959
1082
|
// Subagent execution tracking with live progress/metadata for task tool calls.
|
|
960
1083
|
this.subagentComponents = new Map();
|
|
961
1084
|
this.subagentElapsedTimer = undefined;
|
|
1085
|
+
this.orchestrationCompletedSubagents = [];
|
|
1086
|
+
this.orchestrationArchivedForTurn = false;
|
|
962
1087
|
// Internal UI metadata emitted by runtime for orchestration rendering.
|
|
963
1088
|
this.pendingInternalUserDisplayAliases = [];
|
|
964
1089
|
this.pendingAssistantOrchestrationContexts = 0;
|
|
@@ -986,6 +1111,7 @@ export class InteractiveMode {
|
|
|
986
1111
|
// IOSM automation state
|
|
987
1112
|
this.iosmAutomationRun = undefined;
|
|
988
1113
|
this.iosmVerificationSession = undefined;
|
|
1114
|
+
this.standardInitSession = undefined;
|
|
989
1115
|
this.singularAnalysisSession = undefined;
|
|
990
1116
|
// Extension UI state
|
|
991
1117
|
this.extensionSelector = undefined;
|
|
@@ -1031,6 +1157,7 @@ export class InteractiveMode {
|
|
|
1031
1157
|
this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
|
|
1032
1158
|
this.headerContainer = new Container();
|
|
1033
1159
|
this.chatContainer = new Container();
|
|
1160
|
+
this.orchestrationContainer = new Container();
|
|
1034
1161
|
this.pendingMessagesContainer = new Container();
|
|
1035
1162
|
this.statusContainer = new Container();
|
|
1036
1163
|
this.widgetContainerAbove = new Container();
|
|
@@ -1048,6 +1175,7 @@ export class InteractiveMode {
|
|
|
1048
1175
|
this.footerDataProvider = new FooterDataProvider();
|
|
1049
1176
|
this.footer = new FooterComponent(session, this.footerDataProvider);
|
|
1050
1177
|
this.footer.setAutoCompactEnabled(session.autoCompactionEnabled);
|
|
1178
|
+
this.footer.setCompactModeEnabled(this.getCompactFooterSetting());
|
|
1051
1179
|
const profile = getAgentProfile(options.profile);
|
|
1052
1180
|
this.activeProfileName = profile.name;
|
|
1053
1181
|
this.profilePromptSuffix = profile.systemPromptAppend || undefined;
|
|
@@ -1967,6 +2095,7 @@ export class InteractiveMode {
|
|
|
1967
2095
|
this.ui.addChild(this.chatContainer);
|
|
1968
2096
|
this.ui.addChild(this.pendingMessagesContainer);
|
|
1969
2097
|
this.ui.addChild(this.statusContainer);
|
|
2098
|
+
this.ui.addChild(this.orchestrationContainer);
|
|
1970
2099
|
this.renderWidgets(); // Initialize with default spacer
|
|
1971
2100
|
this.ui.addChild(this.widgetContainerAbove);
|
|
1972
2101
|
this.ui.addChild(this.editorContainer);
|
|
@@ -3261,6 +3390,7 @@ export class InteractiveMode {
|
|
|
3261
3390
|
this.session.isRetrying ||
|
|
3262
3391
|
this.iosmAutomationRun !== undefined ||
|
|
3263
3392
|
this.iosmVerificationSession !== undefined ||
|
|
3393
|
+
this.standardInitSession !== undefined ||
|
|
3264
3394
|
this.swarmActiveRunId !== undefined ||
|
|
3265
3395
|
this.singularAnalysisSession !== undefined ||
|
|
3266
3396
|
queuedMessages.steering.length > 0 ||
|
|
@@ -3653,31 +3783,210 @@ export class InteractiveMode {
|
|
|
3653
3783
|
this.editor.addToHistory?.(text);
|
|
3654
3784
|
};
|
|
3655
3785
|
}
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3786
|
+
resetOrchestrationSummary() {
|
|
3787
|
+
this.orchestrationCompletedSubagents = [];
|
|
3788
|
+
this.orchestrationArchivedForTurn = false;
|
|
3789
|
+
this.refreshOrchestrationSummaryDisplay();
|
|
3790
|
+
}
|
|
3791
|
+
refreshOrchestrationSummaryDisplay() {
|
|
3792
|
+
this.orchestrationContainer.clear();
|
|
3793
|
+
const runningStates = [...this.subagentComponents.values()].sort((a, b) => a.startTime - b.startTime);
|
|
3794
|
+
const completedStates = [...this.orchestrationCompletedSubagents].sort((a, b) => b.finishedAt - a.finishedAt);
|
|
3795
|
+
const now = Date.now();
|
|
3796
|
+
const sectionTaskLimit = Number.POSITIVE_INFINITY;
|
|
3797
|
+
const runningRows = [];
|
|
3798
|
+
const queuedRows = [];
|
|
3799
|
+
const completedRows = [];
|
|
3800
|
+
const failedRows = [];
|
|
3801
|
+
const criticalPath = [];
|
|
3802
|
+
const sectionCounters = {
|
|
3803
|
+
running: { shown: 0, hidden: 0 },
|
|
3804
|
+
queued: { shown: 0, hidden: 0 },
|
|
3805
|
+
completed: { shown: 0, hidden: 0 },
|
|
3806
|
+
failed: { shown: 0, hidden: 0 },
|
|
3807
|
+
};
|
|
3808
|
+
const pushTaskBlock = (target, lines, counter) => {
|
|
3809
|
+
if (counter.shown >= sectionTaskLimit) {
|
|
3810
|
+
counter.hidden += 1;
|
|
3811
|
+
return;
|
|
3812
|
+
}
|
|
3813
|
+
target.push(...lines);
|
|
3814
|
+
counter.shown += 1;
|
|
3815
|
+
};
|
|
3816
|
+
for (const state of runningStates) {
|
|
3817
|
+
const elapsed = formatElapsedClock(now - state.startTime);
|
|
3818
|
+
const phase = compactOneLineText(state.phase?.trim() || "running", 56);
|
|
3819
|
+
const toolProgress = formatOrchestrationToolProgress(state.toolCallsStarted, state.toolCallsCompleted);
|
|
3820
|
+
const msgCount = Math.max(0, state.assistantMessages ?? 0);
|
|
3821
|
+
const isQueuedTask = state.phaseState === "queued";
|
|
3822
|
+
const delegateRows = [];
|
|
3823
|
+
appendDelegateTreeRows(delegateRows, state, { indent: " " });
|
|
3824
|
+
if (isQueuedTask) {
|
|
3825
|
+
pushTaskBlock(queuedRows, [
|
|
3826
|
+
`• ${state.profile} ${compactOneLineText(state.description, 52)} reason: ${phase}`,
|
|
3827
|
+
...delegateRows,
|
|
3828
|
+
], sectionCounters.queued);
|
|
3829
|
+
}
|
|
3830
|
+
else {
|
|
3831
|
+
if (criticalPath.length < 3) {
|
|
3832
|
+
criticalPath.push(state.profile);
|
|
3833
|
+
}
|
|
3834
|
+
pushTaskBlock(runningRows, [
|
|
3835
|
+
`▶ ${state.profile} ${compactOneLineText(state.description, 52)} ${elapsed} ${toolProgress} msgs ${msgCount} last: ${phase}`,
|
|
3836
|
+
...delegateRows,
|
|
3837
|
+
], sectionCounters.running);
|
|
3838
|
+
}
|
|
3839
|
+
}
|
|
3840
|
+
for (const state of completedStates) {
|
|
3841
|
+
const elapsed = formatElapsedClock(state.durationMs);
|
|
3842
|
+
const toolProgress = formatOrchestrationToolProgress(state.toolCallsStarted, state.toolCallsCompleted);
|
|
3843
|
+
const msgCount = Math.max(0, state.assistantMessages ?? 0);
|
|
3844
|
+
const delegateRows = [];
|
|
3845
|
+
appendDelegateTreeRows(delegateRows, state, { indent: " " });
|
|
3846
|
+
if (state.status === "error") {
|
|
3847
|
+
const row = `[!] ${state.profile} ${compactOneLineText(state.description, 46)} ${elapsed} ${toolProgress} msgs ${msgCount} error: ${compactOneLineText(state.errorMessage || "error", 46)}`;
|
|
3848
|
+
pushTaskBlock(failedRows, [row, ...delegateRows], sectionCounters.failed);
|
|
3849
|
+
continue;
|
|
3850
|
+
}
|
|
3851
|
+
const outputText = typeof state.outputLength === "number" && Number.isFinite(state.outputLength) && state.outputLength >= 0
|
|
3852
|
+
? `${(state.outputLength / 1024).toFixed(1)}KB`
|
|
3853
|
+
: "-";
|
|
3854
|
+
const queueText = typeof state.waitMs === "number" && Number.isFinite(state.waitMs) && state.waitMs >= 0
|
|
3855
|
+
? `queue ${Math.max(0, Math.floor(state.waitMs))}ms`
|
|
3856
|
+
: "queue -";
|
|
3857
|
+
const row = `[x] ${state.profile} ${compactOneLineText(state.description, 46)} ${elapsed} ${toolProgress} msgs ${msgCount} out ${outputText} ${queueText}`;
|
|
3858
|
+
pushTaskBlock(completedRows, [row, ...delegateRows], sectionCounters.completed);
|
|
3859
|
+
}
|
|
3860
|
+
if (sectionCounters.running.hidden > 0) {
|
|
3861
|
+
runningRows.push(`• … +${sectionCounters.running.hidden} more task(s)`);
|
|
3862
|
+
}
|
|
3863
|
+
if (sectionCounters.queued.hidden > 0) {
|
|
3864
|
+
queuedRows.push(`• … +${sectionCounters.queued.hidden} more task(s)`);
|
|
3865
|
+
}
|
|
3866
|
+
if (sectionCounters.completed.hidden > 0) {
|
|
3867
|
+
completedRows.push(`• … +${sectionCounters.completed.hidden} more task(s)`);
|
|
3868
|
+
}
|
|
3869
|
+
if (sectionCounters.failed.hidden > 0) {
|
|
3870
|
+
failedRows.push(`• … +${sectionCounters.failed.hidden} more task(s)`);
|
|
3871
|
+
}
|
|
3872
|
+
const runningCount = runningStates.filter((state) => state.phaseState !== "queued").length;
|
|
3873
|
+
const queuedCount = runningStates.filter((state) => state.phaseState === "queued").length;
|
|
3874
|
+
const doneCount = completedStates.filter((state) => state.status === "done").length;
|
|
3875
|
+
const failedCount = completedStates.filter((state) => state.status === "error").length;
|
|
3876
|
+
const totalCount = doneCount + runningCount + queuedCount + failedCount;
|
|
3877
|
+
if (totalCount === 0) {
|
|
3878
|
+
return;
|
|
3879
|
+
}
|
|
3880
|
+
const etaText = runningCount > 0 || queuedCount > 0 ? "--:--" : "done";
|
|
3881
|
+
const header = theme.fg("warning", "ORCH") +
|
|
3882
|
+
theme.fg("customMessageText", ` ${doneCount}/${totalCount} done`) +
|
|
3883
|
+
theme.fg("dim", " | ") +
|
|
3884
|
+
theme.fg("customMessageText", `${runningCount} running`) +
|
|
3885
|
+
theme.fg("dim", " | ") +
|
|
3886
|
+
theme.fg("customMessageText", `${queuedCount} queued`) +
|
|
3887
|
+
theme.fg("dim", " | ") +
|
|
3888
|
+
(failedCount > 0
|
|
3889
|
+
? theme.fg("warning", `${failedCount} failed`)
|
|
3890
|
+
: theme.fg("customMessageText", `${failedCount} failed`)) +
|
|
3891
|
+
theme.fg("dim", " | ") +
|
|
3892
|
+
theme.fg("muted", `ETA ${etaText}`);
|
|
3893
|
+
const panelContent = new Container();
|
|
3894
|
+
panelContent.addChild(new Text(header, 0, 0));
|
|
3895
|
+
if (criticalPath.length > 0) {
|
|
3896
|
+
panelContent.addChild(new Text(theme.fg("muted", `CP: ${criticalPath.join(" -> ")}`), 0, 0));
|
|
3897
|
+
}
|
|
3898
|
+
const renderSection = (title, rows, color = "customMessageText") => {
|
|
3899
|
+
panelContent.addChild(new Spacer(1));
|
|
3900
|
+
panelContent.addChild(new Text(theme.fg("warning", title), 0, 0));
|
|
3901
|
+
if (rows.length === 0) {
|
|
3902
|
+
panelContent.addChild(new Text(theme.fg("muted", "• none"), 0, 0));
|
|
3903
|
+
return;
|
|
3904
|
+
}
|
|
3905
|
+
for (const row of rows) {
|
|
3906
|
+
panelContent.addChild(new Text(theme.fg(color, row), 0, 0));
|
|
3907
|
+
}
|
|
3908
|
+
};
|
|
3909
|
+
renderSection("RUNNING", runningRows);
|
|
3910
|
+
renderSection("QUEUED", queuedRows);
|
|
3911
|
+
renderSection("COMPLETED", completedRows, "success");
|
|
3912
|
+
renderSection("FAILED", failedRows, "warning");
|
|
3913
|
+
this.orchestrationContainer.addChild(new MessageWindow(panelContent, {
|
|
3914
|
+
label: "IOSM Orchestration",
|
|
3915
|
+
lineColor: "warning",
|
|
3916
|
+
labelColor: "warning",
|
|
3917
|
+
paddingY: 1,
|
|
3918
|
+
}));
|
|
3919
|
+
this.orchestrationContainer.addChild(new Spacer(1));
|
|
3920
|
+
}
|
|
3921
|
+
pushOrchestrationCompletedSubagent(state) {
|
|
3922
|
+
this.orchestrationCompletedSubagents.push(state);
|
|
3923
|
+
}
|
|
3924
|
+
archiveOrchestrationPanelToChatIfComplete() {
|
|
3925
|
+
if (this.orchestrationArchivedForTurn)
|
|
3926
|
+
return;
|
|
3927
|
+
if (this.subagentComponents.size > 0)
|
|
3928
|
+
return;
|
|
3929
|
+
if (this.orchestrationCompletedSubagents.length === 0)
|
|
3930
|
+
return;
|
|
3931
|
+
if (this.orchestrationContainer.children.length === 0)
|
|
3932
|
+
return;
|
|
3933
|
+
const snapshot = [...this.orchestrationContainer.children];
|
|
3934
|
+
this.orchestrationContainer.clear();
|
|
3935
|
+
const trailingNode = this.chatContainer.children.length > 0
|
|
3936
|
+
? this.chatContainer.children[this.chatContainer.children.length - 1]
|
|
3937
|
+
: undefined;
|
|
3938
|
+
if (trailingNode) {
|
|
3939
|
+
this.chatContainer.removeChild(trailingNode);
|
|
3940
|
+
}
|
|
3941
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
3942
|
+
for (const child of snapshot) {
|
|
3943
|
+
this.chatContainer.addChild(child);
|
|
3944
|
+
}
|
|
3945
|
+
if (trailingNode) {
|
|
3946
|
+
this.chatContainer.addChild(trailingNode);
|
|
3947
|
+
}
|
|
3948
|
+
this.orchestrationArchivedForTurn = true;
|
|
3949
|
+
}
|
|
3950
|
+
hasCompletedSubagentForToolCall(toolCallId) {
|
|
3951
|
+
return this.orchestrationCompletedSubagents.some((item) => item.toolCallId === toolCallId);
|
|
3952
|
+
}
|
|
3953
|
+
queuePendingTaskCallsFromAssistantMessage(message) {
|
|
3954
|
+
let changed = false;
|
|
3955
|
+
for (const content of message.content) {
|
|
3956
|
+
if (content.type !== "toolCall" || content.name !== "task")
|
|
3957
|
+
continue;
|
|
3958
|
+
if (typeof content.id !== "string" || content.id.trim().length === 0)
|
|
3959
|
+
continue;
|
|
3960
|
+
const toolCallId = content.id;
|
|
3961
|
+
const alreadyCompleted = typeof this.hasCompletedSubagentForToolCall === "function"
|
|
3962
|
+
? this.hasCompletedSubagentForToolCall(toolCallId)
|
|
3963
|
+
: Array.isArray(this.orchestrationCompletedSubagents)
|
|
3964
|
+
? this.orchestrationCompletedSubagents.some((item) => item?.toolCallId === toolCallId)
|
|
3965
|
+
: false;
|
|
3966
|
+
if (this.subagentComponents.has(toolCallId) || alreadyCompleted) {
|
|
3967
|
+
continue;
|
|
3968
|
+
}
|
|
3969
|
+
const args = content.arguments;
|
|
3970
|
+
this.subagentComponents.set(toolCallId, {
|
|
3971
|
+
startTime: Date.now(),
|
|
3972
|
+
profile: args.profile ?? "explore",
|
|
3973
|
+
description: args.description ?? "Running subtask",
|
|
3974
|
+
cwd: args.cwd,
|
|
3975
|
+
agent: args.agent,
|
|
3976
|
+
lockKey: args.lock_key,
|
|
3977
|
+
isolation: args.isolation,
|
|
3978
|
+
phase: "queued for execution",
|
|
3979
|
+
phaseState: "queued",
|
|
3980
|
+
toolCallsStarted: 0,
|
|
3981
|
+
toolCallsCompleted: 0,
|
|
3982
|
+
assistantMessages: 0,
|
|
3983
|
+
});
|
|
3984
|
+
changed = true;
|
|
3985
|
+
}
|
|
3986
|
+
if (!changed)
|
|
3987
|
+
return;
|
|
3988
|
+
this.ensureSubagentElapsedTimer();
|
|
3989
|
+
this.refreshOrchestrationSummaryDisplay();
|
|
3681
3990
|
}
|
|
3682
3991
|
getSwarmSubagentKey(runId, taskId) {
|
|
3683
3992
|
return `swarm:${runId}:${taskId}`;
|
|
@@ -3688,14 +3997,13 @@ export class InteractiveMode {
|
|
|
3688
3997
|
if (existing) {
|
|
3689
3998
|
return existing;
|
|
3690
3999
|
}
|
|
3691
|
-
const
|
|
3692
|
-
|
|
4000
|
+
const state = {
|
|
4001
|
+
startTime: Date.now(),
|
|
4002
|
+
profile: (input.profile?.trim() || this.resolveSwarmTaskProfile(input.task)).trim(),
|
|
3693
4003
|
description: input.task.brief || input.task.id,
|
|
3694
|
-
|
|
3695
|
-
status: "running",
|
|
4004
|
+
cwd: this.sessionManager.getCwd(),
|
|
3696
4005
|
phase: "starting subagent",
|
|
3697
4006
|
phaseState: "starting",
|
|
3698
|
-
cwd: this.sessionManager.getCwd(),
|
|
3699
4007
|
toolCallsStarted: 0,
|
|
3700
4008
|
toolCallsCompleted: 0,
|
|
3701
4009
|
assistantMessages: 0,
|
|
@@ -3703,34 +4011,9 @@ export class InteractiveMode {
|
|
|
3703
4011
|
delegatedSucceeded: 0,
|
|
3704
4012
|
delegatedFailed: 0,
|
|
3705
4013
|
};
|
|
3706
|
-
const component = new SubagentMessageComponent(info);
|
|
3707
|
-
this.chatContainer.addChild(component);
|
|
3708
|
-
const state = {
|
|
3709
|
-
component,
|
|
3710
|
-
startTime: Date.now(),
|
|
3711
|
-
profile: info.profile,
|
|
3712
|
-
description: info.description,
|
|
3713
|
-
cwd: info.cwd,
|
|
3714
|
-
agent: info.agent,
|
|
3715
|
-
lockKey: info.lockKey,
|
|
3716
|
-
isolation: info.isolation,
|
|
3717
|
-
phase: info.phase,
|
|
3718
|
-
phaseState: info.phaseState,
|
|
3719
|
-
activeTool: info.activeTool,
|
|
3720
|
-
toolCallsStarted: info.toolCallsStarted ?? 0,
|
|
3721
|
-
toolCallsCompleted: info.toolCallsCompleted ?? 0,
|
|
3722
|
-
assistantMessages: info.assistantMessages ?? 0,
|
|
3723
|
-
delegatedTasks: info.delegatedTasks,
|
|
3724
|
-
delegatedSucceeded: info.delegatedSucceeded,
|
|
3725
|
-
delegatedFailed: info.delegatedFailed,
|
|
3726
|
-
delegateIndex: info.delegateIndex,
|
|
3727
|
-
delegateTotal: info.delegateTotal,
|
|
3728
|
-
delegateDescription: info.delegateDescription,
|
|
3729
|
-
delegateProfile: info.delegateProfile,
|
|
3730
|
-
delegateItems: info.delegateItems,
|
|
3731
|
-
};
|
|
3732
4014
|
this.subagentComponents.set(key, state);
|
|
3733
4015
|
this.ensureSubagentElapsedTimer();
|
|
4016
|
+
this.refreshOrchestrationSummaryDisplay();
|
|
3734
4017
|
this.ui.requestRender();
|
|
3735
4018
|
return state;
|
|
3736
4019
|
}
|
|
@@ -3800,9 +4083,12 @@ export class InteractiveMode {
|
|
|
3800
4083
|
: undefined;
|
|
3801
4084
|
}
|
|
3802
4085
|
if ("delegateItems" in progress) {
|
|
3803
|
-
|
|
4086
|
+
const parsed = parseSubagentDelegateItems(progress.delegateItems);
|
|
4087
|
+
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
4088
|
+
state.delegateItems = parsed;
|
|
4089
|
+
}
|
|
3804
4090
|
}
|
|
3805
|
-
this.
|
|
4091
|
+
this.refreshOrchestrationSummaryDisplay();
|
|
3806
4092
|
this.ui.requestRender();
|
|
3807
4093
|
}
|
|
3808
4094
|
finalizeSwarmSubagentDisplay(input) {
|
|
@@ -3811,26 +4097,35 @@ export class InteractiveMode {
|
|
|
3811
4097
|
if (!state)
|
|
3812
4098
|
return;
|
|
3813
4099
|
const durationMs = Date.now() - state.startTime;
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
4100
|
+
this.pushOrchestrationCompletedSubagent({
|
|
4101
|
+
toolCallId: key,
|
|
4102
|
+
finishedAt: Date.now(),
|
|
3817
4103
|
status: input.status,
|
|
4104
|
+
profile: state.profile,
|
|
4105
|
+
description: state.description,
|
|
3818
4106
|
durationMs,
|
|
3819
|
-
phaseState: state.phaseState,
|
|
3820
4107
|
cwd: state.cwd,
|
|
3821
4108
|
agent: state.agent,
|
|
3822
4109
|
lockKey: state.lockKey,
|
|
3823
4110
|
isolation: state.isolation,
|
|
4111
|
+
phase: state.phase,
|
|
4112
|
+
phaseState: state.phaseState,
|
|
3824
4113
|
toolCallsStarted: state.toolCallsStarted,
|
|
3825
4114
|
toolCallsCompleted: state.toolCallsCompleted,
|
|
3826
4115
|
assistantMessages: state.assistantMessages,
|
|
3827
4116
|
delegatedTasks: state.delegatedTasks,
|
|
3828
4117
|
delegatedSucceeded: state.delegatedSucceeded,
|
|
3829
4118
|
delegatedFailed: state.delegatedFailed,
|
|
4119
|
+
delegateIndex: state.delegateIndex,
|
|
4120
|
+
delegateTotal: state.delegateTotal,
|
|
4121
|
+
delegateDescription: state.delegateDescription,
|
|
4122
|
+
delegateProfile: state.delegateProfile,
|
|
4123
|
+
delegateItems: state.delegateItems,
|
|
3830
4124
|
errorMessage: input.status === "error" ? input.errorMessage ?? "error" : undefined,
|
|
3831
4125
|
});
|
|
3832
4126
|
this.subagentComponents.delete(key);
|
|
3833
4127
|
this.stopSubagentElapsedTimerIfIdle();
|
|
4128
|
+
this.refreshOrchestrationSummaryDisplay();
|
|
3834
4129
|
this.ui.requestRender();
|
|
3835
4130
|
}
|
|
3836
4131
|
finalizeSwarmRunSubagentDisplays(runId, errorMessage) {
|
|
@@ -3855,9 +4150,7 @@ export class InteractiveMode {
|
|
|
3855
4150
|
this.clearSubagentElapsedTimer();
|
|
3856
4151
|
return;
|
|
3857
4152
|
}
|
|
3858
|
-
|
|
3859
|
-
this.updateRunningSubagentDisplay(subagent);
|
|
3860
|
-
}
|
|
4153
|
+
this.refreshOrchestrationSummaryDisplay();
|
|
3861
4154
|
this.ui.requestRender();
|
|
3862
4155
|
}, 1000);
|
|
3863
4156
|
}
|
|
@@ -3888,6 +4181,19 @@ export class InteractiveMode {
|
|
|
3888
4181
|
this.currentTurnSawAssistantMessage = false;
|
|
3889
4182
|
this.currentTurnSawTaskToolCall = false;
|
|
3890
4183
|
this.turnAllowedToolSignatures.clear();
|
|
4184
|
+
this.orchestrationArchivedForTurn = false;
|
|
4185
|
+
if (typeof this.resetOrchestrationSummary === "function") {
|
|
4186
|
+
this.resetOrchestrationSummary();
|
|
4187
|
+
}
|
|
4188
|
+
else {
|
|
4189
|
+
this.orchestrationCompletedSubagents = [];
|
|
4190
|
+
if (typeof this.refreshOrchestrationSummaryDisplay === "function") {
|
|
4191
|
+
this.refreshOrchestrationSummaryDisplay();
|
|
4192
|
+
}
|
|
4193
|
+
else if (this.orchestrationContainer?.clear) {
|
|
4194
|
+
this.orchestrationContainer.clear();
|
|
4195
|
+
}
|
|
4196
|
+
}
|
|
3891
4197
|
// Restore main escape handler if retry handler is still active
|
|
3892
4198
|
// (retry success event fires later, but we need main handler now)
|
|
3893
4199
|
if (this.retryEscapeHandler) {
|
|
@@ -3930,6 +4236,8 @@ export class InteractiveMode {
|
|
|
3930
4236
|
this.pendingAssistantOrchestrationContexts -= 1;
|
|
3931
4237
|
}
|
|
3932
4238
|
this.streamingComponent = new AssistantMessageComponent(undefined, this.hideThinkingBlock, this.getMarkdownThemeWithSettings());
|
|
4239
|
+
this.streamingComponent.setExpanded(this.toolOutputExpanded);
|
|
4240
|
+
this.streamingComponent.setStreaming(true);
|
|
3933
4241
|
this.streamingMessage = event.message;
|
|
3934
4242
|
this.chatContainer.addChild(this.streamingComponent);
|
|
3935
4243
|
this.streamingComponent.updateContent(this.sanitizeAssistantDisplayMessage(this.streamingMessage));
|
|
@@ -3974,6 +4282,10 @@ export class InteractiveMode {
|
|
|
3974
4282
|
break;
|
|
3975
4283
|
if (this.streamingComponent && event.message.role === "assistant") {
|
|
3976
4284
|
this.streamingMessage = event.message;
|
|
4285
|
+
this.streamingComponent.setStreaming(false);
|
|
4286
|
+
if (typeof this.queuePendingTaskCallsFromAssistantMessage === "function") {
|
|
4287
|
+
this.queuePendingTaskCallsFromAssistantMessage(event.message);
|
|
4288
|
+
}
|
|
3977
4289
|
let errorMessage;
|
|
3978
4290
|
let interruptedStopReason;
|
|
3979
4291
|
if (this.streamingMessage.stopReason === "aborted") {
|
|
@@ -4021,55 +4333,42 @@ export class InteractiveMode {
|
|
|
4021
4333
|
if (event.toolName === "task") {
|
|
4022
4334
|
this.currentTurnSawTaskToolCall = true;
|
|
4023
4335
|
}
|
|
4024
|
-
if (event.toolName === "task"
|
|
4336
|
+
if (event.toolName === "task") {
|
|
4025
4337
|
const staleTaskComponent = this.pendingTools.get(event.toolCallId);
|
|
4026
4338
|
if (staleTaskComponent) {
|
|
4027
4339
|
this.chatContainer.removeChild(staleTaskComponent);
|
|
4028
4340
|
this.pendingTools.delete(event.toolCallId);
|
|
4029
4341
|
}
|
|
4030
4342
|
const args = event.args;
|
|
4031
|
-
const
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
phaseState: info.phaseState,
|
|
4059
|
-
activeTool: info.activeTool,
|
|
4060
|
-
toolCallsStarted: info.toolCallsStarted ?? 0,
|
|
4061
|
-
toolCallsCompleted: info.toolCallsCompleted ?? 0,
|
|
4062
|
-
assistantMessages: info.assistantMessages ?? 0,
|
|
4063
|
-
delegatedTasks: info.delegatedTasks,
|
|
4064
|
-
delegatedSucceeded: info.delegatedSucceeded,
|
|
4065
|
-
delegatedFailed: info.delegatedFailed,
|
|
4066
|
-
delegateIndex: info.delegateIndex,
|
|
4067
|
-
delegateTotal: info.delegateTotal,
|
|
4068
|
-
delegateDescription: info.delegateDescription,
|
|
4069
|
-
delegateProfile: info.delegateProfile,
|
|
4070
|
-
delegateItems: info.delegateItems,
|
|
4071
|
-
});
|
|
4343
|
+
const existing = this.subagentComponents.get(event.toolCallId);
|
|
4344
|
+
if (existing) {
|
|
4345
|
+
existing.profile = args.profile ?? existing.profile;
|
|
4346
|
+
existing.description = args.description ?? existing.description;
|
|
4347
|
+
existing.cwd = args.cwd ?? existing.cwd;
|
|
4348
|
+
existing.agent = args.agent ?? existing.agent;
|
|
4349
|
+
existing.lockKey = args.lock_key ?? existing.lockKey;
|
|
4350
|
+
existing.isolation = args.isolation ?? existing.isolation;
|
|
4351
|
+
existing.phase = "starting subagent";
|
|
4352
|
+
existing.phaseState = "starting";
|
|
4353
|
+
}
|
|
4354
|
+
else {
|
|
4355
|
+
this.subagentComponents.set(event.toolCallId, {
|
|
4356
|
+
startTime: Date.now(),
|
|
4357
|
+
profile: args.profile ?? "explore",
|
|
4358
|
+
description: args.description ?? "Running subtask",
|
|
4359
|
+
cwd: args.cwd,
|
|
4360
|
+
agent: args.agent,
|
|
4361
|
+
lockKey: args.lock_key,
|
|
4362
|
+
isolation: args.isolation,
|
|
4363
|
+
phase: "starting subagent",
|
|
4364
|
+
phaseState: "starting",
|
|
4365
|
+
toolCallsStarted: 0,
|
|
4366
|
+
toolCallsCompleted: 0,
|
|
4367
|
+
assistantMessages: 0,
|
|
4368
|
+
});
|
|
4369
|
+
}
|
|
4072
4370
|
this.ensureSubagentElapsedTimer();
|
|
4371
|
+
this.refreshOrchestrationSummaryDisplay();
|
|
4073
4372
|
this.ui.requestRender();
|
|
4074
4373
|
}
|
|
4075
4374
|
else if (event.toolName !== "task" && !this.pendingTools.has(event.toolCallId)) {
|
|
@@ -4121,6 +4420,15 @@ export class InteractiveMode {
|
|
|
4121
4420
|
if (typeof progress.assistantMessages === "number") {
|
|
4122
4421
|
subagent.assistantMessages = progress.assistantMessages;
|
|
4123
4422
|
}
|
|
4423
|
+
if (typeof progress.delegatedTasks === "number") {
|
|
4424
|
+
subagent.delegatedTasks = Math.max(0, progress.delegatedTasks);
|
|
4425
|
+
}
|
|
4426
|
+
if (typeof progress.delegatedSucceeded === "number") {
|
|
4427
|
+
subagent.delegatedSucceeded = Math.max(0, progress.delegatedSucceeded);
|
|
4428
|
+
}
|
|
4429
|
+
if (typeof progress.delegatedFailed === "number") {
|
|
4430
|
+
subagent.delegatedFailed = Math.max(0, progress.delegatedFailed);
|
|
4431
|
+
}
|
|
4124
4432
|
if ("delegateIndex" in progress) {
|
|
4125
4433
|
subagent.delegateIndex =
|
|
4126
4434
|
typeof progress.delegateIndex === "number" && progress.delegateIndex > 0
|
|
@@ -4146,7 +4454,10 @@ export class InteractiveMode {
|
|
|
4146
4454
|
: undefined;
|
|
4147
4455
|
}
|
|
4148
4456
|
if ("delegateItems" in progress) {
|
|
4149
|
-
|
|
4457
|
+
const parsedDelegateItems = parseSubagentDelegateItems(progress.delegateItems);
|
|
4458
|
+
if (Array.isArray(parsedDelegateItems) && parsedDelegateItems.length > 0) {
|
|
4459
|
+
subagent.delegateItems = parsedDelegateItems;
|
|
4460
|
+
}
|
|
4150
4461
|
}
|
|
4151
4462
|
}
|
|
4152
4463
|
else {
|
|
@@ -4155,7 +4466,7 @@ export class InteractiveMode {
|
|
|
4155
4466
|
subagent.phase = text.trim();
|
|
4156
4467
|
}
|
|
4157
4468
|
}
|
|
4158
|
-
this.
|
|
4469
|
+
this.refreshOrchestrationSummaryDisplay();
|
|
4159
4470
|
this.ui.requestRender();
|
|
4160
4471
|
break;
|
|
4161
4472
|
}
|
|
@@ -4191,24 +4502,32 @@ export class InteractiveMode {
|
|
|
4191
4502
|
subagent.delegatedTasks = delegatedTasks;
|
|
4192
4503
|
subagent.delegatedSucceeded = delegatedSucceeded;
|
|
4193
4504
|
subagent.delegatedFailed = delegatedFailed;
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4505
|
+
this.pushOrchestrationCompletedSubagent({
|
|
4506
|
+
toolCallId: event.toolCallId,
|
|
4507
|
+
finishedAt: Date.now(),
|
|
4197
4508
|
status: event.isError ? "error" : "done",
|
|
4198
|
-
|
|
4509
|
+
profile: subagent.profile,
|
|
4510
|
+
description: subagent.description,
|
|
4199
4511
|
durationMs,
|
|
4200
|
-
waitMs,
|
|
4201
|
-
phaseState: subagent.phaseState,
|
|
4202
4512
|
cwd: subagent.cwd,
|
|
4203
4513
|
agent: subagent.agent,
|
|
4204
4514
|
lockKey: subagent.lockKey,
|
|
4205
4515
|
isolation: subagent.isolation,
|
|
4516
|
+
phase: subagent.phase,
|
|
4517
|
+
phaseState: subagent.phaseState,
|
|
4206
4518
|
toolCallsStarted,
|
|
4207
4519
|
toolCallsCompleted,
|
|
4208
4520
|
assistantMessages,
|
|
4209
4521
|
delegatedTasks,
|
|
4210
4522
|
delegatedSucceeded,
|
|
4211
4523
|
delegatedFailed,
|
|
4524
|
+
delegateIndex: subagent.delegateIndex,
|
|
4525
|
+
delegateTotal: subagent.delegateTotal,
|
|
4526
|
+
delegateDescription: subagent.delegateDescription,
|
|
4527
|
+
delegateProfile: subagent.delegateProfile,
|
|
4528
|
+
delegateItems: subagent.delegateItems,
|
|
4529
|
+
outputLength,
|
|
4530
|
+
waitMs,
|
|
4212
4531
|
errorMessage: event.isError
|
|
4213
4532
|
? event.result?.content?.[0]?.text ?? "error"
|
|
4214
4533
|
: undefined,
|
|
@@ -4220,6 +4539,7 @@ export class InteractiveMode {
|
|
|
4220
4539
|
}
|
|
4221
4540
|
this.subagentComponents.delete(event.toolCallId);
|
|
4222
4541
|
this.stopSubagentElapsedTimerIfIdle();
|
|
4542
|
+
this.refreshOrchestrationSummaryDisplay();
|
|
4223
4543
|
this.ui.requestRender();
|
|
4224
4544
|
break;
|
|
4225
4545
|
}
|
|
@@ -4248,6 +4568,15 @@ export class InteractiveMode {
|
|
|
4248
4568
|
this.pendingTools.clear();
|
|
4249
4569
|
this.subagentComponents.clear();
|
|
4250
4570
|
this.clearSubagentElapsedTimer();
|
|
4571
|
+
if (typeof this.refreshOrchestrationSummaryDisplay === "function") {
|
|
4572
|
+
this.refreshOrchestrationSummaryDisplay();
|
|
4573
|
+
if (typeof this.archiveOrchestrationPanelToChatIfComplete === "function") {
|
|
4574
|
+
this.archiveOrchestrationPanelToChatIfComplete();
|
|
4575
|
+
}
|
|
4576
|
+
}
|
|
4577
|
+
else if (this.orchestrationContainer?.clear) {
|
|
4578
|
+
this.orchestrationContainer.clear();
|
|
4579
|
+
}
|
|
4251
4580
|
this.currentTurnSawAssistantMessage = false;
|
|
4252
4581
|
await this.checkShutdownRequested();
|
|
4253
4582
|
this.ui.requestRender();
|
|
@@ -4515,6 +4844,7 @@ export class InteractiveMode {
|
|
|
4515
4844
|
const displayMessage = this.sanitizeAssistantDisplayMessage(message);
|
|
4516
4845
|
this.activeAssistantOrchestrationContext = previousOrchestrationContext;
|
|
4517
4846
|
const assistantComponent = new AssistantMessageComponent(displayMessage, this.hideThinkingBlock, this.getMarkdownThemeWithSettings());
|
|
4847
|
+
assistantComponent.setExpanded(this.toolOutputExpanded);
|
|
4518
4848
|
this.chatContainer.addChild(assistantComponent);
|
|
4519
4849
|
break;
|
|
4520
4850
|
}
|
|
@@ -4535,6 +4865,7 @@ export class InteractiveMode {
|
|
|
4535
4865
|
*/
|
|
4536
4866
|
renderSessionContext(sessionContext, options = {}) {
|
|
4537
4867
|
this.pendingTools.clear();
|
|
4868
|
+
this.resetOrchestrationSummary();
|
|
4538
4869
|
this.pendingInternalUserDisplayAliases = [];
|
|
4539
4870
|
this.pendingAssistantOrchestrationContexts = 0;
|
|
4540
4871
|
this.activeAssistantOrchestrationContext = false;
|
|
@@ -4552,17 +4883,14 @@ export class InteractiveMode {
|
|
|
4552
4883
|
if (content.type === "toolCall") {
|
|
4553
4884
|
if (content.name === "task") {
|
|
4554
4885
|
const args = content.arguments;
|
|
4555
|
-
|
|
4886
|
+
pendingSubagentHistory.set(content.id, {
|
|
4556
4887
|
description: args.description ?? "Running subtask",
|
|
4557
4888
|
profile: args.profile ?? "explore",
|
|
4558
|
-
status: "running",
|
|
4559
4889
|
cwd: args.cwd,
|
|
4560
4890
|
agent: args.agent,
|
|
4561
4891
|
lockKey: args.lock_key,
|
|
4562
4892
|
isolation: args.isolation,
|
|
4563
4893
|
});
|
|
4564
|
-
this.chatContainer.addChild(subagent);
|
|
4565
|
-
pendingSubagentHistory.set(content.id, subagent);
|
|
4566
4894
|
continue;
|
|
4567
4895
|
}
|
|
4568
4896
|
const component = new ToolExecutionComponent(content.name, content.arguments, { showImages: this.settingsManager.getShowImages() }, this.getRegisteredToolDefinition(content.name), this.ui);
|
|
@@ -4592,18 +4920,36 @@ export class InteractiveMode {
|
|
|
4592
4920
|
const subagent = pendingSubagentHistory.get(message.toolCallId);
|
|
4593
4921
|
if (subagent) {
|
|
4594
4922
|
const details = message.details;
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4923
|
+
this.pushOrchestrationCompletedSubagent({
|
|
4924
|
+
toolCallId: message.toolCallId,
|
|
4925
|
+
finishedAt: Date.now(),
|
|
4598
4926
|
status: message.isError ? "error" : "done",
|
|
4927
|
+
description: typeof details?.description === "string"
|
|
4928
|
+
? details.description
|
|
4929
|
+
: subagent.description ?? "Running subtask",
|
|
4930
|
+
profile: typeof details?.profile === "string"
|
|
4931
|
+
? details.profile
|
|
4932
|
+
: subagent.profile ?? "explore",
|
|
4933
|
+
durationMs: typeof details?.durationMs === "number" && Number.isFinite(details.durationMs)
|
|
4934
|
+
? Math.max(0, Math.floor(details.durationMs))
|
|
4935
|
+
: 0,
|
|
4936
|
+
cwd: subagent.cwd,
|
|
4937
|
+
agent: subagent.agent,
|
|
4938
|
+
lockKey: subagent.lockKey,
|
|
4939
|
+
isolation: subagent.isolation,
|
|
4599
4940
|
outputLength: typeof details?.outputLength === "number" ? details.outputLength : undefined,
|
|
4600
4941
|
waitMs: typeof details?.waitMs === "number" ? details.waitMs : undefined,
|
|
4601
|
-
toolCallsStarted: typeof details?.toolCallsStarted === "number" ? details.toolCallsStarted :
|
|
4602
|
-
toolCallsCompleted: typeof details?.toolCallsCompleted === "number" ? details.toolCallsCompleted :
|
|
4603
|
-
assistantMessages: typeof details?.assistantMessages === "number" ? details.assistantMessages :
|
|
4942
|
+
toolCallsStarted: typeof details?.toolCallsStarted === "number" ? details.toolCallsStarted : 0,
|
|
4943
|
+
toolCallsCompleted: typeof details?.toolCallsCompleted === "number" ? details.toolCallsCompleted : 0,
|
|
4944
|
+
assistantMessages: typeof details?.assistantMessages === "number" ? details.assistantMessages : 0,
|
|
4604
4945
|
delegatedTasks: typeof details?.delegatedTasks === "number" ? details.delegatedTasks : undefined,
|
|
4605
4946
|
delegatedSucceeded: typeof details?.delegatedSucceeded === "number" ? details.delegatedSucceeded : undefined,
|
|
4606
4947
|
delegatedFailed: typeof details?.delegatedFailed === "number" ? details.delegatedFailed : undefined,
|
|
4948
|
+
delegateIndex: typeof details?.delegateIndex === "number" ? details.delegateIndex : undefined,
|
|
4949
|
+
delegateTotal: typeof details?.delegateTotal === "number" ? details.delegateTotal : undefined,
|
|
4950
|
+
delegateDescription: typeof details?.delegateDescription === "string" ? details.delegateDescription : undefined,
|
|
4951
|
+
delegateProfile: typeof details?.delegateProfile === "string" ? details.delegateProfile : undefined,
|
|
4952
|
+
delegateItems: parseSubagentDelegateItems(details?.delegateItems),
|
|
4607
4953
|
errorMessage: message.isError
|
|
4608
4954
|
? message.content?.[0]?.text ?? "error"
|
|
4609
4955
|
: undefined,
|
|
@@ -4659,6 +5005,8 @@ export class InteractiveMode {
|
|
|
4659
5005
|
// =========================================================================
|
|
4660
5006
|
handleCtrlC() {
|
|
4661
5007
|
const now = Date.now();
|
|
5008
|
+
const queuedMessages = this.getAllQueuedMessages();
|
|
5009
|
+
const queuedMeta = queuedMessages.meta ?? [];
|
|
4662
5010
|
if (this.swarmActiveRunId) {
|
|
4663
5011
|
if (this.swarmStopRequested && now - this.lastSigintTime < 500) {
|
|
4664
5012
|
void this.shutdown();
|
|
@@ -4677,6 +5025,21 @@ export class InteractiveMode {
|
|
|
4677
5025
|
void this.interruptCurrentWork();
|
|
4678
5026
|
return;
|
|
4679
5027
|
}
|
|
5028
|
+
const hasInterruptibleWork = this.session.isStreaming ||
|
|
5029
|
+
this.session.isBashRunning ||
|
|
5030
|
+
this.session.isCompacting ||
|
|
5031
|
+
this.session.isRetrying ||
|
|
5032
|
+
this.iosmVerificationSession !== undefined ||
|
|
5033
|
+
this.standardInitSession !== undefined ||
|
|
5034
|
+
this.singularAnalysisSession !== undefined ||
|
|
5035
|
+
queuedMessages.steering.length > 0 ||
|
|
5036
|
+
queuedMessages.followUp.length > 0 ||
|
|
5037
|
+
queuedMeta.length > 0;
|
|
5038
|
+
if (hasInterruptibleWork) {
|
|
5039
|
+
this.lastSigintTime = now;
|
|
5040
|
+
void this.interruptCurrentWork();
|
|
5041
|
+
return;
|
|
5042
|
+
}
|
|
4680
5043
|
if (now - this.lastSigintTime < 500) {
|
|
4681
5044
|
void this.shutdown();
|
|
4682
5045
|
}
|
|
@@ -5075,6 +5438,8 @@ export class InteractiveMode {
|
|
|
5075
5438
|
const hasAutomationWork = this.iosmAutomationRun !== undefined;
|
|
5076
5439
|
const verificationSession = this.iosmVerificationSession;
|
|
5077
5440
|
const hasVerificationWork = verificationSession !== undefined;
|
|
5441
|
+
const standardInitSession = this.standardInitSession;
|
|
5442
|
+
const hasStandardInitWork = standardInitSession !== undefined;
|
|
5078
5443
|
const hasSwarmWork = this.swarmActiveRunId !== undefined;
|
|
5079
5444
|
const singularSession = this.singularAnalysisSession;
|
|
5080
5445
|
const hasSingularWork = singularSession !== undefined;
|
|
@@ -5085,6 +5450,7 @@ export class InteractiveMode {
|
|
|
5085
5450
|
if (!hasPendingQueuedMessages &&
|
|
5086
5451
|
!hasAutomationWork &&
|
|
5087
5452
|
!hasVerificationWork &&
|
|
5453
|
+
!hasStandardInitWork &&
|
|
5088
5454
|
!hasSwarmWork &&
|
|
5089
5455
|
!hasSingularWork &&
|
|
5090
5456
|
!hasMainStreaming &&
|
|
@@ -5123,11 +5489,13 @@ export class InteractiveMode {
|
|
|
5123
5489
|
? "Stopping IOSM automation..."
|
|
5124
5490
|
: hasVerificationWork
|
|
5125
5491
|
? "Stopping IOSM verification..."
|
|
5126
|
-
:
|
|
5127
|
-
? "Stopping
|
|
5128
|
-
:
|
|
5129
|
-
? "Stopping
|
|
5130
|
-
:
|
|
5492
|
+
: hasStandardInitWork
|
|
5493
|
+
? "Stopping /init..."
|
|
5494
|
+
: hasSwarmWork
|
|
5495
|
+
? "Stopping swarm run..."
|
|
5496
|
+
: hasSingularWork
|
|
5497
|
+
? "Stopping /singular analysis..."
|
|
5498
|
+
: "Stopping current run...");
|
|
5131
5499
|
const abortPromises = [];
|
|
5132
5500
|
if (hasMainStreaming) {
|
|
5133
5501
|
abortPromises.push(this.session.abort());
|
|
@@ -5135,6 +5503,9 @@ export class InteractiveMode {
|
|
|
5135
5503
|
if (verificationSession) {
|
|
5136
5504
|
abortPromises.push(verificationSession.abort());
|
|
5137
5505
|
}
|
|
5506
|
+
if (standardInitSession) {
|
|
5507
|
+
abortPromises.push(standardInitSession.abort());
|
|
5508
|
+
}
|
|
5138
5509
|
if (singularSession) {
|
|
5139
5510
|
abortPromises.push(singularSession.abort());
|
|
5140
5511
|
}
|
|
@@ -5795,6 +6166,7 @@ export class InteractiveMode {
|
|
|
5795
6166
|
autocompleteMaxVisible: this.settingsManager.getAutocompleteMaxVisible(),
|
|
5796
6167
|
quietStartup: this.settingsManager.getQuietStartup(),
|
|
5797
6168
|
clearOnShrink: this.settingsManager.getClearOnShrink(),
|
|
6169
|
+
compactFooter: this.getCompactFooterSetting(),
|
|
5798
6170
|
webSearchEnabled: this.settingsManager.getWebSearchEnabled(),
|
|
5799
6171
|
webSearchProviderMode: this.settingsManager.getWebSearchProviderMode(),
|
|
5800
6172
|
webSearchFallbackMode: this.settingsManager.getWebSearchFallbackMode(),
|
|
@@ -6003,6 +6375,11 @@ export class InteractiveMode {
|
|
|
6003
6375
|
this.settingsManager.setClearOnShrink(enabled);
|
|
6004
6376
|
this.ui.setClearOnShrink(enabled);
|
|
6005
6377
|
},
|
|
6378
|
+
onCompactFooterChange: (enabled) => {
|
|
6379
|
+
this.setCompactFooterSetting(enabled);
|
|
6380
|
+
this.footer.setCompactModeEnabled?.(enabled);
|
|
6381
|
+
this.ui.requestRender();
|
|
6382
|
+
},
|
|
6006
6383
|
onCancel: () => {
|
|
6007
6384
|
done();
|
|
6008
6385
|
this.ui.requestRender();
|
|
@@ -8595,6 +8972,7 @@ export class InteractiveMode {
|
|
|
8595
8972
|
profile: "plan",
|
|
8596
8973
|
enableTaskTool: false,
|
|
8597
8974
|
});
|
|
8975
|
+
this.standardInitSession = session;
|
|
8598
8976
|
let toolCallsStarted = 0;
|
|
8599
8977
|
const chunks = [];
|
|
8600
8978
|
const eventBridge = this.createIosmVerificationEventBridge({
|
|
@@ -9975,9 +10353,8 @@ export class InteractiveMode {
|
|
|
9975
10353
|
const mentionTask = cleaned.length > 0 ? cleaned : userInput;
|
|
9976
10354
|
const orchestrationAwareAgent = /orchestrator/i.test(mentionedAgent);
|
|
9977
10355
|
const mentionMode = orchestrationAwareAgent ? "parallel" : "sequential";
|
|
9978
|
-
const mentionMaxParallel = orchestrationAwareAgent ? MAX_ORCHESTRATION_PARALLEL : undefined;
|
|
9979
10356
|
const mentionPrompt = [
|
|
9980
|
-
`<orchestrate mode="${mentionMode}" agents="1"
|
|
10357
|
+
`<orchestrate mode="${mentionMode}" agents="1">`,
|
|
9981
10358
|
`- agent 1: profile=${this.activeProfileName} cwd=${this.sessionManager.getCwd()} agent=${mentionedAgent}`,
|
|
9982
10359
|
`task: ${mentionTask}`,
|
|
9983
10360
|
"constraints:",
|
|
@@ -9986,8 +10363,8 @@ export class InteractiveMode {
|
|
|
9986
10363
|
...(orchestrationAwareAgent
|
|
9987
10364
|
? [
|
|
9988
10365
|
"- Include delegate_parallel_hint in the task call.",
|
|
9989
|
-
|
|
9990
|
-
|
|
10366
|
+
"- If user explicitly requested an agent count, set delegate_parallel_hint to that count.",
|
|
10367
|
+
"- Otherwise set delegate_parallel_hint based on complexity: simple=1, medium=3-6, complex/risky=7+.",
|
|
9991
10368
|
"- For non-trivial tasks, prefer delegate_parallel_hint >= 2 and split into independent <delegate_task> workstreams.",
|
|
9992
10369
|
'- Prefer existing custom agents for delegated work when suitable (use <delegate_task agent="name" ...>).',
|
|
9993
10370
|
"- If no existing custom agent fits, create focused delegate streams via profile-based <delegate_task> blocks.",
|
|
@@ -10019,10 +10396,10 @@ export class InteractiveMode {
|
|
|
10019
10396
|
}
|
|
10020
10397
|
const explicitRequested = parseRequestedParallelAgentCount(userInput);
|
|
10021
10398
|
const hasComplexSignal = /\b(audit|security|hardening|refactor|migration|orchestrat|parallel|delegate|multi[-\s]?agent)\b/i.test(userInput);
|
|
10022
|
-
const fallbackParallel = Math.max(1,
|
|
10399
|
+
const fallbackParallel = Math.max(1, explicitRequested ??
|
|
10023
10400
|
(hasComplexSignal
|
|
10024
10401
|
? Math.max(details.requiredTopLevelTasks, 6)
|
|
10025
|
-
: Math.max(details.requiredTopLevelTasks, 3)))
|
|
10402
|
+
: Math.max(details.requiredTopLevelTasks, 3)));
|
|
10026
10403
|
this.showWarning(`META enforcement fallback: orchestration contract not satisfied (${details.launchedTopLevelTasks}/${details.requiredTopLevelTasks} task calls). Launching /swarm run.`);
|
|
10027
10404
|
await this.runSwarmFromTask(userInput, { maxParallel: fallbackParallel });
|
|
10028
10405
|
},
|
|
@@ -10050,6 +10427,8 @@ export class InteractiveMode {
|
|
|
10050
10427
|
case "message_start":
|
|
10051
10428
|
if (event.message.role === "assistant" && !hideAssistantText) {
|
|
10052
10429
|
verifyStreamingComponent = new AssistantMessageComponent(undefined, false, this.getMarkdownThemeWithSettings());
|
|
10430
|
+
verifyStreamingComponent.setExpanded(this.toolOutputExpanded);
|
|
10431
|
+
verifyStreamingComponent.setStreaming(true);
|
|
10053
10432
|
verifyStreamingMessage = event.message;
|
|
10054
10433
|
this.chatContainer.addChild(verifyStreamingComponent);
|
|
10055
10434
|
verifyStreamingComponent.updateContent(verifyStreamingMessage);
|
|
@@ -10072,6 +10451,7 @@ export class InteractiveMode {
|
|
|
10072
10451
|
case "message_end":
|
|
10073
10452
|
if (verifyStreamingComponent && event.message.role === "assistant") {
|
|
10074
10453
|
verifyStreamingMessage = event.message;
|
|
10454
|
+
verifyStreamingComponent.setStreaming(false);
|
|
10075
10455
|
verifyStreamingComponent.updateContent(verifyStreamingMessage);
|
|
10076
10456
|
verifyStreamingComponent = undefined;
|
|
10077
10457
|
verifyStreamingMessage = undefined;
|
|
@@ -10278,7 +10658,7 @@ export class InteractiveMode {
|
|
|
10278
10658
|
const highRisk = /\b(refactor|rewrite|migration|migrate|breaking|rollback|security|auth|authentication|authorization|permission|payment|billing|schema|database|critical)\b/i.test(normalizedTask);
|
|
10279
10659
|
const mediumRisk = /\b(cross[-\s]?module|architecture|infra|platform|multi[-\s]?file|integration|audit|hardening)\b/i.test(normalizedTask);
|
|
10280
10660
|
let hint = input.mode === "parallel"
|
|
10281
|
-
? Math.max(2,
|
|
10661
|
+
? Math.max(2, input.maxParallel ?? input.agents)
|
|
10282
10662
|
: 1;
|
|
10283
10663
|
if (highRisk) {
|
|
10284
10664
|
hint = Math.max(hint, 7);
|
|
@@ -10290,12 +10670,12 @@ export class InteractiveMode {
|
|
|
10290
10670
|
hint = Math.max(hint, 6);
|
|
10291
10671
|
}
|
|
10292
10672
|
if (input.hasDependencies) {
|
|
10293
|
-
hint = Math.max(2,
|
|
10673
|
+
hint = Math.max(2, hint);
|
|
10294
10674
|
}
|
|
10295
10675
|
if (input.hasLock) {
|
|
10296
|
-
hint = Math.max(1,
|
|
10676
|
+
hint = Math.max(1, hint);
|
|
10297
10677
|
}
|
|
10298
|
-
return Math.max(1,
|
|
10678
|
+
return Math.max(1, hint);
|
|
10299
10679
|
}
|
|
10300
10680
|
isEffectiveContractReady(contract) {
|
|
10301
10681
|
const hasText = (value) => typeof value === "string" && value.trim().length > 0;
|
|
@@ -10518,8 +10898,8 @@ export class InteractiveMode {
|
|
|
10518
10898
|
if (token === "--max-parallel") {
|
|
10519
10899
|
const next = rest[index + 1];
|
|
10520
10900
|
const parsed = next ? Number.parseInt(next, 10) : Number.NaN;
|
|
10521
|
-
if (!Number.isInteger(parsed) || parsed < 1
|
|
10522
|
-
this.showWarning(
|
|
10901
|
+
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
10902
|
+
this.showWarning("Invalid --max-parallel value (expected integer >= 1).");
|
|
10523
10903
|
return undefined;
|
|
10524
10904
|
}
|
|
10525
10905
|
maxParallel = parsed;
|
|
@@ -10692,16 +11072,15 @@ export class InteractiveMode {
|
|
|
10692
11072
|
resolveSwarmMaxParallel(input) {
|
|
10693
11073
|
const requested = input.requested;
|
|
10694
11074
|
if (typeof requested === "number" && Number.isFinite(requested)) {
|
|
10695
|
-
return Math.max(1, Math.
|
|
11075
|
+
return Math.max(1, Math.floor(requested));
|
|
10696
11076
|
}
|
|
10697
11077
|
const totalTasks = Math.max(1, input.plan.tasks.length);
|
|
10698
11078
|
const initialFanout = Math.max(1, input.plan.tasks.filter((task) => task.depends_on.length === 0).length);
|
|
10699
11079
|
const parallelizable = input.plan.tasks.filter((task) => task.concurrency_class === "implementation" || task.concurrency_class === "tests")
|
|
10700
11080
|
.length;
|
|
10701
11081
|
const sourceFloor = input.source === "singular" ? 4 : 3;
|
|
10702
|
-
const autoCap = Math.min(MAX_ORCHESTRATION_PARALLEL, 10);
|
|
10703
11082
|
const heuristic = Math.max(sourceFloor, Math.ceil(totalTasks / 2), initialFanout, parallelizable >= 4 ? Math.ceil(parallelizable / 2) : 1);
|
|
10704
|
-
return Math.max(1,
|
|
11083
|
+
return Math.max(1, heuristic);
|
|
10705
11084
|
}
|
|
10706
11085
|
resolveSwarmDispatchTimeoutMs() {
|
|
10707
11086
|
const dispatchTimeoutRaw = Number.parseInt(process.env.IOSM_SWARM_DISPATCH_TIMEOUT_MS ?? "", 10);
|
|
@@ -11803,8 +12182,8 @@ export class InteractiveMode {
|
|
|
11803
12182
|
if (arg === "--agents") {
|
|
11804
12183
|
const value = args[index + 1];
|
|
11805
12184
|
const parsed = value ? Number.parseInt(value, 10) : Number.NaN;
|
|
11806
|
-
if (!Number.isInteger(parsed) || parsed < 1
|
|
11807
|
-
this.showWarning(
|
|
12185
|
+
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
12186
|
+
this.showWarning("Invalid --agents value (expected integer >= 1).");
|
|
11808
12187
|
return undefined;
|
|
11809
12188
|
}
|
|
11810
12189
|
agents = parsed;
|
|
@@ -11814,8 +12193,8 @@ export class InteractiveMode {
|
|
|
11814
12193
|
if (arg === "--max-parallel") {
|
|
11815
12194
|
const value = args[index + 1];
|
|
11816
12195
|
const parsed = value ? Number.parseInt(value, 10) : Number.NaN;
|
|
11817
|
-
if (!Number.isInteger(parsed) || parsed < 1
|
|
11818
|
-
this.showWarning(
|
|
12196
|
+
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
12197
|
+
this.showWarning("Invalid --max-parallel value (expected integer >= 1).");
|
|
11819
12198
|
return undefined;
|
|
11820
12199
|
}
|
|
11821
12200
|
maxParallel = parsed;
|
|
@@ -11935,7 +12314,7 @@ export class InteractiveMode {
|
|
|
11935
12314
|
return undefined;
|
|
11936
12315
|
}
|
|
11937
12316
|
if (mode === "parallel" && maxParallel === undefined) {
|
|
11938
|
-
maxParallel = Math.max(1,
|
|
12317
|
+
maxParallel = Math.max(1, agents);
|
|
11939
12318
|
}
|
|
11940
12319
|
if (maxParallel !== undefined && maxParallel > agents) {
|
|
11941
12320
|
maxParallel = agents;
|
|
@@ -12068,6 +12447,8 @@ export class InteractiveMode {
|
|
|
12068
12447
|
"- when assignment lines include depends_on, still emit one task call per assignment; runtime enforces dependency gating",
|
|
12069
12448
|
"- include delegate_parallel_hint from each assignment/task_call hint in every corresponding task tool call",
|
|
12070
12449
|
"- for delegate_parallel_hint >= 2, split child work into nested <delegate_task> streams unless impossible",
|
|
12450
|
+
"- treat delegates strictly as child task calls; do not count plain tool invocations as delegated agents",
|
|
12451
|
+
"- assign explicit ownership domains per top-level agent to minimize overlap and duplicate findings",
|
|
12071
12452
|
"- if nested split is impossible for a non-trivial stream, emit one line: DELEGATION_IMPOSSIBLE: <reason>",
|
|
12072
12453
|
"- keep required orchestration task calls in foreground; do not set background=true unless user explicitly requested detached async runs",
|
|
12073
12454
|
"- do not poll .iosm/subagents/background via bash/read during orchestration; wait for task results and then synthesize",
|
|
@@ -14148,6 +14529,9 @@ export class InteractiveMode {
|
|
|
14148
14529
|
};
|
|
14149
14530
|
}
|
|
14150
14531
|
finally {
|
|
14532
|
+
if (this.standardInitSession === session) {
|
|
14533
|
+
this.standardInitSession = undefined;
|
|
14534
|
+
}
|
|
14151
14535
|
unsubscribe();
|
|
14152
14536
|
session.dispose();
|
|
14153
14537
|
}
|
|
@@ -14173,7 +14557,7 @@ export class InteractiveMode {
|
|
|
14173
14557
|
: "Mode: standard overwrite (existing guidance merged by agent when applicable).",
|
|
14174
14558
|
`.iosm/agents: ready`,
|
|
14175
14559
|
options.agentVerify
|
|
14176
|
-
? "Agent verification skipped in standard mode
|
|
14560
|
+
? "Agent verification skipped in standard mode. Switch to profile `iosm` for IOSM artifacts."
|
|
14177
14561
|
: "Verification: disabled.",
|
|
14178
14562
|
].join("\n"));
|
|
14179
14563
|
}
|
|
@@ -14194,6 +14578,10 @@ export class InteractiveMode {
|
|
|
14194
14578
|
this.showWarning("Cannot run /init while IOSM verification is already running.");
|
|
14195
14579
|
return;
|
|
14196
14580
|
}
|
|
14581
|
+
if (this.standardInitSession) {
|
|
14582
|
+
this.showWarning("Cannot run /init while another /init run is already in progress.");
|
|
14583
|
+
return;
|
|
14584
|
+
}
|
|
14197
14585
|
const args = this.parseSlashArgs(text).slice(1);
|
|
14198
14586
|
let force = false;
|
|
14199
14587
|
let agentVerify = true;
|
|
@@ -14343,6 +14731,7 @@ ${priorityLines}
|
|
|
14343
14731
|
|
|
14344
14732
|
### Key workspace files
|
|
14345
14733
|
|
|
14734
|
+
- \`AGENTS.md\` — contributor/agent collaboration guide (auto-synced on init)
|
|
14346
14735
|
- \`IOSM.md\` — agent playbook (auto-loaded as context each session)
|
|
14347
14736
|
- \`iosm.yaml\` — cycle configuration${result.cycle ? `\n- \`.iosm/cycles/${cycleId}/cycle-report.json\`` : ""}
|
|
14348
14737
|
- \`${shortPath(guidePath)}\`
|
|
@@ -14573,6 +14962,7 @@ The agent will automatically receive IOSM context on every turn.`;
|
|
|
14573
14962
|
}
|
|
14574
14963
|
setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
|
|
14575
14964
|
this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
|
|
14965
|
+
this.footer.setCompactModeEnabled(this.getCompactFooterSetting());
|
|
14576
14966
|
const themeName = this.settingsManager.getTheme();
|
|
14577
14967
|
const themeResult = themeName ? setTheme(themeName, true) : { success: true };
|
|
14578
14968
|
if (!themeResult.success) {
|
|
@@ -14911,7 +15301,7 @@ The agent will automatically receive IOSM context on every turn.`;
|
|
|
14911
15301
|
| \`${cycleThinkingLevel}\` | Cycle thinking level |
|
|
14912
15302
|
| \`${cycleModelForward}\` | Cycle models |
|
|
14913
15303
|
| \`${selectModel}\` | Open model selector |
|
|
14914
|
-
| \`${expandTools}\` | Toggle tool output expansion |
|
|
15304
|
+
| \`${expandTools}\` | Toggle tool/reasoning output expansion |
|
|
14915
15305
|
| \`${toggleThinking}\` | Toggle thinking block visibility |
|
|
14916
15306
|
| \`${externalEditor}\` | Edit message in external editor |
|
|
14917
15307
|
| \`${steer}\` | Queue steer message |
|