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
|
@@ -9,9 +9,20 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
9
9
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.UpdateAgentDto = void 0;
|
|
12
|
+
exports.UpdateAgentDto = exports.AgentSkillsDto = void 0;
|
|
13
13
|
const swagger_1 = require("@nestjs/swagger");
|
|
14
14
|
const class_validator_1 = require("class-validator");
|
|
15
|
+
const class_transformer_1 = require("class-transformer");
|
|
16
|
+
class AgentSkillsDto {
|
|
17
|
+
include;
|
|
18
|
+
}
|
|
19
|
+
exports.AgentSkillsDto = AgentSkillsDto;
|
|
20
|
+
__decorate([
|
|
21
|
+
(0, swagger_1.ApiPropertyOptional)({ description: 'Whitelist of skill names. Empty array means no skills allowed.', type: [String] }),
|
|
22
|
+
(0, class_validator_1.IsArray)(),
|
|
23
|
+
(0, class_validator_1.IsString)({ each: true }),
|
|
24
|
+
__metadata("design:type", Array)
|
|
25
|
+
], AgentSkillsDto.prototype, "include", void 0);
|
|
15
26
|
class UpdateAgentDto {
|
|
16
27
|
name;
|
|
17
28
|
role;
|
|
@@ -20,6 +31,7 @@ class UpdateAgentDto {
|
|
|
20
31
|
provider;
|
|
21
32
|
model;
|
|
22
33
|
prompt;
|
|
34
|
+
skills;
|
|
23
35
|
}
|
|
24
36
|
exports.UpdateAgentDto = UpdateAgentDto;
|
|
25
37
|
__decorate([
|
|
@@ -64,3 +76,10 @@ __decorate([
|
|
|
64
76
|
(0, class_validator_1.IsString)(),
|
|
65
77
|
__metadata("design:type", String)
|
|
66
78
|
], UpdateAgentDto.prototype, "prompt", void 0);
|
|
79
|
+
__decorate([
|
|
80
|
+
(0, swagger_1.ApiPropertyOptional)({ description: 'Skill configuration. Undefined = keep existing; include:[] = block all; include:[...] = whitelist.' }),
|
|
81
|
+
(0, class_validator_1.IsOptional)(),
|
|
82
|
+
(0, class_validator_1.ValidateNested)(),
|
|
83
|
+
(0, class_transformer_1.Type)(() => AgentSkillsDto),
|
|
84
|
+
__metadata("design:type", AgentSkillsDto)
|
|
85
|
+
], UpdateAgentDto.prototype, "skills", void 0);
|
|
@@ -1,65 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.createCrewxTool = createCrewxTool;
|
|
4
4
|
const common_1 = require("@nestjs/common");
|
|
5
|
-
const fs_1 = require("fs");
|
|
6
|
-
const path_1 = require("path");
|
|
7
|
-
const child_process_1 = require("child_process");
|
|
8
|
-
const workspace_context_store_js_1 = require("../../common/workspace-context.store.js");
|
|
9
|
-
const crewx_server_js_1 = require("../../bootstrap/crewx-server.js");
|
|
10
5
|
const logger = new common_1.Logger('CrewXToolFactory');
|
|
11
|
-
let crewxToolInstance = null;
|
|
12
6
|
/**
|
|
13
|
-
*
|
|
14
|
-
* Priority: CREWX_CLI env → local packages/cli/dist/main.js → npx crewx
|
|
7
|
+
* Create ICrewXTool implementation backed by a shared Crewx singleton (NestJS DI).
|
|
15
8
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
9
|
+
* All paths delegate to `crewx.query/execute` — threads row upsert, platform,
|
|
10
|
+
* title, first_message, and message persistence are handled by the SDK's
|
|
11
|
+
* ConversationPlugin chain. The Crewx instance lifecycle is owned by
|
|
12
|
+
* CrewxModule; this factory must NEVER call crewx.close().
|
|
18
13
|
*/
|
|
19
|
-
function
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
* Priority: CREWX_CONFIG env → workspace crewx.yaml → workspace crewx.yml
|
|
34
|
-
*/
|
|
35
|
-
function resolveConfigPath(workspacePath) {
|
|
36
|
-
const envConfig = process.env.CREWX_CONFIG;
|
|
37
|
-
if (envConfig && (0, fs_1.existsSync)(envConfig))
|
|
38
|
-
return envConfig;
|
|
39
|
-
const yaml = (0, path_1.join)(workspacePath, 'crewx.yaml');
|
|
40
|
-
const yml = (0, path_1.join)(workspacePath, 'crewx.yml');
|
|
41
|
-
if ((0, fs_1.existsSync)(yaml))
|
|
42
|
-
return yaml;
|
|
43
|
-
if ((0, fs_1.existsSync)(yml))
|
|
44
|
-
return yml;
|
|
45
|
-
return yaml; // will fail gracefully in loadYaml
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Create ICrewXTool implementation backed by the new @crewx/sdk + subprocess spawn.
|
|
49
|
-
*
|
|
50
|
-
* - listAgents / queryAgent: use Crewx SDK in-process (createServerCrewx for plugin coverage)
|
|
51
|
-
* - executeAgent: spawn crewx CLI subprocess so FileLoggerPlugin + SqliteTracingPlugin run
|
|
52
|
-
*
|
|
53
|
-
* This replaces the old NestJS AppModule bootstrap which required packages/cli to be a
|
|
54
|
-
* NestJS application (cli-bak pattern). The new CLI is a plain command dispatcher.
|
|
55
|
-
*/
|
|
56
|
-
function createTool() {
|
|
14
|
+
function createCrewxTool(crewx) {
|
|
15
|
+
// Pre-call helper: ensures threads row exists before fire-and-forget SDK call,
|
|
16
|
+
// closing the race window between task:start emission and REST response.
|
|
17
|
+
const preEnsureThread = async (threadId, platform) => {
|
|
18
|
+
if (!threadId)
|
|
19
|
+
return;
|
|
20
|
+
const conv = crewx.plugins.find((p) => p.name === 'conversation')?.conversationProvider;
|
|
21
|
+
try {
|
|
22
|
+
await conv?.ensureThread(threadId, platform, crewx.workspaceId);
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
logger.warn(`ensureThread skipped [thread=${threadId}]: ${err.message}`);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
57
28
|
return {
|
|
58
29
|
async listAgents() {
|
|
59
|
-
let crewx;
|
|
60
30
|
try {
|
|
61
|
-
const configPath = resolveConfigPath((0, workspace_context_store_js_1.getWorkspacePath)());
|
|
62
|
-
crewx = await (0, crewx_server_js_1.createServerCrewx)(configPath);
|
|
63
31
|
const availableAgents = Array.from(crewx.agents.values()).map((a) => ({
|
|
64
32
|
id: a.id,
|
|
65
33
|
name: a.name,
|
|
@@ -73,27 +41,24 @@ function createTool() {
|
|
|
73
41
|
success: true,
|
|
74
42
|
availableAgents,
|
|
75
43
|
totalCount: availableAgents.length,
|
|
76
|
-
configurationSource: configPath,
|
|
77
44
|
};
|
|
78
45
|
}
|
|
79
46
|
catch (err) {
|
|
80
47
|
logger.error(`listAgents error: ${err.message}`, err.stack);
|
|
81
48
|
return { content: [], success: false, totalCount: 0, error: err.message };
|
|
82
49
|
}
|
|
83
|
-
finally {
|
|
84
|
-
if (crewx)
|
|
85
|
-
await crewx.close();
|
|
86
|
-
}
|
|
87
50
|
},
|
|
88
51
|
async queryAgent(args) {
|
|
89
|
-
let crewx;
|
|
90
52
|
try {
|
|
91
|
-
const
|
|
92
|
-
|
|
53
|
+
const platform = args.platform ?? 'channel/mcp';
|
|
54
|
+
await preEnsureThread(args.threadId, platform);
|
|
93
55
|
const result = await crewx.query(`@${args.agentId}`, args.query, {
|
|
94
56
|
provider: args.provider,
|
|
95
57
|
model: args.model,
|
|
58
|
+
context: args.context,
|
|
59
|
+
threadId: args.threadId,
|
|
96
60
|
metadata: args.metadata,
|
|
61
|
+
platform,
|
|
97
62
|
});
|
|
98
63
|
return {
|
|
99
64
|
content: [{ type: 'text', text: result.data }],
|
|
@@ -109,67 +74,33 @@ function createTool() {
|
|
|
109
74
|
logger.error(`queryAgent error [agent=${args.agentId}]: ${err.message}`, err.stack);
|
|
110
75
|
return { content: [], success: false, isError: true, error: err.message };
|
|
111
76
|
}
|
|
112
|
-
finally {
|
|
113
|
-
if (crewx)
|
|
114
|
-
await crewx.close();
|
|
115
|
-
}
|
|
116
77
|
},
|
|
117
78
|
async executeAgent(args) {
|
|
118
79
|
const { agentId, task, metadata } = args;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
task,
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
child.stdout?.on('data', (data) => {
|
|
138
|
-
logger.debug(`[execute:${agentId}] stdout: ${data.toString().trim()}`);
|
|
139
|
-
});
|
|
140
|
-
child.stderr?.on('data', (data) => {
|
|
141
|
-
logger.warn(`[execute:${agentId}] stderr: ${data.toString().trim()}`);
|
|
142
|
-
});
|
|
143
|
-
child.on('error', (err) => {
|
|
144
|
-
logger.error(`executeAgent spawn error [thread=${thread}, agent=${agentId}]: ${err.message}`);
|
|
145
|
-
});
|
|
146
|
-
child.on('close', (code) => {
|
|
147
|
-
if (code !== 0 && code !== null) {
|
|
148
|
-
logger.error(`[execute:${agentId}] process exited with code ${code}`);
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
logger.log(`[execute:${agentId}] process completed (code=${code})`);
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
// Unref child so the server process isn't blocked waiting for it
|
|
155
|
-
child.unref();
|
|
80
|
+
// threadId sibling takes priority; fall back to legacy metadata.thread for backward compat
|
|
81
|
+
const threadId = args.threadId ?? metadata?.['thread'];
|
|
82
|
+
logger.log(`[execute:${agentId}] starting (thread=${threadId ?? 'none'}) via shared Crewx`);
|
|
83
|
+
const platform = args.platform ?? 'channel/mcp';
|
|
84
|
+
await preEnsureThread(threadId, platform);
|
|
85
|
+
// Fire-and-forget: return immediately, task runs in background.
|
|
86
|
+
// Never close the shared Crewx instance — CrewxModule owns its lifecycle.
|
|
87
|
+
crewx
|
|
88
|
+
.execute(`@${agentId}`, task, {
|
|
89
|
+
provider: args.provider,
|
|
90
|
+
model: args.model,
|
|
91
|
+
context: args.context,
|
|
92
|
+
threadId,
|
|
93
|
+
metadata: args.metadata,
|
|
94
|
+
platform,
|
|
95
|
+
})
|
|
96
|
+
.then((r) => logger.log(`[execute:${agentId}] done (ok=${r.ok})`))
|
|
97
|
+
.catch((e) => logger.error(`[execute:${agentId}] error: ${e.message}`, e.stack));
|
|
156
98
|
return {
|
|
157
99
|
content: [{ type: 'text', text: 'Task started' }],
|
|
158
100
|
success: true,
|
|
159
101
|
agent: agentId,
|
|
160
|
-
taskId:
|
|
102
|
+
taskId: threadId,
|
|
161
103
|
};
|
|
162
104
|
},
|
|
163
105
|
};
|
|
164
106
|
}
|
|
165
|
-
/**
|
|
166
|
-
* Return the singleton ICrewXTool implementation.
|
|
167
|
-
* Memoised — only creates the tool once per server lifetime.
|
|
168
|
-
*/
|
|
169
|
-
async function getCrewXTool() {
|
|
170
|
-
if (!crewxToolInstance) {
|
|
171
|
-
crewxToolInstance = createTool();
|
|
172
|
-
logger.log('CrewXTool initialised (SDK + subprocess mode)');
|
|
173
|
-
}
|
|
174
|
-
return crewxToolInstance;
|
|
175
|
-
}
|
|
@@ -13,11 +13,13 @@ const crypto_1 = require("crypto");
|
|
|
13
13
|
const mcp_controller_js_1 = require("./mcp.controller.js");
|
|
14
14
|
const mcp_service_js_1 = require("./mcp.service.js");
|
|
15
15
|
const mcp_constants_js_1 = require("./mcp.constants.js");
|
|
16
|
+
const crewx_module_js_1 = require("../../modules/crewx.module.js");
|
|
16
17
|
let McpModule = class McpModule {
|
|
17
18
|
};
|
|
18
19
|
exports.McpModule = McpModule;
|
|
19
20
|
exports.McpModule = McpModule = __decorate([
|
|
20
21
|
(0, common_1.Module)({
|
|
22
|
+
imports: [crewx_module_js_1.CrewxModule],
|
|
21
23
|
controllers: [mcp_controller_js_1.McpController],
|
|
22
24
|
providers: [
|
|
23
25
|
mcp_service_js_1.McpService,
|
|
@@ -5,10 +5,17 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
6
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
7
|
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
8
14
|
var McpService_1;
|
|
9
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
16
|
exports.McpService = void 0;
|
|
11
17
|
const common_1 = require("@nestjs/common");
|
|
18
|
+
const sdk_1 = require("@crewx/sdk");
|
|
12
19
|
const mcp_dto_js_1 = require("./mcp.dto.js");
|
|
13
20
|
const crewx_tool_factory_js_1 = require("./crewx-tool.factory.js");
|
|
14
21
|
const SERVER_NAME = 'crewx-ui';
|
|
@@ -36,7 +43,12 @@ const TOOL_DEFINITIONS = [
|
|
|
36
43
|
},
|
|
37
44
|
thread: {
|
|
38
45
|
type: 'string',
|
|
39
|
-
description: '
|
|
46
|
+
description: 'Thread ID for conversation continuity. Previous messages with the same thread ID will be included in the context automatically.',
|
|
47
|
+
},
|
|
48
|
+
metadata: {
|
|
49
|
+
type: 'object',
|
|
50
|
+
additionalProperties: true,
|
|
51
|
+
description: 'Free-form metadata (e.g., workflow_id, project_id) persisted to the task record for tracing.',
|
|
40
52
|
},
|
|
41
53
|
},
|
|
42
54
|
required: ['agentId', 'query'],
|
|
@@ -62,7 +74,12 @@ const TOOL_DEFINITIONS = [
|
|
|
62
74
|
},
|
|
63
75
|
thread: {
|
|
64
76
|
type: 'string',
|
|
65
|
-
description: '
|
|
77
|
+
description: 'Thread ID for conversation continuity. Previous messages with the same thread ID will be included in the context automatically.',
|
|
78
|
+
},
|
|
79
|
+
metadata: {
|
|
80
|
+
type: 'object',
|
|
81
|
+
additionalProperties: true,
|
|
82
|
+
description: 'Free-form metadata (e.g., workflow_id, project_id) persisted to the task record for tracing.',
|
|
66
83
|
},
|
|
67
84
|
},
|
|
68
85
|
required: ['agentId', 'task'],
|
|
@@ -79,6 +96,10 @@ const TOOL_DEFINITIONS = [
|
|
|
79
96
|
];
|
|
80
97
|
let McpService = McpService_1 = class McpService {
|
|
81
98
|
logger = new common_1.Logger(McpService_1.name);
|
|
99
|
+
tool;
|
|
100
|
+
constructor(crewx) {
|
|
101
|
+
this.tool = (0, crewx_tool_factory_js_1.createCrewxTool)(crewx);
|
|
102
|
+
}
|
|
82
103
|
// Validate JSON-RPC 2.0 request structure
|
|
83
104
|
validateRequest(body) {
|
|
84
105
|
if (!body || typeof body !== 'object') {
|
|
@@ -249,7 +270,7 @@ let McpService = McpService_1 = class McpService {
|
|
|
249
270
|
*/
|
|
250
271
|
async execListAgents(id) {
|
|
251
272
|
try {
|
|
252
|
-
const tool =
|
|
273
|
+
const tool = this.tool;
|
|
253
274
|
const result = await tool.listAgents();
|
|
254
275
|
return {
|
|
255
276
|
jsonrpc: '2.0',
|
|
@@ -281,7 +302,7 @@ let McpService = McpService_1 = class McpService {
|
|
|
281
302
|
* crewx_queryAgent — delegates to CrewXTool.queryAgent()
|
|
282
303
|
*/
|
|
283
304
|
async execQueryAgent(id, args) {
|
|
284
|
-
const { agentId, query, context, thread } = args;
|
|
305
|
+
const { agentId, query, context, thread, metadata } = args;
|
|
285
306
|
if (!agentId || !query) {
|
|
286
307
|
return {
|
|
287
308
|
jsonrpc: '2.0',
|
|
@@ -293,14 +314,15 @@ let McpService = McpService_1 = class McpService {
|
|
|
293
314
|
};
|
|
294
315
|
}
|
|
295
316
|
try {
|
|
296
|
-
const tool =
|
|
317
|
+
const tool = this.tool;
|
|
297
318
|
const startTime = Date.now();
|
|
298
319
|
const result = await tool.queryAgent({
|
|
299
320
|
agentId,
|
|
300
321
|
query,
|
|
301
322
|
context,
|
|
302
|
-
|
|
303
|
-
metadata:
|
|
323
|
+
threadId: thread,
|
|
324
|
+
metadata: metadata ?? {},
|
|
325
|
+
platform: 'channel/mcp',
|
|
304
326
|
});
|
|
305
327
|
const duration = Date.now() - startTime;
|
|
306
328
|
const content = normalizeContent(result);
|
|
@@ -342,7 +364,7 @@ let McpService = McpService_1 = class McpService {
|
|
|
342
364
|
* crewx_executeAgent — delegates to CrewXTool.executeAgent()
|
|
343
365
|
*/
|
|
344
366
|
async execExecuteAgent(id, args) {
|
|
345
|
-
const { agentId, task, context, thread } = args;
|
|
367
|
+
const { agentId, task, context, thread, metadata } = args;
|
|
346
368
|
if (!agentId || !task) {
|
|
347
369
|
return {
|
|
348
370
|
jsonrpc: '2.0',
|
|
@@ -354,14 +376,15 @@ let McpService = McpService_1 = class McpService {
|
|
|
354
376
|
};
|
|
355
377
|
}
|
|
356
378
|
try {
|
|
357
|
-
const tool =
|
|
379
|
+
const tool = this.tool;
|
|
358
380
|
const startTime = Date.now();
|
|
359
381
|
const result = await tool.executeAgent({
|
|
360
382
|
agentId,
|
|
361
383
|
task,
|
|
362
384
|
context,
|
|
363
|
-
|
|
364
|
-
metadata:
|
|
385
|
+
threadId: thread,
|
|
386
|
+
metadata: metadata ?? {},
|
|
387
|
+
platform: 'channel/mcp',
|
|
365
388
|
});
|
|
366
389
|
const duration = Date.now() - startTime;
|
|
367
390
|
const content = normalizeContent(result);
|
|
@@ -402,7 +425,9 @@ let McpService = McpService_1 = class McpService {
|
|
|
402
425
|
};
|
|
403
426
|
exports.McpService = McpService;
|
|
404
427
|
exports.McpService = McpService = McpService_1 = __decorate([
|
|
405
|
-
(0, common_1.Injectable)()
|
|
428
|
+
(0, common_1.Injectable)(),
|
|
429
|
+
__param(0, (0, common_1.Inject)(sdk_1.Crewx)),
|
|
430
|
+
__metadata("design:paramtypes", [sdk_1.Crewx])
|
|
406
431
|
], McpService);
|
|
407
432
|
function normalizeContent(result) {
|
|
408
433
|
if (Array.isArray(result.content) && result.content.length > 0) {
|
|
@@ -98,7 +98,7 @@ let MessageService = MessageService_1 = class MessageService {
|
|
|
98
98
|
config: ctx.config,
|
|
99
99
|
};
|
|
100
100
|
}
|
|
101
|
-
// MSG.SEND: Send message —
|
|
101
|
+
// MSG.SEND: Send message — fire crewx SDK; ConversationPlugin persists threads row
|
|
102
102
|
async sendMessage(threadId, message, agent, mode = 'query', title, workspaceId) {
|
|
103
103
|
this.validateId(threadId);
|
|
104
104
|
if (!message || !message.trim()) {
|
|
@@ -107,17 +107,30 @@ let MessageService = MessageService_1 = class MessageService {
|
|
|
107
107
|
if (!agent || !agent.trim()) {
|
|
108
108
|
throw new common_1.BadRequestException('agent is required');
|
|
109
109
|
}
|
|
110
|
-
//
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
110
|
+
// Explicit user-supplied title locks the thread title against plugin overwrite.
|
|
111
|
+
if (title) {
|
|
112
|
+
try {
|
|
113
|
+
this.threadRepo.updateThreadTitle(threadId, title, workspaceId);
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
// Non-fatal: plugin chain will still persist message/thread row shortly.
|
|
117
|
+
this.logger.warn(`updateThreadTitle skipped [thread=${threadId}]: ${err.message}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
117
120
|
const sdkOptions = {
|
|
118
121
|
threadId,
|
|
122
|
+
platform: 'cli',
|
|
119
123
|
metadata: { thread: threadId, parentTaskId: null },
|
|
120
124
|
};
|
|
125
|
+
// Pre-call ensureThread so REST response is safe to follow with GET /threads/:id
|
|
126
|
+
// (frontend ThreadNewPage navigates to /threads/:id right after POST /messages).
|
|
127
|
+
const conv = this.crewx.plugins.find((p) => p.name === 'conversation')?.conversationProvider;
|
|
128
|
+
try {
|
|
129
|
+
await conv?.ensureThread(threadId, sdkOptions.platform, this.crewx.workspaceId);
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
this.logger.warn(`ensureThread skipped [thread=${threadId}]: ${err.message}`);
|
|
133
|
+
}
|
|
121
134
|
const agentRef = `@${agent}`;
|
|
122
135
|
const sdkCall = mode === 'execute'
|
|
123
136
|
? this.crewx.execute(agentRef, message, sdkOptions)
|
|
@@ -137,11 +150,6 @@ let MessageService = MessageService_1 = class MessageService {
|
|
|
137
150
|
filterLogs(logs) {
|
|
138
151
|
return logs;
|
|
139
152
|
}
|
|
140
|
-
truncate(text, maxLen) {
|
|
141
|
-
if (text.length <= maxLen)
|
|
142
|
-
return text;
|
|
143
|
-
return text.slice(0, maxLen) + '...';
|
|
144
|
-
}
|
|
145
153
|
};
|
|
146
154
|
exports.MessageService = MessageService;
|
|
147
155
|
exports.MessageService = MessageService = MessageService_1 = __decorate([
|
|
@@ -47,6 +47,7 @@ const promises_1 = require("fs/promises");
|
|
|
47
47
|
const path_1 = require("path");
|
|
48
48
|
const crypto_1 = require("crypto");
|
|
49
49
|
const yaml = __importStar(require("js-yaml"));
|
|
50
|
+
const skill_1 = require("@crewx/skill");
|
|
50
51
|
const workspace_context_store_js_1 = require("../../common/workspace-context.store.js");
|
|
51
52
|
// --- Constants ---
|
|
52
53
|
const DEFAULT_REGISTRY_URL = 'https://github.com/sowonlabs/crewx-templates';
|
|
@@ -199,53 +200,72 @@ let SkillService = SkillService_1 = class SkillService {
|
|
|
199
200
|
this.logger.log(`Uninstalled skill '${name}'`);
|
|
200
201
|
}
|
|
201
202
|
// --- Installed skills ---
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
203
|
+
resolveSkillSource(dir, projectRoot) {
|
|
204
|
+
const nmDir = (0, path_1.join)(projectRoot, 'node_modules') + '/';
|
|
205
|
+
if (!dir.startsWith(nmDir) && dir !== (0, path_1.join)(projectRoot, 'node_modules')) {
|
|
206
|
+
return 'local';
|
|
205
207
|
}
|
|
206
|
-
const
|
|
208
|
+
const relFromNm = dir.slice(nmDir.length);
|
|
209
|
+
return relFromNm.startsWith('@crewx/') ? 'builtin' : 'node_modules';
|
|
210
|
+
}
|
|
211
|
+
async listInstalledSkills() {
|
|
212
|
+
const projectRoot = (0, path_1.dirname)(this.skillsDir);
|
|
213
|
+
const nmDir = (0, path_1.join)(projectRoot, 'node_modules');
|
|
214
|
+
const engine = new skill_1.SkillEngine(projectRoot, (0, fs_1.existsSync)(nmDir) ? [nmDir] : []);
|
|
215
|
+
const discovered = engine.discover();
|
|
207
216
|
const skills = [];
|
|
208
|
-
for (const
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
try {
|
|
227
|
-
updatedAt = (await (0, promises_1.stat)(skillMdPath)).mtime.toISOString();
|
|
228
|
-
}
|
|
229
|
-
catch {
|
|
230
|
-
// ignore stat errors
|
|
217
|
+
for (const item of discovered) {
|
|
218
|
+
const source = this.resolveSkillSource(item.dir, projectRoot);
|
|
219
|
+
if (source === 'local') {
|
|
220
|
+
// For local skills keep rich metadata from frontmatter + GitHub cache
|
|
221
|
+
const skillMdPath = item.skillMdPath ?? (0, path_1.join)(item.dir, 'SKILL.md');
|
|
222
|
+
const { frontmatter } = (0, fs_1.existsSync)(skillMdPath)
|
|
223
|
+
? await this.parseSkillMdAsync(skillMdPath)
|
|
224
|
+
: { frontmatter: {} };
|
|
225
|
+
const installSource = this.detectInstallSource(item.name);
|
|
226
|
+
const cached = this.getGitHubCacheEntry(item.name);
|
|
227
|
+
let updatedAt = cached?.updatedAt;
|
|
228
|
+
if (!updatedAt) {
|
|
229
|
+
try {
|
|
230
|
+
updatedAt = (await (0, promises_1.stat)(skillMdPath)).mtime.toISOString();
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
// ignore stat errors
|
|
234
|
+
}
|
|
231
235
|
}
|
|
236
|
+
skills.push({
|
|
237
|
+
name: item.name,
|
|
238
|
+
displayName: item.name,
|
|
239
|
+
description: item.description || frontmatter.description || '',
|
|
240
|
+
author: frontmatter.author || '',
|
|
241
|
+
version: item.version || frontmatter.version || '0.0.0',
|
|
242
|
+
tags: frontmatter.tags ? String(frontmatter.tags).split(',').map((t) => t.trim()) : [],
|
|
243
|
+
type: item.type,
|
|
244
|
+
isVerified: false,
|
|
245
|
+
isInstalled: true,
|
|
246
|
+
source,
|
|
247
|
+
installSource,
|
|
248
|
+
authors: cached?.authors,
|
|
249
|
+
updatedAt,
|
|
250
|
+
stars: cached?.stars,
|
|
251
|
+
license: cached?.license,
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
// For builtin / node_modules skills use basic discover() info
|
|
256
|
+
skills.push({
|
|
257
|
+
name: item.name,
|
|
258
|
+
displayName: item.name,
|
|
259
|
+
description: item.description || '',
|
|
260
|
+
author: '',
|
|
261
|
+
version: item.version || '0.0.0',
|
|
262
|
+
tags: [],
|
|
263
|
+
type: item.type,
|
|
264
|
+
isVerified: false,
|
|
265
|
+
isInstalled: false,
|
|
266
|
+
source,
|
|
267
|
+
});
|
|
232
268
|
}
|
|
233
|
-
skills.push({
|
|
234
|
-
name: frontmatter.name || entry,
|
|
235
|
-
displayName: frontmatter.name || entry,
|
|
236
|
-
description: frontmatter.description || '',
|
|
237
|
-
author: frontmatter.author || '',
|
|
238
|
-
version: frontmatter.version || '0.0.0',
|
|
239
|
-
tags: frontmatter.tags ? frontmatter.tags.split(',').map((t) => t.trim()) : [],
|
|
240
|
-
type: 'skill',
|
|
241
|
-
isVerified: false,
|
|
242
|
-
isInstalled: true,
|
|
243
|
-
installSource,
|
|
244
|
-
authors: cached?.authors,
|
|
245
|
-
updatedAt,
|
|
246
|
-
stars: cached?.stars,
|
|
247
|
-
license: cached?.license,
|
|
248
|
-
});
|
|
249
269
|
}
|
|
250
270
|
return { skills };
|
|
251
271
|
}
|
|
@@ -10,11 +10,13 @@ exports.TaskModule = void 0;
|
|
|
10
10
|
const common_1 = require("@nestjs/common");
|
|
11
11
|
const task_controller_js_1 = require("./task.controller.js");
|
|
12
12
|
const task_service_js_1 = require("./task.service.js");
|
|
13
|
+
const crewx_module_js_1 = require("../../modules/crewx.module.js");
|
|
13
14
|
let TaskModule = class TaskModule {
|
|
14
15
|
};
|
|
15
16
|
exports.TaskModule = TaskModule;
|
|
16
17
|
exports.TaskModule = TaskModule = __decorate([
|
|
17
18
|
(0, common_1.Module)({
|
|
19
|
+
imports: [crewx_module_js_1.CrewxModule],
|
|
18
20
|
controllers: [task_controller_js_1.TaskController],
|
|
19
21
|
providers: [task_service_js_1.TaskService],
|
|
20
22
|
})
|