@wrongstack/tui 0.291.0 → 0.291.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app-initial-state.d.ts +2 -0
- package/dist/app-initial-state.d.ts.map +1 -1
- package/dist/app-props.d.ts +2 -0
- package/dist/app-props.d.ts.map +1 -1
- package/dist/app.d.ts +1 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/components/history/banner.d.ts.map +1 -1
- package/dist/components/history/types.d.ts +3 -0
- package/dist/components/history/types.d.ts.map +1 -1
- package/dist/components/scrollable-history.d.ts.map +1 -1
- package/dist/components/statusline-picker.d.ts.map +1 -1
- package/dist/index.js +999 -22
- package/dist/index.js.map +4 -4
- package/dist/input-validation.d.ts +263 -0
- package/dist/input-validation.d.ts.map +1 -0
- package/dist/run-tui.d.ts +2 -0
- package/dist/run-tui.d.ts.map +1 -1
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -617,6 +617,7 @@ function createInitialState(options) {
|
|
|
617
617
|
family,
|
|
618
618
|
keyTail,
|
|
619
619
|
sessionId,
|
|
620
|
+
profile,
|
|
620
621
|
autonomyAgents,
|
|
621
622
|
restoredEntries,
|
|
622
623
|
restoredCheckpoints,
|
|
@@ -639,6 +640,7 @@ function createInitialState(options) {
|
|
|
639
640
|
family,
|
|
640
641
|
keyTail,
|
|
641
642
|
sessionId,
|
|
643
|
+
profile,
|
|
642
644
|
autonomyAgents
|
|
643
645
|
}
|
|
644
646
|
] : [],
|
|
@@ -2677,23 +2679,20 @@ var ITEM_LINE = {
|
|
|
2677
2679
|
time: 1,
|
|
2678
2680
|
tokens: 1,
|
|
2679
2681
|
version: 1,
|
|
2680
|
-
working_dir: 1,
|
|
2681
2682
|
yolo: 1,
|
|
2682
|
-
// Line 2 — session context:
|
|
2683
|
-
//
|
|
2684
|
-
// runtime counters and is more useful grouped alongside session-context
|
|
2685
|
-
// chips that the user inspects together when something goes wrong.
|
|
2683
|
+
// Line 2 — session context: workdir/project first, then mode, git, goals,
|
|
2684
|
+
// memory pressure (RAM/heap), countdowns, tools.
|
|
2686
2685
|
auto_proceed: 2,
|
|
2687
2686
|
eternal_stage: 2,
|
|
2688
2687
|
git: 2,
|
|
2689
2688
|
goal: 2,
|
|
2690
2689
|
memory: 2,
|
|
2691
2690
|
mode: 2,
|
|
2692
|
-
project:
|
|
2693
|
-
// kept on line 1 by render parity — see comment near project
|
|
2691
|
+
project: 2,
|
|
2694
2692
|
sessions: 2,
|
|
2695
2693
|
token_saving: 2,
|
|
2696
2694
|
tools: 2,
|
|
2695
|
+
working_dir: 2,
|
|
2697
2696
|
// Line 3 — active work + connectivity
|
|
2698
2697
|
brain: 3,
|
|
2699
2698
|
debug_stream: 3,
|
|
@@ -2719,15 +2718,15 @@ var STATUSLINE_ITEMS = [
|
|
|
2719
2718
|
"index",
|
|
2720
2719
|
"model",
|
|
2721
2720
|
"processes",
|
|
2722
|
-
"project",
|
|
2723
2721
|
"queue",
|
|
2724
2722
|
"state",
|
|
2725
2723
|
"time",
|
|
2726
2724
|
"tokens",
|
|
2727
2725
|
"version",
|
|
2728
|
-
"working_dir",
|
|
2729
2726
|
"yolo",
|
|
2730
|
-
// Line 2
|
|
2727
|
+
// Line 2 — workdir/project first, then session context
|
|
2728
|
+
"project",
|
|
2729
|
+
"working_dir",
|
|
2731
2730
|
"auto_proceed",
|
|
2732
2731
|
"eternal_stage",
|
|
2733
2732
|
"git",
|
|
@@ -6062,7 +6061,6 @@ function StatusBar({
|
|
|
6062
6061
|
" process",
|
|
6063
6062
|
processCount === 1 ? "" : "es"
|
|
6064
6063
|
] }) : null,
|
|
6065
|
-
memoryStatusChip,
|
|
6066
6064
|
hint && showChip("hint") ? /* @__PURE__ */ jsx9(Text, { dimColor: !isNoColor, children: hint }) : null,
|
|
6067
6065
|
indexState?.indexing && showChip("index") ? /* @__PURE__ */ jsxs8(Text, { color: isNoColor ? void 0 : theme.warn, children: [
|
|
6068
6066
|
glyphs.index,
|
|
@@ -6086,7 +6084,7 @@ function StatusBar({
|
|
|
6086
6084
|
})() : null
|
|
6087
6085
|
].filter((chip) => chip !== null);
|
|
6088
6086
|
const modeChips = [
|
|
6089
|
-
// Line 1 runtime chips: YOLO, autonomy,
|
|
6087
|
+
// Line 1 runtime chips: YOLO, autonomy, provider/model,
|
|
6090
6088
|
// then the context meter and remaining runtime details.
|
|
6091
6089
|
yolo && showChip("yolo") ? /* @__PURE__ */ jsx9(Text, { color: chipColor(theme.error, isNoColor), bold: true, children: isNoColor ? "YOLO" : `${glyphs.warning} YOLO` }) : null,
|
|
6092
6090
|
autonomy && autonomy !== "off" && showChip("autonomy") ? /* @__PURE__ */ jsx9(
|
|
@@ -6100,8 +6098,6 @@ function StatusBar({
|
|
|
6100
6098
|
children: isNoColor ? autonomy.toUpperCase() : `\u221E ${autonomy.toUpperCase()}`
|
|
6101
6099
|
}
|
|
6102
6100
|
) : null,
|
|
6103
|
-
projectName && showChip("project") ? /* @__PURE__ */ jsx9(Text, { color: chipColor(theme.accent, isNoColor), children: isNoColor ? truncateChip(projectName, 24) : `${glyphs.folder} ${truncateChip(projectName, 24)}` }) : null,
|
|
6104
|
-
workingDir && showChip("working_dir") ? /* @__PURE__ */ jsx9(Text, { color: chipColor(theme.accent, isNoColor), children: isNoColor ? truncateChip(workingDir, 28) : `${glyphs.workingDirectory} ${truncateChip(workingDir, 28)}` }) : null,
|
|
6105
6101
|
modelStatusChip,
|
|
6106
6102
|
...primaryChips,
|
|
6107
6103
|
stateStatusChip,
|
|
@@ -6255,6 +6251,8 @@ function StatusBar({
|
|
|
6255
6251
|
PowerlineRail,
|
|
6256
6252
|
{
|
|
6257
6253
|
segments: [
|
|
6254
|
+
projectName && showChip("project") ? /* @__PURE__ */ jsx9(Text, { color: chipColor(theme.accent, isNoColor), children: isNoColor ? truncateChip(projectName, 24) : `${glyphs.folder} ${truncateChip(projectName, 24)}` }) : null,
|
|
6255
|
+
workingDir && showChip("working_dir") ? /* @__PURE__ */ jsx9(Text, { color: chipColor(theme.accent, isNoColor), children: isNoColor ? truncateChip(workingDir, 28) : `${glyphs.workingDirectory} ${truncateChip(workingDir, 28)}` }) : null,
|
|
6258
6256
|
git && showChip("git") ? /* @__PURE__ */ jsxs8(Text, { children: [
|
|
6259
6257
|
/* @__PURE__ */ jsxs8(Text, { color: theme.monitor.agents, children: [
|
|
6260
6258
|
glyphs.gitBranch,
|
|
@@ -6274,7 +6272,8 @@ function StatusBar({
|
|
|
6274
6272
|
sessionCount != null && sessionCount > 0 && showChip("sessions") ? /* @__PURE__ */ jsx9(Text, { color: isNoColor ? void 0 : theme.accent, children: isNoColor ? `${sessionCount} session${sessionCount === 1 ? "" : "s"}` : `${glyphs.sessions} ${sessionCount} session${sessionCount === 1 ? "" : "s"}` }) : null,
|
|
6275
6273
|
toolCount != null && showChip("tools") ? /* @__PURE__ */ jsx9(Text, { color: isNoColor ? void 0 : theme.accent, children: isNoColor ? `${toolCount} tool${toolCount === 1 ? "" : "s"}` : `${glyphs.tools} ${toolCount} tool${toolCount === 1 ? "" : "s"}` }) : null,
|
|
6276
6274
|
tokenSavingMode !== void 0 && tokenSavingMode !== "off" && showChip("token_saving") ? /* @__PURE__ */ jsx9(Text, { color: isNoColor ? void 0 : theme.warn, bold: true, children: isNoColor ? tokenSavingMode : `${glyphs.save} ${tokenSavingMode}` }) : null,
|
|
6277
|
-
sideEffectCount > 0 ? /* @__PURE__ */ jsx9(Text, { color: isNoColor ? void 0 : theme.warn, children: isNoColor ? `${sideEffectCount} audit${sideEffectCount === 1 ? "" : "s"}` : `${glyphs.audit} ${sideEffectCount} audit${sideEffectCount === 1 ? "" : "s"}` }) : null
|
|
6275
|
+
sideEffectCount > 0 ? /* @__PURE__ */ jsx9(Text, { color: isNoColor ? void 0 : theme.warn, children: isNoColor ? `${sideEffectCount} audit${sideEffectCount === 1 ? "" : "s"}` : `${glyphs.audit} ${sideEffectCount} audit${sideEffectCount === 1 ? "" : "s"}` }) : null,
|
|
6276
|
+
memoryStatusChip
|
|
6278
6277
|
].filter((c) => c !== null),
|
|
6279
6278
|
budget: Math.max(12, termWidth),
|
|
6280
6279
|
monochrome: isNoColor,
|
|
@@ -15356,7 +15355,18 @@ function Banner({
|
|
|
15356
15355
|
contentWidth,
|
|
15357
15356
|
compact
|
|
15358
15357
|
}
|
|
15359
|
-
)
|
|
15358
|
+
),
|
|
15359
|
+
entry.profile ? /* @__PURE__ */ jsx40(
|
|
15360
|
+
InfoRow,
|
|
15361
|
+
{
|
|
15362
|
+
icon: "\u2699",
|
|
15363
|
+
label: "profile",
|
|
15364
|
+
value: entry.profile,
|
|
15365
|
+
contentWidth,
|
|
15366
|
+
compact,
|
|
15367
|
+
accent: true
|
|
15368
|
+
}
|
|
15369
|
+
) : null
|
|
15360
15370
|
] }),
|
|
15361
15371
|
/* @__PURE__ */ jsx40(Footer, { contentWidth, compact }),
|
|
15362
15372
|
entry.autonomyAgents && entry.autonomyAgents.length > 0 ? /* @__PURE__ */ jsx40(
|
|
@@ -16515,6 +16525,957 @@ var Input = memo2(function Input2({
|
|
|
16515
16525
|
] });
|
|
16516
16526
|
});
|
|
16517
16527
|
|
|
16528
|
+
// src/input-validation.ts
|
|
16529
|
+
var MAX_INPUT_BUFFER_CHARS = 1e5;
|
|
16530
|
+
var MAX_ENTRY_TEXT_CHARS = 5e5;
|
|
16531
|
+
var MAX_HISTORY_ENTRIES = 400;
|
|
16532
|
+
var MAX_BATCHED_ACTIONS = 500;
|
|
16533
|
+
var MAX_ACTION_STRING_FIELD = 1e4;
|
|
16534
|
+
var MAX_FLEET_ENTRIES = 200;
|
|
16535
|
+
var MAX_ACTION_DEPTH = 8;
|
|
16536
|
+
var MAX_HOST_STRING_FIELD = 500;
|
|
16537
|
+
var MAX_PICKER_MATCHES = 500;
|
|
16538
|
+
var ALLOWED_ACTION_TYPES = [
|
|
16539
|
+
"addEntry",
|
|
16540
|
+
"compactHistory",
|
|
16541
|
+
"setBuffer",
|
|
16542
|
+
"clearInput",
|
|
16543
|
+
"clearHistory",
|
|
16544
|
+
"replaceHistory",
|
|
16545
|
+
"replaceEntry",
|
|
16546
|
+
"historyRoll",
|
|
16547
|
+
"setHistoryIndex",
|
|
16548
|
+
"setHistoryDraft",
|
|
16549
|
+
"scrollBy",
|
|
16550
|
+
"scrollTo",
|
|
16551
|
+
"scrollPage",
|
|
16552
|
+
"scrollToBottom",
|
|
16553
|
+
"scrollToTop",
|
|
16554
|
+
"setMeasuredLines",
|
|
16555
|
+
"setViewportRows",
|
|
16556
|
+
"pickerOpen",
|
|
16557
|
+
"pickerMove",
|
|
16558
|
+
"pickerClose",
|
|
16559
|
+
"pickerQuery",
|
|
16560
|
+
"pickerSetMatches",
|
|
16561
|
+
"slashPickerOpen",
|
|
16562
|
+
"slashPickerMove",
|
|
16563
|
+
"slashPickerClose",
|
|
16564
|
+
"slashPickerQuery",
|
|
16565
|
+
"slashPickerSetMatches",
|
|
16566
|
+
"modelPickerOpen",
|
|
16567
|
+
"modelPickerMove",
|
|
16568
|
+
"modelPickerClose",
|
|
16569
|
+
"modelPickerSelect",
|
|
16570
|
+
"modelPickerSetProviders",
|
|
16571
|
+
"autonomyPickerOpen",
|
|
16572
|
+
"autonomyPickerMove",
|
|
16573
|
+
"autonomyPickerClose",
|
|
16574
|
+
"autonomyPickerSelect",
|
|
16575
|
+
"cancelSend",
|
|
16576
|
+
"submit",
|
|
16577
|
+
"afterSubmit",
|
|
16578
|
+
"streamStart",
|
|
16579
|
+
"streamToken",
|
|
16580
|
+
"streamToolUse",
|
|
16581
|
+
"streamToolResult",
|
|
16582
|
+
"streamEnd",
|
|
16583
|
+
"setMode",
|
|
16584
|
+
"toggleHelp",
|
|
16585
|
+
"toggleMonitor",
|
|
16586
|
+
"toggleAgentsMonitor",
|
|
16587
|
+
"toggleTodosMonitor",
|
|
16588
|
+
"toggleQueuePanel",
|
|
16589
|
+
"toggleProcessList",
|
|
16590
|
+
"toggleCronMonitor",
|
|
16591
|
+
"toggleAuditPanel",
|
|
16592
|
+
"togglePlanPanel",
|
|
16593
|
+
"closeAllPanels",
|
|
16594
|
+
"toggleKanbanPanel",
|
|
16595
|
+
"toggleGoalPanel",
|
|
16596
|
+
"toggleGoalKanbanPanel",
|
|
16597
|
+
"toggleContextPanel",
|
|
16598
|
+
"toggleSessionsPanel",
|
|
16599
|
+
"sessionsPanelSet",
|
|
16600
|
+
"sessionsPanelMove",
|
|
16601
|
+
"sessionsPanelBusy",
|
|
16602
|
+
"sessionResumeConfirmSet",
|
|
16603
|
+
"sessionResumeConfirmClear",
|
|
16604
|
+
"settingsPickerOpen",
|
|
16605
|
+
"settingsPickerMove",
|
|
16606
|
+
"settingsPickerClose",
|
|
16607
|
+
"settingsPick",
|
|
16608
|
+
"statuslinePickerOpen",
|
|
16609
|
+
"statuslinePickerMove",
|
|
16610
|
+
"statuslinePickerClose",
|
|
16611
|
+
"pluginPickerOpen",
|
|
16612
|
+
"pluginPickerMove",
|
|
16613
|
+
"pluginPickerClose",
|
|
16614
|
+
"mcpPickerOpen",
|
|
16615
|
+
"mcpPickerMove",
|
|
16616
|
+
"mcpPickerClose",
|
|
16617
|
+
"toolsPickerOpen",
|
|
16618
|
+
"toolsPickerMove",
|
|
16619
|
+
"toolsPickerClose",
|
|
16620
|
+
"projectPickerOpen",
|
|
16621
|
+
"projectPickerMove",
|
|
16622
|
+
"projectPickerClose",
|
|
16623
|
+
"projectPickerSelect",
|
|
16624
|
+
"projectPickerSetItems",
|
|
16625
|
+
"fKeyPickerOpen",
|
|
16626
|
+
"fKeyPickerMove",
|
|
16627
|
+
"fKeyPickerClose",
|
|
16628
|
+
"confirmPromptOpen",
|
|
16629
|
+
"confirmPromptClose",
|
|
16630
|
+
"clearConfirmOpen",
|
|
16631
|
+
"clearConfirmClose",
|
|
16632
|
+
"clearConfirmSetValue",
|
|
16633
|
+
"exitConfirmOpen",
|
|
16634
|
+
"exitConfirmClose",
|
|
16635
|
+
"slashConfirmOpen",
|
|
16636
|
+
"slashConfirmClose",
|
|
16637
|
+
"escConfirmOpen",
|
|
16638
|
+
"escConfirmClose",
|
|
16639
|
+
"sendModePickerOpen",
|
|
16640
|
+
"sendModePickerMove",
|
|
16641
|
+
"sendModePickerClose",
|
|
16642
|
+
"resetContextChip",
|
|
16643
|
+
"fleetSeed",
|
|
16644
|
+
"fleetSpawn",
|
|
16645
|
+
"fleetToolStart",
|
|
16646
|
+
"fleetToolEnd",
|
|
16647
|
+
"fleetStart",
|
|
16648
|
+
"fleetDelta",
|
|
16649
|
+
"fleetMessage",
|
|
16650
|
+
"fleetTool",
|
|
16651
|
+
"fleetUsage",
|
|
16652
|
+
"fleetDone",
|
|
16653
|
+
"fleetRemove",
|
|
16654
|
+
"fleetBudgetWarning",
|
|
16655
|
+
"fleetBudgetExtended",
|
|
16656
|
+
"fleetCtxPct",
|
|
16657
|
+
"fleetCost",
|
|
16658
|
+
"fleetConcurrency",
|
|
16659
|
+
"fleetBatch",
|
|
16660
|
+
"leaderIterStart",
|
|
16661
|
+
"leaderIterEnd",
|
|
16662
|
+
"leaderToolStart",
|
|
16663
|
+
"leaderToolEnd",
|
|
16664
|
+
"leaderCtxPct",
|
|
16665
|
+
"setFleetChat",
|
|
16666
|
+
"enhanceOpen",
|
|
16667
|
+
"enhanceClose",
|
|
16668
|
+
"enhanceBusy",
|
|
16669
|
+
"enhanceBusyDone",
|
|
16670
|
+
"enhanceResult",
|
|
16671
|
+
"enhanceCancel",
|
|
16672
|
+
"enhanceDismiss",
|
|
16673
|
+
"refineFailureOpen",
|
|
16674
|
+
"refineFailureClose",
|
|
16675
|
+
"continueConfirmOpen",
|
|
16676
|
+
"continueConfirmClose",
|
|
16677
|
+
"checkpointReceived",
|
|
16678
|
+
"rewindOverlayOpen",
|
|
16679
|
+
"rewindOverlayClose",
|
|
16680
|
+
"rewindOverlayMove",
|
|
16681
|
+
"setDeadline",
|
|
16682
|
+
"setLiveProvider",
|
|
16683
|
+
"setLiveModel",
|
|
16684
|
+
"setCapability",
|
|
16685
|
+
"setDesignKit",
|
|
16686
|
+
"setAnimationStyle",
|
|
16687
|
+
"setEffectiveMaxContext",
|
|
16688
|
+
"setStreamingText",
|
|
16689
|
+
"setToolStream",
|
|
16690
|
+
"toolStreamClear",
|
|
16691
|
+
"setThinkingWord",
|
|
16692
|
+
"setFleetVerbosity",
|
|
16693
|
+
"setAutonomyMode",
|
|
16694
|
+
"setSendMode",
|
|
16695
|
+
"setSteering",
|
|
16696
|
+
"setSteeringPending",
|
|
16697
|
+
"clearSteering",
|
|
16698
|
+
"setGoalText",
|
|
16699
|
+
"setGoalPanelGoal",
|
|
16700
|
+
"showGoal",
|
|
16701
|
+
"goalSummary",
|
|
16702
|
+
"goalRunInit",
|
|
16703
|
+
"goalRunPhaseUpdate",
|
|
16704
|
+
"goalRunRunningPhases",
|
|
16705
|
+
"goalRunElapsed",
|
|
16706
|
+
"goalRunTaskActive",
|
|
16707
|
+
"goalRunMonitorToggle",
|
|
16708
|
+
"goalRunReset",
|
|
16709
|
+
"sddBoardSnapshot",
|
|
16710
|
+
"toggleSddBoardMonitor",
|
|
16711
|
+
"sddBoardFocusNext",
|
|
16712
|
+
"sddBoardFocusPrev",
|
|
16713
|
+
"worktreeUpsert",
|
|
16714
|
+
"worktreeRemove",
|
|
16715
|
+
"toggleWorktreeMonitor",
|
|
16716
|
+
"collabBugFound",
|
|
16717
|
+
"collabPlanEmitted",
|
|
16718
|
+
"collabEvalComplete",
|
|
16719
|
+
"collabSessionDone",
|
|
16720
|
+
"collabSubagentSpawned",
|
|
16721
|
+
"debugStreamStats",
|
|
16722
|
+
"debugStreamStatsClear",
|
|
16723
|
+
"countdownTick",
|
|
16724
|
+
"countdownEnded",
|
|
16725
|
+
"coordinatorEvent",
|
|
16726
|
+
"toggleCoordinatorMonitor",
|
|
16727
|
+
"setEnhancedPrompt",
|
|
16728
|
+
"enhanceConfirmOpen",
|
|
16729
|
+
"enhanceConfirmClose",
|
|
16730
|
+
"setShowModelReasoning"
|
|
16731
|
+
];
|
|
16732
|
+
var TEXT_BEARING_ENTRY_KINDS = /* @__PURE__ */ new Set([
|
|
16733
|
+
"user",
|
|
16734
|
+
"assistant",
|
|
16735
|
+
"thinking",
|
|
16736
|
+
"info",
|
|
16737
|
+
"warn",
|
|
16738
|
+
"error",
|
|
16739
|
+
"turn-summary"
|
|
16740
|
+
]);
|
|
16741
|
+
var ALLOWED_ENTRY_KINDS = /* @__PURE__ */ new Set([
|
|
16742
|
+
...TEXT_BEARING_ENTRY_KINDS,
|
|
16743
|
+
"tool",
|
|
16744
|
+
"banner",
|
|
16745
|
+
"divider"
|
|
16746
|
+
]);
|
|
16747
|
+
var ALLOWED_SCROLL_DIRS = /* @__PURE__ */ new Set(["up", "down"]);
|
|
16748
|
+
var ALLOWED_AUTONOMY_MODES = /* @__PURE__ */ new Set([
|
|
16749
|
+
"off",
|
|
16750
|
+
"suggest",
|
|
16751
|
+
"auto",
|
|
16752
|
+
"eternal",
|
|
16753
|
+
"eternal-parallel"
|
|
16754
|
+
]);
|
|
16755
|
+
var ALLOWED_SEND_MODES = /* @__PURE__ */ new Set(["queue", "steer", "btw", "direct"]);
|
|
16756
|
+
var ALLOWED_FLEET_CHAT_MODES = /* @__PURE__ */ new Set(["off", "concise", "full"]);
|
|
16757
|
+
var ALLOWED_COLLAB_VERDICTS = /* @__PURE__ */ new Set(["approve", "needs_revision", "reject"]);
|
|
16758
|
+
var ALLOWED_CAPABILITY_FIELDS = /* @__PURE__ */ new Set([
|
|
16759
|
+
"colorDepth",
|
|
16760
|
+
"mouseProtocol",
|
|
16761
|
+
"supportsTitle"
|
|
16762
|
+
]);
|
|
16763
|
+
function validateAction(action) {
|
|
16764
|
+
const type = String(action.type);
|
|
16765
|
+
const typeAllowed = ALLOWED_ACTION_TYPES.includes(type);
|
|
16766
|
+
if (!typeAllowed) {
|
|
16767
|
+
return {
|
|
16768
|
+
valid: false,
|
|
16769
|
+
error: `action.type: "${type}" is not on the allow-list.`
|
|
16770
|
+
};
|
|
16771
|
+
}
|
|
16772
|
+
const normalized = normalizeActionType(type);
|
|
16773
|
+
if (!normalized) {
|
|
16774
|
+
return { valid: false, error: `action.type: "${type}" normalized to empty.` };
|
|
16775
|
+
}
|
|
16776
|
+
const payload = { ...action, type: normalized };
|
|
16777
|
+
const depth = measureDepth(payload, 0);
|
|
16778
|
+
if (depth > MAX_ACTION_DEPTH) {
|
|
16779
|
+
return {
|
|
16780
|
+
valid: false,
|
|
16781
|
+
error: `action: payload nesting depth ${depth} exceeds max ${MAX_ACTION_DEPTH}.`
|
|
16782
|
+
};
|
|
16783
|
+
}
|
|
16784
|
+
for (const [k, v] of Object.entries(payload)) {
|
|
16785
|
+
if (k === "actions") continue;
|
|
16786
|
+
if (typeof v === "string" && v.length > MAX_ACTION_STRING_FIELD) {
|
|
16787
|
+
return {
|
|
16788
|
+
valid: false,
|
|
16789
|
+
error: `action.${k}: string exceeds ${MAX_ACTION_STRING_FIELD.toLocaleString()} chars (got ${v.length}).`
|
|
16790
|
+
};
|
|
16791
|
+
}
|
|
16792
|
+
}
|
|
16793
|
+
switch (normalized) {
|
|
16794
|
+
// ── Buffer/input mutations ──────────────────────────────────────
|
|
16795
|
+
case "setBuffer": {
|
|
16796
|
+
const buf = String(action.buffer ?? "");
|
|
16797
|
+
if (buf.length > MAX_INPUT_BUFFER_CHARS) {
|
|
16798
|
+
return {
|
|
16799
|
+
valid: false,
|
|
16800
|
+
error: `setBuffer.buffer: exceeds ${MAX_INPUT_BUFFER_CHARS.toLocaleString()} chars (got ${buf.length}).`
|
|
16801
|
+
};
|
|
16802
|
+
}
|
|
16803
|
+
const cursor = Number(action.cursor);
|
|
16804
|
+
if (!Number.isInteger(cursor) || cursor < 0 || cursor > buf.length) {
|
|
16805
|
+
return {
|
|
16806
|
+
valid: false,
|
|
16807
|
+
error: `setBuffer.cursor: ${action.cursor} out of range [0, ${buf.length}].`
|
|
16808
|
+
};
|
|
16809
|
+
}
|
|
16810
|
+
return { valid: true, value: payload };
|
|
16811
|
+
}
|
|
16812
|
+
case "clearInput":
|
|
16813
|
+
return { valid: true, value: payload };
|
|
16814
|
+
// ── History mutations ───────────────────────────────────────────
|
|
16815
|
+
case "addEntry": {
|
|
16816
|
+
const entry = action.entry;
|
|
16817
|
+
if (!entry || typeof entry !== "object") {
|
|
16818
|
+
return { valid: false, error: "addEntry.entry: missing or non-object." };
|
|
16819
|
+
}
|
|
16820
|
+
const kind = String(entry.kind ?? "");
|
|
16821
|
+
if (!ALLOWED_ENTRY_KINDS.has(kind)) {
|
|
16822
|
+
return {
|
|
16823
|
+
valid: false,
|
|
16824
|
+
error: `addEntry.entry.kind: "${kind}" not on allow-list.`
|
|
16825
|
+
};
|
|
16826
|
+
}
|
|
16827
|
+
if (TEXT_BEARING_ENTRY_KINDS.has(kind)) {
|
|
16828
|
+
const text = entry.text;
|
|
16829
|
+
if (typeof text === "string" && text.length > MAX_ENTRY_TEXT_CHARS) {
|
|
16830
|
+
return {
|
|
16831
|
+
valid: false,
|
|
16832
|
+
error: `addEntry.entry.text: exceeds ${MAX_ENTRY_TEXT_CHARS.toLocaleString()} chars (got ${text.length}).`
|
|
16833
|
+
};
|
|
16834
|
+
}
|
|
16835
|
+
}
|
|
16836
|
+
return { valid: true, value: payload };
|
|
16837
|
+
}
|
|
16838
|
+
case "replaceEntry": {
|
|
16839
|
+
const id = Number(action.id);
|
|
16840
|
+
if (!Number.isInteger(id) || id < 0) {
|
|
16841
|
+
return { valid: false, error: `replaceEntry.id: ${action.id} is not a non-negative integer.` };
|
|
16842
|
+
}
|
|
16843
|
+
return { valid: true, value: payload };
|
|
16844
|
+
}
|
|
16845
|
+
case "replaceHistory": {
|
|
16846
|
+
const entries = action.entries;
|
|
16847
|
+
if (!Array.isArray(entries)) {
|
|
16848
|
+
return { valid: false, error: "replaceHistory.entries: not an array." };
|
|
16849
|
+
}
|
|
16850
|
+
if (entries.length > MAX_HISTORY_ENTRIES) {
|
|
16851
|
+
return {
|
|
16852
|
+
valid: false,
|
|
16853
|
+
error: `replaceHistory.entries: ${entries.length} exceeds max ${MAX_HISTORY_ENTRIES}.`
|
|
16854
|
+
};
|
|
16855
|
+
}
|
|
16856
|
+
return { valid: true, value: payload };
|
|
16857
|
+
}
|
|
16858
|
+
// ── Scroll ──────────────────────────────────────────────────────
|
|
16859
|
+
case "scrollBy": {
|
|
16860
|
+
const delta = Number(action.delta);
|
|
16861
|
+
if (!Number.isInteger(delta)) {
|
|
16862
|
+
return { valid: false, error: `scrollBy.delta: ${action.delta} is not an integer.` };
|
|
16863
|
+
}
|
|
16864
|
+
return { valid: true, value: payload };
|
|
16865
|
+
}
|
|
16866
|
+
case "scrollPage": {
|
|
16867
|
+
const dir = String(action.dir ?? "");
|
|
16868
|
+
if (!ALLOWED_SCROLL_DIRS.has(dir)) {
|
|
16869
|
+
return { valid: false, error: `scrollPage.dir: "${dir}" not on allow-list (up|down).` };
|
|
16870
|
+
}
|
|
16871
|
+
return { valid: true, value: payload };
|
|
16872
|
+
}
|
|
16873
|
+
case "setMeasuredLines": {
|
|
16874
|
+
const lines = Number(action.totalLines);
|
|
16875
|
+
if (!Number.isInteger(lines) || lines < 0) {
|
|
16876
|
+
return { valid: false, error: `setMeasuredLines.totalLines: ${action.totalLines} is not a non-negative integer.` };
|
|
16877
|
+
}
|
|
16878
|
+
return { valid: true, value: payload };
|
|
16879
|
+
}
|
|
16880
|
+
case "setViewportRows": {
|
|
16881
|
+
const rows = Number(action.rows);
|
|
16882
|
+
if (!Number.isInteger(rows) || rows < 0) {
|
|
16883
|
+
return { valid: false, error: `setViewportRows.rows: ${action.rows} is not a non-negative integer.` };
|
|
16884
|
+
}
|
|
16885
|
+
return { valid: true, value: payload };
|
|
16886
|
+
}
|
|
16887
|
+
// ── Picker ──────────────────────────────────────────────────────
|
|
16888
|
+
case "pickerMove":
|
|
16889
|
+
case "slashPickerMove":
|
|
16890
|
+
case "modelPickerMove":
|
|
16891
|
+
case "autonomyPickerMove":
|
|
16892
|
+
case "settingsPickerMove":
|
|
16893
|
+
case "statuslinePickerMove":
|
|
16894
|
+
case "pluginPickerMove":
|
|
16895
|
+
case "mcpPickerMove":
|
|
16896
|
+
case "toolsPickerMove":
|
|
16897
|
+
case "projectPickerMove":
|
|
16898
|
+
case "fKeyPickerMove":
|
|
16899
|
+
case "sessionsPanelMove":
|
|
16900
|
+
case "rewindOverlayMove":
|
|
16901
|
+
case "sendModePickerMove": {
|
|
16902
|
+
const delta = Number(action.delta);
|
|
16903
|
+
if (!Number.isInteger(delta) || delta < -1 || delta > 1) {
|
|
16904
|
+
return { valid: false, error: `${type}.delta: ${action.delta} is not -1, 0, or 1.` };
|
|
16905
|
+
}
|
|
16906
|
+
return { valid: true, value: payload };
|
|
16907
|
+
}
|
|
16908
|
+
case "pickerSetMatches":
|
|
16909
|
+
case "slashPickerSetMatches": {
|
|
16910
|
+
const matches = action.matches;
|
|
16911
|
+
if (!Array.isArray(matches)) {
|
|
16912
|
+
return { valid: false, error: `${type}.matches: not an array.` };
|
|
16913
|
+
}
|
|
16914
|
+
if (matches.length > MAX_PICKER_MATCHES) {
|
|
16915
|
+
return {
|
|
16916
|
+
valid: false,
|
|
16917
|
+
error: `${type}.matches: ${matches.length} exceeds max ${MAX_PICKER_MATCHES}.`
|
|
16918
|
+
};
|
|
16919
|
+
}
|
|
16920
|
+
return { valid: true, value: payload };
|
|
16921
|
+
}
|
|
16922
|
+
case "modelPickerSelect": {
|
|
16923
|
+
const idx = Number(action.index);
|
|
16924
|
+
if (!Number.isInteger(idx) || idx < 0) {
|
|
16925
|
+
return { valid: false, error: `modelPickerSelect.index: ${action.index} is not a non-negative integer.` };
|
|
16926
|
+
}
|
|
16927
|
+
return { valid: true, value: payload };
|
|
16928
|
+
}
|
|
16929
|
+
case "projectPickerSelect": {
|
|
16930
|
+
const idx = Number(action.selected);
|
|
16931
|
+
if (!Number.isInteger(idx) || idx < 0) {
|
|
16932
|
+
return { valid: false, error: `projectPickerSelect.selected: ${action.selected} is not a non-negative integer.` };
|
|
16933
|
+
}
|
|
16934
|
+
return { valid: true, value: payload };
|
|
16935
|
+
}
|
|
16936
|
+
case "projectPickerSetItems": {
|
|
16937
|
+
const items = action.items;
|
|
16938
|
+
if (!Array.isArray(items)) {
|
|
16939
|
+
return { valid: false, error: "projectPickerSetItems.items: not an array." };
|
|
16940
|
+
}
|
|
16941
|
+
if (items.length > MAX_PICKER_MATCHES) {
|
|
16942
|
+
return {
|
|
16943
|
+
valid: false,
|
|
16944
|
+
error: `projectPickerSetItems.items: ${items.length} exceeds max ${MAX_PICKER_MATCHES}.`
|
|
16945
|
+
};
|
|
16946
|
+
}
|
|
16947
|
+
return { valid: true, value: payload };
|
|
16948
|
+
}
|
|
16949
|
+
case "modelPickerSetProviders": {
|
|
16950
|
+
const providers = action.providers;
|
|
16951
|
+
if (!Array.isArray(providers)) {
|
|
16952
|
+
return { valid: false, error: "modelPickerSetProviders.providers: not an array." };
|
|
16953
|
+
}
|
|
16954
|
+
return { valid: true, value: payload };
|
|
16955
|
+
}
|
|
16956
|
+
// ── Settings ────────────────────────────────────────────────────
|
|
16957
|
+
case "settingsPick": {
|
|
16958
|
+
const field = String(action.field ?? "");
|
|
16959
|
+
if (field.length > 100) {
|
|
16960
|
+
return { valid: false, error: `settingsPick.field: length ${field.length} exceeds 100.` };
|
|
16961
|
+
}
|
|
16962
|
+
return { valid: true, value: payload };
|
|
16963
|
+
}
|
|
16964
|
+
// ── Fleet ───────────────────────────────────────────────────────
|
|
16965
|
+
case "fleetSeed": {
|
|
16966
|
+
const entries = action.entries;
|
|
16967
|
+
if (!Array.isArray(entries)) {
|
|
16968
|
+
return { valid: false, error: "fleetSeed.entries: not an array." };
|
|
16969
|
+
}
|
|
16970
|
+
if (entries.length > MAX_FLEET_ENTRIES) {
|
|
16971
|
+
return {
|
|
16972
|
+
valid: false,
|
|
16973
|
+
error: `fleetSeed.entries: ${entries.length} exceeds max ${MAX_FLEET_ENTRIES}.`
|
|
16974
|
+
};
|
|
16975
|
+
}
|
|
16976
|
+
return { valid: true, value: payload };
|
|
16977
|
+
}
|
|
16978
|
+
case "fleetBatch": {
|
|
16979
|
+
const actions = action.actions;
|
|
16980
|
+
if (!Array.isArray(actions)) {
|
|
16981
|
+
return { valid: false, error: "fleetBatch.actions: not an array." };
|
|
16982
|
+
}
|
|
16983
|
+
if (actions.length > MAX_BATCHED_ACTIONS) {
|
|
16984
|
+
return {
|
|
16985
|
+
valid: false,
|
|
16986
|
+
error: `fleetBatch.actions: ${actions.length} exceeds max ${MAX_BATCHED_ACTIONS}.`
|
|
16987
|
+
};
|
|
16988
|
+
}
|
|
16989
|
+
return { valid: true, value: payload };
|
|
16990
|
+
}
|
|
16991
|
+
case "fleetToolStart":
|
|
16992
|
+
case "fleetToolEnd":
|
|
16993
|
+
case "fleetTool": {
|
|
16994
|
+
const id = String(action.id ?? "");
|
|
16995
|
+
if (id.length === 0) {
|
|
16996
|
+
return { valid: false, error: `${type}.id: empty or missing.` };
|
|
16997
|
+
}
|
|
16998
|
+
return { valid: true, value: payload };
|
|
16999
|
+
}
|
|
17000
|
+
case "fleetSpawn":
|
|
17001
|
+
case "fleetStart":
|
|
17002
|
+
case "fleetDelta":
|
|
17003
|
+
case "fleetMessage":
|
|
17004
|
+
case "fleetUsage":
|
|
17005
|
+
case "fleetDone":
|
|
17006
|
+
case "fleetRemove":
|
|
17007
|
+
case "fleetBudgetWarning":
|
|
17008
|
+
case "fleetBudgetExtended":
|
|
17009
|
+
case "fleetCtxPct":
|
|
17010
|
+
case "fleetCost":
|
|
17011
|
+
case "fleetConcurrency":
|
|
17012
|
+
case "leaderIterStart":
|
|
17013
|
+
case "leaderIterEnd":
|
|
17014
|
+
case "leaderToolStart":
|
|
17015
|
+
case "leaderToolEnd":
|
|
17016
|
+
case "leaderCtxPct": {
|
|
17017
|
+
const id = String(action.id ?? "");
|
|
17018
|
+
if (id.length === 0) {
|
|
17019
|
+
return { valid: false, error: `${type}.id: empty or missing.` };
|
|
17020
|
+
}
|
|
17021
|
+
return { valid: true, value: payload };
|
|
17022
|
+
}
|
|
17023
|
+
case "setFleetChat": {
|
|
17024
|
+
const mode = String(action.mode ?? "");
|
|
17025
|
+
if (!ALLOWED_FLEET_CHAT_MODES.has(mode)) {
|
|
17026
|
+
return { valid: false, error: `setFleetChat.mode: "${mode}" not on allow-list.` };
|
|
17027
|
+
}
|
|
17028
|
+
return { valid: true, value: payload };
|
|
17029
|
+
}
|
|
17030
|
+
// ── State mutations ─────────────────────────────────────────────
|
|
17031
|
+
case "setAutonomyMode": {
|
|
17032
|
+
const mode = String(action.mode ?? "");
|
|
17033
|
+
if (!ALLOWED_AUTONOMY_MODES.has(mode)) {
|
|
17034
|
+
return { valid: false, error: `setAutonomyMode.mode: "${mode}" not on allow-list.` };
|
|
17035
|
+
}
|
|
17036
|
+
return { valid: true, value: payload };
|
|
17037
|
+
}
|
|
17038
|
+
case "setSendMode": {
|
|
17039
|
+
const mode = String(action.mode ?? "");
|
|
17040
|
+
if (!ALLOWED_SEND_MODES.has(mode)) {
|
|
17041
|
+
return { valid: false, error: `setSendMode.mode: "${mode}" not on allow-list.` };
|
|
17042
|
+
}
|
|
17043
|
+
return { valid: true, value: payload };
|
|
17044
|
+
}
|
|
17045
|
+
case "setLiveProvider":
|
|
17046
|
+
case "setLiveModel": {
|
|
17047
|
+
const value = String(action.value ?? "");
|
|
17048
|
+
if (value.length > MAX_HOST_STRING_FIELD) {
|
|
17049
|
+
return { valid: false, error: `${type}.value: exceeds ${MAX_HOST_STRING_FIELD} chars.` };
|
|
17050
|
+
}
|
|
17051
|
+
return { valid: true, value: payload };
|
|
17052
|
+
}
|
|
17053
|
+
case "setEffectiveMaxContext": {
|
|
17054
|
+
const ctx = Number(action.value);
|
|
17055
|
+
if (!Number.isInteger(ctx) || ctx < 0 || ctx > 1e7) {
|
|
17056
|
+
return { valid: false, error: `setEffectiveMaxContext.value: ${action.value} out of range [0, 10_000_000].` };
|
|
17057
|
+
}
|
|
17058
|
+
return { valid: true, value: payload };
|
|
17059
|
+
}
|
|
17060
|
+
case "setStreamingText": {
|
|
17061
|
+
const text = String(action.text ?? "");
|
|
17062
|
+
if (text.length > MAX_ENTRY_TEXT_CHARS) {
|
|
17063
|
+
return {
|
|
17064
|
+
valid: false,
|
|
17065
|
+
error: `setStreamingText.text: exceeds ${MAX_ENTRY_TEXT_CHARS.toLocaleString()} chars.`
|
|
17066
|
+
};
|
|
17067
|
+
}
|
|
17068
|
+
return { valid: true, value: payload };
|
|
17069
|
+
}
|
|
17070
|
+
case "setToolStream": {
|
|
17071
|
+
const text = String(action.text ?? "");
|
|
17072
|
+
if (text.length > MAX_TOOL_STREAM_RETAINED_CHARS) {
|
|
17073
|
+
return {
|
|
17074
|
+
valid: false,
|
|
17075
|
+
error: `setToolStream.text: exceeds ${MAX_TOOL_STREAM_RETAINED_CHARS.toLocaleString()} chars.`
|
|
17076
|
+
};
|
|
17077
|
+
}
|
|
17078
|
+
return { valid: true, value: payload };
|
|
17079
|
+
}
|
|
17080
|
+
case "setThinkingWord": {
|
|
17081
|
+
const word = String(action.word ?? "");
|
|
17082
|
+
if (word.length > 16) {
|
|
17083
|
+
return { valid: false, error: `setThinkingWord.word: "${word}" exceeds 16 chars.` };
|
|
17084
|
+
}
|
|
17085
|
+
return { valid: true, value: payload };
|
|
17086
|
+
}
|
|
17087
|
+
case "setAnimationStyle": {
|
|
17088
|
+
const style = String(action.style ?? "");
|
|
17089
|
+
if (style.length > 50) {
|
|
17090
|
+
return { valid: false, error: `setAnimationStyle.style: length ${style.length} exceeds 50.` };
|
|
17091
|
+
}
|
|
17092
|
+
return { valid: true, value: payload };
|
|
17093
|
+
}
|
|
17094
|
+
case "setCapability": {
|
|
17095
|
+
const cap = action.capability;
|
|
17096
|
+
if (!cap || typeof cap !== "object") {
|
|
17097
|
+
return { valid: false, error: "setCapability.capability: missing or non-object." };
|
|
17098
|
+
}
|
|
17099
|
+
for (const k of Object.keys(cap)) {
|
|
17100
|
+
if (!ALLOWED_CAPABILITY_FIELDS.has(k)) {
|
|
17101
|
+
return { valid: false, error: `setCapability.capability.${k}: unknown field.` };
|
|
17102
|
+
}
|
|
17103
|
+
}
|
|
17104
|
+
return { valid: true, value: payload };
|
|
17105
|
+
}
|
|
17106
|
+
// ── Confirm panels ──────────────────────────────────────────────
|
|
17107
|
+
case "clearConfirmOpen":
|
|
17108
|
+
case "exitConfirmOpen":
|
|
17109
|
+
case "slashConfirmOpen":
|
|
17110
|
+
case "escConfirmOpen":
|
|
17111
|
+
case "enhanceConfirmOpen": {
|
|
17112
|
+
const info = action.info;
|
|
17113
|
+
if (!info || typeof info !== "object") {
|
|
17114
|
+
return { valid: false, error: `${type}.info: missing or non-object.` };
|
|
17115
|
+
}
|
|
17116
|
+
return { valid: true, value: payload };
|
|
17117
|
+
}
|
|
17118
|
+
case "clearConfirmSetValue": {
|
|
17119
|
+
const value = String(action.value ?? "");
|
|
17120
|
+
if (value.length > 100) {
|
|
17121
|
+
return { valid: false, error: `clearConfirmSetValue.value: exceeds 100 chars.` };
|
|
17122
|
+
}
|
|
17123
|
+
return { valid: true, value: payload };
|
|
17124
|
+
}
|
|
17125
|
+
// ── Checkpoints ─────────────────────────────────────────────────
|
|
17126
|
+
case "checkpointReceived": {
|
|
17127
|
+
const cp = action.cp;
|
|
17128
|
+
if (!cp || typeof cp !== "object") {
|
|
17129
|
+
return { valid: false, error: "checkpointReceived.cp: missing or non-object." };
|
|
17130
|
+
}
|
|
17131
|
+
const promptIndex = Number(cp.promptIndex);
|
|
17132
|
+
if (!Number.isInteger(promptIndex) || promptIndex < 0) {
|
|
17133
|
+
return {
|
|
17134
|
+
valid: false,
|
|
17135
|
+
error: `checkpointReceived.cp.promptIndex: ${promptIndex} is not a non-negative integer.`
|
|
17136
|
+
};
|
|
17137
|
+
}
|
|
17138
|
+
return { valid: true, value: payload };
|
|
17139
|
+
}
|
|
17140
|
+
// ── Rewind ──────────────────────────────────────────────────────
|
|
17141
|
+
case "rewindOverlayOpen": {
|
|
17142
|
+
const checkpoints = action.checkpoints;
|
|
17143
|
+
if (!Array.isArray(checkpoints)) {
|
|
17144
|
+
return { valid: false, error: "rewindOverlayOpen.checkpoints: not an array." };
|
|
17145
|
+
}
|
|
17146
|
+
if (checkpoints.length > MAX_HISTORY_ENTRIES) {
|
|
17147
|
+
return {
|
|
17148
|
+
valid: false,
|
|
17149
|
+
error: `rewindOverlayOpen.checkpoints: ${checkpoints.length} exceeds max ${MAX_HISTORY_ENTRIES}.`
|
|
17150
|
+
};
|
|
17151
|
+
}
|
|
17152
|
+
return { valid: true, value: payload };
|
|
17153
|
+
}
|
|
17154
|
+
// ── Steering ────────────────────────────────────────────────────
|
|
17155
|
+
case "setSteering": {
|
|
17156
|
+
const text = String(action.text ?? "");
|
|
17157
|
+
if (text.length > MAX_INPUT_BUFFER_CHARS) {
|
|
17158
|
+
return {
|
|
17159
|
+
valid: false,
|
|
17160
|
+
error: `setSteering.text: exceeds ${MAX_INPUT_BUFFER_CHARS.toLocaleString()} chars.`
|
|
17161
|
+
};
|
|
17162
|
+
}
|
|
17163
|
+
return { valid: true, value: payload };
|
|
17164
|
+
}
|
|
17165
|
+
// ── Goal ────────────────────────────────────────────────────────
|
|
17166
|
+
case "goalRunInit": {
|
|
17167
|
+
const title = String(action.title ?? "");
|
|
17168
|
+
if (title.length > 500) {
|
|
17169
|
+
return { valid: false, error: `goalRunInit.title: exceeds 500 chars.` };
|
|
17170
|
+
}
|
|
17171
|
+
return { valid: true, value: payload };
|
|
17172
|
+
}
|
|
17173
|
+
case "goalRunPhaseUpdate": {
|
|
17174
|
+
const completed = Number(action.completedTasks);
|
|
17175
|
+
if (!Number.isInteger(completed) || completed < 0) {
|
|
17176
|
+
return { valid: false, error: `goalRunPhaseUpdate.completedTasks: ${completed} is not a non-negative integer.` };
|
|
17177
|
+
}
|
|
17178
|
+
const total = Number(action.totalTasks);
|
|
17179
|
+
if (!Number.isInteger(total) || total < 0) {
|
|
17180
|
+
return { valid: false, error: `goalRunPhaseUpdate.totalTasks: ${total} is not a non-negative integer.` };
|
|
17181
|
+
}
|
|
17182
|
+
return { valid: true, value: payload };
|
|
17183
|
+
}
|
|
17184
|
+
case "goalRunRunningPhases": {
|
|
17185
|
+
const phaseIds = action.phaseIds;
|
|
17186
|
+
if (!Array.isArray(phaseIds)) {
|
|
17187
|
+
return { valid: false, error: "goalRunRunningPhases.phaseIds: not an array." };
|
|
17188
|
+
}
|
|
17189
|
+
return { valid: true, value: payload };
|
|
17190
|
+
}
|
|
17191
|
+
case "goalRunElapsed": {
|
|
17192
|
+
const ms = Number(action.ms);
|
|
17193
|
+
if (!Number.isFinite(ms) || ms < 0) {
|
|
17194
|
+
return { valid: false, error: `goalRunElapsed.ms: ${ms} is not a non-negative number.` };
|
|
17195
|
+
}
|
|
17196
|
+
return { valid: true, value: payload };
|
|
17197
|
+
}
|
|
17198
|
+
case "goalRunTaskActive": {
|
|
17199
|
+
if (typeof action.active !== "boolean") {
|
|
17200
|
+
return { valid: false, error: "goalRunTaskActive.active: not a boolean." };
|
|
17201
|
+
}
|
|
17202
|
+
return { valid: true, value: payload };
|
|
17203
|
+
}
|
|
17204
|
+
// ── SDD board ───────────────────────────────────────────────────
|
|
17205
|
+
case "sddBoardSnapshot": {
|
|
17206
|
+
if (!action.snapshot || typeof action.snapshot !== "object") {
|
|
17207
|
+
return { valid: false, error: "sddBoardSnapshot.snapshot: missing or non-object." };
|
|
17208
|
+
}
|
|
17209
|
+
return { valid: true, value: payload };
|
|
17210
|
+
}
|
|
17211
|
+
// ── Worktree ────────────────────────────────────────────────────
|
|
17212
|
+
case "worktreeUpsert": {
|
|
17213
|
+
const handleId = String(action.handleId ?? "");
|
|
17214
|
+
if (handleId.length === 0) {
|
|
17215
|
+
return { valid: false, error: "worktreeUpsert.handleId: empty." };
|
|
17216
|
+
}
|
|
17217
|
+
return { valid: true, value: payload };
|
|
17218
|
+
}
|
|
17219
|
+
case "worktreeRemove": {
|
|
17220
|
+
const handleId = String(action.handleId ?? "");
|
|
17221
|
+
if (handleId.length === 0) {
|
|
17222
|
+
return { valid: false, error: "worktreeRemove.handleId: empty." };
|
|
17223
|
+
}
|
|
17224
|
+
return { valid: true, value: payload };
|
|
17225
|
+
}
|
|
17226
|
+
// ── Collaboration ───────────────────────────────────────────────
|
|
17227
|
+
case "collabBugFound": {
|
|
17228
|
+
const bugId = String(action.bugId ?? "");
|
|
17229
|
+
if (bugId.length === 0) {
|
|
17230
|
+
return { valid: false, error: "collabBugFound.bugId: empty." };
|
|
17231
|
+
}
|
|
17232
|
+
return { valid: true, value: payload };
|
|
17233
|
+
}
|
|
17234
|
+
case "collabSessionDone": {
|
|
17235
|
+
const verdict = String(action.verdict ?? "");
|
|
17236
|
+
if (!ALLOWED_COLLAB_VERDICTS.has(verdict)) {
|
|
17237
|
+
return { valid: false, error: `collabSessionDone.verdict: "${verdict}" not on allow-list.` };
|
|
17238
|
+
}
|
|
17239
|
+
return { valid: true, value: payload };
|
|
17240
|
+
}
|
|
17241
|
+
case "collabSubagentSpawned": {
|
|
17242
|
+
const role = String(action.role ?? "");
|
|
17243
|
+
if (role.length === 0) {
|
|
17244
|
+
return { valid: false, error: "collabSubagentSpawned.role: empty." };
|
|
17245
|
+
}
|
|
17246
|
+
return { valid: true, value: payload };
|
|
17247
|
+
}
|
|
17248
|
+
// ── Debug stream ────────────────────────────────────────────────
|
|
17249
|
+
case "debugStreamStats": {
|
|
17250
|
+
const chunkCount = Number(action.chunkCount);
|
|
17251
|
+
if (!Number.isInteger(chunkCount) || chunkCount < 0) {
|
|
17252
|
+
return { valid: false, error: `debugStreamStats.chunkCount: ${chunkCount} is not a non-negative integer.` };
|
|
17253
|
+
}
|
|
17254
|
+
const lastChunkSize = Number(action.lastChunkSize);
|
|
17255
|
+
if (!Number.isInteger(lastChunkSize) || lastChunkSize < 0) {
|
|
17256
|
+
return { valid: false, error: `debugStreamStats.lastChunkSize: ${lastChunkSize} is not a non-negative integer.` };
|
|
17257
|
+
}
|
|
17258
|
+
const totalBytes = Number(action.totalBytes);
|
|
17259
|
+
if (!Number.isInteger(totalBytes) || totalBytes < 0) {
|
|
17260
|
+
return { valid: false, error: `debugStreamStats.totalBytes: ${totalBytes} is not a non-negative integer.` };
|
|
17261
|
+
}
|
|
17262
|
+
return { valid: true, value: payload };
|
|
17263
|
+
}
|
|
17264
|
+
// ── Countdown ───────────────────────────────────────────────────
|
|
17265
|
+
case "countdownTick": {
|
|
17266
|
+
const remaining = Number(action.remainingSeconds);
|
|
17267
|
+
if (!Number.isFinite(remaining) || remaining < 0) {
|
|
17268
|
+
return { valid: false, error: `countdownTick.remainingSeconds: ${remaining} is not a non-negative number.` };
|
|
17269
|
+
}
|
|
17270
|
+
return { valid: true, value: payload };
|
|
17271
|
+
}
|
|
17272
|
+
// ── Coordinator ─────────────────────────────────────────────────
|
|
17273
|
+
case "coordinatorEvent": {
|
|
17274
|
+
if (!action.event || typeof action.event !== "object") {
|
|
17275
|
+
return { valid: false, error: "coordinatorEvent.event: missing or non-object." };
|
|
17276
|
+
}
|
|
17277
|
+
return { valid: true, value: payload };
|
|
17278
|
+
}
|
|
17279
|
+
// ── Sessions panel ──────────────────────────────────────────────
|
|
17280
|
+
case "sessionsPanelSet": {
|
|
17281
|
+
const sessions = action.sessions;
|
|
17282
|
+
if (!Array.isArray(sessions)) {
|
|
17283
|
+
return { valid: false, error: "sessionsPanelSet.sessions: not an array." };
|
|
17284
|
+
}
|
|
17285
|
+
if (sessions.length > 200) {
|
|
17286
|
+
return { valid: false, error: `sessionsPanelSet.sessions: ${sessions.length} exceeds max 200.` };
|
|
17287
|
+
}
|
|
17288
|
+
return { valid: true, value: payload };
|
|
17289
|
+
}
|
|
17290
|
+
case "sessionsPanelBusy": {
|
|
17291
|
+
if (typeof action.on !== "boolean") {
|
|
17292
|
+
return { valid: false, error: "sessionsPanelBusy.on: not a boolean." };
|
|
17293
|
+
}
|
|
17294
|
+
return { valid: true, value: payload };
|
|
17295
|
+
}
|
|
17296
|
+
case "sessionResumeConfirmSet": {
|
|
17297
|
+
const sessionId = String(action.sessionId ?? "");
|
|
17298
|
+
if (sessionId.length === 0) {
|
|
17299
|
+
return { valid: false, error: "sessionResumeConfirmSet.sessionId: empty." };
|
|
17300
|
+
}
|
|
17301
|
+
return { valid: true, value: payload };
|
|
17302
|
+
}
|
|
17303
|
+
// ── Simple state toggles and setters ────────────────────────────
|
|
17304
|
+
case "setShowModelReasoning": {
|
|
17305
|
+
if (typeof action.value !== "boolean") {
|
|
17306
|
+
return { valid: false, error: "setShowModelReasoning.value: not a boolean." };
|
|
17307
|
+
}
|
|
17308
|
+
return { valid: true, value: payload };
|
|
17309
|
+
}
|
|
17310
|
+
case "setEnhancedPrompt": {
|
|
17311
|
+
const text = String(action.text ?? "");
|
|
17312
|
+
if (text.length > MAX_ENTRY_TEXT_CHARS) {
|
|
17313
|
+
return {
|
|
17314
|
+
valid: false,
|
|
17315
|
+
error: `setEnhancedPrompt.text: exceeds ${MAX_ENTRY_TEXT_CHARS.toLocaleString()} chars.`
|
|
17316
|
+
};
|
|
17317
|
+
}
|
|
17318
|
+
return { valid: true, value: payload };
|
|
17319
|
+
}
|
|
17320
|
+
case "setDesignKit": {
|
|
17321
|
+
const name = String(action.name ?? "");
|
|
17322
|
+
if (name.length > 100) {
|
|
17323
|
+
return { valid: false, error: `setDesignKit.name: exceeds 100 chars.` };
|
|
17324
|
+
}
|
|
17325
|
+
return { valid: true, value: payload };
|
|
17326
|
+
}
|
|
17327
|
+
case "setGoalText":
|
|
17328
|
+
case "setGoalPanelGoal": {
|
|
17329
|
+
const text = String(action.text ?? "");
|
|
17330
|
+
if (text.length > 5e3) {
|
|
17331
|
+
return { valid: false, error: `${type}.text: exceeds 5000 chars.` };
|
|
17332
|
+
}
|
|
17333
|
+
return { valid: true, value: payload };
|
|
17334
|
+
}
|
|
17335
|
+
// ── Enhance / refine ───────────────────────────────────────────
|
|
17336
|
+
case "enhanceResult": {
|
|
17337
|
+
const result = action.result;
|
|
17338
|
+
if (!result || typeof result !== "object") {
|
|
17339
|
+
return { valid: false, error: "enhanceResult.result: missing or non-object." };
|
|
17340
|
+
}
|
|
17341
|
+
return { valid: true, value: payload };
|
|
17342
|
+
}
|
|
17343
|
+
case "refineFailureOpen": {
|
|
17344
|
+
const info = action.info;
|
|
17345
|
+
if (!info || typeof info !== "object") {
|
|
17346
|
+
return { valid: false, error: "refineFailureOpen.info: missing or non-object." };
|
|
17347
|
+
}
|
|
17348
|
+
return { valid: true, value: payload };
|
|
17349
|
+
}
|
|
17350
|
+
// ── Actions with no payload or trivial payload ──────────────────
|
|
17351
|
+
case "toggleHelp":
|
|
17352
|
+
case "toggleMonitor":
|
|
17353
|
+
case "toggleAgentsMonitor":
|
|
17354
|
+
case "toggleTodosMonitor":
|
|
17355
|
+
case "toggleQueuePanel":
|
|
17356
|
+
case "toggleProcessList":
|
|
17357
|
+
case "toggleCronMonitor":
|
|
17358
|
+
case "toggleAuditPanel":
|
|
17359
|
+
case "togglePlanPanel":
|
|
17360
|
+
case "closeAllPanels":
|
|
17361
|
+
case "toggleKanbanPanel":
|
|
17362
|
+
case "toggleGoalPanel":
|
|
17363
|
+
case "toggleGoalKanbanPanel":
|
|
17364
|
+
case "toggleContextPanel":
|
|
17365
|
+
case "toggleSessionsPanel":
|
|
17366
|
+
case "toggleSddBoardMonitor":
|
|
17367
|
+
case "toggleWorktreeMonitor":
|
|
17368
|
+
case "toggleCoordinatorMonitor":
|
|
17369
|
+
case "resetContextChip":
|
|
17370
|
+
case "clearConfirmClose":
|
|
17371
|
+
case "exitConfirmClose":
|
|
17372
|
+
case "slashConfirmClose":
|
|
17373
|
+
case "escConfirmClose":
|
|
17374
|
+
case "sendModePickerClose":
|
|
17375
|
+
case "enhanceClose":
|
|
17376
|
+
case "enhanceBusy":
|
|
17377
|
+
case "enhanceBusyDone":
|
|
17378
|
+
case "enhanceCancel":
|
|
17379
|
+
case "enhanceDismiss":
|
|
17380
|
+
case "enhanceConfirmClose":
|
|
17381
|
+
case "refineFailureClose":
|
|
17382
|
+
case "continueConfirmOpen":
|
|
17383
|
+
case "continueConfirmClose":
|
|
17384
|
+
case "rewindOverlayClose":
|
|
17385
|
+
case "countdownEnded":
|
|
17386
|
+
case "cancelSend":
|
|
17387
|
+
case "submit":
|
|
17388
|
+
case "afterSubmit":
|
|
17389
|
+
case "streamStart":
|
|
17390
|
+
case "streamToken":
|
|
17391
|
+
case "streamToolUse":
|
|
17392
|
+
case "streamToolResult":
|
|
17393
|
+
case "streamEnd":
|
|
17394
|
+
case "setMode":
|
|
17395
|
+
case "clearInput":
|
|
17396
|
+
case "clearHistory":
|
|
17397
|
+
case "toolStreamClear":
|
|
17398
|
+
case "debugStreamStatsClear":
|
|
17399
|
+
case "setSteeringPending":
|
|
17400
|
+
case "clearSteering":
|
|
17401
|
+
case "showGoal":
|
|
17402
|
+
case "goalSummary":
|
|
17403
|
+
case "goalRunMonitorToggle":
|
|
17404
|
+
case "goalRunReset":
|
|
17405
|
+
case "sddBoardFocusNext":
|
|
17406
|
+
case "sddBoardFocusPrev":
|
|
17407
|
+
case "compactHistory":
|
|
17408
|
+
case "scrollToBottom":
|
|
17409
|
+
case "scrollToTop":
|
|
17410
|
+
case "pickerOpen":
|
|
17411
|
+
case "pickerClose":
|
|
17412
|
+
case "slashPickerOpen":
|
|
17413
|
+
case "slashPickerClose":
|
|
17414
|
+
case "modelPickerOpen":
|
|
17415
|
+
case "modelPickerClose":
|
|
17416
|
+
case "autonomyPickerOpen":
|
|
17417
|
+
case "autonomyPickerClose":
|
|
17418
|
+
case "settingsPickerOpen":
|
|
17419
|
+
case "settingsPickerClose":
|
|
17420
|
+
case "statuslinePickerOpen":
|
|
17421
|
+
case "statuslinePickerClose":
|
|
17422
|
+
case "pluginPickerOpen":
|
|
17423
|
+
case "pluginPickerClose":
|
|
17424
|
+
case "mcpPickerOpen":
|
|
17425
|
+
case "mcpPickerClose":
|
|
17426
|
+
case "toolsPickerOpen":
|
|
17427
|
+
case "toolsPickerClose":
|
|
17428
|
+
case "projectPickerOpen":
|
|
17429
|
+
case "projectPickerClose":
|
|
17430
|
+
case "fKeyPickerOpen":
|
|
17431
|
+
case "fKeyPickerClose":
|
|
17432
|
+
case "confirmPromptOpen":
|
|
17433
|
+
case "confirmPromptClose":
|
|
17434
|
+
case "setDeadline":
|
|
17435
|
+
case "enhanceOpen":
|
|
17436
|
+
return { valid: true, value: payload };
|
|
17437
|
+
default:
|
|
17438
|
+
return {
|
|
17439
|
+
valid: false,
|
|
17440
|
+
error: `action.type: "${type}" has no type-specific validator \u2014 may be a missing case.`
|
|
17441
|
+
};
|
|
17442
|
+
}
|
|
17443
|
+
}
|
|
17444
|
+
function normalizeActionType(type) {
|
|
17445
|
+
const trimmed = String(type ?? "").trim();
|
|
17446
|
+
if (trimmed.length === 0) return null;
|
|
17447
|
+
return trimmed;
|
|
17448
|
+
}
|
|
17449
|
+
function measureDepth(value, depth) {
|
|
17450
|
+
if (depth > MAX_ACTION_DEPTH) return depth;
|
|
17451
|
+
if (value === null || typeof value !== "object") return depth;
|
|
17452
|
+
if (Array.isArray(value)) {
|
|
17453
|
+
let max2 = depth;
|
|
17454
|
+
for (const item of value.slice(0, 10)) {
|
|
17455
|
+
const d = measureDepth(item, depth + 1);
|
|
17456
|
+
if (d > max2) max2 = d;
|
|
17457
|
+
if (max2 > MAX_ACTION_DEPTH) return max2;
|
|
17458
|
+
}
|
|
17459
|
+
return max2;
|
|
17460
|
+
}
|
|
17461
|
+
let max = depth;
|
|
17462
|
+
for (const v of Object.values(value).slice(0, 10)) {
|
|
17463
|
+
const d = measureDepth(v, depth + 1);
|
|
17464
|
+
if (d > max) max = d;
|
|
17465
|
+
if (max > MAX_ACTION_DEPTH) return max;
|
|
17466
|
+
}
|
|
17467
|
+
return max;
|
|
17468
|
+
}
|
|
17469
|
+
function safeDispatch(action, dispatch) {
|
|
17470
|
+
const result = validateAction(action);
|
|
17471
|
+
if (!result.valid) {
|
|
17472
|
+
console.error(`[input-validation] REJECTED dispatch "${action.type}": ${result.error}`);
|
|
17473
|
+
return false;
|
|
17474
|
+
}
|
|
17475
|
+
dispatch(result.value);
|
|
17476
|
+
return true;
|
|
17477
|
+
}
|
|
17478
|
+
|
|
16518
17479
|
// src/components/kanban-panel.tsx
|
|
16519
17480
|
import {
|
|
16520
17481
|
addTask,
|
|
@@ -19308,7 +20269,9 @@ var ScrollableHistory = memo3(function ScrollableHistory2({
|
|
|
19308
20269
|
const visibleCount = Math.min(entries.length, Math.max(1, Math.round(height / 3)));
|
|
19309
20270
|
const estimatedPerEntry = Math.max(1, Math.round(height / visibleCount));
|
|
19310
20271
|
for (const entry of entries) {
|
|
19311
|
-
cache2.
|
|
20272
|
+
if (cache2.getHeight(entry.id) === void 0) {
|
|
20273
|
+
cache2.record(entry.id, estimatedPerEntry);
|
|
20274
|
+
}
|
|
19312
20275
|
}
|
|
19313
20276
|
}
|
|
19314
20277
|
const cacheTotal2 = cache2.totalHeight();
|
|
@@ -26110,6 +27073,7 @@ function App({
|
|
|
26110
27073
|
provider,
|
|
26111
27074
|
family,
|
|
26112
27075
|
keyTail,
|
|
27076
|
+
profile,
|
|
26113
27077
|
autonomyAgents,
|
|
26114
27078
|
tokenSavingMode,
|
|
26115
27079
|
toolCount,
|
|
@@ -26268,7 +27232,7 @@ function App({
|
|
|
26268
27232
|
restoredEvents
|
|
26269
27233
|
);
|
|
26270
27234
|
const restoredCheckpoints = buildRestoredCheckpoints(restoredEvents);
|
|
26271
|
-
const [state,
|
|
27235
|
+
const [state, rawDispatch] = useReducer(
|
|
26272
27236
|
reducer,
|
|
26273
27237
|
createInitialState({
|
|
26274
27238
|
banner,
|
|
@@ -26279,6 +27243,7 @@ function App({
|
|
|
26279
27243
|
family,
|
|
26280
27244
|
keyTail,
|
|
26281
27245
|
sessionId: agent.ctx.session.id,
|
|
27246
|
+
profile,
|
|
26282
27247
|
autonomyAgents,
|
|
26283
27248
|
restoredEntries,
|
|
26284
27249
|
restoredCheckpoints,
|
|
@@ -26287,6 +27252,12 @@ function App({
|
|
|
26287
27252
|
initialFleetChat: fleetStreamController?.mode
|
|
26288
27253
|
})
|
|
26289
27254
|
);
|
|
27255
|
+
const dispatch = useCallback12(
|
|
27256
|
+
(action) => {
|
|
27257
|
+
safeDispatch(action, rawDispatch);
|
|
27258
|
+
},
|
|
27259
|
+
[rawDispatch]
|
|
27260
|
+
);
|
|
26290
27261
|
const [focusedBoardId, setFocusedBoardId] = useState29(null);
|
|
26291
27262
|
const boardFocusRef = useRef17(null);
|
|
26292
27263
|
if (!boardFocusRef.current) {
|
|
@@ -26442,6 +27413,7 @@ function App({
|
|
|
26442
27413
|
dispatch
|
|
26443
27414
|
});
|
|
26444
27415
|
const onMeasure = useCallback12((totalLines) => {
|
|
27416
|
+
if (totalLines === stateRef.current.totalLines) return;
|
|
26445
27417
|
dispatch({ type: "setMeasuredLines", totalLines });
|
|
26446
27418
|
}, []);
|
|
26447
27419
|
const liveDirector = useCallback12(
|
|
@@ -28484,6 +29456,8 @@ Available chords:
|
|
|
28484
29456
|
const [enhanceCountdown, setEnhanceCountdown] = useState29(null);
|
|
28485
29457
|
const [enhanceStartedAt, setEnhanceStartedAt] = useState29(null);
|
|
28486
29458
|
const [enhanceDurationMs, setEnhanceDurationMs] = useState29(null);
|
|
29459
|
+
const [refineProviderId, setRefineProviderId] = useState29(null);
|
|
29460
|
+
const [refineModel, setRefineModel] = useState29(null);
|
|
28487
29461
|
const [nextStepsAutoSubmitCountdown, setNextStepsAutoSubmitCountdown] = useState29(
|
|
28488
29462
|
null
|
|
28489
29463
|
);
|
|
@@ -30108,6 +31082,8 @@ ${content}
|
|
|
30108
31082
|
const attemptStartedAt = Date.now();
|
|
30109
31083
|
setEnhanceStartedAt(attemptStartedAt);
|
|
30110
31084
|
setEnhanceDurationMs(null);
|
|
31085
|
+
setRefineProviderId(provider2.id);
|
|
31086
|
+
setRefineModel(model2);
|
|
30111
31087
|
enhanceAbortRef.current = ac;
|
|
30112
31088
|
dispatch({ type: "enhanceBusy", on: true });
|
|
30113
31089
|
let out = null;
|
|
@@ -30900,8 +31876,8 @@ ${content}
|
|
|
30900
31876
|
original: enhanceOriginalRef.current,
|
|
30901
31877
|
elapsedMs: enhanceStartedAt === null ? 0 : Math.max(0, Date.now() - enhanceStartedAt),
|
|
30902
31878
|
pulseFrame: enhanceDots,
|
|
30903
|
-
providerId: agent.ctx.provider?.id,
|
|
30904
|
-
model: agent.ctx.model
|
|
31879
|
+
providerId: refineProviderId ?? agent.ctx.provider?.id,
|
|
31880
|
+
model: refineModel ?? agent.ctx.model
|
|
30905
31881
|
}
|
|
30906
31882
|
) : null,
|
|
30907
31883
|
state.enhance ? (() => {
|
|
@@ -30924,8 +31900,8 @@ ${content}
|
|
|
30924
31900
|
enhanceLanguage: state.settingsPicker.enhanceLanguage,
|
|
30925
31901
|
onDecision,
|
|
30926
31902
|
onTick: (r) => setEnhanceCountdown(r > 0 ? r : null),
|
|
30927
|
-
providerId: agent.ctx.provider?.id,
|
|
30928
|
-
model: agent.ctx.model
|
|
31903
|
+
providerId: refineProviderId ?? agent.ctx.provider?.id,
|
|
31904
|
+
model: refineModel ?? agent.ctx.model
|
|
30929
31905
|
}
|
|
30930
31906
|
);
|
|
30931
31907
|
})() : null,
|
|
@@ -31675,6 +32651,7 @@ async function runTui(opts) {
|
|
|
31675
32651
|
provider: opts.provider,
|
|
31676
32652
|
family: opts.family,
|
|
31677
32653
|
keyTail: opts.keyTail,
|
|
32654
|
+
profile: opts.profile,
|
|
31678
32655
|
autonomyAgents: opts.autonomyAgents,
|
|
31679
32656
|
getPickableProviders: opts.getPickableProviders,
|
|
31680
32657
|
switchProviderAndModel: opts.switchProviderAndModel,
|