@navios/commander-tui 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/{src/__tests__/mocks/scm-mock.ts → dist/base/src/__tests__/mocks/scm-mock.d.ts} +3 -1
- package/dist/base/src/__tests__/mocks/scm-mock.d.ts.map +1 -0
- package/dist/base/src/__tests__/setup.d.ts +2 -0
- package/dist/base/src/__tests__/setup.d.ts.map +1 -0
- package/dist/base/src/__tests__/utils/factories.d.ts +67 -0
- package/dist/base/src/__tests__/utils/factories.d.ts.map +1 -0
- package/dist/base/src/__tests__/utils/render-utils.d.ts +21 -0
- package/dist/base/src/__tests__/utils/render-utils.d.ts.map +1 -0
- package/dist/base/src/__tests__/utils/test-container.d.ts +20 -0
- package/dist/base/src/__tests__/utils/test-container.d.ts.map +1 -0
- package/dist/base/src/adapters/interface.d.ts +9 -2
- package/dist/base/src/adapters/interface.d.ts.map +1 -1
- package/dist/base/src/overrides/missing-adapter.override.d.ts +10 -0
- package/dist/base/src/overrides/missing-adapter.override.d.ts.map +1 -1
- package/dist/base/src/schemas/logger-options.d.ts +1 -1
- package/dist/base/src/services/index.d.ts +1 -0
- package/dist/base/src/services/index.d.ts.map +1 -1
- package/dist/base/src/services/logger.d.ts.map +1 -1
- package/dist/base/src/services/readline_prompt.d.ts +27 -0
- package/dist/base/src/services/readline_prompt.d.ts.map +1 -0
- package/dist/base/src/services/screen.d.ts +14 -8
- package/dist/base/src/services/screen.d.ts.map +1 -1
- package/dist/base/src/services/screen_manager.d.ts +62 -12
- package/dist/base/src/services/screen_manager.d.ts.map +1 -1
- package/dist/base/src/types/events.types.d.ts +40 -0
- package/dist/base/src/types/events.types.d.ts.map +1 -0
- package/dist/base/src/types/index.d.ts +1 -0
- package/dist/base/src/types/index.d.ts.map +1 -1
- package/dist/base/src/types/screen.types.d.ts +28 -0
- package/dist/base/src/types/screen.types.d.ts.map +1 -1
- package/dist/base/src/utils/colors/helpers.d.ts +0 -16
- package/dist/base/src/utils/colors/helpers.d.ts.map +1 -1
- package/dist/base/src/utils/index.d.ts +2 -0
- package/dist/base/src/utils/index.d.ts.map +1 -1
- package/dist/base/src/utils/prompt.d.ts +7 -0
- package/dist/base/src/utils/prompt.d.ts.map +1 -0
- package/dist/base/src/utils/runtime.d.ts +10 -0
- package/dist/base/src/utils/runtime.d.ts.map +1 -0
- package/dist/base/src/utils/stdout-printer.d.ts +5 -0
- package/dist/base/src/utils/stdout-printer.d.ts.map +1 -1
- package/dist/base/tsconfig.base.tsbuildinfo +1 -1
- package/dist/base/tsconfig.tsbuildinfo +1 -0
- package/dist/ink/src/adapters/ink/components/file/file_log.d.ts +28 -0
- package/dist/ink/src/adapters/ink/components/file/file_log.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/file/index.d.ts +2 -0
- package/dist/ink/src/adapters/ink/components/file/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/filter/filter_bar.d.ts +7 -0
- package/dist/ink/src/adapters/ink/components/filter/filter_bar.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/filter/index.d.ts +2 -0
- package/dist/ink/src/adapters/ink/components/filter/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/help/help_overlay.d.ts +6 -0
- package/dist/ink/src/adapters/ink/components/help/help_overlay.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/help/index.d.ts +2 -0
- package/dist/ink/src/adapters/ink/components/help/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/index.d.ts +9 -0
- package/dist/ink/src/adapters/ink/components/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/log/index.d.ts +2 -0
- package/dist/ink/src/adapters/ink/components/log/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/log/log_message.d.ts +15 -0
- package/dist/ink/src/adapters/ink/components/log/log_message.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/prompt/index.d.ts +2 -0
- package/dist/ink/src/adapters/ink/components/prompt/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/prompt/prompt_renderer.d.ts +6 -0
- package/dist/ink/src/adapters/ink/components/prompt/prompt_renderer.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/screen/group_renderer.d.ts +14 -0
- package/dist/ink/src/adapters/ink/components/screen/group_renderer.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/screen/index.d.ts +7 -0
- package/dist/ink/src/adapters/ink/components/screen/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/screen/loading_message.d.ts +6 -0
- package/dist/ink/src/adapters/ink/components/screen/loading_message.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/screen/message_renderer.d.ts +6 -0
- package/dist/ink/src/adapters/ink/components/screen/message_renderer.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/screen/progress_message.d.ts +6 -0
- package/dist/ink/src/adapters/ink/components/screen/progress_message.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/screen/screen_bridge.d.ts +14 -0
- package/dist/ink/src/adapters/ink/components/screen/screen_bridge.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/screen/table_message.d.ts +6 -0
- package/dist/ink/src/adapters/ink/components/screen/table_message.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/screen_manager_bridge.d.ts +8 -0
- package/dist/ink/src/adapters/ink/components/screen_manager_bridge.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/sidebar/index.d.ts +4 -0
- package/dist/ink/src/adapters/ink/components/sidebar/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/sidebar/sidebar.d.ts +11 -0
- package/dist/ink/src/adapters/ink/components/sidebar/sidebar.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/sidebar/sidebar_item.d.ts +9 -0
- package/dist/ink/src/adapters/ink/components/sidebar/sidebar_item.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/components/sidebar/sidebar_separator.d.ts +2 -0
- package/dist/ink/src/adapters/ink/components/sidebar/sidebar_separator.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/context/index.d.ts +2 -0
- package/dist/ink/src/adapters/ink/context/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/context/logger_context.d.ts +33 -0
- package/dist/ink/src/adapters/ink/context/logger_context.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/hooks/index.d.ts +2 -0
- package/dist/ink/src/adapters/ink/hooks/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/hooks/use_theme.d.ts +7 -0
- package/dist/ink/src/adapters/ink/hooks/use_theme.d.ts.map +1 -0
- package/dist/ink/src/adapters/ink/index.d.ts +18 -0
- package/dist/ink/src/adapters/ink/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/react-shared/hooks/index.d.ts +4 -0
- package/dist/ink/src/adapters/react-shared/hooks/index.d.ts.map +1 -0
- package/dist/ink/src/adapters/react-shared/hooks/use_filter_state.d.ts +18 -0
- package/dist/ink/src/adapters/react-shared/hooks/use_filter_state.d.ts.map +1 -0
- package/dist/ink/src/adapters/react-shared/hooks/use_keyboard_manager.d.ts +26 -0
- package/dist/ink/src/adapters/react-shared/hooks/use_keyboard_manager.d.ts.map +1 -0
- package/dist/ink/src/adapters/react-shared/hooks/use_manager_subscription.d.ts +7 -0
- package/dist/ink/src/adapters/react-shared/hooks/use_manager_subscription.d.ts.map +1 -0
- package/dist/ink/src/adapters/react-shared/index.d.ts +2 -0
- package/dist/ink/src/adapters/react-shared/index.d.ts.map +1 -0
- package/dist/ink/tsconfig.ink.tsbuildinfo +1 -0
- package/dist/react/src/adapters/react-shared/hooks/index.d.ts +4 -0
- package/dist/react/src/adapters/react-shared/hooks/index.d.ts.map +1 -0
- package/dist/react/src/adapters/react-shared/hooks/use_filter_state.d.ts +18 -0
- package/dist/react/src/adapters/react-shared/hooks/use_filter_state.d.ts.map +1 -0
- package/dist/react/src/adapters/react-shared/hooks/use_keyboard_manager.d.ts +26 -0
- package/dist/react/src/adapters/react-shared/hooks/use_keyboard_manager.d.ts.map +1 -0
- package/dist/react/src/adapters/react-shared/hooks/use_manager_subscription.d.ts +7 -0
- package/dist/react/src/adapters/react-shared/hooks/use_manager_subscription.d.ts.map +1 -0
- package/dist/react/src/adapters/react-shared/index.d.ts +2 -0
- package/dist/react/src/adapters/react-shared/index.d.ts.map +1 -0
- package/dist/react/tsconfig.react.tsbuildinfo +1 -1
- package/dist/solid/tsconfig.solid.tsbuildinfo +1 -1
- package/lib/index.cjs +2177 -178
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +942 -78
- package/lib/index.d.cts.map +1 -0
- package/lib/index.d.mts +902 -38
- package/lib/index.d.mts.map +1 -0
- package/lib/index.mjs +2098 -135
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -31
- package/src/__tests__/services/logger.spec.ts +32 -0
- package/src/__tests__/services/screen.spec.ts +106 -95
- package/src/__tests__/utils/factories.ts +2 -0
- package/src/adapters/interface.ts +10 -2
- package/src/overrides/missing-adapter.override.ts +16 -6
- package/src/services/index.ts +1 -0
- package/src/services/logger.ts +7 -1
- package/src/services/readline_prompt.ts +194 -0
- package/src/services/screen.ts +106 -54
- package/src/services/screen_manager.ts +282 -74
- package/src/types/events.types.ts +84 -0
- package/src/types/index.ts +3 -0
- package/src/types/screen.types.ts +34 -0
- package/src/utils/colors/helpers.ts +0 -25
- package/src/utils/index.ts +6 -0
- package/src/utils/prompt.ts +18 -0
- package/src/utils/runtime.ts +14 -0
- package/src/utils/stdout-printer.ts +16 -5
- package/tsconfig.base.json +1 -17
- package/tsconfig.json +1 -6
- package/tsdown.config.mts +13 -70
- package/lib/adapters/react/index.cjs +0 -1768
- package/lib/adapters/react/index.cjs.map +0 -1
- package/lib/adapters/react/index.d.cts +0 -80
- package/lib/adapters/react/index.d.mts +0 -80
- package/lib/adapters/react/index.mjs +0 -1760
- package/lib/adapters/react/index.mjs.map +0 -1
- package/lib/adapters/solid/index.cjs +0 -3855
- package/lib/adapters/solid/index.cjs.map +0 -1
- package/lib/adapters/solid/index.d.cts +0 -74
- package/lib/adapters/solid/index.d.mts +0 -74
- package/lib/adapters/solid/index.mjs +0 -3847
- package/lib/adapters/solid/index.mjs.map +0 -1
- package/lib/filter_engine-DXqu9Vaq.cjs +0 -1836
- package/lib/filter_engine-DXqu9Vaq.cjs.map +0 -1
- package/lib/filter_engine-DmqhEhpA.mjs +0 -1609
- package/lib/filter_engine-DmqhEhpA.mjs.map +0 -1
- package/lib/interface-CTHQ08aY.d.mts +0 -699
- package/lib/interface-DQEIz9Mb.d.cts +0 -699
- package/src/__tests__/components/__snapshots__/filter_bar.spec.tsx.snap +0 -2293
- package/src/__tests__/components/__snapshots__/loading_message.spec.tsx.snap +0 -1414
- package/src/__tests__/components/__snapshots__/log_message.spec.tsx.snap +0 -3245
- package/src/__tests__/components/__snapshots__/progress_message.spec.tsx.snap +0 -1783
- package/src/__tests__/components/__snapshots__/prompt_renderer.spec.tsx.snap +0 -3203
- package/src/__tests__/components/__snapshots__/sidebar.spec.tsx.snap +0 -2857
- package/src/__tests__/components/filter_bar.spec.tsx +0 -190
- package/src/__tests__/components/loading_message.spec.tsx +0 -110
- package/src/__tests__/components/log_message.spec.tsx +0 -166
- package/src/__tests__/components/progress_message.spec.tsx +0 -147
- package/src/__tests__/components/prompt_renderer.spec.tsx +0 -274
- package/src/__tests__/components/sidebar.spec.tsx +0 -322
- package/src/__tests__/utils/render-utils.tsx +0 -39
- package/src/adapters/react/components/file/file_log.tsx +0 -241
- package/src/adapters/react/components/file/index.ts +0 -1
- package/src/adapters/react/components/filter/filter_bar.tsx +0 -79
- package/src/adapters/react/components/filter/index.ts +0 -1
- package/src/adapters/react/components/help/help_overlay.tsx +0 -100
- package/src/adapters/react/components/help/index.ts +0 -1
- package/src/adapters/react/components/log/index.ts +0 -1
- package/src/adapters/react/components/log/log_message.tsx +0 -102
- package/src/adapters/react/components/prompt/index.ts +0 -2
- package/src/adapters/react/components/prompt/prompt_renderer.tsx +0 -346
- package/src/adapters/react/components/screen/group_renderer.tsx +0 -64
- package/src/adapters/react/components/screen/index.ts +0 -6
- package/src/adapters/react/components/screen/loading_message.tsx +0 -43
- package/src/adapters/react/components/screen/message_renderer.tsx +0 -108
- package/src/adapters/react/components/screen/progress_message.tsx +0 -60
- package/src/adapters/react/components/screen/screen_bridge.tsx +0 -149
- package/src/adapters/react/components/screen/table_message.tsx +0 -57
- package/src/adapters/react/components/screen_manager_bridge.tsx +0 -245
- package/src/adapters/react/components/sidebar/index.ts +0 -3
- package/src/adapters/react/components/sidebar/sidebar.tsx +0 -102
- package/src/adapters/react/components/sidebar/sidebar_item.tsx +0 -50
- package/src/adapters/react/components/sidebar/sidebar_separator.tsx +0 -13
- package/src/adapters/react/context/index.ts +0 -1
- package/src/adapters/react/context/logger_context.tsx +0 -109
- package/src/adapters/react/hooks/index.ts +0 -1
- package/src/adapters/react/hooks/use_theme.ts +0 -12
- package/src/adapters/react/index.ts +0 -39
- package/src/adapters/solid/components/file/file_log.tsx +0 -221
- package/src/adapters/solid/components/file/index.ts +0 -1
- package/src/adapters/solid/components/filter/filter_bar.tsx +0 -84
- package/src/adapters/solid/components/filter/index.ts +0 -1
- package/src/adapters/solid/components/help/help_overlay.tsx +0 -106
- package/src/adapters/solid/components/help/index.ts +0 -1
- package/src/adapters/solid/components/log/index.ts +0 -1
- package/src/adapters/solid/components/log/log_message.tsx +0 -92
- package/src/adapters/solid/components/prompt/index.ts +0 -2
- package/src/adapters/solid/components/prompt/prompt_renderer.tsx +0 -350
- package/src/adapters/solid/components/screen/group_renderer.tsx +0 -61
- package/src/adapters/solid/components/screen/index.ts +0 -6
- package/src/adapters/solid/components/screen/loading_message.tsx +0 -39
- package/src/adapters/solid/components/screen/message_renderer.tsx +0 -122
- package/src/adapters/solid/components/screen/progress_message.tsx +0 -61
- package/src/adapters/solid/components/screen/screen_bridge.tsx +0 -155
- package/src/adapters/solid/components/screen/table_message.tsx +0 -58
- package/src/adapters/solid/components/screen_manager_bridge.tsx +0 -243
- package/src/adapters/solid/components/sidebar/index.ts +0 -3
- package/src/adapters/solid/components/sidebar/sidebar.tsx +0 -108
- package/src/adapters/solid/components/sidebar/sidebar_item.tsx +0 -55
- package/src/adapters/solid/components/sidebar/sidebar_separator.tsx +0 -13
- package/src/adapters/solid/context/index.ts +0 -2
- package/src/adapters/solid/context/logger_context.tsx +0 -95
- package/src/adapters/solid/hooks/index.ts +0 -1
- package/src/adapters/solid/hooks/use_theme.ts +0 -12
- package/src/adapters/solid/index.tsx +0 -43
- package/src/adapters/solid/jsx.d.ts +0 -98
- package/tsconfig.react.json +0 -16
- package/tsconfig.solid.json +0 -16
package/lib/index.mjs
CHANGED
|
@@ -1,7 +1,561 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
import { Container, Factory, Injectable, InjectionToken, Logger, LoggerOutput, inject } from "@navios/core";
|
|
2
|
+
import { EventEmitter } from "node:events";
|
|
3
|
+
import * as readline from "node:readline";
|
|
4
4
|
|
|
5
|
+
//#region src/types/screen.types.ts
|
|
6
|
+
/**
|
|
7
|
+
* Render mode determines how the TUI operates.
|
|
8
|
+
* This is set during bind() and affects prompts, screen printing, and exit behavior.
|
|
9
|
+
*/ var RenderMode = /* @__PURE__ */ function(RenderMode$1) {
|
|
10
|
+
/** bind() never called - screens print on completion, prompts return defaults */ RenderMode$1["UNBOUND"] = "unbound";
|
|
11
|
+
/** bind() called with useOpenTUI: false - stdout mode with readline prompts */ RenderMode$1["STDOUT_INTERACTIVE"] = "stdout";
|
|
12
|
+
/** bind() called with useOpenTUI: true but adapter unavailable - fallback to stdout with warning */ RenderMode$1["STDOUT_FALLBACK"] = "fallback";
|
|
13
|
+
/** Full TUI rendering active with adapter */ RenderMode$1["TUI_ACTIVE"] = "tui";
|
|
14
|
+
return RenderMode$1;
|
|
15
|
+
}({});
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/types/filter.types.ts
|
|
19
|
+
/**
|
|
20
|
+
* All log levels in order.
|
|
21
|
+
*/ const ALL_LOG_LEVELS = [
|
|
22
|
+
"verbose",
|
|
23
|
+
"debug",
|
|
24
|
+
"log",
|
|
25
|
+
"warn",
|
|
26
|
+
"error",
|
|
27
|
+
"fatal"
|
|
28
|
+
];
|
|
29
|
+
/**
|
|
30
|
+
* Create a default filter state.
|
|
31
|
+
*/ function createDefaultFilterState() {
|
|
32
|
+
return {
|
|
33
|
+
enabledLevels: new Set(ALL_LOG_LEVELS),
|
|
34
|
+
searchQuery: "",
|
|
35
|
+
isVisible: false,
|
|
36
|
+
focusedField: "search"
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Check if any filtering is active.
|
|
41
|
+
*/ function hasActiveFilter(filter) {
|
|
42
|
+
return filter.searchQuery !== "" || filter.enabledLevels.size < ALL_LOG_LEVELS.length;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/types/events.types.ts
|
|
47
|
+
/**
|
|
48
|
+
* All manager events that adapters typically subscribe to for re-renders.
|
|
49
|
+
*/ const MANAGER_EVENTS = [
|
|
50
|
+
"screen:added",
|
|
51
|
+
"screen:removed",
|
|
52
|
+
"screen:reordered",
|
|
53
|
+
"activeScreen:changed",
|
|
54
|
+
"focus:changed",
|
|
55
|
+
"sidebar:indexChanged",
|
|
56
|
+
"mode:changed"
|
|
57
|
+
];
|
|
58
|
+
/**
|
|
59
|
+
* All screen events that adapters typically subscribe to for re-renders.
|
|
60
|
+
*/ const SCREEN_EVENTS = [
|
|
61
|
+
"message:added",
|
|
62
|
+
"message:updated",
|
|
63
|
+
"messages:cleared",
|
|
64
|
+
"status:changed",
|
|
65
|
+
"visibility:changed",
|
|
66
|
+
"badge:changed",
|
|
67
|
+
"prompt:activated",
|
|
68
|
+
"prompt:updated",
|
|
69
|
+
"prompt:resolved"
|
|
70
|
+
];
|
|
71
|
+
/**
|
|
72
|
+
* Sidebar-specific events that require re-render.
|
|
73
|
+
*/ const SIDEBAR_EVENTS = [
|
|
74
|
+
"screen:added",
|
|
75
|
+
"screen:removed",
|
|
76
|
+
"screen:reordered",
|
|
77
|
+
"sidebar:indexChanged",
|
|
78
|
+
"focus:changed",
|
|
79
|
+
"activeScreen:changed"
|
|
80
|
+
];
|
|
81
|
+
/**
|
|
82
|
+
* Content area events that affect active screen changes.
|
|
83
|
+
*/ const CONTENT_MANAGER_EVENTS = ["activeScreen:changed", "focus:changed"];
|
|
84
|
+
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region src/utils/colors/log-colors.ts
|
|
87
|
+
/**
|
|
88
|
+
* Default color scheme for all log levels.
|
|
89
|
+
* Each level has a prominent border color and a subtle background tint.
|
|
90
|
+
*/ const DEFAULT_LOG_LEVEL_COLORS = {
|
|
91
|
+
verbose: {
|
|
92
|
+
border: "#6B7280",
|
|
93
|
+
background: "#6B728015"
|
|
94
|
+
},
|
|
95
|
+
debug: {
|
|
96
|
+
border: "#8B5CF6",
|
|
97
|
+
background: "#8B5CF615"
|
|
98
|
+
},
|
|
99
|
+
log: {
|
|
100
|
+
border: "#3B82F6",
|
|
101
|
+
background: "#3B82F615"
|
|
102
|
+
},
|
|
103
|
+
warn: {
|
|
104
|
+
border: "#F59E0B",
|
|
105
|
+
background: "#F59E0B15"
|
|
106
|
+
},
|
|
107
|
+
error: {
|
|
108
|
+
border: "#EF4444",
|
|
109
|
+
background: "#EF444415"
|
|
110
|
+
},
|
|
111
|
+
fatal: {
|
|
112
|
+
border: "#DC2626",
|
|
113
|
+
background: "#DC262625",
|
|
114
|
+
text: "#FCA5A5"
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Colors for semantic variants (override level colors when variant is set).
|
|
119
|
+
*/ const VARIANT_COLORS = {
|
|
120
|
+
success: {
|
|
121
|
+
border: "#22C55E",
|
|
122
|
+
background: "#22C55E15"
|
|
123
|
+
},
|
|
124
|
+
trace: {
|
|
125
|
+
border: "#6B7280",
|
|
126
|
+
background: "#6B728015"
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Error highlighting colors.
|
|
131
|
+
*/ const ERROR_HIGHLIGHT_COLORS = {
|
|
132
|
+
background: "#EF444425",
|
|
133
|
+
border: "#EF4444",
|
|
134
|
+
gutterBackground: "#EF444440"
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
//#endregion
|
|
138
|
+
//#region src/utils/colors/sidebar-colors.ts
|
|
139
|
+
/**
|
|
140
|
+
* Sidebar colors.
|
|
141
|
+
*/ const SIDEBAR_COLORS = {
|
|
142
|
+
background: void 0,
|
|
143
|
+
selectedBackground: "#1F293780",
|
|
144
|
+
hoverBackground: "#374151",
|
|
145
|
+
text: "#E5E7EB",
|
|
146
|
+
textDim: "#6B7280",
|
|
147
|
+
border: "#374151",
|
|
148
|
+
badge: "#3B82F6",
|
|
149
|
+
focusBorder: "#3B82F6"
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Screen header colors.
|
|
153
|
+
*/ const HEADER_COLORS = {
|
|
154
|
+
background: void 0,
|
|
155
|
+
text: "#F9FAFB",
|
|
156
|
+
border: "#374151"
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* Screen status indicator colors and icons.
|
|
160
|
+
*/ const STATUS_INDICATORS = {
|
|
161
|
+
waiting: {
|
|
162
|
+
icon: "○",
|
|
163
|
+
color: "#6B7280"
|
|
164
|
+
},
|
|
165
|
+
pending: {
|
|
166
|
+
icon: "◐",
|
|
167
|
+
color: "#F59E0B"
|
|
168
|
+
},
|
|
169
|
+
success: {
|
|
170
|
+
icon: "✓",
|
|
171
|
+
color: "#22C55E"
|
|
172
|
+
},
|
|
173
|
+
fail: {
|
|
174
|
+
icon: "✗",
|
|
175
|
+
color: "#EF4444"
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
/**
|
|
179
|
+
* Separator colors for sidebar sections.
|
|
180
|
+
*/ const SEPARATOR_COLORS = {
|
|
181
|
+
line: "#374151",
|
|
182
|
+
text: "#6B7280"
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
//#endregion
|
|
186
|
+
//#region src/utils/colors/progress-colors.ts
|
|
187
|
+
/**
|
|
188
|
+
* Progress bar colors.
|
|
189
|
+
*/ const PROGRESS_COLORS = {
|
|
190
|
+
border: "#3B82F6",
|
|
191
|
+
background: "#3B82F615",
|
|
192
|
+
barFilled: "#3B82F6",
|
|
193
|
+
barEmpty: "#374151",
|
|
194
|
+
text: "#E5E7EB",
|
|
195
|
+
textDim: "#9CA3AF",
|
|
196
|
+
complete: "#22C55E",
|
|
197
|
+
completeBackground: "#22C55E15",
|
|
198
|
+
failed: "#EF4444",
|
|
199
|
+
failedBackground: "#EF444415"
|
|
200
|
+
};
|
|
201
|
+
/**
|
|
202
|
+
* Group colors for collapsible log groups.
|
|
203
|
+
*/ const GROUP_COLORS = {
|
|
204
|
+
border: "#6B7280",
|
|
205
|
+
background: "#6B728010",
|
|
206
|
+
headerText: "#E5E7EB",
|
|
207
|
+
icon: "#9CA3AF"
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
//#endregion
|
|
211
|
+
//#region src/utils/colors/table-colors.ts
|
|
212
|
+
/**
|
|
213
|
+
* Table colors (uses info/blue scheme).
|
|
214
|
+
*/ const TABLE_COLORS = {
|
|
215
|
+
border: "#3B82F6",
|
|
216
|
+
background: "#3B82F615",
|
|
217
|
+
headerText: "#F9FAFB",
|
|
218
|
+
cellText: "#E5E7EB",
|
|
219
|
+
title: "#F9FAFB",
|
|
220
|
+
separator: "#3B82F650"
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
//#endregion
|
|
224
|
+
//#region src/utils/colors/file-colors.ts
|
|
225
|
+
/**
|
|
226
|
+
* File display colors (uses info/blue scheme).
|
|
227
|
+
*/ const FILE_COLORS = {
|
|
228
|
+
border: "#3B82F6",
|
|
229
|
+
background: "#3B82F615",
|
|
230
|
+
headerText: "#F9FAFB",
|
|
231
|
+
headerBackground: "#3B82F625"
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
//#endregion
|
|
235
|
+
//#region src/utils/colors/prompt-colors.ts
|
|
236
|
+
/**
|
|
237
|
+
* Prompt colors for interactive prompts.
|
|
238
|
+
*/ const PROMPT_COLORS = {
|
|
239
|
+
question: "#F9FAFB",
|
|
240
|
+
optionText: "#E5E7EB",
|
|
241
|
+
optionTextDim: "#9CA3AF",
|
|
242
|
+
optionSelected: "#3B82F6",
|
|
243
|
+
optionSelectedBackground: "#1E3A5F",
|
|
244
|
+
confirmButton: "#22C55E",
|
|
245
|
+
cancelButton: "#EF4444",
|
|
246
|
+
buttonBackground: "#374151",
|
|
247
|
+
buttonSelectedBackground: "#1F2937",
|
|
248
|
+
inputBorder: "#3B82F6",
|
|
249
|
+
inputBackground: "#1F2937",
|
|
250
|
+
inputText: "#F9FAFB",
|
|
251
|
+
inputPlaceholder: "#6B7280",
|
|
252
|
+
inputCursor: "#3B82F6",
|
|
253
|
+
border: "#374151",
|
|
254
|
+
focusBorder: "#3B82F6"
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
//#endregion
|
|
258
|
+
//#region src/utils/colors/helpers.ts
|
|
259
|
+
/**
|
|
260
|
+
* Gets colors for a specific log level.
|
|
261
|
+
*
|
|
262
|
+
* @param level - The log level
|
|
263
|
+
* @param customColors - Optional custom color map
|
|
264
|
+
*/ function getLogLevelColors(level, customColors) {
|
|
265
|
+
const defaultColors = DEFAULT_LOG_LEVEL_COLORS[level];
|
|
266
|
+
const custom = customColors?.[level];
|
|
267
|
+
return {
|
|
268
|
+
border: custom?.border ?? defaultColors.border,
|
|
269
|
+
background: custom?.background ?? defaultColors.background,
|
|
270
|
+
text: custom?.text ?? defaultColors.text
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
//#endregion
|
|
275
|
+
//#region src/utils/filetype.ts
|
|
276
|
+
/**
|
|
277
|
+
* Common file extension to filetype mapping for syntax highlighting.
|
|
278
|
+
*/ const COMMON_FILETYPES = {
|
|
279
|
+
ts: "typescript",
|
|
280
|
+
tsx: "tsx",
|
|
281
|
+
js: "javascript",
|
|
282
|
+
jsx: "javascript",
|
|
283
|
+
json: "json",
|
|
284
|
+
md: "markdown",
|
|
285
|
+
py: "python",
|
|
286
|
+
rs: "rust",
|
|
287
|
+
go: "go",
|
|
288
|
+
java: "java",
|
|
289
|
+
c: "c",
|
|
290
|
+
cpp: "cpp",
|
|
291
|
+
h: "c",
|
|
292
|
+
hpp: "cpp",
|
|
293
|
+
css: "css",
|
|
294
|
+
html: "html",
|
|
295
|
+
yaml: "yaml",
|
|
296
|
+
yml: "yaml",
|
|
297
|
+
sh: "bash",
|
|
298
|
+
bash: "bash",
|
|
299
|
+
zsh: "bash",
|
|
300
|
+
toml: "toml",
|
|
301
|
+
xml: "xml",
|
|
302
|
+
sql: "sql",
|
|
303
|
+
rb: "ruby",
|
|
304
|
+
php: "php",
|
|
305
|
+
swift: "swift",
|
|
306
|
+
kt: "kotlin",
|
|
307
|
+
scala: "scala",
|
|
308
|
+
hs: "haskell",
|
|
309
|
+
elm: "elm",
|
|
310
|
+
vue: "vue",
|
|
311
|
+
svelte: "svelte"
|
|
312
|
+
};
|
|
313
|
+
/**
|
|
314
|
+
* Resolves filetype from file path for syntax highlighting.
|
|
315
|
+
*
|
|
316
|
+
* @param filePath - Full file path or just filename
|
|
317
|
+
* @returns Filetype string for tree-sitter, or undefined
|
|
318
|
+
*/ function resolveFiletype(filePath) {
|
|
319
|
+
const lastDot = filePath.lastIndexOf(".");
|
|
320
|
+
if (lastDot === -1) return void 0;
|
|
321
|
+
return COMMON_FILETYPES[filePath.slice(lastDot + 1).toLowerCase()];
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Gets the filename from a full path.
|
|
325
|
+
*
|
|
326
|
+
* @param filePath - Full file path
|
|
327
|
+
* @returns Just the filename
|
|
328
|
+
*/ function getFileName(filePath) {
|
|
329
|
+
const lastSlash = Math.max(filePath.lastIndexOf("/"), filePath.lastIndexOf("\\"));
|
|
330
|
+
return lastSlash === -1 ? filePath : filePath.slice(lastSlash + 1);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
//#endregion
|
|
334
|
+
//#region src/utils/stdout-printer.ts
|
|
335
|
+
const RESET = "\x1B[0m";
|
|
336
|
+
const BOLD = "\x1B[1m";
|
|
337
|
+
const DIM = "\x1B[2m";
|
|
338
|
+
function hexToAnsi(hex, isForeground = true) {
|
|
339
|
+
const cleanHex = hex.replace("#", "").slice(0, 6);
|
|
340
|
+
if (!/^[0-9A-Fa-f]{6}$/.test(cleanHex)) return "";
|
|
341
|
+
const r = parseInt(cleanHex.slice(0, 2), 16);
|
|
342
|
+
const g = parseInt(cleanHex.slice(2, 4), 16);
|
|
343
|
+
const b = parseInt(cleanHex.slice(4, 6), 16);
|
|
344
|
+
return `\x1b[${isForeground ? 38 : 48};2;${r};${g};${b}m`;
|
|
345
|
+
}
|
|
346
|
+
function getLogLevelAnsiColor(level, variant) {
|
|
347
|
+
return hexToAnsi((variant ? VARIANT_COLORS[variant] : DEFAULT_LOG_LEVEL_COLORS[level]).border, true);
|
|
348
|
+
}
|
|
349
|
+
function formatLevel(level, variant) {
|
|
350
|
+
return `${getLogLevelAnsiColor(level, variant)}${BOLD}[${(variant ?? level).toUpperCase().padEnd(7)}]${RESET}`;
|
|
351
|
+
}
|
|
352
|
+
function formatTimestamp(date$2) {
|
|
353
|
+
return `${DIM}${date$2.toLocaleTimeString()}${RESET}`;
|
|
354
|
+
}
|
|
355
|
+
function printMessage(message, stream) {
|
|
356
|
+
switch (message.type) {
|
|
357
|
+
case "log": {
|
|
358
|
+
const logMessage = message;
|
|
359
|
+
const timestamp = formatTimestamp(message.timestamp);
|
|
360
|
+
const level = formatLevel(logMessage.level, logMessage.variant);
|
|
361
|
+
const label = logMessage.label ? ` ${DIM}[${logMessage.label}]${RESET}` : "";
|
|
362
|
+
stream.write(`${timestamp} ${level}${label} ${logMessage.content}\n`);
|
|
363
|
+
break;
|
|
364
|
+
}
|
|
365
|
+
case "file": {
|
|
366
|
+
const header = `${DIM}─── ${message.filePath} ───${RESET}`;
|
|
367
|
+
stream.write(`${header}\n${message.content}\n`);
|
|
368
|
+
break;
|
|
369
|
+
}
|
|
370
|
+
case "diff": {
|
|
371
|
+
const header = `${DIM}─── ${message.filePath} (diff) ───${RESET}`;
|
|
372
|
+
const coloredDiff = message.diff.split("\n").map((line) => {
|
|
373
|
+
if (line.startsWith("+") && !line.startsWith("+++")) return `\x1b[32m${line}${RESET}`;
|
|
374
|
+
else if (line.startsWith("-") && !line.startsWith("---")) return `\x1b[31m${line}${RESET}`;
|
|
375
|
+
else if (line.startsWith("@@")) return `\x1b[36m${line}${RESET}`;
|
|
376
|
+
return line;
|
|
377
|
+
}).join("\n");
|
|
378
|
+
stream.write(`${header}\n${coloredDiff}\n`);
|
|
379
|
+
break;
|
|
380
|
+
}
|
|
381
|
+
case "fileError": {
|
|
382
|
+
const header = `${DIM}─── ${message.filePath} ───${RESET}`;
|
|
383
|
+
const errorLineSet = new Set(message.errorLines);
|
|
384
|
+
const startLine = message.startLine ?? 1;
|
|
385
|
+
const numberedLines = message.content.split("\n").map((line, index) => {
|
|
386
|
+
const lineNum = startLine + index;
|
|
387
|
+
const numStr = String(lineNum).padStart(4);
|
|
388
|
+
if (errorLineSet.has(lineNum)) return `\x1b[31m${numStr} │ ${line}${RESET}`;
|
|
389
|
+
return `${DIM}${numStr}${RESET} │ ${line}`;
|
|
390
|
+
});
|
|
391
|
+
stream.write(`${header}\n${numberedLines.join("\n")}\n`);
|
|
392
|
+
break;
|
|
393
|
+
}
|
|
394
|
+
case "loading": {
|
|
395
|
+
const loadingMessage = message;
|
|
396
|
+
const status = loadingMessage.status;
|
|
397
|
+
const content = loadingMessage.resolvedContent ?? loadingMessage.content;
|
|
398
|
+
let level = "log";
|
|
399
|
+
let variant;
|
|
400
|
+
if (status === "success") {
|
|
401
|
+
level = "log";
|
|
402
|
+
variant = "success";
|
|
403
|
+
} else if (status === "fail") level = "error";
|
|
404
|
+
const timestamp = formatTimestamp(message.timestamp);
|
|
405
|
+
const levelStr = formatLevel(level, variant);
|
|
406
|
+
const prefix = status === "loading" ? "... " : "";
|
|
407
|
+
stream.write(`${timestamp} ${levelStr} ${prefix}${content}\n`);
|
|
408
|
+
break;
|
|
409
|
+
}
|
|
410
|
+
case "progress": {
|
|
411
|
+
const { label, current, total, status, resolvedContent } = message;
|
|
412
|
+
const percentage = total > 0 ? Math.round(current / total * 100) : 0;
|
|
413
|
+
const barWidth = 20;
|
|
414
|
+
const filledWidth = Math.round(percentage / 100 * barWidth);
|
|
415
|
+
const emptyWidth = barWidth - filledWidth;
|
|
416
|
+
const progressColor = hexToAnsi(PROGRESS_COLORS.barFilled);
|
|
417
|
+
const emptyColor = hexToAnsi(PROGRESS_COLORS.barEmpty);
|
|
418
|
+
const filledBar = "█".repeat(filledWidth);
|
|
419
|
+
const emptyBar = "░".repeat(emptyWidth);
|
|
420
|
+
let statusIcon = "";
|
|
421
|
+
let statusColor = "";
|
|
422
|
+
if (status === "complete") {
|
|
423
|
+
statusIcon = "✓";
|
|
424
|
+
statusColor = hexToAnsi(PROGRESS_COLORS.complete);
|
|
425
|
+
} else if (status === "failed") {
|
|
426
|
+
statusIcon = "✗";
|
|
427
|
+
statusColor = hexToAnsi(PROGRESS_COLORS.failed);
|
|
428
|
+
}
|
|
429
|
+
const displayLabel = resolvedContent ?? label;
|
|
430
|
+
const progressBar = `${progressColor}${filledBar}${RESET}${emptyColor}${emptyBar}${RESET}`;
|
|
431
|
+
const percentStr = `${String(percentage).padStart(3)}%`;
|
|
432
|
+
if (statusIcon) stream.write(`${statusColor}${statusIcon}${RESET} ${displayLabel} [${progressBar}] ${percentStr}\n`);
|
|
433
|
+
else stream.write(` ${displayLabel} [${progressBar}] ${percentStr} (${current}/${total})\n`);
|
|
434
|
+
break;
|
|
435
|
+
}
|
|
436
|
+
case "group": {
|
|
437
|
+
const { label, collapsed, isEnd } = message;
|
|
438
|
+
const groupColor = hexToAnsi(GROUP_COLORS.border);
|
|
439
|
+
const iconColor = hexToAnsi(GROUP_COLORS.icon);
|
|
440
|
+
if (isEnd) stream.write(`${groupColor}└─${RESET} ${DIM}end ${label}${RESET}\n`);
|
|
441
|
+
else {
|
|
442
|
+
const icon = collapsed ? "▶" : "▼";
|
|
443
|
+
stream.write(`${groupColor}┌─${RESET} ${iconColor}${icon}${RESET} ${BOLD}${label}${RESET}\n`);
|
|
444
|
+
}
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
case "table": {
|
|
448
|
+
const { headers, rows, title } = message;
|
|
449
|
+
const tableColor = hexToAnsi(TABLE_COLORS.border);
|
|
450
|
+
const headerColor = hexToAnsi(TABLE_COLORS.headerText);
|
|
451
|
+
const cellColor = hexToAnsi(TABLE_COLORS.cellText);
|
|
452
|
+
const colWidths = headers.map((h, i) => {
|
|
453
|
+
const maxRowWidth = rows.reduce((max, row) => Math.max(max, (row[i] ?? "").length), 0);
|
|
454
|
+
return Math.max(h.length, maxRowWidth);
|
|
455
|
+
});
|
|
456
|
+
const separator = `${tableColor}├${colWidths.map((w) => "─".repeat(w + 2)).join("┼")}┤${RESET}`;
|
|
457
|
+
const topBorder = `${tableColor}┌${colWidths.map((w) => "─".repeat(w + 2)).join("┬")}┐${RESET}`;
|
|
458
|
+
const bottomBorder = `${tableColor}└${colWidths.map((w) => "─".repeat(w + 2)).join("┴")}┘${RESET}`;
|
|
459
|
+
if (title) stream.write(`${BOLD}${title}${RESET}\n`);
|
|
460
|
+
stream.write(`${topBorder}\n`);
|
|
461
|
+
const headerRow = headers.map((h, i) => ` ${h.padEnd(colWidths[i])} `).join(`${tableColor}│${RESET}`);
|
|
462
|
+
stream.write(`${tableColor}│${RESET}${headerColor}${headerRow}${RESET}${tableColor}│${RESET}\n`);
|
|
463
|
+
stream.write(`${separator}\n`);
|
|
464
|
+
for (const row of rows) {
|
|
465
|
+
const rowStr = headers.map((_, i) => ` ${(row[i] ?? "").padEnd(colWidths[i])} `).join(`${tableColor}│${RESET}`);
|
|
466
|
+
stream.write(`${tableColor}│${RESET}${cellColor}${rowStr}${RESET}${tableColor}│${RESET}\n`);
|
|
467
|
+
}
|
|
468
|
+
stream.write(`${bottomBorder}\n`);
|
|
469
|
+
break;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Print a single message to stdout with optional screen name prefix.
|
|
475
|
+
* Used for immediate output in stdout mode (when OpenTUI is not active).
|
|
476
|
+
*/ function printSingleMessage(message, screenName, isError = false) {
|
|
477
|
+
const stream = isError ? process.stderr : process.stdout;
|
|
478
|
+
if (screenName) stream.write(`${DIM}[${screenName}]${RESET} `);
|
|
479
|
+
printMessage(message, stream);
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Print all messages to stdout (or stderr if isError)
|
|
483
|
+
*/ function printMessagesToStdout(messages, screenName, isError = false) {
|
|
484
|
+
const stream = isError ? process.stderr : process.stdout;
|
|
485
|
+
const headerColor = isError ? "\x1B[31m" : "\x1B[32m";
|
|
486
|
+
const status = isError ? "FAILED" : "COMPLETED";
|
|
487
|
+
stream.write(`\n${headerColor}${BOLD}═══ ${screenName} [${status}] ═══${RESET}\n\n`);
|
|
488
|
+
for (const message of messages) printMessage(message, stream);
|
|
489
|
+
stream.write("\n");
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
//#endregion
|
|
493
|
+
//#region src/utils/format.ts
|
|
494
|
+
/**
|
|
495
|
+
* Format an object for display with configurable depth
|
|
496
|
+
*/ function formatObject(obj, depth = 2, currentDepth = 0) {
|
|
497
|
+
if (currentDepth >= depth) {
|
|
498
|
+
if (Array.isArray(obj)) return "[Array]";
|
|
499
|
+
if (typeof obj === "object" && obj !== null) return `[${obj.constructor?.name ?? "Object"}]`;
|
|
500
|
+
return String(obj);
|
|
501
|
+
}
|
|
502
|
+
if (obj === null) return "null";
|
|
503
|
+
if (obj === void 0) return "undefined";
|
|
504
|
+
if (typeof obj === "string") return `"${obj}"`;
|
|
505
|
+
if (typeof obj === "number" || typeof obj === "boolean") return String(obj);
|
|
506
|
+
if (typeof obj === "function") return "[Function]";
|
|
507
|
+
if (obj instanceof Date) return obj.toISOString();
|
|
508
|
+
if (obj instanceof Error) return `${obj.name}: ${obj.message}`;
|
|
509
|
+
const indent = " ".repeat(currentDepth);
|
|
510
|
+
const childIndent = " ".repeat(currentDepth + 1);
|
|
511
|
+
if (Array.isArray(obj)) {
|
|
512
|
+
if (obj.length === 0) return "[]";
|
|
513
|
+
return `[\n${childIndent}${obj.map((item) => formatObject(item, depth, currentDepth + 1)).join(`,\n${childIndent}`)}\n${indent}]`;
|
|
514
|
+
}
|
|
515
|
+
if (typeof obj === "object") {
|
|
516
|
+
const entries = Object.entries(obj);
|
|
517
|
+
if (entries.length === 0) return "{}";
|
|
518
|
+
return `{\n${childIndent}${entries.map(([key, value]) => `${key}: ${formatObject(value, depth, currentDepth + 1)}`).join(`,\n${childIndent}`)}\n${indent}}`;
|
|
519
|
+
}
|
|
520
|
+
return String(obj);
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Capture a stack trace, filtering out internal frames
|
|
524
|
+
*/ function captureTrace(offset = 0) {
|
|
525
|
+
const lines = ((/* @__PURE__ */ new Error()).stack ?? "").split("\n");
|
|
526
|
+
const begin = lines.findIndex((line) => line.includes("captureTrace"));
|
|
527
|
+
return lines.slice(begin !== -1 ? begin + 1 + offset : 4).join("\n");
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
//#endregion
|
|
531
|
+
//#region src/utils/runtime.ts
|
|
532
|
+
/**
|
|
533
|
+
* Detect if running in Bun environment (OpenTUI is not supported in Bun)
|
|
534
|
+
*/ function isBunRuntime() {
|
|
535
|
+
return typeof globalThis.Bun !== "undefined";
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Dynamic import that bypasses bundler static analysis.
|
|
539
|
+
* Uses Function constructor to prevent bundlers from resolving the import at build time.
|
|
540
|
+
*/ function dynamicImport(modulePath) {
|
|
541
|
+
return new Function("modulePath", "return import(modulePath)")(modulePath);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
//#endregion
|
|
545
|
+
//#region src/utils/prompt.ts
|
|
546
|
+
/**
|
|
547
|
+
* Get the default value for a prompt based on its type.
|
|
548
|
+
* Used for resolving prompts when no interaction is possible.
|
|
549
|
+
*/ function getPromptDefaultValue(prompt) {
|
|
550
|
+
switch (prompt.type) {
|
|
551
|
+
case "choice": return prompt.defaultChoice;
|
|
552
|
+
case "confirm": return prompt.defaultValue;
|
|
553
|
+
case "input": return prompt.defaultValue;
|
|
554
|
+
case "multiChoice": return prompt.choices.filter((_, i) => prompt.selectedIndices.has(i)).map((c) => c.value);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
//#endregion
|
|
5
559
|
//#region ../../node_modules/zod/v4/core/core.js
|
|
6
560
|
/** A special constant with type `never` */
|
|
7
561
|
const NEVER = Object.freeze({ status: "aborted" });
|
|
@@ -2628,7 +3182,7 @@ function initializeContext(params) {
|
|
|
2628
3182
|
external: params?.external ?? void 0
|
|
2629
3183
|
};
|
|
2630
3184
|
}
|
|
2631
|
-
function process(schema, ctx, _params = {
|
|
3185
|
+
function process$1(schema, ctx, _params = {
|
|
2632
3186
|
path: [],
|
|
2633
3187
|
schemaPath: []
|
|
2634
3188
|
}) {
|
|
@@ -2665,7 +3219,7 @@ function process(schema, ctx, _params = {
|
|
|
2665
3219
|
const parent = schema._zod.parent;
|
|
2666
3220
|
if (parent) {
|
|
2667
3221
|
if (!result.ref) result.ref = parent;
|
|
2668
|
-
process(parent, ctx, params);
|
|
3222
|
+
process$1(parent, ctx, params);
|
|
2669
3223
|
ctx.seen.get(parent).isParent = true;
|
|
2670
3224
|
}
|
|
2671
3225
|
}
|
|
@@ -2877,7 +3431,7 @@ const createToJSONSchemaMethod = (schema, processors = {}) => (params) => {
|
|
|
2877
3431
|
...params,
|
|
2878
3432
|
processors
|
|
2879
3433
|
});
|
|
2880
|
-
process(schema, ctx);
|
|
3434
|
+
process$1(schema, ctx);
|
|
2881
3435
|
extractDefs(ctx, schema);
|
|
2882
3436
|
return finalize(ctx, schema);
|
|
2883
3437
|
};
|
|
@@ -2889,7 +3443,7 @@ const createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params)
|
|
|
2889
3443
|
io,
|
|
2890
3444
|
processors
|
|
2891
3445
|
});
|
|
2892
|
-
process(schema, ctx);
|
|
3446
|
+
process$1(schema, ctx);
|
|
2893
3447
|
extractDefs(ctx, schema);
|
|
2894
3448
|
return finalize(ctx, schema);
|
|
2895
3449
|
};
|
|
@@ -2976,7 +3530,7 @@ const arrayProcessor = (schema, ctx, _json, params) => {
|
|
|
2976
3530
|
if (typeof minimum === "number") json.minItems = minimum;
|
|
2977
3531
|
if (typeof maximum === "number") json.maxItems = maximum;
|
|
2978
3532
|
json.type = "array";
|
|
2979
|
-
json.items = process(def.element, ctx, {
|
|
3533
|
+
json.items = process$1(def.element, ctx, {
|
|
2980
3534
|
...params,
|
|
2981
3535
|
path: [...params.path, "items"]
|
|
2982
3536
|
});
|
|
@@ -2987,7 +3541,7 @@ const objectProcessor = (schema, ctx, _json, params) => {
|
|
|
2987
3541
|
json.type = "object";
|
|
2988
3542
|
json.properties = {};
|
|
2989
3543
|
const shape = def.shape;
|
|
2990
|
-
for (const key in shape) json.properties[key] = process(shape[key], ctx, {
|
|
3544
|
+
for (const key in shape) json.properties[key] = process$1(shape[key], ctx, {
|
|
2991
3545
|
...params,
|
|
2992
3546
|
path: [
|
|
2993
3547
|
...params.path,
|
|
@@ -3005,7 +3559,7 @@ const objectProcessor = (schema, ctx, _json, params) => {
|
|
|
3005
3559
|
if (def.catchall?._zod.def.type === "never") json.additionalProperties = false;
|
|
3006
3560
|
else if (!def.catchall) {
|
|
3007
3561
|
if (ctx.io === "output") json.additionalProperties = false;
|
|
3008
|
-
} else if (def.catchall) json.additionalProperties = process(def.catchall, ctx, {
|
|
3562
|
+
} else if (def.catchall) json.additionalProperties = process$1(def.catchall, ctx, {
|
|
3009
3563
|
...params,
|
|
3010
3564
|
path: [...params.path, "additionalProperties"]
|
|
3011
3565
|
});
|
|
@@ -3013,7 +3567,7 @@ const objectProcessor = (schema, ctx, _json, params) => {
|
|
|
3013
3567
|
const unionProcessor = (schema, ctx, json, params) => {
|
|
3014
3568
|
const def = schema._zod.def;
|
|
3015
3569
|
const isExclusive = def.inclusive === false;
|
|
3016
|
-
const options = def.options.map((x, i) => process(x, ctx, {
|
|
3570
|
+
const options = def.options.map((x, i) => process$1(x, ctx, {
|
|
3017
3571
|
...params,
|
|
3018
3572
|
path: [
|
|
3019
3573
|
...params.path,
|
|
@@ -3026,7 +3580,7 @@ const unionProcessor = (schema, ctx, json, params) => {
|
|
|
3026
3580
|
};
|
|
3027
3581
|
const intersectionProcessor = (schema, ctx, json, params) => {
|
|
3028
3582
|
const def = schema._zod.def;
|
|
3029
|
-
const a = process(def.left, ctx, {
|
|
3583
|
+
const a = process$1(def.left, ctx, {
|
|
3030
3584
|
...params,
|
|
3031
3585
|
path: [
|
|
3032
3586
|
...params.path,
|
|
@@ -3034,7 +3588,7 @@ const intersectionProcessor = (schema, ctx, json, params) => {
|
|
|
3034
3588
|
0
|
|
3035
3589
|
]
|
|
3036
3590
|
});
|
|
3037
|
-
const b = process(def.right, ctx, {
|
|
3591
|
+
const b = process$1(def.right, ctx, {
|
|
3038
3592
|
...params,
|
|
3039
3593
|
path: [
|
|
3040
3594
|
...params.path,
|
|
@@ -3047,7 +3601,7 @@ const intersectionProcessor = (schema, ctx, json, params) => {
|
|
|
3047
3601
|
};
|
|
3048
3602
|
const nullableProcessor = (schema, ctx, json, params) => {
|
|
3049
3603
|
const def = schema._zod.def;
|
|
3050
|
-
const inner = process(def.innerType, ctx, params);
|
|
3604
|
+
const inner = process$1(def.innerType, ctx, params);
|
|
3051
3605
|
const seen = ctx.seen.get(schema);
|
|
3052
3606
|
if (ctx.target === "openapi-3.0") {
|
|
3053
3607
|
seen.ref = def.innerType;
|
|
@@ -3056,27 +3610,27 @@ const nullableProcessor = (schema, ctx, json, params) => {
|
|
|
3056
3610
|
};
|
|
3057
3611
|
const nonoptionalProcessor = (schema, ctx, _json, params) => {
|
|
3058
3612
|
const def = schema._zod.def;
|
|
3059
|
-
process(def.innerType, ctx, params);
|
|
3613
|
+
process$1(def.innerType, ctx, params);
|
|
3060
3614
|
const seen = ctx.seen.get(schema);
|
|
3061
3615
|
seen.ref = def.innerType;
|
|
3062
3616
|
};
|
|
3063
3617
|
const defaultProcessor = (schema, ctx, json, params) => {
|
|
3064
3618
|
const def = schema._zod.def;
|
|
3065
|
-
process(def.innerType, ctx, params);
|
|
3619
|
+
process$1(def.innerType, ctx, params);
|
|
3066
3620
|
const seen = ctx.seen.get(schema);
|
|
3067
3621
|
seen.ref = def.innerType;
|
|
3068
3622
|
json.default = JSON.parse(JSON.stringify(def.defaultValue));
|
|
3069
3623
|
};
|
|
3070
3624
|
const prefaultProcessor = (schema, ctx, json, params) => {
|
|
3071
3625
|
const def = schema._zod.def;
|
|
3072
|
-
process(def.innerType, ctx, params);
|
|
3626
|
+
process$1(def.innerType, ctx, params);
|
|
3073
3627
|
const seen = ctx.seen.get(schema);
|
|
3074
3628
|
seen.ref = def.innerType;
|
|
3075
3629
|
if (ctx.io === "input") json._prefault = JSON.parse(JSON.stringify(def.defaultValue));
|
|
3076
3630
|
};
|
|
3077
3631
|
const catchProcessor = (schema, ctx, json, params) => {
|
|
3078
3632
|
const def = schema._zod.def;
|
|
3079
|
-
process(def.innerType, ctx, params);
|
|
3633
|
+
process$1(def.innerType, ctx, params);
|
|
3080
3634
|
const seen = ctx.seen.get(schema);
|
|
3081
3635
|
seen.ref = def.innerType;
|
|
3082
3636
|
let catchValue;
|
|
@@ -3090,20 +3644,20 @@ const catchProcessor = (schema, ctx, json, params) => {
|
|
|
3090
3644
|
const pipeProcessor = (schema, ctx, _json, params) => {
|
|
3091
3645
|
const def = schema._zod.def;
|
|
3092
3646
|
const innerType = ctx.io === "input" ? def.in._zod.def.type === "transform" ? def.out : def.in : def.out;
|
|
3093
|
-
process(innerType, ctx, params);
|
|
3647
|
+
process$1(innerType, ctx, params);
|
|
3094
3648
|
const seen = ctx.seen.get(schema);
|
|
3095
3649
|
seen.ref = innerType;
|
|
3096
3650
|
};
|
|
3097
3651
|
const readonlyProcessor = (schema, ctx, json, params) => {
|
|
3098
3652
|
const def = schema._zod.def;
|
|
3099
|
-
process(def.innerType, ctx, params);
|
|
3653
|
+
process$1(def.innerType, ctx, params);
|
|
3100
3654
|
const seen = ctx.seen.get(schema);
|
|
3101
3655
|
seen.ref = def.innerType;
|
|
3102
3656
|
json.readOnly = true;
|
|
3103
3657
|
};
|
|
3104
3658
|
const optionalProcessor = (schema, ctx, _json, params) => {
|
|
3105
3659
|
const def = schema._zod.def;
|
|
3106
|
-
process(def.innerType, ctx, params);
|
|
3660
|
+
process$1(def.innerType, ctx, params);
|
|
3107
3661
|
const seen = ctx.seen.get(schema);
|
|
3108
3662
|
seen.ref = def.innerType;
|
|
3109
3663
|
};
|
|
@@ -3782,6 +4336,14 @@ const ScreenLogger = InjectionToken.create("ScreenLoggerInstance", LoggerOptions
|
|
|
3782
4336
|
//#region src/tokens/prompt.ts
|
|
3783
4337
|
const Prompt = InjectionToken.create("Prompt", PromptOptionsSchema);
|
|
3784
4338
|
|
|
4339
|
+
//#endregion
|
|
4340
|
+
//#region src/tokens/adapter.ts
|
|
4341
|
+
/**
|
|
4342
|
+
* Injection token for the TUI rendering adapter.
|
|
4343
|
+
* Import the specific adapter (e.g., '@navios/commander-tui/adapters/react')
|
|
4344
|
+
* to register an implementation.
|
|
4345
|
+
*/ const Adapter = InjectionToken.create("Adapter");
|
|
4346
|
+
|
|
3785
4347
|
//#endregion
|
|
3786
4348
|
//#region src/tokens/screen-manager.ts
|
|
3787
4349
|
/**
|
|
@@ -4991,6 +5553,7 @@ function _apply_decs_2203_r$3(targetClass, memberDecs, classDecs, parentClass) {
|
|
|
4991
5553
|
return (_apply_decs_2203_r$3 = applyDecs2203RFactory$3())(targetClass, memberDecs, classDecs, parentClass);
|
|
4992
5554
|
}
|
|
4993
5555
|
var _dec$3, _initClass$3;
|
|
5556
|
+
const MISSING_ADAPTER_ERROR = "Adapter not registered, add import statement for @navios/tui-adapter-react, @navios/tui-adapter-ink or @navios/tui-adapter-solid to your module";
|
|
4994
5557
|
let _MissingAdapterOverride;
|
|
4995
5558
|
_dec$3 = Injectable({
|
|
4996
5559
|
token: Adapter,
|
|
@@ -5000,20 +5563,698 @@ var MissingAdapterOverride = class {
|
|
|
5000
5563
|
static {
|
|
5001
5564
|
({c: [_MissingAdapterOverride, _initClass$3]} = _apply_decs_2203_r$3(this, [], [_dec$3]));
|
|
5002
5565
|
}
|
|
5566
|
+
/**
|
|
5567
|
+
* Marker property to identify this as the missing adapter fallback.
|
|
5568
|
+
* Used by ScreenManager.bind() to detect and handle graceful fallback.
|
|
5569
|
+
*/ isMissingAdapter = true;
|
|
5003
5570
|
createRoot() {
|
|
5004
|
-
throw new Error(
|
|
5571
|
+
throw new Error(MISSING_ADAPTER_ERROR);
|
|
5005
5572
|
}
|
|
5006
5573
|
renderToRoot() {
|
|
5007
|
-
throw new Error(
|
|
5574
|
+
throw new Error(MISSING_ADAPTER_ERROR);
|
|
5008
5575
|
}
|
|
5009
5576
|
static {
|
|
5010
5577
|
_initClass$3();
|
|
5011
5578
|
}
|
|
5012
5579
|
};
|
|
5013
5580
|
|
|
5581
|
+
//#endregion
|
|
5582
|
+
//#region src/themes/dark.ts
|
|
5583
|
+
/**
|
|
5584
|
+
* Default dark theme.
|
|
5585
|
+
* Migrated from the scattered color files in utils/colors/.
|
|
5586
|
+
*/ const darkTheme = {
|
|
5587
|
+
name: "dark",
|
|
5588
|
+
logLevels: {
|
|
5589
|
+
verbose: {
|
|
5590
|
+
border: "#6B7280",
|
|
5591
|
+
background: "#6B728015"
|
|
5592
|
+
},
|
|
5593
|
+
debug: {
|
|
5594
|
+
border: "#8B5CF6",
|
|
5595
|
+
background: "#8B5CF615"
|
|
5596
|
+
},
|
|
5597
|
+
log: {
|
|
5598
|
+
border: "#3B82F6",
|
|
5599
|
+
background: "#3B82F615"
|
|
5600
|
+
},
|
|
5601
|
+
warn: {
|
|
5602
|
+
border: "#F59E0B",
|
|
5603
|
+
background: "#F59E0B15"
|
|
5604
|
+
},
|
|
5605
|
+
error: {
|
|
5606
|
+
border: "#EF4444",
|
|
5607
|
+
background: "#EF444415"
|
|
5608
|
+
},
|
|
5609
|
+
fatal: {
|
|
5610
|
+
border: "#DC2626",
|
|
5611
|
+
background: "#DC262625",
|
|
5612
|
+
text: "#FCA5A5"
|
|
5613
|
+
}
|
|
5614
|
+
},
|
|
5615
|
+
sidebar: {
|
|
5616
|
+
background: void 0,
|
|
5617
|
+
selectedBackground: "#1F293780",
|
|
5618
|
+
hoverBackground: "#374151",
|
|
5619
|
+
text: "#E5E7EB",
|
|
5620
|
+
textDim: "#6B7280",
|
|
5621
|
+
border: "#374151",
|
|
5622
|
+
badge: "#3B82F6",
|
|
5623
|
+
focusBorder: "#3B82F6"
|
|
5624
|
+
},
|
|
5625
|
+
header: {
|
|
5626
|
+
background: void 0,
|
|
5627
|
+
text: "#F9FAFB",
|
|
5628
|
+
border: "#374151"
|
|
5629
|
+
},
|
|
5630
|
+
statusIndicators: {
|
|
5631
|
+
waiting: {
|
|
5632
|
+
icon: "○",
|
|
5633
|
+
color: "#6B7280"
|
|
5634
|
+
},
|
|
5635
|
+
pending: {
|
|
5636
|
+
icon: "◐",
|
|
5637
|
+
color: "#F59E0B"
|
|
5638
|
+
},
|
|
5639
|
+
success: {
|
|
5640
|
+
icon: "✓",
|
|
5641
|
+
color: "#22C55E"
|
|
5642
|
+
},
|
|
5643
|
+
fail: {
|
|
5644
|
+
icon: "✗",
|
|
5645
|
+
color: "#EF4444"
|
|
5646
|
+
},
|
|
5647
|
+
static: {
|
|
5648
|
+
icon: "●",
|
|
5649
|
+
color: "#3B82F6"
|
|
5650
|
+
}
|
|
5651
|
+
},
|
|
5652
|
+
separator: {
|
|
5653
|
+
line: "#374151",
|
|
5654
|
+
text: "#6B7280"
|
|
5655
|
+
},
|
|
5656
|
+
progress: {
|
|
5657
|
+
border: "#3B82F6",
|
|
5658
|
+
background: "#3B82F615",
|
|
5659
|
+
barFilled: "#3B82F6",
|
|
5660
|
+
barEmpty: "#374151",
|
|
5661
|
+
text: "#E5E7EB",
|
|
5662
|
+
textDim: "#9CA3AF",
|
|
5663
|
+
complete: "#22C55E",
|
|
5664
|
+
completeBackground: "#22C55E15",
|
|
5665
|
+
failed: "#EF4444",
|
|
5666
|
+
failedBackground: "#EF444415"
|
|
5667
|
+
},
|
|
5668
|
+
group: {
|
|
5669
|
+
border: "#6B7280",
|
|
5670
|
+
background: "#6B728010",
|
|
5671
|
+
headerText: "#E5E7EB",
|
|
5672
|
+
icon: "#9CA3AF"
|
|
5673
|
+
},
|
|
5674
|
+
table: {
|
|
5675
|
+
border: "#3B82F6",
|
|
5676
|
+
background: "#3B82F615",
|
|
5677
|
+
headerText: "#F9FAFB",
|
|
5678
|
+
cellText: "#E5E7EB",
|
|
5679
|
+
title: "#F9FAFB",
|
|
5680
|
+
separator: "#3B82F650"
|
|
5681
|
+
},
|
|
5682
|
+
file: {
|
|
5683
|
+
border: "#3B82F6",
|
|
5684
|
+
background: "#3B82F615",
|
|
5685
|
+
headerText: "#F9FAFB",
|
|
5686
|
+
headerBackground: "#3B82F625"
|
|
5687
|
+
},
|
|
5688
|
+
prompt: {
|
|
5689
|
+
question: "#F9FAFB",
|
|
5690
|
+
optionText: "#E5E7EB",
|
|
5691
|
+
optionTextDim: "#9CA3AF",
|
|
5692
|
+
optionSelected: "#3B82F6",
|
|
5693
|
+
optionSelectedBackground: "#1E3A5F",
|
|
5694
|
+
confirmButton: "#22C55E",
|
|
5695
|
+
cancelButton: "#EF4444",
|
|
5696
|
+
buttonBackground: "#374151",
|
|
5697
|
+
buttonSelectedBackground: "#1F2937",
|
|
5698
|
+
inputBorder: "#3B82F6",
|
|
5699
|
+
inputBackground: "#1F2937",
|
|
5700
|
+
inputText: "#F9FAFB",
|
|
5701
|
+
inputPlaceholder: "#6B7280",
|
|
5702
|
+
inputCursor: "#3B82F6",
|
|
5703
|
+
border: "#374151",
|
|
5704
|
+
focusBorder: "#3B82F6"
|
|
5705
|
+
},
|
|
5706
|
+
errorHighlight: {
|
|
5707
|
+
background: "#EF444425",
|
|
5708
|
+
border: "#EF4444",
|
|
5709
|
+
gutterBackground: "#EF444440"
|
|
5710
|
+
},
|
|
5711
|
+
filter: {
|
|
5712
|
+
background: "#1F293780",
|
|
5713
|
+
border: "#3B82F6",
|
|
5714
|
+
text: "#E5E7EB",
|
|
5715
|
+
textDim: "#6B7280",
|
|
5716
|
+
inputBackground: "#1F2937",
|
|
5717
|
+
inputText: "#F9FAFB",
|
|
5718
|
+
inputPlaceholder: "#6B7280",
|
|
5719
|
+
cursor: "#3B82F6",
|
|
5720
|
+
activeLevel: "#3B82F6",
|
|
5721
|
+
inactiveLevel: "#4B5563"
|
|
5722
|
+
},
|
|
5723
|
+
help: {
|
|
5724
|
+
background: "#1F2937",
|
|
5725
|
+
border: "#3B82F6",
|
|
5726
|
+
title: "#F9FAFB",
|
|
5727
|
+
category: "#3B82F6",
|
|
5728
|
+
key: "#F59E0B",
|
|
5729
|
+
description: "#E5E7EB",
|
|
5730
|
+
hint: "#6B7280"
|
|
5731
|
+
},
|
|
5732
|
+
colors: {
|
|
5733
|
+
primary: "#3B82F6",
|
|
5734
|
+
secondary: "#8B5CF6",
|
|
5735
|
+
success: "#22C55E",
|
|
5736
|
+
warning: "#F59E0B",
|
|
5737
|
+
error: "#EF4444",
|
|
5738
|
+
muted: "#6B7280",
|
|
5739
|
+
background: "#111827",
|
|
5740
|
+
foreground: "#F9FAFB"
|
|
5741
|
+
}
|
|
5742
|
+
};
|
|
5743
|
+
|
|
5744
|
+
//#endregion
|
|
5745
|
+
//#region src/themes/light.ts
|
|
5746
|
+
/**
|
|
5747
|
+
* Light theme for terminals with light backgrounds.
|
|
5748
|
+
*/ const lightTheme = {
|
|
5749
|
+
name: "light",
|
|
5750
|
+
logLevels: {
|
|
5751
|
+
verbose: {
|
|
5752
|
+
border: "#9CA3AF",
|
|
5753
|
+
background: "#F3F4F6"
|
|
5754
|
+
},
|
|
5755
|
+
debug: {
|
|
5756
|
+
border: "#7C3AED",
|
|
5757
|
+
background: "#EDE9FE"
|
|
5758
|
+
},
|
|
5759
|
+
log: {
|
|
5760
|
+
border: "#2563EB",
|
|
5761
|
+
background: "#DBEAFE"
|
|
5762
|
+
},
|
|
5763
|
+
warn: {
|
|
5764
|
+
border: "#D97706",
|
|
5765
|
+
background: "#FEF3C7"
|
|
5766
|
+
},
|
|
5767
|
+
error: {
|
|
5768
|
+
border: "#DC2626",
|
|
5769
|
+
background: "#FEE2E2"
|
|
5770
|
+
},
|
|
5771
|
+
fatal: {
|
|
5772
|
+
border: "#991B1B",
|
|
5773
|
+
background: "#FECACA",
|
|
5774
|
+
text: "#7F1D1D"
|
|
5775
|
+
}
|
|
5776
|
+
},
|
|
5777
|
+
sidebar: {
|
|
5778
|
+
background: "#F9FAFB",
|
|
5779
|
+
selectedBackground: "#E5E7EB",
|
|
5780
|
+
hoverBackground: "#F3F4F6",
|
|
5781
|
+
text: "#1F2937",
|
|
5782
|
+
textDim: "#6B7280",
|
|
5783
|
+
border: "#D1D5DB",
|
|
5784
|
+
badge: "#2563EB",
|
|
5785
|
+
focusBorder: "#2563EB"
|
|
5786
|
+
},
|
|
5787
|
+
header: {
|
|
5788
|
+
background: "#F9FAFB",
|
|
5789
|
+
text: "#111827",
|
|
5790
|
+
border: "#D1D5DB"
|
|
5791
|
+
},
|
|
5792
|
+
statusIndicators: {
|
|
5793
|
+
waiting: {
|
|
5794
|
+
icon: "○",
|
|
5795
|
+
color: "#9CA3AF"
|
|
5796
|
+
},
|
|
5797
|
+
pending: {
|
|
5798
|
+
icon: "◐",
|
|
5799
|
+
color: "#D97706"
|
|
5800
|
+
},
|
|
5801
|
+
success: {
|
|
5802
|
+
icon: "✓",
|
|
5803
|
+
color: "#16A34A"
|
|
5804
|
+
},
|
|
5805
|
+
fail: {
|
|
5806
|
+
icon: "✗",
|
|
5807
|
+
color: "#DC2626"
|
|
5808
|
+
},
|
|
5809
|
+
static: {
|
|
5810
|
+
icon: "●",
|
|
5811
|
+
color: "#2563EB"
|
|
5812
|
+
}
|
|
5813
|
+
},
|
|
5814
|
+
separator: {
|
|
5815
|
+
line: "#D1D5DB",
|
|
5816
|
+
text: "#6B7280"
|
|
5817
|
+
},
|
|
5818
|
+
progress: {
|
|
5819
|
+
border: "#2563EB",
|
|
5820
|
+
background: "#DBEAFE",
|
|
5821
|
+
barFilled: "#2563EB",
|
|
5822
|
+
barEmpty: "#E5E7EB",
|
|
5823
|
+
text: "#1F2937",
|
|
5824
|
+
textDim: "#6B7280",
|
|
5825
|
+
complete: "#16A34A",
|
|
5826
|
+
completeBackground: "#DCFCE7",
|
|
5827
|
+
failed: "#DC2626",
|
|
5828
|
+
failedBackground: "#FEE2E2"
|
|
5829
|
+
},
|
|
5830
|
+
group: {
|
|
5831
|
+
border: "#9CA3AF",
|
|
5832
|
+
background: "#F3F4F6",
|
|
5833
|
+
headerText: "#1F2937",
|
|
5834
|
+
icon: "#6B7280"
|
|
5835
|
+
},
|
|
5836
|
+
table: {
|
|
5837
|
+
border: "#2563EB",
|
|
5838
|
+
background: "#DBEAFE",
|
|
5839
|
+
headerText: "#111827",
|
|
5840
|
+
cellText: "#1F2937",
|
|
5841
|
+
title: "#111827",
|
|
5842
|
+
separator: "#93C5FD"
|
|
5843
|
+
},
|
|
5844
|
+
file: {
|
|
5845
|
+
border: "#2563EB",
|
|
5846
|
+
background: "#DBEAFE",
|
|
5847
|
+
headerText: "#111827",
|
|
5848
|
+
headerBackground: "#BFDBFE"
|
|
5849
|
+
},
|
|
5850
|
+
prompt: {
|
|
5851
|
+
question: "#111827",
|
|
5852
|
+
optionText: "#1F2937",
|
|
5853
|
+
optionTextDim: "#6B7280",
|
|
5854
|
+
optionSelected: "#2563EB",
|
|
5855
|
+
optionSelectedBackground: "#DBEAFE",
|
|
5856
|
+
confirmButton: "#16A34A",
|
|
5857
|
+
cancelButton: "#DC2626",
|
|
5858
|
+
buttonBackground: "#E5E7EB",
|
|
5859
|
+
buttonSelectedBackground: "#D1D5DB",
|
|
5860
|
+
inputBorder: "#2563EB",
|
|
5861
|
+
inputBackground: "#FFFFFF",
|
|
5862
|
+
inputText: "#111827",
|
|
5863
|
+
inputPlaceholder: "#9CA3AF",
|
|
5864
|
+
inputCursor: "#2563EB",
|
|
5865
|
+
border: "#D1D5DB",
|
|
5866
|
+
focusBorder: "#2563EB"
|
|
5867
|
+
},
|
|
5868
|
+
errorHighlight: {
|
|
5869
|
+
background: "#FEE2E2",
|
|
5870
|
+
border: "#DC2626",
|
|
5871
|
+
gutterBackground: "#FECACA"
|
|
5872
|
+
},
|
|
5873
|
+
filter: {
|
|
5874
|
+
background: "#F3F4F6",
|
|
5875
|
+
border: "#2563EB",
|
|
5876
|
+
text: "#1F2937",
|
|
5877
|
+
textDim: "#6B7280",
|
|
5878
|
+
inputBackground: "#FFFFFF",
|
|
5879
|
+
inputText: "#111827",
|
|
5880
|
+
inputPlaceholder: "#9CA3AF",
|
|
5881
|
+
cursor: "#2563EB",
|
|
5882
|
+
activeLevel: "#2563EB",
|
|
5883
|
+
inactiveLevel: "#D1D5DB"
|
|
5884
|
+
},
|
|
5885
|
+
help: {
|
|
5886
|
+
background: "#FFFFFF",
|
|
5887
|
+
border: "#2563EB",
|
|
5888
|
+
title: "#111827",
|
|
5889
|
+
category: "#2563EB",
|
|
5890
|
+
key: "#D97706",
|
|
5891
|
+
description: "#1F2937",
|
|
5892
|
+
hint: "#6B7280"
|
|
5893
|
+
},
|
|
5894
|
+
colors: {
|
|
5895
|
+
primary: "#2563EB",
|
|
5896
|
+
secondary: "#7C3AED",
|
|
5897
|
+
success: "#16A34A",
|
|
5898
|
+
warning: "#D97706",
|
|
5899
|
+
error: "#DC2626",
|
|
5900
|
+
muted: "#6B7280",
|
|
5901
|
+
background: "#FFFFFF",
|
|
5902
|
+
foreground: "#111827"
|
|
5903
|
+
}
|
|
5904
|
+
};
|
|
5905
|
+
|
|
5906
|
+
//#endregion
|
|
5907
|
+
//#region src/themes/high-contrast.ts
|
|
5908
|
+
/**
|
|
5909
|
+
* High contrast theme for accessibility.
|
|
5910
|
+
* Uses pure black/white with saturated colors for maximum visibility.
|
|
5911
|
+
*/ const highContrastTheme = {
|
|
5912
|
+
name: "high-contrast",
|
|
5913
|
+
logLevels: {
|
|
5914
|
+
verbose: {
|
|
5915
|
+
border: "#FFFFFF",
|
|
5916
|
+
background: "#1A1A1A",
|
|
5917
|
+
text: "#FFFFFF"
|
|
5918
|
+
},
|
|
5919
|
+
debug: {
|
|
5920
|
+
border: "#A855F7",
|
|
5921
|
+
background: "#1A1A1A",
|
|
5922
|
+
text: "#E9D5FF"
|
|
5923
|
+
},
|
|
5924
|
+
log: {
|
|
5925
|
+
border: "#3B82F6",
|
|
5926
|
+
background: "#1A1A1A",
|
|
5927
|
+
text: "#BFDBFE"
|
|
5928
|
+
},
|
|
5929
|
+
warn: {
|
|
5930
|
+
border: "#FBBF24",
|
|
5931
|
+
background: "#1A1A1A",
|
|
5932
|
+
text: "#FEF08A"
|
|
5933
|
+
},
|
|
5934
|
+
error: {
|
|
5935
|
+
border: "#EF4444",
|
|
5936
|
+
background: "#1A1A1A",
|
|
5937
|
+
text: "#FECACA"
|
|
5938
|
+
},
|
|
5939
|
+
fatal: {
|
|
5940
|
+
border: "#FF0000",
|
|
5941
|
+
background: "#330000",
|
|
5942
|
+
text: "#FFFFFF"
|
|
5943
|
+
}
|
|
5944
|
+
},
|
|
5945
|
+
sidebar: {
|
|
5946
|
+
background: "#000000",
|
|
5947
|
+
selectedBackground: "#333333",
|
|
5948
|
+
hoverBackground: "#1A1A1A",
|
|
5949
|
+
text: "#FFFFFF",
|
|
5950
|
+
textDim: "#AAAAAA",
|
|
5951
|
+
border: "#FFFFFF",
|
|
5952
|
+
badge: "#FFFF00",
|
|
5953
|
+
focusBorder: "#FFFF00"
|
|
5954
|
+
},
|
|
5955
|
+
header: {
|
|
5956
|
+
background: "#000000",
|
|
5957
|
+
text: "#FFFFFF",
|
|
5958
|
+
border: "#FFFFFF"
|
|
5959
|
+
},
|
|
5960
|
+
statusIndicators: {
|
|
5961
|
+
waiting: {
|
|
5962
|
+
icon: "○",
|
|
5963
|
+
color: "#AAAAAA"
|
|
5964
|
+
},
|
|
5965
|
+
pending: {
|
|
5966
|
+
icon: "◐",
|
|
5967
|
+
color: "#FBBF24"
|
|
5968
|
+
},
|
|
5969
|
+
success: {
|
|
5970
|
+
icon: "✓",
|
|
5971
|
+
color: "#22C55E"
|
|
5972
|
+
},
|
|
5973
|
+
fail: {
|
|
5974
|
+
icon: "✗",
|
|
5975
|
+
color: "#EF4444"
|
|
5976
|
+
},
|
|
5977
|
+
static: {
|
|
5978
|
+
icon: "●",
|
|
5979
|
+
color: "#00FFFF"
|
|
5980
|
+
}
|
|
5981
|
+
},
|
|
5982
|
+
separator: {
|
|
5983
|
+
line: "#FFFFFF",
|
|
5984
|
+
text: "#AAAAAA"
|
|
5985
|
+
},
|
|
5986
|
+
progress: {
|
|
5987
|
+
border: "#3B82F6",
|
|
5988
|
+
background: "#1A1A1A",
|
|
5989
|
+
barFilled: "#3B82F6",
|
|
5990
|
+
barEmpty: "#333333",
|
|
5991
|
+
text: "#FFFFFF",
|
|
5992
|
+
textDim: "#AAAAAA",
|
|
5993
|
+
complete: "#22C55E",
|
|
5994
|
+
completeBackground: "#1A1A1A",
|
|
5995
|
+
failed: "#EF4444",
|
|
5996
|
+
failedBackground: "#1A1A1A"
|
|
5997
|
+
},
|
|
5998
|
+
group: {
|
|
5999
|
+
border: "#FFFFFF",
|
|
6000
|
+
background: "#1A1A1A",
|
|
6001
|
+
headerText: "#FFFFFF",
|
|
6002
|
+
icon: "#AAAAAA"
|
|
6003
|
+
},
|
|
6004
|
+
table: {
|
|
6005
|
+
border: "#FFFFFF",
|
|
6006
|
+
background: "#1A1A1A",
|
|
6007
|
+
headerText: "#FFFFFF",
|
|
6008
|
+
cellText: "#FFFFFF",
|
|
6009
|
+
title: "#FFFFFF",
|
|
6010
|
+
separator: "#666666"
|
|
6011
|
+
},
|
|
6012
|
+
file: {
|
|
6013
|
+
border: "#FFFFFF",
|
|
6014
|
+
background: "#1A1A1A",
|
|
6015
|
+
headerText: "#FFFFFF",
|
|
6016
|
+
headerBackground: "#333333"
|
|
6017
|
+
},
|
|
6018
|
+
prompt: {
|
|
6019
|
+
question: "#FFFFFF",
|
|
6020
|
+
optionText: "#FFFFFF",
|
|
6021
|
+
optionTextDim: "#AAAAAA",
|
|
6022
|
+
optionSelected: "#FFFF00",
|
|
6023
|
+
optionSelectedBackground: "#333333",
|
|
6024
|
+
confirmButton: "#22C55E",
|
|
6025
|
+
cancelButton: "#EF4444",
|
|
6026
|
+
buttonBackground: "#333333",
|
|
6027
|
+
buttonSelectedBackground: "#1A1A1A",
|
|
6028
|
+
inputBorder: "#FFFF00",
|
|
6029
|
+
inputBackground: "#1A1A1A",
|
|
6030
|
+
inputText: "#FFFFFF",
|
|
6031
|
+
inputPlaceholder: "#666666",
|
|
6032
|
+
inputCursor: "#FFFF00",
|
|
6033
|
+
border: "#FFFFFF",
|
|
6034
|
+
focusBorder: "#FFFF00"
|
|
6035
|
+
},
|
|
6036
|
+
errorHighlight: {
|
|
6037
|
+
background: "#330000",
|
|
6038
|
+
border: "#FF0000",
|
|
6039
|
+
gutterBackground: "#660000"
|
|
6040
|
+
},
|
|
6041
|
+
filter: {
|
|
6042
|
+
background: "#1A1A1A",
|
|
6043
|
+
border: "#FFFF00",
|
|
6044
|
+
text: "#FFFFFF",
|
|
6045
|
+
textDim: "#AAAAAA",
|
|
6046
|
+
inputBackground: "#000000",
|
|
6047
|
+
inputText: "#FFFFFF",
|
|
6048
|
+
inputPlaceholder: "#666666",
|
|
6049
|
+
cursor: "#FFFF00",
|
|
6050
|
+
activeLevel: "#FFFF00",
|
|
6051
|
+
inactiveLevel: "#666666"
|
|
6052
|
+
},
|
|
6053
|
+
help: {
|
|
6054
|
+
background: "#000000",
|
|
6055
|
+
border: "#FFFFFF",
|
|
6056
|
+
title: "#FFFFFF",
|
|
6057
|
+
category: "#FFFF00",
|
|
6058
|
+
key: "#00FFFF",
|
|
6059
|
+
description: "#FFFFFF",
|
|
6060
|
+
hint: "#AAAAAA"
|
|
6061
|
+
},
|
|
6062
|
+
colors: {
|
|
6063
|
+
primary: "#3B82F6",
|
|
6064
|
+
secondary: "#A855F7",
|
|
6065
|
+
success: "#22C55E",
|
|
6066
|
+
warning: "#FBBF24",
|
|
6067
|
+
error: "#EF4444",
|
|
6068
|
+
muted: "#AAAAAA",
|
|
6069
|
+
background: "#000000",
|
|
6070
|
+
foreground: "#FFFFFF"
|
|
6071
|
+
}
|
|
6072
|
+
};
|
|
6073
|
+
|
|
6074
|
+
//#endregion
|
|
6075
|
+
//#region src/themes/utils.ts
|
|
6076
|
+
/**
|
|
6077
|
+
* Deep merge two objects, with source taking precedence.
|
|
6078
|
+
*/ function deepMerge(target, source) {
|
|
6079
|
+
const result = { ...target };
|
|
6080
|
+
for (const key in source) if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
6081
|
+
const sourceValue = source[key];
|
|
6082
|
+
const targetValue = target[key];
|
|
6083
|
+
if (sourceValue !== void 0 && typeof sourceValue === "object" && sourceValue !== null && !Array.isArray(sourceValue) && typeof targetValue === "object" && targetValue !== null && !Array.isArray(targetValue)) result[key] = deepMerge(targetValue, sourceValue);
|
|
6084
|
+
else if (sourceValue !== void 0) result[key] = sourceValue;
|
|
6085
|
+
}
|
|
6086
|
+
return result;
|
|
6087
|
+
}
|
|
6088
|
+
/**
|
|
6089
|
+
* Get a theme by preset name.
|
|
6090
|
+
*/ function getThemePreset(preset) {
|
|
6091
|
+
switch (preset) {
|
|
6092
|
+
case "dark": return darkTheme;
|
|
6093
|
+
case "light": return lightTheme;
|
|
6094
|
+
case "high-contrast": return highContrastTheme;
|
|
6095
|
+
default: return darkTheme;
|
|
6096
|
+
}
|
|
6097
|
+
}
|
|
6098
|
+
/**
|
|
6099
|
+
* Merge a base theme with partial overrides.
|
|
6100
|
+
*/ function mergeThemes(base, overrides) {
|
|
6101
|
+
return deepMerge(base, overrides);
|
|
6102
|
+
}
|
|
6103
|
+
/**
|
|
6104
|
+
* Create a custom theme by extending the dark theme with overrides.
|
|
6105
|
+
*/ function createTheme(overrides) {
|
|
6106
|
+
return mergeThemes(darkTheme, overrides);
|
|
6107
|
+
}
|
|
6108
|
+
/**
|
|
6109
|
+
* Create a custom theme by extending a specific base theme.
|
|
6110
|
+
*/ function createThemeFrom(base, overrides) {
|
|
6111
|
+
return mergeThemes(typeof base === "string" ? getThemePreset(base) : base, overrides);
|
|
6112
|
+
}
|
|
6113
|
+
/**
|
|
6114
|
+
* Resolve a theme value which can be a Theme object or a preset name.
|
|
6115
|
+
*/ function resolveTheme(theme) {
|
|
6116
|
+
return typeof theme === "string" ? getThemePreset(theme) : theme;
|
|
6117
|
+
}
|
|
6118
|
+
|
|
6119
|
+
//#endregion
|
|
6120
|
+
//#region src/services/readline_prompt.ts
|
|
6121
|
+
/**
|
|
6122
|
+
* Readline-based prompt service for stdout mode.
|
|
6123
|
+
* Provides basic interactive prompts when TUI adapter is not available.
|
|
6124
|
+
*/ var ReadlinePromptService = class {
|
|
6125
|
+
rl = null;
|
|
6126
|
+
promptQueue = [];
|
|
6127
|
+
isProcessing = false;
|
|
6128
|
+
ensureInterface() {
|
|
6129
|
+
if (!this.rl) this.rl = readline.createInterface({
|
|
6130
|
+
input: process.stdin,
|
|
6131
|
+
output: process.stdout
|
|
6132
|
+
});
|
|
6133
|
+
return this.rl;
|
|
6134
|
+
}
|
|
6135
|
+
/**
|
|
6136
|
+
* Handle a prompt interactively via readline.
|
|
6137
|
+
* Prompts are queued and processed sequentially.
|
|
6138
|
+
*/ async handlePrompt(prompt) {
|
|
6139
|
+
return new Promise((resolve) => {
|
|
6140
|
+
this.promptQueue.push({
|
|
6141
|
+
prompt,
|
|
6142
|
+
resolve
|
|
6143
|
+
});
|
|
6144
|
+
this.processQueue();
|
|
6145
|
+
});
|
|
6146
|
+
}
|
|
6147
|
+
async processQueue() {
|
|
6148
|
+
if (this.isProcessing || this.promptQueue.length === 0) return;
|
|
6149
|
+
this.isProcessing = true;
|
|
6150
|
+
while (this.promptQueue.length > 0) {
|
|
6151
|
+
const { prompt, resolve } = this.promptQueue.shift();
|
|
6152
|
+
resolve(await this.processPrompt(prompt));
|
|
6153
|
+
}
|
|
6154
|
+
this.isProcessing = false;
|
|
6155
|
+
}
|
|
6156
|
+
async processPrompt(prompt) {
|
|
6157
|
+
switch (prompt.type) {
|
|
6158
|
+
case "choice": return this.handleChoice(prompt);
|
|
6159
|
+
case "confirm": return this.handleConfirm(prompt);
|
|
6160
|
+
case "input": return this.handleInput(prompt);
|
|
6161
|
+
case "multiChoice": return this.handleMultiChoice(prompt);
|
|
6162
|
+
}
|
|
6163
|
+
}
|
|
6164
|
+
async handleChoice(prompt) {
|
|
6165
|
+
const rl = this.ensureInterface();
|
|
6166
|
+
console.log(`\n${prompt.question}`);
|
|
6167
|
+
prompt.choices.forEach((choice, index) => {
|
|
6168
|
+
const marker = choice.value === prompt.defaultChoice ? "*" : " ";
|
|
6169
|
+
const inputHint = choice.input ? " (allows custom input)" : "";
|
|
6170
|
+
console.log(` ${marker} ${index + 1}. ${choice.label}${inputHint}`);
|
|
6171
|
+
});
|
|
6172
|
+
return new Promise((resolve) => {
|
|
6173
|
+
rl.question("Enter number (or press Enter for default): ", (answer) => {
|
|
6174
|
+
const trimmed = answer.trim();
|
|
6175
|
+
if (!trimmed) {
|
|
6176
|
+
resolve(prompt.defaultChoice);
|
|
6177
|
+
return;
|
|
6178
|
+
}
|
|
6179
|
+
const num = parseInt(trimmed, 10);
|
|
6180
|
+
if (num >= 1 && num <= prompt.choices.length) {
|
|
6181
|
+
const choice = prompt.choices[num - 1];
|
|
6182
|
+
if (choice.input) rl.question(`Enter value for "${choice.label}": `, (inputValue) => {
|
|
6183
|
+
resolve(inputValue.trim() || choice.value);
|
|
6184
|
+
});
|
|
6185
|
+
else resolve(choice.value);
|
|
6186
|
+
} else resolve(prompt.defaultChoice);
|
|
6187
|
+
});
|
|
6188
|
+
});
|
|
6189
|
+
}
|
|
6190
|
+
async handleConfirm(prompt) {
|
|
6191
|
+
const rl = this.ensureInterface();
|
|
6192
|
+
const defaultText = prompt.defaultValue ? "Y/n" : "y/N";
|
|
6193
|
+
return new Promise((resolve) => {
|
|
6194
|
+
rl.question(`${prompt.question} [${defaultText}]: `, (answer) => {
|
|
6195
|
+
const trimmed = answer.trim().toLowerCase();
|
|
6196
|
+
if (!trimmed) {
|
|
6197
|
+
resolve(prompt.defaultValue);
|
|
6198
|
+
return;
|
|
6199
|
+
}
|
|
6200
|
+
resolve(trimmed === "y" || trimmed === "yes");
|
|
6201
|
+
});
|
|
6202
|
+
});
|
|
6203
|
+
}
|
|
6204
|
+
async handleInput(prompt) {
|
|
6205
|
+
const rl = this.ensureInterface();
|
|
6206
|
+
const defaultHint = prompt.defaultValue ? ` (default: ${prompt.defaultValue})` : "";
|
|
6207
|
+
const placeholderHint = prompt.placeholder ? ` [${prompt.placeholder}]` : "";
|
|
6208
|
+
return new Promise((resolve) => {
|
|
6209
|
+
rl.question(`${prompt.question}${placeholderHint}${defaultHint}: `, (answer) => {
|
|
6210
|
+
resolve(answer.trim() || prompt.defaultValue);
|
|
6211
|
+
});
|
|
6212
|
+
});
|
|
6213
|
+
}
|
|
6214
|
+
async handleMultiChoice(prompt) {
|
|
6215
|
+
const rl = this.ensureInterface();
|
|
6216
|
+
console.log(`\n${prompt.question}`);
|
|
6217
|
+
console.log(`(Select ${prompt.minSelect}-${prompt.maxSelect} options, enter comma-separated numbers)`);
|
|
6218
|
+
prompt.choices.forEach((choice, index) => {
|
|
6219
|
+
const selected = prompt.selectedIndices.has(index) ? "[x]" : "[ ]";
|
|
6220
|
+
console.log(` ${selected} ${index + 1}. ${choice.label}`);
|
|
6221
|
+
});
|
|
6222
|
+
return new Promise((resolve) => {
|
|
6223
|
+
rl.question("Enter numbers (e.g., 1,3,5): ", (answer) => {
|
|
6224
|
+
const trimmed = answer.trim();
|
|
6225
|
+
if (!trimmed) {
|
|
6226
|
+
resolve(prompt.choices.filter((_, i) => prompt.selectedIndices.has(i)).map((c) => c.value));
|
|
6227
|
+
return;
|
|
6228
|
+
}
|
|
6229
|
+
const indices = trimmed.split(",").map((s) => parseInt(s.trim(), 10) - 1).filter((n) => n >= 0 && n < prompt.choices.length);
|
|
6230
|
+
if (indices.length < prompt.minSelect) {
|
|
6231
|
+
console.log(`Minimum ${prompt.minSelect} selections required. Using defaults.`);
|
|
6232
|
+
resolve(prompt.choices.filter((_, i) => prompt.selectedIndices.has(i)).map((c) => c.value));
|
|
6233
|
+
return;
|
|
6234
|
+
}
|
|
6235
|
+
if (indices.length > prompt.maxSelect) {
|
|
6236
|
+
console.log(`Maximum ${prompt.maxSelect} selections allowed. Taking first ${prompt.maxSelect}.`);
|
|
6237
|
+
indices.splice(prompt.maxSelect);
|
|
6238
|
+
}
|
|
6239
|
+
resolve(indices.map((i) => prompt.choices[i].value));
|
|
6240
|
+
});
|
|
6241
|
+
});
|
|
6242
|
+
}
|
|
6243
|
+
/**
|
|
6244
|
+
* Cleanup readline interface
|
|
6245
|
+
*/ destroy() {
|
|
6246
|
+
if (this.rl) {
|
|
6247
|
+
this.rl.close();
|
|
6248
|
+
this.rl = null;
|
|
6249
|
+
}
|
|
6250
|
+
this.promptQueue = [];
|
|
6251
|
+
this.isProcessing = false;
|
|
6252
|
+
}
|
|
6253
|
+
};
|
|
6254
|
+
|
|
5014
6255
|
//#endregion
|
|
5015
6256
|
//#region src/services/screen.ts
|
|
5016
|
-
var ScreenInstance = class {
|
|
6257
|
+
var ScreenInstance = class extends EventEmitter {
|
|
5017
6258
|
id;
|
|
5018
6259
|
name;
|
|
5019
6260
|
icon;
|
|
@@ -5022,13 +6263,13 @@ var ScreenInstance = class {
|
|
|
5022
6263
|
hidden = false;
|
|
5023
6264
|
messages = [];
|
|
5024
6265
|
manager = null;
|
|
5025
|
-
changeListeners = /* @__PURE__ */ new Set();
|
|
5026
6266
|
printFn = null;
|
|
5027
6267
|
hasPrinted = false;
|
|
5028
6268
|
version = 0;
|
|
5029
6269
|
promptQueue = [];
|
|
5030
6270
|
activePrompt = null;
|
|
5031
6271
|
constructor(id, options) {
|
|
6272
|
+
super();
|
|
5032
6273
|
this.id = id;
|
|
5033
6274
|
this.name = options.name;
|
|
5034
6275
|
this.icon = options.icon;
|
|
@@ -5066,7 +6307,7 @@ var ScreenInstance = class {
|
|
|
5066
6307
|
}
|
|
5067
6308
|
setBadgeCount(count) {
|
|
5068
6309
|
this.badgeCount = count;
|
|
5069
|
-
this.
|
|
6310
|
+
this.emit("badge:changed", count);
|
|
5070
6311
|
return this;
|
|
5071
6312
|
}
|
|
5072
6313
|
isHidden() {
|
|
@@ -5075,7 +6316,7 @@ var ScreenInstance = class {
|
|
|
5075
6316
|
setHidden(hidden) {
|
|
5076
6317
|
this.hidden = hidden;
|
|
5077
6318
|
this.manager?.onScreenVisibilityChanged(this);
|
|
5078
|
-
this.
|
|
6319
|
+
this.emit("visibility:changed", hidden);
|
|
5079
6320
|
return this;
|
|
5080
6321
|
}
|
|
5081
6322
|
show() {
|
|
@@ -5088,15 +6329,22 @@ var ScreenInstance = class {
|
|
|
5088
6329
|
return this.status;
|
|
5089
6330
|
}
|
|
5090
6331
|
/**
|
|
5091
|
-
*
|
|
6332
|
+
* Check if a log level is enabled globally via the ScreenManager.
|
|
6333
|
+
* Returns true if no manager is set or if the level is allowed.
|
|
6334
|
+
*/ isLogLevelEnabled(level) {
|
|
6335
|
+
if (!this.manager) return true;
|
|
6336
|
+
return this.manager.isLogLevelEnabled(level);
|
|
6337
|
+
}
|
|
6338
|
+
/**
|
|
6339
|
+
* Set screen status. When success/fail and not in TUI mode, prints to stdout/stderr
|
|
5092
6340
|
*/ setStatus(status) {
|
|
5093
6341
|
const wasComplete = this.status === "success" || this.status === "fail";
|
|
5094
6342
|
this.status = status;
|
|
5095
6343
|
if (!wasComplete && (status === "success" || status === "fail")) {
|
|
5096
|
-
if (!this.manager?.
|
|
6344
|
+
if (!this.manager?.hasTuiRenderer()) this.printToConsole();
|
|
5097
6345
|
this.manager?.onScreenCompleted(this);
|
|
5098
6346
|
}
|
|
5099
|
-
this.
|
|
6347
|
+
this.emit("status:changed", status);
|
|
5100
6348
|
return this;
|
|
5101
6349
|
}
|
|
5102
6350
|
/**
|
|
@@ -5105,9 +6353,12 @@ var ScreenInstance = class {
|
|
|
5105
6353
|
return this.status === "success" || this.status === "fail";
|
|
5106
6354
|
}
|
|
5107
6355
|
/**
|
|
5108
|
-
* Check if this screen has been printed to console
|
|
6356
|
+
* Check if this screen has been printed to console.
|
|
6357
|
+
* Static screens in non-TUI modes are considered printed as they print incrementally.
|
|
5109
6358
|
*/ hasPrintedToConsole() {
|
|
5110
|
-
|
|
6359
|
+
if (this.hasPrinted) return true;
|
|
6360
|
+
if (this.status === "static" && !this.manager?.hasTuiRenderer()) return true;
|
|
6361
|
+
return false;
|
|
5111
6362
|
}
|
|
5112
6363
|
/**
|
|
5113
6364
|
* Force print to console (called when TUI unbinds)
|
|
@@ -5124,19 +6375,25 @@ var ScreenInstance = class {
|
|
|
5124
6375
|
*/ addMessage(message) {
|
|
5125
6376
|
this.messages.push(message);
|
|
5126
6377
|
this.incrementVersion();
|
|
5127
|
-
this.
|
|
6378
|
+
if (this.status === "static" && !this.manager?.hasTuiRenderer()) this.printSingleMessageToConsole(message);
|
|
6379
|
+
this.emit("message:added", message.id);
|
|
5128
6380
|
}
|
|
5129
6381
|
/**
|
|
5130
6382
|
* Update a loading message (internal use by Logger)
|
|
5131
6383
|
*/ updateMessage(id, updates) {
|
|
5132
6384
|
const index = this.messages.findIndex((m) => m.id === id);
|
|
5133
6385
|
if (index !== -1) {
|
|
6386
|
+
const oldMessage = this.messages[index];
|
|
5134
6387
|
this.messages[index] = {
|
|
5135
6388
|
...this.messages[index],
|
|
5136
6389
|
...updates
|
|
5137
6390
|
};
|
|
5138
6391
|
this.incrementVersion();
|
|
5139
|
-
this.
|
|
6392
|
+
if (this.status === "static" && !this.manager?.hasTuiRenderer()) {
|
|
6393
|
+
const newMessage = this.messages[index];
|
|
6394
|
+
if (newMessage.status !== "loading" && oldMessage.status === "loading") this.printSingleMessageToConsole(newMessage);
|
|
6395
|
+
}
|
|
6396
|
+
this.emit("message:updated", id);
|
|
5140
6397
|
}
|
|
5141
6398
|
}
|
|
5142
6399
|
/**
|
|
@@ -5144,12 +6401,17 @@ var ScreenInstance = class {
|
|
|
5144
6401
|
*/ updateProgressMessage(id, updates) {
|
|
5145
6402
|
const index = this.messages.findIndex((m) => m.id === id);
|
|
5146
6403
|
if (index !== -1) {
|
|
6404
|
+
const oldMessage = this.messages[index];
|
|
5147
6405
|
this.messages[index] = {
|
|
5148
6406
|
...this.messages[index],
|
|
5149
6407
|
...updates
|
|
5150
6408
|
};
|
|
5151
6409
|
this.incrementVersion();
|
|
5152
|
-
this.
|
|
6410
|
+
if (this.status === "static" && !this.manager?.hasTuiRenderer()) {
|
|
6411
|
+
const newMessage = this.messages[index];
|
|
6412
|
+
if ((newMessage.status === "complete" || newMessage.status === "failed") && oldMessage.status !== "complete" && oldMessage.status !== "failed") this.printSingleMessageToConsole(newMessage);
|
|
6413
|
+
}
|
|
6414
|
+
this.emit("message:updated", id);
|
|
5153
6415
|
}
|
|
5154
6416
|
}
|
|
5155
6417
|
/**
|
|
@@ -5157,7 +6419,7 @@ var ScreenInstance = class {
|
|
|
5157
6419
|
*/ clear() {
|
|
5158
6420
|
this.messages = [];
|
|
5159
6421
|
this.incrementVersion();
|
|
5160
|
-
this.
|
|
6422
|
+
this.emit("messages:cleared");
|
|
5161
6423
|
return this;
|
|
5162
6424
|
}
|
|
5163
6425
|
/**
|
|
@@ -5165,21 +6427,26 @@ var ScreenInstance = class {
|
|
|
5165
6427
|
* Returns a promise that resolves when the user responds
|
|
5166
6428
|
*/ _addPrompt(prompt) {
|
|
5167
6429
|
return new Promise((resolve) => {
|
|
6430
|
+
const mode = this.manager?.getRenderMode() ?? RenderMode.UNBOUND;
|
|
6431
|
+
if (mode === RenderMode.UNBOUND) {
|
|
6432
|
+
this.resolvePromptWithDefault(prompt, resolve);
|
|
6433
|
+
return;
|
|
6434
|
+
}
|
|
6435
|
+
if (mode === RenderMode.STDOUT_INTERACTIVE || mode === RenderMode.STDOUT_FALLBACK) {
|
|
6436
|
+
this.manager?.handleReadlinePrompt(prompt).then(resolve);
|
|
6437
|
+
return;
|
|
6438
|
+
}
|
|
5168
6439
|
const pending = {
|
|
5169
6440
|
data: prompt,
|
|
5170
6441
|
resolve
|
|
5171
6442
|
};
|
|
5172
|
-
if (!this.manager?.isTuiBound()) {
|
|
5173
|
-
this.resolvePromptWithDefault(prompt, resolve);
|
|
5174
|
-
return;
|
|
5175
|
-
}
|
|
5176
6443
|
if (prompt.timeout && prompt.timeoutStarted) pending.timeoutId = setTimeout(() => {
|
|
5177
6444
|
if (this.activePrompt === pending) {
|
|
5178
6445
|
this.resolvePromptWithDefault(prompt, resolve);
|
|
5179
6446
|
this.activePrompt = null;
|
|
5180
6447
|
this.activateNextPrompt();
|
|
5181
6448
|
this.incrementVersion();
|
|
5182
|
-
this.
|
|
6449
|
+
this.emit("prompt:resolved");
|
|
5183
6450
|
} else {
|
|
5184
6451
|
const idx = this.promptQueue.indexOf(pending);
|
|
5185
6452
|
if (idx !== -1) {
|
|
@@ -5196,20 +6463,7 @@ var ScreenInstance = class {
|
|
|
5196
6463
|
/**
|
|
5197
6464
|
* Resolve a prompt with its default value
|
|
5198
6465
|
*/ resolvePromptWithDefault(prompt, resolve) {
|
|
5199
|
-
|
|
5200
|
-
case "choice":
|
|
5201
|
-
resolve(prompt.defaultChoice);
|
|
5202
|
-
break;
|
|
5203
|
-
case "confirm":
|
|
5204
|
-
resolve(prompt.defaultValue);
|
|
5205
|
-
break;
|
|
5206
|
-
case "input":
|
|
5207
|
-
resolve(prompt.defaultValue);
|
|
5208
|
-
break;
|
|
5209
|
-
case "multiChoice":
|
|
5210
|
-
resolve(prompt.choices.filter((_, i) => prompt.selectedIndices.has(i)).map((c) => c.value));
|
|
5211
|
-
break;
|
|
5212
|
-
}
|
|
6466
|
+
resolve(getPromptDefaultValue(prompt));
|
|
5213
6467
|
}
|
|
5214
6468
|
/**
|
|
5215
6469
|
* Get the currently active prompt (for rendering)
|
|
@@ -5233,7 +6487,7 @@ var ScreenInstance = class {
|
|
|
5233
6487
|
const maxIndex = prompt.choices.length - 1;
|
|
5234
6488
|
prompt.focusedIndex = Math.max(0, Math.min(index, maxIndex));
|
|
5235
6489
|
} else if (prompt.type === "confirm") prompt.selectedValue = index === 0;
|
|
5236
|
-
this.
|
|
6490
|
+
this.emit("prompt:updated");
|
|
5237
6491
|
}
|
|
5238
6492
|
/**
|
|
5239
6493
|
* Navigate prompt selection up
|
|
@@ -5260,7 +6514,7 @@ var ScreenInstance = class {
|
|
|
5260
6514
|
const prompt = this.activePrompt.data;
|
|
5261
6515
|
if (prompt.type === "confirm") {
|
|
5262
6516
|
prompt.selectedValue = true;
|
|
5263
|
-
this.
|
|
6517
|
+
this.emit("prompt:updated");
|
|
5264
6518
|
}
|
|
5265
6519
|
}
|
|
5266
6520
|
promptNavigateRight() {
|
|
@@ -5268,7 +6522,7 @@ var ScreenInstance = class {
|
|
|
5268
6522
|
const prompt = this.activePrompt.data;
|
|
5269
6523
|
if (prompt.type === "confirm") {
|
|
5270
6524
|
prompt.selectedValue = false;
|
|
5271
|
-
this.
|
|
6525
|
+
this.emit("prompt:updated");
|
|
5272
6526
|
}
|
|
5273
6527
|
}
|
|
5274
6528
|
/**
|
|
@@ -5280,7 +6534,7 @@ var ScreenInstance = class {
|
|
|
5280
6534
|
const p = prompt;
|
|
5281
6535
|
if (p.selectedIndices.has(p.focusedIndex)) p.selectedIndices.delete(p.focusedIndex);
|
|
5282
6536
|
else if (p.selectedIndices.size < p.maxSelect) p.selectedIndices.add(p.focusedIndex);
|
|
5283
|
-
this.
|
|
6537
|
+
this.emit("prompt:updated");
|
|
5284
6538
|
}
|
|
5285
6539
|
}
|
|
5286
6540
|
/**
|
|
@@ -5292,7 +6546,7 @@ var ScreenInstance = class {
|
|
|
5292
6546
|
if (prompt.type === "choice") {
|
|
5293
6547
|
if (prompt.choices[prompt.selectedIndex]?.input) {
|
|
5294
6548
|
prompt.inputMode = true;
|
|
5295
|
-
this.
|
|
6549
|
+
this.emit("prompt:updated");
|
|
5296
6550
|
return true;
|
|
5297
6551
|
}
|
|
5298
6552
|
} else if (prompt.type === "input") return true;
|
|
@@ -5305,7 +6559,7 @@ var ScreenInstance = class {
|
|
|
5305
6559
|
const prompt = this.activePrompt.data;
|
|
5306
6560
|
if (prompt.type === "choice" && prompt.inputMode) {
|
|
5307
6561
|
prompt.inputMode = false;
|
|
5308
|
-
this.
|
|
6562
|
+
this.emit("prompt:updated");
|
|
5309
6563
|
}
|
|
5310
6564
|
}
|
|
5311
6565
|
/**
|
|
@@ -5324,10 +6578,10 @@ var ScreenInstance = class {
|
|
|
5324
6578
|
const prompt = this.activePrompt.data;
|
|
5325
6579
|
if (prompt.type === "choice" && prompt.inputMode) {
|
|
5326
6580
|
prompt.inputValue = value;
|
|
5327
|
-
this.
|
|
6581
|
+
this.emit("prompt:updated");
|
|
5328
6582
|
} else if (prompt.type === "input") {
|
|
5329
6583
|
prompt.value = value;
|
|
5330
|
-
this.
|
|
6584
|
+
this.emit("prompt:updated");
|
|
5331
6585
|
}
|
|
5332
6586
|
}
|
|
5333
6587
|
/**
|
|
@@ -5337,10 +6591,10 @@ var ScreenInstance = class {
|
|
|
5337
6591
|
const prompt = this.activePrompt.data;
|
|
5338
6592
|
if (prompt.type === "choice" && prompt.inputMode) {
|
|
5339
6593
|
prompt.inputValue += char;
|
|
5340
|
-
this.
|
|
6594
|
+
this.emit("prompt:updated");
|
|
5341
6595
|
} else if (prompt.type === "input") {
|
|
5342
6596
|
prompt.value += char;
|
|
5343
|
-
this.
|
|
6597
|
+
this.emit("prompt:updated");
|
|
5344
6598
|
}
|
|
5345
6599
|
}
|
|
5346
6600
|
/**
|
|
@@ -5350,10 +6604,10 @@ var ScreenInstance = class {
|
|
|
5350
6604
|
const prompt = this.activePrompt.data;
|
|
5351
6605
|
if (prompt.type === "choice" && prompt.inputMode) {
|
|
5352
6606
|
prompt.inputValue = prompt.inputValue.slice(0, -1);
|
|
5353
|
-
this.
|
|
6607
|
+
this.emit("prompt:updated");
|
|
5354
6608
|
} else if (prompt.type === "input") {
|
|
5355
6609
|
prompt.value = prompt.value.slice(0, -1);
|
|
5356
|
-
this.
|
|
6610
|
+
this.emit("prompt:updated");
|
|
5357
6611
|
}
|
|
5358
6612
|
}
|
|
5359
6613
|
/**
|
|
@@ -5398,7 +6652,7 @@ var ScreenInstance = class {
|
|
|
5398
6652
|
this.activePrompt = null;
|
|
5399
6653
|
this.activateNextPrompt();
|
|
5400
6654
|
this.incrementVersion();
|
|
5401
|
-
this.
|
|
6655
|
+
this.emit("prompt:resolved");
|
|
5402
6656
|
}
|
|
5403
6657
|
/**
|
|
5404
6658
|
* Activate the next prompt in the queue
|
|
@@ -5407,17 +6661,13 @@ var ScreenInstance = class {
|
|
|
5407
6661
|
this.activePrompt = this.promptQueue.shift();
|
|
5408
6662
|
this.manager?.onScreenPromptActivated(this);
|
|
5409
6663
|
this.incrementVersion();
|
|
5410
|
-
this.
|
|
6664
|
+
this.emit("prompt:activated");
|
|
5411
6665
|
}
|
|
5412
6666
|
}
|
|
5413
6667
|
/**
|
|
5414
|
-
*
|
|
5415
|
-
*/
|
|
5416
|
-
this.
|
|
5417
|
-
return () => this.changeListeners.delete(listener);
|
|
5418
|
-
}
|
|
5419
|
-
notifyChange() {
|
|
5420
|
-
this.changeListeners.forEach((listener) => listener());
|
|
6668
|
+
* Print a single message immediately to stdout (for static screens in stdout mode)
|
|
6669
|
+
*/ printSingleMessageToConsole(message) {
|
|
6670
|
+
printSingleMessage(message, this.name, false);
|
|
5421
6671
|
}
|
|
5422
6672
|
/**
|
|
5423
6673
|
* Print all messages to stdout/stderr with ANSI colors
|
|
@@ -5710,24 +6960,29 @@ function applyDecs2203RFactory$2() {
|
|
|
5710
6960
|
function _apply_decs_2203_r$2(targetClass, memberDecs, classDecs, parentClass) {
|
|
5711
6961
|
return (_apply_decs_2203_r$2 = applyDecs2203RFactory$2())(targetClass, memberDecs, classDecs, parentClass);
|
|
5712
6962
|
}
|
|
5713
|
-
var _dec$2, _initClass$2;
|
|
6963
|
+
var _dec$2, _initClass$2, _EventEmitter;
|
|
5714
6964
|
let _ScreenManagerInstance;
|
|
5715
6965
|
_dec$2 = Injectable({ token: ScreenManager });
|
|
5716
|
-
var ScreenManagerInstance = class {
|
|
6966
|
+
var ScreenManagerInstance = class extends (_EventEmitter = EventEmitter) {
|
|
5717
6967
|
static {
|
|
5718
|
-
({c: [_ScreenManagerInstance, _initClass$2]} = _apply_decs_2203_r$2(this, [], [_dec$2]));
|
|
6968
|
+
({c: [_ScreenManagerInstance, _initClass$2]} = _apply_decs_2203_r$2(this, [], [_dec$2], _EventEmitter));
|
|
6969
|
+
}
|
|
6970
|
+
constructor() {
|
|
6971
|
+
super();
|
|
5719
6972
|
}
|
|
5720
6973
|
screens = /* @__PURE__ */ new Map();
|
|
5721
6974
|
screenOrder = [];
|
|
5722
6975
|
activeScreenId = null;
|
|
5723
6976
|
renderer = null;
|
|
5724
6977
|
root = null;
|
|
5725
|
-
adapter =
|
|
5726
|
-
|
|
5727
|
-
|
|
6978
|
+
adapter = null;
|
|
6979
|
+
container = inject(Container);
|
|
6980
|
+
mode = RenderMode.UNBOUND;
|
|
6981
|
+
readlinePromptService = null;
|
|
5728
6982
|
bindOptions = {};
|
|
5729
6983
|
autoCloseTimer = null;
|
|
5730
6984
|
theme;
|
|
6985
|
+
globalLogLevels = null;
|
|
5731
6986
|
focusArea = "content";
|
|
5732
6987
|
selectedIndex = 0;
|
|
5733
6988
|
/**
|
|
@@ -5737,11 +6992,11 @@ var ScreenManagerInstance = class {
|
|
|
5737
6992
|
const screen = new ScreenInstance(id, options);
|
|
5738
6993
|
screen._setManager(this);
|
|
5739
6994
|
screen._setPrintFn(printMessagesToStdout);
|
|
5740
|
-
screen.onChange(() => this.notifyChange());
|
|
5741
6995
|
this.screens.set(id, screen);
|
|
5742
6996
|
this.screenOrder.push(id);
|
|
5743
6997
|
if (!this.activeScreenId && !screen.isHidden()) this.activeScreenId = id;
|
|
5744
|
-
this.
|
|
6998
|
+
this.checkAutoClose();
|
|
6999
|
+
this.emit("screen:added", id);
|
|
5745
7000
|
return screen;
|
|
5746
7001
|
}
|
|
5747
7002
|
getScreenByName(name) {
|
|
@@ -5755,71 +7010,190 @@ var ScreenManagerInstance = class {
|
|
|
5755
7010
|
if (!this.screens.has(id)) return;
|
|
5756
7011
|
this.screens.delete(id);
|
|
5757
7012
|
this.screenOrder = this.screenOrder.filter((sid) => sid !== id);
|
|
5758
|
-
if (this.activeScreenId === id)
|
|
7013
|
+
if (this.activeScreenId === id) {
|
|
7014
|
+
this.activeScreenId = this.getScreens()[0]?.getId() ?? null;
|
|
7015
|
+
this.emit("activeScreen:changed", this.activeScreenId);
|
|
7016
|
+
}
|
|
5759
7017
|
const visibleScreens = this.getScreens();
|
|
5760
|
-
if (this.selectedIndex >= visibleScreens.length)
|
|
5761
|
-
|
|
7018
|
+
if (this.selectedIndex >= visibleScreens.length) {
|
|
7019
|
+
const newIndex = Math.max(0, visibleScreens.length - 1);
|
|
7020
|
+
if (newIndex !== this.selectedIndex) {
|
|
7021
|
+
this.selectedIndex = newIndex;
|
|
7022
|
+
this.emit("sidebar:indexChanged", this.selectedIndex);
|
|
7023
|
+
}
|
|
7024
|
+
}
|
|
7025
|
+
this.checkAutoClose();
|
|
7026
|
+
this.emit("screen:removed", id);
|
|
5762
7027
|
}
|
|
5763
7028
|
/**
|
|
5764
7029
|
* Non-blocking bind - starts TUI rendering in background
|
|
5765
7030
|
*/ async bind(options) {
|
|
5766
|
-
if (this.
|
|
7031
|
+
if (this.mode !== RenderMode.UNBOUND) return;
|
|
5767
7032
|
this.bindOptions = options ?? {};
|
|
5768
7033
|
if (options?.theme) this.theme = typeof options.theme === "string" ? getThemePreset(options.theme) : options.theme;
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
7034
|
+
if (!(options?.useOpenTUI ?? !isBunRuntime())) {
|
|
7035
|
+
this.mode = RenderMode.STDOUT_INTERACTIVE;
|
|
7036
|
+
this.readlinePromptService = new ReadlinePromptService();
|
|
7037
|
+
this.emit("mode:changed", this.mode);
|
|
7038
|
+
return;
|
|
7039
|
+
}
|
|
7040
|
+
try {
|
|
7041
|
+
this.adapter = await this.container.get(Adapter);
|
|
7042
|
+
if (this.adapter.isMissingAdapter) throw new Error("No adapter registered");
|
|
7043
|
+
if (this.adapter.handlesOwnRenderer) this.root = await this.adapter.createRoot();
|
|
7044
|
+
else {
|
|
7045
|
+
const { createCliRenderer } = await dynamicImport("@opentui/core");
|
|
7046
|
+
this.renderer = await createCliRenderer({
|
|
7047
|
+
exitOnCtrlC: options?.exitOnCtrlC ?? true,
|
|
7048
|
+
useAlternateScreen: true,
|
|
7049
|
+
useMouse: options?.useMouse ?? true
|
|
7050
|
+
});
|
|
7051
|
+
this.root = await this.adapter.createRoot(this.renderer);
|
|
7052
|
+
}
|
|
7053
|
+
this.mode = RenderMode.TUI_ACTIVE;
|
|
7054
|
+
this.emit("mode:changed", this.mode);
|
|
7055
|
+
this.render();
|
|
7056
|
+
} catch {
|
|
7057
|
+
console.warn("[commander-tui] TUI adapter not available, falling back to stdout mode. To enable TUI, import a TUI adapter: @navios/tui-adapter-react, @navios/tui-adapter-ink, or @navios/tui-adapter-solid");
|
|
7058
|
+
this.mode = RenderMode.STDOUT_FALLBACK;
|
|
7059
|
+
this.readlinePromptService = new ReadlinePromptService();
|
|
7060
|
+
this.adapter = null;
|
|
7061
|
+
this.renderer = null;
|
|
7062
|
+
this.root = null;
|
|
7063
|
+
this.emit("mode:changed", this.mode);
|
|
7064
|
+
}
|
|
7065
|
+
}
|
|
7066
|
+
/**
|
|
7067
|
+
* Get the current render mode
|
|
7068
|
+
*/ getRenderMode() {
|
|
7069
|
+
return this.mode;
|
|
7070
|
+
}
|
|
7071
|
+
/**
|
|
7072
|
+
* Check if TUI is interactive (any mode except UNBOUND).
|
|
7073
|
+
* In interactive modes, prompts can be handled via readline or TUI.
|
|
7074
|
+
*/ isInteractive() {
|
|
7075
|
+
return this.mode !== RenderMode.UNBOUND;
|
|
7076
|
+
}
|
|
7077
|
+
/**
|
|
7078
|
+
* Check if TUI rendering is active (TUI_ACTIVE mode).
|
|
7079
|
+
* When true, screens are rendered in the TUI and not printed to stdout.
|
|
7080
|
+
*/ hasTuiRenderer() {
|
|
7081
|
+
return this.mode === RenderMode.TUI_ACTIVE;
|
|
7082
|
+
}
|
|
7083
|
+
/**
|
|
7084
|
+
* Handle a prompt via readline (for stdout modes)
|
|
7085
|
+
*/ handleReadlinePrompt(prompt) {
|
|
7086
|
+
if (!this.readlinePromptService) return Promise.resolve(getPromptDefaultValue(prompt));
|
|
7087
|
+
return this.readlinePromptService.handlePrompt(prompt);
|
|
5777
7088
|
}
|
|
5778
7089
|
/**
|
|
5779
7090
|
* Get the configured theme
|
|
5780
7091
|
*/ getTheme() {
|
|
5781
7092
|
return this.theme;
|
|
5782
7093
|
}
|
|
7094
|
+
/**
|
|
7095
|
+
* Setup global configuration for the screen manager.
|
|
7096
|
+
* Can be called before or after bind() to configure theme and log levels.
|
|
7097
|
+
*/ setup(options) {
|
|
7098
|
+
if (options.theme) this.theme = typeof options.theme === "string" ? getThemePreset(options.theme) : options.theme;
|
|
7099
|
+
if (options.logLevels) this.globalLogLevels = new Set(options.logLevels);
|
|
7100
|
+
}
|
|
7101
|
+
/**
|
|
7102
|
+
* Check if a log level is enabled globally.
|
|
7103
|
+
* Returns true if no global filter is set, or if the level is in the allowed set.
|
|
7104
|
+
*/ isLogLevelEnabled(level) {
|
|
7105
|
+
if (this.globalLogLevels === null) return true;
|
|
7106
|
+
return this.globalLogLevels.has(level);
|
|
7107
|
+
}
|
|
7108
|
+
/**
|
|
7109
|
+
* Get the current global log levels filter.
|
|
7110
|
+
* Returns null if no filter is set (all levels allowed).
|
|
7111
|
+
*/ getGlobalLogLevels() {
|
|
7112
|
+
return this.globalLogLevels ? Array.from(this.globalLogLevels) : null;
|
|
7113
|
+
}
|
|
5783
7114
|
onServiceDestroy() {
|
|
5784
7115
|
this.unbind();
|
|
5785
7116
|
}
|
|
5786
7117
|
/**
|
|
5787
7118
|
* Stop TUI rendering and cleanup
|
|
5788
|
-
* Flushes
|
|
7119
|
+
* Flushes screens to stdout/stderr based on mode
|
|
5789
7120
|
*/ unbind() {
|
|
5790
|
-
if (
|
|
7121
|
+
if (this.mode === RenderMode.UNBOUND) {
|
|
7122
|
+
this.flushRemainingScreens();
|
|
7123
|
+
return;
|
|
7124
|
+
}
|
|
7125
|
+
const previousMode = this.mode;
|
|
5791
7126
|
if (this.autoCloseTimer) {
|
|
5792
7127
|
clearTimeout(this.autoCloseTimer);
|
|
5793
7128
|
this.autoCloseTimer = null;
|
|
5794
7129
|
}
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
|
|
7130
|
+
if (previousMode === RenderMode.TUI_ACTIVE) {
|
|
7131
|
+
if (this.root) this.root.unmount();
|
|
7132
|
+
if (this.renderer) {
|
|
7133
|
+
if ("disableMouse" in this.renderer) this.renderer.disableMouse();
|
|
7134
|
+
this.renderer.destroy();
|
|
7135
|
+
}
|
|
7136
|
+
}
|
|
7137
|
+
if (this.readlinePromptService) {
|
|
7138
|
+
this.readlinePromptService.destroy();
|
|
7139
|
+
this.readlinePromptService = null;
|
|
7140
|
+
}
|
|
7141
|
+
this.flushScreensOnExit(previousMode);
|
|
7142
|
+
this.mode = RenderMode.UNBOUND;
|
|
5798
7143
|
this.renderer = null;
|
|
5799
7144
|
this.root = null;
|
|
5800
|
-
this.
|
|
5801
|
-
this.
|
|
7145
|
+
this.adapter = null;
|
|
7146
|
+
this.emit("mode:changed", this.mode);
|
|
7147
|
+
}
|
|
7148
|
+
/**
|
|
7149
|
+
* Flush screens on exit based on the mode we're exiting from
|
|
7150
|
+
*/ flushScreensOnExit(previousMode) {
|
|
7151
|
+
for (const id of this.screenOrder) {
|
|
7152
|
+
const screen = this.screens.get(id);
|
|
7153
|
+
if (!screen || screen.isHidden()) continue;
|
|
7154
|
+
if (previousMode === RenderMode.TUI_ACTIVE) screen._flushToConsole(true);
|
|
7155
|
+
else if (!screen.hasPrintedToConsole()) screen._flushToConsole(true);
|
|
7156
|
+
}
|
|
5802
7157
|
}
|
|
5803
7158
|
/**
|
|
5804
|
-
*
|
|
5805
|
-
|
|
7159
|
+
* Flush any remaining non-hidden screens that haven't been printed.
|
|
7160
|
+
* Called on destroy even in UNBOUND mode to handle forgotten completions.
|
|
7161
|
+
*/ flushRemainingScreens() {
|
|
5806
7162
|
for (const id of this.screenOrder) {
|
|
5807
7163
|
const screen = this.screens.get(id);
|
|
5808
|
-
if (screen
|
|
7164
|
+
if (!screen || screen.isHidden()) continue;
|
|
7165
|
+
if (!screen.hasPrintedToConsole()) screen._flushToConsole(true);
|
|
5809
7166
|
}
|
|
5810
7167
|
}
|
|
5811
7168
|
/**
|
|
5812
7169
|
* Check if TUI is currently bound
|
|
7170
|
+
* @deprecated Use isInteractive() instead
|
|
5813
7171
|
*/ isTuiBound() {
|
|
5814
|
-
return this.
|
|
7172
|
+
return this.isInteractive();
|
|
7173
|
+
}
|
|
7174
|
+
/**
|
|
7175
|
+
* Check if TUI rendering is active (has renderer or self-rendering adapter).
|
|
7176
|
+
* @deprecated Use hasTuiRenderer() instead
|
|
7177
|
+
*/ isTuiRendererActive() {
|
|
7178
|
+
return this.hasTuiRenderer();
|
|
7179
|
+
}
|
|
7180
|
+
/**
|
|
7181
|
+
* Check if OpenTUI rendering is active (has renderer).
|
|
7182
|
+
* @deprecated Use hasTuiRenderer() instead
|
|
7183
|
+
*/ isOpenTUIActive() {
|
|
7184
|
+
return this.hasTuiRenderer();
|
|
5815
7185
|
}
|
|
5816
7186
|
/**
|
|
5817
7187
|
* Called by Screen when a prompt becomes active
|
|
5818
7188
|
* Focuses the screen and switches to content area
|
|
5819
7189
|
*/ onScreenPromptActivated(screen) {
|
|
5820
|
-
this.
|
|
5821
|
-
this.
|
|
5822
|
-
this.
|
|
7190
|
+
const prevActiveId = this.activeScreenId;
|
|
7191
|
+
this.activeScreenId = screen.getId();
|
|
7192
|
+
if (prevActiveId !== this.activeScreenId) this.emit("activeScreen:changed", this.activeScreenId);
|
|
7193
|
+
if (this.focusArea !== "content") {
|
|
7194
|
+
this.focusArea = "content";
|
|
7195
|
+
this.emit("focus:changed", this.focusArea);
|
|
7196
|
+
}
|
|
5823
7197
|
}
|
|
5824
7198
|
/**
|
|
5825
7199
|
* Check if any screen has an active prompt
|
|
@@ -5840,10 +7214,18 @@ var ScreenManagerInstance = class {
|
|
|
5840
7214
|
if (screen.isHidden() && this.activeScreenId === screen.getId()) {
|
|
5841
7215
|
this.activeScreenId = this.getScreens()[0]?.getId() ?? null;
|
|
5842
7216
|
this.selectedIndex = 0;
|
|
7217
|
+
this.emit("activeScreen:changed", this.activeScreenId);
|
|
7218
|
+
this.emit("sidebar:indexChanged", this.selectedIndex);
|
|
5843
7219
|
}
|
|
5844
7220
|
const visibleScreens = this.getScreens();
|
|
5845
|
-
if (this.selectedIndex >= visibleScreens.length)
|
|
5846
|
-
|
|
7221
|
+
if (this.selectedIndex >= visibleScreens.length) {
|
|
7222
|
+
const newIndex = Math.max(0, visibleScreens.length - 1);
|
|
7223
|
+
if (newIndex !== this.selectedIndex) {
|
|
7224
|
+
this.selectedIndex = newIndex;
|
|
7225
|
+
this.emit("sidebar:indexChanged", this.selectedIndex);
|
|
7226
|
+
}
|
|
7227
|
+
}
|
|
7228
|
+
this.checkAutoClose();
|
|
5847
7229
|
}
|
|
5848
7230
|
/**
|
|
5849
7231
|
* Called by Screen when status becomes success/fail
|
|
@@ -5855,9 +7237,16 @@ var ScreenManagerInstance = class {
|
|
|
5855
7237
|
this.screenOrder.splice(index, 1);
|
|
5856
7238
|
this.screenOrder.push(id);
|
|
5857
7239
|
const visibleScreens = this.getScreens();
|
|
5858
|
-
if (this.selectedIndex >= visibleScreens.length)
|
|
7240
|
+
if (this.selectedIndex >= visibleScreens.length) {
|
|
7241
|
+
const newIndex = Math.max(0, visibleScreens.length - 1);
|
|
7242
|
+
if (newIndex !== this.selectedIndex) {
|
|
7243
|
+
this.selectedIndex = newIndex;
|
|
7244
|
+
this.emit("sidebar:indexChanged", this.selectedIndex);
|
|
7245
|
+
}
|
|
7246
|
+
}
|
|
7247
|
+
this.checkAutoClose();
|
|
7248
|
+
this.emit("screen:reordered");
|
|
5859
7249
|
}
|
|
5860
|
-
this.notifyChange();
|
|
5861
7250
|
}
|
|
5862
7251
|
/**
|
|
5863
7252
|
* Check if all screens are successful (or only static) and start auto-close timer if enabled.
|
|
@@ -5865,7 +7254,7 @@ var ScreenManagerInstance = class {
|
|
|
5865
7254
|
* If there are only static screens, the timer will trigger after the delay with no new activity.
|
|
5866
7255
|
*/ checkAutoClose() {
|
|
5867
7256
|
const autoClose = this.bindOptions.autoClose;
|
|
5868
|
-
if (!autoClose ||
|
|
7257
|
+
if (!autoClose || this.mode === RenderMode.UNBOUND) return;
|
|
5869
7258
|
if (this.autoCloseTimer) {
|
|
5870
7259
|
clearTimeout(this.autoCloseTimer);
|
|
5871
7260
|
this.autoCloseTimer = null;
|
|
@@ -5897,8 +7286,9 @@ var ScreenManagerInstance = class {
|
|
|
5897
7286
|
/**
|
|
5898
7287
|
* Set the active screen
|
|
5899
7288
|
*/ setActiveScreen(screen) {
|
|
7289
|
+
const prevActiveId = this.activeScreenId;
|
|
5900
7290
|
this.activeScreenId = screen.getId();
|
|
5901
|
-
this.
|
|
7291
|
+
if (prevActiveId !== this.activeScreenId) this.emit("activeScreen:changed", this.activeScreenId);
|
|
5902
7292
|
}
|
|
5903
7293
|
/**
|
|
5904
7294
|
* Get bind options
|
|
@@ -5908,15 +7298,20 @@ var ScreenManagerInstance = class {
|
|
|
5908
7298
|
/**
|
|
5909
7299
|
* Set focus area (sidebar or content)
|
|
5910
7300
|
*/ setFocusArea(area) {
|
|
5911
|
-
this.focusArea
|
|
5912
|
-
|
|
7301
|
+
if (this.focusArea !== area) {
|
|
7302
|
+
this.focusArea = area;
|
|
7303
|
+
this.emit("focus:changed", area);
|
|
7304
|
+
}
|
|
5913
7305
|
}
|
|
5914
7306
|
/**
|
|
5915
7307
|
* Set selected index in sidebar
|
|
5916
7308
|
*/ setSelectedIndex(index) {
|
|
5917
7309
|
const visibleScreens = this.getScreens();
|
|
5918
|
-
|
|
5919
|
-
this.
|
|
7310
|
+
const newIndex = Math.max(0, Math.min(index, visibleScreens.length - 1));
|
|
7311
|
+
if (this.selectedIndex !== newIndex) {
|
|
7312
|
+
this.selectedIndex = newIndex;
|
|
7313
|
+
this.emit("sidebar:indexChanged", newIndex);
|
|
7314
|
+
}
|
|
5920
7315
|
}
|
|
5921
7316
|
/**
|
|
5922
7317
|
* Navigate sidebar up
|
|
@@ -5938,20 +7333,10 @@ var ScreenManagerInstance = class {
|
|
|
5938
7333
|
* Toggle focus between sidebar and content
|
|
5939
7334
|
*/ toggleFocus() {
|
|
5940
7335
|
this.focusArea = this.focusArea === "sidebar" ? "content" : "sidebar";
|
|
5941
|
-
this.
|
|
5942
|
-
}
|
|
5943
|
-
/**
|
|
5944
|
-
* Register a change listener for re-renders
|
|
5945
|
-
*/ onChange(listener) {
|
|
5946
|
-
this.changeListeners.add(listener);
|
|
5947
|
-
return () => this.changeListeners.delete(listener);
|
|
5948
|
-
}
|
|
5949
|
-
notifyChange() {
|
|
5950
|
-
this.checkAutoClose();
|
|
5951
|
-
this.changeListeners.forEach((listener) => listener());
|
|
7336
|
+
this.emit("focus:changed", this.focusArea);
|
|
5952
7337
|
}
|
|
5953
7338
|
render() {
|
|
5954
|
-
if (!this.root) return;
|
|
7339
|
+
if (!this.root || !this.adapter) return;
|
|
5955
7340
|
this.adapter.renderToRoot(this.root, {
|
|
5956
7341
|
manager: this,
|
|
5957
7342
|
theme: this.theme
|
|
@@ -6253,7 +7638,10 @@ var ScreenLoggerInstance = class {
|
|
|
6253
7638
|
({c: [_ScreenLoggerInstance, _initClass$1]} = _apply_decs_2203_r$1(this, [], [_dec$1]));
|
|
6254
7639
|
}
|
|
6255
7640
|
constructor(options) {
|
|
6256
|
-
this.screen = inject(Screen, typeof options.screen === "string" ? {
|
|
7641
|
+
this.screen = inject(Screen, typeof options.screen === "string" ? {
|
|
7642
|
+
name: options.screen,
|
|
7643
|
+
static: true
|
|
7644
|
+
} : options.screen);
|
|
6257
7645
|
this.context = options.context;
|
|
6258
7646
|
this.enabledLevels = new Set(options.enabledLevels);
|
|
6259
7647
|
}
|
|
@@ -6261,7 +7649,8 @@ var ScreenLoggerInstance = class {
|
|
|
6261
7649
|
context;
|
|
6262
7650
|
enabledLevels;
|
|
6263
7651
|
isLevelEnabled(level) {
|
|
6264
|
-
|
|
7652
|
+
if (!this.enabledLevels.has(level)) return false;
|
|
7653
|
+
return this.screen.isLogLevelEnabled(level);
|
|
6265
7654
|
}
|
|
6266
7655
|
verbose(msg, label) {
|
|
6267
7656
|
return this.write("verbose", msg, label);
|
|
@@ -6877,5 +8266,579 @@ var PromptInstance = class {
|
|
|
6877
8266
|
};
|
|
6878
8267
|
|
|
6879
8268
|
//#endregion
|
|
6880
|
-
|
|
8269
|
+
//#region src/keyboard/keyboard_manager.ts
|
|
8270
|
+
/**
|
|
8271
|
+
* Manages keyboard bindings and dispatches key events to handlers.
|
|
8272
|
+
*/ var KeyboardManager = class {
|
|
8273
|
+
bindings = [];
|
|
8274
|
+
disabled = /* @__PURE__ */ new Set();
|
|
8275
|
+
constructor(config$1) {
|
|
8276
|
+
if (config$1?.bindings) this.bindings = [...config$1.bindings];
|
|
8277
|
+
if (config$1?.disabled) this.disabled = new Set(config$1.disabled);
|
|
8278
|
+
this.sortBindings();
|
|
8279
|
+
}
|
|
8280
|
+
/**
|
|
8281
|
+
* Add bindings to the manager.
|
|
8282
|
+
*/ addBindings(bindings) {
|
|
8283
|
+
this.bindings.push(...bindings);
|
|
8284
|
+
this.sortBindings();
|
|
8285
|
+
}
|
|
8286
|
+
/**
|
|
8287
|
+
* Remove a binding by key name.
|
|
8288
|
+
*/ removeBinding(key) {
|
|
8289
|
+
this.bindings = this.bindings.filter((b) => {
|
|
8290
|
+
return !(Array.isArray(b.key) ? b.key : [b.key]).includes(key);
|
|
8291
|
+
});
|
|
8292
|
+
}
|
|
8293
|
+
/**
|
|
8294
|
+
* Disable a key (prevents it from being matched).
|
|
8295
|
+
*/ disableKey(key) {
|
|
8296
|
+
this.disabled.add(key);
|
|
8297
|
+
}
|
|
8298
|
+
/**
|
|
8299
|
+
* Enable a previously disabled key.
|
|
8300
|
+
*/ enableKey(key) {
|
|
8301
|
+
this.disabled.delete(key);
|
|
8302
|
+
}
|
|
8303
|
+
/**
|
|
8304
|
+
* Handle a key event, dispatching to the appropriate handler.
|
|
8305
|
+
* Returns true if a handler consumed the event.
|
|
8306
|
+
*/ handleKey(key, context) {
|
|
8307
|
+
const binding = this.findMatchingBinding(key, context);
|
|
8308
|
+
if (binding) return binding.handler(key, context) !== false;
|
|
8309
|
+
return false;
|
|
8310
|
+
}
|
|
8311
|
+
/**
|
|
8312
|
+
* Get all bindings for display in help overlay.
|
|
8313
|
+
*/ getBindingsForHelp() {
|
|
8314
|
+
return this.bindings.filter((b) => b.description);
|
|
8315
|
+
}
|
|
8316
|
+
/**
|
|
8317
|
+
* Get bindings grouped by category.
|
|
8318
|
+
*/ getBindingsByCategory() {
|
|
8319
|
+
const grouped = {
|
|
8320
|
+
general: [],
|
|
8321
|
+
navigation: [],
|
|
8322
|
+
screen: [],
|
|
8323
|
+
prompt: [],
|
|
8324
|
+
filter: []
|
|
8325
|
+
};
|
|
8326
|
+
for (const binding of this.bindings) if (binding.description) grouped[binding.category].push(binding);
|
|
8327
|
+
return grouped;
|
|
8328
|
+
}
|
|
8329
|
+
/**
|
|
8330
|
+
* Find a matching binding for the given key and context.
|
|
8331
|
+
*/ findMatchingBinding(key, context) {
|
|
8332
|
+
for (const binding of this.bindings) if (this.keyMatches(key, binding) && this.conditionMatches(binding.when, context) && !this.isDisabled(binding)) return binding;
|
|
8333
|
+
return null;
|
|
8334
|
+
}
|
|
8335
|
+
/**
|
|
8336
|
+
* Check if a key event matches a binding's key specification.
|
|
8337
|
+
*/ keyMatches(key, binding) {
|
|
8338
|
+
const keys = Array.isArray(binding.key) ? binding.key : [binding.key];
|
|
8339
|
+
if (!(keys.includes(key.name) || key.sequence && keys.includes(key.sequence))) return false;
|
|
8340
|
+
const ctrlMatches = (binding.ctrl ?? false) === (key.ctrl ?? false);
|
|
8341
|
+
const metaMatches = (binding.meta ?? false) === (key.meta ?? false);
|
|
8342
|
+
const shiftMatches = (binding.shift ?? false) === (key.shift ?? false);
|
|
8343
|
+
return ctrlMatches && metaMatches && shiftMatches;
|
|
8344
|
+
}
|
|
8345
|
+
/**
|
|
8346
|
+
* Check if context matches a binding's condition.
|
|
8347
|
+
*/ conditionMatches(condition, context) {
|
|
8348
|
+
if (!condition) return true;
|
|
8349
|
+
if (condition.hasPrompt !== void 0 && condition.hasPrompt !== context.hasPrompt) return false;
|
|
8350
|
+
if (condition.inInputMode !== void 0 && condition.inInputMode !== context.inInputMode) return false;
|
|
8351
|
+
if (condition.focusArea !== void 0 && condition.focusArea !== context.focusArea) return false;
|
|
8352
|
+
if (condition.isFilterActive !== void 0 && condition.isFilterActive !== context.isFilterActive) return false;
|
|
8353
|
+
if (condition.isHelpVisible !== void 0 && condition.isHelpVisible !== context.isHelpVisible) return false;
|
|
8354
|
+
if (condition.hasSidebar !== void 0 && condition.hasSidebar !== context.hasSidebar) return false;
|
|
8355
|
+
return true;
|
|
8356
|
+
}
|
|
8357
|
+
/**
|
|
8358
|
+
* Check if a binding is disabled.
|
|
8359
|
+
*/ isDisabled(binding) {
|
|
8360
|
+
return (Array.isArray(binding.key) ? binding.key : [binding.key]).some((k) => this.disabled.has(k));
|
|
8361
|
+
}
|
|
8362
|
+
/**
|
|
8363
|
+
* Sort bindings by priority (higher first).
|
|
8364
|
+
*/ sortBindings() {
|
|
8365
|
+
this.bindings.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
|
|
8366
|
+
}
|
|
8367
|
+
};
|
|
8368
|
+
/**
|
|
8369
|
+
* Format a key binding for display.
|
|
8370
|
+
*/ function formatKeyBinding(binding) {
|
|
8371
|
+
const keys = Array.isArray(binding.key) ? binding.key : [binding.key];
|
|
8372
|
+
const parts = [];
|
|
8373
|
+
if (binding.ctrl) parts.push("Ctrl");
|
|
8374
|
+
if (binding.meta) parts.push("Cmd");
|
|
8375
|
+
if (binding.shift) parts.push("Shift");
|
|
8376
|
+
const keyDisplay = keys.map((k) => {
|
|
8377
|
+
switch (k) {
|
|
8378
|
+
case "up": return "↑";
|
|
8379
|
+
case "down": return "↓";
|
|
8380
|
+
case "left": return "←";
|
|
8381
|
+
case "right": return "→";
|
|
8382
|
+
case "return": return "Enter";
|
|
8383
|
+
case "escape": return "Esc";
|
|
8384
|
+
case "space": return "Space";
|
|
8385
|
+
case "tab": return "Tab";
|
|
8386
|
+
case "\\": return "\\";
|
|
8387
|
+
default: return k;
|
|
8388
|
+
}
|
|
8389
|
+
}).join("/");
|
|
8390
|
+
parts.push(keyDisplay);
|
|
8391
|
+
return parts.join("+");
|
|
8392
|
+
}
|
|
8393
|
+
|
|
8394
|
+
//#endregion
|
|
8395
|
+
//#region src/keyboard/create_bindings.ts
|
|
8396
|
+
/**
|
|
8397
|
+
* Create the default keybindings with access to manager and screens.
|
|
8398
|
+
*/ function createDefaultBindings(handlers) {
|
|
8399
|
+
const { manager, getActiveScreen, toggleHelp, toggleFilter, closeFilter } = handlers;
|
|
8400
|
+
const bindings = [];
|
|
8401
|
+
bindings.push({
|
|
8402
|
+
key: "escape",
|
|
8403
|
+
handler: () => {
|
|
8404
|
+
const screen = getActiveScreen();
|
|
8405
|
+
if (screen?.isPromptInInputMode()) {
|
|
8406
|
+
screen.promptExitInputMode();
|
|
8407
|
+
return true;
|
|
8408
|
+
}
|
|
8409
|
+
},
|
|
8410
|
+
description: "Exit input mode",
|
|
8411
|
+
category: "prompt",
|
|
8412
|
+
when: {
|
|
8413
|
+
hasPrompt: true,
|
|
8414
|
+
inInputMode: true
|
|
8415
|
+
},
|
|
8416
|
+
priority: 100
|
|
8417
|
+
});
|
|
8418
|
+
bindings.push({
|
|
8419
|
+
key: "return",
|
|
8420
|
+
handler: () => {
|
|
8421
|
+
const screen = getActiveScreen();
|
|
8422
|
+
if (screen?.isPromptInInputMode()) {
|
|
8423
|
+
screen.promptSubmit();
|
|
8424
|
+
return true;
|
|
8425
|
+
}
|
|
8426
|
+
},
|
|
8427
|
+
description: "Submit input",
|
|
8428
|
+
category: "prompt",
|
|
8429
|
+
when: {
|
|
8430
|
+
hasPrompt: true,
|
|
8431
|
+
inInputMode: true
|
|
8432
|
+
},
|
|
8433
|
+
priority: 100
|
|
8434
|
+
});
|
|
8435
|
+
bindings.push({
|
|
8436
|
+
key: "backspace",
|
|
8437
|
+
handler: () => {
|
|
8438
|
+
const screen = getActiveScreen();
|
|
8439
|
+
if (screen?.isPromptInInputMode()) {
|
|
8440
|
+
screen.promptDeleteLastChar();
|
|
8441
|
+
return true;
|
|
8442
|
+
}
|
|
8443
|
+
},
|
|
8444
|
+
description: "Delete character",
|
|
8445
|
+
category: "prompt",
|
|
8446
|
+
when: {
|
|
8447
|
+
hasPrompt: true,
|
|
8448
|
+
inInputMode: true
|
|
8449
|
+
},
|
|
8450
|
+
priority: 100
|
|
8451
|
+
});
|
|
8452
|
+
bindings.push({
|
|
8453
|
+
key: ["up", "k"],
|
|
8454
|
+
handler: () => {
|
|
8455
|
+
const screen = getActiveScreen();
|
|
8456
|
+
const prompt = screen?.getActivePrompt();
|
|
8457
|
+
if (prompt?.type === "choice" || prompt?.type === "multiChoice") {
|
|
8458
|
+
screen?.promptNavigateUp();
|
|
8459
|
+
return true;
|
|
8460
|
+
}
|
|
8461
|
+
},
|
|
8462
|
+
description: "Navigate up",
|
|
8463
|
+
category: "prompt",
|
|
8464
|
+
when: {
|
|
8465
|
+
hasPrompt: true,
|
|
8466
|
+
inInputMode: false
|
|
8467
|
+
},
|
|
8468
|
+
priority: 90
|
|
8469
|
+
});
|
|
8470
|
+
bindings.push({
|
|
8471
|
+
key: ["down", "j"],
|
|
8472
|
+
handler: () => {
|
|
8473
|
+
const screen = getActiveScreen();
|
|
8474
|
+
const prompt = screen?.getActivePrompt();
|
|
8475
|
+
if (prompt?.type === "choice" || prompt?.type === "multiChoice") {
|
|
8476
|
+
screen?.promptNavigateDown();
|
|
8477
|
+
return true;
|
|
8478
|
+
}
|
|
8479
|
+
},
|
|
8480
|
+
description: "Navigate down",
|
|
8481
|
+
category: "prompt",
|
|
8482
|
+
when: {
|
|
8483
|
+
hasPrompt: true,
|
|
8484
|
+
inInputMode: false
|
|
8485
|
+
},
|
|
8486
|
+
priority: 90
|
|
8487
|
+
});
|
|
8488
|
+
bindings.push({
|
|
8489
|
+
key: ["left", "h"],
|
|
8490
|
+
handler: () => {
|
|
8491
|
+
const screen = getActiveScreen();
|
|
8492
|
+
if ((screen?.getActivePrompt())?.type === "confirm") {
|
|
8493
|
+
screen?.promptNavigateLeft();
|
|
8494
|
+
return true;
|
|
8495
|
+
}
|
|
8496
|
+
},
|
|
8497
|
+
description: "Select confirm",
|
|
8498
|
+
category: "prompt",
|
|
8499
|
+
when: {
|
|
8500
|
+
hasPrompt: true,
|
|
8501
|
+
inInputMode: false
|
|
8502
|
+
},
|
|
8503
|
+
priority: 90
|
|
8504
|
+
});
|
|
8505
|
+
bindings.push({
|
|
8506
|
+
key: ["right", "l"],
|
|
8507
|
+
handler: () => {
|
|
8508
|
+
const screen = getActiveScreen();
|
|
8509
|
+
if ((screen?.getActivePrompt())?.type === "confirm") {
|
|
8510
|
+
screen?.promptNavigateRight();
|
|
8511
|
+
return true;
|
|
8512
|
+
}
|
|
8513
|
+
},
|
|
8514
|
+
description: "Select cancel",
|
|
8515
|
+
category: "prompt",
|
|
8516
|
+
when: {
|
|
8517
|
+
hasPrompt: true,
|
|
8518
|
+
inInputMode: false
|
|
8519
|
+
},
|
|
8520
|
+
priority: 90
|
|
8521
|
+
});
|
|
8522
|
+
bindings.push({
|
|
8523
|
+
key: "space",
|
|
8524
|
+
handler: () => {
|
|
8525
|
+
const screen = getActiveScreen();
|
|
8526
|
+
if ((screen?.getActivePrompt())?.type === "multiChoice") {
|
|
8527
|
+
screen?.promptToggleSelection();
|
|
8528
|
+
return true;
|
|
8529
|
+
}
|
|
8530
|
+
},
|
|
8531
|
+
description: "Toggle selection",
|
|
8532
|
+
category: "prompt",
|
|
8533
|
+
when: {
|
|
8534
|
+
hasPrompt: true,
|
|
8535
|
+
inInputMode: false
|
|
8536
|
+
},
|
|
8537
|
+
priority: 90
|
|
8538
|
+
});
|
|
8539
|
+
bindings.push({
|
|
8540
|
+
key: "return",
|
|
8541
|
+
handler: () => {
|
|
8542
|
+
const screen = getActiveScreen();
|
|
8543
|
+
const prompt = screen?.getActivePrompt();
|
|
8544
|
+
if (!prompt) return false;
|
|
8545
|
+
if (prompt.type === "choice") {
|
|
8546
|
+
if (!screen?.promptEnterInputMode()) screen?.promptSubmit();
|
|
8547
|
+
return true;
|
|
8548
|
+
} else if (prompt.type === "confirm") {
|
|
8549
|
+
screen?.promptSubmit();
|
|
8550
|
+
return true;
|
|
8551
|
+
} else if (prompt.type === "multiChoice") {
|
|
8552
|
+
if (screen?.canSubmitPrompt()) screen.promptSubmit();
|
|
8553
|
+
return true;
|
|
8554
|
+
}
|
|
8555
|
+
},
|
|
8556
|
+
description: "Submit selection",
|
|
8557
|
+
category: "prompt",
|
|
8558
|
+
when: {
|
|
8559
|
+
hasPrompt: true,
|
|
8560
|
+
inInputMode: false
|
|
8561
|
+
},
|
|
8562
|
+
priority: 90
|
|
8563
|
+
});
|
|
8564
|
+
bindings.push({
|
|
8565
|
+
key: "?",
|
|
8566
|
+
handler: () => {
|
|
8567
|
+
toggleHelp();
|
|
8568
|
+
return true;
|
|
8569
|
+
},
|
|
8570
|
+
description: "Toggle help",
|
|
8571
|
+
category: "general",
|
|
8572
|
+
when: {
|
|
8573
|
+
hasPrompt: false,
|
|
8574
|
+
isFilterActive: false
|
|
8575
|
+
},
|
|
8576
|
+
priority: 50
|
|
8577
|
+
});
|
|
8578
|
+
bindings.push({
|
|
8579
|
+
key: "escape",
|
|
8580
|
+
handler: () => {
|
|
8581
|
+
toggleHelp();
|
|
8582
|
+
return true;
|
|
8583
|
+
},
|
|
8584
|
+
description: "Close help",
|
|
8585
|
+
category: "general",
|
|
8586
|
+
when: { isHelpVisible: true },
|
|
8587
|
+
priority: 80
|
|
8588
|
+
});
|
|
8589
|
+
bindings.push({
|
|
8590
|
+
key: "/",
|
|
8591
|
+
handler: () => {
|
|
8592
|
+
toggleFilter();
|
|
8593
|
+
return true;
|
|
8594
|
+
},
|
|
8595
|
+
description: "Toggle filter",
|
|
8596
|
+
category: "filter",
|
|
8597
|
+
when: {
|
|
8598
|
+
hasPrompt: false,
|
|
8599
|
+
isHelpVisible: false
|
|
8600
|
+
},
|
|
8601
|
+
priority: 50
|
|
8602
|
+
});
|
|
8603
|
+
bindings.push({
|
|
8604
|
+
key: "escape",
|
|
8605
|
+
handler: () => {
|
|
8606
|
+
closeFilter();
|
|
8607
|
+
return true;
|
|
8608
|
+
},
|
|
8609
|
+
description: "Close filter",
|
|
8610
|
+
category: "filter",
|
|
8611
|
+
when: { isFilterActive: true },
|
|
8612
|
+
priority: 70
|
|
8613
|
+
});
|
|
8614
|
+
bindings.push({
|
|
8615
|
+
key: "tab",
|
|
8616
|
+
handler: () => {
|
|
8617
|
+
handlers.filterCycleField();
|
|
8618
|
+
return true;
|
|
8619
|
+
},
|
|
8620
|
+
description: "Cycle filter fields",
|
|
8621
|
+
category: "filter",
|
|
8622
|
+
when: { isFilterActive: true },
|
|
8623
|
+
priority: 70
|
|
8624
|
+
});
|
|
8625
|
+
bindings.push({
|
|
8626
|
+
key: "backspace",
|
|
8627
|
+
handler: () => {
|
|
8628
|
+
handlers.filterDeleteChar();
|
|
8629
|
+
return true;
|
|
8630
|
+
},
|
|
8631
|
+
description: "Delete character",
|
|
8632
|
+
category: "filter",
|
|
8633
|
+
when: { isFilterActive: true },
|
|
8634
|
+
priority: 70
|
|
8635
|
+
});
|
|
8636
|
+
for (let i = 1; i <= 7; i++) bindings.push({
|
|
8637
|
+
key: String(i),
|
|
8638
|
+
handler: () => {
|
|
8639
|
+
handlers.filterToggleLevel(i - 1);
|
|
8640
|
+
return true;
|
|
8641
|
+
},
|
|
8642
|
+
description: `Toggle level ${i}`,
|
|
8643
|
+
category: "filter",
|
|
8644
|
+
when: { isFilterActive: true },
|
|
8645
|
+
priority: 70
|
|
8646
|
+
});
|
|
8647
|
+
bindings.push({
|
|
8648
|
+
key: "q",
|
|
8649
|
+
handler: () => {
|
|
8650
|
+
manager.unbind();
|
|
8651
|
+
return true;
|
|
8652
|
+
},
|
|
8653
|
+
description: "Exit",
|
|
8654
|
+
category: "general",
|
|
8655
|
+
when: {
|
|
8656
|
+
hasPrompt: false,
|
|
8657
|
+
isFilterActive: false,
|
|
8658
|
+
isHelpVisible: false
|
|
8659
|
+
},
|
|
8660
|
+
priority: 10
|
|
8661
|
+
});
|
|
8662
|
+
bindings.push({
|
|
8663
|
+
key: "tab",
|
|
8664
|
+
handler: (_, ctx) => {
|
|
8665
|
+
if (ctx.hasSidebar) {
|
|
8666
|
+
manager.toggleFocus();
|
|
8667
|
+
return true;
|
|
8668
|
+
}
|
|
8669
|
+
},
|
|
8670
|
+
description: "Toggle focus",
|
|
8671
|
+
category: "navigation",
|
|
8672
|
+
when: {
|
|
8673
|
+
hasPrompt: false,
|
|
8674
|
+
isFilterActive: false
|
|
8675
|
+
},
|
|
8676
|
+
priority: 20
|
|
8677
|
+
});
|
|
8678
|
+
bindings.push({
|
|
8679
|
+
key: "\\",
|
|
8680
|
+
handler: (_, ctx) => {
|
|
8681
|
+
if (ctx.hasSidebar) {
|
|
8682
|
+
manager.toggleFocus();
|
|
8683
|
+
return true;
|
|
8684
|
+
}
|
|
8685
|
+
},
|
|
8686
|
+
description: "Toggle focus",
|
|
8687
|
+
category: "navigation",
|
|
8688
|
+
when: {
|
|
8689
|
+
hasPrompt: false,
|
|
8690
|
+
isFilterActive: false
|
|
8691
|
+
},
|
|
8692
|
+
priority: 20
|
|
8693
|
+
});
|
|
8694
|
+
bindings.push({
|
|
8695
|
+
key: ["up", "k"],
|
|
8696
|
+
handler: () => {
|
|
8697
|
+
manager.navigateUp();
|
|
8698
|
+
return true;
|
|
8699
|
+
},
|
|
8700
|
+
description: "Navigate up",
|
|
8701
|
+
category: "navigation",
|
|
8702
|
+
when: {
|
|
8703
|
+
focusArea: "sidebar",
|
|
8704
|
+
hasPrompt: false
|
|
8705
|
+
},
|
|
8706
|
+
priority: 30
|
|
8707
|
+
});
|
|
8708
|
+
bindings.push({
|
|
8709
|
+
key: ["down", "j"],
|
|
8710
|
+
handler: () => {
|
|
8711
|
+
manager.navigateDown();
|
|
8712
|
+
return true;
|
|
8713
|
+
},
|
|
8714
|
+
description: "Navigate down",
|
|
8715
|
+
category: "navigation",
|
|
8716
|
+
when: {
|
|
8717
|
+
focusArea: "sidebar",
|
|
8718
|
+
hasPrompt: false
|
|
8719
|
+
},
|
|
8720
|
+
priority: 30
|
|
8721
|
+
});
|
|
8722
|
+
bindings.push({
|
|
8723
|
+
key: "return",
|
|
8724
|
+
handler: () => {
|
|
8725
|
+
manager.selectCurrent();
|
|
8726
|
+
return true;
|
|
8727
|
+
},
|
|
8728
|
+
description: "Select screen",
|
|
8729
|
+
category: "navigation",
|
|
8730
|
+
when: {
|
|
8731
|
+
focusArea: "sidebar",
|
|
8732
|
+
hasPrompt: false
|
|
8733
|
+
},
|
|
8734
|
+
priority: 30
|
|
8735
|
+
});
|
|
8736
|
+
for (let i = 1; i <= 9; i++) bindings.push({
|
|
8737
|
+
key: String(i),
|
|
8738
|
+
handler: () => {
|
|
8739
|
+
const screens = manager.getScreens();
|
|
8740
|
+
if (i <= screens.length) {
|
|
8741
|
+
manager.setActiveScreen(screens[i - 1]);
|
|
8742
|
+
manager.setSelectedIndex(i - 1);
|
|
8743
|
+
return true;
|
|
8744
|
+
}
|
|
8745
|
+
},
|
|
8746
|
+
description: `Jump to screen ${i}`,
|
|
8747
|
+
category: "screen",
|
|
8748
|
+
when: {
|
|
8749
|
+
hasPrompt: false,
|
|
8750
|
+
isFilterActive: false
|
|
8751
|
+
},
|
|
8752
|
+
priority: 15
|
|
8753
|
+
});
|
|
8754
|
+
bindings.push({
|
|
8755
|
+
key: "c",
|
|
8756
|
+
handler: () => {
|
|
8757
|
+
getActiveScreen()?.clear();
|
|
8758
|
+
return true;
|
|
8759
|
+
},
|
|
8760
|
+
description: "Clear screen",
|
|
8761
|
+
category: "screen",
|
|
8762
|
+
when: {
|
|
8763
|
+
focusArea: "content",
|
|
8764
|
+
hasPrompt: false,
|
|
8765
|
+
isFilterActive: false
|
|
8766
|
+
},
|
|
8767
|
+
priority: 15
|
|
8768
|
+
});
|
|
8769
|
+
return bindings;
|
|
8770
|
+
}
|
|
8771
|
+
/**
|
|
8772
|
+
* Handle printable character input for prompts and filter.
|
|
8773
|
+
* This should be called for any key not handled by bindings.
|
|
8774
|
+
*/ function handlePrintableInput(key, context, handlers) {
|
|
8775
|
+
if (!key.sequence || key.sequence.length !== 1 || key.ctrl || key.meta) return false;
|
|
8776
|
+
const charCode = key.sequence.charCodeAt(0);
|
|
8777
|
+
if (charCode < 32 || charCode > 126) return false;
|
|
8778
|
+
if (context.isFilterActive) {
|
|
8779
|
+
handlers.filterAppendChar(key.sequence);
|
|
8780
|
+
return true;
|
|
8781
|
+
}
|
|
8782
|
+
if (context.hasPrompt && context.inInputMode) {
|
|
8783
|
+
handlers.getActiveScreen()?.promptAppendInput(key.sequence);
|
|
8784
|
+
return true;
|
|
8785
|
+
}
|
|
8786
|
+
return false;
|
|
8787
|
+
}
|
|
8788
|
+
|
|
8789
|
+
//#endregion
|
|
8790
|
+
//#region src/filter/filter_engine.ts
|
|
8791
|
+
/**
|
|
8792
|
+
* Filter engine for filtering log messages.
|
|
8793
|
+
*/ var FilterEngine = class {
|
|
8794
|
+
/**
|
|
8795
|
+
* Apply filter to messages array.
|
|
8796
|
+
*/ static filterMessages(messages, filter) {
|
|
8797
|
+
if (filter.searchQuery === "" && filter.enabledLevels.size === ALL_LOG_LEVELS.length) return messages;
|
|
8798
|
+
return messages.filter((msg) => {
|
|
8799
|
+
if (msg.type !== "log") {
|
|
8800
|
+
if (filter.searchQuery) return this.messageMatchesSearch(msg, filter.searchQuery);
|
|
8801
|
+
if (msg.type === "group") return true;
|
|
8802
|
+
return true;
|
|
8803
|
+
}
|
|
8804
|
+
const logMsg = msg;
|
|
8805
|
+
if (!filter.enabledLevels.has(logMsg.level)) return false;
|
|
8806
|
+
if (filter.searchQuery && !this.messageMatchesSearch(logMsg, filter.searchQuery)) return false;
|
|
8807
|
+
return true;
|
|
8808
|
+
});
|
|
8809
|
+
}
|
|
8810
|
+
/**
|
|
8811
|
+
* Check if a message matches the search query.
|
|
8812
|
+
*/ static messageMatchesSearch(msg, query) {
|
|
8813
|
+
const lowerQuery = query.toLowerCase();
|
|
8814
|
+
switch (msg.type) {
|
|
8815
|
+
case "log": return msg.content.toLowerCase().includes(lowerQuery) || (msg.label?.toLowerCase().includes(lowerQuery) ?? false);
|
|
8816
|
+
case "file":
|
|
8817
|
+
case "fileError": return msg.filePath.toLowerCase().includes(lowerQuery) || msg.content.toLowerCase().includes(lowerQuery);
|
|
8818
|
+
case "diff": return msg.filePath.toLowerCase().includes(lowerQuery) || msg.diff.toLowerCase().includes(lowerQuery);
|
|
8819
|
+
case "loading": return msg.content.toLowerCase().includes(lowerQuery) || (msg.resolvedContent?.toLowerCase().includes(lowerQuery) ?? false);
|
|
8820
|
+
case "progress": return msg.label.toLowerCase().includes(lowerQuery);
|
|
8821
|
+
case "group": return msg.label.toLowerCase().includes(lowerQuery);
|
|
8822
|
+
case "table": return (msg.title?.toLowerCase().includes(lowerQuery) ?? false) || msg.headers.some((h) => h.toLowerCase().includes(lowerQuery)) || msg.rows.some((row) => row.some((cell) => cell.toLowerCase().includes(lowerQuery)));
|
|
8823
|
+
default: return false;
|
|
8824
|
+
}
|
|
8825
|
+
}
|
|
8826
|
+
/**
|
|
8827
|
+
* Count messages by log level.
|
|
8828
|
+
*/ static countByLevel(messages) {
|
|
8829
|
+
const counts = {
|
|
8830
|
+
debug: 0,
|
|
8831
|
+
log: 0,
|
|
8832
|
+
verbose: 0,
|
|
8833
|
+
error: 0,
|
|
8834
|
+
fatal: 0,
|
|
8835
|
+
warn: 0
|
|
8836
|
+
};
|
|
8837
|
+
for (const msg of messages) if (msg.type === "log") counts[msg.level]++;
|
|
8838
|
+
return counts;
|
|
8839
|
+
}
|
|
8840
|
+
};
|
|
8841
|
+
|
|
8842
|
+
//#endregion
|
|
8843
|
+
export { ALL_LOG_LEVELS, Adapter, COMMON_FILETYPES, CONTENT_MANAGER_EVENTS, DEFAULT_LOG_LEVEL_COLORS, ERROR_HIGHLIGHT_COLORS, FILE_COLORS, FilterEngine, GROUP_COLORS, HEADER_COLORS, IsomorphicLogger, _IsomorphicLoggerFactory as IsomorphicLoggerFactory, KeyboardManager, LoggerOptionsSchema, MANAGER_EVENTS, _MissingAdapterOverride as MissingAdapterOverride, PROGRESS_COLORS, PROMPT_COLORS, Prompt, _PromptInstance as PromptInstance, PromptOptionsSchema, ReadlinePromptService, RenderMode, SCREEN_EVENTS, SEPARATOR_COLORS, SIDEBAR_COLORS, SIDEBAR_EVENTS, STATUS_INDICATORS, Screen, _ScreenFactory as ScreenFactory, ScreenInstance, ScreenLogger, _ScreenLoggerInstance as ScreenLoggerInstance, ScreenManager, _ScreenManagerInstance as ScreenManagerInstance, ScreenOptionsSchema, TABLE_COLORS, VARIANT_COLORS, captureTrace, createDefaultBindings, createDefaultFilterState, createTheme, createThemeFrom, darkTheme, dynamicImport, formatKeyBinding, formatObject, getFileName, getLogLevelColors, getPromptDefaultValue, getThemePreset, handlePrintableInput, hasActiveFilter, highContrastTheme, isBunRuntime, lightTheme, mergeThemes, overrideConsoleLogger, printMessagesToStdout, printSingleMessage, resolveFiletype, resolveTheme };
|
|
6881
8844
|
//# sourceMappingURL=index.mjs.map
|