projax 3.3.41 → 3.3.52

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 (111) hide show
  1. package/coverage/core-bridge.ts.html +24 -3
  2. package/coverage/index.html +34 -19
  3. package/coverage/lcov-report/core-bridge.ts.html +24 -3
  4. package/coverage/lcov-report/index.html +34 -19
  5. package/coverage/lcov-report/port-extractor.ts.html +1 -1
  6. package/coverage/lcov-report/port-scanner.ts.html +3 -3
  7. package/coverage/lcov-report/port-utils.ts.html +1 -1
  8. package/coverage/lcov-report/script-runner.ts.html +302 -11
  9. package/coverage/lcov-report/test-parser.ts.html +799 -0
  10. package/coverage/lcov.info +270 -49
  11. package/coverage/port-extractor.ts.html +1 -1
  12. package/coverage/port-scanner.ts.html +3 -3
  13. package/coverage/port-utils.ts.html +1 -1
  14. package/coverage/script-runner.ts.html +302 -11
  15. package/coverage/test-parser.ts.html +799 -0
  16. package/dist/api/__tests__/routes.test.js +1 -0
  17. package/dist/api/__tests__/routes.test.js.map +1 -1
  18. package/dist/api/__tests__/scanner.test.js +1 -0
  19. package/dist/api/__tests__/scanner.test.js.map +1 -1
  20. package/dist/api/package.json +4 -0
  21. package/dist/api/routes/backup.d.ts +2 -1
  22. package/dist/api/routes/backup.d.ts.map +1 -1
  23. package/dist/api/routes/backup.js.map +1 -1
  24. package/dist/api/routes/index.d.ts +2 -1
  25. package/dist/api/routes/index.d.ts.map +1 -1
  26. package/dist/api/routes/index.js.map +1 -1
  27. package/dist/api/routes/projects.d.ts +2 -1
  28. package/dist/api/routes/projects.d.ts.map +1 -1
  29. package/dist/api/routes/projects.js.map +1 -1
  30. package/dist/api/routes/settings.d.ts +2 -1
  31. package/dist/api/routes/settings.d.ts.map +1 -1
  32. package/dist/api/routes/settings.js +21 -1
  33. package/dist/api/routes/settings.js.map +1 -1
  34. package/dist/api/routes/workspaces.d.ts +2 -1
  35. package/dist/api/routes/workspaces.d.ts.map +1 -1
  36. package/dist/api/routes/workspaces.js.map +1 -1
  37. package/dist/core/__tests__/index.test.js +1 -0
  38. package/dist/core/__tests__/scanner.test.js +1 -0
  39. package/dist/core/__tests__/settings.test.js +1 -0
  40. package/dist/core-bridge.js +5 -1
  41. package/dist/electron/core/__tests__/index.test.js +1 -0
  42. package/dist/electron/core/__tests__/scanner.test.js +1 -0
  43. package/dist/electron/core/__tests__/settings.test.js +1 -0
  44. package/dist/electron/core.js +5 -1
  45. package/dist/electron/main.js +113 -99
  46. package/dist/electron/port-scanner.js +1 -1
  47. package/dist/electron/renderer/assets/index-BjZn_mEF.js +66 -0
  48. package/dist/electron/renderer/assets/index-CZmDxbJO.js +66 -0
  49. package/dist/electron/renderer/assets/{index-CWxXs5M7.css → index-DfocdjIj.css} +1 -1
  50. package/dist/electron/renderer/index.html +2 -2
  51. package/dist/index.js +19 -19
  52. package/dist/port-scanner.js +1 -1
  53. package/dist/prxi.d.ts +1 -0
  54. package/dist/prxi.js +1106 -0
  55. package/dist/prxi.tsx +6 -6
  56. package/jest.config.js +8 -0
  57. package/package.json +8 -4
  58. package/dist/api/routes/mcp.d.ts +0 -3
  59. package/dist/api/routes/mcp.d.ts.map +0 -1
  60. package/dist/api/routes/mcp.js +0 -147
  61. package/dist/api/routes/mcp.js.map +0 -1
  62. package/dist/electron/renderer/assets/index-59AhiV_K.css +0 -1
  63. package/dist/electron/renderer/assets/index-A04svynq.js +0 -62
  64. package/dist/electron/renderer/assets/index-B-etDnj2.js +0 -64
  65. package/dist/electron/renderer/assets/index-BGodNljq.js +0 -62
  66. package/dist/electron/renderer/assets/index-Bx18Cyic.js +0 -64
  67. package/dist/electron/renderer/assets/index-ByBOaxqv.js +0 -62
  68. package/dist/electron/renderer/assets/index-ByHY-x-j.js +0 -62
  69. package/dist/electron/renderer/assets/index-C1SRt6Jx.js +0 -62
  70. package/dist/electron/renderer/assets/index-C8f5yNYe.js +0 -64
  71. package/dist/electron/renderer/assets/index-C9Fo49a8.js +0 -61
  72. package/dist/electron/renderer/assets/index-CGx7K7jh.js +0 -62
  73. package/dist/electron/renderer/assets/index-CIZ3Wl6c.css +0 -1
  74. package/dist/electron/renderer/assets/index-CJbsU9y8.css +0 -1
  75. package/dist/electron/renderer/assets/index-CJrLunKK.js +0 -62
  76. package/dist/electron/renderer/assets/index-CQTleudf.css +0 -1
  77. package/dist/electron/renderer/assets/index-CQcilqlv.js +0 -62
  78. package/dist/electron/renderer/assets/index-CS-85xbL.css +0 -1
  79. package/dist/electron/renderer/assets/index-CYph0WPA.js +0 -62
  80. package/dist/electron/renderer/assets/index-C_WSLD6y.css +0 -1
  81. package/dist/electron/renderer/assets/index-CgB-tTpV.js +0 -62
  82. package/dist/electron/renderer/assets/index-ChoTzPLo.css +0 -1
  83. package/dist/electron/renderer/assets/index-CopVNRnR.js +0 -64
  84. package/dist/electron/renderer/assets/index-CtXtIMer.js +0 -64
  85. package/dist/electron/renderer/assets/index-D1jmaGv5.css +0 -1
  86. package/dist/electron/renderer/assets/index-D2AOB6Er.js +0 -62
  87. package/dist/electron/renderer/assets/index-DAfjuYKX.js +0 -61
  88. package/dist/electron/renderer/assets/index-DEOOHPEi.css +0 -1
  89. package/dist/electron/renderer/assets/index-DTtg6XrF.css +0 -1
  90. package/dist/electron/renderer/assets/index-DUvcepWm.js +0 -64
  91. package/dist/electron/renderer/assets/index-DVWDlM1D.js +0 -62
  92. package/dist/electron/renderer/assets/index-DWe2TQFv.css +0 -1
  93. package/dist/electron/renderer/assets/index-DZzB20Xf.css +0 -1
  94. package/dist/electron/renderer/assets/index-Dk0EQt0u.css +0 -1
  95. package/dist/electron/renderer/assets/index-DknLdADV.js +0 -63
  96. package/dist/electron/renderer/assets/index-DocuD8Lk.js +0 -64
  97. package/dist/electron/renderer/assets/index-DwRy5FqP.js +0 -62
  98. package/dist/electron/renderer/assets/index-DyU-xfd8.css +0 -1
  99. package/dist/electron/renderer/assets/index-GwC-JVUy.css +0 -1
  100. package/dist/electron/renderer/assets/index-JXrtTB1F.js +0 -63
  101. package/dist/electron/renderer/assets/index-Ocrdv8Lb.css +0 -1
  102. package/dist/electron/renderer/assets/index-R-HsWJ0K.js +0 -62
  103. package/dist/electron/renderer/assets/index-Ytah0wbZ.js +0 -62
  104. package/dist/electron/renderer/assets/index-ZVyXUshO.css +0 -1
  105. package/dist/electron/renderer/assets/index-Z_8dJn3i.js +0 -62
  106. package/dist/electron/renderer/assets/index-fehviker.js +0 -63
  107. package/dist/electron/renderer/assets/index-nts9ST-M.js +0 -62
  108. package/dist/electron/renderer/assets/index-q8NVIH3g.css +0 -1
  109. package/dist/electron/renderer/assets/index-thUWIXon.js +0 -62
  110. package/dist/electron/renderer/assets/index-tuQmrwcm.css +0 -1
  111. package/dist/prxi/src/index.tsx +0 -1370
@@ -54,6 +54,10 @@ function resolveCore() {
54
54
  if (cachedCore) {
55
55
  return cachedCore;
56
56
  }
57
+ // Try multiple locations to find the projax-core module
58
+ // 1. Local dist/core (copied during build)
59
+ // 2. Workspace root packages/core/dist (development)
60
+ // 3. Workspace alias 'projax-core' (resolved by pnpm via workspace:*)
57
61
  const candidates = [
58
62
  path.join(__dirname, 'core', 'index.js'),
59
63
  path.join(__dirname, 'core'),
@@ -61,7 +65,7 @@ function resolveCore() {
61
65
  path.join(__dirname, '..', '..', 'core', 'dist'),
62
66
  path.join(__dirname, '..', 'core', 'dist', 'index.js'),
63
67
  path.join(__dirname, '..', 'core', 'dist'),
64
- 'projax-core',
68
+ 'projax-core', // Workspace alias - pnpm resolves this to packages/core
65
69
  ];
66
70
  for (const candidate of candidates) {
67
71
  const mod = tryRequire(candidate);
@@ -39,16 +39,51 @@ const fs = __importStar(require("fs"));
39
39
  const http = __importStar(require("http"));
40
40
  const child_process_1 = require("child_process");
41
41
  const tail_1 = require("tail");
42
+ const url_1 = require("url");
43
+ // #region agent log
44
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:7', message: 'Importing core modules', data: { __dirname }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'F' }) }).catch(() => { });
45
+ // #endregion
42
46
  const core_1 = require("./core");
47
+ // #region agent log
48
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:16', message: 'Core modules imported successfully', data: {}, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'F' }) }).catch(() => { });
43
49
  let mainWindow = null;
44
50
  let apiProcess = null;
45
51
  const logWatchers = new Map();
52
+ function resolveCliDistModulePath(moduleFileName) {
53
+ const candidates = [
54
+ // When running from CLI bundle: dist/electron/main.js -> dist/...
55
+ path.join(__dirname, '..', moduleFileName),
56
+ path.join(__dirname, '..', 'packages', 'cli', 'src', moduleFileName),
57
+ // When running desktop in dev: packages/desktop/dist/main.js -> packages/cli/dist/...
58
+ path.join(__dirname, '..', '..', 'cli', 'dist', moduleFileName),
59
+ path.join(__dirname, '..', '..', 'cli', 'dist', 'packages', 'cli', 'src', moduleFileName),
60
+ ];
61
+ for (const candidate of candidates) {
62
+ if (fs.existsSync(candidate))
63
+ return candidate;
64
+ }
65
+ throw new Error(`Module not found: ${moduleFileName}. Tried:\n` +
66
+ candidates.map(p => `- ${p}`).join('\n'));
67
+ }
68
+ async function importCliDistModule(modulePath) {
69
+ // Use a file:// URL to avoid platform/path edge-cases in Node's ESM loader.
70
+ return await Promise.resolve(`${(0, url_1.pathToFileURL)(modulePath).href}`).then(s => __importStar(require(s)));
71
+ }
72
+ // #region agent log
73
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:23', message: 'Checking single instance lock', data: {}, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'E' }) }).catch(() => { });
74
+ // #endregion
46
75
  // Prevent multiple instances
47
76
  const gotTheLock = electron_1.app.requestSingleInstanceLock();
48
77
  if (!gotTheLock) {
78
+ // #region agent log
79
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:27', message: 'Single instance lock failed - another instance running', data: {}, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'E' }) }).catch(() => { });
80
+ // #endregion
49
81
  electron_1.app.quit();
50
82
  }
51
83
  else {
84
+ // #region agent log
85
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:30', message: 'Single instance lock acquired', data: {}, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'E' }) }).catch(() => { });
86
+ // #endregion
52
87
  electron_1.app.on('second-instance', () => {
53
88
  // Someone tried to run a second instance, focus our window instead
54
89
  if (mainWindow) {
@@ -58,12 +93,21 @@ else {
58
93
  }
59
94
  });
60
95
  function createWindow() {
96
+ // #region agent log
97
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:36', message: 'createWindow called', data: { hasMainWindow: !!mainWindow }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'B' }) }).catch(() => { });
98
+ // #endregion
61
99
  // Don't create a new window if one already exists
62
100
  if (mainWindow) {
101
+ // #region agent log
102
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:39', message: 'Window already exists, focusing', data: {}, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'B' }) }).catch(() => { });
103
+ // #endregion
63
104
  mainWindow.focus();
64
105
  return;
65
106
  }
66
107
  const isDev = process.env.NODE_ENV === 'development';
108
+ // #region agent log
109
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:45', message: 'Creating BrowserWindow', data: { isDev, __dirname }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'B' }) }).catch(() => { });
110
+ // #endregion
67
111
  mainWindow = new electron_1.BrowserWindow({
68
112
  width: 1200,
69
113
  height: 800,
@@ -80,23 +124,41 @@ else {
80
124
  });
81
125
  // Show window when ready to prevent white screen flash
82
126
  mainWindow.once('ready-to-show', () => {
127
+ // #region agent log
128
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:63', message: 'Window ready-to-show event fired', data: {}, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'B' }) }).catch(() => { });
129
+ // #endregion
83
130
  mainWindow?.show();
84
131
  });
85
132
  // Load the app
86
133
  if (isDev) {
134
+ // #region agent log
135
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:67', message: 'Dev mode: checking Vite server', data: { port: 7898 }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'C' }) }).catch(() => { });
136
+ // #endregion
87
137
  // Wait for Vite dev server to be ready before loading
88
138
  const checkServerAndLoad = (retries = 10) => {
139
+ // #region agent log
140
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:70', message: 'Checking Vite server availability', data: { retries }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'C' }) }).catch(() => { });
141
+ // #endregion
89
142
  const req = http.get('http://localhost:7898', (res) => {
143
+ // #region agent log
144
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:72', message: 'Vite server is ready', data: { statusCode: res.statusCode }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'C' }) }).catch(() => { });
145
+ // #endregion
90
146
  console.log('Vite dev server is ready!');
91
147
  mainWindow?.loadURL('http://localhost:7898');
92
148
  mainWindow?.webContents.openDevTools();
93
149
  });
94
150
  req.on('error', (error) => {
151
+ // #region agent log
152
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:76', message: 'Vite server check error', data: { error: error.message, retries }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'C' }) }).catch(() => { });
153
+ // #endregion
95
154
  if (retries > 0) {
96
155
  console.log(`Vite dev server not ready (${retries} retries left), retrying in 1 second...`);
97
156
  setTimeout(() => checkServerAndLoad(retries - 1), 1000);
98
157
  }
99
158
  else {
159
+ // #region agent log
160
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:82', message: 'Vite server connection failed after all retries', data: { error: error.message }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'C' }) }).catch(() => { });
161
+ // #endregion
100
162
  console.error('Failed to connect to Vite dev server after multiple retries');
101
163
  console.error('Make sure Vite is running on port 7898');
102
164
  mainWindow?.loadURL('http://localhost:7898'); // Try anyway
@@ -134,6 +196,13 @@ else {
134
196
  electron_1.app.quit();
135
197
  }
136
198
  }
199
+ // Prevent navigation on file drops (prevents default file:// protocol navigation)
200
+ mainWindow.webContents.on('will-navigate', (event, url) => {
201
+ // Allow navigation only to localhost (dev server) or file:// (local renderer)
202
+ if (!url.startsWith('http://localhost') && !url.startsWith('file://')) {
203
+ event.preventDefault();
204
+ }
205
+ });
137
206
  // Handle external links securely
138
207
  mainWindow.webContents.setWindowOpenHandler(({ url }) => {
139
208
  // Only allow http/https links to be opened externally for security
@@ -195,6 +264,9 @@ else {
195
264
  }
196
265
  // Start API server
197
266
  function startAPIServer() {
267
+ // #region agent log
268
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:187', message: 'startAPIServer called', data: { __dirname, processCwd: process.cwd() }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'D' }) }).catch(() => { });
269
+ // #endregion
198
270
  try {
199
271
  // Try to find API server in various locations
200
272
  const apiPaths = [
@@ -202,14 +274,24 @@ else {
202
274
  path.join(__dirname, '..', '..', 'api', 'dist', 'index.js'),
203
275
  path.join(process.cwd(), 'packages', 'api', 'dist', 'index.js'),
204
276
  ];
277
+ // #region agent log
278
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:196', message: 'Checking API paths', data: { apiPaths, __dirname }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'D' }) }).catch(() => { });
279
+ // #endregion
205
280
  let apiPath = null;
206
281
  for (const p of apiPaths) {
207
- if (fs.existsSync(p)) {
282
+ const exists = fs.existsSync(p);
283
+ // #region agent log
284
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:199', message: 'Checking API path', data: { path: p, exists }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'D' }) }).catch(() => { });
285
+ // #endregion
286
+ if (exists) {
208
287
  apiPath = p;
209
288
  break;
210
289
  }
211
290
  }
212
291
  if (!apiPath) {
292
+ // #region agent log
293
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:205', message: 'API server not found', data: { checkedPaths: apiPaths }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'D' }) }).catch(() => { });
294
+ // #endregion
213
295
  console.warn('API server not found. Some features may not work.');
214
296
  return;
215
297
  }
@@ -220,12 +302,18 @@ else {
220
302
  apiProcess.kill();
221
303
  apiProcess = null;
222
304
  }
305
+ // #region agent log
306
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:216', message: 'Spawning API server process', data: { apiPath, cwd: path.dirname(apiPath) }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'D' }) }).catch(() => { });
307
+ // #endregion
223
308
  apiProcess = (0, child_process_1.spawn)('node', [apiPath], {
224
309
  detached: false,
225
310
  stdio: 'pipe',
226
311
  env: { ...process.env },
227
312
  cwd: path.dirname(apiPath),
228
313
  });
314
+ // #region agent log
315
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:222', message: 'API server process spawned', data: { pid: apiProcess.pid }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'D' }) }).catch(() => { });
316
+ // #endregion
229
317
  apiProcess.stdout?.on('data', (data) => {
230
318
  console.log(`[API] ${data.toString().trim()}`);
231
319
  });
@@ -245,10 +333,18 @@ else {
245
333
  });
246
334
  }
247
335
  catch (error) {
336
+ // #region agent log
337
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:243', message: 'API server startup error', data: { error: error instanceof Error ? error.message : String(error) }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'D' }) }).catch(() => { });
338
+ // #endregion
248
339
  console.error('Failed to start API server:', error);
249
340
  }
250
341
  }
342
+ // Set app name for menu bar (macOS)
343
+ electron_1.app.setName('PROJAX');
251
344
  electron_1.app.whenReady().then(() => {
345
+ // #region agent log
346
+ fetch('http://127.0.0.1:7242/ingest/6c072a46-f01e-4db0-a457-6218bdb7cec6', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'main.ts:247', message: 'App whenReady fired', data: {}, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'A' }) }).catch(() => { });
347
+ // #endregion
252
348
  startAPIServer();
253
349
  createWindow();
254
350
  electron_1.app.on('activate', () => {
@@ -386,18 +482,8 @@ electron_1.ipcMain.handle('rename-project', async (_, projectId, newName) => {
386
482
  });
387
483
  // Get project scripts
388
484
  electron_1.ipcMain.handle('get-project-scripts', async (_, projectPath) => {
389
- // Try bundled path first (when bundled in CLI: dist/electron/main.js -> dist/script-runner.js)
390
- // Then try local dev path (packages/desktop/dist/main.js -> packages/cli/dist/script-runner.js)
391
- const bundledScriptRunnerPath = path.join(__dirname, '..', 'script-runner.js');
392
- const localScriptRunnerPath = path.join(__dirname, '..', '..', 'cli', 'dist', 'script-runner.js');
393
- let scriptRunnerPath;
394
- if (fs.existsSync(bundledScriptRunnerPath)) {
395
- scriptRunnerPath = bundledScriptRunnerPath;
396
- }
397
- else {
398
- scriptRunnerPath = localScriptRunnerPath;
399
- }
400
- const { getProjectScripts } = await Promise.resolve(`${scriptRunnerPath}`).then(s => __importStar(require(s)));
485
+ const scriptRunnerPath = resolveCliDistModulePath('script-runner.js');
486
+ const { getProjectScripts } = await importCliDistModule(scriptRunnerPath);
401
487
  const result = getProjectScripts(projectPath);
402
488
  // Convert Map to array for IPC serialization
403
489
  const scriptsArray = Array.from(result.scripts.entries()).map(([name, script]) => ({
@@ -412,21 +498,8 @@ electron_1.ipcMain.handle('get-project-scripts', async (_, projectPath) => {
412
498
  // Run script
413
499
  electron_1.ipcMain.handle('run-script', async (_, projectPath, scriptName, args = [], background = false) => {
414
500
  try {
415
- // Try bundled path first (when bundled in CLI: dist/electron/main.js -> dist/script-runner.js)
416
- // Then try local dev path (packages/desktop/dist/main.js -> packages/cli/dist/script-runner.js)
417
- const bundledScriptRunnerPath = path.join(__dirname, '..', 'script-runner.js');
418
- const localScriptRunnerPath = path.join(__dirname, '..', '..', 'cli', 'dist', 'script-runner.js');
419
- let scriptRunnerPath;
420
- if (fs.existsSync(bundledScriptRunnerPath)) {
421
- scriptRunnerPath = bundledScriptRunnerPath;
422
- }
423
- else if (fs.existsSync(localScriptRunnerPath)) {
424
- scriptRunnerPath = localScriptRunnerPath;
425
- }
426
- else {
427
- throw new Error(`Script runner not found. Tried: ${bundledScriptRunnerPath} and ${localScriptRunnerPath}`);
428
- }
429
- const scriptRunnerModule = await Promise.resolve(`${scriptRunnerPath}`).then(s => __importStar(require(s)));
501
+ const scriptRunnerPath = resolveCliDistModulePath('script-runner.js');
502
+ const scriptRunnerModule = await importCliDistModule(scriptRunnerPath);
430
503
  const { runScriptInBackground } = scriptRunnerModule;
431
504
  if (!runScriptInBackground || typeof runScriptInBackground !== 'function') {
432
505
  throw new Error('runScriptInBackground function not found in script runner module');
@@ -447,35 +520,15 @@ electron_1.ipcMain.handle('run-script', async (_, projectPath, scriptName, args
447
520
  });
448
521
  // Scan ports
449
522
  electron_1.ipcMain.handle('scan-project-ports', async (_, projectId) => {
450
- // Try bundled path first (when bundled in CLI: dist/electron/main.js -> dist/port-scanner.js)
451
- // Then try local dev path (packages/desktop/dist/main.js -> packages/cli/dist/port-scanner.js)
452
- const bundledPortScannerPath = path.join(__dirname, '..', 'port-scanner.js');
453
- const localPortScannerPath = path.join(__dirname, '..', '..', 'cli', 'dist', 'port-scanner.js');
454
- let portScannerPath;
455
- if (fs.existsSync(bundledPortScannerPath)) {
456
- portScannerPath = bundledPortScannerPath;
457
- }
458
- else {
459
- portScannerPath = localPortScannerPath;
460
- }
461
- const { scanProjectPorts } = await Promise.resolve(`${portScannerPath}`).then(s => __importStar(require(s)));
523
+ const portScannerPath = resolveCliDistModulePath('port-scanner.js');
524
+ const { scanProjectPorts } = await importCliDistModule(portScannerPath);
462
525
  await scanProjectPorts(projectId);
463
526
  const db = (0, core_1.getDatabaseManager)();
464
527
  return db.getProjectPorts(projectId);
465
528
  });
466
529
  electron_1.ipcMain.handle('scan-all-ports', async () => {
467
- // Try bundled path first (when bundled in CLI: dist/electron/main.js -> dist/port-scanner.js)
468
- // Then try local dev path (packages/desktop/dist/main.js -> packages/cli/dist/port-scanner.js)
469
- const bundledPortScannerPath = path.join(__dirname, '..', 'port-scanner.js');
470
- const localPortScannerPath = path.join(__dirname, '..', '..', 'cli', 'dist', 'port-scanner.js');
471
- let portScannerPath;
472
- if (fs.existsSync(bundledPortScannerPath)) {
473
- portScannerPath = bundledPortScannerPath;
474
- }
475
- else {
476
- portScannerPath = localPortScannerPath;
477
- }
478
- const { scanAllProjectPorts } = await Promise.resolve(`${portScannerPath}`).then(s => __importStar(require(s)));
530
+ const portScannerPath = resolveCliDistModulePath('port-scanner.js');
531
+ const { scanAllProjectPorts } = await importCliDistModule(portScannerPath);
479
532
  await scanAllProjectPorts();
480
533
  const db = (0, core_1.getDatabaseManager)();
481
534
  const projects = (0, core_1.getAllProjects)();
@@ -492,50 +545,20 @@ electron_1.ipcMain.handle('get-project-ports', async (_, projectId) => {
492
545
  });
493
546
  // Get running processes
494
547
  electron_1.ipcMain.handle('get-running-processes', async () => {
495
- // Try bundled path first (when bundled in CLI: dist/electron/main.js -> dist/script-runner.js)
496
- // Then try local dev path (packages/desktop/dist/main.js -> packages/cli/dist/script-runner.js)
497
- const bundledScriptRunnerPath = path.join(__dirname, '..', 'script-runner.js');
498
- const localScriptRunnerPath = path.join(__dirname, '..', '..', 'cli', 'dist', 'script-runner.js');
499
- let scriptRunnerPath;
500
- if (fs.existsSync(bundledScriptRunnerPath)) {
501
- scriptRunnerPath = bundledScriptRunnerPath;
502
- }
503
- else {
504
- scriptRunnerPath = localScriptRunnerPath;
505
- }
506
- const { getRunningProcessesClean } = await Promise.resolve(`${scriptRunnerPath}`).then(s => __importStar(require(s)));
548
+ const scriptRunnerPath = resolveCliDistModulePath('script-runner.js');
549
+ const { getRunningProcessesClean } = await importCliDistModule(scriptRunnerPath);
507
550
  return await getRunningProcessesClean();
508
551
  });
509
552
  // Stop script by PID
510
553
  electron_1.ipcMain.handle('stop-script', async (_, pid) => {
511
- // Try bundled path first (when bundled in CLI: dist/electron/main.js -> dist/script-runner.js)
512
- // Then try local dev path (packages/desktop/dist/main.js -> packages/cli/dist/script-runner.js)
513
- const bundledScriptRunnerPath = path.join(__dirname, '..', 'script-runner.js');
514
- const localScriptRunnerPath = path.join(__dirname, '..', '..', 'cli', 'dist', 'script-runner.js');
515
- let scriptRunnerPath;
516
- if (fs.existsSync(bundledScriptRunnerPath)) {
517
- scriptRunnerPath = bundledScriptRunnerPath;
518
- }
519
- else {
520
- scriptRunnerPath = localScriptRunnerPath;
521
- }
522
- const { stopScript } = await Promise.resolve(`${scriptRunnerPath}`).then(s => __importStar(require(s)));
554
+ const scriptRunnerPath = resolveCliDistModulePath('script-runner.js');
555
+ const { stopScript } = await importCliDistModule(scriptRunnerPath);
523
556
  return await stopScript(pid);
524
557
  });
525
558
  // Stop all processes for a project
526
559
  electron_1.ipcMain.handle('stop-project', async (_, projectPath) => {
527
- // Try bundled path first (when bundled in CLI: dist/electron/main.js -> dist/script-runner.js)
528
- // Then try local dev path (packages/desktop/dist/main.js -> packages/cli/dist/script-runner.js)
529
- const bundledScriptRunnerPath = path.join(__dirname, '..', 'script-runner.js');
530
- const localScriptRunnerPath = path.join(__dirname, '..', '..', 'cli', 'dist', 'script-runner.js');
531
- let scriptRunnerPath;
532
- if (fs.existsSync(bundledScriptRunnerPath)) {
533
- scriptRunnerPath = bundledScriptRunnerPath;
534
- }
535
- else {
536
- scriptRunnerPath = localScriptRunnerPath;
537
- }
538
- const { stopProjectProcesses } = await Promise.resolve(`${scriptRunnerPath}`).then(s => __importStar(require(s)));
560
+ const scriptRunnerPath = resolveCliDistModulePath('script-runner.js');
561
+ const { stopProjectProcesses } = await importCliDistModule(scriptRunnerPath);
539
562
  return await stopProjectProcesses(projectPath);
540
563
  });
541
564
  // Open URL in browser
@@ -835,17 +858,8 @@ electron_1.ipcMain.on('open-external-url', (event, url) => {
835
858
  // Watch process output
836
859
  electron_1.ipcMain.handle('watch-process-output', async (_, pid) => {
837
860
  try {
838
- // Try bundled path first
839
- const bundledScriptRunnerPath = path.join(__dirname, '..', 'script-runner.js');
840
- const localScriptRunnerPath = path.join(__dirname, '..', '..', 'cli', 'dist', 'script-runner.js');
841
- let scriptRunnerPath;
842
- if (fs.existsSync(bundledScriptRunnerPath)) {
843
- scriptRunnerPath = bundledScriptRunnerPath;
844
- }
845
- else {
846
- scriptRunnerPath = localScriptRunnerPath;
847
- }
848
- const { getRunningProcessesClean } = await Promise.resolve(`${scriptRunnerPath}`).then(s => __importStar(require(s)));
861
+ const scriptRunnerPath = resolveCliDistModulePath('script-runner.js');
862
+ const { getRunningProcessesClean } = await importCliDistModule(scriptRunnerPath);
849
863
  const processes = await getRunningProcessesClean();
850
864
  const process = processes.find((p) => p.pid === pid);
851
865
  if (!process || !process.logFile) {
@@ -88,6 +88,6 @@ function shouldRescanPorts(projectId) {
88
88
  }
89
89
  // Check if any port was detected 24 hours ago or older
90
90
  const twentyFourHoursAgo = Math.floor(Date.now() / 1000) - (24 * 60 * 60);
91
- const needsRescan = ports.some(port => (port.last_detected || 0) <= twentyFourHoursAgo);
91
+ const needsRescan = ports.some((port) => (port.last_detected || 0) <= twentyFourHoursAgo);
92
92
  return needsRescan;
93
93
  }