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.
- package/README.md +268 -268
- package/bin/cli-commands.js +34 -0
- package/bin/crewx-lib.js +213 -108
- package/bin/crewx-ui.js +83 -83
- package/bin/crewx.js +219 -147
- package/bin/launcher-flags.js +29 -0
- package/bin/package.json +1 -1
- package/dist/assets/{MarketPage-Dwsg6K-B.js → MarketPage-njRHlSSN.js} +1 -1
- package/dist/assets/{PromptTab-DVKc7hJY.js → PromptTab-CNyClpEe.js} +1 -1
- package/dist/assets/{_baseUniq-wjlVo2E6.js → _baseUniq-CGNNUfN7.js} +1 -1
- package/dist/assets/{arc-BfPgRtzW.js → arc-BEN-1A69.js} +1 -1
- package/dist/assets/{architectureDiagram-Q4EWVU46-ewcueFAG.js → architectureDiagram-Q4EWVU46-fAPvGzXk.js} +1 -1
- package/dist/assets/{blockDiagram-DXYQGD6D-TxlbbvKn.js → blockDiagram-DXYQGD6D-BWrb7uua.js} +1 -1
- package/dist/assets/{c4Diagram-AHTNJAMY-C1lT_bl_.js → c4Diagram-AHTNJAMY-CbnLz81q.js} +1 -1
- package/dist/assets/channel-uEnl63Ym.js +1 -0
- package/dist/assets/chatgpt-logo-dark.svg +15 -15
- package/dist/assets/chatgpt-logo.svg +15 -15
- package/dist/assets/{chunk-4BX2VUAB-C41j2mCL.js → chunk-4BX2VUAB-BopMVv1Q.js} +1 -1
- package/dist/assets/{chunk-4TB4RGXK-HNNsUbz0.js → chunk-4TB4RGXK-Axjc-DMR.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-qtCgO0r2.js → chunk-55IACEB6-BVzu25a2.js} +1 -1
- package/dist/assets/{chunk-EDXVE4YY-BSnDYtsd.js → chunk-EDXVE4YY-Csh0IKkY.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-DyHRLQqX.js → chunk-FMBD7UC4-D3yW6Ykv.js} +1 -1
- package/dist/assets/{chunk-OYMX7WX6-CCjfi6WS.js → chunk-OYMX7WX6-CDzLbKmY.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-COLty8kd.js → chunk-QZHKN3VN-CqYP7txP.js} +1 -1
- package/dist/assets/{chunk-YZCP3GAM-CHUUnGeN.js → chunk-YZCP3GAM-CIz2ApJG.js} +1 -1
- package/dist/assets/classDiagram-6PBFFD2Q-CU98S3yn.js +1 -0
- package/dist/assets/classDiagram-v2-HSJHXN6E-CU98S3yn.js +1 -0
- package/dist/assets/clone-D3Eqsbb8.js +1 -0
- package/dist/assets/{cose-bilkent-S5V4N54A-CSip-V2g.js → cose-bilkent-S5V4N54A-DgVG9_nb.js} +1 -1
- package/dist/assets/{dagre-KV5264BT-DkdpnWhv.js → dagre-KV5264BT-DnNIMI1A.js} +1 -1
- package/dist/assets/{diagram-5BDNPKRD-PH4qc6PV.js → diagram-5BDNPKRD-asGr2q6a.js} +1 -1
- package/dist/assets/{diagram-G4DWMVQ6-Cg5xZcjx.js → diagram-G4DWMVQ6-hwyZkwNx.js} +1 -1
- package/dist/assets/{diagram-MMDJMWI5-soKmeTCW.js → diagram-MMDJMWI5-BJbIxezj.js} +1 -1
- package/dist/assets/{diagram-TYMM5635-Daq5Mihu.js → diagram-TYMM5635-JB2YJBVu.js} +1 -1
- package/dist/assets/{erDiagram-SMLLAGMA-kr2OtY0Y.js → erDiagram-SMLLAGMA-i1KkUgG6.js} +1 -1
- package/dist/assets/{flowDiagram-DWJPFMVM-DQZCb8gm.js → flowDiagram-DWJPFMVM-62cwXjLB.js} +1 -1
- package/dist/assets/{ganttDiagram-T4ZO3ILL-BHkn485T.js → ganttDiagram-T4ZO3ILL-BDhku_zz.js} +1 -1
- package/dist/assets/{gitGraphDiagram-UUTBAWPF-FaCyYFmC.js → gitGraphDiagram-UUTBAWPF-DkHe0Kwk.js} +1 -1
- package/dist/assets/{graph-BVJlrP6V.js → graph-BnMMHCuQ.js} +1 -1
- package/dist/assets/{infoDiagram-42DDH7IO-DJOWkKdM.js → infoDiagram-42DDH7IO-V7zg8GAV.js} +1 -1
- package/dist/assets/{ishikawaDiagram-UXIWVN3A-VfpvNaIf.js → ishikawaDiagram-UXIWVN3A-CTtEO2wl.js} +1 -1
- package/dist/assets/{journeyDiagram-VCZTEJTY-CPzsak-v.js → journeyDiagram-VCZTEJTY-NxQMTN2m.js} +1 -1
- package/dist/assets/{kanban-definition-6JOO6SKY-DFqLDBU0.js → kanban-definition-6JOO6SKY-BHBrmGg3.js} +1 -1
- package/dist/assets/{layout-CCSbNPHm.js → layout-DutU1eng.js} +1 -1
- package/dist/assets/{linear-C4T7PCKE.js → linear-Czvrvocq.js} +1 -1
- package/dist/assets/{main-CELBpK6r.js → main-D0PuDE6-.js} +230 -226
- package/dist/assets/{min-CGQNEYGh.js → min-CI38XtLs.js} +1 -1
- package/dist/assets/{mindmap-definition-QFDTVHPH-AuU1EqwS.js → mindmap-definition-QFDTVHPH-CbFeHoxp.js} +1 -1
- package/dist/assets/{pieDiagram-DEJITSTG-CopkCZwp.js → pieDiagram-DEJITSTG-MV4uB5yA.js} +1 -1
- package/dist/assets/{quadrantDiagram-34T5L4WZ-lMKrSv_t.js → quadrantDiagram-34T5L4WZ-D0a8e2mx.js} +1 -1
- package/dist/assets/{requirementDiagram-MS252O5E-dWUpHOFb.js → requirementDiagram-MS252O5E-CeTlv4na.js} +1 -1
- package/dist/assets/{sankeyDiagram-XADWPNL6-C8UQx9Bb.js → sankeyDiagram-XADWPNL6-D1E3xq9q.js} +1 -1
- package/dist/assets/{sequenceDiagram-FGHM5R23-CUVNIItJ.js → sequenceDiagram-FGHM5R23-BO1RXtYs.js} +1 -1
- package/dist/assets/{stateDiagram-FHFEXIEX-Ct0GamGl.js → stateDiagram-FHFEXIEX-AhFKkuPE.js} +1 -1
- package/dist/assets/stateDiagram-v2-QKLJ7IA2-gv2g1MYi.js +1 -0
- package/dist/assets/{timeline-definition-GMOUNBTQ-ul8Po7f7.js → timeline-definition-GMOUNBTQ-BMVxUhID.js} +1 -1
- package/dist/assets/{vennDiagram-DHZGUBPP-B4AOWQnP.js → vennDiagram-DHZGUBPP-YFiJZns6.js} +1 -1
- package/dist/assets/{wardley-RL74JXVD-Dr7Wp3AJ.js → wardley-RL74JXVD-JlCdJekg.js} +1 -1
- package/dist/assets/{wardleyDiagram-NUSXRM2D-Ck70faXX.js → wardleyDiagram-NUSXRM2D-BLn2PZq9.js} +1 -1
- package/dist/assets/{xychartDiagram-5P7HB3ND-Bsy5-cNt.js → xychartDiagram-5P7HB3ND-DNOUK9or.js} +1 -1
- package/dist/index.html +12 -12
- package/dist-electron/main.js +153 -116
- package/dist-electron/overlay.js +102 -65
- package/dist-electron/package.json +1 -0
- package/dist-electron/preload.js +8 -8
- package/dist-server/bootstrap/crewx-server.js +19 -10
- package/dist-server/repository/box.repository.js +20 -20
- package/dist-server/repository/project.repository.js +13 -13
- package/dist-server/repository/request-log.repository.js +10 -10
- package/dist-server/repository/task.repository.js +72 -72
- package/dist-server/repository/thread.repository.js +57 -57
- package/package.json +6 -6
- package/packages/cli/dist/bootstrap/crewx-cli.js +12 -0
- package/packages/cli/dist/commands/agent.js +23 -23
- package/packages/cli/dist/commands/init.js +19 -19
- package/packages/cli/dist/commands/parse-common-flags.d.ts +19 -3
- package/packages/cli/dist/commands/parse-common-flags.js +46 -6
- package/packages/cli/dist/commands/registry.d.ts +13 -0
- package/packages/cli/dist/commands/registry.js +29 -0
- package/packages/cli/dist/commands/task-db.js +7 -7
- package/packages/cli/dist/examples/deny-secrets-plugin.d.ts +22 -0
- package/packages/cli/dist/examples/deny-secrets-plugin.js +40 -0
- package/packages/cli/dist/main.js +134 -68
- package/packages/cli/dist/plugins/examples/echo-hook.d.ts +24 -0
- package/packages/cli/dist/plugins/examples/echo-hook.js +60 -0
- package/packages/cli/dist/plugins/examples/verify-echo-hook.d.ts +8 -0
- package/packages/cli/dist/plugins/examples/verify-echo-hook.js +47 -0
- package/packages/cli/dist/plugins/sqlite-tracing.d.ts +11 -0
- package/packages/cli/dist/plugins/sqlite-tracing.js +19 -0
- package/packages/cli/dist/schema/tasks.d.ts +7 -0
- package/packages/cli/dist/schema/tasks.js +48 -0
- package/packages/cli/package.json +52 -52
- package/scripts/build-manual.mjs +266 -266
- package/scripts/emit-dist-server-package-json.mjs +7 -7
- package/scripts/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/scripts/postinstall.mjs +44 -44
- package/scripts/smoke-tarball.mjs +285 -285
- package/scripts/snapshot-msg-list.sh +52 -52
- package/server.js +167 -164
- package/dist/assets/channel-BP4PNMmz.js +0 -1
- package/dist/assets/classDiagram-6PBFFD2Q-Upr3UAcM.js +0 -1
- package/dist/assets/classDiagram-v2-HSJHXN6E-Upr3UAcM.js +0 -1
- package/dist/assets/clone-B8BP7ReZ.js +0 -1
- package/dist/assets/stateDiagram-v2-QKLJ7IA2-CFBLQDEx.js +0 -1
- package/dist-server/domain/task/dto/project-usage.dto.js +0 -38
- package/dist-server/domain/thread/dto/send-message.dto.js +0 -10
package/dist-electron/main.js
CHANGED
|
@@ -1,157 +1,194 @@
|
|
|
1
|
-
import { ipcMain
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
|
61
|
-
|
|
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:
|
|
66
|
+
icon: path.join(projectRoot, "public", "assets", "crewx-icon-256.png"),
|
|
67
67
|
webPreferences: {
|
|
68
|
-
nodeIntegration:
|
|
69
|
-
contextIsolation:
|
|
70
|
-
preload:
|
|
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:
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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:
|
|
83
|
-
|
|
84
|
-
|
|
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
|
|
91
|
+
x,
|
|
87
92
|
y: 40,
|
|
88
|
-
transparent:
|
|
89
|
-
alwaysOnTop:
|
|
90
|
-
frame:
|
|
91
|
-
hasShadow:
|
|
92
|
-
skipTaskbar:
|
|
93
|
-
resizable:
|
|
93
|
+
transparent: true,
|
|
94
|
+
alwaysOnTop: true,
|
|
95
|
+
frame: false,
|
|
96
|
+
hasShadow: false,
|
|
97
|
+
skipTaskbar: true,
|
|
98
|
+
resizable: false,
|
|
94
99
|
webPreferences: {
|
|
95
|
-
nodeIntegration:
|
|
96
|
-
contextIsolation:
|
|
97
|
-
preload:
|
|
100
|
+
nodeIntegration: false,
|
|
101
|
+
contextIsolation: true,
|
|
102
|
+
preload: path.join(__dirname$1, "preload.mjs")
|
|
98
103
|
},
|
|
99
104
|
backgroundColor: "#00000000",
|
|
100
|
-
show:
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
})
|
|
106
|
-
|
|
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
|
-
|
|
110
|
-
|
|
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
|
-
|
|
113
|
-
|
|
133
|
+
ipcMain.on("overlay:close", () => {
|
|
134
|
+
overlayWindow == null ? void 0 : overlayWindow.hide();
|
|
114
135
|
});
|
|
115
|
-
|
|
116
|
-
|
|
136
|
+
ipcMain.on("overlay:move", (_event, { x, y }) => {
|
|
137
|
+
overlayWindow == null ? void 0 : overlayWindow.setPosition(Math.round(x), Math.round(y));
|
|
117
138
|
});
|
|
118
|
-
|
|
119
|
-
const
|
|
139
|
+
ipcMain.handle("capture-screen", async () => {
|
|
140
|
+
const wasVisible = (overlayWindow == null ? void 0 : overlayWindow.isVisible()) ?? false;
|
|
120
141
|
try {
|
|
121
|
-
|
|
122
|
-
|
|
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
|
-
|
|
127
|
-
|
|
128
|
-
|
|
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
|
-
|
|
157
|
+
if (wasVisible) overlayWindow == null ? void 0 : overlayWindow.show();
|
|
131
158
|
}
|
|
132
159
|
});
|
|
133
|
-
async function
|
|
134
|
-
var r;
|
|
160
|
+
async function bootstrap() {
|
|
135
161
|
try {
|
|
136
162
|
if (process.platform === "darwin") {
|
|
137
|
-
const
|
|
138
|
-
|
|
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
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
-
|
|
146
|
-
|
|
147
|
-
process.platform !== "darwin"
|
|
175
|
+
app.whenReady().then(bootstrap);
|
|
176
|
+
app.on("window-all-closed", () => {
|
|
177
|
+
if (process.platform !== "darwin") {
|
|
178
|
+
app.quit();
|
|
179
|
+
}
|
|
148
180
|
});
|
|
149
|
-
|
|
150
|
-
|
|
181
|
+
app.on("will-quit", () => {
|
|
182
|
+
globalShortcut.unregisterAll();
|
|
151
183
|
});
|
|
152
|
-
|
|
153
|
-
|
|
184
|
+
app.on("before-quit", () => {
|
|
185
|
+
if (serverProcess) {
|
|
186
|
+
serverProcess.kill();
|
|
187
|
+
serverProcess = null;
|
|
188
|
+
}
|
|
154
189
|
});
|
|
155
|
-
|
|
156
|
-
|
|
190
|
+
app.on("activate", () => {
|
|
191
|
+
if (mainWindow === null) {
|
|
192
|
+
createWindow();
|
|
193
|
+
}
|
|
157
194
|
});
|
package/dist-electron/overlay.js
CHANGED
|
@@ -1,92 +1,129 @@
|
|
|
1
|
-
import { app
|
|
2
|
-
import
|
|
3
|
-
import { spawn
|
|
4
|
-
import { fileURLToPath
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
})
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
|
40
|
-
const { width:
|
|
41
|
-
|
|
42
|
-
|
|
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
|
|
66
|
+
x,
|
|
45
67
|
y: 40,
|
|
46
|
-
transparent:
|
|
47
|
-
alwaysOnTop:
|
|
48
|
-
frame:
|
|
49
|
-
hasShadow:
|
|
50
|
-
skipTaskbar:
|
|
51
|
-
resizable:
|
|
68
|
+
transparent: true,
|
|
69
|
+
alwaysOnTop: true,
|
|
70
|
+
frame: false,
|
|
71
|
+
hasShadow: false,
|
|
72
|
+
skipTaskbar: true,
|
|
73
|
+
resizable: false,
|
|
52
74
|
webPreferences: {
|
|
53
|
-
nodeIntegration:
|
|
54
|
-
contextIsolation:
|
|
55
|
-
preload:
|
|
75
|
+
nodeIntegration: false,
|
|
76
|
+
contextIsolation: true,
|
|
77
|
+
preload: path.join(__dirname$1, "preload.mjs")
|
|
56
78
|
},
|
|
57
79
|
backgroundColor: "#00000000",
|
|
58
|
-
show:
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
e == null || e.show();
|
|
63
|
-
}), e.on("closed", () => {
|
|
64
|
-
e = null;
|
|
87
|
+
overlayWindow.on("closed", () => {
|
|
88
|
+
overlayWindow = null;
|
|
65
89
|
});
|
|
66
90
|
}
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
71
|
-
|
|
100
|
+
ipcMain.on("overlay:close", () => {
|
|
101
|
+
app.quit();
|
|
72
102
|
});
|
|
73
|
-
|
|
74
|
-
|
|
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
|
|
106
|
+
async function bootstrap() {
|
|
77
107
|
try {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
115
|
+
app.whenReady().then(bootstrap);
|
|
116
|
+
app.on("window-all-closed", () => {
|
|
117
|
+
app.quit();
|
|
86
118
|
});
|
|
87
|
-
|
|
88
|
-
|
|
119
|
+
app.on("before-quit", () => {
|
|
120
|
+
if (serverProcess) {
|
|
121
|
+
serverProcess.kill();
|
|
122
|
+
serverProcess = null;
|
|
123
|
+
}
|
|
89
124
|
});
|
|
90
|
-
|
|
91
|
-
|
|
125
|
+
app.on("activate", () => {
|
|
126
|
+
if (overlayWindow === null && serverPort > 0) {
|
|
127
|
+
createOverlay();
|
|
128
|
+
}
|
|
92
129
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module","main":"main.js"}
|
package/dist-electron/preload.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { contextBridge
|
|
2
|
-
|
|
1
|
+
import { contextBridge, ipcRenderer } from "electron";
|
|
2
|
+
contextBridge.exposeInMainWorld("electron", {
|
|
3
3
|
platform: process.platform
|
|
4
4
|
});
|
|
5
|
-
|
|
6
|
-
move: (
|
|
7
|
-
close: () =>
|
|
8
|
-
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
|
-
|
|
11
|
-
captureScreen: () =>
|
|
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
|
|
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 (
|
|
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
|
-
|
|
43
|
-
|
|
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) {
|