maxsimcli 4.6.0 → 4.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/dist/assets/CHANGELOG.md +39 -0
  2. package/dist/cli.cjs +470 -961
  3. package/dist/cli.cjs.map +1 -1
  4. package/dist/{core-RRjCSt0G.cjs → core-D5zUr9cb.cjs} +4 -3
  5. package/dist/core-D5zUr9cb.cjs.map +1 -0
  6. package/dist/install.cjs +3 -195
  7. package/dist/install.cjs.map +1 -1
  8. package/dist/mcp-server.cjs +2853 -217
  9. package/dist/mcp-server.cjs.map +1 -1
  10. package/dist/{skills-MYlMkYNt.cjs → skills-CjFWZIGM.cjs} +6 -6
  11. package/dist/{skills-MYlMkYNt.cjs.map → skills-CjFWZIGM.cjs.map} +1 -1
  12. package/package.json +1 -7
  13. package/dist/.tsbuildinfo +0 -1
  14. package/dist/assets/dashboard/client/assets/index-C199D4Eb.css +0 -32
  15. package/dist/assets/dashboard/client/assets/index-nAXJLp0_.js +0 -233
  16. package/dist/assets/dashboard/client/index.html +0 -19
  17. package/dist/assets/dashboard/server.js +0 -78813
  18. package/dist/backend/index.d.ts +0 -4
  19. package/dist/backend/index.d.ts.map +0 -1
  20. package/dist/backend/index.js +0 -12
  21. package/dist/backend/index.js.map +0 -1
  22. package/dist/backend/lifecycle.d.ts +0 -13
  23. package/dist/backend/lifecycle.d.ts.map +0 -1
  24. package/dist/backend/lifecycle.js +0 -168
  25. package/dist/backend/lifecycle.js.map +0 -1
  26. package/dist/backend/server.d.ts +0 -13
  27. package/dist/backend/server.d.ts.map +0 -1
  28. package/dist/backend/server.js +0 -1013
  29. package/dist/backend/server.js.map +0 -1
  30. package/dist/backend/terminal.d.ts +0 -49
  31. package/dist/backend/terminal.d.ts.map +0 -1
  32. package/dist/backend/terminal.js +0 -209
  33. package/dist/backend/terminal.js.map +0 -1
  34. package/dist/backend/types.d.ts +0 -77
  35. package/dist/backend/types.d.ts.map +0 -1
  36. package/dist/backend/types.js +0 -6
  37. package/dist/backend/types.js.map +0 -1
  38. package/dist/backend-server.cjs +0 -80672
  39. package/dist/backend-server.cjs.map +0 -1
  40. package/dist/backend-server.d.cts +0 -2
  41. package/dist/backend-server.d.ts +0 -11
  42. package/dist/backend-server.d.ts.map +0 -1
  43. package/dist/backend-server.js +0 -43
  44. package/dist/backend-server.js.map +0 -1
  45. package/dist/cli.d.cts +0 -2
  46. package/dist/cli.d.ts +0 -7
  47. package/dist/cli.d.ts.map +0 -1
  48. package/dist/cli.js +0 -510
  49. package/dist/cli.js.map +0 -1
  50. package/dist/core/artefakte.d.ts +0 -12
  51. package/dist/core/artefakte.d.ts.map +0 -1
  52. package/dist/core/artefakte.js +0 -152
  53. package/dist/core/artefakte.js.map +0 -1
  54. package/dist/core/commands.d.ts +0 -26
  55. package/dist/core/commands.d.ts.map +0 -1
  56. package/dist/core/commands.js +0 -550
  57. package/dist/core/commands.js.map +0 -1
  58. package/dist/core/config.d.ts +0 -10
  59. package/dist/core/config.d.ts.map +0 -1
  60. package/dist/core/config.js +0 -143
  61. package/dist/core/config.js.map +0 -1
  62. package/dist/core/context-loader.d.ts +0 -21
  63. package/dist/core/context-loader.d.ts.map +0 -1
  64. package/dist/core/context-loader.js +0 -212
  65. package/dist/core/context-loader.js.map +0 -1
  66. package/dist/core/core.d.ts +0 -91
  67. package/dist/core/core.d.ts.map +0 -1
  68. package/dist/core/core.js +0 -823
  69. package/dist/core/core.js.map +0 -1
  70. package/dist/core/dashboard-launcher.d.ts +0 -56
  71. package/dist/core/dashboard-launcher.d.ts.map +0 -1
  72. package/dist/core/dashboard-launcher.js +0 -246
  73. package/dist/core/dashboard-launcher.js.map +0 -1
  74. package/dist/core/drift.d.ts +0 -37
  75. package/dist/core/drift.d.ts.map +0 -1
  76. package/dist/core/drift.js +0 -213
  77. package/dist/core/drift.js.map +0 -1
  78. package/dist/core/frontmatter.d.ts +0 -33
  79. package/dist/core/frontmatter.d.ts.map +0 -1
  80. package/dist/core/frontmatter.js +0 -193
  81. package/dist/core/frontmatter.js.map +0 -1
  82. package/dist/core/index.d.ts +0 -28
  83. package/dist/core/index.d.ts.map +0 -1
  84. package/dist/core/index.js +0 -189
  85. package/dist/core/index.js.map +0 -1
  86. package/dist/core/init.d.ts +0 -287
  87. package/dist/core/init.d.ts.map +0 -1
  88. package/dist/core/init.js +0 -816
  89. package/dist/core/init.js.map +0 -1
  90. package/dist/core/milestone.d.ts +0 -9
  91. package/dist/core/milestone.d.ts.map +0 -1
  92. package/dist/core/milestone.js +0 -230
  93. package/dist/core/milestone.js.map +0 -1
  94. package/dist/core/phase.d.ts +0 -53
  95. package/dist/core/phase.d.ts.map +0 -1
  96. package/dist/core/phase.js +0 -891
  97. package/dist/core/phase.js.map +0 -1
  98. package/dist/core/roadmap.d.ts +0 -10
  99. package/dist/core/roadmap.d.ts.map +0 -1
  100. package/dist/core/roadmap.js +0 -165
  101. package/dist/core/roadmap.js.map +0 -1
  102. package/dist/core/skills.d.ts +0 -20
  103. package/dist/core/skills.d.ts.map +0 -1
  104. package/dist/core/skills.js +0 -144
  105. package/dist/core/skills.js.map +0 -1
  106. package/dist/core/start.d.ts +0 -15
  107. package/dist/core/start.d.ts.map +0 -1
  108. package/dist/core/start.js +0 -80
  109. package/dist/core/start.js.map +0 -1
  110. package/dist/core/state.d.ts +0 -32
  111. package/dist/core/state.d.ts.map +0 -1
  112. package/dist/core/state.js +0 -582
  113. package/dist/core/state.js.map +0 -1
  114. package/dist/core/template.d.ts +0 -30
  115. package/dist/core/template.d.ts.map +0 -1
  116. package/dist/core/template.js +0 -223
  117. package/dist/core/template.js.map +0 -1
  118. package/dist/core/types.d.ts +0 -519
  119. package/dist/core/types.d.ts.map +0 -1
  120. package/dist/core/types.js +0 -60
  121. package/dist/core/types.js.map +0 -1
  122. package/dist/core/verify.d.ts +0 -128
  123. package/dist/core/verify.d.ts.map +0 -1
  124. package/dist/core/verify.js +0 -754
  125. package/dist/core/verify.js.map +0 -1
  126. package/dist/core-RRjCSt0G.cjs.map +0 -1
  127. package/dist/esm-iIOBzmdz.cjs +0 -1561
  128. package/dist/esm-iIOBzmdz.cjs.map +0 -1
  129. package/dist/hooks/index.d.ts +0 -11
  130. package/dist/hooks/index.d.ts.map +0 -1
  131. package/dist/hooks/index.js +0 -18
  132. package/dist/hooks/index.js.map +0 -1
  133. package/dist/hooks/maxsim-check-update.d.ts +0 -17
  134. package/dist/hooks/maxsim-check-update.d.ts.map +0 -1
  135. package/dist/hooks/maxsim-check-update.js +0 -101
  136. package/dist/hooks/maxsim-check-update.js.map +0 -1
  137. package/dist/hooks/maxsim-context-monitor.d.ts +0 -21
  138. package/dist/hooks/maxsim-context-monitor.d.ts.map +0 -1
  139. package/dist/hooks/maxsim-context-monitor.js +0 -131
  140. package/dist/hooks/maxsim-context-monitor.js.map +0 -1
  141. package/dist/hooks/maxsim-statusline.d.ts +0 -19
  142. package/dist/hooks/maxsim-statusline.d.ts.map +0 -1
  143. package/dist/hooks/maxsim-statusline.js +0 -146
  144. package/dist/hooks/maxsim-statusline.js.map +0 -1
  145. package/dist/hooks/shared.d.ts +0 -11
  146. package/dist/hooks/shared.d.ts.map +0 -1
  147. package/dist/hooks/shared.js +0 -29
  148. package/dist/hooks/shared.js.map +0 -1
  149. package/dist/index.d.ts +0 -2
  150. package/dist/index.d.ts.map +0 -1
  151. package/dist/index.js +0 -3
  152. package/dist/index.js.map +0 -1
  153. package/dist/install/adapters.d.ts +0 -6
  154. package/dist/install/adapters.d.ts.map +0 -1
  155. package/dist/install/adapters.js +0 -65
  156. package/dist/install/adapters.js.map +0 -1
  157. package/dist/install/copy.d.ts +0 -6
  158. package/dist/install/copy.d.ts.map +0 -1
  159. package/dist/install/copy.js +0 -71
  160. package/dist/install/copy.js.map +0 -1
  161. package/dist/install/dashboard.d.ts +0 -16
  162. package/dist/install/dashboard.d.ts.map +0 -1
  163. package/dist/install/dashboard.js +0 -273
  164. package/dist/install/dashboard.js.map +0 -1
  165. package/dist/install/hooks.d.ts +0 -31
  166. package/dist/install/hooks.d.ts.map +0 -1
  167. package/dist/install/hooks.js +0 -260
  168. package/dist/install/hooks.js.map +0 -1
  169. package/dist/install/index.d.ts +0 -2
  170. package/dist/install/index.d.ts.map +0 -1
  171. package/dist/install/index.js +0 -534
  172. package/dist/install/index.js.map +0 -1
  173. package/dist/install/manifest.d.ts +0 -23
  174. package/dist/install/manifest.d.ts.map +0 -1
  175. package/dist/install/manifest.js +0 -133
  176. package/dist/install/manifest.js.map +0 -1
  177. package/dist/install/patches.d.ts +0 -10
  178. package/dist/install/patches.d.ts.map +0 -1
  179. package/dist/install/patches.js +0 -124
  180. package/dist/install/patches.js.map +0 -1
  181. package/dist/install/shared.d.ts +0 -56
  182. package/dist/install/shared.d.ts.map +0 -1
  183. package/dist/install/shared.js +0 -181
  184. package/dist/install/shared.js.map +0 -1
  185. package/dist/install/uninstall.d.ts +0 -5
  186. package/dist/install/uninstall.d.ts.map +0 -1
  187. package/dist/install/uninstall.js +0 -222
  188. package/dist/install/uninstall.js.map +0 -1
  189. package/dist/install/utils.d.ts +0 -27
  190. package/dist/install/utils.d.ts.map +0 -1
  191. package/dist/install/utils.js +0 -99
  192. package/dist/install/utils.js.map +0 -1
  193. package/dist/install.d.cts +0 -2
  194. package/dist/lifecycle-DxCru7rk.cjs +0 -136
  195. package/dist/lifecycle-DxCru7rk.cjs.map +0 -1
  196. package/dist/mcp/config-tools.d.ts +0 -13
  197. package/dist/mcp/config-tools.d.ts.map +0 -1
  198. package/dist/mcp/config-tools.js +0 -66
  199. package/dist/mcp/config-tools.js.map +0 -1
  200. package/dist/mcp/context-tools.d.ts +0 -13
  201. package/dist/mcp/context-tools.d.ts.map +0 -1
  202. package/dist/mcp/context-tools.js +0 -176
  203. package/dist/mcp/context-tools.js.map +0 -1
  204. package/dist/mcp/index.d.ts +0 -11
  205. package/dist/mcp/index.d.ts.map +0 -1
  206. package/dist/mcp/index.js +0 -26
  207. package/dist/mcp/index.js.map +0 -1
  208. package/dist/mcp/phase-tools.d.ts +0 -13
  209. package/dist/mcp/phase-tools.d.ts.map +0 -1
  210. package/dist/mcp/phase-tools.js +0 -177
  211. package/dist/mcp/phase-tools.js.map +0 -1
  212. package/dist/mcp/roadmap-tools.d.ts +0 -13
  213. package/dist/mcp/roadmap-tools.d.ts.map +0 -1
  214. package/dist/mcp/roadmap-tools.js +0 -79
  215. package/dist/mcp/roadmap-tools.js.map +0 -1
  216. package/dist/mcp/state-tools.d.ts +0 -13
  217. package/dist/mcp/state-tools.d.ts.map +0 -1
  218. package/dist/mcp/state-tools.js +0 -185
  219. package/dist/mcp/state-tools.js.map +0 -1
  220. package/dist/mcp/todo-tools.d.ts +0 -13
  221. package/dist/mcp/todo-tools.d.ts.map +0 -1
  222. package/dist/mcp/todo-tools.js +0 -143
  223. package/dist/mcp/todo-tools.js.map +0 -1
  224. package/dist/mcp/utils.d.ts +0 -27
  225. package/dist/mcp/utils.d.ts.map +0 -1
  226. package/dist/mcp/utils.js +0 -82
  227. package/dist/mcp/utils.js.map +0 -1
  228. package/dist/mcp-server.d.cts +0 -2
  229. package/dist/mcp-server.d.ts +0 -12
  230. package/dist/mcp-server.d.ts.map +0 -1
  231. package/dist/mcp-server.js +0 -31
  232. package/dist/mcp-server.js.map +0 -1
  233. package/dist/server-By0TN-nC.cjs +0 -2995
  234. package/dist/server-By0TN-nC.cjs.map +0 -1
@@ -1,2995 +0,0 @@
1
- #!/usr/bin/env node
2
- const require_cli = require('./cli.cjs');
3
- let node_fs = require("node:fs");
4
- node_fs = require_cli.__toESM(node_fs);
5
- let node_path = require("node:path");
6
- node_path = require_cli.__toESM(node_path);
7
- let node_os = require("node:os");
8
- node_os = require_cli.__toESM(node_os);
9
- let node_http = require("node:http");
10
- let express = require("express");
11
- express = require_cli.__toESM(express);
12
- let ws = require("ws");
13
- let _modelcontextprotocol_sdk_server_mcp_js = require("@modelcontextprotocol/sdk/server/mcp.js");
14
- let _modelcontextprotocol_sdk_server_streamableHttp_js = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
15
- let detect_port = require("detect-port");
16
- detect_port = require_cli.__toESM(detect_port);
17
- let zod = require("zod");
18
-
19
- //#region src/mcp/utils.ts
20
- /**
21
- * MCP Utilities — Shared helpers for MCP tools
22
- *
23
- * CRITICAL: Never import output() or error() from core — they call process.exit().
24
- * CRITICAL: Never write to stdout — it is reserved for MCP JSON-RPC protocol.
25
- */
26
- /**
27
- * Walk up from startDir to find a directory containing `.planning/`.
28
- * Returns the directory containing `.planning/` or null if not found.
29
- */
30
- let _cachedRoot;
31
- function detectProjectRoot(startDir) {
32
- if (startDir === void 0 && _cachedRoot !== void 0) return _cachedRoot;
33
- let dir = startDir || process.cwd();
34
- for (let i = 0; i < 100; i++) {
35
- const planningDir = node_path.default.join(dir, ".planning");
36
- try {
37
- if (node_fs.default.statSync(planningDir).isDirectory()) {
38
- if (startDir === void 0) _cachedRoot = dir;
39
- return dir;
40
- }
41
- } catch {}
42
- const parent = node_path.default.dirname(dir);
43
- if (parent === dir) {
44
- if (startDir === void 0) _cachedRoot = null;
45
- return null;
46
- }
47
- dir = parent;
48
- }
49
- if (startDir === void 0) _cachedRoot = null;
50
- return null;
51
- }
52
- /**
53
- * Return a structured MCP success response.
54
- */
55
- function mcpSuccess(data, summary) {
56
- return { content: [{
57
- type: "text",
58
- text: JSON.stringify({
59
- success: true,
60
- data,
61
- summary
62
- }, null, 2)
63
- }] };
64
- }
65
- /**
66
- * Return a structured MCP error response.
67
- */
68
- function mcpError(error, summary) {
69
- return {
70
- content: [{
71
- type: "text",
72
- text: JSON.stringify({
73
- success: false,
74
- error,
75
- summary
76
- }, null, 2)
77
- }],
78
- isError: true
79
- };
80
- }
81
-
82
- //#endregion
83
- //#region src/mcp/phase-tools.ts
84
- /**
85
- * Phase CRUD MCP Tools — Phase operations exposed as MCP tools
86
- *
87
- * CRITICAL: Never import output() or error() from core — they call process.exit().
88
- * CRITICAL: Never write to stdout — it is reserved for MCP JSON-RPC protocol.
89
- * CRITICAL: Never call process.exit() — the server must stay alive after every tool call.
90
- */
91
- /**
92
- * Register all phase CRUD tools on the MCP server.
93
- */
94
- function registerPhaseTools(server) {
95
- server.tool("mcp_find_phase", "Find a phase directory by number or name. Returns phase details including plans, summaries, and status.", { phase: zod.z.string().describe("Phase number or name (e.g. \"01\", \"1\", \"01A\", \"1.1\")") }, async ({ phase }) => {
96
- try {
97
- const cwd = detectProjectRoot();
98
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
99
- const result = require_cli.findPhaseInternal(cwd, phase);
100
- if (!result) return mcpError(`Phase ${phase} not found`, "Phase not found");
101
- return mcpSuccess({
102
- found: result.found,
103
- directory: result.directory,
104
- phase_number: result.phase_number,
105
- phase_name: result.phase_name,
106
- phase_slug: result.phase_slug,
107
- plans: result.plans,
108
- summaries: result.summaries,
109
- incomplete_plans: result.incomplete_plans,
110
- has_research: result.has_research,
111
- has_context: result.has_context,
112
- has_verification: result.has_verification,
113
- archived: result.archived ?? null
114
- }, `Found phase ${result.phase_number}: ${result.phase_name ?? "unnamed"}`);
115
- } catch (e) {
116
- return mcpError(e.message, "Operation failed");
117
- }
118
- });
119
- server.tool("mcp_list_phases", "List phase directories with pagination. Returns sorted phases with offset/limit support.", {
120
- include_archived: zod.z.boolean().optional().default(false).describe("Include archived phases from completed milestones"),
121
- offset: zod.z.number().optional().default(0).describe("Number of phases to skip (for pagination)"),
122
- limit: zod.z.number().optional().default(20).describe("Maximum number of phases to return")
123
- }, async ({ include_archived, offset, limit }) => {
124
- try {
125
- const cwd = detectProjectRoot();
126
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
127
- const phasesDir = require_cli.phasesPath(cwd);
128
- if (!node_fs.default.existsSync(phasesDir)) return mcpSuccess({
129
- directories: [],
130
- count: 0,
131
- total_count: 0,
132
- offset,
133
- limit,
134
- has_more: false
135
- }, "No phases directory found");
136
- let dirs = require_cli.listSubDirs(phasesDir);
137
- if (include_archived) {
138
- const archived = require_cli.getArchivedPhaseDirs(cwd);
139
- for (const a of archived) dirs.push(`${a.name} [${a.milestone}]`);
140
- }
141
- dirs.sort((a, b) => require_cli.comparePhaseNum(a, b));
142
- const total_count = dirs.length;
143
- const paginated = dirs.slice(offset, offset + limit);
144
- const has_more = offset + limit < total_count;
145
- return mcpSuccess({
146
- directories: paginated,
147
- count: paginated.length,
148
- total_count,
149
- offset,
150
- limit,
151
- has_more
152
- }, `Showing ${paginated.length} of ${total_count} phase(s)`);
153
- } catch (e) {
154
- return mcpError(e.message, "Operation failed");
155
- }
156
- });
157
- server.tool("mcp_create_phase", "Create a new phase. Adds the next sequential phase directory and appends to ROADMAP.md.", { name: zod.z.string().describe("Phase description/name (e.g. \"Authentication System\")") }, async ({ name }) => {
158
- try {
159
- const cwd = detectProjectRoot();
160
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
161
- if (!name || !name.trim()) return mcpError("Phase name must not be empty", "Validation failed");
162
- const result = await require_cli.phaseAddCore(cwd, name, { includeStubs: true });
163
- return mcpSuccess({
164
- phase_number: result.phase_number,
165
- padded: result.padded,
166
- name: result.description,
167
- slug: result.slug,
168
- directory: result.directory
169
- }, `Created Phase ${result.phase_number}: ${result.description}`);
170
- } catch (e) {
171
- return mcpError(e.message, "Operation failed");
172
- }
173
- });
174
- server.tool("mcp_insert_phase", "Insert a decimal phase after a specified phase (e.g. 01.1 after 01). Creates directory and updates ROADMAP.md.", {
175
- name: zod.z.string().describe("Phase description/name"),
176
- after: zod.z.string().describe("Phase number to insert after (e.g. \"01\", \"1\")")
177
- }, async ({ name, after }) => {
178
- try {
179
- const cwd = detectProjectRoot();
180
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
181
- if (!name || !name.trim()) return mcpError("Phase name must not be empty", "Validation failed");
182
- const result = await require_cli.phaseInsertCore(cwd, after, name, { includeStubs: true });
183
- return mcpSuccess({
184
- phase_number: result.phase_number,
185
- after_phase: result.after_phase,
186
- name: result.description,
187
- slug: result.slug,
188
- directory: result.directory
189
- }, `Inserted Phase ${result.phase_number}: ${result.description} after Phase ${result.after_phase}`);
190
- } catch (e) {
191
- return mcpError(e.message, "Operation failed");
192
- }
193
- });
194
- server.tool("mcp_complete_phase", "Mark a phase as complete. Updates ROADMAP.md checkbox, progress table, plan count, STATE.md, and REQUIREMENTS.md.", { phase: zod.z.string().describe("Phase number to complete (e.g. \"01\", \"1\", \"1.1\")") }, async ({ phase }) => {
195
- try {
196
- const cwd = detectProjectRoot();
197
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
198
- const result = await require_cli.phaseCompleteCore(cwd, phase);
199
- return mcpSuccess({
200
- completed_phase: result.completed_phase,
201
- phase_name: result.phase_name,
202
- plans_executed: result.plans_executed,
203
- next_phase: result.next_phase,
204
- next_phase_name: result.next_phase_name,
205
- is_last_phase: result.is_last_phase,
206
- date: result.date,
207
- roadmap_updated: result.roadmap_updated,
208
- state_updated: result.state_updated
209
- }, `Phase ${phase} marked as complete${result.next_phase ? `, next: Phase ${result.next_phase}` : ""}`);
210
- } catch (e) {
211
- return mcpError(e.message, "Operation failed");
212
- }
213
- });
214
- }
215
-
216
- //#endregion
217
- //#region src/mcp/todo-tools.ts
218
- /**
219
- * Todo CRUD MCP Tools — Todo operations exposed as MCP tools
220
- *
221
- * CRITICAL: Never import output() or error() from core — they call process.exit().
222
- * CRITICAL: Never write to stdout — it is reserved for MCP JSON-RPC protocol.
223
- * CRITICAL: Never call process.exit() — the server must stay alive after every tool call.
224
- */
225
- /**
226
- * Register all todo CRUD tools on the MCP server.
227
- */
228
- function registerTodoTools(server) {
229
- server.tool("mcp_add_todo", "Create a new todo item in .planning/todos/pending/ with frontmatter metadata.", {
230
- title: zod.z.string().describe("Title of the todo item"),
231
- description: zod.z.string().optional().describe("Optional description body"),
232
- area: zod.z.string().optional().default("general").describe("Area/category (default: general)"),
233
- phase: zod.z.string().optional().describe("Associated phase number")
234
- }, async ({ title, description, area, phase }) => {
235
- try {
236
- const cwd = detectProjectRoot();
237
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
238
- const pendingDir = require_cli.planningPath(cwd, "todos", "pending");
239
- node_fs.default.mkdirSync(pendingDir, { recursive: true });
240
- const today = require_cli.todayISO();
241
- const slug = require_cli.generateSlugInternal(title) || "untitled";
242
- const filename = `${Date.now()}-${slug}.md`;
243
- const filePath = node_path.default.join(pendingDir, filename);
244
- const content = `---\ncreated: ${today}\ntitle: ${title}\narea: ${area || "general"}\nphase: ${phase || "unassigned"}\n---\n${description || ""}\n`;
245
- node_fs.default.writeFileSync(filePath, content, "utf-8");
246
- return mcpSuccess({
247
- file: filename,
248
- path: `.planning/todos/pending/${filename}`,
249
- title,
250
- area: area || "general"
251
- }, `Todo created: ${title}`);
252
- } catch (e) {
253
- return mcpError(e.message, "Operation failed");
254
- }
255
- });
256
- server.tool("mcp_complete_todo", "Mark a pending todo as completed by moving it from pending/ to completed/ with a completion timestamp.", { todo_id: zod.z.string().describe("Filename of the todo (e.g., 1234567890-my-task.md)") }, async ({ todo_id }) => {
257
- try {
258
- const cwd = detectProjectRoot();
259
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
260
- const pendingDir = require_cli.planningPath(cwd, "todos", "pending");
261
- const completedDir = require_cli.planningPath(cwd, "todos", "completed");
262
- const sourcePath = node_path.default.join(pendingDir, todo_id);
263
- if (!node_fs.default.existsSync(sourcePath)) return mcpError(`Todo not found in pending: ${todo_id}`, "Todo not found");
264
- node_fs.default.mkdirSync(completedDir, { recursive: true });
265
- let content = node_fs.default.readFileSync(sourcePath, "utf-8");
266
- const today = require_cli.todayISO();
267
- content = `completed: ${today}\n` + content;
268
- node_fs.default.writeFileSync(node_path.default.join(completedDir, todo_id), content, "utf-8");
269
- node_fs.default.unlinkSync(sourcePath);
270
- return mcpSuccess({
271
- completed: true,
272
- file: todo_id,
273
- date: today
274
- }, `Todo completed: ${todo_id}`);
275
- } catch (e) {
276
- return mcpError(e.message, "Operation failed");
277
- }
278
- });
279
- server.tool("mcp_list_todos", "List todo items, optionally filtered by area and status (pending, completed, or all).", {
280
- area: zod.z.string().optional().describe("Filter by area/category"),
281
- status: zod.z.enum([
282
- "pending",
283
- "completed",
284
- "all"
285
- ]).optional().default("pending").describe("Which todos to list (default: pending)")
286
- }, async ({ area, status }) => {
287
- try {
288
- const cwd = detectProjectRoot();
289
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
290
- const todosBase = require_cli.planningPath(cwd, "todos");
291
- const dirs = [];
292
- if (status === "pending" || status === "all") dirs.push(node_path.default.join(todosBase, "pending"));
293
- if (status === "completed" || status === "all") dirs.push(node_path.default.join(todosBase, "completed"));
294
- const todos = [];
295
- for (const dir of dirs) {
296
- const dirStatus = dir.endsWith("pending") ? "pending" : "completed";
297
- let files = [];
298
- try {
299
- files = node_fs.default.readdirSync(dir).filter((f) => f.endsWith(".md"));
300
- } catch {
301
- continue;
302
- }
303
- for (const file of files) try {
304
- const fm = require_cli.parseTodoFrontmatter(node_fs.default.readFileSync(node_path.default.join(dir, file), "utf-8"));
305
- if (area && fm.area !== area) continue;
306
- todos.push({
307
- file,
308
- created: fm.created,
309
- title: fm.title,
310
- area: fm.area,
311
- status: dirStatus,
312
- path: `.planning/todos/${dirStatus}/${file}`
313
- });
314
- } catch {}
315
- }
316
- return mcpSuccess({
317
- count: todos.length,
318
- todos
319
- }, `${todos.length} todos found`);
320
- } catch (e) {
321
- return mcpError(e.message, "Operation failed");
322
- }
323
- });
324
- }
325
-
326
- //#endregion
327
- //#region src/mcp/state-tools.ts
328
- /**
329
- * State Management MCP Tools — STATE.md operations exposed as MCP tools
330
- *
331
- * CRITICAL: Never import output() or error() from core — they call process.exit().
332
- * CRITICAL: Never write to stdout — it is reserved for MCP JSON-RPC protocol.
333
- * CRITICAL: Never call process.exit() — the server must stay alive after every tool call.
334
- */
335
- /**
336
- * Register all state management tools on the MCP server.
337
- */
338
- function registerStateTools(server) {
339
- server.tool("mcp_get_state", "Read STATE.md content — full file, a specific **field:** value, or a ## section.", { field: zod.z.string().optional().describe("Specific field or section name, or omit for full STATE.md") }, async ({ field }) => {
340
- try {
341
- const cwd = detectProjectRoot();
342
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
343
- const stPath = require_cli.statePath(cwd);
344
- if (!node_fs.default.existsSync(stPath)) return mcpError("STATE.md not found", "STATE.md missing");
345
- const content = node_fs.default.readFileSync(stPath, "utf-8");
346
- if (!field) return mcpSuccess({ content }, "Full STATE.md retrieved");
347
- const fieldValue = require_cli.stateExtractField(content, field);
348
- if (fieldValue) return mcpSuccess({
349
- content: fieldValue,
350
- field
351
- }, `State field retrieved: ${field}`);
352
- const fieldEscaped = require_cli.escapeStringRegexp(field);
353
- const sectionPattern = new RegExp(`##\\s*${fieldEscaped}\\s*\n([\\s\\S]*?)(?=\\n##|$)`, "i");
354
- const sectionMatch = content.match(sectionPattern);
355
- if (sectionMatch) return mcpSuccess({
356
- content: sectionMatch[1].trim(),
357
- field
358
- }, `State section retrieved: ${field}`);
359
- return mcpError(`Section or field "${field}" not found in STATE.md`, "Field not found");
360
- } catch (e) {
361
- return mcpError(e.message, "Operation failed");
362
- }
363
- });
364
- server.tool("mcp_update_state", "Update a **field:** value in STATE.md (e.g., \"Status\", \"Current focus\").", {
365
- field: zod.z.string().describe("Field name (e.g., \"Status\", \"Current focus\")"),
366
- value: zod.z.string().describe("New value for the field")
367
- }, async ({ field, value }) => {
368
- try {
369
- const cwd = detectProjectRoot();
370
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
371
- const stPath = require_cli.statePath(cwd);
372
- if (!node_fs.default.existsSync(stPath)) return mcpError("STATE.md not found", "STATE.md missing");
373
- const updated = require_cli.stateReplaceField(node_fs.default.readFileSync(stPath, "utf-8"), field, value);
374
- if (!updated) return mcpError(`Field "${field}" not found in STATE.md`, "Field not found");
375
- node_fs.default.writeFileSync(stPath, updated, "utf-8");
376
- return mcpSuccess({
377
- updated: true,
378
- field,
379
- value
380
- }, `State updated: ${field}`);
381
- } catch (e) {
382
- return mcpError(e.message, "Operation failed");
383
- }
384
- });
385
- server.tool("mcp_add_decision", "Record a decision in the Decisions section of STATE.md.", {
386
- summary: zod.z.string().describe("Decision summary"),
387
- rationale: zod.z.string().optional().describe("Optional rationale"),
388
- phase: zod.z.string().optional().describe("Associated phase number")
389
- }, async ({ summary, rationale, phase }) => {
390
- try {
391
- const cwd = detectProjectRoot();
392
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
393
- const stPath = require_cli.statePath(cwd);
394
- if (!node_fs.default.existsSync(stPath)) return mcpError("STATE.md not found", "STATE.md missing");
395
- const content = node_fs.default.readFileSync(stPath, "utf-8");
396
- const entry = `- [Phase ${phase || "?"}]: ${summary}${rationale ? ` -- ${rationale}` : ""}`;
397
- const updated = require_cli.appendToStateSection(content, /(###?\s*(?:Decisions|Decisions Made|Accumulated.*Decisions)\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i, entry, [/None yet\.?\s*\n?/gi, /No decisions yet\.?\s*\n?/gi]);
398
- if (!updated) return mcpError("Decisions section not found in STATE.md", "Section not found");
399
- node_fs.default.writeFileSync(stPath, updated, "utf-8");
400
- return mcpSuccess({
401
- added: true,
402
- decision: entry
403
- }, "Decision recorded");
404
- } catch (e) {
405
- return mcpError(e.message, "Operation failed");
406
- }
407
- });
408
- server.tool("mcp_add_blocker", "Add a blocker entry to the Blockers section of STATE.md.", { text: zod.z.string().describe("Blocker description") }, async ({ text }) => {
409
- try {
410
- const cwd = detectProjectRoot();
411
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
412
- const stPath = require_cli.statePath(cwd);
413
- if (!node_fs.default.existsSync(stPath)) return mcpError("STATE.md not found", "STATE.md missing");
414
- const updated = require_cli.appendToStateSection(node_fs.default.readFileSync(stPath, "utf-8"), /(###?\s*(?:Blockers|Blockers\/Concerns|Concerns)\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i, `- ${text}`, [/None\.?\s*\n?/gi, /None yet\.?\s*\n?/gi]);
415
- if (!updated) return mcpError("Blockers section not found in STATE.md", "Section not found");
416
- node_fs.default.writeFileSync(stPath, updated, "utf-8");
417
- return mcpSuccess({
418
- added: true,
419
- blocker: text
420
- }, "Blocker added");
421
- } catch (e) {
422
- return mcpError(e.message, "Operation failed");
423
- }
424
- });
425
- server.tool("mcp_resolve_blocker", "Remove a blocker from STATE.md by matching text (case-insensitive partial match).", { text: zod.z.string().describe("Text to match against blocker entries (case-insensitive partial match)") }, async ({ text }) => {
426
- try {
427
- const cwd = detectProjectRoot();
428
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
429
- const stPath = require_cli.statePath(cwd);
430
- if (!node_fs.default.existsSync(stPath)) return mcpError("STATE.md not found", "STATE.md missing");
431
- let content = node_fs.default.readFileSync(stPath, "utf-8");
432
- const sectionPattern = /(###?\s*(?:Blockers|Blockers\/Concerns|Concerns)\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i;
433
- const match = content.match(sectionPattern);
434
- if (!match) return mcpError("Blockers section not found in STATE.md", "Section not found");
435
- let newBody = match[2].split("\n").filter((line) => {
436
- if (!line.startsWith("- ")) return true;
437
- return !line.toLowerCase().includes(text.toLowerCase());
438
- }).join("\n");
439
- if (!newBody.trim() || !newBody.includes("- ")) newBody = "None\n";
440
- content = content.replace(sectionPattern, (_match, header) => `${header}${newBody}`);
441
- node_fs.default.writeFileSync(stPath, content, "utf-8");
442
- return mcpSuccess({
443
- resolved: true,
444
- blocker: text
445
- }, "Blocker resolved");
446
- } catch (e) {
447
- return mcpError(e.message, "Operation failed");
448
- }
449
- });
450
- }
451
-
452
- //#endregion
453
- //#region src/mcp/context-tools.ts
454
- /**
455
- * Context Query MCP Tools — Project context exposed as MCP tools
456
- *
457
- * CRITICAL: Never import output() or error() from core — they call process.exit().
458
- * CRITICAL: Never write to stdout — it is reserved for MCP JSON-RPC protocol.
459
- * CRITICAL: Never call process.exit() — the server must stay alive after every tool call.
460
- */
461
- /**
462
- * Register all context query tools on the MCP server.
463
- */
464
- function registerContextTools(server) {
465
- server.tool("mcp_get_active_phase", "Get the currently active phase and next phase from roadmap analysis and STATE.md.", {}, async () => {
466
- try {
467
- const cwd = detectProjectRoot();
468
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
469
- const roadmapResult = await require_cli.cmdRoadmapAnalyze(cwd);
470
- let current_phase = null;
471
- let next_phase = null;
472
- let phase_name = null;
473
- let status = null;
474
- if (roadmapResult.ok) {
475
- const data = roadmapResult.result;
476
- current_phase = data.current_phase ?? null;
477
- next_phase = data.next_phase ?? null;
478
- }
479
- const stateContent = require_cli.safeReadFile(require_cli.planningPath(cwd, "STATE.md"));
480
- if (stateContent) {
481
- const statePhase = require_cli.stateExtractField(stateContent, "Current Phase");
482
- if (statePhase) phase_name = statePhase;
483
- const stateStatus = require_cli.stateExtractField(stateContent, "Status");
484
- if (stateStatus) status = stateStatus;
485
- }
486
- return mcpSuccess({
487
- current_phase,
488
- next_phase,
489
- phase_name,
490
- status
491
- }, `Active phase: ${phase_name ?? current_phase ?? "unknown"}`);
492
- } catch (e) {
493
- return mcpError("Failed: " + e.message, "Error occurred");
494
- }
495
- });
496
- server.tool("mcp_get_guidelines", "Get project guidelines: PROJECT.md vision, config, and optionally phase-specific context.", { phase: zod.z.string().optional().describe("Optional phase number to include phase-specific context") }, async ({ phase }) => {
497
- try {
498
- const cwd = detectProjectRoot();
499
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
500
- const project_vision = require_cli.safeReadFile(require_cli.planningPath(cwd, "PROJECT.md"));
501
- const config = require_cli.loadConfig(cwd);
502
- let phase_context = null;
503
- if (phase) {
504
- const phaseInfo = require_cli.findPhaseInternal(cwd, phase);
505
- if (phaseInfo) phase_context = require_cli.safeReadFile(node_path.default.join(phaseInfo.directory, `${phaseInfo.phase_number}-CONTEXT.md`));
506
- }
507
- return mcpSuccess({
508
- project_vision,
509
- config,
510
- phase_context
511
- }, `Guidelines loaded${phase ? ` with phase ${phase} context` : ""}`);
512
- } catch (e) {
513
- return mcpError("Failed: " + e.message, "Error occurred");
514
- }
515
- });
516
- server.tool("mcp_get_context_for_task", "Load context files for a task. Includes project context, roadmap, artefakte, and codebase docs filtered by topic. Topic keywords select relevant codebase docs: \"ui/frontend\" loads CONVENTIONS+STRUCTURE, \"api/backend\" loads ARCHITECTURE+CONVENTIONS, \"testing\" loads TESTING+CONVENTIONS, \"database\" loads ARCHITECTURE+STACK, \"refactor\" loads CONCERNS+ARCHITECTURE. Without topic, defaults to STACK+ARCHITECTURE.", {
517
- phase: zod.z.string().optional().describe("Phase number to scope context to"),
518
- topic: zod.z.string().optional().describe("Topic keywords to filter codebase docs (e.g. \"frontend\", \"api\", \"testing\", \"database\", \"refactor\")")
519
- }, async ({ phase, topic }) => {
520
- try {
521
- const cwd = detectProjectRoot();
522
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
523
- const result = require_cli.cmdContextLoad(cwd, phase, topic, true);
524
- if (!result.ok) return mcpError(result.error, "Context load failed");
525
- return mcpSuccess({ context: result.result }, `Context loaded${phase ? ` for phase ${phase}` : ""}${topic ? ` topic "${topic}"` : ""}`);
526
- } catch (e) {
527
- return mcpError("Failed: " + e.message, "Error occurred");
528
- }
529
- });
530
- server.tool("mcp_get_project_overview", "Get a high-level project overview: PROJECT.md, REQUIREMENTS.md, and STATE.md contents.", {}, async () => {
531
- try {
532
- const cwd = detectProjectRoot();
533
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
534
- return mcpSuccess({
535
- project: require_cli.safeReadFile(require_cli.planningPath(cwd, "PROJECT.md")),
536
- requirements: require_cli.safeReadFile(require_cli.planningPath(cwd, "REQUIREMENTS.md")),
537
- state: require_cli.safeReadFile(require_cli.planningPath(cwd, "STATE.md"))
538
- }, "Project overview loaded");
539
- } catch (e) {
540
- return mcpError("Failed: " + e.message, "Error occurred");
541
- }
542
- });
543
- server.tool("mcp_get_phase_detail", "Get detailed information about a specific phase including all its files (plans, summaries, context, research, verification).", { phase: zod.z.string().describe("Phase number or name (e.g. \"01\", \"1\", \"01A\")") }, async ({ phase }) => {
544
- try {
545
- const cwd = detectProjectRoot();
546
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
547
- const phaseInfo = require_cli.findPhaseInternal(cwd, phase);
548
- if (!phaseInfo) return mcpError(`Phase ${phase} not found`, "Phase not found");
549
- const files = [];
550
- try {
551
- const entries = node_fs.default.readdirSync(phaseInfo.directory);
552
- for (const entry of entries) {
553
- const fullPath = node_path.default.join(phaseInfo.directory, entry);
554
- if (node_fs.default.statSync(fullPath).isFile()) files.push({
555
- name: entry,
556
- content: require_cli.safeReadFile(fullPath)
557
- });
558
- }
559
- } catch {}
560
- return mcpSuccess({
561
- phase_number: phaseInfo.phase_number,
562
- phase_name: phaseInfo.phase_name,
563
- directory: phaseInfo.directory,
564
- files
565
- }, `Phase ${phaseInfo.phase_number} detail: ${files.length} file(s)`);
566
- } catch (e) {
567
- return mcpError("Failed: " + e.message, "Error occurred");
568
- }
569
- });
570
- }
571
-
572
- //#endregion
573
- //#region src/mcp/roadmap-tools.ts
574
- /**
575
- * Register all roadmap query tools on the MCP server.
576
- */
577
- function registerRoadmapTools(server) {
578
- server.tool("mcp_get_roadmap", "Get the full roadmap analysis including all phases, their status, and progress.", {}, async () => {
579
- try {
580
- const cwd = detectProjectRoot();
581
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
582
- const result = await require_cli.cmdRoadmapAnalyze(cwd);
583
- if (!result.ok) return mcpError(result.error, "Roadmap analysis failed");
584
- return mcpSuccess({ roadmap: result.result }, "Roadmap analysis complete");
585
- } catch (e) {
586
- return mcpError("Failed: " + e.message, "Error occurred");
587
- }
588
- });
589
- server.tool("mcp_get_roadmap_progress", "Get a focused progress summary: total phases, completed, in-progress, not started, and progress percentage.", {}, async () => {
590
- try {
591
- const cwd = detectProjectRoot();
592
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
593
- const result = await require_cli.cmdRoadmapAnalyze(cwd);
594
- if (!result.ok) return mcpError(result.error, "Roadmap analysis failed");
595
- const data = result.result;
596
- const phases = data.phases ?? [];
597
- const total_phases = phases.length;
598
- let completed = 0;
599
- let in_progress = 0;
600
- let not_started = 0;
601
- for (const p of phases) {
602
- const status = String(p.status ?? "").toLowerCase();
603
- if (status === "completed" || status === "done") completed++;
604
- else if (status === "in-progress" || status === "in_progress" || status === "active") in_progress++;
605
- else not_started++;
606
- }
607
- const progress_percent = total_phases > 0 ? Math.round(completed / total_phases * 100) : 0;
608
- return mcpSuccess({
609
- total_phases,
610
- completed,
611
- in_progress,
612
- not_started,
613
- progress_percent,
614
- current_phase: data.current_phase ?? null,
615
- next_phase: data.next_phase ?? null
616
- }, `Progress: ${completed}/${total_phases} phases complete (${progress_percent}%)`);
617
- } catch (e) {
618
- return mcpError("Failed: " + e.message, "Error occurred");
619
- }
620
- });
621
- }
622
-
623
- //#endregion
624
- //#region src/mcp/config-tools.ts
625
- /**
626
- * Config Query MCP Tools — Project configuration exposed as MCP tools
627
- *
628
- * CRITICAL: Never import output() or error() from core — they call process.exit().
629
- * CRITICAL: Never write to stdout — it is reserved for MCP JSON-RPC protocol.
630
- * CRITICAL: Never call process.exit() — the server must stay alive after every tool call.
631
- */
632
- /**
633
- * Register all config query tools on the MCP server.
634
- */
635
- function registerConfigTools(server) {
636
- server.tool("mcp_get_config", "Get project configuration. Optionally provide a key path to get a specific value.", { key: zod.z.string().optional().describe("Optional dot-separated key path (e.g. \"model_profile\", \"branching.strategy\")") }, async ({ key }) => {
637
- try {
638
- const cwd = detectProjectRoot();
639
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
640
- if (key) {
641
- const result = require_cli.cmdConfigGet(cwd, key, true);
642
- if (!result.ok) return mcpError(result.error, "Config get failed");
643
- return mcpSuccess({
644
- key,
645
- value: result.rawValue ?? result.result
646
- }, `Config value for "${key}"`);
647
- }
648
- return mcpSuccess({ config: require_cli.loadConfig(cwd) }, "Full configuration loaded");
649
- } catch (e) {
650
- return mcpError("Failed: " + e.message, "Error occurred");
651
- }
652
- });
653
- server.tool("mcp_update_config", "Update a project configuration value by key path.", {
654
- key: zod.z.string().describe("Dot-separated key path (e.g. \"model_profile\", \"branching.strategy\")"),
655
- value: zod.z.string().describe("New value to set")
656
- }, async ({ key, value }) => {
657
- try {
658
- const cwd = detectProjectRoot();
659
- if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
660
- const result = require_cli.cmdConfigSet(cwd, key, value, true);
661
- if (!result.ok) return mcpError(result.error, "Config update failed");
662
- return mcpSuccess({
663
- updated: true,
664
- key,
665
- value
666
- }, `Config "${key}" updated to "${value}"`);
667
- } catch (e) {
668
- return mcpError("Failed: " + e.message, "Error occurred");
669
- }
670
- });
671
- }
672
-
673
- //#endregion
674
- //#region src/mcp/index.ts
675
- /**
676
- * Register all MCP tools on the given server instance.
677
- */
678
- function registerAllTools(server) {
679
- registerPhaseTools(server);
680
- registerTodoTools(server);
681
- registerStateTools(server);
682
- registerContextTools(server);
683
- registerRoadmapTools(server);
684
- registerConfigTools(server);
685
- }
686
-
687
- //#endregion
688
- //#region ../../node_modules/node-pty/lib/utils.js
689
- var require_utils = /* @__PURE__ */ require_cli.__commonJSMin(((exports) => {
690
- /**
691
- * Copyright (c) 2017, Daniel Imms (MIT License).
692
- * Copyright (c) 2018, Microsoft Corporation (MIT License).
693
- */
694
- Object.defineProperty(exports, "__esModule", { value: true });
695
- exports.loadNativeModule = exports.assign = void 0;
696
- function assign(target) {
697
- var sources = [];
698
- for (var _i = 1; _i < arguments.length; _i++) sources[_i - 1] = arguments[_i];
699
- sources.forEach(function(source) {
700
- return Object.keys(source).forEach(function(key) {
701
- return target[key] = source[key];
702
- });
703
- });
704
- return target;
705
- }
706
- exports.assign = assign;
707
- function loadNativeModule(name) {
708
- var dirs = [
709
- "build/Release",
710
- "build/Debug",
711
- "prebuilds/" + process.platform + "-" + process.arch
712
- ];
713
- var relative = ["..", "."];
714
- var lastError;
715
- for (var _i = 0, dirs_1 = dirs; _i < dirs_1.length; _i++) {
716
- var d = dirs_1[_i];
717
- for (var _a = 0, relative_1 = relative; _a < relative_1.length; _a++) {
718
- var dir = relative_1[_a] + "/" + d + "/";
719
- try {
720
- return {
721
- dir,
722
- module: require(dir + "/" + name + ".node")
723
- };
724
- } catch (e) {
725
- lastError = e;
726
- }
727
- }
728
- }
729
- throw new Error("Failed to load native module: " + name + ".node, checked: " + dirs.join(", ") + ": " + lastError);
730
- }
731
- exports.loadNativeModule = loadNativeModule;
732
- }));
733
-
734
- //#endregion
735
- //#region ../../node_modules/node-pty/lib/eventEmitter2.js
736
- var require_eventEmitter2 = /* @__PURE__ */ require_cli.__commonJSMin(((exports) => {
737
- /**
738
- * Copyright (c) 2019, Microsoft Corporation (MIT License).
739
- */
740
- Object.defineProperty(exports, "__esModule", { value: true });
741
- exports.EventEmitter2 = void 0;
742
- var EventEmitter2 = function() {
743
- function EventEmitter2() {
744
- this._listeners = [];
745
- }
746
- Object.defineProperty(EventEmitter2.prototype, "event", {
747
- get: function() {
748
- var _this = this;
749
- if (!this._event) this._event = function(listener) {
750
- _this._listeners.push(listener);
751
- return { dispose: function() {
752
- for (var i = 0; i < _this._listeners.length; i++) if (_this._listeners[i] === listener) {
753
- _this._listeners.splice(i, 1);
754
- return;
755
- }
756
- } };
757
- };
758
- return this._event;
759
- },
760
- enumerable: false,
761
- configurable: true
762
- });
763
- EventEmitter2.prototype.fire = function(data) {
764
- var queue = [];
765
- for (var i = 0; i < this._listeners.length; i++) queue.push(this._listeners[i]);
766
- for (var i = 0; i < queue.length; i++) queue[i].call(void 0, data);
767
- };
768
- return EventEmitter2;
769
- }();
770
- exports.EventEmitter2 = EventEmitter2;
771
- }));
772
-
773
- //#endregion
774
- //#region ../../node_modules/node-pty/lib/terminal.js
775
- var require_terminal = /* @__PURE__ */ require_cli.__commonJSMin(((exports) => {
776
- /**
777
- * Copyright (c) 2012-2015, Christopher Jeffrey (MIT License)
778
- * Copyright (c) 2016, Daniel Imms (MIT License).
779
- * Copyright (c) 2018, Microsoft Corporation (MIT License).
780
- */
781
- Object.defineProperty(exports, "__esModule", { value: true });
782
- exports.Terminal = exports.DEFAULT_ROWS = exports.DEFAULT_COLS = void 0;
783
- var events_1 = require("events");
784
- var eventEmitter2_1 = require_eventEmitter2();
785
- exports.DEFAULT_COLS = 80;
786
- exports.DEFAULT_ROWS = 24;
787
- /**
788
- * Default messages to indicate PAUSE/RESUME for automatic flow control.
789
- * To avoid conflicts with rebound XON/XOFF control codes (such as on-my-zsh),
790
- * the sequences can be customized in `IPtyForkOptions`.
791
- */
792
- var FLOW_CONTROL_PAUSE = "";
793
- var FLOW_CONTROL_RESUME = "";
794
- var Terminal = function() {
795
- function Terminal(opt) {
796
- this._pid = 0;
797
- this._fd = 0;
798
- this._cols = 0;
799
- this._rows = 0;
800
- this._readable = false;
801
- this._writable = false;
802
- this._onData = new eventEmitter2_1.EventEmitter2();
803
- this._onExit = new eventEmitter2_1.EventEmitter2();
804
- this._internalee = new events_1.EventEmitter();
805
- this.handleFlowControl = !!(opt === null || opt === void 0 ? void 0 : opt.handleFlowControl);
806
- this._flowControlPause = (opt === null || opt === void 0 ? void 0 : opt.flowControlPause) || FLOW_CONTROL_PAUSE;
807
- this._flowControlResume = (opt === null || opt === void 0 ? void 0 : opt.flowControlResume) || FLOW_CONTROL_RESUME;
808
- if (!opt) return;
809
- this._checkType("name", opt.name ? opt.name : void 0, "string");
810
- this._checkType("cols", opt.cols ? opt.cols : void 0, "number");
811
- this._checkType("rows", opt.rows ? opt.rows : void 0, "number");
812
- this._checkType("cwd", opt.cwd ? opt.cwd : void 0, "string");
813
- this._checkType("env", opt.env ? opt.env : void 0, "object");
814
- this._checkType("uid", opt.uid ? opt.uid : void 0, "number");
815
- this._checkType("gid", opt.gid ? opt.gid : void 0, "number");
816
- this._checkType("encoding", opt.encoding ? opt.encoding : void 0, "string");
817
- }
818
- Object.defineProperty(Terminal.prototype, "onData", {
819
- get: function() {
820
- return this._onData.event;
821
- },
822
- enumerable: false,
823
- configurable: true
824
- });
825
- Object.defineProperty(Terminal.prototype, "onExit", {
826
- get: function() {
827
- return this._onExit.event;
828
- },
829
- enumerable: false,
830
- configurable: true
831
- });
832
- Object.defineProperty(Terminal.prototype, "pid", {
833
- get: function() {
834
- return this._pid;
835
- },
836
- enumerable: false,
837
- configurable: true
838
- });
839
- Object.defineProperty(Terminal.prototype, "cols", {
840
- get: function() {
841
- return this._cols;
842
- },
843
- enumerable: false,
844
- configurable: true
845
- });
846
- Object.defineProperty(Terminal.prototype, "rows", {
847
- get: function() {
848
- return this._rows;
849
- },
850
- enumerable: false,
851
- configurable: true
852
- });
853
- Terminal.prototype.write = function(data) {
854
- if (this.handleFlowControl) {
855
- if (data === this._flowControlPause) {
856
- this.pause();
857
- return;
858
- }
859
- if (data === this._flowControlResume) {
860
- this.resume();
861
- return;
862
- }
863
- }
864
- this._write(data);
865
- };
866
- Terminal.prototype._forwardEvents = function() {
867
- var _this = this;
868
- this.on("data", function(e) {
869
- return _this._onData.fire(e);
870
- });
871
- this.on("exit", function(exitCode, signal) {
872
- return _this._onExit.fire({
873
- exitCode,
874
- signal
875
- });
876
- });
877
- };
878
- Terminal.prototype._checkType = function(name, value, type, allowArray) {
879
- if (allowArray === void 0) allowArray = false;
880
- if (value === void 0) return;
881
- if (allowArray) {
882
- if (Array.isArray(value)) {
883
- value.forEach(function(v, i) {
884
- if (typeof v !== type) throw new Error(name + "[" + i + "] must be a " + type + " (not a " + typeof v[i] + ")");
885
- });
886
- return;
887
- }
888
- }
889
- if (typeof value !== type) throw new Error(name + " must be a " + type + " (not a " + typeof value + ")");
890
- };
891
- /** See net.Socket.end */
892
- Terminal.prototype.end = function(data) {
893
- this._socket.end(data);
894
- };
895
- /** See stream.Readable.pipe */
896
- Terminal.prototype.pipe = function(dest, options) {
897
- return this._socket.pipe(dest, options);
898
- };
899
- /** See net.Socket.pause */
900
- Terminal.prototype.pause = function() {
901
- return this._socket.pause();
902
- };
903
- /** See net.Socket.resume */
904
- Terminal.prototype.resume = function() {
905
- return this._socket.resume();
906
- };
907
- /** See net.Socket.setEncoding */
908
- Terminal.prototype.setEncoding = function(encoding) {
909
- if (this._socket._decoder) delete this._socket._decoder;
910
- if (encoding) this._socket.setEncoding(encoding);
911
- };
912
- Terminal.prototype.addListener = function(eventName, listener) {
913
- this.on(eventName, listener);
914
- };
915
- Terminal.prototype.on = function(eventName, listener) {
916
- if (eventName === "close") {
917
- this._internalee.on("close", listener);
918
- return;
919
- }
920
- this._socket.on(eventName, listener);
921
- };
922
- Terminal.prototype.emit = function(eventName) {
923
- var args = [];
924
- for (var _i = 1; _i < arguments.length; _i++) args[_i - 1] = arguments[_i];
925
- if (eventName === "close") return this._internalee.emit.apply(this._internalee, arguments);
926
- return this._socket.emit.apply(this._socket, arguments);
927
- };
928
- Terminal.prototype.listeners = function(eventName) {
929
- return this._socket.listeners(eventName);
930
- };
931
- Terminal.prototype.removeListener = function(eventName, listener) {
932
- this._socket.removeListener(eventName, listener);
933
- };
934
- Terminal.prototype.removeAllListeners = function(eventName) {
935
- this._socket.removeAllListeners(eventName);
936
- };
937
- Terminal.prototype.once = function(eventName, listener) {
938
- this._socket.once(eventName, listener);
939
- };
940
- Terminal.prototype._close = function() {
941
- this._socket.readable = false;
942
- this.write = function() {};
943
- this.end = function() {};
944
- this._writable = false;
945
- this._readable = false;
946
- };
947
- Terminal.prototype._parseEnv = function(env) {
948
- var keys = Object.keys(env || {});
949
- var pairs = [];
950
- for (var i = 0; i < keys.length; i++) {
951
- if (keys[i] === void 0) continue;
952
- pairs.push(keys[i] + "=" + env[keys[i]]);
953
- }
954
- return pairs;
955
- };
956
- return Terminal;
957
- }();
958
- exports.Terminal = Terminal;
959
- }));
960
-
961
- //#endregion
962
- //#region ../../node_modules/node-pty/lib/shared/conout.js
963
- var require_conout = /* @__PURE__ */ require_cli.__commonJSMin(((exports) => {
964
- /**
965
- * Copyright (c) 2020, Microsoft Corporation (MIT License).
966
- */
967
- Object.defineProperty(exports, "__esModule", { value: true });
968
- exports.getWorkerPipeName = void 0;
969
- function getWorkerPipeName(conoutPipeName) {
970
- return conoutPipeName + "-worker";
971
- }
972
- exports.getWorkerPipeName = getWorkerPipeName;
973
- }));
974
-
975
- //#endregion
976
- //#region ../../node_modules/node-pty/lib/windowsConoutConnection.js
977
- var require_windowsConoutConnection = /* @__PURE__ */ require_cli.__commonJSMin(((exports) => {
978
- /**
979
- * Copyright (c) 2020, Microsoft Corporation (MIT License).
980
- */
981
- var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
982
- function adopt(value) {
983
- return value instanceof P ? value : new P(function(resolve) {
984
- resolve(value);
985
- });
986
- }
987
- return new (P || (P = Promise))(function(resolve, reject) {
988
- function fulfilled(value) {
989
- try {
990
- step(generator.next(value));
991
- } catch (e) {
992
- reject(e);
993
- }
994
- }
995
- function rejected(value) {
996
- try {
997
- step(generator["throw"](value));
998
- } catch (e) {
999
- reject(e);
1000
- }
1001
- }
1002
- function step(result) {
1003
- result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
1004
- }
1005
- step((generator = generator.apply(thisArg, _arguments || [])).next());
1006
- });
1007
- };
1008
- var __generator = exports && exports.__generator || function(thisArg, body) {
1009
- var _ = {
1010
- label: 0,
1011
- sent: function() {
1012
- if (t[0] & 1) throw t[1];
1013
- return t[1];
1014
- },
1015
- trys: [],
1016
- ops: []
1017
- }, f, y, t, g;
1018
- return g = {
1019
- next: verb(0),
1020
- "throw": verb(1),
1021
- "return": verb(2)
1022
- }, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
1023
- return this;
1024
- }), g;
1025
- function verb(n) {
1026
- return function(v) {
1027
- return step([n, v]);
1028
- };
1029
- }
1030
- function step(op) {
1031
- if (f) throw new TypeError("Generator is already executing.");
1032
- while (_) try {
1033
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
1034
- if (y = 0, t) op = [op[0] & 2, t.value];
1035
- switch (op[0]) {
1036
- case 0:
1037
- case 1:
1038
- t = op;
1039
- break;
1040
- case 4:
1041
- _.label++;
1042
- return {
1043
- value: op[1],
1044
- done: false
1045
- };
1046
- case 5:
1047
- _.label++;
1048
- y = op[1];
1049
- op = [0];
1050
- continue;
1051
- case 7:
1052
- op = _.ops.pop();
1053
- _.trys.pop();
1054
- continue;
1055
- default:
1056
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
1057
- _ = 0;
1058
- continue;
1059
- }
1060
- if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
1061
- _.label = op[1];
1062
- break;
1063
- }
1064
- if (op[0] === 6 && _.label < t[1]) {
1065
- _.label = t[1];
1066
- t = op;
1067
- break;
1068
- }
1069
- if (t && _.label < t[2]) {
1070
- _.label = t[2];
1071
- _.ops.push(op);
1072
- break;
1073
- }
1074
- if (t[2]) _.ops.pop();
1075
- _.trys.pop();
1076
- continue;
1077
- }
1078
- op = body.call(thisArg, _);
1079
- } catch (e) {
1080
- op = [6, e];
1081
- y = 0;
1082
- } finally {
1083
- f = t = 0;
1084
- }
1085
- if (op[0] & 5) throw op[1];
1086
- return {
1087
- value: op[0] ? op[1] : void 0,
1088
- done: true
1089
- };
1090
- }
1091
- };
1092
- Object.defineProperty(exports, "__esModule", { value: true });
1093
- exports.ConoutConnection = void 0;
1094
- var worker_threads_1 = require("worker_threads");
1095
- var conout_1 = require_conout();
1096
- var path_1 = require("path");
1097
- var eventEmitter2_1 = require_eventEmitter2();
1098
- /**
1099
- * The amount of time to wait for additional data after the conpty shell process has exited before
1100
- * shutting down the worker and sockets. The timer will be reset if a new data event comes in after
1101
- * the timer has started.
1102
- */
1103
- var FLUSH_DATA_INTERVAL = 1e3;
1104
- /**
1105
- * Connects to and manages the lifecycle of the conout socket. This socket must be drained on
1106
- * another thread in order to avoid deadlocks where Conpty waits for the out socket to drain
1107
- * when `ClosePseudoConsole` is called. This happens when data is being written to the terminal when
1108
- * the pty is closed.
1109
- *
1110
- * See also:
1111
- * - https://github.com/microsoft/node-pty/issues/375
1112
- * - https://github.com/microsoft/vscode/issues/76548
1113
- * - https://github.com/microsoft/terminal/issues/1810
1114
- * - https://docs.microsoft.com/en-us/windows/console/closepseudoconsole
1115
- */
1116
- var ConoutConnection = function() {
1117
- function ConoutConnection(_conoutPipeName, _useConptyDll) {
1118
- var _this = this;
1119
- this._conoutPipeName = _conoutPipeName;
1120
- this._useConptyDll = _useConptyDll;
1121
- this._isDisposed = false;
1122
- this._onReady = new eventEmitter2_1.EventEmitter2();
1123
- var workerData = { conoutPipeName: _conoutPipeName };
1124
- var scriptPath = __dirname.replace("node_modules.asar", "node_modules.asar.unpacked");
1125
- this._worker = new worker_threads_1.Worker(path_1.join(scriptPath, "worker/conoutSocketWorker.js"), { workerData });
1126
- this._worker.on("message", function(message) {
1127
- switch (message) {
1128
- case 1:
1129
- _this._onReady.fire();
1130
- return;
1131
- default: console.warn("Unexpected ConoutWorkerMessage", message);
1132
- }
1133
- });
1134
- }
1135
- Object.defineProperty(ConoutConnection.prototype, "onReady", {
1136
- get: function() {
1137
- return this._onReady.event;
1138
- },
1139
- enumerable: false,
1140
- configurable: true
1141
- });
1142
- ConoutConnection.prototype.dispose = function() {
1143
- if (!this._useConptyDll && this._isDisposed) return;
1144
- this._isDisposed = true;
1145
- this._drainDataAndClose();
1146
- };
1147
- ConoutConnection.prototype.connectSocket = function(socket) {
1148
- socket.connect(conout_1.getWorkerPipeName(this._conoutPipeName));
1149
- };
1150
- ConoutConnection.prototype._drainDataAndClose = function() {
1151
- var _this = this;
1152
- if (this._drainTimeout) clearTimeout(this._drainTimeout);
1153
- this._drainTimeout = setTimeout(function() {
1154
- return _this._destroySocket();
1155
- }, FLUSH_DATA_INTERVAL);
1156
- };
1157
- ConoutConnection.prototype._destroySocket = function() {
1158
- return __awaiter(this, void 0, void 0, function() {
1159
- return __generator(this, function(_a) {
1160
- switch (_a.label) {
1161
- case 0: return [4, this._worker.terminate()];
1162
- case 1:
1163
- _a.sent();
1164
- return [2];
1165
- }
1166
- });
1167
- });
1168
- };
1169
- return ConoutConnection;
1170
- }();
1171
- exports.ConoutConnection = ConoutConnection;
1172
- }));
1173
-
1174
- //#endregion
1175
- //#region ../../node_modules/node-pty/lib/windowsPtyAgent.js
1176
- var require_windowsPtyAgent = /* @__PURE__ */ require_cli.__commonJSMin(((exports) => {
1177
- /**
1178
- * Copyright (c) 2012-2015, Christopher Jeffrey, Peter Sunde (MIT License)
1179
- * Copyright (c) 2016, Daniel Imms (MIT License).
1180
- * Copyright (c) 2018, Microsoft Corporation (MIT License).
1181
- */
1182
- Object.defineProperty(exports, "__esModule", { value: true });
1183
- exports.argsToCommandLine = exports.WindowsPtyAgent = void 0;
1184
- var fs$1 = require("fs");
1185
- var os = require("os");
1186
- var path$1 = require("path");
1187
- var child_process_1 = require("child_process");
1188
- var net_1 = require("net");
1189
- var windowsConoutConnection_1 = require_windowsConoutConnection();
1190
- var utils_1 = require_utils();
1191
- var conptyNative;
1192
- var winptyNative;
1193
- /**
1194
- * The amount of time to wait for additional data after the conpty shell process has exited before
1195
- * shutting down the socket. The timer will be reset if a new data event comes in after the timer
1196
- * has started.
1197
- */
1198
- var FLUSH_DATA_INTERVAL = 1e3;
1199
- /**
1200
- * This agent sits between the WindowsTerminal class and provides a common interface for both conpty
1201
- * and winpty.
1202
- */
1203
- var WindowsPtyAgent = function() {
1204
- function WindowsPtyAgent(file, args, env, cwd, cols, rows, debug, _useConpty, _useConptyDll, conptyInheritCursor) {
1205
- var _this = this;
1206
- if (_useConptyDll === void 0) _useConptyDll = false;
1207
- if (conptyInheritCursor === void 0) conptyInheritCursor = false;
1208
- this._useConpty = _useConpty;
1209
- this._useConptyDll = _useConptyDll;
1210
- this._pid = 0;
1211
- this._innerPid = 0;
1212
- if (this._useConpty === void 0 || this._useConpty === true) this._useConpty = this._getWindowsBuildNumber() >= 18309;
1213
- if (this._useConpty) {
1214
- if (!conptyNative) conptyNative = utils_1.loadNativeModule("conpty").module;
1215
- } else if (!winptyNative) winptyNative = utils_1.loadNativeModule("pty").module;
1216
- this._ptyNative = this._useConpty ? conptyNative : winptyNative;
1217
- cwd = path$1.resolve(cwd);
1218
- var commandLine = argsToCommandLine(file, args);
1219
- var term;
1220
- if (this._useConpty) term = this._ptyNative.startProcess(file, cols, rows, debug, this._generatePipeName(), conptyInheritCursor, this._useConptyDll);
1221
- else {
1222
- term = this._ptyNative.startProcess(file, commandLine, env, cwd, cols, rows, debug);
1223
- this._pid = term.pid;
1224
- this._innerPid = term.innerPid;
1225
- }
1226
- this._fd = term.fd;
1227
- this._pty = term.pty;
1228
- this._outSocket = new net_1.Socket();
1229
- this._outSocket.setEncoding("utf8");
1230
- this._conoutSocketWorker = new windowsConoutConnection_1.ConoutConnection(term.conout, this._useConptyDll);
1231
- this._conoutSocketWorker.onReady(function() {
1232
- _this._conoutSocketWorker.connectSocket(_this._outSocket);
1233
- });
1234
- this._outSocket.on("connect", function() {
1235
- _this._outSocket.emit("ready_datapipe");
1236
- });
1237
- var inSocketFD = fs$1.openSync(term.conin, "w");
1238
- this._inSocket = new net_1.Socket({
1239
- fd: inSocketFD,
1240
- readable: false,
1241
- writable: true
1242
- });
1243
- this._inSocket.setEncoding("utf8");
1244
- if (this._useConpty) this._innerPid = this._ptyNative.connect(this._pty, commandLine, cwd, env, this._useConptyDll, function(c) {
1245
- return _this._$onProcessExit(c);
1246
- }).pid;
1247
- }
1248
- Object.defineProperty(WindowsPtyAgent.prototype, "inSocket", {
1249
- get: function() {
1250
- return this._inSocket;
1251
- },
1252
- enumerable: false,
1253
- configurable: true
1254
- });
1255
- Object.defineProperty(WindowsPtyAgent.prototype, "outSocket", {
1256
- get: function() {
1257
- return this._outSocket;
1258
- },
1259
- enumerable: false,
1260
- configurable: true
1261
- });
1262
- Object.defineProperty(WindowsPtyAgent.prototype, "fd", {
1263
- get: function() {
1264
- return this._fd;
1265
- },
1266
- enumerable: false,
1267
- configurable: true
1268
- });
1269
- Object.defineProperty(WindowsPtyAgent.prototype, "innerPid", {
1270
- get: function() {
1271
- return this._innerPid;
1272
- },
1273
- enumerable: false,
1274
- configurable: true
1275
- });
1276
- Object.defineProperty(WindowsPtyAgent.prototype, "pty", {
1277
- get: function() {
1278
- return this._pty;
1279
- },
1280
- enumerable: false,
1281
- configurable: true
1282
- });
1283
- WindowsPtyAgent.prototype.resize = function(cols, rows) {
1284
- if (this._useConpty) {
1285
- if (this._exitCode !== void 0) throw new Error("Cannot resize a pty that has already exited");
1286
- this._ptyNative.resize(this._pty, cols, rows, this._useConptyDll);
1287
- return;
1288
- }
1289
- this._ptyNative.resize(this._pid, cols, rows);
1290
- };
1291
- WindowsPtyAgent.prototype.clear = function() {
1292
- if (this._useConpty) this._ptyNative.clear(this._pty, this._useConptyDll);
1293
- };
1294
- WindowsPtyAgent.prototype.kill = function() {
1295
- var _this = this;
1296
- if (this._useConpty) if (!this._useConptyDll) {
1297
- this._inSocket.readable = false;
1298
- this._outSocket.readable = false;
1299
- this._getConsoleProcessList().then(function(consoleProcessList) {
1300
- consoleProcessList.forEach(function(pid) {
1301
- try {
1302
- process.kill(pid);
1303
- } catch (e) {}
1304
- });
1305
- });
1306
- this._ptyNative.kill(this._pty, this._useConptyDll);
1307
- this._conoutSocketWorker.dispose();
1308
- } else {
1309
- this._inSocket.destroy();
1310
- this._ptyNative.kill(this._pty, this._useConptyDll);
1311
- this._outSocket.on("data", function() {
1312
- _this._conoutSocketWorker.dispose();
1313
- });
1314
- }
1315
- else {
1316
- var processList = this._ptyNative.getProcessList(this._pid);
1317
- this._ptyNative.kill(this._pid, this._innerPid);
1318
- processList.forEach(function(pid) {
1319
- try {
1320
- process.kill(pid);
1321
- } catch (e) {}
1322
- });
1323
- }
1324
- };
1325
- WindowsPtyAgent.prototype._getConsoleProcessList = function() {
1326
- var _this = this;
1327
- return new Promise(function(resolve) {
1328
- var agent = child_process_1.fork(path$1.join(__dirname, "conpty_console_list_agent"), [_this._innerPid.toString()]);
1329
- agent.on("message", function(message) {
1330
- clearTimeout(timeout);
1331
- resolve(message.consoleProcessList);
1332
- });
1333
- var timeout = setTimeout(function() {
1334
- agent.kill();
1335
- resolve([_this._innerPid]);
1336
- }, 5e3);
1337
- });
1338
- };
1339
- Object.defineProperty(WindowsPtyAgent.prototype, "exitCode", {
1340
- get: function() {
1341
- if (this._useConpty) return this._exitCode;
1342
- var winptyExitCode = this._ptyNative.getExitCode(this._innerPid);
1343
- return winptyExitCode === -1 ? void 0 : winptyExitCode;
1344
- },
1345
- enumerable: false,
1346
- configurable: true
1347
- });
1348
- WindowsPtyAgent.prototype._getWindowsBuildNumber = function() {
1349
- var osVersion = /(\d+)\.(\d+)\.(\d+)/g.exec(os.release());
1350
- var buildNumber = 0;
1351
- if (osVersion && osVersion.length === 4) buildNumber = parseInt(osVersion[3]);
1352
- return buildNumber;
1353
- };
1354
- WindowsPtyAgent.prototype._generatePipeName = function() {
1355
- return "conpty-" + Math.random() * 1e7;
1356
- };
1357
- /**
1358
- * Triggered from the native side when a contpy process exits.
1359
- */
1360
- WindowsPtyAgent.prototype._$onProcessExit = function(exitCode) {
1361
- var _this = this;
1362
- this._exitCode = exitCode;
1363
- if (!this._useConptyDll) {
1364
- this._flushDataAndCleanUp();
1365
- this._outSocket.on("data", function() {
1366
- return _this._flushDataAndCleanUp();
1367
- });
1368
- }
1369
- };
1370
- WindowsPtyAgent.prototype._flushDataAndCleanUp = function() {
1371
- var _this = this;
1372
- if (this._useConptyDll) return;
1373
- if (this._closeTimeout) clearTimeout(this._closeTimeout);
1374
- this._closeTimeout = setTimeout(function() {
1375
- return _this._cleanUpProcess();
1376
- }, FLUSH_DATA_INTERVAL);
1377
- };
1378
- WindowsPtyAgent.prototype._cleanUpProcess = function() {
1379
- if (this._useConptyDll) return;
1380
- this._inSocket.readable = false;
1381
- this._outSocket.readable = false;
1382
- this._outSocket.destroy();
1383
- };
1384
- return WindowsPtyAgent;
1385
- }();
1386
- exports.WindowsPtyAgent = WindowsPtyAgent;
1387
- function argsToCommandLine(file, args) {
1388
- if (isCommandLine(args)) {
1389
- if (args.length === 0) return file;
1390
- return argsToCommandLine(file, []) + " " + args;
1391
- }
1392
- var argv = [file];
1393
- Array.prototype.push.apply(argv, args);
1394
- var result = "";
1395
- for (var argIndex = 0; argIndex < argv.length; argIndex++) {
1396
- if (argIndex > 0) result += " ";
1397
- var arg = argv[argIndex];
1398
- var hasLopsidedEnclosingQuote = xOr(arg[0] !== "\"", arg[arg.length - 1] !== "\"");
1399
- var hasNoEnclosingQuotes = arg[0] !== "\"" && arg[arg.length - 1] !== "\"";
1400
- var quote = arg === "" || (arg.indexOf(" ") !== -1 || arg.indexOf(" ") !== -1) && arg.length > 1 && (hasLopsidedEnclosingQuote || hasNoEnclosingQuotes);
1401
- if (quote) result += "\"";
1402
- var bsCount = 0;
1403
- for (var i = 0; i < arg.length; i++) {
1404
- var p = arg[i];
1405
- if (p === "\\") bsCount++;
1406
- else if (p === "\"") {
1407
- result += repeatText("\\", bsCount * 2 + 1);
1408
- result += "\"";
1409
- bsCount = 0;
1410
- } else {
1411
- result += repeatText("\\", bsCount);
1412
- bsCount = 0;
1413
- result += p;
1414
- }
1415
- }
1416
- if (quote) {
1417
- result += repeatText("\\", bsCount * 2);
1418
- result += "\"";
1419
- } else result += repeatText("\\", bsCount);
1420
- }
1421
- return result;
1422
- }
1423
- exports.argsToCommandLine = argsToCommandLine;
1424
- function isCommandLine(args) {
1425
- return typeof args === "string";
1426
- }
1427
- function repeatText(text, count) {
1428
- var result = "";
1429
- for (var i = 0; i < count; i++) result += text;
1430
- return result;
1431
- }
1432
- function xOr(arg1, arg2) {
1433
- return arg1 && !arg2 || !arg1 && arg2;
1434
- }
1435
- }));
1436
-
1437
- //#endregion
1438
- //#region ../../node_modules/node-pty/lib/windowsTerminal.js
1439
- var require_windowsTerminal = /* @__PURE__ */ require_cli.__commonJSMin(((exports) => {
1440
- /**
1441
- * Copyright (c) 2012-2015, Christopher Jeffrey, Peter Sunde (MIT License)
1442
- * Copyright (c) 2016, Daniel Imms (MIT License).
1443
- * Copyright (c) 2018, Microsoft Corporation (MIT License).
1444
- */
1445
- var __extends = exports && exports.__extends || (function() {
1446
- var extendStatics = function(d, b) {
1447
- extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d, b) {
1448
- d.__proto__ = b;
1449
- } || function(d, b) {
1450
- for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
1451
- };
1452
- return extendStatics(d, b);
1453
- };
1454
- return function(d, b) {
1455
- extendStatics(d, b);
1456
- function __() {
1457
- this.constructor = d;
1458
- }
1459
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
1460
- };
1461
- })();
1462
- Object.defineProperty(exports, "__esModule", { value: true });
1463
- exports.WindowsTerminal = void 0;
1464
- var terminal_1 = require_terminal();
1465
- var windowsPtyAgent_1 = require_windowsPtyAgent();
1466
- var utils_1 = require_utils();
1467
- var DEFAULT_FILE = "cmd.exe";
1468
- var DEFAULT_NAME = "Windows Shell";
1469
- var WindowsTerminal = function(_super) {
1470
- __extends(WindowsTerminal, _super);
1471
- function WindowsTerminal(file, args, opt) {
1472
- var _this = _super.call(this, opt) || this;
1473
- _this._checkType("args", args, "string", true);
1474
- args = args || [];
1475
- file = file || DEFAULT_FILE;
1476
- opt = opt || {};
1477
- opt.env = opt.env || process.env;
1478
- if (opt.encoding) console.warn("Setting encoding on Windows is not supported");
1479
- var env = utils_1.assign({}, opt.env);
1480
- _this._cols = opt.cols || terminal_1.DEFAULT_COLS;
1481
- _this._rows = opt.rows || terminal_1.DEFAULT_ROWS;
1482
- var cwd = opt.cwd || process.cwd();
1483
- var name = opt.name || env.TERM || DEFAULT_NAME;
1484
- var parsedEnv = _this._parseEnv(env);
1485
- _this._isReady = false;
1486
- _this._deferreds = [];
1487
- _this._agent = new windowsPtyAgent_1.WindowsPtyAgent(file, args, parsedEnv, cwd, _this._cols, _this._rows, false, opt.useConpty, opt.useConptyDll, opt.conptyInheritCursor);
1488
- _this._socket = _this._agent.outSocket;
1489
- _this._pid = _this._agent.innerPid;
1490
- _this._fd = _this._agent.fd;
1491
- _this._pty = _this._agent.pty;
1492
- _this._socket.on("ready_datapipe", function() {
1493
- _this._socket.once("data", function() {
1494
- if (!_this._isReady) {
1495
- _this._isReady = true;
1496
- _this._deferreds.forEach(function(fn) {
1497
- fn.run();
1498
- });
1499
- _this._deferreds = [];
1500
- }
1501
- });
1502
- _this._socket.on("error", function(err) {
1503
- _this._close();
1504
- if (err.code) {
1505
- if (~err.code.indexOf("errno 5") || ~err.code.indexOf("EIO")) return;
1506
- }
1507
- if (_this.listeners("error").length < 2) throw err;
1508
- });
1509
- _this._socket.on("close", function() {
1510
- _this.emit("exit", _this._agent.exitCode);
1511
- _this._close();
1512
- });
1513
- });
1514
- _this._file = file;
1515
- _this._name = name;
1516
- _this._readable = true;
1517
- _this._writable = true;
1518
- _this._forwardEvents();
1519
- return _this;
1520
- }
1521
- WindowsTerminal.prototype._write = function(data) {
1522
- this._defer(this._doWrite, data);
1523
- };
1524
- WindowsTerminal.prototype._doWrite = function(data) {
1525
- this._agent.inSocket.write(data);
1526
- };
1527
- /**
1528
- * openpty
1529
- */
1530
- WindowsTerminal.open = function(options) {
1531
- throw new Error("open() not supported on windows, use Fork() instead.");
1532
- };
1533
- /**
1534
- * TTY
1535
- */
1536
- WindowsTerminal.prototype.resize = function(cols, rows) {
1537
- var _this = this;
1538
- if (cols <= 0 || rows <= 0 || isNaN(cols) || isNaN(rows) || cols === Infinity || rows === Infinity) throw new Error("resizing must be done using positive cols and rows");
1539
- this._deferNoArgs(function() {
1540
- _this._agent.resize(cols, rows);
1541
- _this._cols = cols;
1542
- _this._rows = rows;
1543
- });
1544
- };
1545
- WindowsTerminal.prototype.clear = function() {
1546
- var _this = this;
1547
- this._deferNoArgs(function() {
1548
- _this._agent.clear();
1549
- });
1550
- };
1551
- WindowsTerminal.prototype.destroy = function() {
1552
- var _this = this;
1553
- this._deferNoArgs(function() {
1554
- _this.kill();
1555
- });
1556
- };
1557
- WindowsTerminal.prototype.kill = function(signal) {
1558
- var _this = this;
1559
- this._deferNoArgs(function() {
1560
- if (signal) throw new Error("Signals not supported on windows.");
1561
- _this._close();
1562
- _this._agent.kill();
1563
- });
1564
- };
1565
- WindowsTerminal.prototype._deferNoArgs = function(deferredFn) {
1566
- var _this = this;
1567
- if (this._isReady) {
1568
- deferredFn.call(this);
1569
- return;
1570
- }
1571
- this._deferreds.push({ run: function() {
1572
- return deferredFn.call(_this);
1573
- } });
1574
- };
1575
- WindowsTerminal.prototype._defer = function(deferredFn, arg) {
1576
- var _this = this;
1577
- if (this._isReady) {
1578
- deferredFn.call(this, arg);
1579
- return;
1580
- }
1581
- this._deferreds.push({ run: function() {
1582
- return deferredFn.call(_this, arg);
1583
- } });
1584
- };
1585
- Object.defineProperty(WindowsTerminal.prototype, "process", {
1586
- get: function() {
1587
- return this._name;
1588
- },
1589
- enumerable: false,
1590
- configurable: true
1591
- });
1592
- Object.defineProperty(WindowsTerminal.prototype, "master", {
1593
- get: function() {
1594
- throw new Error("master is not supported on Windows");
1595
- },
1596
- enumerable: false,
1597
- configurable: true
1598
- });
1599
- Object.defineProperty(WindowsTerminal.prototype, "slave", {
1600
- get: function() {
1601
- throw new Error("slave is not supported on Windows");
1602
- },
1603
- enumerable: false,
1604
- configurable: true
1605
- });
1606
- return WindowsTerminal;
1607
- }(terminal_1.Terminal);
1608
- exports.WindowsTerminal = WindowsTerminal;
1609
- }));
1610
-
1611
- //#endregion
1612
- //#region ../../node_modules/node-pty/lib/unixTerminal.js
1613
- var require_unixTerminal = /* @__PURE__ */ require_cli.__commonJSMin(((exports) => {
1614
- var __extends = exports && exports.__extends || (function() {
1615
- var extendStatics = function(d, b) {
1616
- extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d, b) {
1617
- d.__proto__ = b;
1618
- } || function(d, b) {
1619
- for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
1620
- };
1621
- return extendStatics(d, b);
1622
- };
1623
- return function(d, b) {
1624
- extendStatics(d, b);
1625
- function __() {
1626
- this.constructor = d;
1627
- }
1628
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
1629
- };
1630
- })();
1631
- Object.defineProperty(exports, "__esModule", { value: true });
1632
- exports.UnixTerminal = void 0;
1633
- /**
1634
- * Copyright (c) 2012-2015, Christopher Jeffrey (MIT License)
1635
- * Copyright (c) 2016, Daniel Imms (MIT License).
1636
- * Copyright (c) 2018, Microsoft Corporation (MIT License).
1637
- */
1638
- var fs = require("fs");
1639
- var path = require("path");
1640
- var tty = require("tty");
1641
- var terminal_1 = require_terminal();
1642
- var utils_1 = require_utils();
1643
- var native = utils_1.loadNativeModule("pty");
1644
- var pty = native.module;
1645
- var helperPath = native.dir + "/spawn-helper";
1646
- helperPath = path.resolve(__dirname, helperPath);
1647
- helperPath = helperPath.replace("app.asar", "app.asar.unpacked");
1648
- helperPath = helperPath.replace("node_modules.asar", "node_modules.asar.unpacked");
1649
- var DEFAULT_FILE = "sh";
1650
- var DEFAULT_NAME = "xterm";
1651
- var DESTROY_SOCKET_TIMEOUT_MS = 200;
1652
- var UnixTerminal = function(_super) {
1653
- __extends(UnixTerminal, _super);
1654
- function UnixTerminal(file, args, opt) {
1655
- var _a, _b;
1656
- var _this = _super.call(this, opt) || this;
1657
- _this._boundClose = false;
1658
- _this._emittedClose = false;
1659
- if (typeof args === "string") throw new Error("args as a string is not supported on unix.");
1660
- args = args || [];
1661
- file = file || DEFAULT_FILE;
1662
- opt = opt || {};
1663
- opt.env = opt.env || process.env;
1664
- _this._cols = opt.cols || terminal_1.DEFAULT_COLS;
1665
- _this._rows = opt.rows || terminal_1.DEFAULT_ROWS;
1666
- var uid = (_a = opt.uid) !== null && _a !== void 0 ? _a : -1;
1667
- var gid = (_b = opt.gid) !== null && _b !== void 0 ? _b : -1;
1668
- var env = utils_1.assign({}, opt.env);
1669
- if (opt.env === process.env) _this._sanitizeEnv(env);
1670
- var cwd = opt.cwd || process.cwd();
1671
- env.PWD = cwd;
1672
- var name = opt.name || env.TERM || DEFAULT_NAME;
1673
- env.TERM = name;
1674
- var parsedEnv = _this._parseEnv(env);
1675
- var encoding = opt.encoding === void 0 ? "utf8" : opt.encoding;
1676
- var onexit = function(code, signal) {
1677
- if (!_this._emittedClose) {
1678
- if (_this._boundClose) return;
1679
- _this._boundClose = true;
1680
- var timeout_1 = setTimeout(function() {
1681
- timeout_1 = null;
1682
- _this._socket.destroy();
1683
- }, DESTROY_SOCKET_TIMEOUT_MS);
1684
- _this.once("close", function() {
1685
- if (timeout_1 !== null) clearTimeout(timeout_1);
1686
- _this.emit("exit", code, signal);
1687
- });
1688
- return;
1689
- }
1690
- _this.emit("exit", code, signal);
1691
- };
1692
- var term = pty.fork(file, args, parsedEnv, cwd, _this._cols, _this._rows, uid, gid, encoding === "utf8", helperPath, onexit);
1693
- _this._socket = new tty.ReadStream(term.fd);
1694
- if (encoding !== null) _this._socket.setEncoding(encoding);
1695
- _this._writeStream = new CustomWriteStream(term.fd, encoding || void 0);
1696
- _this._socket.on("error", function(err) {
1697
- if (err.code) {
1698
- if (~err.code.indexOf("EAGAIN")) return;
1699
- }
1700
- _this._close();
1701
- if (!_this._emittedClose) {
1702
- _this._emittedClose = true;
1703
- _this.emit("close");
1704
- }
1705
- if (err.code) {
1706
- if (~err.code.indexOf("errno 5") || ~err.code.indexOf("EIO")) return;
1707
- }
1708
- if (_this.listeners("error").length < 2) throw err;
1709
- });
1710
- _this._pid = term.pid;
1711
- _this._fd = term.fd;
1712
- _this._pty = term.pty;
1713
- _this._file = file;
1714
- _this._name = name;
1715
- _this._readable = true;
1716
- _this._writable = true;
1717
- _this._socket.on("close", function() {
1718
- if (_this._emittedClose) return;
1719
- _this._emittedClose = true;
1720
- _this._close();
1721
- _this.emit("close");
1722
- });
1723
- _this._forwardEvents();
1724
- return _this;
1725
- }
1726
- Object.defineProperty(UnixTerminal.prototype, "master", {
1727
- get: function() {
1728
- return this._master;
1729
- },
1730
- enumerable: false,
1731
- configurable: true
1732
- });
1733
- Object.defineProperty(UnixTerminal.prototype, "slave", {
1734
- get: function() {
1735
- return this._slave;
1736
- },
1737
- enumerable: false,
1738
- configurable: true
1739
- });
1740
- UnixTerminal.prototype._write = function(data) {
1741
- this._writeStream.write(data);
1742
- };
1743
- Object.defineProperty(UnixTerminal.prototype, "fd", {
1744
- get: function() {
1745
- return this._fd;
1746
- },
1747
- enumerable: false,
1748
- configurable: true
1749
- });
1750
- Object.defineProperty(UnixTerminal.prototype, "ptsName", {
1751
- get: function() {
1752
- return this._pty;
1753
- },
1754
- enumerable: false,
1755
- configurable: true
1756
- });
1757
- /**
1758
- * openpty
1759
- */
1760
- UnixTerminal.open = function(opt) {
1761
- var self = Object.create(UnixTerminal.prototype);
1762
- opt = opt || {};
1763
- if (arguments.length > 1) opt = {
1764
- cols: arguments[1],
1765
- rows: arguments[2]
1766
- };
1767
- var cols = opt.cols || terminal_1.DEFAULT_COLS;
1768
- var rows = opt.rows || terminal_1.DEFAULT_ROWS;
1769
- var encoding = opt.encoding === void 0 ? "utf8" : opt.encoding;
1770
- var term = pty.open(cols, rows);
1771
- self._master = new tty.ReadStream(term.master);
1772
- if (encoding !== null) self._master.setEncoding(encoding);
1773
- self._master.resume();
1774
- self._slave = new tty.ReadStream(term.slave);
1775
- if (encoding !== null) self._slave.setEncoding(encoding);
1776
- self._slave.resume();
1777
- self._socket = self._master;
1778
- self._pid = -1;
1779
- self._fd = term.master;
1780
- self._pty = term.pty;
1781
- self._file = process.argv[0] || "node";
1782
- self._name = process.env.TERM || "";
1783
- self._readable = true;
1784
- self._writable = true;
1785
- self._socket.on("error", function(err) {
1786
- self._close();
1787
- if (self.listeners("error").length < 2) throw err;
1788
- });
1789
- self._socket.on("close", function() {
1790
- self._close();
1791
- });
1792
- return self;
1793
- };
1794
- UnixTerminal.prototype.destroy = function() {
1795
- var _this = this;
1796
- this._close();
1797
- this._socket.once("close", function() {
1798
- _this.kill("SIGHUP");
1799
- });
1800
- this._socket.destroy();
1801
- this._writeStream.dispose();
1802
- };
1803
- UnixTerminal.prototype.kill = function(signal) {
1804
- try {
1805
- process.kill(this.pid, signal || "SIGHUP");
1806
- } catch (e) {}
1807
- };
1808
- Object.defineProperty(UnixTerminal.prototype, "process", {
1809
- get: function() {
1810
- if (process.platform === "darwin") {
1811
- var title = pty.process(this._fd);
1812
- return title !== "kernel_task" ? title : this._file;
1813
- }
1814
- return pty.process(this._fd, this._pty) || this._file;
1815
- },
1816
- enumerable: false,
1817
- configurable: true
1818
- });
1819
- /**
1820
- * TTY
1821
- */
1822
- UnixTerminal.prototype.resize = function(cols, rows) {
1823
- if (cols <= 0 || rows <= 0 || isNaN(cols) || isNaN(rows) || cols === Infinity || rows === Infinity) throw new Error("resizing must be done using positive cols and rows");
1824
- pty.resize(this._fd, cols, rows);
1825
- this._cols = cols;
1826
- this._rows = rows;
1827
- };
1828
- UnixTerminal.prototype.clear = function() {};
1829
- UnixTerminal.prototype._sanitizeEnv = function(env) {
1830
- delete env["TMUX"];
1831
- delete env["TMUX_PANE"];
1832
- delete env["STY"];
1833
- delete env["WINDOW"];
1834
- delete env["WINDOWID"];
1835
- delete env["TERMCAP"];
1836
- delete env["COLUMNS"];
1837
- delete env["LINES"];
1838
- };
1839
- return UnixTerminal;
1840
- }(terminal_1.Terminal);
1841
- exports.UnixTerminal = UnixTerminal;
1842
- /**
1843
- * A custom write stream that writes directly to a file descriptor with proper
1844
- * handling of backpressure and errors. This avoids some event loop exhaustion
1845
- * issues that can occur when using the standard APIs in Node.
1846
- */
1847
- var CustomWriteStream = function() {
1848
- function CustomWriteStream(_fd, _encoding) {
1849
- this._fd = _fd;
1850
- this._encoding = _encoding;
1851
- this._writeQueue = [];
1852
- }
1853
- CustomWriteStream.prototype.dispose = function() {
1854
- clearImmediate(this._writeImmediate);
1855
- this._writeImmediate = void 0;
1856
- };
1857
- CustomWriteStream.prototype.write = function(data) {
1858
- var buffer = typeof data === "string" ? Buffer.from(data, this._encoding) : Buffer.from(data);
1859
- if (buffer.byteLength !== 0) {
1860
- this._writeQueue.push({
1861
- buffer,
1862
- offset: 0
1863
- });
1864
- if (this._writeQueue.length === 1) this._processWriteQueue();
1865
- }
1866
- };
1867
- CustomWriteStream.prototype._processWriteQueue = function() {
1868
- var _this = this;
1869
- this._writeImmediate = void 0;
1870
- if (this._writeQueue.length === 0) return;
1871
- var task = this._writeQueue[0];
1872
- fs.write(this._fd, task.buffer, task.offset, function(err, written) {
1873
- if (err) {
1874
- if ("code" in err && err.code === "EAGAIN") _this._writeImmediate = setImmediate(function() {
1875
- return _this._processWriteQueue();
1876
- });
1877
- else {
1878
- _this._writeQueue.length = 0;
1879
- console.error("Unhandled pty write error", err);
1880
- }
1881
- return;
1882
- }
1883
- task.offset += written;
1884
- if (task.offset >= task.buffer.byteLength) _this._writeQueue.shift();
1885
- _this._processWriteQueue();
1886
- });
1887
- };
1888
- return CustomWriteStream;
1889
- }();
1890
- }));
1891
-
1892
- //#endregion
1893
- //#region ../../node_modules/node-pty/lib/index.js
1894
- var require_lib = /* @__PURE__ */ require_cli.__commonJSMin(((exports) => {
1895
- /**
1896
- * Copyright (c) 2012-2015, Christopher Jeffrey, Peter Sunde (MIT License)
1897
- * Copyright (c) 2016, Daniel Imms (MIT License).
1898
- * Copyright (c) 2018, Microsoft Corporation (MIT License).
1899
- */
1900
- Object.defineProperty(exports, "__esModule", { value: true });
1901
- exports.native = exports.open = exports.createTerminal = exports.fork = exports.spawn = void 0;
1902
- var utils_1 = require_utils();
1903
- var terminalCtor;
1904
- if (process.platform === "win32") terminalCtor = require_windowsTerminal().WindowsTerminal;
1905
- else terminalCtor = require_unixTerminal().UnixTerminal;
1906
- /**
1907
- * Forks a process as a pseudoterminal.
1908
- * @param file The file to launch.
1909
- * @param args The file's arguments as argv (string[]) or in a pre-escaped
1910
- * CommandLine format (string). Note that the CommandLine option is only
1911
- * available on Windows and is expected to be escaped properly.
1912
- * @param options The options of the terminal.
1913
- * @throws When the file passed to spawn with does not exists.
1914
- * @see CommandLineToArgvW https://msdn.microsoft.com/en-us/library/windows/desktop/bb776391(v=vs.85).aspx
1915
- * @see Parsing C++ Comamnd-Line Arguments https://msdn.microsoft.com/en-us/library/17w5ykft.aspx
1916
- * @see GetCommandLine https://msdn.microsoft.com/en-us/library/windows/desktop/ms683156.aspx
1917
- */
1918
- function spawn(file, args, opt) {
1919
- return new terminalCtor(file, args, opt);
1920
- }
1921
- exports.spawn = spawn;
1922
- /** @deprecated */
1923
- function fork(file, args, opt) {
1924
- return new terminalCtor(file, args, opt);
1925
- }
1926
- exports.fork = fork;
1927
- /** @deprecated */
1928
- function createTerminal(file, args, opt) {
1929
- return new terminalCtor(file, args, opt);
1930
- }
1931
- exports.createTerminal = createTerminal;
1932
- function open(options) {
1933
- return terminalCtor.open(options);
1934
- }
1935
- exports.open = open;
1936
- /**
1937
- * Expose the native API when not Windows, note that this is not public API and
1938
- * could be removed at any time.
1939
- */
1940
- exports.native = process.platform !== "win32" ? utils_1.loadNativeModule("pty").module : null;
1941
- }));
1942
-
1943
- //#endregion
1944
- //#region src/backend/terminal.ts
1945
- const MAX_SCROLLBACK = 5e4;
1946
- var SessionStore = class {
1947
- scrollback = [];
1948
- append(data) {
1949
- this.scrollback.push(data);
1950
- if (this.scrollback.length > MAX_SCROLLBACK * 1.5) this.scrollback = this.scrollback.slice(-MAX_SCROLLBACK);
1951
- }
1952
- getAll() {
1953
- return this.scrollback.join("");
1954
- }
1955
- clear() {
1956
- this.scrollback = [];
1957
- }
1958
- };
1959
- let pty = null;
1960
- let ptyLoadError = null;
1961
- try {
1962
- pty = require_lib();
1963
- } catch (err) {
1964
- ptyLoadError = err instanceof Error ? err.message : String(err);
1965
- }
1966
- const DISCONNECT_TIMEOUT_MS = 6e4;
1967
- const STATUS_INTERVAL_MS = 1e3;
1968
- const ACTIVE_THRESHOLD_MS = 2e3;
1969
- function ptyLog(level, ...args) {
1970
- const ts = (/* @__PURE__ */ new Date()).toISOString();
1971
- const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
1972
- console.error(`[${ts}] [${level}] [pty-manager] ${msg}`);
1973
- }
1974
- var PtyManager = class PtyManager {
1975
- static instance = null;
1976
- session = null;
1977
- connectedClients = /* @__PURE__ */ new Set();
1978
- lastOutputTime = 0;
1979
- statusInterval = null;
1980
- static getInstance() {
1981
- if (!PtyManager.instance) PtyManager.instance = new PtyManager();
1982
- return PtyManager.instance;
1983
- }
1984
- spawn(opts) {
1985
- if (!pty) {
1986
- ptyLog("ERROR", `node-pty not available: ${ptyLoadError}`);
1987
- this.broadcastToClients({
1988
- type: "output",
1989
- data: `\r\n\x1b[31mTerminal unavailable: node-pty is not installed.\r\nError: ${ptyLoadError}\r\nRun: npm install node-pty\x1b[0m\r\n`
1990
- });
1991
- return;
1992
- }
1993
- if (this.session) {
1994
- ptyLog("INFO", "Killing existing session before spawn");
1995
- this.kill();
1996
- }
1997
- const isWin = process.platform === "win32";
1998
- const shell = isWin ? "cmd.exe" : "/bin/sh";
1999
- const claudeCmd = `claude${opts.skipPermissions ? " --dangerously-skip-permissions" : ""}`;
2000
- const shellArgs = isWin ? ["/c", claudeCmd] : ["-c", claudeCmd];
2001
- ptyLog("INFO", `Spawning: shell=${shell}, args=${JSON.stringify(shellArgs)}, cwd=${opts.cwd}`);
2002
- const proc = pty.spawn(shell, shellArgs, {
2003
- name: "xterm-256color",
2004
- cols: opts.cols ?? 120,
2005
- rows: opts.rows ?? 30,
2006
- cwd: opts.cwd,
2007
- env: process.env
2008
- });
2009
- ptyLog("INFO", `Process spawned with pid=${proc.pid}`);
2010
- const store = new SessionStore();
2011
- this.session = {
2012
- process: proc,
2013
- pid: proc.pid,
2014
- startTime: Date.now(),
2015
- cwd: opts.cwd,
2016
- skipPermissions: opts.skipPermissions,
2017
- disconnectTimer: null,
2018
- store
2019
- };
2020
- this.lastOutputTime = Date.now();
2021
- proc.onData((data) => {
2022
- this.lastOutputTime = Date.now();
2023
- store.append(data);
2024
- if (this.session?.pid === proc.pid) this.broadcastToClients({
2025
- type: "output",
2026
- data
2027
- });
2028
- });
2029
- proc.onExit(({ exitCode }) => {
2030
- ptyLog("INFO", `Process exited with code=${exitCode}`);
2031
- if (this.session?.pid !== proc.pid) {
2032
- ptyLog("INFO", `Ignoring stale exit for old pid=${proc.pid}`);
2033
- return;
2034
- }
2035
- this.broadcastToClients({
2036
- type: "exit",
2037
- code: exitCode
2038
- });
2039
- this.stopStatusBroadcast();
2040
- this.session = null;
2041
- });
2042
- this.broadcastToClients({
2043
- type: "started",
2044
- pid: proc.pid
2045
- });
2046
- this.startStatusBroadcast();
2047
- }
2048
- write(data) {
2049
- if (this.session) this.session.process.write(data);
2050
- }
2051
- resize(cols, rows) {
2052
- if (this.session) this.session.process.resize(cols, rows);
2053
- }
2054
- kill() {
2055
- if (this.session) {
2056
- this.stopStatusBroadcast();
2057
- try {
2058
- this.session.process.kill();
2059
- } catch {}
2060
- if (this.session.disconnectTimer) clearTimeout(this.session.disconnectTimer);
2061
- this.session = null;
2062
- }
2063
- }
2064
- getStatus() {
2065
- if (!this.session) return null;
2066
- return {
2067
- pid: this.session.pid,
2068
- uptime: Math.floor((Date.now() - this.session.startTime) / 1e3),
2069
- cwd: this.session.cwd,
2070
- memoryMB: Math.round(process.memoryUsage().rss / 1024 / 1024 * 10) / 10,
2071
- isActive: Date.now() - this.lastOutputTime < ACTIVE_THRESHOLD_MS,
2072
- skipPermissions: this.session.skipPermissions,
2073
- alive: true
2074
- };
2075
- }
2076
- addClient(ws) {
2077
- this.connectedClients.add(ws);
2078
- if (this.session?.disconnectTimer) {
2079
- clearTimeout(this.session.disconnectTimer);
2080
- this.session.disconnectTimer = null;
2081
- }
2082
- if (this.session) {
2083
- const scrollback = this.session.store.getAll();
2084
- if (scrollback) ws.send(JSON.stringify({
2085
- type: "scrollback",
2086
- data: scrollback
2087
- }));
2088
- const status = this.getStatus();
2089
- if (status) ws.send(JSON.stringify({
2090
- type: "status",
2091
- ...status
2092
- }));
2093
- }
2094
- }
2095
- removeClient(ws) {
2096
- this.connectedClients.delete(ws);
2097
- if (this.connectedClients.size === 0 && this.session) this.session.disconnectTimer = setTimeout(() => {
2098
- console.error("[pty] No clients connected for 60s, killing process");
2099
- this.kill();
2100
- }, DISCONNECT_TIMEOUT_MS);
2101
- }
2102
- isAlive() {
2103
- return this.session !== null;
2104
- }
2105
- isAvailable() {
2106
- return pty !== null;
2107
- }
2108
- broadcastToClients(message) {
2109
- const data = JSON.stringify(message);
2110
- for (const client of this.connectedClients) if (client.readyState === 1) client.send(data);
2111
- }
2112
- startStatusBroadcast() {
2113
- this.stopStatusBroadcast();
2114
- this.statusInterval = setInterval(() => {
2115
- const status = this.getStatus();
2116
- if (status) this.broadcastToClients({
2117
- type: "status",
2118
- ...status
2119
- });
2120
- }, STATUS_INTERVAL_MS);
2121
- }
2122
- stopStatusBroadcast() {
2123
- if (this.statusInterval) {
2124
- clearInterval(this.statusInterval);
2125
- this.statusInterval = null;
2126
- }
2127
- }
2128
- };
2129
-
2130
- //#endregion
2131
- //#region src/backend/server.ts
2132
- /**
2133
- * MAXSIM Backend Server — Unified persistent backend service
2134
- *
2135
- * Consolidates HTTP API, WebSocket, MCP endpoint, terminal management,
2136
- * and file watching into a single per-project process.
2137
- *
2138
- * CRITICAL: Never import output() or error() from core — they call process.exit().
2139
- * CRITICAL: Never write to stdout directly — stdout may be reserved for protocol use.
2140
- * All logging must go to stderr via console.error().
2141
- */
2142
- function log(level, tag, ...args) {
2143
- const ts = (/* @__PURE__ */ new Date()).toISOString();
2144
- const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
2145
- console.error(`[${ts}] [${level}] [${tag}] ${msg}`);
2146
- }
2147
- function isWithinPlanning(cwd, targetPath) {
2148
- const planningDir = node_path.resolve(cwd, ".planning");
2149
- return node_path.resolve(cwd, targetPath).startsWith(planningDir);
2150
- }
2151
- function normalizeFsPath(p) {
2152
- return p.replace(/\\/g, "/");
2153
- }
2154
- function parseRoadmap(cwd) {
2155
- const roadmapPath = node_path.join(cwd, ".planning", "ROADMAP.md");
2156
- if (!node_fs.existsSync(roadmapPath)) return null;
2157
- const content = node_fs.readFileSync(roadmapPath, "utf-8").replace(/\r\n/g, "\n");
2158
- const phasesDir = node_path.join(cwd, ".planning", "phases");
2159
- const phasePattern = require_cli.getPhasePattern();
2160
- const phases = [];
2161
- let match;
2162
- while ((match = phasePattern.exec(content)) !== null) {
2163
- const phaseNum = match[1];
2164
- const phaseName = match[2].replace(/\(INSERTED\)/i, "").trim();
2165
- const sectionStart = match.index;
2166
- const nextHeader = content.slice(sectionStart).match(/\n#{2,4}\s+Phase\s+\d/i);
2167
- const sectionEnd = nextHeader ? sectionStart + nextHeader.index : content.length;
2168
- const section = content.slice(sectionStart, sectionEnd);
2169
- const goalMatch = section.match(/\*\*Goal(?::\*\*|\*\*:)\s*([^\n]+)/i);
2170
- const goal = goalMatch ? goalMatch[1].trim() : null;
2171
- const dependsMatch = section.match(/\*\*Depends on:\*\*\s*([^\n]+)/i);
2172
- const depends_on = dependsMatch ? dependsMatch[1].trim() : null;
2173
- const normalized = require_cli.normalizePhaseName(phaseNum);
2174
- let diskStatus = "no_directory";
2175
- let planCount = 0;
2176
- let summaryCount = 0;
2177
- let hasContext = false;
2178
- let hasResearch = false;
2179
- try {
2180
- const dirMatch = node_fs.readdirSync(phasesDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).find((d) => d.startsWith(normalized + "-") || d === normalized);
2181
- if (dirMatch) {
2182
- const phaseFiles = node_fs.readdirSync(node_path.join(phasesDir, dirMatch));
2183
- planCount = phaseFiles.filter((f) => f.endsWith("-PLAN.md") || f === "PLAN.md").length;
2184
- summaryCount = phaseFiles.filter((f) => f.endsWith("-SUMMARY.md") || f === "SUMMARY.md").length;
2185
- hasContext = phaseFiles.some((f) => f.endsWith("-CONTEXT.md") || f === "CONTEXT.md");
2186
- hasResearch = phaseFiles.some((f) => f.endsWith("-RESEARCH.md") || f === "RESEARCH.md");
2187
- if (summaryCount >= planCount && planCount > 0) diskStatus = "complete";
2188
- else if (summaryCount > 0) diskStatus = "partial";
2189
- else if (planCount > 0) diskStatus = "planned";
2190
- else if (hasResearch) diskStatus = "researched";
2191
- else if (hasContext) diskStatus = "discussed";
2192
- else diskStatus = "empty";
2193
- }
2194
- } catch {}
2195
- const checkboxPattern = new RegExp(`-\\s*\\[(x| )\\]\\s*.*Phase\\s+${phaseNum.replace(".", "\\.")}`, "i");
2196
- const checkboxMatch = content.match(checkboxPattern);
2197
- const roadmapComplete = checkboxMatch ? checkboxMatch[1] === "x" : false;
2198
- phases.push({
2199
- number: phaseNum,
2200
- name: phaseName,
2201
- goal,
2202
- depends_on,
2203
- plan_count: planCount,
2204
- summary_count: summaryCount,
2205
- has_context: hasContext,
2206
- has_research: hasResearch,
2207
- disk_status: diskStatus,
2208
- roadmap_complete: roadmapComplete
2209
- });
2210
- }
2211
- const milestones = [];
2212
- const milestonePattern = /##\s*(.*v(\d+\.\d+)[^(\n]*)/gi;
2213
- let mMatch;
2214
- while ((mMatch = milestonePattern.exec(content)) !== null) milestones.push({
2215
- heading: mMatch[1].trim(),
2216
- version: "v" + mMatch[2]
2217
- });
2218
- const currentPhase = phases.find((p) => p.disk_status === "planned" || p.disk_status === "partial") || null;
2219
- const nextPhase = phases.find((p) => p.disk_status === "empty" || p.disk_status === "no_directory" || p.disk_status === "discussed" || p.disk_status === "researched") || null;
2220
- const totalPlans = phases.reduce((sum, p) => sum + p.plan_count, 0);
2221
- const totalSummaries = phases.reduce((sum, p) => sum + p.summary_count, 0);
2222
- const completedPhases = phases.filter((p) => p.disk_status === "complete").length;
2223
- return {
2224
- milestones,
2225
- phases,
2226
- phase_count: phases.length,
2227
- completed_phases: completedPhases,
2228
- total_plans: totalPlans,
2229
- total_summaries: totalSummaries,
2230
- progress_percent: totalPlans > 0 ? Math.min(100, Math.round(totalSummaries / totalPlans * 100)) : 0,
2231
- current_phase: currentPhase ? currentPhase.number : null,
2232
- next_phase: nextPhase ? nextPhase.number : null,
2233
- missing_phase_details: null
2234
- };
2235
- }
2236
- function parseState(cwd) {
2237
- const statePath = node_path.join(cwd, ".planning", "STATE.md");
2238
- if (!node_fs.existsSync(statePath)) return null;
2239
- const content = node_fs.readFileSync(statePath, "utf-8").replace(/\r\n/g, "\n");
2240
- const position = require_cli.stateExtractField(content, "Current Position") || require_cli.stateExtractField(content, "Phase");
2241
- const lastActivity = require_cli.stateExtractField(content, "Last activity") || require_cli.stateExtractField(content, "Last Activity");
2242
- const currentPhase = require_cli.stateExtractField(content, "Current Phase") || require_cli.stateExtractField(content, "Phase");
2243
- const currentPlan = require_cli.stateExtractField(content, "Current Plan") || require_cli.stateExtractField(content, "Plan");
2244
- const status = require_cli.stateExtractField(content, "Status");
2245
- const progress = require_cli.stateExtractField(content, "Progress");
2246
- const decisions = [];
2247
- const decisionsMatch = content.match(/###?\s*Decisions\s*\n([\s\S]*?)(?=\n###?|\n##[^#]|$)/i);
2248
- if (decisionsMatch) {
2249
- const items = decisionsMatch[1].match(/^-\s+(.+)$/gm) || [];
2250
- for (const item of items) decisions.push(item.replace(/^-\s+/, "").trim());
2251
- }
2252
- const blockers = [];
2253
- const blockersMatch = content.match(/###?\s*(?:Blockers|Blockers\/Concerns)\s*\n([\s\S]*?)(?=\n###?|\n##[^#]|$)/i);
2254
- if (blockersMatch) {
2255
- const items = blockersMatch[1].match(/^-\s+(.+)$/gm) || [];
2256
- for (const item of items) blockers.push(item.replace(/^-\s+/, "").trim());
2257
- }
2258
- return {
2259
- position,
2260
- lastActivity,
2261
- currentPhase,
2262
- currentPlan,
2263
- status,
2264
- progress,
2265
- decisions,
2266
- blockers,
2267
- content
2268
- };
2269
- }
2270
- function parsePhases(cwd) {
2271
- const phasesDir = node_path.join(cwd, ".planning", "phases");
2272
- if (!node_fs.existsSync(phasesDir)) return [];
2273
- const phases = [];
2274
- try {
2275
- const dirs = node_fs.readdirSync(phasesDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort((a, b) => require_cli.comparePhaseNum(a, b));
2276
- for (const dir of dirs) {
2277
- const dm = dir.match(/^(\d+[A-Z]?(?:\.\d+)?)-?(.*)/i);
2278
- const phaseNum = dm ? dm[1] : dir;
2279
- const phaseName = dm && dm[2] ? dm[2].replace(/-/g, " ") : "";
2280
- const phaseFiles = node_fs.readdirSync(node_path.join(phasesDir, dir));
2281
- const planCount = phaseFiles.filter((f) => f.endsWith("-PLAN.md") || f === "PLAN.md").length;
2282
- const summaryCount = phaseFiles.filter((f) => f.endsWith("-SUMMARY.md") || f === "SUMMARY.md").length;
2283
- const hasContext = phaseFiles.some((f) => f.endsWith("-CONTEXT.md") || f === "CONTEXT.md");
2284
- const hasResearch = phaseFiles.some((f) => f.endsWith("-RESEARCH.md") || f === "RESEARCH.md");
2285
- let diskStatus = "no_directory";
2286
- if (summaryCount >= planCount && planCount > 0) diskStatus = "complete";
2287
- else if (summaryCount > 0) diskStatus = "partial";
2288
- else if (planCount > 0) diskStatus = "planned";
2289
- else if (hasResearch) diskStatus = "researched";
2290
- else if (hasContext) diskStatus = "discussed";
2291
- else diskStatus = "empty";
2292
- phases.push({
2293
- number: phaseNum,
2294
- name: phaseName,
2295
- goal: "",
2296
- dependsOn: [],
2297
- planCount,
2298
- summaryCount,
2299
- diskStatus,
2300
- roadmapComplete: diskStatus === "complete",
2301
- hasContext,
2302
- hasResearch
2303
- });
2304
- }
2305
- } catch {}
2306
- return phases;
2307
- }
2308
- function parsePhaseDetail(cwd, phaseId) {
2309
- const phasesDir = node_path.join(cwd, ".planning", "phases");
2310
- if (!node_fs.existsSync(phasesDir)) return null;
2311
- const normalized = require_cli.normalizePhaseName(phaseId);
2312
- try {
2313
- const dirMatch = node_fs.readdirSync(phasesDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).find((d) => d.startsWith(normalized + "-") || d === normalized);
2314
- if (!dirMatch) return null;
2315
- const phaseDir = node_path.join(phasesDir, dirMatch);
2316
- const phaseFiles = node_fs.readdirSync(phaseDir);
2317
- const planFileNames = phaseFiles.filter((f) => f.endsWith("-PLAN.md") || f === "PLAN.md").sort();
2318
- const plans = [];
2319
- for (const planFileName of planFileNames) {
2320
- const planPath = node_path.join(phaseDir, planFileName);
2321
- const content = node_fs.readFileSync(planPath, "utf-8").replace(/\r\n/g, "\n");
2322
- const frontmatter = require_cli.extractFrontmatter(content);
2323
- const tasks = [];
2324
- const taskRegex = /<task\s+type="([^"]*)"[^>]*>\s*<name>([^<]+)<\/name>([\s\S]*?)<\/task>/g;
2325
- let taskMatch;
2326
- while ((taskMatch = taskRegex.exec(content)) !== null) {
2327
- const taskType = taskMatch[1];
2328
- const taskName = taskMatch[2].trim();
2329
- const taskBody = taskMatch[3];
2330
- const filesMatch = taskBody.match(/<files>([\s\S]*?)<\/files>/);
2331
- const actionMatch = taskBody.match(/<action>([\s\S]*?)<\/action>/);
2332
- const verifyMatch = taskBody.match(/<verify>([\s\S]*?)<\/verify>/);
2333
- const doneMatch = taskBody.match(/<done>([\s\S]*?)<\/done>/);
2334
- const files = filesMatch ? filesMatch[1].trim().split("\n").map((f) => f.trim()).filter(Boolean) : [];
2335
- const doneText = doneMatch ? doneMatch[1].trim() : "";
2336
- tasks.push({
2337
- name: taskName,
2338
- type: taskType,
2339
- files,
2340
- action: actionMatch ? actionMatch[1].trim() : "",
2341
- verify: verifyMatch ? verifyMatch[1].trim() : "",
2342
- done: doneText,
2343
- completed: /^\[x\]/i.test(doneText)
2344
- });
2345
- }
2346
- plans.push({
2347
- path: node_path.join(".planning", "phases", dirMatch, planFileName),
2348
- content,
2349
- frontmatter,
2350
- tasks
2351
- });
2352
- }
2353
- let context = null;
2354
- const contextFile = phaseFiles.find((f) => f.endsWith("-CONTEXT.md") || f === "CONTEXT.md");
2355
- if (contextFile) context = node_fs.readFileSync(node_path.join(phaseDir, contextFile), "utf-8");
2356
- let research = null;
2357
- const researchFile = phaseFiles.find((f) => f.endsWith("-RESEARCH.md") || f === "RESEARCH.md");
2358
- if (researchFile) research = node_fs.readFileSync(node_path.join(phaseDir, researchFile), "utf-8");
2359
- return {
2360
- plans,
2361
- context,
2362
- research
2363
- };
2364
- } catch {
2365
- return null;
2366
- }
2367
- }
2368
- function parseTodos(cwd) {
2369
- const pendingDir = node_path.join(cwd, ".planning", "todos", "pending");
2370
- const completedDir = node_path.join(cwd, ".planning", "todos", "completed");
2371
- const pending = [];
2372
- const completed = [];
2373
- if (node_fs.existsSync(pendingDir)) try {
2374
- const files = node_fs.readdirSync(pendingDir).filter((f) => f.endsWith(".md"));
2375
- for (const file of files) try {
2376
- const titleMatch = node_fs.readFileSync(node_path.join(pendingDir, file), "utf-8").match(/^title:\s*(.+)$/m);
2377
- pending.push({
2378
- text: titleMatch ? titleMatch[1].trim() : file.replace(".md", ""),
2379
- completed: false,
2380
- file
2381
- });
2382
- } catch {}
2383
- } catch {}
2384
- if (node_fs.existsSync(completedDir)) try {
2385
- const files = node_fs.readdirSync(completedDir).filter((f) => f.endsWith(".md"));
2386
- for (const file of files) try {
2387
- const titleMatch = node_fs.readFileSync(node_path.join(completedDir, file), "utf-8").match(/^title:\s*(.+)$/m);
2388
- completed.push({
2389
- text: titleMatch ? titleMatch[1].trim() : file.replace(".md", ""),
2390
- completed: true,
2391
- file
2392
- });
2393
- } catch {}
2394
- } catch {}
2395
- return {
2396
- pending,
2397
- completed
2398
- };
2399
- }
2400
- function parseProject(cwd) {
2401
- const projectPath = node_path.join(cwd, ".planning", "PROJECT.md");
2402
- const requirementsPath = node_path.join(cwd, ".planning", "REQUIREMENTS.md");
2403
- return {
2404
- project: node_fs.existsSync(projectPath) ? node_fs.readFileSync(projectPath, "utf-8") : null,
2405
- requirements: node_fs.existsSync(requirementsPath) ? node_fs.readFileSync(requirementsPath, "utf-8") : null
2406
- };
2407
- }
2408
- function createBackendServer(config) {
2409
- const { projectCwd, host, enableTerminal, enableFileWatcher, enableMcp, logDir } = config;
2410
- let resolvedPort = config.port;
2411
- const startTime = Date.now();
2412
- let serverReady = false;
2413
- node_fs.mkdirSync(logDir, { recursive: true });
2414
- const suppressedPaths = /* @__PURE__ */ new Map();
2415
- const SUPPRESS_TTL_MS = 500;
2416
- function suppressPath(filePath) {
2417
- suppressedPaths.set(normalizeFsPath(filePath), Date.now());
2418
- }
2419
- function isSuppressed(filePath) {
2420
- const normalized = normalizeFsPath(filePath);
2421
- const timestamp = suppressedPaths.get(normalized);
2422
- if (timestamp === void 0) return false;
2423
- if (Date.now() - timestamp > SUPPRESS_TTL_MS) {
2424
- suppressedPaths.delete(normalized);
2425
- return false;
2426
- }
2427
- return true;
2428
- }
2429
- const cleanupInterval = setInterval(() => {
2430
- const now = Date.now();
2431
- for (const [p, ts] of suppressedPaths.entries()) if (now - ts > SUPPRESS_TTL_MS) suppressedPaths.delete(p);
2432
- }, 6e4);
2433
- cleanupInterval.unref();
2434
- const questionQueue = [];
2435
- const pendingAnswers = /* @__PURE__ */ new Map();
2436
- let clientCount = 0;
2437
- const wss = new ws.WebSocketServer({ noServer: true });
2438
- wss.on("connection", (ws$1) => {
2439
- clientCount++;
2440
- log("INFO", "ws", `Client connected (${clientCount} total)`);
2441
- ws$1.on("close", () => {
2442
- clientCount--;
2443
- log("INFO", "ws", `Client disconnected (${clientCount} total)`);
2444
- });
2445
- ws$1.on("error", (err) => {
2446
- log("ERROR", "ws", `Client error: ${err.message}`);
2447
- });
2448
- ws$1.send(JSON.stringify({
2449
- type: "connected",
2450
- timestamp: Date.now()
2451
- }));
2452
- if (questionQueue.length > 0) ws$1.send(JSON.stringify({
2453
- type: "questions-queued",
2454
- questions: questionQueue,
2455
- count: questionQueue.length
2456
- }));
2457
- });
2458
- function broadcast(message) {
2459
- const data = JSON.stringify(message);
2460
- for (const client of wss.clients) if (client.readyState === ws.WebSocket.OPEN) client.send(data);
2461
- }
2462
- let watcher = null;
2463
- async function setupWatcher() {
2464
- if (!enableFileWatcher) return;
2465
- const planningDir = node_path.join(projectCwd, ".planning");
2466
- if (!node_fs.existsSync(planningDir)) {
2467
- log("WARN", "watcher", `.planning/ directory not found at ${planningDir}`);
2468
- return;
2469
- }
2470
- try {
2471
- const chokidar = await import("chokidar");
2472
- const changedPaths = /* @__PURE__ */ new Set();
2473
- let flushTimer = null;
2474
- function flushChanges() {
2475
- if (changedPaths.size > 0) {
2476
- const changes = Array.from(changedPaths);
2477
- changedPaths.clear();
2478
- log("INFO", "watcher", `Broadcasting ${changes.length} change(s)`);
2479
- broadcast({
2480
- type: "file-changes",
2481
- changes,
2482
- timestamp: Date.now()
2483
- });
2484
- }
2485
- }
2486
- function onFileChange(filePath) {
2487
- const normalized = normalizeFsPath(filePath);
2488
- if (isSuppressed(normalized)) return;
2489
- changedPaths.add(normalized);
2490
- if (flushTimer) clearTimeout(flushTimer);
2491
- flushTimer = setTimeout(flushChanges, 500);
2492
- }
2493
- const w = chokidar.watch(planningDir, {
2494
- persistent: true,
2495
- ignoreInitial: true,
2496
- depth: 5
2497
- });
2498
- w.on("add", onFileChange);
2499
- w.on("change", onFileChange);
2500
- w.on("unlink", onFileChange);
2501
- w.on("error", (err) => {
2502
- log("ERROR", "watcher", `Error: ${err.message}`);
2503
- });
2504
- watcher = w;
2505
- log("INFO", "watcher", `Watching ${planningDir}`);
2506
- } catch (err) {
2507
- log("ERROR", "watcher", `Failed to start file watcher: ${err.message}`);
2508
- }
2509
- }
2510
- const app = (0, express.default)();
2511
- app.use(express.default.json());
2512
- app.get("/api/health", (_req, res) => {
2513
- res.json({
2514
- status: "ok",
2515
- ready: serverReady,
2516
- port: resolvedPort,
2517
- cwd: projectCwd,
2518
- uptime: (Date.now() - startTime) / 1e3,
2519
- pid: process.pid,
2520
- mcpEndpoint: enableMcp ? `http://127.0.0.1:${resolvedPort}/mcp` : null,
2521
- terminalAvailable: enableTerminal && PtyManager.getInstance().isAvailable(),
2522
- connectedClients: clientCount
2523
- });
2524
- });
2525
- app.get("/api/ready", (_req, res) => {
2526
- if (serverReady) return res.json({
2527
- ready: true,
2528
- port: resolvedPort,
2529
- cwd: projectCwd
2530
- });
2531
- return res.status(503).json({
2532
- ready: false,
2533
- message: "Server is starting up"
2534
- });
2535
- });
2536
- app.get("/api/roadmap", (_req, res) => {
2537
- try {
2538
- const data = parseRoadmap(projectCwd);
2539
- if (!data) return res.status(404).json({ error: "ROADMAP.md not found" });
2540
- return res.json(data);
2541
- } catch (err) {
2542
- log("ERROR", "api", `GET /api/roadmap failed: ${err.message}`);
2543
- return res.status(500).json({ error: "Internal server error" });
2544
- }
2545
- });
2546
- app.patch("/api/roadmap", (req, res) => {
2547
- try {
2548
- const roadmapPath = node_path.join(projectCwd, ".planning", "ROADMAP.md");
2549
- if (!node_fs.existsSync(roadmapPath)) return res.status(404).json({ error: "ROADMAP.md not found" });
2550
- const { phaseNumber, checked } = req.body;
2551
- if (!phaseNumber || checked === void 0) return res.status(400).json({ error: "phaseNumber and checked are required" });
2552
- let content = node_fs.readFileSync(roadmapPath, "utf-8").replace(/\r\n/g, "\n");
2553
- const escapedNum = phaseNumber.replace(".", "\\.");
2554
- const pattern = new RegExp(`(-\\s*\\[)(x| )(\\]\\s*.*Phase\\s+${escapedNum})`, "i");
2555
- if (!content.match(pattern)) return res.status(404).json({ error: `Phase ${phaseNumber} checkbox not found` });
2556
- content = content.replace(pattern, `$1${checked ? "x" : " "}$3`);
2557
- suppressPath(roadmapPath);
2558
- node_fs.writeFileSync(roadmapPath, content, "utf-8");
2559
- return res.json({
2560
- updated: true,
2561
- phaseNumber,
2562
- checked
2563
- });
2564
- } catch (err) {
2565
- log("ERROR", "api", `PATCH /api/roadmap failed: ${err.message}`);
2566
- return res.status(500).json({ error: "Internal server error" });
2567
- }
2568
- });
2569
- app.get("/api/state", (_req, res) => {
2570
- try {
2571
- const data = parseState(projectCwd);
2572
- if (!data) return res.status(404).json({ error: "STATE.md not found" });
2573
- return res.json(data);
2574
- } catch (err) {
2575
- log("ERROR", "api", `GET /api/state failed: ${err.message}`);
2576
- return res.status(500).json({ error: "Internal server error" });
2577
- }
2578
- });
2579
- app.patch("/api/state", (req, res) => {
2580
- try {
2581
- const statePath = node_path.join(projectCwd, ".planning", "STATE.md");
2582
- if (!node_fs.existsSync(statePath)) return res.status(404).json({ error: "STATE.md not found" });
2583
- const { field, value } = req.body;
2584
- if (!field || value === void 0) return res.status(400).json({ error: "field and value are required" });
2585
- const updated = require_cli.stateReplaceField(node_fs.readFileSync(statePath, "utf-8").replace(/\r\n/g, "\n"), field, value);
2586
- if (!updated) return res.status(404).json({ error: `Field "${field}" not found in STATE.md` });
2587
- suppressPath(statePath);
2588
- node_fs.writeFileSync(statePath, updated, "utf-8");
2589
- return res.json({
2590
- updated: true,
2591
- field
2592
- });
2593
- } catch (err) {
2594
- log("ERROR", "api", `PATCH /api/state failed: ${err.message}`);
2595
- return res.status(500).json({ error: "Internal server error" });
2596
- }
2597
- });
2598
- function ensureStateMd(statePath) {
2599
- if (node_fs.existsSync(statePath)) return;
2600
- const planningDir = node_path.dirname(statePath);
2601
- node_fs.mkdirSync(planningDir, { recursive: true });
2602
- const template = `# Project State
2603
-
2604
- ## Current Position
2605
-
2606
- Phase: 1
2607
- Status: In progress
2608
- Last activity: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]} — State file created
2609
-
2610
- ## Accumulated Context
2611
-
2612
- ### Decisions
2613
-
2614
- None yet.
2615
-
2616
- ### Blockers/Concerns
2617
-
2618
- None yet.
2619
- `;
2620
- node_fs.writeFileSync(statePath, template, "utf-8");
2621
- }
2622
- function appendToStateSection(statePath, sectionPattern, entry, fallbackSection) {
2623
- let content = node_fs.readFileSync(statePath, "utf-8").replace(/\r\n/g, "\n");
2624
- const match = content.match(sectionPattern);
2625
- if (match) {
2626
- let sectionBody = match[2];
2627
- sectionBody = sectionBody.replace(/None yet\.?\s*\n?/gi, "").replace(/No decisions yet\.?\s*\n?/gi, "").replace(/None\.?\s*\n?/gi, "");
2628
- sectionBody = sectionBody.trimEnd() + "\n" + entry + "\n";
2629
- content = content.replace(sectionPattern, (_m, header) => `${header}${sectionBody}`);
2630
- } else content = content.trimEnd() + "\n\n" + fallbackSection + "\n" + entry + "\n";
2631
- suppressPath(statePath);
2632
- node_fs.writeFileSync(statePath, content, "utf-8");
2633
- }
2634
- app.post("/api/state/decision", (req, res) => {
2635
- try {
2636
- const statePath = node_path.join(projectCwd, ".planning", "STATE.md");
2637
- ensureStateMd(statePath);
2638
- const { phase, text } = req.body;
2639
- if (!text?.trim()) return res.status(400).json({ error: "text is required" });
2640
- const entry = `- [Phase ${phase?.trim() || "?"}]: ${text.trim()}`;
2641
- appendToStateSection(statePath, /(###?\s*(?:Decisions|Decisions Made|Accumulated.*Decisions)\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i, entry, "### Decisions");
2642
- return res.json({
2643
- added: true,
2644
- decision: entry
2645
- });
2646
- } catch (err) {
2647
- log("ERROR", "api", `POST /api/state/decision failed: ${err.message}`);
2648
- return res.status(500).json({ error: "Internal server error" });
2649
- }
2650
- });
2651
- app.post("/api/state/blocker", (req, res) => {
2652
- try {
2653
- const statePath = node_path.join(projectCwd, ".planning", "STATE.md");
2654
- ensureStateMd(statePath);
2655
- const { text } = req.body;
2656
- if (!text?.trim()) return res.status(400).json({ error: "text is required" });
2657
- appendToStateSection(statePath, /(###?\s*(?:Blockers|Blockers\/Concerns|Concerns)\s*\n)([\s\S]*?)(?=\n###?|\n##[^#]|$)/i, `- ${text.trim()}`, "### Blockers/Concerns");
2658
- return res.json({
2659
- added: true,
2660
- blocker: text.trim()
2661
- });
2662
- } catch (err) {
2663
- log("ERROR", "api", `POST /api/state/blocker failed: ${err.message}`);
2664
- return res.status(500).json({ error: "Internal server error" });
2665
- }
2666
- });
2667
- app.get("/api/phases", (_req, res) => {
2668
- try {
2669
- return res.json(parsePhases(projectCwd));
2670
- } catch (err) {
2671
- log("ERROR", "api", `GET /api/phases failed: ${err.message}`);
2672
- return res.status(500).json({ error: "Internal server error" });
2673
- }
2674
- });
2675
- app.get("/api/phase/:id", (req, res) => {
2676
- try {
2677
- const data = parsePhaseDetail(projectCwd, req.params.id);
2678
- if (!data) return res.status(404).json({ error: `Phase ${req.params.id} not found` });
2679
- return res.json(data);
2680
- } catch (err) {
2681
- log("ERROR", "api", `GET /api/phase/:id failed: ${err.message}`);
2682
- return res.status(500).json({ error: "Internal server error" });
2683
- }
2684
- });
2685
- app.get("/api/todos", (_req, res) => {
2686
- try {
2687
- return res.json(parseTodos(projectCwd));
2688
- } catch (err) {
2689
- log("ERROR", "api", `GET /api/todos failed: ${err.message}`);
2690
- return res.status(500).json({ error: "Internal server error" });
2691
- }
2692
- });
2693
- app.post("/api/todos", (req, res) => {
2694
- try {
2695
- const pendingDir = node_path.join(projectCwd, ".planning", "todos", "pending");
2696
- const { text } = req.body;
2697
- if (!text) return res.status(400).json({ error: "text is required" });
2698
- node_fs.mkdirSync(pendingDir, { recursive: true });
2699
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2700
- const filename = `${timestamp}-${text.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 40)}.md`;
2701
- const filePath = node_path.join(pendingDir, filename);
2702
- const content = `title: ${text}\ncreated: ${timestamp}\narea: general\n\n${text}\n`;
2703
- suppressPath(filePath);
2704
- node_fs.writeFileSync(filePath, content, "utf-8");
2705
- return res.json({
2706
- created: true,
2707
- file: filename,
2708
- text
2709
- });
2710
- } catch (err) {
2711
- log("ERROR", "api", `POST /api/todos failed: ${err.message}`);
2712
- return res.status(500).json({ error: "Internal server error" });
2713
- }
2714
- });
2715
- app.patch("/api/todos", (req, res) => {
2716
- try {
2717
- const pendingDir = node_path.join(projectCwd, ".planning", "todos", "pending");
2718
- const completedDir = node_path.join(projectCwd, ".planning", "todos", "completed");
2719
- const { file, completed } = req.body;
2720
- if (!file) return res.status(400).json({ error: "file is required" });
2721
- if (file.includes("/") || file.includes("\\") || file.includes("..")) return res.status(400).json({ error: "Invalid filename" });
2722
- if (completed) {
2723
- const sourcePath = node_path.join(pendingDir, file);
2724
- if (!node_fs.existsSync(sourcePath)) return res.status(404).json({ error: "Todo not found in pending" });
2725
- node_fs.mkdirSync(completedDir, { recursive: true });
2726
- const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2727
- let content = node_fs.readFileSync(sourcePath, "utf-8");
2728
- content = `completed: ${today}\n` + content;
2729
- const destPath = node_path.join(completedDir, file);
2730
- suppressPath(sourcePath);
2731
- suppressPath(destPath);
2732
- node_fs.writeFileSync(destPath, content, "utf-8");
2733
- node_fs.unlinkSync(sourcePath);
2734
- return res.json({
2735
- completed: true,
2736
- file,
2737
- date: today
2738
- });
2739
- } else {
2740
- const sourcePath = node_path.join(completedDir, file);
2741
- if (!node_fs.existsSync(sourcePath)) return res.status(404).json({ error: "Todo not found in completed" });
2742
- node_fs.mkdirSync(pendingDir, { recursive: true });
2743
- let content = node_fs.readFileSync(sourcePath, "utf-8");
2744
- content = content.replace(/^completed:\s*.+\n/m, "");
2745
- const destPath = node_path.join(pendingDir, file);
2746
- suppressPath(sourcePath);
2747
- suppressPath(destPath);
2748
- node_fs.writeFileSync(destPath, content, "utf-8");
2749
- node_fs.unlinkSync(sourcePath);
2750
- return res.json({
2751
- completed: false,
2752
- file
2753
- });
2754
- }
2755
- } catch (err) {
2756
- log("ERROR", "api", `PATCH /api/todos failed: ${err.message}`);
2757
- return res.status(500).json({ error: "Internal server error" });
2758
- }
2759
- });
2760
- app.get("/api/project", (_req, res) => {
2761
- try {
2762
- return res.json(parseProject(projectCwd));
2763
- } catch (err) {
2764
- log("ERROR", "api", `GET /api/project failed: ${err.message}`);
2765
- return res.status(500).json({ error: "Internal server error" });
2766
- }
2767
- });
2768
- app.get("/api/plan/*", (req, res) => {
2769
- try {
2770
- const pathSegments = req.params["0"].split("/");
2771
- const relativePath = node_path.join(".planning", ...pathSegments);
2772
- if (!isWithinPlanning(projectCwd, relativePath)) return res.status(403).json({ error: "Path traversal not allowed" });
2773
- const fullPath = node_path.join(projectCwd, relativePath);
2774
- if (!node_fs.existsSync(fullPath)) return res.status(404).json({ error: "File not found" });
2775
- const content = node_fs.readFileSync(fullPath, "utf-8");
2776
- return res.json({
2777
- path: relativePath,
2778
- content
2779
- });
2780
- } catch (err) {
2781
- log("ERROR", "api", `GET /api/plan/* failed: ${err.message}`);
2782
- return res.status(500).json({ error: "Internal server error" });
2783
- }
2784
- });
2785
- app.put("/api/plan/*", (req, res) => {
2786
- try {
2787
- const pathSegments = req.params["0"].split("/");
2788
- const relativePath = node_path.join(".planning", ...pathSegments);
2789
- if (!isWithinPlanning(projectCwd, relativePath)) return res.status(403).json({ error: "Path traversal not allowed" });
2790
- const { content } = req.body;
2791
- if (content === void 0) return res.status(400).json({ error: "content is required" });
2792
- const fullPath = node_path.join(projectCwd, relativePath);
2793
- const dir = node_path.dirname(fullPath);
2794
- if (!node_fs.existsSync(dir)) node_fs.mkdirSync(dir, { recursive: true });
2795
- suppressPath(fullPath);
2796
- node_fs.writeFileSync(fullPath, content, "utf-8");
2797
- return res.json({
2798
- written: true,
2799
- path: relativePath
2800
- });
2801
- } catch (err) {
2802
- log("ERROR", "api", `PUT /api/plan/* failed: ${err.message}`);
2803
- return res.status(500).json({ error: "Internal server error" });
2804
- }
2805
- });
2806
- app.get("/api/server-info", (_req, res) => {
2807
- const localNetworkIp = getLocalNetworkIp();
2808
- return res.json({
2809
- localUrl: `http://127.0.0.1:${resolvedPort}`,
2810
- networkUrl: localNetworkIp ? `http://${localNetworkIp}:${resolvedPort}` : null,
2811
- projectName: node_path.basename(projectCwd),
2812
- projectCwd
2813
- });
2814
- });
2815
- let shutdownFn = null;
2816
- app.post("/api/shutdown", (_req, res) => {
2817
- res.json({ shutdown: true });
2818
- setTimeout(() => shutdownFn?.(), 100);
2819
- });
2820
- app.post("/api/mcp-answer", (req, res) => {
2821
- const { questionId, answer } = req.body;
2822
- if (!questionId || !answer) return res.status(400).json({ error: "questionId and answer are required" });
2823
- const resolve = pendingAnswers.get(questionId);
2824
- if (!resolve) return res.status(404).json({ error: "No pending question with that ID" });
2825
- pendingAnswers.delete(questionId);
2826
- resolve(answer);
2827
- return res.json({ answered: true });
2828
- });
2829
- if (enableMcp) {
2830
- app.post("/mcp", async (req, res) => {
2831
- const mcpServer = new _modelcontextprotocol_sdk_server_mcp_js.McpServer({
2832
- name: "maxsim-backend",
2833
- version: "1.0.0"
2834
- });
2835
- registerAllTools(mcpServer);
2836
- try {
2837
- const transport = new _modelcontextprotocol_sdk_server_streamableHttp_js.StreamableHTTPServerTransport({ sessionIdGenerator: void 0 });
2838
- await mcpServer.connect(transport);
2839
- await transport.handleRequest(req, res, req.body);
2840
- res.on("close", () => {
2841
- transport.close();
2842
- mcpServer.close();
2843
- });
2844
- } catch (error) {
2845
- log("ERROR", "mcp", `Error handling MCP POST request: ${error}`);
2846
- if (!res.headersSent) res.status(500).json({
2847
- jsonrpc: "2.0",
2848
- error: {
2849
- code: -32603,
2850
- message: "Internal server error"
2851
- },
2852
- id: null
2853
- });
2854
- }
2855
- });
2856
- app.get("/mcp", (_req, res) => {
2857
- res.writeHead(405).end(JSON.stringify({
2858
- jsonrpc: "2.0",
2859
- error: {
2860
- code: -32e3,
2861
- message: "Method not allowed."
2862
- },
2863
- id: null
2864
- }));
2865
- });
2866
- app.delete("/mcp", (_req, res) => {
2867
- res.status(200).end();
2868
- });
2869
- }
2870
- const terminalWss = new ws.WebSocketServer({ noServer: true });
2871
- const ptyManager = enableTerminal ? PtyManager.getInstance() : null;
2872
- if (ptyManager && !ptyManager.isAvailable()) log("WARN", "server", "node-pty not available — terminal features disabled");
2873
- terminalWss.on("connection", (ws$2) => {
2874
- if (!ptyManager) return;
2875
- log("INFO", "terminal-ws", "Client connected");
2876
- ptyManager.addClient(ws$2);
2877
- if (!ptyManager.isAvailable()) ws$2.send(JSON.stringify({
2878
- type: "unavailable",
2879
- reason: "node-pty is not installed"
2880
- }));
2881
- ws$2.on("message", (raw) => {
2882
- try {
2883
- const msg = JSON.parse(typeof raw === "string" ? raw : raw.toString());
2884
- switch (msg.type) {
2885
- case "input":
2886
- ptyManager.write(msg.data);
2887
- break;
2888
- case "resize":
2889
- ptyManager.resize(msg.cols, msg.rows);
2890
- break;
2891
- case "spawn":
2892
- try {
2893
- ptyManager.spawn({
2894
- skipPermissions: !!msg.skipPermissions,
2895
- cwd: projectCwd,
2896
- cols: msg.cols,
2897
- rows: msg.rows
2898
- });
2899
- } catch (err) {
2900
- const errMsg = err instanceof Error ? err.message : String(err);
2901
- ws$2.send(JSON.stringify({
2902
- type: "output",
2903
- data: `\r\n\x1b[31mFailed to start terminal: ${errMsg}\x1b[0m\r\n`
2904
- }));
2905
- }
2906
- break;
2907
- case "kill":
2908
- ptyManager.kill();
2909
- break;
2910
- }
2911
- } catch (err) {
2912
- log("ERROR", "terminal-ws", `Message handling error: ${err.message}`);
2913
- }
2914
- });
2915
- ws$2.on("close", () => {
2916
- log("INFO", "terminal-ws", "Client disconnected");
2917
- ptyManager.removeClient(ws$2);
2918
- });
2919
- ws$2.on("error", (err) => {
2920
- log("ERROR", "terminal-ws", `Client error: ${err.message}`);
2921
- });
2922
- });
2923
- const server = (0, node_http.createServer)(app);
2924
- server.on("upgrade", (req, socket, head) => {
2925
- const url = req.url || "/";
2926
- if (url === "/ws/terminal" || url.startsWith("/ws/terminal?")) terminalWss.handleUpgrade(req, socket, head, (ws$3) => {
2927
- terminalWss.emit("connection", ws$3, req);
2928
- });
2929
- else if (url === "/api/ws" || url.startsWith("/api/ws?")) wss.handleUpgrade(req, socket, head, (ws$4) => {
2930
- wss.emit("connection", ws$4, req);
2931
- });
2932
- else socket.destroy();
2933
- });
2934
- async function start() {
2935
- const port = await (0, detect_port.default)(config.port);
2936
- resolvedPort = port;
2937
- await setupWatcher();
2938
- return new Promise((resolve) => {
2939
- server.listen(port, host, () => {
2940
- serverReady = true;
2941
- log("INFO", "server", `Backend ready on ${host}:${port} for ${projectCwd}`);
2942
- if (enableMcp) log("INFO", "mcp", `MCP endpoint available at http://127.0.0.1:${port}/mcp`);
2943
- resolve();
2944
- });
2945
- });
2946
- }
2947
- async function stop() {
2948
- log("INFO", "server", "Shutting down...");
2949
- clearInterval(cleanupInterval);
2950
- if (ptyManager) ptyManager.kill();
2951
- if (watcher) await watcher.close().catch(() => {});
2952
- terminalWss.close(() => {});
2953
- wss.close(() => {});
2954
- return new Promise((resolve) => {
2955
- server.close(() => {
2956
- log("INFO", "server", "Server closed");
2957
- resolve();
2958
- });
2959
- });
2960
- }
2961
- shutdownFn = () => {
2962
- stop().then(() => process.exit(0)).catch(() => process.exit(1));
2963
- };
2964
- function getStatus() {
2965
- return {
2966
- status: serverReady ? "ok" : "starting",
2967
- ready: serverReady,
2968
- port: resolvedPort,
2969
- cwd: projectCwd,
2970
- uptime: (Date.now() - startTime) / 1e3,
2971
- pid: process.pid,
2972
- mcpEndpoint: enableMcp ? `http://127.0.0.1:${resolvedPort}/mcp` : null,
2973
- terminalAvailable: ptyManager?.isAvailable() ?? false,
2974
- connectedClients: clientCount
2975
- };
2976
- }
2977
- function getPort() {
2978
- return resolvedPort;
2979
- }
2980
- return {
2981
- start,
2982
- stop,
2983
- getStatus,
2984
- getPort
2985
- };
2986
- }
2987
- function getLocalNetworkIp() {
2988
- const ifaces = node_os.networkInterfaces();
2989
- for (const iface of Object.values(ifaces)) for (const info of iface ?? []) if (info.family === "IPv4" && !info.internal) return info.address;
2990
- return null;
2991
- }
2992
-
2993
- //#endregion
2994
- exports.createBackendServer = createBackendServer;
2995
- //# sourceMappingURL=server-By0TN-nC.cjs.map