@bike4mind/cli 0.2.64-worktree-refactor-extract-search-query-builders.21815 → 0.2.64

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.
Files changed (85) hide show
  1. package/bin/bike4mind-cli.mjs +6 -6
  2. package/dist/BubblewrapRuntime-BHbtqvLx.mjs +72 -0
  3. package/dist/ConfigStore-CllM6jOf.mjs +8614 -0
  4. package/dist/ImageStore-DaKT_Ew8.mjs +202 -0
  5. package/dist/ProxyManager-Dl2nFk-A.mjs +259 -0
  6. package/dist/ProxyManager-kiOD1X8-.mjs +3 -0
  7. package/dist/SandboxOrchestrator-BEW3rqYi.mjs +159 -0
  8. package/dist/SandboxOrchestrator-CHZgSR3P.mjs +3 -0
  9. package/dist/SandboxRuntimeAdapter-C1B4t20N.mjs +57 -0
  10. package/dist/SandboxRuntimeAdapter-D7UAG13n.mjs +3 -0
  11. package/dist/SeatbeltRuntime-D4m0VOcD.mjs +116 -0
  12. package/dist/StderrViolationParser-D0afQ3-1.mjs +70 -0
  13. package/dist/ViolationLogStore-CZl35HcA.mjs +96 -0
  14. package/dist/bashExecute-BTkdqlSs-5foM20Lb.mjs +466 -0
  15. package/dist/commands/doctorCommand.mjs +101 -0
  16. package/dist/commands/headlessCommand.mjs +319 -0
  17. package/dist/commands/mcpCommand.mjs +218 -0
  18. package/dist/commands/updateCommand.mjs +40 -0
  19. package/dist/createFile-yQfh8uvk-I-yM5DxC.mjs +63 -0
  20. package/dist/deleteFile-DKHfnyny-G3b1Kj2T.mjs +66 -0
  21. package/dist/globFiles-D1en6joM-8jekiXdX.mjs +100 -0
  22. package/dist/grepSearch-aMamoBn_-DCJcY8JS.mjs +173 -0
  23. package/dist/index.mjs +6722 -0
  24. package/dist/pathValidation-Cgjh5WQO-DiCZTcq6.mjs +63 -0
  25. package/dist/store-Dw1nZX2Y.mjs +128 -0
  26. package/dist/store-nZExNOWX.mjs +3 -0
  27. package/dist/terminalSetup-rmr1P8KF.mjs +254 -0
  28. package/dist/tools-C6M5aW8W.mjs +20907 -0
  29. package/dist/treeSitterEngine-DCSXcm_3.mjs +309 -0
  30. package/dist/types-DBEjF9YS.mjs +59 -0
  31. package/dist/types-DK3P88Px.mjs +3 -0
  32. package/dist/updateChecker-Cu9dkHxV.mjs +120 -0
  33. package/package.json +10 -10
  34. package/dist/BubblewrapRuntime-PMIOLWKR.js +0 -71
  35. package/dist/HydrationEngine-YL2HWJ3V.js +0 -9
  36. package/dist/ImageStore-MMUOUPI2.js +0 -224
  37. package/dist/ProxyManager-HEB4TLVX.js +0 -7
  38. package/dist/SandboxOrchestrator-UIJ5GYBB.js +0 -8
  39. package/dist/SandboxRuntimeAdapter-FQ56MAB2.js +0 -13
  40. package/dist/SeatbeltRuntime-EE3TTLEP.js +0 -98
  41. package/dist/StderrViolationParser-7OYPM2DJ.js +0 -59
  42. package/dist/ViolationLogStore-RIIUVURH.js +0 -104
  43. package/dist/artifactExtractor-R7DIP2XO.js +0 -180
  44. package/dist/bashExecute-GLGLD3JD.js +0 -379
  45. package/dist/chunk-4BIBE3J7.js +0 -48
  46. package/dist/chunk-5LZS5CVJ.js +0 -161
  47. package/dist/chunk-BDQBOLYG.js +0 -120
  48. package/dist/chunk-BPFEGDC7.js +0 -192
  49. package/dist/chunk-EPIYC3LA.js +0 -13770
  50. package/dist/chunk-G4ZGEQFT.js +0 -250
  51. package/dist/chunk-GQGOWACU.js +0 -770
  52. package/dist/chunk-J6ZBI6TI.js +0 -1079
  53. package/dist/chunk-JW3JRHH7.js +0 -12433
  54. package/dist/chunk-KQAMBXAW.js +0 -163
  55. package/dist/chunk-KUVV2NAB.js +0 -19125
  56. package/dist/chunk-LTLJRF6I.js +0 -44
  57. package/dist/chunk-PFBYGCOW.js +0 -449
  58. package/dist/chunk-QWB6ZYY4.js +0 -48
  59. package/dist/chunk-SGPRXN4C.js +0 -245
  60. package/dist/chunk-UZUHPHZC.js +0 -95
  61. package/dist/chunk-WBE7SQUB.js +0 -241
  62. package/dist/chunk-Y4WOJJM3.js +0 -147
  63. package/dist/commands/doctorCommand.js +0 -87
  64. package/dist/commands/headlessCommand.js +0 -380
  65. package/dist/commands/mcpCommand.js +0 -203
  66. package/dist/commands/updateCommand.js +0 -42
  67. package/dist/create-C4VEEEYR.js +0 -12
  68. package/dist/createFile-6PSPLW6R.js +0 -71
  69. package/dist/deleteFile-AUSRLWIK.js +0 -73
  70. package/dist/formatConverter-5QEJDW24.js +0 -7
  71. package/dist/globFiles-TSRN64N2.js +0 -120
  72. package/dist/grepSearch-634XWZOJ.js +0 -216
  73. package/dist/index.js +0 -6779
  74. package/dist/llmMarkdownGenerator-Z6NB26TT.js +0 -371
  75. package/dist/markdownGenerator-SK2ZQQL4.js +0 -269
  76. package/dist/mementoService-N4IM6QAC.js +0 -12
  77. package/dist/notificationDeduplicator-HUC53NEW.js +0 -9
  78. package/dist/src-F4KZCAA2.js +0 -319
  79. package/dist/src-ISX322I7.js +0 -1101
  80. package/dist/store-CAB6BV3P.js +0 -11
  81. package/dist/subtractCredits-D4KEM6VU.js +0 -12
  82. package/dist/terminalSetup-C5FHMLC3.js +0 -214
  83. package/dist/treeSitterEngine-4SGFQDY3.js +0 -330
  84. package/dist/types-KB5NP6T4.js +0 -7
  85. package/dist/utils-JCHWDM4Z.js +0 -31
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+ import { realpathSync } from "fs";
3
+ import path from "path";
4
+ //#region ../../b4m-core/packages/services/dist/pathValidation-Cgjh5WQO.mjs
5
+ /**
6
+ * Resolves a path to its canonical form, following symlinks.
7
+ * If the path doesn't exist (e.g., file being created), resolves the
8
+ * nearest existing ancestor and appends the remaining segments.
9
+ */
10
+ function resolveRealPath(filePath) {
11
+ try {
12
+ return realpathSync(filePath);
13
+ } catch {
14
+ const parentDir = path.dirname(filePath);
15
+ const basename = path.basename(filePath);
16
+ if (parentDir === filePath) return filePath;
17
+ return path.join(resolveRealPath(parentDir), basename);
18
+ }
19
+ }
20
+ /**
21
+ * Validates if a path is within any of the allowed directories.
22
+ * Always includes process.cwd() as an allowed directory.
23
+ * Resolves symlinks to prevent symlink-based directory escapes.
24
+ *
25
+ * @param filePath - The path to validate (can be relative or absolute)
26
+ * @param allowedDirectories - Optional list of additional allowed directories
27
+ * @returns Object with validation result, resolved path, and matched directory if allowed
28
+ */
29
+ function isPathAllowed(filePath, allowedDirectories) {
30
+ const cwd = resolveRealPath(process.cwd());
31
+ const allAllowed = [cwd, ...(allowedDirectories || []).map((d) => resolveRealPath(d))];
32
+ const normalizedPath = path.normalize(filePath);
33
+ const resolvedPath = resolveRealPath(path.isAbsolute(normalizedPath) ? normalizedPath : path.resolve(cwd, normalizedPath));
34
+ for (const dir of allAllowed) if (resolvedPath === dir || resolvedPath.startsWith(dir + path.sep)) return {
35
+ allowed: true,
36
+ resolvedPath,
37
+ matchedDirectory: dir
38
+ };
39
+ return {
40
+ allowed: false,
41
+ resolvedPath
42
+ };
43
+ }
44
+ /**
45
+ * Throws an error if the path is not within allowed directories.
46
+ *
47
+ * @param filePath - The path to validate
48
+ * @param allowedDirectories - Optional list of additional allowed directories
49
+ * @param operation - Description of the operation (for error message), e.g., 'read', 'write', 'delete'
50
+ * @returns The resolved absolute path if allowed
51
+ * @throws Error if path is not within allowed directories
52
+ */
53
+ function assertPathAllowed(filePath, allowedDirectories, operation = "access") {
54
+ const result = isPathAllowed(filePath, allowedDirectories);
55
+ if (!result.allowed) {
56
+ const cwd = process.cwd();
57
+ const dirsMsg = allowedDirectories && allowedDirectories.length > 0 ? `Allowed directories: ${[cwd, ...allowedDirectories].join(", ")}` : `Working directory: ${cwd}`;
58
+ throw new Error(`Access denied: Cannot ${operation} files outside allowed directories. ${dirsMsg}`);
59
+ }
60
+ return result.resolvedPath;
61
+ }
62
+ //#endregion
63
+ export { isPathAllowed as n, assertPathAllowed as t };
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env node
2
+ import { create } from "zustand";
3
+ //#region src/store/index.ts
4
+ /** Active job statuses (jobs still in progress) */
5
+ const ACTIVE_STATUSES = new Set(["running", "queued"]);
6
+ /** Check if a job status is active (running or queued) */
7
+ function isActiveStatus(status) {
8
+ return ACTIVE_STATUSES.has(status);
9
+ }
10
+ const useCliStore = create((set) => ({
11
+ session: null,
12
+ setSession: (session) => set({ session }),
13
+ addMessage: (message) => set((state) => {
14
+ if (!state.session) return state;
15
+ return { session: {
16
+ ...state.session,
17
+ messages: [...state.session.messages, message],
18
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
19
+ } };
20
+ }),
21
+ pendingMessages: [],
22
+ addPendingMessage: (message) => set((state) => ({ pendingMessages: [...state.pendingMessages, message] })),
23
+ updatePendingMessage: (index, message) => set((state) => {
24
+ const updated = [...state.pendingMessages];
25
+ updated[index] = message;
26
+ return { pendingMessages: updated };
27
+ }),
28
+ clearPendingMessages: () => set({ pendingMessages: [] }),
29
+ completePendingMessage: (index, finalMessage) => set((state) => {
30
+ const pending = [...state.pendingMessages];
31
+ pending.splice(index, 1);
32
+ const session = state.session;
33
+ if (!session) return { pendingMessages: pending };
34
+ return {
35
+ pendingMessages: pending,
36
+ session: {
37
+ ...session,
38
+ messages: [...session.messages, finalMessage],
39
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
40
+ }
41
+ };
42
+ }),
43
+ isThinking: false,
44
+ setIsThinking: (thinking) => set({ isThinking: thinking }),
45
+ inputValue: "",
46
+ setInputValue: (value) => set({ inputValue: value }),
47
+ clearInput: () => set({
48
+ inputValue: "",
49
+ pastedContent: null,
50
+ pastedLineCount: 0
51
+ }),
52
+ pastedContent: null,
53
+ pastedLineCount: 0,
54
+ setPastedContent: (content, lineCount) => set({
55
+ pastedContent: content,
56
+ pastedLineCount: lineCount,
57
+ inputValue: content
58
+ }),
59
+ clearPaste: () => set({
60
+ pastedContent: null,
61
+ pastedLineCount: 0,
62
+ inputValue: ""
63
+ }),
64
+ permissionPrompt: null,
65
+ permissionQueue: [],
66
+ enqueuePermissionPrompt: (prompt) => set((state) => {
67
+ if (!state.permissionPrompt) return { permissionPrompt: prompt };
68
+ return { permissionQueue: [...state.permissionQueue, prompt] };
69
+ }),
70
+ dequeuePermissionPrompt: () => set((state) => {
71
+ const [next, ...rest] = state.permissionQueue;
72
+ return {
73
+ permissionPrompt: next ?? null,
74
+ permissionQueue: rest
75
+ };
76
+ }),
77
+ userQuestionPrompt: null,
78
+ userQuestionQueue: [],
79
+ enqueueUserQuestionPrompt: (prompt) => set((state) => {
80
+ if (!state.userQuestionPrompt) return { userQuestionPrompt: prompt };
81
+ return { userQuestionQueue: [...state.userQuestionQueue, prompt] };
82
+ }),
83
+ dequeueUserQuestionPrompt: () => set((state) => {
84
+ const [next, ...rest] = state.userQuestionQueue;
85
+ return {
86
+ userQuestionPrompt: next ?? null,
87
+ userQuestionQueue: rest
88
+ };
89
+ }),
90
+ showConfigEditor: false,
91
+ setShowConfigEditor: (show) => set({ showConfigEditor: show }),
92
+ showMcpViewer: false,
93
+ setShowMcpViewer: (show) => set({ showMcpViewer: show }),
94
+ autoAcceptEdits: false,
95
+ toggleAutoAcceptEdits: () => set((state) => ({ autoAcceptEdits: !state.autoAcceptEdits })),
96
+ exitRequested: false,
97
+ setExitRequested: (requested) => set({ exitRequested: requested }),
98
+ backgroundAgents: [],
99
+ upsertBackgroundAgent: (job) => set((state) => {
100
+ const existing = state.backgroundAgents.findIndex((j) => j.id === job.id);
101
+ if (existing >= 0) {
102
+ const updated = [...state.backgroundAgents];
103
+ updated[existing] = job;
104
+ return { backgroundAgents: updated };
105
+ }
106
+ return { backgroundAgents: [...state.backgroundAgents, job] };
107
+ }),
108
+ cleanupCompletedBackgroundAgents: () => set((state) => ({ backgroundAgents: state.backgroundAgents.filter((j) => isActiveStatus(j.status)) })),
109
+ completedGroupNotifications: [],
110
+ addCompletedGroupNotification: (notification, groupDescription) => set((state) => ({ completedGroupNotifications: [...state.completedGroupNotifications, {
111
+ notification,
112
+ groupDescription,
113
+ timestamp: Date.now()
114
+ }] })),
115
+ clearCompletedGroupNotifications: () => set({ completedGroupNotifications: [] }),
116
+ pendingBackgroundTrigger: false,
117
+ setPendingBackgroundTrigger: (pending) => set({ pendingBackgroundTrigger: pending }),
118
+ tavernActivityLog: [],
119
+ addTavernLogEntry: (entry) => set((state) => {
120
+ const log = [...state.tavernActivityLog, entry];
121
+ return { tavernActivityLog: log.length > 200 ? log.slice(-200) : log };
122
+ }),
123
+ clearTavernActivityLog: () => set({ tavernActivityLog: [] })
124
+ }));
125
+ /** Select only active (running or queued) background agents */
126
+ const selectActiveBackgroundAgents = (state) => state.backgroundAgents.filter((j) => isActiveStatus(j.status));
127
+ //#endregion
128
+ export { useCliStore as n, selectActiveBackgroundAgents as t };
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { n as useCliStore } from "./store-Dw1nZX2Y.mjs";
3
+ export { useCliStore };
@@ -0,0 +1,254 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync, promises } from "fs";
3
+ import { homedir } from "os";
4
+ import path from "path";
5
+ //#region src/utils/terminalSetup.ts
6
+ /**
7
+ * Terminal setup utility for configuring Shift+Enter keybindings.
8
+ *
9
+ * Most terminal emulators send the same byte (\r) for both Enter and Shift+Enter,
10
+ * making them indistinguishable. This utility detects the user's terminal and provides
11
+ * instructions or automatic configuration to make Shift+Enter emit a distinct sequence.
12
+ *
13
+ * Terminals with native Shift+Enter support (no setup needed):
14
+ * - iTerm2, WezTerm, Ghostty, Kitty
15
+ *
16
+ * Terminals that need configuration:
17
+ * - VS Code integrated terminal
18
+ * - Alacritty
19
+ * - Zed
20
+ * - macOS Terminal.app
21
+ */
22
+ const TERMINAL_INFO = {
23
+ iterm2: {
24
+ name: "iTerm2",
25
+ status: "native"
26
+ },
27
+ wezterm: {
28
+ name: "WezTerm",
29
+ status: "native"
30
+ },
31
+ ghostty: {
32
+ name: "Ghostty",
33
+ status: "native"
34
+ },
35
+ kitty: {
36
+ name: "Kitty",
37
+ status: "native"
38
+ },
39
+ vscode: {
40
+ name: "VS Code",
41
+ status: "configurable"
42
+ },
43
+ alacritty: {
44
+ name: "Alacritty",
45
+ status: "configurable"
46
+ },
47
+ zed: {
48
+ name: "Zed",
49
+ status: "manual"
50
+ },
51
+ terminal_app: {
52
+ name: "Terminal.app",
53
+ status: "manual"
54
+ },
55
+ warp: {
56
+ name: "Warp",
57
+ status: "manual"
58
+ },
59
+ unknown: {
60
+ name: "Unknown",
61
+ status: "unknown"
62
+ }
63
+ };
64
+ /**
65
+ * Detect the current terminal emulator from environment variables.
66
+ */
67
+ function detectTerminal() {
68
+ const termProgram = process.env["TERM_PROGRAM"] ?? "";
69
+ const term = process.env["TERM"] ?? "";
70
+ if (termProgram === "vscode" || process.env["VSCODE_PID"]) return {
71
+ id: "vscode",
72
+ ...TERMINAL_INFO.vscode
73
+ };
74
+ if (termProgram === "iTerm.app" || process.env["ITERM_SESSION_ID"]) return {
75
+ id: "iterm2",
76
+ ...TERMINAL_INFO.iterm2
77
+ };
78
+ if (termProgram === "WezTerm" || process.env["WEZTERM_PANE"]) return {
79
+ id: "wezterm",
80
+ ...TERMINAL_INFO.wezterm
81
+ };
82
+ if (termProgram === "ghostty" || term === "xterm-ghostty") return {
83
+ id: "ghostty",
84
+ ...TERMINAL_INFO.ghostty
85
+ };
86
+ if (term === "xterm-kitty" || process.env["KITTY_PID"]) return {
87
+ id: "kitty",
88
+ ...TERMINAL_INFO.kitty
89
+ };
90
+ if (termProgram === "Alacritty" || term === "alacritty") return {
91
+ id: "alacritty",
92
+ ...TERMINAL_INFO.alacritty
93
+ };
94
+ if (termProgram === "WarpTerminal" || process.env["WARP_IS_LOCAL_SHELL_SESSION"]) return {
95
+ id: "warp",
96
+ ...TERMINAL_INFO.warp
97
+ };
98
+ if (termProgram === "zed") return {
99
+ id: "zed",
100
+ ...TERMINAL_INFO.zed
101
+ };
102
+ if (termProgram === "Apple_Terminal") return {
103
+ id: "terminal_app",
104
+ ...TERMINAL_INFO.terminal_app
105
+ };
106
+ return {
107
+ id: "unknown",
108
+ ...TERMINAL_INFO.unknown
109
+ };
110
+ }
111
+ /**
112
+ * VS Code keybindings.json entry for Shift+Enter → \x1b[13;2u (Kitty protocol)
113
+ */
114
+ const VSCODE_KEYBINDING = {
115
+ key: "shift+enter",
116
+ command: "workbench.action.terminal.sendSequence",
117
+ args: { text: "\x1B[13;2u" },
118
+ when: "terminalFocus"
119
+ };
120
+ /**
121
+ * Configure VS Code to send a Kitty-protocol escape sequence for Shift+Enter.
122
+ */
123
+ async function setupVSCode() {
124
+ const vscodeDir = [
125
+ path.join(homedir(), "Library", "Application Support", "Code", "User"),
126
+ path.join(homedir(), ".config", "Code", "User"),
127
+ path.join(homedir(), "AppData", "Roaming", "Code", "User")
128
+ ].find((dir) => existsSync(dir));
129
+ if (!vscodeDir) return {
130
+ success: false,
131
+ message: "Could not find VS Code settings directory.\nManually add this to your keybindings.json (Cmd+K Cmd+S → Open Keyboard Shortcuts JSON):\n\n" + JSON.stringify(VSCODE_KEYBINDING, null, 2)
132
+ };
133
+ const keybindingsPath = path.join(vscodeDir, "keybindings.json");
134
+ let keybindings = [];
135
+ if (existsSync(keybindingsPath)) {
136
+ const stripped = (await promises.readFile(keybindingsPath, "utf-8")).replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
137
+ try {
138
+ keybindings = JSON.parse(stripped);
139
+ } catch {
140
+ return {
141
+ success: false,
142
+ message: "Could not parse keybindings.json. Manually add this entry:\n\n" + JSON.stringify(VSCODE_KEYBINDING, null, 2)
143
+ };
144
+ }
145
+ }
146
+ if (keybindings.some((binding) => binding["key"] === "shift+enter" && binding["command"] === "workbench.action.terminal.sendSequence" && binding["when"] === "terminalFocus")) return {
147
+ success: true,
148
+ message: "VS Code is already configured for Shift+Enter newlines."
149
+ };
150
+ keybindings.push(VSCODE_KEYBINDING);
151
+ await promises.writeFile(keybindingsPath, JSON.stringify(keybindings, null, 2) + "\n", "utf-8");
152
+ return {
153
+ success: true,
154
+ message: `Updated ${keybindingsPath}\nShift+Enter will now insert a newline in the B4M CLI.
155
+ Restart your VS Code terminal for the change to take effect.`
156
+ };
157
+ }
158
+ /**
159
+ * Alacritty config entry for Shift+Enter → Kitty protocol sequence.
160
+ */
161
+ const ALACRITTY_TOML_SNIPPET = `
162
+ # B4M CLI: Shift+Enter sends Kitty-protocol sequence for newline
163
+ [[keyboard.bindings]]
164
+ key = "Return"
165
+ mods = "Shift"
166
+ chars = "\\u001b[13;2u"
167
+ `.trim();
168
+ /**
169
+ * Configure Alacritty to send a distinct escape sequence for Shift+Enter.
170
+ */
171
+ async function setupAlacritty() {
172
+ const configPaths = [path.join(homedir(), ".config", "alacritty", "alacritty.toml"), path.join(homedir(), ".alacritty.toml")];
173
+ const existingConfig = configPaths.find((p) => existsSync(p));
174
+ const configPath = existingConfig ?? configPaths[0];
175
+ let content = "";
176
+ if (existingConfig) {
177
+ content = await promises.readFile(configPath, "utf-8");
178
+ if (content.includes("[13;2u") || content.includes("\\u001b[13;2u")) return {
179
+ success: true,
180
+ message: "Alacritty is already configured for Shift+Enter newlines."
181
+ };
182
+ }
183
+ const newContent = content ? content.trimEnd() + "\n\n" + ALACRITTY_TOML_SNIPPET + "\n" : ALACRITTY_TOML_SNIPPET + "\n";
184
+ const configDir = path.dirname(configPath);
185
+ if (!existsSync(configDir)) await promises.mkdir(configDir, { recursive: true });
186
+ await promises.writeFile(configPath, newContent, "utf-8");
187
+ return {
188
+ success: true,
189
+ message: `Updated ${configPath}\nShift+Enter will now insert a newline in the B4M CLI.
190
+ Restart Alacritty for the change to take effect.`
191
+ };
192
+ }
193
+ /**
194
+ * Get manual instructions for terminals that can't be auto-configured.
195
+ */
196
+ function getManualInstructions(terminal) {
197
+ switch (terminal.id) {
198
+ case "zed": return "Add this to your Zed keymap.json (Zed → Settings → Open Key Bindings):\n\n" + JSON.stringify([{
199
+ context: "Terminal",
200
+ bindings: { "shift-enter": ["terminal::SendText", "\\u001b[13;2u"] }
201
+ }], null, 2);
202
+ case "terminal_app": return "macOS Terminal.app cannot send distinct Shift+Enter sequences.\n\nAlternatives:\n • Use Option+Enter (⌥+Enter) to insert newlines\n • Type \\ then Enter to insert newlines\n • Switch to iTerm2, WezTerm, or Ghostty for native Shift+Enter support";
203
+ case "warp": return "Warp terminal has limited keybinding customization.\n\nAlternatives:\n • Use Option+Enter (⌥+Enter) to insert newlines\n • Type \\ then Enter to insert newlines";
204
+ default: return "Your terminal needs to be configured to send a distinct escape sequence for Shift+Enter.\nConfigure Shift+Enter to send: \\x1b[13;2u (Kitty keyboard protocol)\n\nAlternatives that work in all terminals:\n • Option/Alt+Enter to insert newlines\n • Type \\ then Enter to insert newlines";
205
+ }
206
+ }
207
+ /**
208
+ * Run the terminal setup flow.
209
+ */
210
+ async function runTerminalSetup() {
211
+ const terminal = detectTerminal();
212
+ console.log(`\nDetected terminal: ${terminal.name}\n`);
213
+ switch (terminal.status) {
214
+ case "native":
215
+ console.log(`✅ ${terminal.name} natively supports Shift+Enter for newlines.\nNo configuration needed!
216
+ `);
217
+ break;
218
+ case "configurable": {
219
+ console.log(`Configuring ${terminal.name} for Shift+Enter support...\n`);
220
+ let result;
221
+ switch (terminal.id) {
222
+ case "vscode":
223
+ result = await setupVSCode();
224
+ break;
225
+ case "alacritty":
226
+ result = await setupAlacritty();
227
+ break;
228
+ default: result = {
229
+ success: false,
230
+ message: "No auto-configuration available."
231
+ };
232
+ }
233
+ console.log(result.success ? `✅ ${result.message}` : `⚠️ ${result.message}`);
234
+ console.log();
235
+ break;
236
+ }
237
+ case "manual":
238
+ console.log(`⚠️ ${terminal.name} requires manual configuration.\n`);
239
+ console.log(getManualInstructions(terminal));
240
+ console.log();
241
+ break;
242
+ case "unknown":
243
+ console.log(getManualInstructions(terminal));
244
+ console.log();
245
+ break;
246
+ }
247
+ console.log("Universal newline methods (work in all terminals):");
248
+ console.log(" • Option/Alt + Enter — insert newline");
249
+ console.log(" • \\ + Enter — insert newline (backslash-escape)");
250
+ console.log(" • Shift + Enter — insert newline (if terminal supports Kitty protocol)");
251
+ console.log();
252
+ }
253
+ //#endregion
254
+ export { runTerminalSetup };