crewx 0.8.1 → 0.8.2-rc.2
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-DptjaFpT.js +36 -0
- package/dist/assets/{PromptTab-DVKc7hJY.js → PromptTab-DZha2_v1.js} +1 -1
- package/dist/assets/{_baseUniq-wjlVo2E6.js → _baseUniq-jd6NubI3.js} +1 -1
- package/dist/assets/{arc-BfPgRtzW.js → arc-C2te3-8P.js} +1 -1
- package/dist/assets/{architectureDiagram-Q4EWVU46-ewcueFAG.js → architectureDiagram-Q4EWVU46-CbIQua02.js} +1 -1
- package/dist/assets/{blockDiagram-DXYQGD6D-TxlbbvKn.js → blockDiagram-DXYQGD6D-Cg7qkpSM.js} +1 -1
- package/dist/assets/{c4Diagram-AHTNJAMY-C1lT_bl_.js → c4Diagram-AHTNJAMY-BkffDY1F.js} +1 -1
- package/dist/assets/channel-beae0DeI.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-BxHe9wPE.js} +1 -1
- package/dist/assets/{chunk-4TB4RGXK-HNNsUbz0.js → chunk-4TB4RGXK--f1tN90O.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-qtCgO0r2.js → chunk-55IACEB6-B5QXfPXQ.js} +1 -1
- package/dist/assets/{chunk-EDXVE4YY-BSnDYtsd.js → chunk-EDXVE4YY-DqKhblOg.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-DyHRLQqX.js → chunk-FMBD7UC4-DZ1w_G02.js} +1 -1
- package/dist/assets/{chunk-OYMX7WX6-CCjfi6WS.js → chunk-OYMX7WX6-BqAgQpv8.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-COLty8kd.js → chunk-QZHKN3VN-DPqnGqVi.js} +1 -1
- package/dist/assets/{chunk-YZCP3GAM-CHUUnGeN.js → chunk-YZCP3GAM-x-ZYSQLd.js} +1 -1
- package/dist/assets/classDiagram-6PBFFD2Q-BquWrs1y.js +1 -0
- package/dist/assets/classDiagram-v2-HSJHXN6E-BquWrs1y.js +1 -0
- package/dist/assets/clone-C9wSPtDN.js +1 -0
- package/dist/assets/{cose-bilkent-S5V4N54A-CSip-V2g.js → cose-bilkent-S5V4N54A-4VCNRP-E.js} +1 -1
- package/dist/assets/{dagre-KV5264BT-DkdpnWhv.js → dagre-KV5264BT-DucVi1QS.js} +1 -1
- package/dist/assets/{diagram-5BDNPKRD-PH4qc6PV.js → diagram-5BDNPKRD-ChdRA8bE.js} +1 -1
- package/dist/assets/{diagram-G4DWMVQ6-Cg5xZcjx.js → diagram-G4DWMVQ6-B1-97yHr.js} +1 -1
- package/dist/assets/{diagram-MMDJMWI5-soKmeTCW.js → diagram-MMDJMWI5-CQs3cO7G.js} +1 -1
- package/dist/assets/{diagram-TYMM5635-Daq5Mihu.js → diagram-TYMM5635-CuNCxDfO.js} +1 -1
- package/dist/assets/{erDiagram-SMLLAGMA-kr2OtY0Y.js → erDiagram-SMLLAGMA-DdR8v8g-.js} +1 -1
- package/dist/assets/{flowDiagram-DWJPFMVM-DQZCb8gm.js → flowDiagram-DWJPFMVM-Dt02upId.js} +1 -1
- package/dist/assets/{ganttDiagram-T4ZO3ILL-BHkn485T.js → ganttDiagram-T4ZO3ILL-cG_k9VOa.js} +1 -1
- package/dist/assets/{gitGraphDiagram-UUTBAWPF-FaCyYFmC.js → gitGraphDiagram-UUTBAWPF-Dz1DjhKq.js} +1 -1
- package/dist/assets/{graph-BVJlrP6V.js → graph-CF2NtM33.js} +1 -1
- package/dist/assets/{infoDiagram-42DDH7IO-DJOWkKdM.js → infoDiagram-42DDH7IO-tQWKrYM6.js} +1 -1
- package/dist/assets/{ishikawaDiagram-UXIWVN3A-VfpvNaIf.js → ishikawaDiagram-UXIWVN3A-CLuUMkF0.js} +1 -1
- package/dist/assets/{journeyDiagram-VCZTEJTY-CPzsak-v.js → journeyDiagram-VCZTEJTY-a6JenLCk.js} +1 -1
- package/dist/assets/{kanban-definition-6JOO6SKY-DFqLDBU0.js → kanban-definition-6JOO6SKY-rqOxTzYb.js} +1 -1
- package/dist/assets/{layout-CCSbNPHm.js → layout-Dvic1Hpy.js} +1 -1
- package/dist/assets/{linear-C4T7PCKE.js → linear-CfMV1S6a.js} +1 -1
- package/dist/assets/main-05K4ggqd.css +10 -0
- package/dist/assets/main-CCM1gtr8.js +1165 -0
- package/dist/assets/{min-CGQNEYGh.js → min-GpF3DZux.js} +1 -1
- package/dist/assets/{mindmap-definition-QFDTVHPH-AuU1EqwS.js → mindmap-definition-QFDTVHPH-Cg80z0Jx.js} +1 -1
- package/dist/assets/{pieDiagram-DEJITSTG-CopkCZwp.js → pieDiagram-DEJITSTG-BrtK7lAq.js} +1 -1
- package/dist/assets/{quadrantDiagram-34T5L4WZ-lMKrSv_t.js → quadrantDiagram-34T5L4WZ-BL2txAAS.js} +1 -1
- package/dist/assets/{requirementDiagram-MS252O5E-dWUpHOFb.js → requirementDiagram-MS252O5E-Co3wpBnu.js} +1 -1
- package/dist/assets/{sankeyDiagram-XADWPNL6-C8UQx9Bb.js → sankeyDiagram-XADWPNL6-B4KJXdQ4.js} +1 -1
- package/dist/assets/{sequenceDiagram-FGHM5R23-CUVNIItJ.js → sequenceDiagram-FGHM5R23-xs5OuzvV.js} +1 -1
- package/dist/assets/{stateDiagram-FHFEXIEX-Ct0GamGl.js → stateDiagram-FHFEXIEX-bbEP20JD.js} +1 -1
- package/dist/assets/stateDiagram-v2-QKLJ7IA2-XYh9U1A7.js +1 -0
- package/dist/assets/{timeline-definition-GMOUNBTQ-ul8Po7f7.js → timeline-definition-GMOUNBTQ-CTc2wVwC.js} +1 -1
- package/dist/assets/{vennDiagram-DHZGUBPP-B4AOWQnP.js → vennDiagram-DHZGUBPP-oJpXott7.js} +1 -1
- package/dist/assets/{wardley-RL74JXVD-Dr7Wp3AJ.js → wardley-RL74JXVD-aTmOXkKh.js} +1 -1
- package/dist/assets/{wardleyDiagram-NUSXRM2D-Ck70faXX.js → wardleyDiagram-NUSXRM2D-C83SOkig.js} +1 -1
- package/dist/assets/{xychartDiagram-5P7HB3ND-Bsy5-cNt.js → xychartDiagram-5P7HB3ND-BScws0tF.js} +1 -1
- package/dist/index.html +13 -13
- 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/domain/agent/agent.service.js +12 -0
- package/dist-server/domain/agent/dto/update-agent.dto.js +20 -1
- package/dist-server/domain/mcp/crewx-tool.factory.js +44 -113
- package/dist-server/domain/mcp/mcp.module.js +2 -0
- package/dist-server/domain/mcp/mcp.service.js +37 -12
- package/dist-server/domain/message/message.service.js +21 -13
- package/dist-server/domain/skill/skill.service.js +63 -43
- package/dist-server/domain/task/task.module.js +2 -0
- package/dist-server/domain/task/task.service.js +17 -10
- package/dist-server/domain/thread/dto/update-thread.dto.js +23 -0
- package/dist-server/domain/thread/thread.controller.js +16 -0
- package/dist-server/domain/thread/thread.service.js +9 -0
- package/dist-server/main.js +1 -1
- package/dist-server/modules/crewx.module.js +16 -1
- 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 +78 -58
- 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/analyze-task-logs.mjs +569 -0
- 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/MarketPage-Dwsg6K-B.js +0 -31
- 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/main-CELBpK6r.js +0 -1166
- package/dist/assets/main-CmP-VosD.css +0 -10
- 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,
|
|
@@ -150,6 +150,9 @@ let AgentService = AgentService_1 = class AgentService {
|
|
|
150
150
|
existing.inline = inline;
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
|
+
if (dto.skills !== undefined) {
|
|
154
|
+
existing.skills = { include: dto.skills.include };
|
|
155
|
+
}
|
|
153
156
|
agents[idx] = existing;
|
|
154
157
|
config.agents = agents;
|
|
155
158
|
this.saveConfig(configPath, config, raw);
|
|
@@ -261,6 +264,9 @@ let AgentService = AgentService_1 = class AgentService {
|
|
|
261
264
|
providerLocation = String(matched.location);
|
|
262
265
|
}
|
|
263
266
|
}
|
|
267
|
+
const skills = a.skills !== null && a.skills !== undefined && Array.isArray(a.skills.include)
|
|
268
|
+
? { include: a.skills.include }
|
|
269
|
+
: undefined;
|
|
264
270
|
return {
|
|
265
271
|
id: String(a.id || ''),
|
|
266
272
|
name: String(a.name || a.id || ''),
|
|
@@ -271,6 +277,7 @@ let AgentService = AgentService_1 = class AgentService {
|
|
|
271
277
|
model: resolvedModel !== undefined ? String(resolvedModel) : undefined,
|
|
272
278
|
providerLocation,
|
|
273
279
|
prompt: resolvedPrompt,
|
|
280
|
+
...(skills !== undefined && { skills }),
|
|
274
281
|
};
|
|
275
282
|
}
|
|
276
283
|
toAgentInfo(a, providers = []) {
|
|
@@ -290,6 +297,10 @@ let AgentService = AgentService_1 = class AgentService {
|
|
|
290
297
|
providerLocation = String(matched.location);
|
|
291
298
|
}
|
|
292
299
|
}
|
|
300
|
+
const rawSkills = a.skills;
|
|
301
|
+
const skills = rawSkills !== null && rawSkills !== undefined && Array.isArray(rawSkills.include)
|
|
302
|
+
? { include: rawSkills.include }
|
|
303
|
+
: undefined;
|
|
293
304
|
return {
|
|
294
305
|
id: String(a.id || ''),
|
|
295
306
|
name: String(a.name || a.id || ''),
|
|
@@ -300,6 +311,7 @@ let AgentService = AgentService_1 = class AgentService {
|
|
|
300
311
|
model: resolvedModel !== undefined ? String(resolvedModel) : undefined,
|
|
301
312
|
providerLocation,
|
|
302
313
|
prompt: resolvedPrompt,
|
|
314
|
+
...(skills !== undefined && { skills }),
|
|
303
315
|
};
|
|
304
316
|
}
|
|
305
317
|
normalizePrompt(prompt) {
|