@mediadatafusion/pi-workflow-suite 0.0.18 → 0.0.20
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 +18 -0
- package/README.md +85 -44
- package/VERSION +1 -1
- package/config/workflow-settings.example.json +1 -0
- package/extensions/workflow-model-router.ts +5 -1
- package/extensions/workflow-modes.ts +435 -244
- package/extensions/workflow-shortcuts.ts +114 -0
- package/package.json +1 -1
- package/scripts/verify-live.sh +2 -0
|
@@ -8,11 +8,12 @@ import { StringEnum } from "@earendil-works/pi-ai";
|
|
|
8
8
|
import type { AssistantMessage, TextContent } from "@earendil-works/pi-ai";
|
|
9
9
|
import { CustomEditor, VERSION, compact as piCompact, estimateTokens as piEstimateTokens, findCutPoint as piFindCutPoint, getAgentDir, getMarkdownTheme, type ExtensionAPI, type ExtensionContext, type FileOperations, type SessionEntry, type ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
10
10
|
import { Type } from "typebox";
|
|
11
|
-
import { activeWorkflowPresetLabel, applyMissionModelForRole, applyModelForRole, applyStandardModelForRole, applyWorkflowPreset, compactionModeLabel, createProjectSettingsOverride, createWorkflowPreset, defaultWorkflowSettings, deleteWorkflowPreset, effectivePlanApprovalRequired, effectiveReviewAutoRun, effectiveValidateAfterExecution, effectiveValidationAutoRun, effectiveRepairGate, formatRole, getDefaultWriteTarget, loadEffectiveSettings, loadGlobalSettings, loadWorkflowSettings, normalizeWorkflowPresetName, parseMissionModelRole, parseRole, parseThinkingLevel, renameWorkflowPreset, renderActiveWorkflowPresetSummary, renderStandardModelStrategy, renderWorkflowModels, renderWorkflowPresets, resolveWorkflowPresetName, roleIsConfigured, saveCurrentWorkflowPreset, setMissionModelForRole, setMissionThinkingForRole, setModelForRole, setRoleEnabled, setStandardModelForRole, setStandardThinkingForRole, setThinkingForRole, standardModelSource, standardModelSourceLabel, standardTodoTriggerModeLabel, updateSettings, workflowCompactionCheckModeLabel, workflowPresetCatalog, workflowPresetLabel, workflowPresetNames, workflowPresetPickerLabel, workflowRoleLabel, workflowSettingsConsistencyDiagnostics, WORKFLOW_CUSTOM_PRESET_MARKER, WORKFLOW_SETTINGS_FILE, type MissionModelRole, type RoleModelSettings, type WorkflowRole, type WorkflowSettingsScope, type WorkflowStartupLogo, type WorkflowStartupLogoColorStyle, type WorkflowStartupLogoFont, type WorkflowStartupLogoShadowDirection, type WorkflowStartupVisual, type CustomBrandBaseVisual, type StandardClarificationMode, type StandardModelRole, type StandardTodoTriggerMode, type WorkflowAgentScope } from "./workflow-model-router.js";
|
|
11
|
+
import { activeWorkflowPresetLabel, applyMissionModelForRole, applyModelForRole, applyStandardModelForRole, applyWorkflowPreset, compactionModeLabel, createProjectSettingsOverride, createWorkflowPreset, defaultWorkflowSettings, deleteWorkflowPreset, effectivePlanApprovalRequired, effectiveReviewAutoRun, effectiveValidateAfterExecution, effectiveValidationAutoRun, effectiveRepairGate, formatRole, getDefaultWriteTarget, loadEffectiveSettings, loadGlobalSettings, loadWorkflowSettings, normalizeWorkflowPresetName, parseMissionModelRole, parseRole, parseThinkingLevel, renameWorkflowPreset, renderActiveWorkflowPresetSummary, renderStandardModelStrategy, renderWorkflowModels, renderWorkflowPresets, resolveWorkflowPresetName, roleIsConfigured, saveCurrentWorkflowPreset, setMissionModelForRole, setMissionThinkingForRole, setModelForRole, setRoleEnabled, setStandardModelForRole, setStandardThinkingForRole, setThinkingForRole, standardModelSource, standardModelSourceLabel, standardTodoTriggerModeLabel, updateSettings, workflowCompactionCheckModeLabel, workflowPresetCatalog, workflowPresetLabel, workflowPresetNames, workflowPresetPickerLabel, workflowRoleLabel, workflowSettingsConsistencyDiagnostics, WORKFLOW_CUSTOM_PRESET_MARKER, WORKFLOW_SETTINGS_FILE, type MissionModelRole, type RoleModelSettings, type WorkflowRole, type WorkflowSettingsScope, type WorkflowStartupLogo, type WorkflowStartupLogoColorStyle, type WorkflowStartupLogoFont, type WorkflowStartupLogoShadowDirection, type WorkflowStartupVisual, type WorkflowEditorHintContrast, type CustomBrandBaseVisual, type StandardClarificationMode, type StandardModelRole, type StandardTodoTriggerMode, type WorkflowAgentScope } from "./workflow-model-router.js";
|
|
12
12
|
import { renderHandoffProjectContext, renderWorkflowStatus, renderWorkflowSummary } from "./workflow-summary.js";
|
|
13
13
|
import { BASE_EXECUTE_TOOLS, EXECUTE_TOOLS, PLAN_TOOLS, REVIEW_TOOLS, WORKFLOW_DIAGRAM_TOOL, WORKFLOW_PLAN_RESULT_TOOL, WORKFLOW_REVIEW_RESULT_TOOL, WORKFLOW_EXECUTION_RESULT_TOOL, WORKFLOW_VALIDATION_RESULT_TOOL, WORKFLOW_REPAIR_RESULT_TOOL, WORKFLOW_PROGRESS_TOOL, MISSION_PLAN_RESULT_TOOL, MISSION_MILESTONE_RESULT_TOOL, STANDARD_HANDOFF_RESULT_TOOL, isBlockedExecuteCommand, registerToolGuard, standardSafeReadOnlyBash, VALIDATOR_TOOLS } from "./workflow-tool-guard.js";
|
|
14
14
|
import { refreshRuntimeWebTools, registerWorkflowWebTools, runtimeWebResearchGuidance, webSafePlanTools, withRuntimeWebTools } from "./workflow-web-tools.js";
|
|
15
15
|
import { addMissionCheckpoint, applyPlanRuntimeAccounting, applyStandardRuntimeAccounting, clearOldMissionStates, clearOldWorkflowPlans, compact, createMissionState, createStandardRuntimeId, createWorkflowPlanId, emptyState, extractVerdict, isMissionRuntimeActiveStatus, isPlanRuntimeActiveMode, listMissionStates, listWorkflowPlans, loadMissionState, loadState, loadWorkflowPlan, missionActiveRuntimeMs, missionRuntimeCounterState, missionWallClockAgeMs, planActiveRuntimeMs, planRuntimeCounterState, planWallClockAgeMs, saveMissionState, saveState, saveWorkflowPlan, standardActiveRuntimeMs, standardRuntimeCounterState, standardWallClockAgeMs, PLAN_HISTORY_DIR, MISSION_HISTORY_DIR, type ClarificationAnswer, type ClarificationQuestion, type MissionAutonomy, type MissionMilestone, type MissionState, type PlanProgressState, type PlanStepStatus, type PlanValidationStatus, type SavedWorkflowPlan, type StandardTodoItemStatus, type StandardTodoState, type WorkflowState, type WorkflowTypedHandoffType } from "./workflow-state.js";
|
|
16
|
+
import { WORKFLOW_SHORTCUTS, workflowEntryShortcutLabel as workflowRegistryEntryShortcutLabel, workflowPresetCycleShortcutLabel, workflowSettingsShortcutLines, workflowShortcutKey, workflowWidgetShortcutLabel, type WorkflowShortcutActionId } from "./workflow-shortcuts.js";
|
|
16
17
|
import { cleanupOrphanProcesses, clearSubagentResultCache, runWorkflowSubagents, workflowSubagentResultOutput, type WorkflowSubagentResult, type WorkflowSubagentTask } from "./subagent/runner.js";
|
|
17
18
|
import { parseScope, parseBool, parsePlanningDepth, parseClarificationMode, parseStandardTodoTriggerMode, parseStandardClarificationMode, parseStandardModelRole, parseWorkflowAgentScope, parseClarificationTiming, parseSubagentPolicy, parseSubagentPlanningPolicy, parseEditConcurrencyMode, parsePlanningOrchestrationPolicy, parseCompactionMode, parseWorkflowCompactionCheckMode, parseMissionAutonomy, parseValidationRetryMode, parsePositiveInt, updatedMessage, parseClarifyingQuestions, parseShorthandAnswers, formatAnswersForPlanner, planValidationStatusForVerdict } from "./workflow-parsers.js";
|
|
18
19
|
import { classifyValidationFailure, normalizeValidationVerdict, validationReportHasRepairableIssue } from "./workflow-validation-classifier.js";
|
|
@@ -2561,13 +2562,13 @@ Themes:
|
|
|
2561
2562
|
- /workflow-settings theme brand base minimal|workflow_duo|mission_control|diagnostic_center|data_stream|neural_grid
|
|
2562
2563
|
|
|
2563
2564
|
Workflow entry shortcuts:
|
|
2564
|
-
-
|
|
2565
|
-
-
|
|
2566
|
-
-
|
|
2567
|
-
- In the opposite active mode,
|
|
2565
|
+
- ${workflowEntryShortcutLabel("standard").replace(/^Standard:/, "")} toggles Standard Mode
|
|
2566
|
+
- ${workflowEntryShortcutLabel("plan").replace(/^Plan:/, "")} enters Plan Mode
|
|
2567
|
+
- ${workflowEntryShortcutLabel("mission").replace(/^Mission:/, "")} enters Mission Mode
|
|
2568
|
+
- In the opposite active mode, ${workflowEntryShortcutLabel("plan").replace(/^Plan:/, "")}/${workflowEntryShortcutLabel("mission").replace(/^Mission:/, "")} switches directly to that mode
|
|
2568
2569
|
|
|
2569
2570
|
Presets:
|
|
2570
|
-
-
|
|
2571
|
+
- ${workflowPresetCycleShortcutLabel()} cycles workflow presets from the active Plan/Mission/Standard footer/status line
|
|
2571
2572
|
- /workflow presets opens the preset selector
|
|
2572
2573
|
- /workflow presets list
|
|
2573
2574
|
- /workflow presets apply <name>
|
|
@@ -2680,6 +2681,7 @@ UI Widgets:
|
|
|
2680
2681
|
- /workflow-settings set ui showActiveWorkflowSwitchHint true|false
|
|
2681
2682
|
- /workflow-settings set ui showWidgetShortcutHint true|false
|
|
2682
2683
|
- /workflow-settings set ui showPresetShortcutHint true|false
|
|
2684
|
+
- /workflow-settings set ui editorHintContrast subtle|normal|bright|high
|
|
2683
2685
|
|
|
2684
2686
|
Sub-agents and parallelism:
|
|
2685
2687
|
- /workflow-settings set subagents enabled true|false
|
|
@@ -3684,7 +3686,7 @@ ${renderPlanModelSettings(settings)}
|
|
|
3684
3686
|
|
|
3685
3687
|
${renderMissionModelStrategy(settings)}
|
|
3686
3688
|
|
|
3687
|
-
## UI /
|
|
3689
|
+
## UI / Widgets
|
|
3688
3690
|
Plan Top Widget: ${widgetVisibilityLabel(settings, "planTop")}
|
|
3689
3691
|
Plan Bottom Widget: ${widgetVisibilityLabel(settings, "planBottom")}
|
|
3690
3692
|
Mission Top Widget: ${widgetVisibilityLabel(settings, "missionTop")}
|
|
@@ -3695,6 +3697,7 @@ Idle Entry Hint: ${workflowWidgetUi(settings).showIdleWorkflowEntryHint !== fals
|
|
|
3695
3697
|
Active Switch Hint: ${workflowWidgetUi(settings).showActiveWorkflowSwitchHint !== false ? "visible" : "hidden"}
|
|
3696
3698
|
Widget Shortcut Hint: ${workflowWidgetUi(settings).showWidgetShortcutHint !== false ? "visible" : "hidden"}
|
|
3697
3699
|
Preset Shortcut Hint: ${workflowWidgetUi(settings).showPresetShortcutHint !== false ? "visible" : "hidden"}
|
|
3700
|
+
Editor Hint Contrast: ${workflowEditorHintContrastLabel(workflowEditorHintContrast(settings))}
|
|
3698
3701
|
Workflow Theme: ${workflowThemeDisplayName(workflowThemeName(settings))}
|
|
3699
3702
|
Startup Visual: ${startupVisualOrDefault(settings)}
|
|
3700
3703
|
Startup Logo: ${startupLogoOrDefault(settings)}
|
|
@@ -3706,11 +3709,7 @@ Startup On Session Start: ${settings.ui.startupVisualOnSessionStart === true ? "
|
|
|
3706
3709
|
Custom Brand: ${settings.ui.customBrandEnabled === true ? "enabled" : "disabled"}
|
|
3707
3710
|
Custom Brand Text: ${sanitizeCustomBrandText(settings.ui.customBrandText) || "(empty)"}
|
|
3708
3711
|
Custom Brand Base Template: ${customBrandBaseVisualOrDefault(settings)}
|
|
3709
|
-
|
|
3710
|
-
Plan Shortcut: Ctrl+Shift+L enters Plan Mode
|
|
3711
|
-
Mission Shortcut: Ctrl+Shift+M enters Mission Mode
|
|
3712
|
-
Widget Shortcuts: Ctrl+Shift+T/B while Plan/Mission/Standard Mode is active
|
|
3713
|
-
Preset Cycle Shortcut: Ctrl+Shift+U while Plan/Mission/Standard Mode is active
|
|
3712
|
+
${workflowSettingsShortcutLines().join("\n")}
|
|
3714
3713
|
Footer Line: idle displays Plan/Mission entry hints only; active workflows display compact widget/preset hints and workflow switch hints by default
|
|
3715
3714
|
Fallback Commands: /workflow widgets status, /workflow presets, /standard, /plan, /mission
|
|
3716
3715
|
|
|
@@ -5030,15 +5029,10 @@ function planProgressWidget(state: WorkflowState, settings: ReturnType<typeof lo
|
|
|
5030
5029
|
return lines;
|
|
5031
5030
|
}
|
|
5032
5031
|
|
|
5033
|
-
const STANDARD_MODE_SHORTCUT = "Ctrl+Shift+S";
|
|
5034
|
-
const PLAN_MODE_SHORTCUT = "Ctrl+Shift+L";
|
|
5035
|
-
const MISSION_MODE_SHORTCUT = "Ctrl+Shift+M";
|
|
5036
|
-
|
|
5037
5032
|
type WorkflowEntryMode = "standard" | "plan" | "mission";
|
|
5038
5033
|
|
|
5039
5034
|
function workflowEntryShortcutLabel(mode: WorkflowEntryMode): string {
|
|
5040
|
-
|
|
5041
|
-
return mode === "plan" ? `Plan:${PLAN_MODE_SHORTCUT}` : `Mission:${MISSION_MODE_SHORTCUT}`;
|
|
5035
|
+
return workflowRegistryEntryShortcutLabel(mode);
|
|
5042
5036
|
}
|
|
5043
5037
|
|
|
5044
5038
|
function workflowFooterShortcutsEnabled(): boolean {
|
|
@@ -5051,10 +5045,10 @@ function workflowActiveShortcutSummary(mode: WorkflowEntryMode, state: WorkflowS
|
|
|
5051
5045
|
const parts: string[] = [];
|
|
5052
5046
|
if (shortcuts && ui.showWidgetShortcutHint !== false) {
|
|
5053
5047
|
const bottomRelevant = mode === "plan" ? planBottomRelevant(state) : mode === "mission" ? missionBottomRelevant(state, activeMissionForUi(state)) : Boolean(state.standardTodo?.items.length);
|
|
5054
|
-
parts.push(bottomRelevant
|
|
5048
|
+
parts.push(workflowWidgetShortcutLabel(bottomRelevant));
|
|
5055
5049
|
}
|
|
5056
5050
|
if (ui.showPresetShortcutHint !== false) {
|
|
5057
|
-
parts.push(`Preset:${activeWorkflowPresetLabel(settings)}${shortcuts ?
|
|
5051
|
+
parts.push(`Preset:${activeWorkflowPresetLabel(settings)}${shortcuts ? ` ${workflowPresetCycleShortcutLabel()}` : ""}`);
|
|
5058
5052
|
}
|
|
5059
5053
|
if (ui.showActiveWorkflowSwitchHint !== false) {
|
|
5060
5054
|
const switchHints = (["standard", "plan", "mission"] as WorkflowEntryMode[])
|
|
@@ -5414,7 +5408,7 @@ function renderWorkflowThemePreview(settings: ReturnType<typeof loadWorkflowSett
|
|
|
5414
5408
|
}
|
|
5415
5409
|
|
|
5416
5410
|
function renderWorkflowFooterThemePreview(settings: ReturnType<typeof loadWorkflowSettings>): string {
|
|
5417
|
-
const suffix = ` ${workflowShortcutStatusText(settings,
|
|
5411
|
+
const suffix = ` ${workflowShortcutStatusText(settings, `${workflowWidgetShortcutLabel(true)} Preset:simple ${workflowPresetCycleShortcutLabel()} ${workflowEntryShortcutLabel("mission")}`)}`;
|
|
5418
5412
|
return [
|
|
5419
5413
|
`${workflowWidgetRgb(settings, "title", "workflow:")}${workflowWidgetRgb(settings, "emphasis", "planning")}${suffix}`,
|
|
5420
5414
|
`${workflowWidgetRgb(settings, "title", "workflow:")}${workflowWidgetRgb(settings, "progress", "executing")}${suffix}`,
|
|
@@ -5527,8 +5521,8 @@ class WorkflowSuiteEditor extends CustomEditor {
|
|
|
5527
5521
|
try {
|
|
5528
5522
|
const settings = loadWorkflowSettings(this.workflowCwd);
|
|
5529
5523
|
const decorate = workflowRoleTextDecoration(settings, "muted");
|
|
5530
|
-
let hintStyled =
|
|
5531
|
-
if (decorate) hintStyled = decorate(hintStyled);
|
|
5524
|
+
let hintStyled = workflowEditorHintStyledText(settings, workflowEditorHintText);
|
|
5525
|
+
if (workflowEditorHintContrast(settings) === "subtle" && decorate) hintStyled = decorate(hintStyled);
|
|
5532
5526
|
const innerWidth = width - 2;
|
|
5533
5527
|
const hintLen = visibleTextWidth(hintStyled);
|
|
5534
5528
|
const displayHint = hintLen > innerWidth ? truncateVisibleText(hintStyled, innerWidth) : hintStyled;
|
|
@@ -6525,6 +6519,13 @@ function isMissionWorkflowMode(state: WorkflowState): boolean {
|
|
|
6525
6519
|
}
|
|
6526
6520
|
|
|
6527
6521
|
type WorkflowWidgetSlot = "planTop" | "planBottom" | "missionTop" | "missionBottom" | "standardTop" | "standardBottom";
|
|
6522
|
+
const WORKFLOW_EDITOR_HINT_CONTRASTS: WorkflowEditorHintContrast[] = ["subtle", "normal", "bright", "high"];
|
|
6523
|
+
const WORKFLOW_EDITOR_HINT_CONTRAST_LABELS: Record<WorkflowEditorHintContrast, string> = {
|
|
6524
|
+
subtle: "Subtle",
|
|
6525
|
+
normal: "Normal",
|
|
6526
|
+
bright: "Bright",
|
|
6527
|
+
high: "High Contrast",
|
|
6528
|
+
};
|
|
6528
6529
|
type WorkflowWidgetUiSettings = ReturnType<typeof loadWorkflowSettings>["ui"] & {
|
|
6529
6530
|
showPlanModeIndicator?: boolean;
|
|
6530
6531
|
planModeIndicatorText?: string;
|
|
@@ -6538,6 +6539,7 @@ type WorkflowWidgetUiSettings = ReturnType<typeof loadWorkflowSettings>["ui"] &
|
|
|
6538
6539
|
showActiveWorkflowSwitchHint?: boolean;
|
|
6539
6540
|
showWidgetShortcutHint?: boolean;
|
|
6540
6541
|
showPresetShortcutHint?: boolean;
|
|
6542
|
+
editorHintContrast?: WorkflowEditorHintContrast;
|
|
6541
6543
|
};
|
|
6542
6544
|
|
|
6543
6545
|
const widgetVisibilityOverrides: Partial<Record<WorkflowWidgetSlot, boolean>> = {};
|
|
@@ -6554,6 +6556,38 @@ function workflowWidgetUi(settings: ReturnType<typeof loadWorkflowSettings>): Wo
|
|
|
6554
6556
|
return settings.ui as WorkflowWidgetUiSettings;
|
|
6555
6557
|
}
|
|
6556
6558
|
|
|
6559
|
+
function parseEditorHintContrast(value?: string): WorkflowEditorHintContrast | undefined {
|
|
6560
|
+
const input = value?.trim().toLowerCase().replace(/[\s_-]+/g, "");
|
|
6561
|
+
if (!input) return undefined;
|
|
6562
|
+
if (input === "subtle" || input === "muted" || input === "dim") return "subtle";
|
|
6563
|
+
if (input === "normal" || input === "default") return "normal";
|
|
6564
|
+
if (input === "bright") return "bright";
|
|
6565
|
+
if (input === "high" || input === "highcontrast" || input === "maximum") return "high";
|
|
6566
|
+
return undefined;
|
|
6567
|
+
}
|
|
6568
|
+
|
|
6569
|
+
function workflowEditorHintContrast(settings: ReturnType<typeof loadWorkflowSettings>): WorkflowEditorHintContrast {
|
|
6570
|
+
return parseEditorHintContrast(workflowWidgetUi(settings).editorHintContrast) ?? "normal";
|
|
6571
|
+
}
|
|
6572
|
+
|
|
6573
|
+
function workflowEditorHintContrastLabel(contrast: WorkflowEditorHintContrast): string {
|
|
6574
|
+
return WORKFLOW_EDITOR_HINT_CONTRAST_LABELS[contrast];
|
|
6575
|
+
}
|
|
6576
|
+
|
|
6577
|
+
function workflowEditorHintStyledText(settings: ReturnType<typeof loadWorkflowSettings>, text: string): string {
|
|
6578
|
+
switch (workflowEditorHintContrast(settings)) {
|
|
6579
|
+
case "subtle":
|
|
6580
|
+
return `\x1b[2m\x1b[38;5;240m${text}\x1b[0m`;
|
|
6581
|
+
case "bright":
|
|
6582
|
+
return `\x1b[38;5;250m${text}\x1b[0m`;
|
|
6583
|
+
case "high":
|
|
6584
|
+
return `\x1b[1m\x1b[38;5;255m${text}\x1b[0m`;
|
|
6585
|
+
case "normal":
|
|
6586
|
+
default:
|
|
6587
|
+
return `\x1b[38;5;245m${text}\x1b[0m`;
|
|
6588
|
+
}
|
|
6589
|
+
}
|
|
6590
|
+
|
|
6557
6591
|
function workflowWidgetVisible(settings: ReturnType<typeof loadWorkflowSettings>, slot: WorkflowWidgetSlot): boolean {
|
|
6558
6592
|
const override = widgetVisibilityOverrides[slot];
|
|
6559
6593
|
if (override !== undefined) return override;
|
|
@@ -7137,7 +7171,7 @@ function renderSavedPlan(plan: SavedWorkflowPlan): string {
|
|
|
7137
7171
|
}
|
|
7138
7172
|
|
|
7139
7173
|
function missionHelp(): string {
|
|
7140
|
-
return `# Mission Mode Help\n\nMission Mode is a persistent milestone workflow for longer-running work. It runs alongside Plan Mode and does not replace /p.\n\nCommands:\n- /mission enters Mission Mode and waits for a goal\n- /mission help\n- /mission start <goal>\n- /mission <goal>\n- /mission clarify\n- /mission clarify answer 1A 2C\n- /mission clarify skip 1\n- /mission plan\n- /mission review\n- /mission approve\n- /mission run\n- /mission continue\n- /mission next\n- /mission pause\n- /mission resume\n- /mission retry\n- /mission repair\n- /mission revalidate\n- /mission set autonomy manual|approval_gated|supervised_auto|full_auto\n- /mission sync-settings\n- /mission status\n- /mission checkpoints\n- /mission stop\n- /mission list\n- /mission latest\n- /mission cleanup [limit]\n\nShortcuts:\n-
|
|
7174
|
+
return `# Mission Mode Help\n\nMission Mode is a persistent milestone workflow for longer-running work. It runs alongside Plan Mode and does not replace /p.\n\nCommands:\n- /mission enters Mission Mode and waits for a goal\n- /mission help\n- /mission start <goal>\n- /mission <goal>\n- /mission clarify\n- /mission clarify answer 1A 2C\n- /mission clarify skip 1\n- /mission plan\n- /mission review\n- /mission approve\n- /mission run\n- /mission continue\n- /mission next\n- /mission pause\n- /mission resume\n- /mission retry\n- /mission repair\n- /mission revalidate\n- /mission set autonomy manual|approval_gated|supervised_auto|full_auto\n- /mission sync-settings\n- /mission status\n- /mission checkpoints\n- /mission stop\n- /mission list\n- /mission latest\n- /mission cleanup [limit]\n\nShortcuts:\n- ${workflowEntryShortcutLabel("mission").replace(/^Mission:/, "")} enters Mission Mode\n- ${workflowEntryShortcutLabel("plan").replace(/^Plan:/, "")} switches from Mission Mode to Plan Mode\n\nSafety:\n- Mission plans require approval before /mission run.\n- full_auto never runs unless missions.allowFullAuto=true.\n- Destructive actions, push, deploy, database mutation, and secret edits require explicit approval.\n- Mission run uses executor, validator/final-validator, safety, sub-agent, and repair gates and records stop or block reasons.\n- Validation failures attempt safe repair/revalidation within configured retry limits, then block for approval if limits or safety gates are hit.`;
|
|
7141
7175
|
}
|
|
7142
7176
|
|
|
7143
7177
|
function promptCandidateFiles(name: string): string[] {
|
|
@@ -9718,7 +9752,7 @@ export default function workflowModes(pi: ExtensionAPI): void {
|
|
|
9718
9752
|
const route = await applyModelForRole(pi, ctx, "planner", { cwd: ctx.cwd });
|
|
9719
9753
|
if (!route) return false;
|
|
9720
9754
|
updateState({ modelsUsed: { ...(state.modelsUsed ?? {}), planner: modelLabel(route) } }, ctx);
|
|
9721
|
-
if (showNotice) ctx
|
|
9755
|
+
if (showNotice) workflowUiNotify(ctx, `Active Plan Mode planner route reapplied: ${modelLabel(route)}\n${activeModelDiagnostic(ctx)}`, "info");
|
|
9722
9756
|
return true;
|
|
9723
9757
|
};
|
|
9724
9758
|
|
|
@@ -9727,13 +9761,13 @@ export default function workflowModes(pi: ExtensionAPI): void {
|
|
|
9727
9761
|
const settings = loadWorkflowSettings(ctx.cwd);
|
|
9728
9762
|
const standardRole = effectiveStandardModelRole(settings);
|
|
9729
9763
|
if (standardRole === "current") {
|
|
9730
|
-
if (showNotice) ctx
|
|
9764
|
+
if (showNotice) workflowUiNotify(ctx, `Standard Mode keeps the current Pi model.\n${activeModelDiagnostic(ctx)}`, "info");
|
|
9731
9765
|
return false;
|
|
9732
9766
|
}
|
|
9733
9767
|
const route = await applyStandardModelForRole(pi, ctx, standardRole, { cwd: ctx.cwd });
|
|
9734
9768
|
if (!route) return false;
|
|
9735
9769
|
updateState({ modelsUsed: { ...(state.modelsUsed ?? {}), [standardRole]: modelLabel(route) } }, ctx);
|
|
9736
|
-
if (showNotice) ctx
|
|
9770
|
+
if (showNotice) workflowUiNotify(ctx, `Active Standard Mode ${standardRole} route applied: ${modelLabel(route)}\n${activeModelDiagnostic(ctx)}`, "info");
|
|
9737
9771
|
return true;
|
|
9738
9772
|
};
|
|
9739
9773
|
|
|
@@ -9748,7 +9782,7 @@ export default function workflowModes(pi: ExtensionAPI): void {
|
|
|
9748
9782
|
const settings = loadWorkflowSettings(ctx.cwd);
|
|
9749
9783
|
const globalUi = workflowWidgetUi(loadGlobalSettings());
|
|
9750
9784
|
const ui = workflowWidgetUi(settings);
|
|
9751
|
-
const common = `Active Mode: ${state.mode}\nShortcuts: ${globalUi.enableWidgetShortcuts !== false ? "enabled" : "disabled"}\nRemember Visibility: ${globalUi.rememberWidgetVisibility !== false ? "enabled" : "disabled"}\nStorage: ${globalUi.rememberWidgetVisibility !== false ? "global settings" : "current Pi session"}\
|
|
9785
|
+
const common = `Active Mode: ${state.mode}\nShortcuts: ${globalUi.enableWidgetShortcuts !== false ? "enabled" : "disabled"}\nRemember Visibility: ${globalUi.rememberWidgetVisibility !== false ? "enabled" : "disabled"}\nStorage: ${globalUi.rememberWidgetVisibility !== false ? "global settings" : "current Pi session"}\nEditor Hints: idle entry ${ui.showIdleWorkflowEntryHint !== false ? "visible" : "hidden"}, active switch ${ui.showActiveWorkflowSwitchHint !== false ? "visible" : "hidden"}, widgets ${ui.showWidgetShortcutHint !== false ? "visible" : "hidden"}, preset ${ui.showPresetShortcutHint !== false ? "visible" : "hidden"}, contrast ${workflowEditorHintContrastLabel(workflowEditorHintContrast(settings))}`;
|
|
9752
9786
|
if (isPlanWorkflowUiMode(state)) {
|
|
9753
9787
|
const bottom = planBottomRelevant(state) ? widgetVisibilityLabel(settings, "planBottom") : "not applicable";
|
|
9754
9788
|
return `# Workflow Widgets\n\nPlan Top Widget: ${widgetVisibilityLabel(settings, "planTop")}\nPlan Bottom Widget: ${bottom}\nStatus Line: ${widgetVisibilityStatus(state, settings) ?? "none"}\n${common}`;
|
|
@@ -9761,7 +9795,13 @@ export default function workflowModes(pi: ExtensionAPI): void {
|
|
|
9761
9795
|
if (isStandardWorkflowMode(state)) {
|
|
9762
9796
|
return `# Workflow Widgets\n\nStandard Top Widget: ${widgetVisibilityLabel(settings, "standardTop")}\nStandard To Do Widget: ${widgetVisibilityLabel(settings, "standardBottom")}\nStatus Line: ${widgetVisibilityStatus(state, settings) ?? "none"}\n${common}`;
|
|
9763
9797
|
}
|
|
9764
|
-
return `# Workflow Widgets\n\nNo active Plan/Mission/Standard widget is currently visible.\nStatus Line: ${widgetVisibilityStatus(state, settings) ?? "none"}\n\nEntry Shortcuts:\n- ${workflowEntryShortcutLabel("standard")}\n- ${workflowEntryShortcutLabel("plan")}\n- ${workflowEntryShortcutLabel("mission")}\n\nActive-mode
|
|
9798
|
+
return `# Workflow Widgets\n\nNo active Plan/Mission/Standard widget is currently visible.\nStatus Line: ${widgetVisibilityStatus(state, settings) ?? "none"}\n\nEntry Shortcuts:\n- ${workflowEntryShortcutLabel("standard")}\n- ${workflowEntryShortcutLabel("plan")}\n- ${workflowEntryShortcutLabel("mission")}\n\nActive-mode editor hints use compact text such as: ${workflowWidgetShortcutLabel(true)} Preset:${activeWorkflowPresetLabel(settings)} ${workflowPresetCycleShortcutLabel()} ${workflowEntryShortcutLabel("standard")} ${workflowEntryShortcutLabel("mission")}\nWidget toggles and preset cycling are visible only while Plan/Mission/Standard Mode is active.\n\n${common}`;
|
|
9799
|
+
};
|
|
9800
|
+
|
|
9801
|
+
const renderEditorHintsSettings = (ctx: ExtensionContext): string => {
|
|
9802
|
+
const settings = loadWorkflowSettings(ctx.cwd);
|
|
9803
|
+
const ui = workflowWidgetUi(settings);
|
|
9804
|
+
return `# Editor Hints\n\nThese hints render inline in the editor/input box.\n\nIdle Entry Hint: ${ui.showIdleWorkflowEntryHint !== false ? "visible" : "hidden"}\nActive Switch Hint: ${ui.showActiveWorkflowSwitchHint !== false ? "visible" : "hidden"}\nWidget Shortcut Hint: ${ui.showWidgetShortcutHint !== false ? "visible" : "hidden"}\nPreset Shortcut Hint: ${ui.showPresetShortcutHint !== false ? "visible" : "hidden"}\nHint Contrast: ${workflowEditorHintContrastLabel(workflowEditorHintContrast(settings))}`;
|
|
9765
9805
|
};
|
|
9766
9806
|
|
|
9767
9807
|
const setWorkflowWidgetVisibility = (ctx: ExtensionContext, slot: WorkflowWidgetSlot, visible: boolean): string => {
|
|
@@ -9814,7 +9854,7 @@ export default function workflowModes(pi: ExtensionAPI): void {
|
|
|
9814
9854
|
const messages = (["planTop", "planBottom", "missionTop", "missionBottom", "standardTop", "standardBottom"] as WorkflowWidgetSlot[]).map((slot) => setWorkflowWidgetVisibility(ctx, slot, visible));
|
|
9815
9855
|
return show(pi, `# Workflow Widgets\n\n${messages.join("\n")}\n\n${renderWorkflowWidgetsStatus(ctx)}`);
|
|
9816
9856
|
}
|
|
9817
|
-
return show(pi, "# Workflow Widgets\n\nUsage:\n- /workflow widgets status\n- /workflow widgets list\n- /workflow widgets configure\n- /workflow widgets toggle top\n- /workflow widgets toggle bottom\n- /workflow widgets on\n- /workflow widgets off\n\
|
|
9857
|
+
return show(pi, "# Workflow Widgets\n\nUsage:\n- /workflow widgets status\n- /workflow widgets list\n- /workflow widgets configure\n- /workflow widgets toggle top\n- /workflow widgets toggle bottom\n- /workflow widgets on\n- /workflow widgets off\n\nEditor hint behavior:\n- Idle: Plan/Mission entry shortcuts only\n- Active modes: compact widget/preset hints plus Plan/Mission switch hints by default\n- Active switch hints can be configured in /workflow-settings configure widgets -> Editor Hints");
|
|
9818
9858
|
};
|
|
9819
9859
|
|
|
9820
9860
|
const persistCurrentPlan = (ctx: ExtensionContext, approvalStatus: "draft" | "approved" | "revised" | "completed" | "archived", saveReason: string, handoff: { executionSummary?: string; reviewerReport?: string; validationReport?: string; repairAttempt?: string; finalReport?: string } = {}): string | undefined => {
|
|
@@ -14395,7 +14435,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14395
14435
|
const plannerReapplied = role === "planner" ? await reapplyPlannerRouteIfPlanMode(ctx, true) : false;
|
|
14396
14436
|
const standardSettings = loadWorkflowSettings(ctx.cwd);
|
|
14397
14437
|
const standardReapplied = effectiveStandardModelRole(standardSettings) === role ? await reapplyStandardRouteIfStandardMode(ctx, true) : false;
|
|
14398
|
-
ctx
|
|
14438
|
+
workflowUiNotify(ctx, `${role} model set to ${provider}/${model} in ${result.file}${plannerReapplied || standardReapplied ? `\n${activeModelDiagnostic(ctx)}` : ""}`, "info");
|
|
14399
14439
|
}
|
|
14400
14440
|
|
|
14401
14441
|
async function configureStandardRoleModel(ctx: ExtensionContext, role: WorkflowRole) {
|
|
@@ -14403,14 +14443,14 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14403
14443
|
if (!selected) return;
|
|
14404
14444
|
const result = setStandardModelForRole(role, selected.provider, selected.model, ctx.cwd);
|
|
14405
14445
|
await reapplyStandardRouteIfStandardMode(ctx, true);
|
|
14406
|
-
ctx
|
|
14446
|
+
workflowUiNotify(ctx, `standard ${role} model set to ${selected.provider}/${selected.model} in ${result.file}`, "info");
|
|
14407
14447
|
}
|
|
14408
14448
|
|
|
14409
14449
|
async function configureMissionRoleModel(ctx: ExtensionContext, role: MissionModelRole) {
|
|
14410
14450
|
const selected = await selectProviderAndModel(ctx, `Mission ${role} model`);
|
|
14411
14451
|
if (!selected) return;
|
|
14412
14452
|
const result = setMissionModelForRole(role, selected.provider, selected.model, ctx.cwd);
|
|
14413
|
-
ctx
|
|
14453
|
+
workflowUiNotify(ctx, `mission ${role} model set to ${selected.provider}/${selected.model} in ${result.file}`, "info");
|
|
14414
14454
|
}
|
|
14415
14455
|
|
|
14416
14456
|
async function configureStandardThinking(ctx: ExtensionContext) {
|
|
@@ -14420,7 +14460,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14420
14460
|
if (!level) return;
|
|
14421
14461
|
const result = setStandardThinkingForRole(role, level, ctx.cwd);
|
|
14422
14462
|
await reapplyStandardRouteIfStandardMode(ctx, true);
|
|
14423
|
-
ctx
|
|
14463
|
+
workflowUiNotify(ctx, `standard ${role} thinking set to ${level} in ${result.file}`, "info");
|
|
14424
14464
|
}
|
|
14425
14465
|
|
|
14426
14466
|
async function configureMissionThinking(ctx: ExtensionContext) {
|
|
@@ -14429,7 +14469,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14429
14469
|
const level = parseThinkingLevel((await ctx.ui.select("Select mission thinking level:", ["off", "minimal", "low", "medium", "high", "xhigh"])) ?? "");
|
|
14430
14470
|
if (!level) return;
|
|
14431
14471
|
const result = setMissionThinkingForRole(role, level, ctx.cwd);
|
|
14432
|
-
ctx
|
|
14472
|
+
workflowUiNotify(ctx, `mission ${role} thinking set to ${level} in ${result.file}`, "info");
|
|
14433
14473
|
}
|
|
14434
14474
|
|
|
14435
14475
|
async function configureThinking(ctx: ExtensionContext) {
|
|
@@ -14441,7 +14481,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14441
14481
|
const plannerReapplied = role === "planner" ? await reapplyPlannerRouteIfPlanMode(ctx, true) : false;
|
|
14442
14482
|
const standardSettings = loadWorkflowSettings(ctx.cwd);
|
|
14443
14483
|
const standardReapplied = effectiveStandardModelRole(standardSettings) === role ? await reapplyStandardRouteIfStandardMode(ctx, true) : false;
|
|
14444
|
-
ctx
|
|
14484
|
+
workflowUiNotify(ctx, `${role} thinking set to ${level} in ${result.file}${plannerReapplied || standardReapplied ? `\n${activeModelDiagnostic(ctx)}` : ""}`, "info");
|
|
14445
14485
|
}
|
|
14446
14486
|
|
|
14447
14487
|
async function chooseBool(ctx: ExtensionContext, title: string): Promise<boolean | undefined> {
|
|
@@ -14449,6 +14489,128 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14449
14489
|
return parseBool(choice ?? undefined);
|
|
14450
14490
|
}
|
|
14451
14491
|
|
|
14492
|
+
function humanizeWorkflowSettingSegment(segment: string): string {
|
|
14493
|
+
return segment
|
|
14494
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
14495
|
+
.replace(/[_-]+/g, " ")
|
|
14496
|
+
.replace(/\bui\b/gi, "UI")
|
|
14497
|
+
.replace(/\bapi\b/gi, "API")
|
|
14498
|
+
.replace(/\bto do\b/gi, "To Do")
|
|
14499
|
+
.trim()
|
|
14500
|
+
.replace(/\s+/g, " ")
|
|
14501
|
+
.replace(/\w\S*/g, (word) => word === "UI" || word === "API" ? word : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());
|
|
14502
|
+
}
|
|
14503
|
+
|
|
14504
|
+
function workflowSettingDisplayLabel(setting: string): string {
|
|
14505
|
+
const labels: Record<string, string> = {
|
|
14506
|
+
"ui.editorHintContrast": "Editor hint contrast",
|
|
14507
|
+
"ui.showIdleWorkflowEntryHint": "Idle entry hint",
|
|
14508
|
+
"ui.showActiveWorkflowSwitchHint": "Active switch hint",
|
|
14509
|
+
"ui.showWidgetShortcutHint": "Widget shortcut hint",
|
|
14510
|
+
"ui.showPresetShortcutHint": "Preset shortcut hint",
|
|
14511
|
+
"ui.enableWidgetShortcuts": "Widget shortcuts",
|
|
14512
|
+
"ui.rememberWidgetVisibility": "Remember widget visibility",
|
|
14513
|
+
"ui.workflowTheme": "Workflow theme",
|
|
14514
|
+
"ui.widgetTextStyle": "Widget text style",
|
|
14515
|
+
"ui.startupTextStyle": "Startup text style",
|
|
14516
|
+
"ui.startupVisual": "Startup visual",
|
|
14517
|
+
"ui.startupLogo": "Startup logo",
|
|
14518
|
+
"ui.startupLogoText": "Startup logo text",
|
|
14519
|
+
"ui.startupLogoFont": "Startup logo font",
|
|
14520
|
+
"ui.startupLogoShadowDirection": "Startup logo shadow direction",
|
|
14521
|
+
"ui.startupLogoColorStyle": "Startup logo color style",
|
|
14522
|
+
"ui.startupVisualOnSessionStart": "Startup on session start",
|
|
14523
|
+
"ui.customBrandEnabled": "Custom brand",
|
|
14524
|
+
"ui.customBrandText": "Custom brand text",
|
|
14525
|
+
"ui.customBrandBaseVisual": "Custom brand base visual",
|
|
14526
|
+
"interactiveClarificationEnabled": "Interactive clarification",
|
|
14527
|
+
"maxClarificationQuestions": "Max clarification questions",
|
|
14528
|
+
"planning.depth": "Planning depth",
|
|
14529
|
+
"planning.clarificationMode": "Planning clarification mode",
|
|
14530
|
+
"planning.interactiveClarificationEnabled": "Interactive clarification",
|
|
14531
|
+
"planning.maxClarificationQuestions": "Max clarification questions",
|
|
14532
|
+
"planning.clarificationTiming": "Planning clarification timing",
|
|
14533
|
+
"planning.maxTokens": "Planning token budget",
|
|
14534
|
+
"planning.maxRuntimeHours": "Planning runtime budget",
|
|
14535
|
+
"standard.allowSubagents": "Standard sub-agents",
|
|
14536
|
+
"standard.subagentScope": "Standard sub-agent scope",
|
|
14537
|
+
"standard.todoTriggerMode": "To Do trigger mode",
|
|
14538
|
+
"standard.clarificationMode": "Standard clarification mode",
|
|
14539
|
+
"standard.interactiveClarificationEnabled": "Standard interactive clarification",
|
|
14540
|
+
"standard.maxClarificationQuestions": "Standard max clarification questions",
|
|
14541
|
+
"standard.clarificationTiming": "Standard clarification timing",
|
|
14542
|
+
"standard.maxTokens": "Standard token budget",
|
|
14543
|
+
"standard.enabled": "Standard Mode",
|
|
14544
|
+
"subagents.enabled": "Sub-agents",
|
|
14545
|
+
"subagents.activityIndicatorEnabled": "Sub-agent activity indicator",
|
|
14546
|
+
"subagents.allowBackgroundSubagents": "Background sub-agents",
|
|
14547
|
+
"subagents.editConcurrencyMode": "Sub-agent edit concurrency mode",
|
|
14548
|
+
"subagents.planningOrchestrationPolicy": "Planning orchestration policy",
|
|
14549
|
+
"missions.enabled": "Mission Mode",
|
|
14550
|
+
"missions.defaultAutonomy": "Mission default autonomy",
|
|
14551
|
+
"missions.subagentPolicy": "Mission sub-agent policy",
|
|
14552
|
+
"missions.planningDepth": "Mission planning depth",
|
|
14553
|
+
"missions.clarificationMode": "Mission clarification mode",
|
|
14554
|
+
"missions.interactiveClarificationEnabled": "Mission interactive clarification",
|
|
14555
|
+
"missions.maxClarificationQuestions": "Mission max clarification questions",
|
|
14556
|
+
"missions.clarificationTiming": "Mission clarification timing",
|
|
14557
|
+
"missions.maxTokens": "Mission token budget",
|
|
14558
|
+
"missions.maxRuntimeHours": "Mission runtime budget",
|
|
14559
|
+
"missions.checkpointIntervalMinutes": "Mission checkpoint interval",
|
|
14560
|
+
"missions.heartbeatEnabled": "Mission heartbeat",
|
|
14561
|
+
"missions.watchdogEnabled": "Mission watchdog",
|
|
14562
|
+
"missions.watchdogStaleMinutes": "Mission watchdog stale minutes",
|
|
14563
|
+
"missions.missionHistoryLimit": "Mission history limit",
|
|
14564
|
+
"context.autoCompactionEnabled": "Workflow auto trigger",
|
|
14565
|
+
"context.compactionTriggerPercent": "Workflow trigger percent",
|
|
14566
|
+
"context.compactionCooldownMinutes": "Compaction cooldown",
|
|
14567
|
+
"context.customCompactionReserveTokens": "Custom compaction reserve tokens",
|
|
14568
|
+
"context.customCompactionKeepRecentTokens": "Custom compaction keep-recent tokens",
|
|
14569
|
+
"workflow.validationRetryMode": "Validation retry mode",
|
|
14570
|
+
"workflow.planHistoryLimit": "Plan history limit",
|
|
14571
|
+
"workflow.planShowProgressBar": "Plan progress bar",
|
|
14572
|
+
"safety.repoLockEnabled": "Project Repo Lock",
|
|
14573
|
+
};
|
|
14574
|
+
if (labels[setting]) return labels[setting];
|
|
14575
|
+
const parts = setting.split(".");
|
|
14576
|
+
return humanizeWorkflowSettingSegment(parts[parts.length - 1] || setting);
|
|
14577
|
+
}
|
|
14578
|
+
|
|
14579
|
+
function workflowSettingDisplayValue(setting: string, value: string): string {
|
|
14580
|
+
const clean = value.trim().replace(/\s+/g, " ");
|
|
14581
|
+
if (setting === "ui.editorHintContrast") {
|
|
14582
|
+
return workflowEditorHintContrastLabel(parseEditorHintContrast(clean) ?? "normal");
|
|
14583
|
+
}
|
|
14584
|
+
if (clean === "true") {
|
|
14585
|
+
return /^ui\.show.*Hint$/.test(setting) ? "shown" : "enabled";
|
|
14586
|
+
}
|
|
14587
|
+
if (clean === "false") {
|
|
14588
|
+
return /^ui\.show.*Hint$/.test(setting) ? "hidden" : "disabled";
|
|
14589
|
+
}
|
|
14590
|
+
return clean
|
|
14591
|
+
.replace(/_/g, " ")
|
|
14592
|
+
.replace(/\bpi\b/gi, "Pi")
|
|
14593
|
+
.replace(/\w\S*/g, (word) => word === "Pi" || word.toUpperCase() === "API" ? word : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());
|
|
14594
|
+
}
|
|
14595
|
+
|
|
14596
|
+
function workflowFriendlyNotification(message: string, level?: "info" | "warning" | "error"): string {
|
|
14597
|
+
if (level !== "info") return message;
|
|
14598
|
+
let text = message.replace(/\s+in\s+\/\S+/g, "").replace(/\s+/g, " ").trim();
|
|
14599
|
+
const settingMatch = text.match(/^([A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z0-9_]+)*)\s+set to\s+([^.;]+)([.;]?.*)$/);
|
|
14600
|
+
if (settingMatch) {
|
|
14601
|
+
const [, setting, value, tail = ""] = settingMatch;
|
|
14602
|
+
const label = workflowSettingDisplayLabel(setting);
|
|
14603
|
+
const displayValue = workflowSettingDisplayValue(setting, value);
|
|
14604
|
+
const suffix = tail.replace(/^[.;]\s*/, "").trim();
|
|
14605
|
+
return `${label} set to ${displayValue}.${suffix ? ` ${suffix}` : ""}`;
|
|
14606
|
+
}
|
|
14607
|
+
return text.charAt(0).toUpperCase() + text.slice(1);
|
|
14608
|
+
}
|
|
14609
|
+
|
|
14610
|
+
function workflowUiNotify(ctx: ExtensionContext, message: string, level?: "info" | "warning" | "error"): void {
|
|
14611
|
+
ctx.ui.notify(workflowFriendlyNotification(message, level), level);
|
|
14612
|
+
}
|
|
14613
|
+
|
|
14452
14614
|
async function showPlanningSettingsMenu(ctx: ExtensionContext) {
|
|
14453
14615
|
if (!ctx.hasUI) return show(pi, renderFullWorkflowSettings(loadWorkflowSettings(ctx.cwd)));
|
|
14454
14616
|
while (ctx.hasUI) {
|
|
@@ -14456,7 +14618,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14456
14618
|
if (!choice || choice === "Back") return;
|
|
14457
14619
|
if (choice === "Set planning.depth") {
|
|
14458
14620
|
const depth = parsePlanningDepth((await ctx.ui.select("Planning depth", ["fast", "standard", "deep", "maximum"])) ?? "");
|
|
14459
|
-
if (depth) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.depth = depth; }); ctx
|
|
14621
|
+
if (depth) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.depth = depth; }); workflowUiNotify(ctx, `planning.depth set to ${depth} in ${r.file}`, "info"); }
|
|
14460
14622
|
} else if (choice === "List Current Settings") {
|
|
14461
14623
|
const s = loadWorkflowSettings(ctx.cwd);
|
|
14462
14624
|
show(pi, `# Planning Settings\n\nplanning.depth: ${s.planning.depth}`);
|
|
@@ -14471,13 +14633,13 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14471
14633
|
if (!choice || choice === "Back") return;
|
|
14472
14634
|
if (choice === "Set clarificationMode") {
|
|
14473
14635
|
const mode = parseClarificationMode((await ctx.ui.select("Clarification mode", ["auto", "always_for_nontrivial", "never"])) ?? "");
|
|
14474
|
-
if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.clarificationMode = mode; }); ctx
|
|
14636
|
+
if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.clarificationMode = mode; }); workflowUiNotify(ctx, `planning.clarificationMode set to ${mode} in ${r.file}`, "info"); }
|
|
14475
14637
|
} else if (choice === "Set interactiveClarificationEnabled") {
|
|
14476
14638
|
const enabled = await chooseBool(ctx, "Interactive clarification enabled?");
|
|
14477
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.interactiveClarificationEnabled = enabled; }); ctx
|
|
14639
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.interactiveClarificationEnabled = enabled; }); workflowUiNotify(ctx, `interactiveClarificationEnabled set to ${enabled} in ${r.file}`, "info"); }
|
|
14478
14640
|
} else if (choice === "Set maxClarificationQuestions") {
|
|
14479
14641
|
const count = parsePositiveInt((await ctx.ui.select("Max clarification questions", ["1", "2", "3", "4", "5"])) ?? "");
|
|
14480
|
-
if (count) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxClarificationQuestions = count; }); ctx
|
|
14642
|
+
if (count) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxClarificationQuestions = count; }); workflowUiNotify(ctx, `maxClarificationQuestions set to ${count} in ${r.file}`, "info"); }
|
|
14481
14643
|
} else if (choice === "List Current Settings") {
|
|
14482
14644
|
const s = loadWorkflowSettings(ctx.cwd);
|
|
14483
14645
|
show(pi, `# Clarification Settings\n\nClarification Mode: ${s.planning.clarificationMode}\nInteractive Clarification: ${s.planning.interactiveClarificationEnabled !== false ? "enabled" : "disabled"}\nMax Clarification Questions: ${s.planning.maxClarificationQuestions}`);
|
|
@@ -14493,11 +14655,11 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14493
14655
|
if (!choice || choice === "Back") return;
|
|
14494
14656
|
if (choice.endsWith("Policy")) {
|
|
14495
14657
|
const policy = parseSubagentPolicy((await ctx.ui.select(`${label} policy`, ["off", "auto", "deep", "maximum", "forced"])) ?? "");
|
|
14496
|
-
if (policy) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.subagents as typeof s.subagents & Record<string, string>)[keys.policyKey] = policy; }); ctx
|
|
14658
|
+
if (policy) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.subagents as typeof s.subagents & Record<string, string>)[keys.policyKey] = policy; }); workflowUiNotify(ctx, `subagents.${keys.policyKey} set to ${policy} in ${r.file}`, "info"); }
|
|
14497
14659
|
} else {
|
|
14498
14660
|
const key = choice.includes("Deep") ? keys.deepKey : keys.maximumKey;
|
|
14499
14661
|
const count = parsePositiveInt((await ctx.ui.select(`${label} ${choice.includes("Deep") ? "deep" : "maximum / forced"} workers`, ["0", "1", "2", "3", "4", "5", "6", "7", "8"])) ?? "");
|
|
14500
|
-
if (count !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.subagents as typeof s.subagents & Record<string, number>)[key] = count; }); ctx
|
|
14662
|
+
if (count !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.subagents as typeof s.subagents & Record<string, number>)[key] = count; }); workflowUiNotify(ctx, `subagents.${key} set to ${count} in ${r.file}. Forced policy uses this phase's Maximum / Forced worker count.`, "info"); }
|
|
14501
14663
|
}
|
|
14502
14664
|
}
|
|
14503
14665
|
}
|
|
@@ -14515,7 +14677,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14515
14677
|
const standard = s.standard as typeof s.standard & { subagents?: Record<string, boolean | number | string | undefined> };
|
|
14516
14678
|
standard.subagents = { ...(standard.subagents ?? {}), [keys.policyKey]: policy };
|
|
14517
14679
|
});
|
|
14518
|
-
ctx
|
|
14680
|
+
workflowUiNotify(ctx, `standard.subagents.${keys.policyKey} set to ${policy} in ${r.file}`, "info");
|
|
14519
14681
|
}
|
|
14520
14682
|
} else {
|
|
14521
14683
|
const key = choice.includes("Deep") ? keys.deepKey : keys.maximumKey;
|
|
@@ -14525,7 +14687,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14525
14687
|
const standard = s.standard as typeof s.standard & { subagents?: Record<string, boolean | number | string | undefined> };
|
|
14526
14688
|
standard.subagents = { ...(standard.subagents ?? {}), [key]: count };
|
|
14527
14689
|
});
|
|
14528
|
-
ctx
|
|
14690
|
+
workflowUiNotify(ctx, `standard.subagents.${key} set to ${count} in ${r.file}. Forced policy uses this Standard phase's Maximum / Forced worker count.`, "info");
|
|
14529
14691
|
}
|
|
14530
14692
|
}
|
|
14531
14693
|
}
|
|
@@ -14544,7 +14706,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14544
14706
|
const standard = s.standard as typeof s.standard & { subagents?: Record<string, boolean | number | string | undefined> };
|
|
14545
14707
|
standard.subagents = { ...(standard.subagents ?? {}), [key]: enabled };
|
|
14546
14708
|
});
|
|
14547
|
-
ctx
|
|
14709
|
+
workflowUiNotify(ctx, `standard.subagents.${key} set to ${enabled} in ${r.file}`, "info");
|
|
14548
14710
|
}
|
|
14549
14711
|
}
|
|
14550
14712
|
}
|
|
@@ -14561,7 +14723,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14561
14723
|
const standard = s.standard as typeof s.standard & { subagents?: Record<string, boolean | number | string | undefined> };
|
|
14562
14724
|
standard.subagents = { ...(standard.subagents ?? {}), [key]: enabled };
|
|
14563
14725
|
});
|
|
14564
|
-
ctx
|
|
14726
|
+
workflowUiNotify(ctx, `standard.subagents.${key} set to ${enabled} in ${r.file}`, "info");
|
|
14565
14727
|
}
|
|
14566
14728
|
}
|
|
14567
14729
|
}
|
|
@@ -14573,7 +14735,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14573
14735
|
if (!choice || choice === "Back") return;
|
|
14574
14736
|
if (choice === "Enable / Disable Standard Sub-agents") {
|
|
14575
14737
|
const enabled = await chooseBool(ctx, "standard.allowSubagents?");
|
|
14576
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.allowSubagents = enabled; }); ctx
|
|
14738
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.allowSubagents = enabled; }); workflowUiNotify(ctx, `standard.allowSubagents set to ${enabled} in ${r.file}`, "info"); }
|
|
14577
14739
|
} else if (choice === "Standard Planning / Research Policy / Workers") await showStandardSubagentPhaseSettingsMenu(ctx, "Planning", "Standard Planning / Research");
|
|
14578
14740
|
else if (choice === "Standard Execution Policy / Workers") await showStandardSubagentPhaseSettingsMenu(ctx, "Execution", "Standard Execution");
|
|
14579
14741
|
else if (choice === "Standard Repair Policy / Workers") await showStandardSubagentPhaseSettingsMenu(ctx, "Repair", "Standard Repair");
|
|
@@ -14581,15 +14743,15 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14581
14743
|
else if (choice === "Standard Validation Policy / Workers") await showStandardSubagentPhaseSettingsMenu(ctx, "Validation", "Standard Validation");
|
|
14582
14744
|
else if (choice === "Agent Scope") {
|
|
14583
14745
|
const scope = parseWorkflowAgentScope((await ctx.ui.select("Standard agent scope", ["user", "project", "both"])) ?? "");
|
|
14584
|
-
if (scope) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.subagentScope = scope; }); ctx
|
|
14746
|
+
if (scope) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.subagentScope = scope; }); workflowUiNotify(ctx, `standard.subagentScope set to ${scope} in ${r.file}`, "info"); }
|
|
14585
14747
|
} else if (choice === "Auto-use Toggles") await showStandardSubagentAutoUseMenu(ctx);
|
|
14586
14748
|
else if (choice === "Parallel Agent Settings") await showStandardParallelismSettingsMenu(ctx);
|
|
14587
14749
|
else if (choice === "Activity Indicator") {
|
|
14588
14750
|
const enabled = await chooseBool(ctx, "subagents.activityIndicatorEnabled?");
|
|
14589
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.activityIndicatorEnabled = enabled; }); ctx
|
|
14751
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.activityIndicatorEnabled = enabled; }); workflowUiNotify(ctx, `subagents.activityIndicatorEnabled set to ${enabled} in ${r.file}`, "info"); renderWorkflowSubagentActivity(ctx); }
|
|
14590
14752
|
} else if (choice === "List Current Settings") {
|
|
14591
14753
|
const s = loadWorkflowSettings(ctx.cwd);
|
|
14592
|
-
show(pi, `#
|
|
14754
|
+
show(pi, `# Standard Sub-agents / Workers\n\nSub-agents: ${s.standard.allowSubagents !== false ? "enabled" : "disabled"}\nAgent Scope: ${s.standard.subagentScope ?? "user"}\nActivity Indicator: ${s.subagents.activityIndicatorEnabled !== false ? "enabled" : "disabled"}\nAuto-use Planning: ${s.standard.subagents?.autoUseDuringPlanning !== false ? "on" : "off"}\nAuto-use Execution: ${s.standard.subagents?.autoUseDuringExecution !== false ? "on" : "off"}\nAuto-use Repair: ${s.standard.subagents?.autoUseDuringRepair !== false ? "on" : "off"}\nAuto-use Review: ${s.standard.subagents?.autoUseDuringReview !== false ? "on" : "off"}\nAuto-use Validation: ${s.standard.subagents?.autoUseDuringValidation !== false ? "on" : "off"}`);
|
|
14593
14755
|
}
|
|
14594
14756
|
}
|
|
14595
14757
|
}
|
|
@@ -14601,11 +14763,11 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14601
14763
|
if (!choice || choice === "Back") return;
|
|
14602
14764
|
if (choice === "Mission Planning Policy") {
|
|
14603
14765
|
const policy = parseSubagentPolicy((await ctx.ui.select("Mission planning policy", ["off", "auto", "deep", "maximum", "forced"])) ?? "");
|
|
14604
|
-
if (policy) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.subagentPolicy = policy; }); ctx
|
|
14766
|
+
if (policy) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.subagentPolicy = policy; }); workflowUiNotify(ctx, `missions.subagentPolicy set to ${policy} in ${r.file}`, "info"); }
|
|
14605
14767
|
} else {
|
|
14606
14768
|
const key = choice.includes("Deep") ? "minWorkersForDeep" : "minWorkersForMaximum";
|
|
14607
14769
|
const count = parsePositiveInt((await ctx.ui.select(choice, ["0", "1", "2", "3", "4", "5", "6", "7", "8"])) ?? "");
|
|
14608
|
-
if (count !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, number>)[key] = count; }); ctx
|
|
14770
|
+
if (count !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, number>)[key] = count; }); workflowUiNotify(ctx, `missions.${key} set to ${count} in ${r.file}. Forced mission planning uses Mission Planning Maximum / Forced Workers.`, "info"); }
|
|
14609
14771
|
}
|
|
14610
14772
|
}
|
|
14611
14773
|
}
|
|
@@ -14618,7 +14780,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14618
14780
|
const keyMap: Record<string, string> = { "Planning Auto-use": "autoUseDuringPlanning", "Execution Auto-use": "autoUseDuringExecution", "Repair Auto-use": "autoUseDuringRepair", "Review Auto-use": "autoUseDuringReview", "Validation Auto-use": "autoUseDuringValidation" };
|
|
14619
14781
|
const key = keyMap[choice];
|
|
14620
14782
|
const enabled = await chooseBool(ctx, `${key}?`);
|
|
14621
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.subagents as typeof s.subagents & Record<string, boolean>)[key] = enabled; }); ctx
|
|
14783
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.subagents as typeof s.subagents & Record<string, boolean>)[key] = enabled; }); workflowUiNotify(ctx, `subagents.${key} set to ${enabled} in ${r.file}`, "info"); }
|
|
14622
14784
|
}
|
|
14623
14785
|
}
|
|
14624
14786
|
|
|
@@ -14629,7 +14791,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14629
14791
|
if (!choice || choice === "Back") return;
|
|
14630
14792
|
if (choice === "Enable / Disable Sub-agents") {
|
|
14631
14793
|
const enabled = await chooseBool(ctx, "subagents.enabled?");
|
|
14632
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.enabled = enabled; }); ctx
|
|
14794
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.enabled = enabled; }); workflowUiNotify(ctx, `subagents.enabled set to ${enabled} in ${r.file}`, "info"); }
|
|
14633
14795
|
} else if (choice === "Planning Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Planning", "Shared Planning");
|
|
14634
14796
|
else if (choice === "Execution Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Execution", "Shared Execution");
|
|
14635
14797
|
else if (choice === "Repair Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Repair", "Shared Repair");
|
|
@@ -14639,10 +14801,10 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14639
14801
|
else if (choice === "Parallel Agent Settings") await showParallelismSettingsMenu(ctx);
|
|
14640
14802
|
else if (choice === "Background Sub-agents") {
|
|
14641
14803
|
const enabled = await chooseBool(ctx, "subagents.allowBackgroundSubagents?");
|
|
14642
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.allowBackgroundSubagents = enabled; }); ctx
|
|
14804
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.allowBackgroundSubagents = enabled; }); workflowUiNotify(ctx, `subagents.allowBackgroundSubagents set to ${enabled} in ${r.file}. Background sub-agents run in Planning/Review/Validation phases without blocking the parent.`, "info"); }
|
|
14643
14805
|
} else if (choice === "Activity Indicator") {
|
|
14644
14806
|
const enabled = await chooseBool(ctx, "subagents.activityIndicatorEnabled?");
|
|
14645
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.activityIndicatorEnabled = enabled; }); ctx
|
|
14807
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.activityIndicatorEnabled = enabled; }); workflowUiNotify(ctx, `subagents.activityIndicatorEnabled set to ${enabled} in ${r.file}`, "info"); renderWorkflowSubagentActivity(ctx); }
|
|
14646
14808
|
} else if (choice === "List Current Settings") {
|
|
14647
14809
|
const s = loadWorkflowSettings(ctx.cwd);
|
|
14648
14810
|
show(pi, `# Shared Sub-agents / Workers\n\nSub-agents: ${s.subagents.enabled !== false ? "enabled" : "disabled"}\nBackground Sub-agents: ${s.subagents.allowBackgroundSubagents === true ? "enabled" : "disabled"}\nActivity Indicator: ${s.subagents.activityIndicatorEnabled !== false ? "enabled" : "disabled"}\nAuto-use Planning: ${s.subagents.autoUseDuringPlanning !== false ? "on" : "off"}\nAuto-use Execution: ${s.subagents.autoUseDuringExecution !== false ? "on" : "off"}\nAuto-use Repair: ${s.subagents.autoUseDuringRepair !== false ? "on" : "off"}\nAuto-use Review: ${s.subagents.autoUseDuringReview !== false ? "on" : "off"}\nAuto-use Validation: ${s.subagents.autoUseDuringValidation !== false ? "on" : "off"}`);
|
|
@@ -14657,7 +14819,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14657
14819
|
if (!choice || choice === "Back") return;
|
|
14658
14820
|
if (choice === "Enable / Disable Sub-agents") {
|
|
14659
14821
|
const enabled = await chooseBool(ctx, "subagents.enabled?");
|
|
14660
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.enabled = enabled; }); ctx
|
|
14822
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.enabled = enabled; }); workflowUiNotify(ctx, `subagents.enabled set to ${enabled} in ${r.file}`, "info"); }
|
|
14661
14823
|
} else if (choice === "Plan Planning Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Planning", "Plan Planning");
|
|
14662
14824
|
else if (choice === "Plan Execution Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Execution", "Plan Execution");
|
|
14663
14825
|
else if (choice === "Plan Repair Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Repair", "Plan Repair");
|
|
@@ -14667,10 +14829,10 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14667
14829
|
else if (choice === "Parallel Agent Settings") await showParallelismSettingsMenu(ctx);
|
|
14668
14830
|
else if (choice === "Activity Indicator") {
|
|
14669
14831
|
const enabled = await chooseBool(ctx, "subagents.activityIndicatorEnabled?");
|
|
14670
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.activityIndicatorEnabled = enabled; }); ctx
|
|
14832
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.activityIndicatorEnabled = enabled; }); workflowUiNotify(ctx, `subagents.activityIndicatorEnabled set to ${enabled} in ${r.file}`, "info"); renderWorkflowSubagentActivity(ctx); }
|
|
14671
14833
|
} else if (choice === "List Current Settings") {
|
|
14672
14834
|
const s = loadWorkflowSettings(ctx.cwd);
|
|
14673
|
-
show(pi, `#
|
|
14835
|
+
show(pi, `# Plan Sub-agents / Workers\n\n${renderPlanSubagentWorkerSettings(s)}`);
|
|
14674
14836
|
}
|
|
14675
14837
|
}
|
|
14676
14838
|
}
|
|
@@ -14682,7 +14844,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14682
14844
|
if (!choice || choice === "Back") return;
|
|
14683
14845
|
if (choice === "Enable / Disable Sub-agents") {
|
|
14684
14846
|
const enabled = await chooseBool(ctx, "subagents.enabled?");
|
|
14685
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.enabled = enabled; }); ctx
|
|
14847
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.enabled = enabled; }); workflowUiNotify(ctx, `subagents.enabled set to ${enabled} in ${r.file}`, "info"); }
|
|
14686
14848
|
} else if (choice === "Mission Planning Policy / Workers") await showMissionPlanningSubagentSettingsMenu(ctx);
|
|
14687
14849
|
else if (choice === "Mission Execution Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Execution", "Mission Execution");
|
|
14688
14850
|
else if (choice === "Mission Repair Policy / Workers") await showSubagentPhaseSettingsMenu(ctx, "Repair", "Mission Repair");
|
|
@@ -14692,7 +14854,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14692
14854
|
else if (choice === "Parallel Agent Settings") await showParallelismSettingsMenu(ctx);
|
|
14693
14855
|
else if (choice === "Activity Indicator") {
|
|
14694
14856
|
const enabled = await chooseBool(ctx, "subagents.activityIndicatorEnabled?");
|
|
14695
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.activityIndicatorEnabled = enabled; }); ctx
|
|
14857
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.activityIndicatorEnabled = enabled; }); workflowUiNotify(ctx, `subagents.activityIndicatorEnabled set to ${enabled} in ${r.file}`, "info"); renderWorkflowSubagentActivity(ctx); }
|
|
14696
14858
|
} else if (choice === "List Current Settings") {
|
|
14697
14859
|
const s = loadWorkflowSettings(ctx.cwd);
|
|
14698
14860
|
show(pi, `# Mission Sub-agents / Workers\n\n${renderMissionSubagentWorkerSettings(s)}`);
|
|
@@ -14708,10 +14870,10 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14708
14870
|
if (choice?.startsWith("Set allow") || choice === "Set requireParallelEditConflictProtection") {
|
|
14709
14871
|
const key = choice.replace("Set ", "");
|
|
14710
14872
|
const enabled = await chooseBool(ctx, `${key}?`);
|
|
14711
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.subagents as typeof s.subagents & Record<string, boolean>)[key] = enabled; }); ctx
|
|
14873
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.subagents as typeof s.subagents & Record<string, boolean>)[key] = enabled; }); workflowUiNotify(ctx, `subagents.${key} set to ${enabled} in ${r.file}`, "info"); }
|
|
14712
14874
|
} else if (choice === "Set editConcurrencyMode") {
|
|
14713
14875
|
const mode = parseEditConcurrencyMode((await ctx.ui.select("Edit concurrency mode", ["sequential", "scoped", "blocked"])) ?? "");
|
|
14714
|
-
if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.editConcurrencyMode = mode; }); ctx
|
|
14876
|
+
if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.subagents.editConcurrencyMode = mode; }); workflowUiNotify(ctx, `subagents.editConcurrencyMode set to ${mode} in ${r.file}`, "info"); }
|
|
14715
14877
|
} else if (choice === "List Current Settings") {
|
|
14716
14878
|
const s = loadWorkflowSettings(ctx.cwd);
|
|
14717
14879
|
show(pi, `# Parallelism Settings\n\nParallel Read-Only: ${s.subagents.allowParallelReadOnly !== false ? "enabled" : "disabled"}\nParallel Planning: ${s.subagents.allowParallelPlanning !== false ? "enabled" : "disabled"}\nParallel Execution: ${s.subagents.allowParallelExecution !== false ? "enabled" : "disabled"}\nParallel Repair: ${s.subagents.allowParallelRepair !== false ? "enabled" : "disabled"}\nParallel Review: ${s.subagents.allowParallelReview !== false ? "enabled" : "disabled"}\nParallel Validation: ${s.subagents.allowParallelValidation !== false ? "enabled" : "disabled"}\nParallel File Edits: ${s.subagents.allowParallelEdits !== false ? "enabled" : "disabled"}\nEdit Concurrency Mode: ${s.subagents.editConcurrencyMode ?? "sequential"}\nConflict Protection: ${s.subagents.requireParallelEditConflictProtection !== false ? "enabled" : "disabled"}`);
|
|
@@ -14723,7 +14885,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14723
14885
|
const models = ctx.modelRegistry.getAll();
|
|
14724
14886
|
const providers = [...new Set(models.map((m) => m.provider))].sort();
|
|
14725
14887
|
if (providers.length === 0) {
|
|
14726
|
-
ctx
|
|
14888
|
+
workflowUiNotify(ctx, "No models are available in the model registry.", "error");
|
|
14727
14889
|
return undefined;
|
|
14728
14890
|
}
|
|
14729
14891
|
const providerChoice = await ctx.ui.select(`${title}: select provider`, [...providers, "Custom provider name"]);
|
|
@@ -14737,7 +14899,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14737
14899
|
}
|
|
14738
14900
|
const providerModels = models.filter((m) => m.provider === providerChoice).map((m) => m.id).sort();
|
|
14739
14901
|
if (providerModels.length === 0) {
|
|
14740
|
-
ctx
|
|
14902
|
+
workflowUiNotify(ctx, `No models found for provider ${providerChoice}.`, "error");
|
|
14741
14903
|
return undefined;
|
|
14742
14904
|
}
|
|
14743
14905
|
const modelChoice = await ctx.ui.select(`${title}: select model`, providerModels.map((model) => `${providerChoice}/${model}`));
|
|
@@ -14764,7 +14926,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14764
14926
|
s.context.compactionModelProvider = provider;
|
|
14765
14927
|
s.context.compactionModel = "";
|
|
14766
14928
|
});
|
|
14767
|
-
ctx
|
|
14929
|
+
workflowUiNotify(ctx, provider ? `Compaction provider preference stored as ${provider} in ${result.file}. Trigger behavior was not changed.` : `Compaction provider reset to Pi default in ${result.file}. Trigger behavior was not changed.`, "info");
|
|
14768
14930
|
}
|
|
14769
14931
|
|
|
14770
14932
|
async function selectCompactionModel(ctx: ExtensionContext) {
|
|
@@ -14777,7 +14939,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14777
14939
|
s.context.compactionModelProvider = "";
|
|
14778
14940
|
s.context.compactionModel = "";
|
|
14779
14941
|
});
|
|
14780
|
-
ctx
|
|
14942
|
+
workflowUiNotify(ctx, `Compaction summary model reset to Pi default in ${result.file}. Trigger behavior was not changed.`, "info");
|
|
14781
14943
|
return;
|
|
14782
14944
|
}
|
|
14783
14945
|
|
|
@@ -14788,7 +14950,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14788
14950
|
selectedProvider = chosen;
|
|
14789
14951
|
}
|
|
14790
14952
|
if (!selectedProvider) {
|
|
14791
|
-
ctx
|
|
14953
|
+
workflowUiNotify(ctx, "Select a custom compaction provider before selecting a custom model.", "warning");
|
|
14792
14954
|
return;
|
|
14793
14955
|
}
|
|
14794
14956
|
const providerModels = ctx.modelRegistry.getAll().filter((m) => m.provider === selectedProvider).map((m) => m.id).sort();
|
|
@@ -14800,7 +14962,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14800
14962
|
s.context.compactionModelProvider = selectedProvider;
|
|
14801
14963
|
s.context.compactionModel = model;
|
|
14802
14964
|
});
|
|
14803
|
-
ctx
|
|
14965
|
+
workflowUiNotify(ctx, `Compaction model preference stored as ${selectedProvider}/${model} in ${result.file}. Trigger behavior was not changed.`, "info");
|
|
14804
14966
|
}
|
|
14805
14967
|
|
|
14806
14968
|
async function selectCompactionAgent(ctx: ExtensionContext) {
|
|
@@ -14814,7 +14976,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14814
14976
|
s.context.compactionAgent = agent;
|
|
14815
14977
|
s.context.customCompactionEnabled = true;
|
|
14816
14978
|
});
|
|
14817
|
-
ctx
|
|
14979
|
+
workflowUiNotify(ctx, `Compaction agent stored as ${agent} in ${result.file}. Current releases keep Pi default fallback behavior for agent-routed compaction.`, "info");
|
|
14818
14980
|
}
|
|
14819
14981
|
|
|
14820
14982
|
async function showCompactionSettingsMenu(ctx: ExtensionContext) {
|
|
@@ -14833,53 +14995,53 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14833
14995
|
if (trigger === "Pi default") delete s.context.autoCompactionEnabled;
|
|
14834
14996
|
else s.context.autoCompactionEnabled = trigger === "Enabled";
|
|
14835
14997
|
});
|
|
14836
|
-
ctx
|
|
14998
|
+
workflowUiNotify(ctx, `Workflow auto trigger set to ${trigger.toLowerCase()} in ${r.file}.`, "info");
|
|
14837
14999
|
} else if (choice === "Workflow Trigger Percent") {
|
|
14838
15000
|
const mode = await ctx.ui.select("Workflow Trigger Percent", ["Pi default", "Custom percent", "Back"]);
|
|
14839
15001
|
if (!mode || mode === "Back") continue;
|
|
14840
15002
|
if (mode === "Pi default") {
|
|
14841
15003
|
const r = updateSettings(ctx.cwd, undefined, (s) => { delete s.context.compactionTriggerPercent; });
|
|
14842
|
-
ctx
|
|
15004
|
+
workflowUiNotify(ctx, `Workflow compaction trigger percent override removed in ${r.file}; Pi native trigger formula remains in control.`, "info");
|
|
14843
15005
|
} else {
|
|
14844
15006
|
const raw = String((await ctx.ui.input("Workflow compaction trigger percent (50-95)", String(compactionTriggerPercentOverride(loadWorkflowSettings(ctx.cwd)) ?? 85))) ?? "").trim();
|
|
14845
15007
|
const count = Number(raw);
|
|
14846
|
-
if (Number.isInteger(count) && count >= 50 && count <= 95) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.compactionTriggerPercent = count; }); ctx
|
|
14847
|
-
else ctx
|
|
15008
|
+
if (Number.isInteger(count) && count >= 50 && count <= 95) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.compactionTriggerPercent = count; }); workflowUiNotify(ctx, `Workflow compaction trigger percent set to ${count}% in ${r.file}`, "info"); }
|
|
15009
|
+
else workflowUiNotify(ctx, "Trigger percent must be an integer from 50 to 95.", "error");
|
|
14848
15010
|
}
|
|
14849
15011
|
} else if (choice === "Workflow Trigger Cooldown") {
|
|
14850
15012
|
const mode = await ctx.ui.select("Workflow Trigger Cooldown", ["Pi default", "Custom cooldown", "Back"]);
|
|
14851
15013
|
if (!mode || mode === "Back") continue;
|
|
14852
15014
|
if (mode === "Pi default") {
|
|
14853
15015
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.compactionCooldownMinutes = 5; });
|
|
14854
|
-
ctx
|
|
15016
|
+
workflowUiNotify(ctx, `Compaction cooldown reset to Pi default (5 minutes) in ${r.file}.`, "info");
|
|
14855
15017
|
} else {
|
|
14856
15018
|
const count = Number((await ctx.ui.input("Minimum minutes between Workflow Suite proactive compaction attempts", String(compactionCooldownMinutes(loadWorkflowSettings(ctx.cwd)))) ?? ""));
|
|
14857
|
-
if (Number.isInteger(count) && count >= 0 && count <= 240) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.compactionCooldownMinutes = count; }); ctx
|
|
14858
|
-
else ctx
|
|
15019
|
+
if (Number.isInteger(count) && count >= 0 && count <= 240) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.compactionCooldownMinutes = count; }); workflowUiNotify(ctx, `Compaction cooldown set to ${count} minute(s) in ${r.file}. This is the minimum wait between proactive compaction attempts, not a delay before compaction starts.`, "info"); }
|
|
15020
|
+
else workflowUiNotify(ctx, "Cooldown must be an integer from 0 to 240 minutes.", "error");
|
|
14859
15021
|
}
|
|
14860
15022
|
} else if (choice === "Custom Reserve Tokens") {
|
|
14861
15023
|
const mode = await ctx.ui.select("Custom Reserve Tokens", ["Pi default", "Custom reserve tokens", "Back"]);
|
|
14862
15024
|
if (!mode || mode === "Back") continue;
|
|
14863
15025
|
if (mode === "Pi default") {
|
|
14864
15026
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.customCompactionReserveTokens = DEFAULT_PI_COMPACTION_RESERVE_TOKENS; });
|
|
14865
|
-
ctx
|
|
15027
|
+
workflowUiNotify(ctx, `Custom compaction reserve tokens reset to Pi default (${DEFAULT_PI_COMPACTION_RESERVE_TOKENS.toLocaleString()}) in ${r.file}`, "info");
|
|
14866
15028
|
} else {
|
|
14867
15029
|
const raw = String((await ctx.ui.input("Custom compaction reserve tokens (4096-65536)", String(customCompactionReserveTokens(loadWorkflowSettings(ctx.cwd)))) ?? "")).trim();
|
|
14868
15030
|
const count = Number(raw);
|
|
14869
|
-
if (Number.isInteger(count) && count >= 4096 && count <= 65536) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.customCompactionReserveTokens = count; }); ctx
|
|
14870
|
-
else ctx
|
|
15031
|
+
if (Number.isInteger(count) && count >= 4096 && count <= 65536) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.customCompactionReserveTokens = count; }); workflowUiNotify(ctx, `Custom compaction reserve tokens set to ${count.toLocaleString()} in ${r.file}`, "info"); }
|
|
15032
|
+
else workflowUiNotify(ctx, "Reserve tokens must be an integer from 4096 to 65536.", "error");
|
|
14871
15033
|
}
|
|
14872
15034
|
} else if (choice === "Custom Keep Recent Tokens") {
|
|
14873
15035
|
const mode = await ctx.ui.select("Custom Keep Recent Tokens", ["Pi default", "Custom keep-recent tokens", "Back"]);
|
|
14874
15036
|
if (!mode || mode === "Back") continue;
|
|
14875
15037
|
if (mode === "Pi default") {
|
|
14876
15038
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.customCompactionKeepRecentTokens = DEFAULT_PI_COMPACTION_KEEP_RECENT_TOKENS; });
|
|
14877
|
-
ctx
|
|
15039
|
+
workflowUiNotify(ctx, `Custom compaction keep-recent tokens reset to Pi default (${DEFAULT_PI_COMPACTION_KEEP_RECENT_TOKENS.toLocaleString()}) in ${r.file}`, "info");
|
|
14878
15040
|
} else {
|
|
14879
15041
|
const raw = String((await ctx.ui.input("Custom compaction keep-recent tokens (1000-200000)", String(customCompactionKeepRecentTokens(loadWorkflowSettings(ctx.cwd)))) ?? "")).trim();
|
|
14880
15042
|
const count = Number(raw);
|
|
14881
|
-
if (Number.isInteger(count) && count >= 1000 && count <= 200000) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.customCompactionKeepRecentTokens = count; }); ctx
|
|
14882
|
-
else ctx
|
|
15043
|
+
if (Number.isInteger(count) && count >= 1000 && count <= 200000) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.customCompactionKeepRecentTokens = count; }); workflowUiNotify(ctx, `Custom compaction keep-recent tokens set to ${count.toLocaleString()} in ${r.file}`, "info"); }
|
|
15044
|
+
else workflowUiNotify(ctx, "Keep-recent tokens must be an integer from 1000 to 200000.", "error");
|
|
14883
15045
|
}
|
|
14884
15046
|
} else if (choice === "List Current Settings") {
|
|
14885
15047
|
const s = loadWorkflowSettings(ctx.cwd);
|
|
@@ -14930,7 +15092,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14930
15092
|
}
|
|
14931
15093
|
});
|
|
14932
15094
|
await reapplyStandardRouteIfStandardMode(ctx, true);
|
|
14933
|
-
ctx
|
|
15095
|
+
workflowUiNotify(ctx, `Standard model source set to ${source} in ${result.file}`, "info");
|
|
14934
15096
|
} else if (choice === "Standard Model Role") {
|
|
14935
15097
|
const role = parseStandardModelRole((await ctx.ui.select("Standard model role", ["Current Pi model", "Planner", "Executor", "Reviewer", "Validator"])) ?? "");
|
|
14936
15098
|
if (!role) continue;
|
|
@@ -14944,7 +15106,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14944
15106
|
}
|
|
14945
15107
|
});
|
|
14946
15108
|
await reapplyStandardRouteIfStandardMode(ctx, true);
|
|
14947
|
-
ctx
|
|
15109
|
+
workflowUiNotify(ctx, `Standard model role set to ${workflowRoleLabel(role)} in ${result.file}`, "info");
|
|
14948
15110
|
} else if (choice === "Configure Standard Planner") await configureStandardRoleModel(ctx, "planner");
|
|
14949
15111
|
else if (choice === "Configure Standard Executor") await configureStandardRoleModel(ctx, "executor");
|
|
14950
15112
|
else if (choice === "Configure Standard Reviewer") await configureStandardRoleModel(ctx, "reviewer");
|
|
@@ -14965,10 +15127,10 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14965
15127
|
const options = key === "maxValidationRetriesPerPlan" ? ["0", "1", "2", "3", "4", "5", "10"] : ["0", "1", "2", "4", "8", "12", "20", "50", "100"];
|
|
14966
15128
|
const raw = await ctx.ui.select(setting, options);
|
|
14967
15129
|
const count = raw === undefined ? undefined : Number(raw);
|
|
14968
|
-
if (Number.isInteger(count) && count >= 0 && count <= max) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.workflow as typeof s.workflow & Record<string, number>)[key] = count; }); ctx
|
|
15130
|
+
if (Number.isInteger(count) && count >= 0 && count <= max) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.workflow as typeof s.workflow & Record<string, number>)[key] = count; }); workflowUiNotify(ctx, `workflow.${key} set to ${count} in ${r.file}`, "info"); }
|
|
14969
15131
|
} else if (setting === "Validation Retry Mode") {
|
|
14970
15132
|
const mode = parseValidationRetryMode((await ctx.ui.select("Validation retry mode", ["off", "safe_only", "aggressive_within_scope"])) ?? "");
|
|
14971
|
-
if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.validationRetryMode = mode; }); ctx
|
|
15133
|
+
if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.validationRetryMode = mode; }); workflowUiNotify(ctx, `workflow.validationRetryMode set to ${mode} in ${r.file}`, "info"); }
|
|
14972
15134
|
} else {
|
|
14973
15135
|
const keyMap: Record<string, keyof ReturnType<typeof loadWorkflowSettings>["workflow"]> = {
|
|
14974
15136
|
"Auto Repair Validation Failures": "autoRepairValidationFailures",
|
|
@@ -14978,7 +15140,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14978
15140
|
};
|
|
14979
15141
|
const key = keyMap[setting];
|
|
14980
15142
|
const enabled = await chooseBool(ctx, `${String(key)}?`);
|
|
14981
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.workflow as Record<string, unknown>)[String(key)] = enabled; }); ctx
|
|
15143
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.workflow as Record<string, unknown>)[String(key)] = enabled; }); workflowUiNotify(ctx, `workflow.${String(key)} set to ${enabled} in ${r.file}`, "info"); }
|
|
14982
15144
|
}
|
|
14983
15145
|
}
|
|
14984
15146
|
}
|
|
@@ -14992,26 +15154,26 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14992
15154
|
await showModelSettingsMenu(ctx);
|
|
14993
15155
|
} else if (choice === "Planning Depth") {
|
|
14994
15156
|
const depth = parsePlanningDepth((await ctx.ui.select("Planning depth", ["fast", "standard", "deep", "maximum"])) ?? "");
|
|
14995
|
-
if (depth) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.depth = depth; }); ctx
|
|
15157
|
+
if (depth) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.depth = depth; }); workflowUiNotify(ctx, `planning.depth set to ${depth} in ${r.file}`, "info"); }
|
|
14996
15158
|
} else if (choice === "Plan Clarification") {
|
|
14997
15159
|
const setting = await ctx.ui.select("Plan Clarification", ["Clarification Mode", "Interactive Clarification", "Max Clarification Questions", "Timing", "Quality Gate", "Allow Without Analysis", "Use Sub-agents Before Clarification", "Back"]);
|
|
14998
15160
|
if (!setting || setting === "Back") continue;
|
|
14999
15161
|
if (setting === "Clarification Mode") {
|
|
15000
15162
|
const mode = parseClarificationMode((await ctx.ui.select("Plan clarification mode", ["auto", "always_for_nontrivial", "never"])) ?? "");
|
|
15001
|
-
if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.clarificationMode = mode; }); ctx
|
|
15163
|
+
if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.clarificationMode = mode; }); workflowUiNotify(ctx, `planning.clarificationMode set to ${mode} in ${r.file}`, "info"); }
|
|
15002
15164
|
} else if (setting === "Interactive Clarification") {
|
|
15003
15165
|
const enabled = await chooseBool(ctx, "Interactive clarification enabled?");
|
|
15004
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.interactiveClarificationEnabled = enabled; }); ctx
|
|
15166
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.interactiveClarificationEnabled = enabled; }); workflowUiNotify(ctx, `planning.interactiveClarificationEnabled set to ${enabled} in ${r.file}`, "info"); }
|
|
15005
15167
|
} else if (setting === "Max Clarification Questions") {
|
|
15006
15168
|
const count = parsePositiveInt((await ctx.ui.select("Max clarification questions", ["1", "2", "3", "4", "5"])) ?? "");
|
|
15007
|
-
if (count) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxClarificationQuestions = count; }); ctx
|
|
15169
|
+
if (count) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxClarificationQuestions = count; }); workflowUiNotify(ctx, `planning.maxClarificationQuestions set to ${count} in ${r.file}`, "info"); }
|
|
15008
15170
|
} else if (setting === "Timing") {
|
|
15009
15171
|
const timing = parseClarificationTiming((await ctx.ui.select("Plan clarification timing", ["after_initial_analysis", "immediate"])) ?? "");
|
|
15010
|
-
if (timing) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.clarificationTiming = timing; }); ctx
|
|
15172
|
+
if (timing) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.clarificationTiming = timing; }); workflowUiNotify(ctx, `planning.clarificationTiming set to ${timing} in ${r.file}`, "info"); }
|
|
15011
15173
|
} else {
|
|
15012
15174
|
const key = setting === "Quality Gate" ? "clarificationQualityGate" : setting === "Allow Without Analysis" ? "allowClarificationWithoutAnalysis" : "useSubagentsBeforeClarification";
|
|
15013
15175
|
const enabled = await chooseBool(ctx, `planning.${key}?`);
|
|
15014
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.planning as typeof s.planning & Record<string, boolean | string | number | undefined>)[key] = enabled; }); ctx
|
|
15176
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.planning as typeof s.planning & Record<string, boolean | string | number | undefined>)[key] = enabled; }); workflowUiNotify(ctx, `planning.${key} set to ${enabled} in ${r.file}`, "info"); }
|
|
15015
15177
|
}
|
|
15016
15178
|
} else if (choice === "Plan Sub-agents / Workers") {
|
|
15017
15179
|
await showPlanSubagentWorkerSettingsMenu(ctx);
|
|
@@ -15020,16 +15182,16 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15020
15182
|
if (!setting || setting === "Back") continue;
|
|
15021
15183
|
const enabled = await chooseBool(ctx, `${setting}?`);
|
|
15022
15184
|
if (enabled === undefined) continue;
|
|
15023
|
-
if (setting === "Reviewer Enabled") { const r = setRoleEnabled("reviewer", enabled, ctx.cwd); ctx
|
|
15024
|
-
else if (setting === "Validator Enabled") { const r = setRoleEnabled("validator", enabled, ctx.cwd); ctx
|
|
15025
|
-
else if (setting === "Auto Run Reviewer") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.autoRunReviewerBeforeExecute = enabled; }); ctx
|
|
15026
|
-
else if (setting === "Auto Run Validation") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.autoRunValidationAfterExecute = enabled; }); ctx
|
|
15027
|
-
else if (setting === "Auto Repair Review Failures") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.autoRepairReviewFailures = enabled; }); ctx
|
|
15028
|
-
else if (setting === "Pause After Review Failure") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.pauseAfterReviewFailure = enabled; }); ctx
|
|
15029
|
-
else if (setting === "Approval Before Execution") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.requireApprovalBeforeExecution = enabled; s.workflow.requirePlanApprovalBeforeExecute = enabled; }); ctx
|
|
15030
|
-
else if (setting === "Approval Per Step") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.requireApprovalPerStep = enabled; }); ctx
|
|
15031
|
-
else if (setting === "Validate After Each Step") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.validateAfterEachStep = enabled; }); ctx
|
|
15032
|
-
else if (setting === "Validate After Full Execution") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.validateAfterExecution = enabled; s.workflow.autoRunValidationAfterExecute = enabled; }); ctx
|
|
15185
|
+
if (setting === "Reviewer Enabled") { const r = setRoleEnabled("reviewer", enabled, ctx.cwd); workflowUiNotify(ctx, `reviewer.enabled set to ${enabled} in ${r.file}`, "info"); }
|
|
15186
|
+
else if (setting === "Validator Enabled") { const r = setRoleEnabled("validator", enabled, ctx.cwd); workflowUiNotify(ctx, `validator.enabled set to ${enabled} in ${r.file}`, "info"); }
|
|
15187
|
+
else if (setting === "Auto Run Reviewer") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.autoRunReviewerBeforeExecute = enabled; }); workflowUiNotify(ctx, `workflow.autoRunReviewerBeforeExecute set to ${enabled} in ${r.file}`, "info"); }
|
|
15188
|
+
else if (setting === "Auto Run Validation") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.autoRunValidationAfterExecute = enabled; }); workflowUiNotify(ctx, `workflow.autoRunValidationAfterExecute set to ${enabled} in ${r.file}`, "info"); }
|
|
15189
|
+
else if (setting === "Auto Repair Review Failures") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.autoRepairReviewFailures = enabled; }); workflowUiNotify(ctx, `workflow.autoRepairReviewFailures set to ${enabled} in ${r.file}`, "info"); }
|
|
15190
|
+
else if (setting === "Pause After Review Failure") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.pauseAfterReviewFailure = enabled; }); workflowUiNotify(ctx, `workflow.pauseAfterReviewFailure set to ${enabled} in ${r.file}`, "info"); }
|
|
15191
|
+
else if (setting === "Approval Before Execution") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.requireApprovalBeforeExecution = enabled; s.workflow.requirePlanApprovalBeforeExecute = enabled; }); workflowUiNotify(ctx, `workflow.requireApprovalBeforeExecution set to ${enabled} in ${r.file}`, "info"); }
|
|
15192
|
+
else if (setting === "Approval Per Step") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.requireApprovalPerStep = enabled; }); workflowUiNotify(ctx, `workflow.requireApprovalPerStep set to ${enabled} in ${r.file}`, "info"); }
|
|
15193
|
+
else if (setting === "Validate After Each Step") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.validateAfterEachStep = enabled; }); workflowUiNotify(ctx, `workflow.validateAfterEachStep set to ${enabled} in ${r.file}`, "info"); }
|
|
15194
|
+
else if (setting === "Validate After Full Execution") { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.validateAfterExecution = enabled; s.workflow.autoRunValidationAfterExecute = enabled; }); workflowUiNotify(ctx, `workflow.validateAfterExecution set to ${enabled} in ${r.file}`, "info"); }
|
|
15033
15195
|
} else if (choice === "Repair / Validation Retry") {
|
|
15034
15196
|
await showWorkflowRepairRetrySettingsMenu(ctx);
|
|
15035
15197
|
} else if (choice === "Plan Progress / Runtime") {
|
|
@@ -15045,28 +15207,28 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15045
15207
|
const choice = await ctx.ui.select("Plan Token Budget", ["Default (unlimited)", "Custom..."]);
|
|
15046
15208
|
if (choice === "Default (unlimited)") {
|
|
15047
15209
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxTokens = 0; });
|
|
15048
|
-
ctx
|
|
15210
|
+
workflowUiNotify(ctx, `planning.maxTokens set to default (unlimited) in ${r.file}`, "info");
|
|
15049
15211
|
} else if (choice === "Custom...") {
|
|
15050
15212
|
const count = parsePositiveInt((await ctx.ui.input("Enter custom plan token budget", String(current > 0 ? current : ""))) ?? "");
|
|
15051
|
-
if (count !== undefined && count >= 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxTokens = count; }); ctx
|
|
15213
|
+
if (count !== undefined && count >= 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxTokens = count; }); workflowUiNotify(ctx, `planning.maxTokens set to ${count === 0 ? "unlimited" : count.toLocaleString()} in ${r.file}`, "info"); }
|
|
15052
15214
|
}
|
|
15053
15215
|
} else if (setting === "Runtime Budget") {
|
|
15054
15216
|
const current = loadWorkflowSettings(ctx.cwd).planning.maxRuntimeHours ?? 0;
|
|
15055
15217
|
const choice = await ctx.ui.select("Plan Runtime Budget", ["Default (unlimited)", "Custom..."]);
|
|
15056
15218
|
if (choice === "Default (unlimited)") {
|
|
15057
15219
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxRuntimeHours = 0; });
|
|
15058
|
-
ctx
|
|
15220
|
+
workflowUiNotify(ctx, `planning.maxRuntimeHours set to default (unlimited) in ${r.file}`, "info");
|
|
15059
15221
|
} else if (choice === "Custom...") {
|
|
15060
15222
|
const count = parsePositiveInt((await ctx.ui.input("Enter custom plan runtime budget (hours)", String(current > 0 ? current : ""))) ?? "");
|
|
15061
|
-
if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxRuntimeHours = count; }); ctx
|
|
15223
|
+
if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.planning.maxRuntimeHours = count; }); workflowUiNotify(ctx, `planning.maxRuntimeHours set to ${count} hours in ${r.file}`, "info"); }
|
|
15062
15224
|
}
|
|
15063
15225
|
} else if (setting === "Progress Bar Display") {
|
|
15064
15226
|
const enabled = await chooseBool(ctx, "workflow.planShowProgressBar?");
|
|
15065
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.planShowProgressBar = enabled; }); ctx
|
|
15227
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.planShowProgressBar = enabled; }); workflowUiNotify(ctx, `workflow.planShowProgressBar set to ${enabled} in ${r.file}`, "info"); }
|
|
15066
15228
|
} else {
|
|
15067
15229
|
const key = setting === "Progress Tracking" ? "planProgressEnabled" : "planRuntimeEnabled";
|
|
15068
15230
|
const enabled = await chooseBool(ctx, `workflow.${key}?`);
|
|
15069
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.workflow as typeof s.workflow & Record<string, boolean>)[key] = enabled; }); ctx
|
|
15231
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.workflow as typeof s.workflow & Record<string, boolean>)[key] = enabled; }); workflowUiNotify(ctx, `workflow.${key} set to ${enabled} in ${r.file}`, "info"); }
|
|
15070
15232
|
}
|
|
15071
15233
|
} else if (choice === "Plan History") {
|
|
15072
15234
|
const setting = await ctx.ui.select("Plan History", ["Save Plans", "Save Plan History", "Plan History Limit", "Back"]);
|
|
@@ -15074,11 +15236,11 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15074
15236
|
if (!setting || setting === "Back") continue;
|
|
15075
15237
|
if (setting === "Plan History Limit") {
|
|
15076
15238
|
const count = parsePositiveInt((await ctx.ui.input("Plan history limit", String(workflow.planHistoryLimit ?? 50))) ?? "");
|
|
15077
|
-
if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.planHistoryLimit = count; }); ctx
|
|
15239
|
+
if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.workflow.planHistoryLimit = count; }); workflowUiNotify(ctx, `workflow.planHistoryLimit set to ${count} in ${r.file}`, "info"); }
|
|
15078
15240
|
} else {
|
|
15079
15241
|
const key = setting === "Save Plans" ? "savePlans" : "savePlanHistory";
|
|
15080
15242
|
const enabled = await chooseBool(ctx, `${key}?`);
|
|
15081
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.workflow as typeof s.workflow & Record<string, boolean>)[key] = enabled; }); ctx
|
|
15243
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.workflow as typeof s.workflow & Record<string, boolean>)[key] = enabled; }); workflowUiNotify(ctx, `workflow.${key} set to ${enabled} in ${r.file}`, "info"); }
|
|
15082
15244
|
}
|
|
15083
15245
|
} else if (choice === "List Current Settings") {
|
|
15084
15246
|
const s = loadWorkflowSettings(ctx.cwd);
|
|
@@ -15094,11 +15256,11 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15094
15256
|
if (!setting || setting === "Back") return;
|
|
15095
15257
|
if (setting === "To Do Trigger Mode") {
|
|
15096
15258
|
const mode = parseStandardTodoTriggerMode((await ctx.ui.select("To Do Trigger Mode", ["Disabled", "On request", "Automatic when useful", "Required"])) ?? "");
|
|
15097
|
-
if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.todoTriggerMode = mode; s.standard.autoTodoEnabled = mode !== "off"; }); ctx
|
|
15259
|
+
if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.todoTriggerMode = mode; s.standard.autoTodoEnabled = mode !== "off"; }); workflowUiNotify(ctx, `To Do Trigger Mode set to ${standardTodoTriggerModeLabel(mode)} in ${r.file}`, "info"); }
|
|
15098
15260
|
} else {
|
|
15099
15261
|
const key = setting === "Automatic To Do Enabled" ? "autoTodoEnabled" : "todoProgressVisible";
|
|
15100
15262
|
const enabled = await chooseBool(ctx, `standard.${key}?`);
|
|
15101
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.standard as typeof s.standard & Record<string, boolean>)[key] = enabled; }); ctx
|
|
15263
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.standard as typeof s.standard & Record<string, boolean>)[key] = enabled; }); workflowUiNotify(ctx, `standard.${key} set to ${enabled} in ${r.file}`, "info"); }
|
|
15102
15264
|
}
|
|
15103
15265
|
}
|
|
15104
15266
|
}
|
|
@@ -15110,20 +15272,20 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15110
15272
|
if (!setting || setting === "Back") return;
|
|
15111
15273
|
if (setting === "Clarification Mode") {
|
|
15112
15274
|
const mode = parseStandardClarificationMode((await ctx.ui.select("Standard clarification mode", ["auto", "always_for_nontrivial", "never"])) ?? "");
|
|
15113
|
-
if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.clarificationMode = mode; s.standard.clarificationEnabled = mode !== "never"; }); ctx
|
|
15275
|
+
if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.clarificationMode = mode; s.standard.clarificationEnabled = mode !== "never"; }); workflowUiNotify(ctx, `standard.clarificationMode set to ${mode} in ${r.file}`, "info"); }
|
|
15114
15276
|
} else if (setting === "Interactive Clarification") {
|
|
15115
15277
|
const enabled = await chooseBool(ctx, "Standard interactive clarification enabled?");
|
|
15116
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.interactiveClarificationEnabled = enabled; }); ctx
|
|
15278
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.interactiveClarificationEnabled = enabled; }); workflowUiNotify(ctx, `standard.interactiveClarificationEnabled set to ${enabled} in ${r.file}`, "info"); }
|
|
15117
15279
|
} else if (setting === "Max Clarification Questions") {
|
|
15118
15280
|
const count = parsePositiveInt((await ctx.ui.select("Max Standard clarification questions", ["0", "1", "2"])) ?? "");
|
|
15119
|
-
if (count !== undefined && count >= 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.maxClarificationQuestions = count; }); ctx
|
|
15281
|
+
if (count !== undefined && count >= 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.maxClarificationQuestions = count; }); workflowUiNotify(ctx, `standard.maxClarificationQuestions set to ${count} in ${r.file}`, "info"); }
|
|
15120
15282
|
} else if (setting === "Timing") {
|
|
15121
15283
|
const timing = parseClarificationTiming((await ctx.ui.select("Standard clarification timing", ["after_initial_analysis", "immediate"])) ?? "");
|
|
15122
|
-
if (timing) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.clarificationTiming = timing; }); ctx
|
|
15284
|
+
if (timing) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.clarificationTiming = timing; }); workflowUiNotify(ctx, `standard.clarificationTiming set to ${timing} in ${r.file}`, "info"); }
|
|
15123
15285
|
} else {
|
|
15124
15286
|
const key = setting === "Quality Gate" ? "clarificationQualityGate" : setting === "Allow Without Analysis" ? "allowClarificationWithoutAnalysis" : "useSubagentsBeforeClarification";
|
|
15125
15287
|
const enabled = await chooseBool(ctx, `standard.${key}?`);
|
|
15126
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.standard as typeof s.standard & Record<string, boolean | string | number | undefined>)[key] = enabled; }); ctx
|
|
15288
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.standard as typeof s.standard & Record<string, boolean | string | number | undefined>)[key] = enabled; }); workflowUiNotify(ctx, `standard.${key} set to ${enabled} in ${r.file}`, "info"); }
|
|
15127
15289
|
}
|
|
15128
15290
|
}
|
|
15129
15291
|
}
|
|
@@ -15143,15 +15305,15 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15143
15305
|
const choice = await ctx.ui.select("Standard Token Budget", ["Default (unlimited)", "Custom..."]);
|
|
15144
15306
|
if (choice === "Default (unlimited)") {
|
|
15145
15307
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.maxTokens = 0; });
|
|
15146
|
-
ctx
|
|
15308
|
+
workflowUiNotify(ctx, `standard.maxTokens set to default (unlimited) in ${r.file}`, "info");
|
|
15147
15309
|
} else if (choice === "Custom...") {
|
|
15148
15310
|
const count = parsePositiveInt((await ctx.ui.input("Enter custom standard token budget", String(current > 0 ? current : ""))) ?? "");
|
|
15149
|
-
if (count !== undefined && count >= 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.maxTokens = count; }); ctx
|
|
15311
|
+
if (count !== undefined && count >= 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.maxTokens = count; }); workflowUiNotify(ctx, `standard.maxTokens set to ${count === 0 ? "unlimited" : count.toLocaleString()} in ${r.file}`, "info"); }
|
|
15150
15312
|
}
|
|
15151
15313
|
} else {
|
|
15152
15314
|
const key = setting === "Status Widget Visible" ? "statusWidgetVisible" : "todoProgressVisible";
|
|
15153
15315
|
const enabled = await chooseBool(ctx, `standard.${key}?`);
|
|
15154
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.standard as typeof s.standard & Record<string, boolean>)[key] = enabled; }); ctx
|
|
15316
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.standard as typeof s.standard & Record<string, boolean>)[key] = enabled; }); workflowUiNotify(ctx, `standard.${key} set to ${enabled} in ${r.file}`, "info"); }
|
|
15155
15317
|
}
|
|
15156
15318
|
}
|
|
15157
15319
|
}
|
|
@@ -15168,7 +15330,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15168
15330
|
}
|
|
15169
15331
|
if (choice === "Enable / Disable Standard Mode") {
|
|
15170
15332
|
const enabled = await chooseBool(ctx, "standard.enabled?");
|
|
15171
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.enabled = enabled; }); ctx
|
|
15333
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.standard.enabled = enabled; }); workflowUiNotify(ctx, `standard.enabled set to ${enabled} in ${r.file}`, "info"); }
|
|
15172
15334
|
} else if (choice === "Standard To Do" || choice === "To Do Behavior") {
|
|
15173
15335
|
await showStandardTodoSettingsMenu(ctx);
|
|
15174
15336
|
} else if (choice === "Standard Clarification" || choice === "Clarification") {
|
|
@@ -15197,7 +15359,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15197
15359
|
if (!source) continue;
|
|
15198
15360
|
const enabled = source === "Mission-Specific Models";
|
|
15199
15361
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.useMissionSpecificModels = enabled; });
|
|
15200
|
-
ctx
|
|
15362
|
+
workflowUiNotify(ctx, `missions.useMissionSpecificModels set to ${enabled} in ${r.file}`, "info");
|
|
15201
15363
|
} else if (choice === "Configure Mission Planner") await configureMissionRoleModel(ctx, "planner");
|
|
15202
15364
|
else if (choice === "Configure Mission Executor") await configureMissionRoleModel(ctx, "executor");
|
|
15203
15365
|
else if (choice === "Configure Mission Reviewer") await configureMissionRoleModel(ctx, "reviewer");
|
|
@@ -15218,13 +15380,13 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15218
15380
|
show(pi, renderHeartbeatWatchdogStatus(loadWorkflowSettings(ctx.cwd), activeMission ?? loadMissionState()));
|
|
15219
15381
|
} else if (choice === "Enable / Disable Heartbeat") {
|
|
15220
15382
|
const enabled = await chooseBool(ctx, "missions.heartbeatEnabled?");
|
|
15221
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.heartbeatEnabled = enabled; }); ctx
|
|
15383
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.heartbeatEnabled = enabled; }); workflowUiNotify(ctx, `missions.heartbeatEnabled set to ${enabled} in ${r.file}`, "info"); }
|
|
15222
15384
|
} else if (choice === "Enable / Disable Watchdog") {
|
|
15223
15385
|
const enabled = await chooseBool(ctx, "missions.watchdogEnabled? (warning only; no auto-recovery)");
|
|
15224
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.watchdogEnabled = enabled; }); ctx
|
|
15386
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.watchdogEnabled = enabled; }); workflowUiNotify(ctx, `missions.watchdogEnabled set to ${enabled} in ${r.file}`, "info"); }
|
|
15225
15387
|
} else if (choice === "Set Watchdog Stale Minutes") {
|
|
15226
15388
|
const count = parsePositiveInt((await ctx.ui.input("watchdogStaleMinutes", String(loadWorkflowSettings(ctx.cwd).missions.watchdogStaleMinutes ?? 30))) ?? "");
|
|
15227
|
-
if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.watchdogStaleMinutes = count; }); ctx
|
|
15389
|
+
if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.watchdogStaleMinutes = count; }); workflowUiNotify(ctx, `missions.watchdogStaleMinutes set to ${count} in ${r.file}`, "info"); }
|
|
15228
15390
|
}
|
|
15229
15391
|
}
|
|
15230
15392
|
}
|
|
@@ -15237,11 +15399,11 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15237
15399
|
const enabled = await chooseBool(ctx, `${setting}?`);
|
|
15238
15400
|
if (enabled === undefined) continue;
|
|
15239
15401
|
if (setting === "Mission Reviewer Enabled") {
|
|
15240
|
-
if (loadWorkflowSettings(ctx.cwd).missions.useMissionSpecificModels) { const r = updateSettings(ctx.cwd, undefined, (s) => { setMissionRoleEnabled(s, "reviewer", enabled); }); ctx
|
|
15241
|
-
else { const r = setRoleEnabled("reviewer", enabled, ctx.cwd); ctx
|
|
15402
|
+
if (loadWorkflowSettings(ctx.cwd).missions.useMissionSpecificModels) { const r = updateSettings(ctx.cwd, undefined, (s) => { setMissionRoleEnabled(s, "reviewer", enabled); }); workflowUiNotify(ctx, `missions.models.reviewer.enabled set to ${enabled} in ${r.file}`, "info"); }
|
|
15403
|
+
else { const r = setRoleEnabled("reviewer", enabled, ctx.cwd); workflowUiNotify(ctx, `reviewer.enabled set to ${enabled} in ${r.file}`, "info"); }
|
|
15242
15404
|
} else if (setting === "Mission Validator Enabled") {
|
|
15243
|
-
if (loadWorkflowSettings(ctx.cwd).missions.useMissionSpecificModels) { const r = updateSettings(ctx.cwd, undefined, (s) => { setMissionRoleEnabled(s, "validator", enabled); }); ctx
|
|
15244
|
-
else { const r = setRoleEnabled("validator", enabled, ctx.cwd); ctx
|
|
15405
|
+
if (loadWorkflowSettings(ctx.cwd).missions.useMissionSpecificModels) { const r = updateSettings(ctx.cwd, undefined, (s) => { setMissionRoleEnabled(s, "validator", enabled); }); workflowUiNotify(ctx, `missions.models.validator.enabled set to ${enabled} in ${r.file}`, "info"); }
|
|
15406
|
+
else { const r = setRoleEnabled("validator", enabled, ctx.cwd); workflowUiNotify(ctx, `validator.enabled set to ${enabled} in ${r.file}`, "info"); }
|
|
15245
15407
|
} else {
|
|
15246
15408
|
const keyMap: Record<string, string> = {
|
|
15247
15409
|
"Offer Reviewer Before Approval": "offerReviewerBeforeApprove",
|
|
@@ -15259,7 +15421,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15259
15421
|
s.missions.reviewRetryMode = "safe_only";
|
|
15260
15422
|
}
|
|
15261
15423
|
});
|
|
15262
|
-
ctx
|
|
15424
|
+
workflowUiNotify(ctx, `missions.${key} set to ${enabled} in ${r.file}`, "info");
|
|
15263
15425
|
}
|
|
15264
15426
|
}
|
|
15265
15427
|
}
|
|
@@ -15272,18 +15434,18 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15272
15434
|
if (setting === "Max Review Retries Per Mission") {
|
|
15273
15435
|
const raw = await ctx.ui.select(setting, ["0", "1", "2", "3", "4", "5", "10"]);
|
|
15274
15436
|
const count = raw === undefined ? undefined : Number(raw);
|
|
15275
|
-
if (Number.isInteger(count) && count >= 0 && count <= 10) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxReviewRetriesPerMission = count; }); ctx
|
|
15437
|
+
if (Number.isInteger(count) && count >= 0 && count <= 10) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxReviewRetriesPerMission = count; }); workflowUiNotify(ctx, `missions.maxReviewRetriesPerMission set to ${count} in ${r.file}`, "info"); }
|
|
15276
15438
|
} else if (setting === "Max Retries Per Milestone" || setting === "Max Retries Per Mission" || setting === "Max Final Validation Retries") {
|
|
15277
15439
|
const key = setting === "Max Retries Per Milestone" ? "maxValidationRetriesPerMilestone" : setting === "Max Retries Per Mission" ? "maxValidationRetriesPerMission" : "maxFinalValidationRetries";
|
|
15278
15440
|
const max = key === "maxValidationRetriesPerMission" ? 100 : 10;
|
|
15279
15441
|
const options = key === "maxValidationRetriesPerMission" ? ["0", "1", "2", "4", "8", "12", "20", "50", "100"] : ["0", "1", "2", "3", "4", "5", "10"];
|
|
15280
15442
|
const raw = await ctx.ui.select(setting, options);
|
|
15281
15443
|
const count = raw === undefined ? undefined : Number(raw);
|
|
15282
|
-
if (Number.isInteger(count) && count >= 0 && count <= max) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, number>)[key] = count; }); ctx
|
|
15444
|
+
if (Number.isInteger(count) && count >= 0 && count <= max) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, number>)[key] = count; }); workflowUiNotify(ctx, `missions.${key} set to ${count} in ${r.file}`, "info"); }
|
|
15283
15445
|
} else if (setting === "Validation Retry Mode" || setting === "Review Retry Mode") {
|
|
15284
15446
|
const key = setting === "Validation Retry Mode" ? "validationRetryMode" : "reviewRetryMode";
|
|
15285
15447
|
const mode = parseValidationRetryMode((await ctx.ui.select(`${key}`, ["off", "safe_only", "aggressive_within_scope"])) ?? "");
|
|
15286
|
-
if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, string | undefined>)[key] = mode; }); ctx
|
|
15448
|
+
if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, string | undefined>)[key] = mode; }); workflowUiNotify(ctx, `missions.${key} set to ${mode} in ${r.file}`, "info"); }
|
|
15287
15449
|
} else {
|
|
15288
15450
|
const keyMap: Record<string, string> = {
|
|
15289
15451
|
"Auto Repair Review Failures": "autoRepairReviewFailures",
|
|
@@ -15296,7 +15458,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15296
15458
|
};
|
|
15297
15459
|
const key = keyMap[setting];
|
|
15298
15460
|
const enabled = await chooseBool(ctx, `${String(key)}?`);
|
|
15299
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as Record<string, unknown>)[String(key)] = enabled; if (key === "autoRepairReviewFailures" && enabled && s.missions.reviewRetryMode === "off") { s.missions.reviewRetryMode = "safe_only"; } }); ctx
|
|
15461
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as Record<string, unknown>)[String(key)] = enabled; if (key === "autoRepairReviewFailures" && enabled && s.missions.reviewRetryMode === "off") { s.missions.reviewRetryMode = "safe_only"; } }); workflowUiNotify(ctx, `missions.${String(key)} set to ${enabled} in ${r.file}`, "info"); }
|
|
15300
15462
|
}
|
|
15301
15463
|
}
|
|
15302
15464
|
}
|
|
@@ -15309,12 +15471,12 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15309
15471
|
if (setting === "Max Final Validation Retries") {
|
|
15310
15472
|
const raw = await ctx.ui.select(setting, ["0", "1", "2", "3", "4", "5", "10"]);
|
|
15311
15473
|
const count = raw === undefined ? undefined : Number(raw);
|
|
15312
|
-
if (Number.isInteger(count) && count >= 0 && count <= 10) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxFinalValidationRetries = count; }); ctx
|
|
15474
|
+
if (Number.isInteger(count) && count >= 0 && count <= 10) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxFinalValidationRetries = count; }); workflowUiNotify(ctx, `missions.maxFinalValidationRetries set to ${count} in ${r.file}`, "info"); }
|
|
15313
15475
|
} else {
|
|
15314
15476
|
const keyMap: Record<string, string> = { "Final Comprehensive Validation": "finalValidationEnabled", "Final Validation Requires Pass": "finalValidationRequiresPass", "Auto Repair Final Validation Failures": "autoRepairFinalValidationFailures" };
|
|
15315
15477
|
const key = keyMap[setting];
|
|
15316
15478
|
const enabled = await chooseBool(ctx, `${String(key)}?`);
|
|
15317
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as Record<string, unknown>)[String(key)] = enabled; }); ctx
|
|
15479
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as Record<string, unknown>)[String(key)] = enabled; }); workflowUiNotify(ctx, `missions.${String(key)} set to ${enabled} in ${r.file}`, "info"); }
|
|
15318
15480
|
}
|
|
15319
15481
|
}
|
|
15320
15482
|
}
|
|
@@ -15329,12 +15491,12 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15329
15491
|
const count = parsePositiveInt((await ctx.ui.input("Mission history limit", String(current))) ?? "");
|
|
15330
15492
|
if (count !== undefined && count >= 1 && count <= 500) {
|
|
15331
15493
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.missionHistoryLimit = count; });
|
|
15332
|
-
ctx
|
|
15494
|
+
workflowUiNotify(ctx, `missions.missionHistoryLimit set to ${count} in ${r.file}`, "info");
|
|
15333
15495
|
}
|
|
15334
15496
|
} else if (setting === "Cleanup Saved Missions") {
|
|
15335
15497
|
const settings = loadWorkflowSettings(ctx.cwd);
|
|
15336
15498
|
const removed = clearOldMissionStates(settings.missions.missionHistoryLimit ?? 50);
|
|
15337
|
-
ctx
|
|
15499
|
+
workflowUiNotify(ctx, `Removed ${removed} old mission file${removed === 1 ? "" : "s"}.`, "info");
|
|
15338
15500
|
} else if (setting === "List Current Settings") {
|
|
15339
15501
|
const settings = loadWorkflowSettings(ctx.cwd);
|
|
15340
15502
|
show(pi, `# Mission History\n\nMission History Limit: ${settings.missions.missionHistoryLimit ?? 50}\nMissions Directory: ${MISSION_HISTORY_DIR}`);
|
|
@@ -15351,48 +15513,48 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15351
15513
|
await showMissionModelBehaviorMenu(ctx);
|
|
15352
15514
|
} else if (choice === "Enable / Disable Mission Mode") {
|
|
15353
15515
|
const enabled = await chooseBool(ctx, "Missions enabled?");
|
|
15354
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.enabled = enabled; }); ctx
|
|
15516
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.enabled = enabled; }); workflowUiNotify(ctx, `missions.enabled set to ${enabled} in ${r.file}`, "info"); }
|
|
15355
15517
|
} else if (choice === "Mission Autonomy") {
|
|
15356
15518
|
const setting = await ctx.ui.select("Mission Autonomy", ["Default Autonomy", "Allow Full Auto", "Auto Run After Approval", "Continue Across Milestones", "Pause Between Milestones", "Auto Resume", "Back"]);
|
|
15357
15519
|
if (!setting || setting === "Back") continue;
|
|
15358
15520
|
if (setting === "Default Autonomy") {
|
|
15359
15521
|
const autonomy = parseMissionAutonomy((await ctx.ui.select("Mission default autonomy", ["manual", "approval_gated", "supervised_auto", "full_auto"])) ?? "");
|
|
15360
|
-
if (autonomy) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.defaultAutonomy = autonomy; }); ctx
|
|
15522
|
+
if (autonomy) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.defaultAutonomy = autonomy; }); workflowUiNotify(ctx, `missions.defaultAutonomy set to ${autonomy} in ${r.file}${autonomy === "full_auto" && !r.settings.missions.allowFullAuto ? "; full_auto will be blocked until allowFullAuto=true" : ""}`, "info"); }
|
|
15361
15523
|
} else {
|
|
15362
15524
|
const keyMap: Record<string, keyof ReturnType<typeof loadWorkflowSettings>["missions"]> = { "Allow Full Auto": "allowFullAuto", "Auto Run After Approval": "autoRunAfterApproval", "Continue Across Milestones": "continueAcrossMilestones", "Pause Between Milestones": "pauseBetweenMilestones", "Auto Resume": "autoResume" };
|
|
15363
15525
|
const key = keyMap[setting];
|
|
15364
15526
|
const enabled = await chooseBool(ctx, `${String(key)}?`);
|
|
15365
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as Record<string, unknown>)[String(key)] = enabled; }); ctx
|
|
15527
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as Record<string, unknown>)[String(key)] = enabled; }); workflowUiNotify(ctx, `missions.${String(key)} set to ${enabled} in ${r.file}${key === "allowFullAuto" && enabled === false && r.settings.missions.defaultAutonomy === "full_auto" ? "; full_auto default is retained but blocked" : ""}`, "info"); }
|
|
15366
15528
|
}
|
|
15367
15529
|
} else if (choice === "Default Autonomy") {
|
|
15368
15530
|
const autonomy = parseMissionAutonomy((await ctx.ui.select("Mission default autonomy", ["manual", "approval_gated", "supervised_auto", "full_auto"])) ?? "");
|
|
15369
|
-
if (autonomy) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.defaultAutonomy = autonomy; }); ctx
|
|
15531
|
+
if (autonomy) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.defaultAutonomy = autonomy; }); workflowUiNotify(ctx, `missions.defaultAutonomy set to ${autonomy} in ${r.file}${autonomy === "full_auto" && !r.settings.missions.allowFullAuto ? "; full_auto will be blocked until allowFullAuto=true" : ""}`, "info"); }
|
|
15370
15532
|
} else if (choice === "Mission Clarification") {
|
|
15371
15533
|
const setting = await ctx.ui.select("Mission Clarification", ["Clarification Mode", "Interactive Clarification", "Max Clarification Questions", "Timing", "Quality Gate", "Allow Without Analysis", "Use Sub-agents Before Clarification", "Back"]);
|
|
15372
15534
|
if (!setting || setting === "Back") continue;
|
|
15373
15535
|
if (setting === "Clarification Mode") {
|
|
15374
15536
|
const mode = parseClarificationMode((await ctx.ui.select("Mission clarification mode", ["auto", "always_for_nontrivial", "never"])) ?? "");
|
|
15375
|
-
if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.clarificationMode = mode; }); ctx
|
|
15537
|
+
if (mode) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.clarificationMode = mode; }); workflowUiNotify(ctx, `missions.clarificationMode set to ${mode} in ${r.file}`, "info"); }
|
|
15376
15538
|
} else if (setting === "Interactive Clarification") {
|
|
15377
15539
|
const enabled = await chooseBool(ctx, "Mission interactive clarification enabled?");
|
|
15378
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.interactiveClarificationEnabled = enabled; }); ctx
|
|
15540
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.interactiveClarificationEnabled = enabled; }); workflowUiNotify(ctx, `missions.interactiveClarificationEnabled set to ${enabled} in ${r.file}`, "info"); }
|
|
15379
15541
|
} else if (setting === "Max Clarification Questions") {
|
|
15380
15542
|
const count = parsePositiveInt((await ctx.ui.select("Mission max clarification questions", ["1", "2", "3", "4", "5", "6"])) ?? "");
|
|
15381
|
-
if (count) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxClarificationQuestions = count; }); ctx
|
|
15543
|
+
if (count) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxClarificationQuestions = count; }); workflowUiNotify(ctx, `missions.maxClarificationQuestions set to ${count} in ${r.file}`, "info"); }
|
|
15382
15544
|
} else if (setting === "Timing") {
|
|
15383
15545
|
const timing = parseClarificationTiming((await ctx.ui.select("Mission clarification timing", ["after_initial_analysis", "immediate"])) ?? "");
|
|
15384
|
-
if (timing) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.clarificationTiming = timing; }); ctx
|
|
15546
|
+
if (timing) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.clarificationTiming = timing; }); workflowUiNotify(ctx, `missions.clarificationTiming set to ${timing} in ${r.file}`, "info"); }
|
|
15385
15547
|
} else {
|
|
15386
15548
|
const key = setting === "Quality Gate" ? "clarificationQualityGate" : setting === "Allow Without Analysis" ? "allowClarificationWithoutAnalysis" : "useSubagentsBeforeClarification";
|
|
15387
15549
|
const enabled = await chooseBool(ctx, `missions.${key}?`);
|
|
15388
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, boolean | string | number | undefined>)[key] = enabled; }); ctx
|
|
15550
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, boolean | string | number | undefined>)[key] = enabled; }); workflowUiNotify(ctx, `missions.${key} set to ${enabled} in ${r.file}`, "info"); }
|
|
15389
15551
|
}
|
|
15390
15552
|
} else if (choice === "Mission Planning Depth") {
|
|
15391
15553
|
const depth = parsePlanningDepth((await ctx.ui.select("Mission planning depth", ["fast", "standard", "deep", "maximum"])) ?? "");
|
|
15392
|
-
if (depth) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.planningDepth = depth; }); ctx
|
|
15554
|
+
if (depth) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.planningDepth = depth; }); workflowUiNotify(ctx, `missions.planningDepth set to ${depth} in ${r.file}`, "info"); }
|
|
15393
15555
|
} else if (choice === "Mission Sub-Agent Policy") {
|
|
15394
15556
|
const policy = parseSubagentPolicy((await ctx.ui.select("Mission sub-agent policy", ["off", "auto", "deep", "maximum", "forced"])) ?? "");
|
|
15395
|
-
if (policy) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.subagentPolicy = policy; }); ctx
|
|
15557
|
+
if (policy) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.subagentPolicy = policy; }); workflowUiNotify(ctx, `missions.subagentPolicy set to ${policy} in ${r.file}`, "info"); }
|
|
15396
15558
|
} else if (choice === "Mission Sub-agents / Workers" || choice === "Mission Worker Targets") {
|
|
15397
15559
|
await showMissionSubagentWorkerSettingsMenu(ctx);
|
|
15398
15560
|
} else if (choice === "Mission History") {
|
|
@@ -15408,50 +15570,50 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15408
15570
|
if (setting === "Progress Widget" || setting === "Progress Bar Display") {
|
|
15409
15571
|
const key = setting === "Progress Widget" ? "progressWidgetEnabled" : "showProgressBar";
|
|
15410
15572
|
const enabled = await chooseBool(ctx, `missions.${key}?`);
|
|
15411
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, boolean>)[key] = enabled; }); ctx
|
|
15573
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as typeof s.missions & Record<string, boolean>)[key] = enabled; }); workflowUiNotify(ctx, `missions.${key} set to ${enabled} in ${r.file}`, "info"); }
|
|
15412
15574
|
} else if (setting === "Heartbeat / Watchdog") await showHeartbeatWatchdogMenu(ctx);
|
|
15413
15575
|
else if (setting === "Token Budget") {
|
|
15414
15576
|
const current = loadWorkflowSettings(ctx.cwd).missions.maxTokens ?? 0;
|
|
15415
15577
|
const choice = await ctx.ui.select("Mission Token Budget", ["Default (unlimited)", "Custom..."]);
|
|
15416
15578
|
if (choice === "Default (unlimited)") {
|
|
15417
15579
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxTokens = 0; });
|
|
15418
|
-
ctx
|
|
15580
|
+
workflowUiNotify(ctx, `missions.maxTokens set to default (unlimited) in ${r.file}`, "info");
|
|
15419
15581
|
} else if (choice === "Custom...") {
|
|
15420
15582
|
const count = parsePositiveInt((await ctx.ui.input("Enter custom mission token budget", String(current > 0 ? current : ""))) ?? "");
|
|
15421
|
-
if (count !== undefined && count >= 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxTokens = count; }); ctx
|
|
15583
|
+
if (count !== undefined && count >= 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxTokens = count; }); workflowUiNotify(ctx, `missions.maxTokens set to ${count === 0 ? "unlimited" : count.toLocaleString()} in ${r.file}`, "info"); }
|
|
15422
15584
|
}
|
|
15423
15585
|
} else if (setting === "Runtime Budget") {
|
|
15424
15586
|
const current = loadWorkflowSettings(ctx.cwd).missions.maxRuntimeHours;
|
|
15425
15587
|
const choice = await ctx.ui.select("Mission Runtime Budget", ["Default (13 hours)", "Custom..."]);
|
|
15426
15588
|
if (choice === "Default (13 hours)") {
|
|
15427
15589
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxRuntimeHours = 13; });
|
|
15428
|
-
ctx
|
|
15590
|
+
workflowUiNotify(ctx, `missions.maxRuntimeHours set to default (13 hours) in ${r.file}`, "info");
|
|
15429
15591
|
} else if (choice === "Custom...") {
|
|
15430
15592
|
const count = parsePositiveInt((await ctx.ui.input("Enter custom runtime budget (hours)", String(current !== 13 ? current : ""))) ?? "");
|
|
15431
|
-
if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxRuntimeHours = count; }); ctx
|
|
15593
|
+
if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxRuntimeHours = count; }); workflowUiNotify(ctx, `missions.maxRuntimeHours set to ${count} hours in ${r.file}`, "info"); }
|
|
15432
15594
|
}
|
|
15433
15595
|
} else {
|
|
15434
15596
|
const count = parsePositiveInt((await ctx.ui.input("checkpointIntervalMinutes", "30")) ?? "");
|
|
15435
|
-
if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.checkpointIntervalMinutes = count; }); ctx
|
|
15597
|
+
if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.checkpointIntervalMinutes = count; }); workflowUiNotify(ctx, `missions.checkpointIntervalMinutes set to ${count} in ${r.file}`, "info"); }
|
|
15436
15598
|
}
|
|
15437
15599
|
} else if (choice === "Runtime Budget") {
|
|
15438
15600
|
const current = loadWorkflowSettings(ctx.cwd).missions.maxRuntimeHours;
|
|
15439
15601
|
const choice2 = await ctx.ui.select("Mission Runtime Budget", ["Default (13 hours)", "Custom..."]);
|
|
15440
15602
|
if (choice2 === "Default (13 hours)") {
|
|
15441
15603
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxRuntimeHours = 13; });
|
|
15442
|
-
ctx
|
|
15604
|
+
workflowUiNotify(ctx, `missions.maxRuntimeHours set to default (13 hours) in ${r.file}`, "info");
|
|
15443
15605
|
} else if (choice2 === "Custom...") {
|
|
15444
15606
|
const count = parsePositiveInt((await ctx.ui.input("Enter custom runtime budget (hours)", String(current !== 13 ? current : ""))) ?? "");
|
|
15445
|
-
if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxRuntimeHours = count; }); ctx
|
|
15607
|
+
if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.maxRuntimeHours = count; }); workflowUiNotify(ctx, `missions.maxRuntimeHours set to ${count} hours in ${r.file}`, "info"); }
|
|
15446
15608
|
}
|
|
15447
15609
|
} else if (choice === "Checkpoint Interval") {
|
|
15448
15610
|
const count = parsePositiveInt((await ctx.ui.input("checkpointIntervalMinutes", "30")) ?? "");
|
|
15449
|
-
if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.checkpointIntervalMinutes = count; }); ctx
|
|
15611
|
+
if (count !== undefined && count > 0) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.missions.checkpointIntervalMinutes = count; }); workflowUiNotify(ctx, `missions.checkpointIntervalMinutes set to ${count} in ${r.file}`, "info"); }
|
|
15450
15612
|
} else if (choice === "Approval Safety" || choice === "Validation Per Milestone" || choice === "Full Auto Safety" || choice === "Auto Resume") {
|
|
15451
15613
|
const keyMap: Record<string, keyof ReturnType<typeof loadWorkflowSettings>["missions"]> = { "Validation Per Milestone": "requireValidationPerMilestone", "Approval Safety": "requireApprovalForDestructiveActions", "Full Auto Safety": "allowFullAuto", "Auto Resume": "autoResume" };
|
|
15452
15614
|
const key = keyMap[choice];
|
|
15453
15615
|
const enabled = await chooseBool(ctx, `${String(key)}?`);
|
|
15454
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as Record<string, unknown>)[String(key)] = enabled; }); ctx
|
|
15616
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { (s.missions as Record<string, unknown>)[String(key)] = enabled; }); workflowUiNotify(ctx, `missions.${String(key)} set to ${enabled} in ${r.file}${key === "allowFullAuto" && enabled === false && r.settings.missions.defaultAutonomy === "full_auto" ? "; full_auto default is retained but blocked" : ""}`, "info"); }
|
|
15455
15617
|
} else if (choice === "Review / Validation Behavior") {
|
|
15456
15618
|
await showMissionReviewValidationBehaviorMenu(ctx);
|
|
15457
15619
|
} else if (choice === "Repair / Validation Retry" || choice === "Mission Repair / Validation" || choice === "Repair / Validation Retry Settings") {
|
|
@@ -15484,18 +15646,18 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15484
15646
|
const enabled = await chooseBool(ctx, "safety.repoLockEnabled for this project only?");
|
|
15485
15647
|
if (enabled !== undefined) {
|
|
15486
15648
|
const r = updateSettings(ctx.cwd, "project", (s) => { s.safety.repoLockEnabled = enabled; });
|
|
15487
|
-
ctx
|
|
15649
|
+
workflowUiNotify(ctx, `Project Repo Lock set to ${enabled} in ${r.file}. This project override wins over global settings and does not apply to other repos.`, "info");
|
|
15488
15650
|
}
|
|
15489
15651
|
} else {
|
|
15490
15652
|
const key = keyMap[choice];
|
|
15491
15653
|
const enabled = await chooseBool(ctx, `${String(key)}?`);
|
|
15492
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.safety[key] = enabled; }); ctx
|
|
15654
|
+
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.safety[key] = enabled; }); workflowUiNotify(ctx, `safety.${String(key)} set to ${enabled} in ${r.file}`, "info"); }
|
|
15493
15655
|
}
|
|
15494
15656
|
}
|
|
15495
15657
|
}
|
|
15496
15658
|
|
|
15497
|
-
async function
|
|
15498
|
-
if (!ctx.hasUI) return show(pi,
|
|
15659
|
+
async function showEditorHintsSettingsMenu(ctx: ExtensionContext) {
|
|
15660
|
+
if (!ctx.hasUI) return show(pi, renderEditorHintsSettings(ctx));
|
|
15499
15661
|
const options = [
|
|
15500
15662
|
{ label: "Idle Entry Hint", key: "showIdleWorkflowEntryHint" as const },
|
|
15501
15663
|
{ label: "Active Switch Hint", key: "showActiveWorkflowSwitchHint" as const },
|
|
@@ -15506,17 +15668,31 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15506
15668
|
const settings = loadWorkflowSettings(ctx.cwd);
|
|
15507
15669
|
const ui = workflowWidgetUi(settings);
|
|
15508
15670
|
const labels = options.map((option) => `${option.label}: ${ui[option.key] !== false ? "visible" : "hidden"}`);
|
|
15509
|
-
const
|
|
15671
|
+
const contrastLabel = `Hint Contrast: ${workflowEditorHintContrastLabel(workflowEditorHintContrast(settings))}`;
|
|
15672
|
+
const choice = await ctx.ui.select("Editor Hints", [...labels, contrastLabel, "List Current Settings", "Back"]);
|
|
15510
15673
|
if (!choice || choice === "Back") return;
|
|
15511
|
-
if (choice === "List Current Settings") { show(pi,
|
|
15674
|
+
if (choice === "List Current Settings") { show(pi, renderEditorHintsSettings(ctx)); continue; }
|
|
15675
|
+
if (choice === contrastLabel) {
|
|
15676
|
+
const current = workflowEditorHintContrast(settings);
|
|
15677
|
+
const contrastChoice = await ctx.ui.select("Editor Hint Contrast", WORKFLOW_EDITOR_HINT_CONTRASTS.map((contrast) => `${workflowEditorHintContrastLabel(contrast)}${contrast === current ? " (current)" : ""}`).concat("Back"));
|
|
15678
|
+
if (!contrastChoice || contrastChoice === "Back") continue;
|
|
15679
|
+
const contrast = parseEditorHintContrast(contrastChoice.replace(/\s+\(current\)$/, ""));
|
|
15680
|
+
if (contrast) {
|
|
15681
|
+
updateSettings(ctx.cwd, "global", (s) => { workflowWidgetUi(s).editorHintContrast = contrast; });
|
|
15682
|
+
setWorkflowUi(ctx, state, activeSubagents);
|
|
15683
|
+
workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd));
|
|
15684
|
+
workflowUiNotify(ctx, `Editor hint contrast set to ${workflowEditorHintContrastLabel(contrast)}.`, "info");
|
|
15685
|
+
}
|
|
15686
|
+
continue;
|
|
15687
|
+
}
|
|
15512
15688
|
const index = labels.indexOf(choice);
|
|
15513
15689
|
const option = options[index];
|
|
15514
15690
|
if (!option) continue;
|
|
15515
15691
|
const enabled = await chooseBool(ctx, `ui.${option.key}?`);
|
|
15516
15692
|
if (enabled !== undefined) {
|
|
15517
|
-
|
|
15693
|
+
updateSettings(ctx.cwd, "global", (s) => { workflowWidgetUi(s)[option.key] = enabled; });
|
|
15518
15694
|
setWorkflowUi(ctx, state, activeSubagents);
|
|
15519
|
-
ctx
|
|
15695
|
+
workflowUiNotify(ctx, `${option.label} ${enabled ? "shown" : "hidden"}.`, "info");
|
|
15520
15696
|
}
|
|
15521
15697
|
}
|
|
15522
15698
|
}
|
|
@@ -15524,32 +15700,32 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15524
15700
|
async function showUiWidgetsSettingsMenu(ctx: ExtensionContext) {
|
|
15525
15701
|
if (!ctx.hasUI) return show(pi, renderWorkflowWidgetsStatus(ctx));
|
|
15526
15702
|
while (ctx.hasUI) {
|
|
15527
|
-
const choice = await ctx.ui.select("UI Widgets", ["Plan Top Widget", "Plan Bottom Widget", "Mission Top Widget", "Mission Bottom Widget", "Enable Widget Shortcuts", "Remember Widget Visibility", "
|
|
15703
|
+
const choice = await ctx.ui.select("UI Widgets", ["Plan Top Widget", "Plan Bottom Widget", "Mission Top Widget", "Mission Bottom Widget", "Enable Widget Shortcuts", "Remember Widget Visibility", "Editor Hints", "List Current Settings", "Back"]);
|
|
15528
15704
|
if (!choice || choice === "Back") return;
|
|
15529
15705
|
if (choice === "List Current Settings") show(pi, renderWorkflowWidgetsStatus(ctx));
|
|
15530
|
-
else if (choice === "
|
|
15706
|
+
else if (choice === "Editor Hints") await showEditorHintsSettingsMenu(ctx);
|
|
15531
15707
|
else if (choice === "Enable Widget Shortcuts" || choice === "Remember Widget Visibility") {
|
|
15532
15708
|
const key = choice === "Enable Widget Shortcuts" ? "enableWidgetShortcuts" : "rememberWidgetVisibility";
|
|
15533
15709
|
const enabled = await chooseBool(ctx, `ui.${key}?`);
|
|
15534
15710
|
if (enabled !== undefined) {
|
|
15535
|
-
|
|
15711
|
+
updateSettings(ctx.cwd, "global", (s) => { workflowWidgetUi(s)[key] = enabled; });
|
|
15536
15712
|
setWorkflowUi(ctx, state, activeSubagents);
|
|
15537
|
-
ctx
|
|
15713
|
+
workflowUiNotify(ctx, `${choice} ${enabled ? "enabled" : "disabled"}.`, "info");
|
|
15538
15714
|
}
|
|
15539
15715
|
} else {
|
|
15540
15716
|
const slot: WorkflowWidgetSlot = choice === "Plan Top Widget" ? "planTop" : choice === "Plan Bottom Widget" ? "planBottom" : choice === "Mission Top Widget" ? "missionTop" : "missionBottom";
|
|
15541
15717
|
const visible = await chooseBool(ctx, `${widgetSlotLabel(slot)} visible?`);
|
|
15542
|
-
if (visible !== undefined) ctx
|
|
15718
|
+
if (visible !== undefined) workflowUiNotify(ctx, setWorkflowWidgetVisibility(ctx, slot, visible), "info");
|
|
15543
15719
|
}
|
|
15544
15720
|
}
|
|
15545
15721
|
}
|
|
15546
15722
|
|
|
15547
15723
|
function presetUsage(): string {
|
|
15548
|
-
return
|
|
15724
|
+
return `# Workflow Presets\n\nQuick use:\n- /workflow presets opens the selector\n- ${workflowPresetCycleShortcutLabel()} cycles saved presets from the footer only while Plan/Mission/Standard Mode is active\n- /workflow presets list\n- /workflow presets apply <name>\n- /workflow presets next\n- /workflow presets prev\n- /workflow presets save <name>\n- /workflow presets create <name> from simple|standard|deep|maximum\n- /workflow presets edit <name>\n- /workflow presets rename <old> to <new>\n- /workflow presets delete <name>`;
|
|
15549
15725
|
}
|
|
15550
15726
|
|
|
15551
15727
|
function presetActionMessage(title: string, name: string, resultFile?: string, scope?: string): string {
|
|
15552
|
-
return `# ${title}\n\nPreset: ${name}\n${scope ? `Scope: ${scope}\n` : ""}${resultFile ? `File: ${resultFile}\n` : ""}\nScope note: presets apply across Standard Mode, Plan Mode, Mission Mode, shared sub-agents, and selected UI settings.\nUse selector: /workflow presets\nCycle saved presets:
|
|
15728
|
+
return `# ${title}\n\nPreset: ${name}\n${scope ? `Scope: ${scope}\n` : ""}${resultFile ? `File: ${resultFile}\n` : ""}\nScope note: presets apply across Standard Mode, Plan Mode, Mission Mode, shared sub-agents, and selected UI settings.\nUse selector: /workflow presets\nCycle saved presets: ${workflowPresetCycleShortcutLabel()} while Plan/Mission/Standard Mode is active\nFooter: idle displays Plan/Mission entry shortcuts only; active workflows display compact widget/preset hints and workflow switch hints by default.\n\nModel/provider choices and shared compaction settings are preserved.`;
|
|
15553
15729
|
}
|
|
15554
15730
|
|
|
15555
15731
|
function parsePresetCreate(rest: string): { name: string; template?: string } {
|
|
@@ -15577,7 +15753,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15577
15753
|
const { names, options } = presetDisplayOptions(settings);
|
|
15578
15754
|
if (!ctx.hasUI) return show(pi, renderWorkflowPresets(settings));
|
|
15579
15755
|
if (names.length === 0) return show(pi, "# Workflow Presets\n\nNo presets available.");
|
|
15580
|
-
const choice = await ctx.ui.select(`Workflow Presets — active: ${activeWorkflowPresetLabel(settings)} —
|
|
15756
|
+
const choice = await ctx.ui.select(`Workflow Presets — active: ${activeWorkflowPresetLabel(settings)} — ${workflowPresetCycleShortcutLabel()} cycles during Plan/Mission`, options);
|
|
15581
15757
|
if (!choice) return;
|
|
15582
15758
|
const selected = names[options.indexOf(choice)];
|
|
15583
15759
|
if (!selected) return;
|
|
@@ -15591,14 +15767,14 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15591
15767
|
const result = applyWorkflowPreset(ctx.cwd, undefined, resolved);
|
|
15592
15768
|
setWorkflowUi(ctx, state, activeSubagents);
|
|
15593
15769
|
const label = workflowPresetLabel(resolved, workflowPresetCatalog(result.settings)[resolved]);
|
|
15594
|
-
if (notifyOnly) ctx
|
|
15770
|
+
if (notifyOnly) workflowUiNotify(ctx, `Workflow preset active: ${label}`, "info");
|
|
15595
15771
|
else show(pi, presetActionMessage("Workflow Preset Applied", label, result.file, result.scope));
|
|
15596
15772
|
}
|
|
15597
15773
|
|
|
15598
15774
|
async function markWorkflowPresetCustom(ctx: ExtensionContext): Promise<void> {
|
|
15599
15775
|
const result = updateSettings(ctx.cwd, undefined, (s) => { s.presets = { ...(s.presets ?? {}), activePreset: WORKFLOW_CUSTOM_PRESET_MARKER, items: { ...(s.presets?.items ?? {}) } }; });
|
|
15600
15776
|
setWorkflowUi(ctx, state, activeSubagents);
|
|
15601
|
-
ctx
|
|
15777
|
+
workflowUiNotify(ctx, `Workflow preset marker cleared in ${result.file}; workflow settings unchanged.`, "info");
|
|
15602
15778
|
}
|
|
15603
15779
|
|
|
15604
15780
|
async function cycleWorkflowPreset(ctx: ExtensionContext, direction: 1 | -1): Promise<void> {
|
|
@@ -15666,7 +15842,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15666
15842
|
if (policy) updateSettings(ctx.cwd, undefined, (s) => { const item = (s.presets!.items![name] ??= { planning: {}, workflow: {}, missions: {}, subagents: {} }); item.subagents = { ...(item.subagents ?? {}), planningPolicy: policy, executionPolicy: policy, repairPolicy: policy, reviewPolicy: policy, validationPolicy: policy }; });
|
|
15667
15843
|
}
|
|
15668
15844
|
setWorkflowUi(ctx, state, activeSubagents);
|
|
15669
|
-
ctx
|
|
15845
|
+
workflowUiNotify(ctx, `Preset ${name} updated in ${r.file}`, "info");
|
|
15670
15846
|
} catch (e) { show(pi, `# Workflow Preset Error\n\n${e instanceof Error ? e.message : String(e)}`); }
|
|
15671
15847
|
}
|
|
15672
15848
|
}
|
|
@@ -15706,7 +15882,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15706
15882
|
const r = createWorkflowPreset(ctx.cwd, undefined, parsed.name, parsed.template);
|
|
15707
15883
|
setWorkflowUi(ctx, state, activeSubagents);
|
|
15708
15884
|
const safe = normalizeWorkflowPresetName(parsed.name);
|
|
15709
|
-
return show(pi, `# Workflow Preset Created\n\nPreset: ${parsed.name}\nSaved As: ${safe}\n${parsed.template ? `Template: ${parsed.template}\n` : ""}Scope: ${r.scope}\nFile: ${r.file}\n\nThe preset was saved but not applied.\nScope note: presets apply across Standard Mode, Plan Mode, Mission Mode, shared sub-agents, and selected UI settings.\nApply now: /workflow presets apply ${safe}\nOpen selector: /workflow presets\nCycle saved presets:
|
|
15885
|
+
return show(pi, `# Workflow Preset Created\n\nPreset: ${parsed.name}\nSaved As: ${safe}\n${parsed.template ? `Template: ${parsed.template}\n` : ""}Scope: ${r.scope}\nFile: ${r.file}\n\nThe preset was saved but not applied.\nScope note: presets apply across Standard Mode, Plan Mode, Mission Mode, shared sub-agents, and selected UI settings.\nApply now: /workflow presets apply ${safe}\nOpen selector: /workflow presets\nCycle saved presets: ${workflowPresetCycleShortcutLabel()} while Plan/Mission/Standard Mode is active`);
|
|
15710
15886
|
}
|
|
15711
15887
|
if (action === "configure" || action === "edit") {
|
|
15712
15888
|
if (!rest) return show(pi, "# Workflow Presets\n\nUsage: /workflow presets edit <name>");
|
|
@@ -15761,7 +15937,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15761
15937
|
async function showCustomBrandStartupVisualMenu(ctx: ExtensionContext): Promise<boolean | undefined> {
|
|
15762
15938
|
if (!ctx.hasUI) return undefined;
|
|
15763
15939
|
const saved = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupVisual = "custom_brand"; });
|
|
15764
|
-
ctx
|
|
15940
|
+
workflowUiNotify(ctx, `ui.startupVisual set to custom_brand in ${saved.file}`, "info");
|
|
15765
15941
|
while (ctx.hasUI) {
|
|
15766
15942
|
const choice = await ctx.ui.select("Custom Brand Startup Visual", ["Set Text", "Choose Base Template", "Preview", "List Theme Settings", "Back"]);
|
|
15767
15943
|
if (!choice || choice === "Back") return undefined;
|
|
@@ -15770,13 +15946,13 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15770
15946
|
} else if (choice === "Set Text") {
|
|
15771
15947
|
const text = sanitizeCustomBrandText(await ctx.ui.input("Custom brand text", sanitizeCustomBrandText(loadWorkflowSettings(ctx.cwd).ui.customBrandText) || "WORKFLOW SUITE"));
|
|
15772
15948
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.customBrandEnabled = true; s.ui.customBrandText = text; s.ui.startupVisual = "custom_brand"; });
|
|
15773
|
-
ctx
|
|
15949
|
+
workflowUiNotify(ctx, `ui.customBrandText set in ${r.file}`, "info");
|
|
15774
15950
|
void showStartupVisual(ctx, { intent: "manual" });
|
|
15775
15951
|
} else if (choice === "Choose Base Template") {
|
|
15776
15952
|
const base = parseCustomBrandBaseVisual((await ctx.ui.select("Custom brand base template", WORKFLOW_CUSTOM_BRAND_BASE_VISUALS)) ?? "");
|
|
15777
15953
|
if (base) {
|
|
15778
15954
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.customBrandBaseVisual = base; s.ui.startupVisual = "custom_brand"; });
|
|
15779
|
-
ctx
|
|
15955
|
+
workflowUiNotify(ctx, `ui.customBrandBaseVisual set to ${base} in ${r.file}`, "info");
|
|
15780
15956
|
void showStartupVisual(ctx, { intent: "manual" });
|
|
15781
15957
|
}
|
|
15782
15958
|
} else if (choice === "Preview") {
|
|
@@ -15798,27 +15974,27 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15798
15974
|
const text = startupLogoText(loadWorkflowSettings(ctx.cwd)) || "WFS";
|
|
15799
15975
|
const value = sanitizeCustomBrandText(await ctx.ui.input("Custom logo letters (max 6 A-Z/0-9)", text)).toUpperCase().replace(/[^A-Z0-9]/g, "").slice(0, 6);
|
|
15800
15976
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupLogo = "custom"; s.ui.startupLogoText = value; });
|
|
15801
|
-
ctx
|
|
15977
|
+
workflowUiNotify(ctx, `ui.startupLogoText set to ${value || "(empty)"} in ${r.file}`, "info");
|
|
15802
15978
|
void showStartupVisual(ctx, { intent: "manual" });
|
|
15803
15979
|
} else if (choice === "Choose Font") {
|
|
15804
15980
|
const font = parseStartupLogoFont((await ctx.ui.select("Custom logo font", WORKFLOW_STARTUP_LOGO_FONTS)) ?? "");
|
|
15805
15981
|
if (font) {
|
|
15806
15982
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupLogo = "custom"; s.ui.startupLogoFont = font; });
|
|
15807
|
-
ctx
|
|
15983
|
+
workflowUiNotify(ctx, `ui.startupLogoFont set to ${font} in ${r.file}`, "info");
|
|
15808
15984
|
void showStartupVisual(ctx, { intent: "manual" });
|
|
15809
15985
|
}
|
|
15810
15986
|
} else if (choice === "Choose Shadow Direction") {
|
|
15811
15987
|
const direction = parseStartupLogoShadowDirection((await ctx.ui.select("Custom logo shadow direction", WORKFLOW_STARTUP_LOGO_SHADOW_DIRECTIONS)) ?? "");
|
|
15812
15988
|
if (direction) {
|
|
15813
15989
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupLogo = "custom"; s.ui.startupLogoShadowDirection = direction; });
|
|
15814
|
-
ctx
|
|
15990
|
+
workflowUiNotify(ctx, `ui.startupLogoShadowDirection set to ${direction} in ${r.file}`, "info");
|
|
15815
15991
|
void showStartupVisual(ctx, { intent: "manual" });
|
|
15816
15992
|
}
|
|
15817
15993
|
} else if (choice === "Choose Color Style") {
|
|
15818
15994
|
const colorStyle = parseStartupLogoColorStyle((await ctx.ui.select("Custom logo color style", WORKFLOW_STARTUP_LOGO_COLOR_STYLES)) ?? "");
|
|
15819
15995
|
if (colorStyle) {
|
|
15820
15996
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupLogo = "custom"; s.ui.startupLogoColorStyle = colorStyle; });
|
|
15821
|
-
ctx
|
|
15997
|
+
workflowUiNotify(ctx, `ui.startupLogoColorStyle set to ${colorStyle} in ${r.file}`, "info");
|
|
15822
15998
|
void showStartupVisual(ctx, { intent: "manual" });
|
|
15823
15999
|
}
|
|
15824
16000
|
} else if (choice === "Preview") {
|
|
@@ -15843,7 +16019,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15843
16019
|
} else {
|
|
15844
16020
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupVisual = visual; });
|
|
15845
16021
|
const canPreview = startupVisualOrDefault(r.settings) !== "none";
|
|
15846
|
-
ctx
|
|
16022
|
+
workflowUiNotify(ctx, canPreview ? `Startup visual set to ${visual} in ${r.file}` : `Startup visual set to ${visual} (disabled) in ${r.file}`, "info");
|
|
15847
16023
|
if (canPreview) void showStartupVisual(ctx, { intent: "manual" });
|
|
15848
16024
|
}
|
|
15849
16025
|
}
|
|
@@ -15851,14 +16027,14 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15851
16027
|
const name = parseWidgetTextPreset((await ctx.ui.select("Startup text style", (WORKFLOW_WIDGET_TEXT_PRESETS as readonly string[]).map((p) => WORKFLOW_WIDGET_TEXT_PRESET_LABELS[p]))) ?? "");
|
|
15852
16028
|
if (name) {
|
|
15853
16029
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupTextStyle = name; });
|
|
15854
|
-
ctx
|
|
16030
|
+
workflowUiNotify(ctx, `Startup text style set to ${WORKFLOW_WIDGET_TEXT_PRESET_LABELS[name]} in ${r.file}.`, "info");
|
|
15855
16031
|
void showStartupVisual(ctx, { intent: "manual" });
|
|
15856
16032
|
}
|
|
15857
16033
|
} else if (choice === "Turn On" || choice === "Turn Off") {
|
|
15858
16034
|
const visual: WorkflowStartupVisual = choice === "Turn On" ? "mission_control" : "none";
|
|
15859
16035
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupVisual = visual; });
|
|
15860
16036
|
const canPreview = startupVisualOrDefault(r.settings) !== "none";
|
|
15861
|
-
ctx
|
|
16037
|
+
workflowUiNotify(ctx, canPreview ? `Startup visual turned on (${visual}) in ${r.file}` : `Startup visual turned off in ${r.file}`, "info");
|
|
15862
16038
|
if (canPreview) void showStartupVisual(ctx, { intent: "manual" });
|
|
15863
16039
|
} else if (choice === "On Session Start") {
|
|
15864
16040
|
const enabled = await chooseBool(ctx, "Show startup visual on session start?");
|
|
@@ -15867,12 +16043,12 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15867
16043
|
s.ui.startupVisualOnSessionStart = enabled;
|
|
15868
16044
|
if (enabled === true && (parseStartupVisual(s.ui.startupVisual) ?? "none") === "none") s.ui.startupVisual = "minimal";
|
|
15869
16045
|
});
|
|
15870
|
-
ctx
|
|
16046
|
+
workflowUiNotify(ctx, `Startup on session start ${enabled ? "enabled" : "disabled"} in ${r.file}`, "info");
|
|
15871
16047
|
void showStartupVisual(ctx, { intent: "manual" });
|
|
15872
16048
|
}
|
|
15873
16049
|
} else if (choice === "Preview") {
|
|
15874
16050
|
const previewed = await showStartupVisual(ctx, { intent: "manual" });
|
|
15875
|
-
if (!previewed) ctx
|
|
16051
|
+
if (!previewed) workflowUiNotify(ctx, "Startup visual is disabled. Choose a visual or turn it on to preview.", "info");
|
|
15876
16052
|
}
|
|
15877
16053
|
}
|
|
15878
16054
|
return undefined;
|
|
@@ -15901,7 +16077,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15901
16077
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.workflowTheme = name; });
|
|
15902
16078
|
applyWorkflowEditorTheme(ctx);
|
|
15903
16079
|
setWorkflowUi(ctx, state, activeSubagents);
|
|
15904
|
-
ctx
|
|
16080
|
+
workflowUiNotify(ctx, `ui.workflowTheme set to ${workflowThemeDisplayName(name)} in ${r.file}`, "info");
|
|
15905
16081
|
void showStartupVisual(ctx, { intent: "manual" });
|
|
15906
16082
|
}
|
|
15907
16083
|
} else if (choice === "Startup Visual") {
|
|
@@ -15910,7 +16086,7 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
15910
16086
|
const logo = parseStartupLogo((await ctx.ui.select("Startup logo", WORKFLOW_STARTUP_LOGOS)) ?? "");
|
|
15911
16087
|
if (logo) {
|
|
15912
16088
|
const r = updateSettings(ctx.cwd, undefined, (s) => { s.ui.startupLogo = logo; });
|
|
15913
|
-
ctx
|
|
16089
|
+
workflowUiNotify(ctx, `ui.startupLogo set to ${logo} in ${r.file}`, "info");
|
|
15914
16090
|
if (logo === "custom") await showCustomStartupLogoMenu(ctx);
|
|
15915
16091
|
else void showStartupVisual(ctx, { intent: "manual" });
|
|
15916
16092
|
}
|
|
@@ -16070,20 +16246,20 @@ Pi Version: v${VERSION}
|
|
|
16070
16246
|
workflowLastAutoCompactionAt = Date.now();
|
|
16071
16247
|
clearDeferredWorkflowCompaction();
|
|
16072
16248
|
rememberWorkflowCompactionCheck(`${checkpoint} boundary triggered at ${percent.toFixed(1)}% context`);
|
|
16073
|
-
try { ctx
|
|
16249
|
+
try { workflowUiNotify(ctx, `Workflow auto-compaction triggered at ${percent.toFixed(1)}% context usage.`, "info"); } catch { /* UI may be unavailable */ }
|
|
16074
16250
|
ctx.compact({
|
|
16075
16251
|
customInstructions,
|
|
16076
16252
|
onComplete: () => {
|
|
16077
16253
|
workflowAutoCompactionRunning = false;
|
|
16078
16254
|
workflowLastAutoCompactionAt = Date.now();
|
|
16079
16255
|
rememberWorkflowCompactionCheck(`${checkpoint} boundary compaction completed`);
|
|
16080
|
-
try { ctx
|
|
16256
|
+
try { workflowUiNotify(ctx, "Workflow auto-compaction complete.", "info"); } catch { /* UI may be unavailable */ }
|
|
16081
16257
|
},
|
|
16082
16258
|
onError: (error: Error) => {
|
|
16083
16259
|
workflowAutoCompactionRunning = false;
|
|
16084
16260
|
rememberWorkflowCompactionCheck(`${checkpoint} boundary compaction failed — ${error.message}`);
|
|
16085
16261
|
rememberCustomCompactionStatus(`proactive compaction request failed: ${error.message}`);
|
|
16086
|
-
try { ctx
|
|
16262
|
+
try { workflowUiNotify(ctx, `Workflow auto-compaction skipped: ${error.message}`, "warning"); } catch { /* UI may be unavailable */ }
|
|
16087
16263
|
},
|
|
16088
16264
|
});
|
|
16089
16265
|
}
|
|
@@ -16136,7 +16312,7 @@ Pi Version: v${VERSION}
|
|
|
16136
16312
|
const model = ctx.modelRegistry.find(provider, modelId);
|
|
16137
16313
|
if (!model) {
|
|
16138
16314
|
rememberCustomCompactionStatus(`fallback to Pi default: model not found ${provider}/${modelId}`);
|
|
16139
|
-
ctx
|
|
16315
|
+
workflowUiNotify(ctx, `Custom compaction model not found: ${provider}/${modelId}; using Pi default compaction.`, "warning");
|
|
16140
16316
|
return;
|
|
16141
16317
|
}
|
|
16142
16318
|
|
|
@@ -16144,12 +16320,12 @@ Pi Version: v${VERSION}
|
|
|
16144
16320
|
if (auth.ok === false) {
|
|
16145
16321
|
const authError = auth.error;
|
|
16146
16322
|
rememberCustomCompactionStatus(`fallback to Pi default: auth failed for ${provider}/${modelId}: ${authError}`);
|
|
16147
|
-
ctx
|
|
16323
|
+
workflowUiNotify(ctx, `Custom compaction auth failed for ${provider}/${modelId}: ${authError}; using Pi default compaction.`, "warning");
|
|
16148
16324
|
return;
|
|
16149
16325
|
}
|
|
16150
16326
|
if (!auth.apiKey) {
|
|
16151
16327
|
rememberCustomCompactionStatus(`fallback to Pi default: no API key for ${provider}/${modelId}`);
|
|
16152
|
-
ctx
|
|
16328
|
+
workflowUiNotify(ctx, `No API key for custom compaction model ${provider}/${modelId}; using Pi default compaction.`, "warning");
|
|
16153
16329
|
return;
|
|
16154
16330
|
}
|
|
16155
16331
|
|
|
@@ -16161,14 +16337,14 @@ Pi Version: v${VERSION}
|
|
|
16161
16337
|
const fitNote = fitted.adjusted && fitted.safeInputTokens
|
|
16162
16338
|
? ` Adaptive fit: summarizing about ${Math.round(fitted.inputTokens).toLocaleString()} tokens within ${Math.round(fitted.safeInputTokens).toLocaleString()} safe input tokens for the compaction model.`
|
|
16163
16339
|
: "";
|
|
16164
|
-
ctx
|
|
16340
|
+
workflowUiNotify(ctx, `Custom compaction using ${provider}/${modelId}. Keep recent: ${customCompactionKeepRecentTokens(settings).toLocaleString()} tokens; reserve: ${customCompactionReserveTokens(settings).toLocaleString()} tokens.${fitNote}`, "info");
|
|
16165
16341
|
const result = await compactionApi.compact(fitted.preparation, model, auth.apiKey, auth.headers, event.customInstructions, event.signal);
|
|
16166
16342
|
rememberCustomCompactionStatus(`custom compaction succeeded using ${provider}/${modelId}${fitted.adjusted ? " with adaptive context fit" : ""}`);
|
|
16167
16343
|
return { compaction: result };
|
|
16168
16344
|
} catch (error) {
|
|
16169
16345
|
const message = error instanceof Error ? error.message : String(error);
|
|
16170
16346
|
rememberCustomCompactionStatus(`fallback to Pi default: custom compaction failed for ${provider}/${modelId}: ${message}`);
|
|
16171
|
-
if (!event.signal.aborted) ctx
|
|
16347
|
+
if (!event.signal.aborted) workflowUiNotify(ctx, `Custom compaction failed: ${message}; using Pi default compaction.`, "warning");
|
|
16172
16348
|
return;
|
|
16173
16349
|
}
|
|
16174
16350
|
});
|
|
@@ -16607,48 +16783,55 @@ Pi Version: v${VERSION}
|
|
|
16607
16783
|
pi.registerCommand("m retry", { description: "Retry validation repair flow for current mission.", handler: async (_args, ctx) => handleMissionCommand("retry", ctx) });
|
|
16608
16784
|
pi.registerCommand("m revalidate", { description: "Revalidate current mission milestone.", handler: async (_args, ctx) => handleMissionCommand("revalidate", ctx) });
|
|
16609
16785
|
|
|
16786
|
+
const workflowShortcutHandlers: Record<WorkflowShortcutActionId, (ctx: ExtensionContext) => Promise<void> | void> = {
|
|
16787
|
+
"workflow.widget.top.toggle": async (ctx) => {
|
|
16788
|
+
if (workflowWidgetUi(loadGlobalSettings()).enableWidgetShortcuts === false) { workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd), "Top:disabled"); return; }
|
|
16789
|
+
const slot = activeTopWidgetSlot();
|
|
16790
|
+
if (!slot) { workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd)); return; }
|
|
16791
|
+
toggleWorkflowWidget(ctx, slot);
|
|
16792
|
+
setWorkflowWidgetShortcutStatus(ctx, slot);
|
|
16793
|
+
},
|
|
16794
|
+
"workflow.widget.bottom.toggle": async (ctx) => {
|
|
16795
|
+
if (workflowWidgetUi(loadGlobalSettings()).enableWidgetShortcuts === false) { workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd), "Bottom:disabled"); return; }
|
|
16796
|
+
if (isPlanWorkflowUiMode(state) && planBottomRelevant(state)) {
|
|
16797
|
+
toggleWorkflowWidget(ctx, "planBottom");
|
|
16798
|
+
return setWorkflowWidgetShortcutStatus(ctx, "planBottom");
|
|
16799
|
+
}
|
|
16800
|
+
if (isMissionWorkflowMode(state) && missionBottomRelevant(state, activeMissionForUi(state))) {
|
|
16801
|
+
toggleWorkflowWidget(ctx, "missionBottom");
|
|
16802
|
+
return setWorkflowWidgetShortcutStatus(ctx, "missionBottom");
|
|
16803
|
+
}
|
|
16804
|
+
if (isStandardWorkflowMode(state)) {
|
|
16805
|
+
toggleWorkflowWidget(ctx, "standardBottom");
|
|
16806
|
+
return setWorkflowWidgetShortcutStatus(ctx, "standardBottom");
|
|
16807
|
+
}
|
|
16808
|
+
workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd)); return;
|
|
16809
|
+
},
|
|
16810
|
+
"workflow.presets.cycle": async (ctx) => {
|
|
16811
|
+
if (workflowWidgetUi(loadGlobalSettings()).enableWidgetShortcuts === false) { workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd), "Preset:disabled"); return; }
|
|
16812
|
+
if (!isPlanWorkflowUiMode(state) && !isMissionWorkflowMode(state) && !isStandardWorkflowMode(state)) { workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd)); return; }
|
|
16813
|
+
await cycleWorkflowPreset(ctx, 1);
|
|
16814
|
+
},
|
|
16815
|
+
"workflow.standard.toggle": async (ctx) => {
|
|
16816
|
+
if (isStandardWorkflowMode(state)) return exitStandardModeToIdle(ctx);
|
|
16817
|
+
await enterStandardMode(ctx);
|
|
16818
|
+
},
|
|
16819
|
+
"workflow.plan.toggle": async (ctx) => {
|
|
16820
|
+
if (isPlanWorkflowUiMode(state)) return exitPlanModeToIdle(ctx);
|
|
16821
|
+
await enterPlanModeAwaitingInput(ctx);
|
|
16822
|
+
},
|
|
16823
|
+
"workflow.mission.toggle": async (ctx) => {
|
|
16824
|
+
if (isMissionWorkflowMode(state)) return exitMissionModeToIdle(ctx);
|
|
16825
|
+
await enterMissionModeAwaitingInput(ctx);
|
|
16826
|
+
},
|
|
16827
|
+
};
|
|
16610
16828
|
|
|
16611
|
-
|
|
16612
|
-
|
|
16613
|
-
|
|
16614
|
-
|
|
16615
|
-
|
|
16616
|
-
|
|
16617
|
-
setWorkflowWidgetShortcutStatus(ctx, slot);
|
|
16618
|
-
}});
|
|
16619
|
-
pi.registerShortcut("ctrl+shift+b", { description: "Toggle active Plan/Mission/Standard bottom workflow widget", handler: async (ctx) => {
|
|
16620
|
-
if (workflowWidgetUi(loadGlobalSettings()).enableWidgetShortcuts === false) { workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd), "Bottom:disabled"); return; }
|
|
16621
|
-
if (isPlanWorkflowUiMode(state) && planBottomRelevant(state)) {
|
|
16622
|
-
toggleWorkflowWidget(ctx, "planBottom");
|
|
16623
|
-
return setWorkflowWidgetShortcutStatus(ctx, "planBottom");
|
|
16624
|
-
}
|
|
16625
|
-
if (isMissionWorkflowMode(state) && missionBottomRelevant(state, activeMissionForUi(state))) {
|
|
16626
|
-
toggleWorkflowWidget(ctx, "missionBottom");
|
|
16627
|
-
return setWorkflowWidgetShortcutStatus(ctx, "missionBottom");
|
|
16628
|
-
}
|
|
16629
|
-
if (isStandardWorkflowMode(state)) {
|
|
16630
|
-
toggleWorkflowWidget(ctx, "standardBottom");
|
|
16631
|
-
return setWorkflowWidgetShortcutStatus(ctx, "standardBottom");
|
|
16632
|
-
}
|
|
16633
|
-
workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd)); return;
|
|
16634
|
-
}});
|
|
16635
|
-
pi.registerShortcut("ctrl+shift+u", { description: "Cycle workflow presets during Plan/Mission/Standard Mode", handler: async (ctx) => {
|
|
16636
|
-
if (workflowWidgetUi(loadGlobalSettings()).enableWidgetShortcuts === false) { workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd), "Preset:disabled"); return; }
|
|
16637
|
-
if (!isPlanWorkflowUiMode(state) && !isMissionWorkflowMode(state) && !isStandardWorkflowMode(state)) { workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd)); return; }
|
|
16638
|
-
await cycleWorkflowPreset(ctx, 1);
|
|
16639
|
-
}});
|
|
16640
|
-
pi.registerShortcut("ctrl+shift+s", { description: "Toggle Standard Mode", handler: async (ctx) => {
|
|
16641
|
-
if (isStandardWorkflowMode(state)) return exitStandardModeToIdle(ctx);
|
|
16642
|
-
await enterStandardMode(ctx);
|
|
16643
|
-
}});
|
|
16644
|
-
pi.registerShortcut("ctrl+shift+l", { description: "Enter Plan Mode", handler: async (ctx) => {
|
|
16645
|
-
if (isPlanWorkflowUiMode(state)) return exitPlanModeToIdle(ctx);
|
|
16646
|
-
await enterPlanModeAwaitingInput(ctx);
|
|
16647
|
-
}});
|
|
16648
|
-
pi.registerShortcut("ctrl+shift+m", { description: "Toggle Mission Mode", handler: async (ctx) => {
|
|
16649
|
-
if (isMissionWorkflowMode(state)) return exitMissionModeToIdle(ctx);
|
|
16650
|
-
await enterMissionModeAwaitingInput(ctx);
|
|
16651
|
-
}});
|
|
16829
|
+
for (const shortcut of WORKFLOW_SHORTCUTS) {
|
|
16830
|
+
pi.registerShortcut(workflowShortcutKey(shortcut.id), {
|
|
16831
|
+
description: shortcut.description,
|
|
16832
|
+
handler: workflowShortcutHandlers[shortcut.id],
|
|
16833
|
+
});
|
|
16834
|
+
}
|
|
16652
16835
|
|
|
16653
16836
|
const handleWorkflowPlansCommand = async (args: string, _ctx: ExtensionContext): Promise<void> => {
|
|
16654
16837
|
const parts = args.trim().split(/\s+/).filter(Boolean);
|
|
@@ -17025,6 +17208,14 @@ Pi Version: v${VERSION}
|
|
|
17025
17208
|
setWorkflowUi(ctx, state, activeSubagents);
|
|
17026
17209
|
return show(pi, updatedMessage(result.scope, result.file, `ui.${key}`, String(bool)));
|
|
17027
17210
|
}
|
|
17211
|
+
if (subject === "ui" && key === "editorHintContrast") {
|
|
17212
|
+
const contrast = parseEditorHintContrast(value);
|
|
17213
|
+
if (!contrast) return show(pi, "# Error\n\nUsage: `/workflow-settings set ui editorHintContrast <subtle|normal|bright|high>`");
|
|
17214
|
+
const result = updateSettings(ctx.cwd, scope ?? "global", (s) => { workflowWidgetUi(s).editorHintContrast = contrast; });
|
|
17215
|
+
setWorkflowUi(ctx, state, activeSubagents);
|
|
17216
|
+
workflowEditorHintText = workflowEditorHintTextFor(state, loadWorkflowSettings(ctx.cwd));
|
|
17217
|
+
return show(pi, updatedMessage(result.scope, result.file, "ui.editorHintContrast", contrast));
|
|
17218
|
+
}
|
|
17028
17219
|
if (subject === "subagents" && (key === "enabled" || key === "activityIndicatorEnabled" || key === "autoUseDuringPlanning" || key === "autoUseDuringExecution" || key === "autoUseDuringRepair" || key === "autoUseDuringReview" || key === "autoUseDuringValidation" || key === "allowParallelReadOnly" || key === "allowParallelPlanning" || key === "allowParallelExecution" || key === "allowParallelRepair" || key === "allowParallelReview" || key === "allowParallelValidation" || key === "allowParallelEdits" || key === "requireParallelEditConflictProtection" || key === "allowBackgroundSubagents")) {
|
|
17029
17220
|
if (bool === undefined) return show(pi, "# Error\n\nUsage: `/workflow-settings set subagents <enabled|activityIndicatorEnabled|autoUseDuringPlanning|autoUseDuringExecution|autoUseDuringRepair|autoUseDuringReview|autoUseDuringValidation|allowParallelReadOnly|allowParallelPlanning|allowParallelExecution|allowParallelRepair|allowParallelReview|allowParallelValidation|allowParallelEdits|requireParallelEditConflictProtection> <true|false>`");
|
|
17030
17221
|
const result = updateSettings(ctx.cwd, scope, (s) => {
|