crewx 0.8.1 → 0.8.2-rc.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 (106) hide show
  1. package/README.md +268 -268
  2. package/bin/cli-commands.js +34 -0
  3. package/bin/crewx-lib.js +213 -108
  4. package/bin/crewx-ui.js +83 -83
  5. package/bin/crewx.js +219 -147
  6. package/bin/launcher-flags.js +29 -0
  7. package/bin/package.json +1 -1
  8. package/dist/assets/{MarketPage-Dwsg6K-B.js → MarketPage-njRHlSSN.js} +1 -1
  9. package/dist/assets/{PromptTab-DVKc7hJY.js → PromptTab-CNyClpEe.js} +1 -1
  10. package/dist/assets/{_baseUniq-wjlVo2E6.js → _baseUniq-CGNNUfN7.js} +1 -1
  11. package/dist/assets/{arc-BfPgRtzW.js → arc-BEN-1A69.js} +1 -1
  12. package/dist/assets/{architectureDiagram-Q4EWVU46-ewcueFAG.js → architectureDiagram-Q4EWVU46-fAPvGzXk.js} +1 -1
  13. package/dist/assets/{blockDiagram-DXYQGD6D-TxlbbvKn.js → blockDiagram-DXYQGD6D-BWrb7uua.js} +1 -1
  14. package/dist/assets/{c4Diagram-AHTNJAMY-C1lT_bl_.js → c4Diagram-AHTNJAMY-CbnLz81q.js} +1 -1
  15. package/dist/assets/channel-uEnl63Ym.js +1 -0
  16. package/dist/assets/chatgpt-logo-dark.svg +15 -15
  17. package/dist/assets/chatgpt-logo.svg +15 -15
  18. package/dist/assets/{chunk-4BX2VUAB-C41j2mCL.js → chunk-4BX2VUAB-BopMVv1Q.js} +1 -1
  19. package/dist/assets/{chunk-4TB4RGXK-HNNsUbz0.js → chunk-4TB4RGXK-Axjc-DMR.js} +1 -1
  20. package/dist/assets/{chunk-55IACEB6-qtCgO0r2.js → chunk-55IACEB6-BVzu25a2.js} +1 -1
  21. package/dist/assets/{chunk-EDXVE4YY-BSnDYtsd.js → chunk-EDXVE4YY-Csh0IKkY.js} +1 -1
  22. package/dist/assets/{chunk-FMBD7UC4-DyHRLQqX.js → chunk-FMBD7UC4-D3yW6Ykv.js} +1 -1
  23. package/dist/assets/{chunk-OYMX7WX6-CCjfi6WS.js → chunk-OYMX7WX6-CDzLbKmY.js} +1 -1
  24. package/dist/assets/{chunk-QZHKN3VN-COLty8kd.js → chunk-QZHKN3VN-CqYP7txP.js} +1 -1
  25. package/dist/assets/{chunk-YZCP3GAM-CHUUnGeN.js → chunk-YZCP3GAM-CIz2ApJG.js} +1 -1
  26. package/dist/assets/classDiagram-6PBFFD2Q-CU98S3yn.js +1 -0
  27. package/dist/assets/classDiagram-v2-HSJHXN6E-CU98S3yn.js +1 -0
  28. package/dist/assets/clone-D3Eqsbb8.js +1 -0
  29. package/dist/assets/{cose-bilkent-S5V4N54A-CSip-V2g.js → cose-bilkent-S5V4N54A-DgVG9_nb.js} +1 -1
  30. package/dist/assets/{dagre-KV5264BT-DkdpnWhv.js → dagre-KV5264BT-DnNIMI1A.js} +1 -1
  31. package/dist/assets/{diagram-5BDNPKRD-PH4qc6PV.js → diagram-5BDNPKRD-asGr2q6a.js} +1 -1
  32. package/dist/assets/{diagram-G4DWMVQ6-Cg5xZcjx.js → diagram-G4DWMVQ6-hwyZkwNx.js} +1 -1
  33. package/dist/assets/{diagram-MMDJMWI5-soKmeTCW.js → diagram-MMDJMWI5-BJbIxezj.js} +1 -1
  34. package/dist/assets/{diagram-TYMM5635-Daq5Mihu.js → diagram-TYMM5635-JB2YJBVu.js} +1 -1
  35. package/dist/assets/{erDiagram-SMLLAGMA-kr2OtY0Y.js → erDiagram-SMLLAGMA-i1KkUgG6.js} +1 -1
  36. package/dist/assets/{flowDiagram-DWJPFMVM-DQZCb8gm.js → flowDiagram-DWJPFMVM-62cwXjLB.js} +1 -1
  37. package/dist/assets/{ganttDiagram-T4ZO3ILL-BHkn485T.js → ganttDiagram-T4ZO3ILL-BDhku_zz.js} +1 -1
  38. package/dist/assets/{gitGraphDiagram-UUTBAWPF-FaCyYFmC.js → gitGraphDiagram-UUTBAWPF-DkHe0Kwk.js} +1 -1
  39. package/dist/assets/{graph-BVJlrP6V.js → graph-BnMMHCuQ.js} +1 -1
  40. package/dist/assets/{infoDiagram-42DDH7IO-DJOWkKdM.js → infoDiagram-42DDH7IO-V7zg8GAV.js} +1 -1
  41. package/dist/assets/{ishikawaDiagram-UXIWVN3A-VfpvNaIf.js → ishikawaDiagram-UXIWVN3A-CTtEO2wl.js} +1 -1
  42. package/dist/assets/{journeyDiagram-VCZTEJTY-CPzsak-v.js → journeyDiagram-VCZTEJTY-NxQMTN2m.js} +1 -1
  43. package/dist/assets/{kanban-definition-6JOO6SKY-DFqLDBU0.js → kanban-definition-6JOO6SKY-BHBrmGg3.js} +1 -1
  44. package/dist/assets/{layout-CCSbNPHm.js → layout-DutU1eng.js} +1 -1
  45. package/dist/assets/{linear-C4T7PCKE.js → linear-Czvrvocq.js} +1 -1
  46. package/dist/assets/{main-CELBpK6r.js → main-D0PuDE6-.js} +230 -226
  47. package/dist/assets/{min-CGQNEYGh.js → min-CI38XtLs.js} +1 -1
  48. package/dist/assets/{mindmap-definition-QFDTVHPH-AuU1EqwS.js → mindmap-definition-QFDTVHPH-CbFeHoxp.js} +1 -1
  49. package/dist/assets/{pieDiagram-DEJITSTG-CopkCZwp.js → pieDiagram-DEJITSTG-MV4uB5yA.js} +1 -1
  50. package/dist/assets/{quadrantDiagram-34T5L4WZ-lMKrSv_t.js → quadrantDiagram-34T5L4WZ-D0a8e2mx.js} +1 -1
  51. package/dist/assets/{requirementDiagram-MS252O5E-dWUpHOFb.js → requirementDiagram-MS252O5E-CeTlv4na.js} +1 -1
  52. package/dist/assets/{sankeyDiagram-XADWPNL6-C8UQx9Bb.js → sankeyDiagram-XADWPNL6-D1E3xq9q.js} +1 -1
  53. package/dist/assets/{sequenceDiagram-FGHM5R23-CUVNIItJ.js → sequenceDiagram-FGHM5R23-BO1RXtYs.js} +1 -1
  54. package/dist/assets/{stateDiagram-FHFEXIEX-Ct0GamGl.js → stateDiagram-FHFEXIEX-AhFKkuPE.js} +1 -1
  55. package/dist/assets/stateDiagram-v2-QKLJ7IA2-gv2g1MYi.js +1 -0
  56. package/dist/assets/{timeline-definition-GMOUNBTQ-ul8Po7f7.js → timeline-definition-GMOUNBTQ-BMVxUhID.js} +1 -1
  57. package/dist/assets/{vennDiagram-DHZGUBPP-B4AOWQnP.js → vennDiagram-DHZGUBPP-YFiJZns6.js} +1 -1
  58. package/dist/assets/{wardley-RL74JXVD-Dr7Wp3AJ.js → wardley-RL74JXVD-JlCdJekg.js} +1 -1
  59. package/dist/assets/{wardleyDiagram-NUSXRM2D-Ck70faXX.js → wardleyDiagram-NUSXRM2D-BLn2PZq9.js} +1 -1
  60. package/dist/assets/{xychartDiagram-5P7HB3ND-Bsy5-cNt.js → xychartDiagram-5P7HB3ND-DNOUK9or.js} +1 -1
  61. package/dist/index.html +12 -12
  62. package/dist-electron/main.js +153 -116
  63. package/dist-electron/overlay.js +102 -65
  64. package/dist-electron/package.json +1 -0
  65. package/dist-electron/preload.js +8 -8
  66. package/dist-server/bootstrap/crewx-server.js +19 -10
  67. package/dist-server/repository/box.repository.js +20 -20
  68. package/dist-server/repository/project.repository.js +13 -13
  69. package/dist-server/repository/request-log.repository.js +10 -10
  70. package/dist-server/repository/task.repository.js +72 -72
  71. package/dist-server/repository/thread.repository.js +57 -57
  72. package/package.json +6 -6
  73. package/packages/cli/dist/bootstrap/crewx-cli.js +12 -0
  74. package/packages/cli/dist/commands/agent.js +23 -23
  75. package/packages/cli/dist/commands/init.js +19 -19
  76. package/packages/cli/dist/commands/parse-common-flags.d.ts +19 -3
  77. package/packages/cli/dist/commands/parse-common-flags.js +46 -6
  78. package/packages/cli/dist/commands/registry.d.ts +13 -0
  79. package/packages/cli/dist/commands/registry.js +29 -0
  80. package/packages/cli/dist/commands/task-db.js +7 -7
  81. package/packages/cli/dist/examples/deny-secrets-plugin.d.ts +22 -0
  82. package/packages/cli/dist/examples/deny-secrets-plugin.js +40 -0
  83. package/packages/cli/dist/main.js +134 -68
  84. package/packages/cli/dist/plugins/examples/echo-hook.d.ts +24 -0
  85. package/packages/cli/dist/plugins/examples/echo-hook.js +60 -0
  86. package/packages/cli/dist/plugins/examples/verify-echo-hook.d.ts +8 -0
  87. package/packages/cli/dist/plugins/examples/verify-echo-hook.js +47 -0
  88. package/packages/cli/dist/plugins/sqlite-tracing.d.ts +11 -0
  89. package/packages/cli/dist/plugins/sqlite-tracing.js +19 -0
  90. package/packages/cli/dist/schema/tasks.d.ts +7 -0
  91. package/packages/cli/dist/schema/tasks.js +48 -0
  92. package/packages/cli/package.json +52 -52
  93. package/scripts/build-manual.mjs +266 -266
  94. package/scripts/emit-dist-server-package-json.mjs +7 -7
  95. package/scripts/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  96. package/scripts/postinstall.mjs +44 -44
  97. package/scripts/smoke-tarball.mjs +285 -285
  98. package/scripts/snapshot-msg-list.sh +52 -52
  99. package/server.js +167 -164
  100. package/dist/assets/channel-BP4PNMmz.js +0 -1
  101. package/dist/assets/classDiagram-6PBFFD2Q-Upr3UAcM.js +0 -1
  102. package/dist/assets/classDiagram-v2-HSJHXN6E-Upr3UAcM.js +0 -1
  103. package/dist/assets/clone-B8BP7ReZ.js +0 -1
  104. package/dist/assets/stateDiagram-v2-QKLJ7IA2-CFBLQDEx.js +0 -1
  105. package/dist-server/domain/task/dto/project-usage.dto.js +0 -38
  106. package/dist-server/domain/thread/dto/send-message.dto.js +0 -10
@@ -1,157 +1,194 @@
1
- import { ipcMain as u, desktopCapturer as R, app as c, globalShortcut as j, nativeImage as I, BrowserWindow as y, screen as T } from "electron";
2
- import a from "path";
3
- import k from "fs";
4
- import { spawn as g } from "child_process";
5
- import { fileURLToPath as C } from "url";
6
- const U = C(import.meta.url), m = a.dirname(U), D = a.join(m, "..");
7
- let i = null, e = null, h = 0, n = null;
8
- async function L() {
9
- return new Promise((r, t) => {
10
- var b, P;
11
- const o = a.join(m, ".."), d = a.join(o, "dist-server", "src", "server", "main.js"), x = a.join(o, "src", "server", "main.ts"), S = !k.existsSync(d), v = S ? x : d, f = {
12
- ...process.env,
13
- PORT: "0",
14
- // Random port
15
- ELECTRON_MODE: "true",
16
- // Enable static file serving
17
- SERVE_STATIC: "true"
18
- };
19
- if (S) {
20
- const s = process.platform === "win32", l = `node --import @swc-node/register/esm-register "${v}"`;
21
- if (s)
22
- n = g("cmd.exe", ["/c", l], {
23
- cwd: o,
24
- env: f,
25
- stdio: ["pipe", "pipe", "pipe"]
26
- });
27
- else {
28
- const p = process.env.SHELL || "/bin/zsh";
29
- n = g(p, ["-i", "-c", l], {
30
- cwd: o,
31
- env: f,
32
- stdio: ["pipe", "pipe", "pipe"]
33
- });
1
+ import { ipcMain, desktopCapturer, app, globalShortcut, nativeImage, BrowserWindow, screen } from "electron";
2
+ import path from "path";
3
+ import { spawn } from "child_process";
4
+ import { fileURLToPath } from "url";
5
+ const __filename$1 = fileURLToPath(import.meta.url);
6
+ const __dirname$1 = path.dirname(__filename$1);
7
+ const projectRoot = path.join(__dirname$1, "..");
8
+ let mainWindow = null;
9
+ let overlayWindow = null;
10
+ let serverPort = 0;
11
+ let serverProcess = null;
12
+ async function startNestServer() {
13
+ return new Promise((resolve, reject) => {
14
+ var _a, _b;
15
+ const isDev = process.env.NODE_ENV !== "production";
16
+ const projectRoot2 = path.join(__dirname$1, "..");
17
+ const serverScript = isDev ? path.join(projectRoot2, "src", "server", "main.ts") : path.join(projectRoot2, "dist-server", "main.js");
18
+ const nodeCmd = isDev ? `node --import @swc-node/register/esm-register "${serverScript}"` : `node "${serverScript}"`;
19
+ const shell = process.env.SHELL || "/bin/zsh";
20
+ serverProcess = spawn(shell, ["-i", "-c", nodeCmd], {
21
+ cwd: projectRoot2,
22
+ env: {
23
+ ...process.env,
24
+ PORT: "0",
25
+ // Random port
26
+ ELECTRON_MODE: "true"
27
+ // Enable static file serving
28
+ },
29
+ stdio: ["pipe", "pipe", "pipe"]
30
+ });
31
+ (_a = serverProcess.stdout) == null ? void 0 : _a.on("data", (data) => {
32
+ const output = data.toString();
33
+ console.log("[Server]", output);
34
+ const portMatch = output.match(/localhost:(\d+)|port\s*:?\s*(\d+)/i);
35
+ if (portMatch) {
36
+ const port = parseInt(portMatch[1] || portMatch[2], 10);
37
+ if (port > 0) {
38
+ serverPort = port;
39
+ resolve(port);
40
+ }
34
41
  }
35
- } else
36
- n = g(process.execPath, [v], {
37
- cwd: o,
38
- env: f,
39
- stdio: ["pipe", "pipe", "pipe"]
40
- });
41
- (b = n.stdout) == null || b.on("data", (s) => {
42
- const l = s.toString();
43
- console.log("[Server]", l);
44
- const p = l.match(/localhost:(\d+)|port\s*:?\s*(\d+)/i);
45
- if (p) {
46
- const w = parseInt(p[1] || p[2], 10);
47
- w > 0 && (h = w, r(w));
42
+ });
43
+ (_b = serverProcess.stderr) == null ? void 0 : _b.on("data", (data) => {
44
+ console.error("[Server Error]", data.toString());
45
+ });
46
+ serverProcess.on("error", (err) => {
47
+ console.error("Failed to start server:", err);
48
+ reject(err);
49
+ });
50
+ serverProcess.on("exit", (code) => {
51
+ console.log(`Server process exited with code ${code}`);
52
+ });
53
+ setTimeout(() => {
54
+ if (serverPort === 0) {
55
+ reject(new Error("Server startup timeout"));
48
56
  }
49
- }), (P = n.stderr) == null || P.on("data", (s) => {
50
- console.error("[Server Error]", s.toString());
51
- }), n.on("error", (s) => {
52
- console.error("Failed to start server:", s), t(s);
53
- }), n.on("exit", (s) => {
54
- console.log(`Server process exited with code ${s}`);
55
- }), setTimeout(() => {
56
- h === 0 && t(new Error("Server startup timeout"));
57
57
  }, 3e4);
58
58
  });
59
59
  }
60
- function E() {
61
- i = new y({
60
+ function createWindow() {
61
+ mainWindow = new BrowserWindow({
62
62
  width: 1200,
63
63
  height: 800,
64
64
  minWidth: 1e3,
65
65
  minHeight: 700,
66
- icon: a.join(D, "public", "assets", "crewx-icon-256.png"),
66
+ icon: path.join(projectRoot, "public", "assets", "crewx-icon-256.png"),
67
67
  webPreferences: {
68
- nodeIntegration: !1,
69
- contextIsolation: !0,
70
- preload: a.join(m, "preload.mjs")
68
+ nodeIntegration: false,
69
+ contextIsolation: true,
70
+ preload: path.join(__dirname$1, "preload.mjs")
71
71
  },
72
72
  titleBarStyle: "hiddenInset",
73
73
  backgroundColor: "#F9FAFB",
74
- show: !1
75
- }), i.loadURL(`http://localhost:${h}`), i.once("ready-to-show", () => {
76
- i == null || i.show();
77
- }), i.on("closed", () => {
78
- i = null;
74
+ show: false
75
+ });
76
+ mainWindow.loadURL(`http://localhost:${serverPort}`);
77
+ mainWindow.once("ready-to-show", () => {
78
+ mainWindow == null ? void 0 : mainWindow.show();
79
+ });
80
+ mainWindow.on("closed", () => {
81
+ mainWindow = null;
79
82
  });
80
83
  }
81
- function _() {
82
- const { width: r } = T.getPrimaryDisplay().workAreaSize, t = 400, o = Math.round((r - t) / 2);
83
- e = new y({
84
- width: t,
84
+ function createOverlayWindow() {
85
+ const { width: screenWidth } = screen.getPrimaryDisplay().workAreaSize;
86
+ const winWidth = 400;
87
+ const x = Math.round((screenWidth - winWidth) / 2);
88
+ overlayWindow = new BrowserWindow({
89
+ width: winWidth,
85
90
  height: 60,
86
- x: o,
91
+ x,
87
92
  y: 40,
88
- transparent: !0,
89
- alwaysOnTop: !0,
90
- frame: !1,
91
- hasShadow: !1,
92
- skipTaskbar: !0,
93
- resizable: !1,
93
+ transparent: true,
94
+ alwaysOnTop: true,
95
+ frame: false,
96
+ hasShadow: false,
97
+ skipTaskbar: true,
98
+ resizable: false,
94
99
  webPreferences: {
95
- nodeIntegration: !1,
96
- contextIsolation: !0,
97
- preload: a.join(m, "preload.mjs")
100
+ nodeIntegration: false,
101
+ contextIsolation: true,
102
+ preload: path.join(__dirname$1, "preload.mjs")
98
103
  },
99
104
  backgroundColor: "#00000000",
100
- show: !1
101
- }), e.loadURL(`http://localhost:${h}/overlay.html`), e.once("ready-to-show", () => {
102
- e == null || e.show();
103
- }), e.on("closed", () => {
104
- e = null;
105
- }), j.register("CommandOrControl+Shift+Space", () => {
106
- e && (e.isVisible() ? e.hide() : (e.show(), e.focus()));
105
+ show: false
106
+ });
107
+ overlayWindow.loadURL(`http://localhost:${serverPort}/overlay.html`);
108
+ overlayWindow.once("ready-to-show", () => {
109
+ overlayWindow == null ? void 0 : overlayWindow.show();
110
+ });
111
+ overlayWindow.on("closed", () => {
112
+ overlayWindow = null;
113
+ });
114
+ globalShortcut.register("CommandOrControl+Shift+Space", () => {
115
+ if (!overlayWindow) return;
116
+ if (overlayWindow.isVisible()) {
117
+ overlayWindow.hide();
118
+ } else {
119
+ overlayWindow.show();
120
+ overlayWindow.focus();
121
+ }
107
122
  });
108
123
  }
109
- u.on("overlay:toggle", () => {
110
- e && (e.isVisible() ? e.hide() : (e.show(), e.focus()));
124
+ ipcMain.on("overlay:toggle", () => {
125
+ if (!overlayWindow) return;
126
+ if (overlayWindow.isVisible()) {
127
+ overlayWindow.hide();
128
+ } else {
129
+ overlayWindow.show();
130
+ overlayWindow.focus();
131
+ }
111
132
  });
112
- u.on("overlay:close", () => {
113
- e == null || e.hide();
133
+ ipcMain.on("overlay:close", () => {
134
+ overlayWindow == null ? void 0 : overlayWindow.hide();
114
135
  });
115
- u.on("overlay:move", (r, { x: t, y: o }) => {
116
- e == null || e.setPosition(Math.round(t), Math.round(o));
136
+ ipcMain.on("overlay:move", (_event, { x, y }) => {
137
+ overlayWindow == null ? void 0 : overlayWindow.setPosition(Math.round(x), Math.round(y));
117
138
  });
118
- u.handle("capture-screen", async () => {
119
- const r = (e == null ? void 0 : e.isVisible()) ?? !1;
139
+ ipcMain.handle("capture-screen", async () => {
140
+ const wasVisible = (overlayWindow == null ? void 0 : overlayWindow.isVisible()) ?? false;
120
141
  try {
121
- r && (e == null || e.hide()), await new Promise((d) => setTimeout(d, 150));
122
- const t = await R.getSources({
142
+ if (wasVisible) overlayWindow == null ? void 0 : overlayWindow.hide();
143
+ await new Promise((resolve) => setTimeout(resolve, 150));
144
+ const sources = await desktopCapturer.getSources({
123
145
  types: ["screen"],
124
146
  thumbnailSize: { width: 1920, height: 1080 }
125
147
  });
126
- return t.length === 0 ? { success: !1, imageDataUrl: "", timestamp: Date.now() } : { success: !0, imageDataUrl: t[0].thumbnail.toDataURL(), timestamp: Date.now() };
127
- } catch (t) {
128
- return console.error("[capture-screen] Error:", t), { success: !1, imageDataUrl: "", timestamp: Date.now() };
148
+ if (sources.length === 0) {
149
+ return { success: false, imageDataUrl: "", timestamp: Date.now() };
150
+ }
151
+ const imageDataUrl = sources[0].thumbnail.toDataURL();
152
+ return { success: true, imageDataUrl, timestamp: Date.now() };
153
+ } catch (error) {
154
+ console.error("[capture-screen] Error:", error);
155
+ return { success: false, imageDataUrl: "", timestamp: Date.now() };
129
156
  } finally {
130
- r && (e == null || e.show());
157
+ if (wasVisible) overlayWindow == null ? void 0 : overlayWindow.show();
131
158
  }
132
159
  });
133
- async function F() {
134
- var r;
160
+ async function bootstrap() {
135
161
  try {
136
162
  if (process.platform === "darwin") {
137
- const t = a.join(D, "public", "assets", "crewx-icon-512.png"), o = I.createFromPath(t);
138
- o.isEmpty() || (r = c.dock) == null || r.setIcon(o);
163
+ const iconPath = path.join(projectRoot, "public", "assets", "crewx-icon-512.png");
164
+ const icon = nativeImage.createFromPath(iconPath);
165
+ if (!icon.isEmpty()) app.dock.setIcon(icon);
139
166
  }
140
- h = await L(), E(), _();
141
- } catch (t) {
142
- console.error("Failed to start application:", t), c.quit();
167
+ serverPort = await startNestServer();
168
+ createWindow();
169
+ createOverlayWindow();
170
+ } catch (error) {
171
+ console.error("Failed to start application:", error);
172
+ app.quit();
143
173
  }
144
174
  }
145
- c.whenReady().then(F);
146
- c.on("window-all-closed", () => {
147
- process.platform !== "darwin" && c.quit();
175
+ app.whenReady().then(bootstrap);
176
+ app.on("window-all-closed", () => {
177
+ if (process.platform !== "darwin") {
178
+ app.quit();
179
+ }
148
180
  });
149
- c.on("will-quit", () => {
150
- j.unregisterAll();
181
+ app.on("will-quit", () => {
182
+ globalShortcut.unregisterAll();
151
183
  });
152
- c.on("before-quit", () => {
153
- n && (n.kill(), n = null);
184
+ app.on("before-quit", () => {
185
+ if (serverProcess) {
186
+ serverProcess.kill();
187
+ serverProcess = null;
188
+ }
154
189
  });
155
- c.on("activate", () => {
156
- i === null && E();
190
+ app.on("activate", () => {
191
+ if (mainWindow === null) {
192
+ createWindow();
193
+ }
157
194
  });
@@ -1,92 +1,129 @@
1
- import { app as t, ipcMain as u, screen as b, BrowserWindow as E } from "electron";
2
- import l from "path";
3
- import { spawn as P } from "child_process";
4
- import { fileURLToPath as _ } from "url";
5
- const j = _(import.meta.url), w = l.dirname(j);
6
- process.platform === "darwin" && t.disableHardwareAcceleration();
7
- let e = null, c = 0, r = null;
8
- async function M() {
9
- return new Promise((n, s) => {
10
- var m, f;
11
- const i = process.env.NODE_ENV !== "production", a = l.join(w, ".."), h = i ? l.join(a, "src", "server", "main.ts") : l.join(a, "dist-server", "main.js"), g = i ? `node --import @swc-node/register/esm-register "${h}"` : `node "${h}"`, S = process.env.SHELL || "/bin/zsh";
12
- r = P(S, ["-i", "-c", g], {
13
- cwd: a,
1
+ import { app, ipcMain, screen, BrowserWindow } from "electron";
2
+ import path from "path";
3
+ import { spawn } from "child_process";
4
+ import { fileURLToPath } from "url";
5
+ const __filename$1 = fileURLToPath(import.meta.url);
6
+ const __dirname$1 = path.dirname(__filename$1);
7
+ if (process.platform === "darwin") {
8
+ app.disableHardwareAcceleration();
9
+ }
10
+ let overlayWindow = null;
11
+ let serverPort = 0;
12
+ let serverProcess = null;
13
+ async function startNestServer() {
14
+ return new Promise((resolve, reject) => {
15
+ var _a, _b;
16
+ const isDev = process.env.NODE_ENV !== "production";
17
+ const projectRoot = path.join(__dirname$1, "..");
18
+ const serverScript = isDev ? path.join(projectRoot, "src", "server", "main.ts") : path.join(projectRoot, "dist-server", "main.js");
19
+ const nodeCmd = isDev ? `node --import @swc-node/register/esm-register "${serverScript}"` : `node "${serverScript}"`;
20
+ const shell = process.env.SHELL || "/bin/zsh";
21
+ serverProcess = spawn(shell, ["-i", "-c", nodeCmd], {
22
+ cwd: projectRoot,
14
23
  env: {
15
24
  ...process.env,
16
25
  PORT: "0",
17
26
  ELECTRON_MODE: "true"
18
27
  },
19
28
  stdio: ["pipe", "pipe", "pipe"]
20
- }), (m = r.stdout) == null || m.on("data", (o) => {
21
- const v = o.toString();
22
- console.log("[Server]", v);
23
- const d = v.match(/localhost:(\d+)|port\s*:?\s*(\d+)/i);
24
- if (d) {
25
- const p = parseInt(d[1] || d[2], 10);
26
- p > 0 && (c = p, n(p));
29
+ });
30
+ (_a = serverProcess.stdout) == null ? void 0 : _a.on("data", (data) => {
31
+ const output = data.toString();
32
+ console.log("[Server]", output);
33
+ const portMatch = output.match(/localhost:(\d+)|port\s*:?\s*(\d+)/i);
34
+ if (portMatch) {
35
+ const port = parseInt(portMatch[1] || portMatch[2], 10);
36
+ if (port > 0) {
37
+ serverPort = port;
38
+ resolve(port);
39
+ }
40
+ }
41
+ });
42
+ (_b = serverProcess.stderr) == null ? void 0 : _b.on("data", (data) => {
43
+ console.error("[Server Error]", data.toString());
44
+ });
45
+ serverProcess.on("error", (err) => {
46
+ console.error("Failed to start server:", err);
47
+ reject(err);
48
+ });
49
+ serverProcess.on("exit", (code) => {
50
+ console.log(`Server process exited with code ${code}`);
51
+ });
52
+ setTimeout(() => {
53
+ if (serverPort === 0) {
54
+ reject(new Error("Server startup timeout"));
27
55
  }
28
- }), (f = r.stderr) == null || f.on("data", (o) => {
29
- console.error("[Server Error]", o.toString());
30
- }), r.on("error", (o) => {
31
- console.error("Failed to start server:", o), s(o);
32
- }), r.on("exit", (o) => {
33
- console.log(`Server process exited with code ${o}`);
34
- }), setTimeout(() => {
35
- c === 0 && s(new Error("Server startup timeout"));
36
56
  }, 3e4);
37
57
  });
38
58
  }
39
- function y() {
40
- const { width: n } = b.getPrimaryDisplay().workAreaSize, s = 400, i = Math.round((n - s) / 2);
41
- e = new E({
42
- width: s,
59
+ function createOverlay() {
60
+ const { width: screenWidth } = screen.getPrimaryDisplay().workAreaSize;
61
+ const winWidth = 400;
62
+ const x = Math.round((screenWidth - winWidth) / 2);
63
+ overlayWindow = new BrowserWindow({
64
+ width: winWidth,
43
65
  height: 60,
44
- x: i,
66
+ x,
45
67
  y: 40,
46
- transparent: !0,
47
- alwaysOnTop: !0,
48
- frame: !1,
49
- hasShadow: !1,
50
- skipTaskbar: !0,
51
- resizable: !1,
68
+ transparent: true,
69
+ alwaysOnTop: true,
70
+ frame: false,
71
+ hasShadow: false,
72
+ skipTaskbar: true,
73
+ resizable: false,
52
74
  webPreferences: {
53
- nodeIntegration: !1,
54
- contextIsolation: !0,
55
- preload: l.join(w, "preload.mjs")
75
+ nodeIntegration: false,
76
+ contextIsolation: true,
77
+ preload: path.join(__dirname$1, "preload.mjs")
56
78
  },
57
79
  backgroundColor: "#00000000",
58
- show: !1
80
+ show: false
81
+ });
82
+ const overlayUrl = `http://localhost:${serverPort}/overlay.html`;
83
+ overlayWindow.loadURL(overlayUrl);
84
+ overlayWindow.once("ready-to-show", () => {
85
+ overlayWindow == null ? void 0 : overlayWindow.show();
59
86
  });
60
- const a = `http://localhost:${c}/overlay.html`;
61
- e.loadURL(a), e.once("ready-to-show", () => {
62
- e == null || e.show();
63
- }), e.on("closed", () => {
64
- e = null;
87
+ overlayWindow.on("closed", () => {
88
+ overlayWindow = null;
65
89
  });
66
90
  }
67
- u.on("overlay:toggle", () => {
68
- e && (e.isVisible() ? e.hide() : (e.show(), e.focus()));
91
+ ipcMain.on("overlay:toggle", () => {
92
+ if (!overlayWindow) return;
93
+ if (overlayWindow.isVisible()) {
94
+ overlayWindow.hide();
95
+ } else {
96
+ overlayWindow.show();
97
+ overlayWindow.focus();
98
+ }
69
99
  });
70
- u.on("overlay:close", () => {
71
- t.quit();
100
+ ipcMain.on("overlay:close", () => {
101
+ app.quit();
72
102
  });
73
- u.on("overlay:move", (n, { x: s, y: i }) => {
74
- e == null || e.setPosition(Math.round(s), Math.round(i));
103
+ ipcMain.on("overlay:move", (_event, { x, y }) => {
104
+ overlayWindow == null ? void 0 : overlayWindow.setPosition(Math.round(x), Math.round(y));
75
105
  });
76
- async function O() {
106
+ async function bootstrap() {
77
107
  try {
78
- c = await M(), y();
79
- } catch (n) {
80
- console.error("Failed to start overlay:", n), t.quit();
108
+ serverPort = await startNestServer();
109
+ createOverlay();
110
+ } catch (error) {
111
+ console.error("Failed to start overlay:", error);
112
+ app.quit();
81
113
  }
82
114
  }
83
- t.whenReady().then(O);
84
- t.on("window-all-closed", () => {
85
- t.quit();
115
+ app.whenReady().then(bootstrap);
116
+ app.on("window-all-closed", () => {
117
+ app.quit();
86
118
  });
87
- t.on("before-quit", () => {
88
- r && (r.kill(), r = null);
119
+ app.on("before-quit", () => {
120
+ if (serverProcess) {
121
+ serverProcess.kill();
122
+ serverProcess = null;
123
+ }
89
124
  });
90
- t.on("activate", () => {
91
- e === null && c > 0 && y();
125
+ app.on("activate", () => {
126
+ if (overlayWindow === null && serverPort > 0) {
127
+ createOverlay();
128
+ }
92
129
  });
@@ -0,0 +1 @@
1
+ {"type":"module","main":"main.js"}
@@ -1,12 +1,12 @@
1
- import { contextBridge as o, ipcRenderer as e } from "electron";
2
- o.exposeInMainWorld("electron", {
1
+ import { contextBridge, ipcRenderer } from "electron";
2
+ contextBridge.exposeInMainWorld("electron", {
3
3
  platform: process.platform
4
4
  });
5
- o.exposeInMainWorld("electronOverlay", {
6
- move: (r, n) => e.send("overlay:move", { x: r, y: n }),
7
- close: () => e.send("overlay:close"),
8
- toggle: () => e.send("overlay:toggle")
5
+ contextBridge.exposeInMainWorld("electronOverlay", {
6
+ move: (x, y) => ipcRenderer.send("overlay:move", { x, y }),
7
+ close: () => ipcRenderer.send("overlay:close"),
8
+ toggle: () => ipcRenderer.send("overlay:toggle")
9
9
  });
10
- o.exposeInMainWorld("electronAPI", {
11
- captureScreen: () => e.invoke("capture-screen")
10
+ contextBridge.exposeInMainWorld("electronAPI", {
11
+ captureScreen: () => ipcRenderer.invoke("capture-screen")
12
12
  });
@@ -25,22 +25,31 @@ const SERVER_VERSION = '0.1.0';
25
25
  * workspaceRoot used by FileLoggerPlugin: directory of the yaml when present,
26
26
  * otherwise process.cwd() so logs land in the launch directory.
27
27
  */
28
- async function createServerCrewx(configPath = process.env.CREWX_CONFIG ?? 'crewx.yaml') {
29
- const absConfigPath = (0, path_1.resolve)(configPath);
30
- const isExplicitConfig = Boolean(process.env.CREWX_CONFIG);
31
- const fileExists = (0, fs_1.existsSync)(absConfigPath);
28
+ async function createServerCrewx(configPath) {
32
29
  let yamlPath;
33
30
  let workspaceRoot;
34
- if (fileExists) {
31
+ if (configPath !== undefined) {
32
+ // Caller explicitly provided a path — trust it directly without existsSync
33
+ const absConfigPath = (0, path_1.resolve)(configPath);
35
34
  yamlPath = absConfigPath;
36
35
  workspaceRoot = (0, path_1.dirname)(absConfigPath);
37
36
  }
38
- else if (isExplicitConfig) {
39
- throw new Error(`[crewx] Config file not found: ${absConfigPath} (set via CREWX_CONFIG)`);
40
- }
41
37
  else {
42
- yamlPath = undefined;
43
- workspaceRoot = process.cwd();
38
+ // No explicit path — use env/default with existsSync fallback
39
+ const defaultPath = (0, path_1.resolve)(process.env.CREWX_CONFIG ?? 'crewx.yaml');
40
+ const isExplicitConfig = Boolean(process.env.CREWX_CONFIG);
41
+ const fileExists = (0, fs_1.existsSync)(defaultPath);
42
+ if (fileExists) {
43
+ yamlPath = defaultPath;
44
+ workspaceRoot = (0, path_1.dirname)(defaultPath);
45
+ }
46
+ else if (isExplicitConfig) {
47
+ throw new Error(`[crewx] Config file not found: ${defaultPath} (set via CREWX_CONFIG)`);
48
+ }
49
+ else {
50
+ yamlPath = undefined;
51
+ workspaceRoot = process.cwd();
52
+ }
44
53
  }
45
54
  const crewx = await sdk_1.Crewx.loadYaml(yamlPath, {
46
55
  remoteFactory: createServerCrewx,
@@ -20,12 +20,12 @@ let BoxRepository = class BoxRepository extends base_sqlite_repository_js_1.Base
20
20
  const db = this.openReadonly(dbPath);
21
21
  try {
22
22
  this.ensureThreadExists(db, threadId);
23
- return db.all(`
24
- SELECT id, thread_id, seq, first_task_id, mid_task_id, last_task_id,
25
- task_count, summary, source_tokens, summary_tokens, created_at
26
- FROM thread_boxes
27
- WHERE thread_id = ?
28
- ORDER BY seq ASC
23
+ return db.all(`
24
+ SELECT id, thread_id, seq, first_task_id, mid_task_id, last_task_id,
25
+ task_count, summary, source_tokens, summary_tokens, created_at
26
+ FROM thread_boxes
27
+ WHERE thread_id = ?
28
+ ORDER BY seq ASC
29
29
  `, [threadId]);
30
30
  }
31
31
  catch (error) {
@@ -48,11 +48,11 @@ let BoxRepository = class BoxRepository extends base_sqlite_repository_js_1.Base
48
48
  }
49
49
  const db = this.openReadonly(dbPath);
50
50
  try {
51
- const row = db.get(`
52
- SELECT id, thread_id, seq, first_task_id, mid_task_id, last_task_id,
53
- task_count, summary, source_tokens, summary_tokens, created_at
54
- FROM thread_boxes
55
- WHERE id = ? AND thread_id = ?
51
+ const row = db.get(`
52
+ SELECT id, thread_id, seq, first_task_id, mid_task_id, last_task_id,
53
+ task_count, summary, source_tokens, summary_tokens, created_at
54
+ FROM thread_boxes
55
+ WHERE id = ? AND thread_id = ?
56
56
  `, [boxId, threadId]);
57
57
  if (!row) {
58
58
  throw new common_1.NotFoundException(`Box not found: ${boxId} in thread: ${threadId}`);
@@ -81,11 +81,11 @@ let BoxRepository = class BoxRepository extends base_sqlite_repository_js_1.Base
81
81
  try {
82
82
  this.ensureThreadExists(db, threadId);
83
83
  try {
84
- db.run(`
85
- INSERT INTO thread_boxes
86
- (id, thread_id, seq, first_task_id, mid_task_id, last_task_id,
87
- task_count, summary, source_tokens, summary_tokens, created_at)
88
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
84
+ db.run(`
85
+ INSERT INTO thread_boxes
86
+ (id, thread_id, seq, first_task_id, mid_task_id, last_task_id,
87
+ task_count, summary, source_tokens, summary_tokens, created_at)
88
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
89
89
  `, [
90
90
  data.id,
91
91
  threadId,
@@ -106,10 +106,10 @@ let BoxRepository = class BoxRepository extends base_sqlite_repository_js_1.Base
106
106
  }
107
107
  throw error;
108
108
  }
109
- return db.get(`
110
- SELECT id, thread_id, seq, first_task_id, mid_task_id, last_task_id,
111
- task_count, summary, source_tokens, summary_tokens, created_at
112
- FROM thread_boxes WHERE id = ?
109
+ return db.get(`
110
+ SELECT id, thread_id, seq, first_task_id, mid_task_id, last_task_id,
111
+ task_count, summary, source_tokens, summary_tokens, created_at
112
+ FROM thread_boxes WHERE id = ?
113
113
  `, [data.id]);
114
114
  }
115
115
  catch (error) {