devchain-cli 0.2.2 → 0.3.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 +2 -0
- package/dist/drizzle/0018_whole_zodiak.sql +43 -0
- package/dist/drizzle/0019_flat_avengers.sql +3 -0
- package/dist/drizzle/0020_statuses_mcp_hidden.sql +1 -0
- package/dist/drizzle/meta/0018_snapshot.json +2920 -0
- package/dist/drizzle/meta/0019_snapshot.json +2943 -0
- package/dist/drizzle/meta/0020_snapshot.json +2951 -0
- package/dist/drizzle/meta/_journal.json +21 -0
- package/dist/server/app.module.js +11 -1
- package/dist/server/app.module.js.map +1 -1
- package/dist/server/common/config/env.config.d.ts +1 -0
- package/dist/server/common/config/env.config.js +4 -0
- package/dist/server/common/config/env.config.js.map +1 -1
- package/dist/server/common/filters/http-exception.filter.js +24 -1
- package/dist/server/common/filters/http-exception.filter.js.map +1 -1
- package/dist/server/common/logging/logger.js +4 -3
- package/dist/server/common/logging/logger.js.map +1 -1
- package/dist/server/main.js +0 -3
- package/dist/server/main.js.map +1 -1
- package/dist/server/modules/agents/agents.module.js +2 -1
- package/dist/server/modules/agents/agents.module.js.map +1 -1
- package/dist/server/modules/agents/controllers/agents.controller.d.ts +17 -2
- package/dist/server/modules/agents/controllers/agents.controller.js +84 -3
- package/dist/server/modules/agents/controllers/agents.controller.js.map +1 -1
- package/dist/server/modules/chat/dtos/chat.dto.d.ts +18 -18
- package/dist/server/modules/chat/dtos/chat.dto.js +1 -1
- package/dist/server/modules/chat/dtos/chat.dto.js.map +1 -1
- package/dist/server/modules/chat/services/invite-template.util.js +1 -1
- package/dist/server/modules/chat/services/invite-template.util.js.map +1 -1
- package/dist/server/modules/events/catalog/index.d.ts +40 -0
- package/dist/server/modules/events/catalog/index.js +2 -0
- package/dist/server/modules/events/catalog/index.js.map +1 -1
- package/dist/server/modules/events/catalog/terminal.watcher.triggered.d.ts +45 -0
- package/dist/server/modules/events/catalog/terminal.watcher.triggered.js +22 -0
- package/dist/server/modules/events/catalog/terminal.watcher.triggered.js.map +1 -0
- package/dist/server/modules/events/subscribers/chat-message-delivery.subscriber.d.ts +1 -0
- package/dist/server/modules/events/subscribers/chat-message-delivery.subscriber.js +30 -12
- package/dist/server/modules/events/subscribers/chat-message-delivery.subscriber.js.map +1 -1
- package/dist/server/modules/mcp/constants.d.ts +2 -0
- package/dist/server/modules/mcp/constants.js +11 -2
- package/dist/server/modules/mcp/constants.js.map +1 -1
- package/dist/server/modules/mcp/controllers/mcp-http.controller.js +78 -81
- package/dist/server/modules/mcp/controllers/mcp-http.controller.js.map +1 -1
- package/dist/server/modules/mcp/controllers/mcp-sdk.controller.js +78 -77
- package/dist/server/modules/mcp/controllers/mcp-sdk.controller.js.map +1 -1
- package/dist/server/modules/mcp/dtos/mcp.dto.d.ts +125 -97
- package/dist/server/modules/mcp/dtos/mcp.dto.js +23 -26
- package/dist/server/modules/mcp/dtos/mcp.dto.js.map +1 -1
- package/dist/server/modules/mcp/services/instructions-resolver.d.ts +3 -0
- package/dist/server/modules/mcp/services/instructions-resolver.js +83 -2
- package/dist/server/modules/mcp/services/instructions-resolver.js.map +1 -1
- package/dist/server/modules/mcp/services/mcp.service.d.ts +3 -2
- package/dist/server/modules/mcp/services/mcp.service.js +549 -263
- package/dist/server/modules/mcp/services/mcp.service.js.map +1 -1
- package/dist/server/modules/projects/controllers/projects.controller.d.ts +43 -0
- package/dist/server/modules/projects/projects.module.js +2 -1
- package/dist/server/modules/projects/projects.module.js.map +1 -1
- package/dist/server/modules/projects/services/projects.service.d.ts +48 -1
- package/dist/server/modules/projects/services/projects.service.js +341 -19
- package/dist/server/modules/projects/services/projects.service.js.map +1 -1
- package/dist/server/modules/prompts/controllers/prompts.controller.d.ts +1 -1
- package/dist/server/modules/prompts/controllers/prompts.controller.js +26 -4
- package/dist/server/modules/prompts/controllers/prompts.controller.js.map +1 -1
- package/dist/server/modules/sessions/utils/template-renderer.js +1 -0
- package/dist/server/modules/sessions/utils/template-renderer.js.map +1 -1
- package/dist/server/modules/statuses/controllers/statuses.controller.js +2 -0
- package/dist/server/modules/statuses/controllers/statuses.controller.js.map +1 -1
- package/dist/server/modules/storage/db/schema.d.ts +613 -0
- package/dist/server/modules/storage/db/schema.js +50 -1
- package/dist/server/modules/storage/db/schema.js.map +1 -1
- package/dist/server/modules/storage/interfaces/storage.interface.d.ts +40 -2
- package/dist/server/modules/storage/interfaces/storage.interface.js.map +1 -1
- package/dist/server/modules/storage/local/local-storage.service.d.ts +18 -3
- package/dist/server/modules/storage/local/local-storage.service.js +407 -11
- package/dist/server/modules/storage/local/local-storage.service.js.map +1 -1
- package/dist/server/modules/storage/models/domain.models.d.ts +59 -1
- package/dist/server/modules/subscribers/actions/action.interface.d.ts +67 -0
- package/dist/server/modules/subscribers/actions/action.interface.js +3 -0
- package/dist/server/modules/subscribers/actions/action.interface.js.map +1 -0
- package/dist/server/modules/subscribers/actions/actions.registry.d.ts +7 -0
- package/dist/server/modules/subscribers/actions/actions.registry.js +37 -0
- package/dist/server/modules/subscribers/actions/actions.registry.js.map +1 -0
- package/dist/server/modules/subscribers/actions/restart-agent.action.d.ts +8 -0
- package/dist/server/modules/subscribers/actions/restart-agent.action.js +119 -0
- package/dist/server/modules/subscribers/actions/restart-agent.action.js.map +1 -0
- package/dist/server/modules/subscribers/actions/send-message.action.d.ts +2 -0
- package/dist/server/modules/subscribers/actions/send-message.action.js +83 -0
- package/dist/server/modules/subscribers/actions/send-message.action.js.map +1 -0
- package/dist/server/modules/subscribers/controllers/actions.controller.d.ts +6 -0
- package/dist/server/modules/subscribers/controllers/actions.controller.js +51 -0
- package/dist/server/modules/subscribers/controllers/actions.controller.js.map +1 -0
- package/dist/server/modules/subscribers/controllers/subscribers.controller.d.ts +17 -0
- package/dist/server/modules/subscribers/controllers/subscribers.controller.js +178 -0
- package/dist/server/modules/subscribers/controllers/subscribers.controller.js.map +1 -0
- package/dist/server/modules/subscribers/dtos/subscriber.dto.d.ts +251 -0
- package/dist/server/modules/subscribers/dtos/subscriber.dto.js +68 -0
- package/dist/server/modules/subscribers/dtos/subscriber.dto.js.map +1 -0
- package/dist/server/modules/subscribers/events/event-fields-catalog.d.ts +19 -0
- package/dist/server/modules/subscribers/events/event-fields-catalog.js +98 -0
- package/dist/server/modules/subscribers/events/event-fields-catalog.js.map +1 -0
- package/dist/server/modules/subscribers/services/automation-scheduler.service.d.ts +49 -0
- package/dist/server/modules/subscribers/services/automation-scheduler.service.js +300 -0
- package/dist/server/modules/subscribers/services/automation-scheduler.service.js.map +1 -0
- package/dist/server/modules/subscribers/services/subscriber-executor.service.d.ts +77 -0
- package/dist/server/modules/subscribers/services/subscriber-executor.service.js +576 -0
- package/dist/server/modules/subscribers/services/subscriber-executor.service.js.map +1 -0
- package/dist/server/modules/subscribers/services/subscribers.service.d.ts +14 -0
- package/dist/server/modules/subscribers/services/subscribers.service.js +70 -0
- package/dist/server/modules/subscribers/services/subscribers.service.js.map +1 -0
- package/dist/server/modules/subscribers/subscribers.module.d.ts +2 -0
- package/dist/server/modules/subscribers/subscribers.module.js +36 -0
- package/dist/server/modules/subscribers/subscribers.module.js.map +1 -0
- package/dist/server/modules/terminal/services/tmux.service.js +9 -6
- package/dist/server/modules/terminal/services/tmux.service.js.map +1 -1
- package/dist/server/modules/watchers/controllers/watchers.controller.d.ts +16 -0
- package/dist/server/modules/watchers/controllers/watchers.controller.js +180 -0
- package/dist/server/modules/watchers/controllers/watchers.controller.js.map +1 -0
- package/dist/server/modules/watchers/dtos/watcher.dto.d.ts +206 -0
- package/dist/server/modules/watchers/dtos/watcher.dto.js +54 -0
- package/dist/server/modules/watchers/dtos/watcher.dto.js.map +1 -0
- package/dist/server/modules/watchers/services/watcher-runner.service.d.ts +68 -0
- package/dist/server/modules/watchers/services/watcher-runner.service.js +477 -0
- package/dist/server/modules/watchers/services/watcher-runner.service.js.map +1 -0
- package/dist/server/modules/watchers/services/watchers.service.d.ts +29 -0
- package/dist/server/modules/watchers/services/watchers.service.js +98 -0
- package/dist/server/modules/watchers/services/watchers.service.js.map +1 -0
- package/dist/server/modules/watchers/watchers.module.d.ts +2 -0
- package/dist/server/modules/watchers/watchers.module.js +34 -0
- package/dist/server/modules/watchers/watchers.module.js.map +1 -0
- package/dist/server/templates/claude-codex-advanced-swe.json +130 -0
- package/dist/server/templates/claude-codex-advanced.json +377 -0
- package/dist/server/templates/claude-opus.json +241 -34
- package/dist/server/templates/simple-codex.json +138 -42
- package/dist/server/test-setup-node.d.ts +1 -0
- package/dist/server/test-setup-node.js +8 -0
- package/dist/server/test-setup-node.js.map +1 -0
- package/dist/server/test-setup.js +2 -0
- package/dist/server/test-setup.js.map +1 -1
- package/dist/server/tsconfig.tsbuildinfo +1 -1
- package/dist/server/ui/assets/index-C9GXCjnF.js +700 -0
- package/dist/server/ui/assets/index-o0FbZg-1.css +32 -0
- package/dist/server/ui/index.html +2 -2
- package/dist/templates/claude-codex-advanced-swe.json +130 -0
- package/dist/templates/claude-codex-advanced.json +377 -0
- package/dist/templates/claude-opus.json +241 -34
- package/dist/templates/simple-codex.json +138 -42
- package/package.json +47 -27
- package/dist/server/templates/codex-claude.json +0 -178
- package/dist/server/ui/assets/index-CbYIbCQV.css +0 -32
- package/dist/server/ui/assets/index-sfYpjMjv.js +0 -641
- package/dist/templates/codex-claude.json +0 -178
|
@@ -17,6 +17,8 @@ const common_1 = require("@nestjs/common");
|
|
|
17
17
|
const storage_interface_1 = require("../../storage/interfaces/storage.interface");
|
|
18
18
|
const sessions_service_1 = require("../../sessions/services/sessions.service");
|
|
19
19
|
const settings_service_1 = require("../../settings/services/settings.service");
|
|
20
|
+
const watchers_service_1 = require("../../watchers/services/watchers.service");
|
|
21
|
+
const watcher_runner_service_1 = require("../../watchers/services/watcher-runner.service");
|
|
20
22
|
const logger_1 = require("../../../common/logging/logger");
|
|
21
23
|
const error_types_1 = require("../../../common/errors/error-types");
|
|
22
24
|
const path_1 = require("path");
|
|
@@ -65,6 +67,7 @@ const ExportSchema = zod_1.z
|
|
|
65
67
|
label: zod_1.z.string().min(1),
|
|
66
68
|
color: zod_1.z.string().min(1),
|
|
67
69
|
position: zod_1.z.number().int(),
|
|
70
|
+
mcpHidden: zod_1.z.boolean().optional().default(false),
|
|
68
71
|
}))
|
|
69
72
|
.optional()
|
|
70
73
|
.default([]),
|
|
@@ -79,13 +82,66 @@ const ExportSchema = zod_1.z
|
|
|
79
82
|
epicAssignedTemplate: zod_1.z.string().optional(),
|
|
80
83
|
})
|
|
81
84
|
.optional(),
|
|
85
|
+
watchers: zod_1.z
|
|
86
|
+
.array(zod_1.z.object({
|
|
87
|
+
id: zod_1.z.string().uuid().optional(),
|
|
88
|
+
name: zod_1.z.string().min(1),
|
|
89
|
+
description: zod_1.z.string().nullable().optional(),
|
|
90
|
+
enabled: zod_1.z.boolean(),
|
|
91
|
+
scope: zod_1.z.enum(['all', 'agent', 'profile', 'provider']),
|
|
92
|
+
scopeFilterName: zod_1.z.string().nullable().optional(),
|
|
93
|
+
pollIntervalMs: zod_1.z.number().int(),
|
|
94
|
+
viewportLines: zod_1.z.number().int(),
|
|
95
|
+
condition: zod_1.z.object({
|
|
96
|
+
type: zod_1.z.enum(['contains', 'regex', 'not_contains']),
|
|
97
|
+
pattern: zod_1.z.string(),
|
|
98
|
+
flags: zod_1.z.string().optional(),
|
|
99
|
+
}),
|
|
100
|
+
cooldownMs: zod_1.z.number().int(),
|
|
101
|
+
cooldownMode: zod_1.z.enum(['time', 'until_clear']),
|
|
102
|
+
eventName: zod_1.z.string(),
|
|
103
|
+
}))
|
|
104
|
+
.optional()
|
|
105
|
+
.default([]),
|
|
106
|
+
subscribers: zod_1.z
|
|
107
|
+
.array(zod_1.z.object({
|
|
108
|
+
id: zod_1.z.string().uuid().optional(),
|
|
109
|
+
name: zod_1.z.string().min(1),
|
|
110
|
+
description: zod_1.z.string().nullable().optional(),
|
|
111
|
+
enabled: zod_1.z.boolean(),
|
|
112
|
+
eventName: zod_1.z.string(),
|
|
113
|
+
eventFilter: zod_1.z
|
|
114
|
+
.object({
|
|
115
|
+
field: zod_1.z.string(),
|
|
116
|
+
operator: zod_1.z.enum(['equals', 'contains', 'regex']),
|
|
117
|
+
value: zod_1.z.string(),
|
|
118
|
+
})
|
|
119
|
+
.nullable()
|
|
120
|
+
.optional(),
|
|
121
|
+
actionType: zod_1.z.string(),
|
|
122
|
+
actionInputs: zod_1.z.record(zod_1.z.string(), zod_1.z.object({
|
|
123
|
+
source: zod_1.z.enum(['event_field', 'custom']),
|
|
124
|
+
eventField: zod_1.z.string().optional(),
|
|
125
|
+
customValue: zod_1.z.string().optional(),
|
|
126
|
+
})),
|
|
127
|
+
delayMs: zod_1.z.number().int(),
|
|
128
|
+
cooldownMs: zod_1.z.number().int(),
|
|
129
|
+
retryOnError: zod_1.z.boolean(),
|
|
130
|
+
groupName: zod_1.z.string().nullable().optional(),
|
|
131
|
+
position: zod_1.z.number().int().optional().default(0),
|
|
132
|
+
priority: zod_1.z.number().int().optional().default(0),
|
|
133
|
+
}))
|
|
134
|
+
.optional()
|
|
135
|
+
.default([]),
|
|
82
136
|
})
|
|
83
137
|
.strict();
|
|
84
138
|
let ProjectsService = class ProjectsService {
|
|
85
|
-
constructor(storage, sessions, settings) {
|
|
139
|
+
constructor(storage, sessions, settings, watchersService, watcherRunner) {
|
|
86
140
|
this.storage = storage;
|
|
87
141
|
this.sessions = sessions;
|
|
88
142
|
this.settings = settings;
|
|
143
|
+
this.watchersService = watchersService;
|
|
144
|
+
this.watcherRunner = watcherRunner;
|
|
89
145
|
}
|
|
90
146
|
findTemplatesDirectory() {
|
|
91
147
|
const env = (0, env_config_1.getEnvConfig)();
|
|
@@ -276,6 +332,7 @@ let ProjectsService = class ProjectsService {
|
|
|
276
332
|
label: s.label,
|
|
277
333
|
color: s.color,
|
|
278
334
|
position: s.position,
|
|
335
|
+
mcpHidden: s.mcpHidden,
|
|
279
336
|
})),
|
|
280
337
|
initialPrompt: payload.initialPrompt,
|
|
281
338
|
};
|
|
@@ -285,6 +342,18 @@ let ProjectsService = class ProjectsService {
|
|
|
285
342
|
rootPath: input.rootPath,
|
|
286
343
|
isTemplate: false,
|
|
287
344
|
}, templatePayload);
|
|
345
|
+
const agentNameToNewId = new Map();
|
|
346
|
+
for (const a of templatePayload.agents) {
|
|
347
|
+
if (a.id && result.mappings.agentIdMap[a.id]) {
|
|
348
|
+
agentNameToNewId.set(a.name.trim().toLowerCase(), result.mappings.agentIdMap[a.id]);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
const profileNameToNewId = new Map();
|
|
352
|
+
for (const prof of templatePayload.profiles) {
|
|
353
|
+
if (prof.id && result.mappings.profileIdMap[prof.id]) {
|
|
354
|
+
profileNameToNewId.set(prof.name.trim().toLowerCase(), result.mappings.profileIdMap[prof.id]);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
288
357
|
let initialPromptSet = false;
|
|
289
358
|
if (payload.initialPrompt) {
|
|
290
359
|
let targetPromptId = null;
|
|
@@ -331,9 +400,11 @@ let ProjectsService = class ProjectsService {
|
|
|
331
400
|
})
|
|
332
401
|
.filter((id) => !!id);
|
|
333
402
|
if (autoCleanStatusIds.length > 0) {
|
|
403
|
+
const currentSettings = this.settings.getSettings();
|
|
404
|
+
const existingAutoClean = currentSettings.autoClean?.statusIds ?? {};
|
|
334
405
|
await this.settings.updateSettings({
|
|
335
406
|
autoClean: {
|
|
336
|
-
statusIds: { [result.project.id]: autoCleanStatusIds },
|
|
407
|
+
statusIds: { ...existingAutoClean, [result.project.id]: autoCleanStatusIds },
|
|
337
408
|
},
|
|
338
409
|
});
|
|
339
410
|
logger.info({ projectId: result.project.id, autoCleanStatusIds }, 'Applied autoClean statuses from projectSettings');
|
|
@@ -344,9 +415,11 @@ let ProjectsService = class ProjectsService {
|
|
|
344
415
|
if (archiveTemplateStatus?.id) {
|
|
345
416
|
const archiveNewId = result.mappings.statusIdMap[archiveTemplateStatus.id];
|
|
346
417
|
if (archiveNewId) {
|
|
418
|
+
const currentSettings = this.settings.getSettings();
|
|
419
|
+
const existingAutoClean = currentSettings.autoClean?.statusIds ?? {};
|
|
347
420
|
await this.settings.updateSettings({
|
|
348
421
|
autoClean: {
|
|
349
|
-
statusIds: { [result.project.id]: [archiveNewId] },
|
|
422
|
+
statusIds: { ...existingAutoClean, [result.project.id]: [archiveNewId] },
|
|
350
423
|
},
|
|
351
424
|
});
|
|
352
425
|
logger.info({ projectId: result.project.id, archiveStatusId: archiveNewId }, 'Auto-configured Archive status for auto-clean (fallback)');
|
|
@@ -367,19 +440,106 @@ let ProjectsService = class ProjectsService {
|
|
|
367
440
|
if (archiveTemplateStatus?.id) {
|
|
368
441
|
const archiveNewId = result.mappings.statusIdMap[archiveTemplateStatus.id];
|
|
369
442
|
if (archiveNewId) {
|
|
443
|
+
const currentSettings = this.settings.getSettings();
|
|
444
|
+
const existingAutoClean = currentSettings.autoClean?.statusIds ?? {};
|
|
370
445
|
await this.settings.updateSettings({
|
|
371
446
|
autoClean: {
|
|
372
|
-
statusIds: { [result.project.id]: [archiveNewId] },
|
|
447
|
+
statusIds: { ...existingAutoClean, [result.project.id]: [archiveNewId] },
|
|
373
448
|
},
|
|
374
449
|
});
|
|
375
450
|
logger.info({ projectId: result.project.id, archiveStatusId: archiveNewId }, 'Auto-configured Archive status for auto-clean');
|
|
376
451
|
}
|
|
377
452
|
}
|
|
378
453
|
}
|
|
454
|
+
let watchersCreated = 0;
|
|
455
|
+
for (const w of payload.watchers) {
|
|
456
|
+
let scopeFilterId = null;
|
|
457
|
+
if (w.scopeFilterName && w.scope !== 'all') {
|
|
458
|
+
const scopeFilterNameLower = w.scopeFilterName.trim().toLowerCase();
|
|
459
|
+
switch (w.scope) {
|
|
460
|
+
case 'agent': {
|
|
461
|
+
scopeFilterId = agentNameToNewId.get(scopeFilterNameLower) ?? null;
|
|
462
|
+
break;
|
|
463
|
+
}
|
|
464
|
+
case 'profile': {
|
|
465
|
+
scopeFilterId = profileNameToNewId.get(scopeFilterNameLower) ?? null;
|
|
466
|
+
break;
|
|
467
|
+
}
|
|
468
|
+
case 'provider': {
|
|
469
|
+
const provider = providers.items.find((p) => p.name.trim().toLowerCase() === scopeFilterNameLower);
|
|
470
|
+
scopeFilterId = provider?.id ?? null;
|
|
471
|
+
break;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
if (!scopeFilterId) {
|
|
475
|
+
logger.warn({
|
|
476
|
+
projectId: result.project.id,
|
|
477
|
+
watcherName: w.name,
|
|
478
|
+
scope: w.scope,
|
|
479
|
+
scopeFilterName: w.scopeFilterName,
|
|
480
|
+
}, 'Could not resolve scope filter for template watcher, setting scope to "all"');
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
try {
|
|
484
|
+
const created = await this.storage.createWatcher({
|
|
485
|
+
projectId: result.project.id,
|
|
486
|
+
name: w.name,
|
|
487
|
+
description: w.description ?? null,
|
|
488
|
+
enabled: w.enabled,
|
|
489
|
+
scope: scopeFilterId ? w.scope : 'all',
|
|
490
|
+
scopeFilterId,
|
|
491
|
+
pollIntervalMs: w.pollIntervalMs,
|
|
492
|
+
viewportLines: w.viewportLines,
|
|
493
|
+
condition: w.condition,
|
|
494
|
+
cooldownMs: w.cooldownMs,
|
|
495
|
+
cooldownMode: w.cooldownMode,
|
|
496
|
+
eventName: w.eventName,
|
|
497
|
+
});
|
|
498
|
+
watchersCreated++;
|
|
499
|
+
if (created.enabled) {
|
|
500
|
+
await this.watcherRunner.startWatcher(created);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
catch (error) {
|
|
504
|
+
if (error instanceof Error &&
|
|
505
|
+
error.message.includes('UNIQUE constraint failed') &&
|
|
506
|
+
error.message.includes('event_name')) {
|
|
507
|
+
throw new common_1.BadRequestException({
|
|
508
|
+
message: `Duplicate watcher eventName: "${w.eventName}"`,
|
|
509
|
+
hint: 'Each watcher must have a unique eventName within the project.',
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
throw error;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
let subscribersCreated = 0;
|
|
516
|
+
for (const s of payload.subscribers) {
|
|
517
|
+
await this.storage.createSubscriber({
|
|
518
|
+
projectId: result.project.id,
|
|
519
|
+
name: s.name,
|
|
520
|
+
description: s.description ?? null,
|
|
521
|
+
enabled: s.enabled,
|
|
522
|
+
eventName: s.eventName,
|
|
523
|
+
eventFilter: s.eventFilter ?? null,
|
|
524
|
+
actionType: s.actionType,
|
|
525
|
+
actionInputs: s.actionInputs,
|
|
526
|
+
delayMs: s.delayMs,
|
|
527
|
+
cooldownMs: s.cooldownMs,
|
|
528
|
+
retryOnError: s.retryOnError,
|
|
529
|
+
groupName: s.groupName ?? null,
|
|
530
|
+
position: s.position ?? 0,
|
|
531
|
+
priority: s.priority ?? 0,
|
|
532
|
+
});
|
|
533
|
+
subscribersCreated++;
|
|
534
|
+
}
|
|
379
535
|
return {
|
|
380
536
|
success: true,
|
|
381
537
|
project: result.project,
|
|
382
|
-
imported:
|
|
538
|
+
imported: {
|
|
539
|
+
...result.imported,
|
|
540
|
+
watchers: watchersCreated,
|
|
541
|
+
subscribers: subscribersCreated,
|
|
542
|
+
},
|
|
383
543
|
mappings: result.mappings,
|
|
384
544
|
initialPromptSet,
|
|
385
545
|
message: 'Project created from template successfully.',
|
|
@@ -387,13 +547,15 @@ let ProjectsService = class ProjectsService {
|
|
|
387
547
|
}
|
|
388
548
|
async exportProject(projectId) {
|
|
389
549
|
logger.info({ projectId }, 'exportProject');
|
|
390
|
-
const [promptsRes, profilesRes, agentsRes, statusesRes, initialPrompt, settings] = await Promise.all([
|
|
391
|
-
this.storage.listPrompts(projectId,
|
|
550
|
+
const [promptsRes, profilesRes, agentsRes, statusesRes, initialPrompt, settings, watchersRes, subscribersRes,] = await Promise.all([
|
|
551
|
+
this.storage.listPrompts({ projectId, limit: 1000, offset: 0 }),
|
|
392
552
|
this.storage.listAgentProfiles({ projectId, limit: 1000, offset: 0 }),
|
|
393
553
|
this.storage.listAgents(projectId, { limit: 1000, offset: 0 }),
|
|
394
554
|
this.storage.listStatuses(projectId, { limit: 1000, offset: 0 }),
|
|
395
555
|
this.storage.getInitialSessionPrompt(projectId),
|
|
396
556
|
Promise.resolve(this.settings.getSettings()),
|
|
557
|
+
this.storage.listWatchers(projectId),
|
|
558
|
+
this.storage.listSubscribers(projectId),
|
|
397
559
|
]);
|
|
398
560
|
const secretKeys = new Set([
|
|
399
561
|
'apikey',
|
|
@@ -441,7 +603,8 @@ let ProjectsService = class ProjectsService {
|
|
|
441
603
|
return null;
|
|
442
604
|
return options;
|
|
443
605
|
};
|
|
444
|
-
const
|
|
606
|
+
const fullPrompts = await Promise.all(promptsRes.items.map((p) => this.storage.getPrompt(p.id)));
|
|
607
|
+
const prompts = fullPrompts.map((p) => ({
|
|
445
608
|
id: p.id,
|
|
446
609
|
title: p.title,
|
|
447
610
|
content: p.content,
|
|
@@ -471,6 +634,7 @@ let ProjectsService = class ProjectsService {
|
|
|
471
634
|
label: s.label,
|
|
472
635
|
color: s.color,
|
|
473
636
|
position: s.position,
|
|
637
|
+
mcpHidden: s.mcpHidden,
|
|
474
638
|
}));
|
|
475
639
|
const projectSettings = {};
|
|
476
640
|
if (initialPrompt?.title) {
|
|
@@ -490,6 +654,63 @@ let ProjectsService = class ProjectsService {
|
|
|
490
654
|
if (epicAssignedTemplate) {
|
|
491
655
|
projectSettings.epicAssignedTemplate = epicAssignedTemplate;
|
|
492
656
|
}
|
|
657
|
+
const watchers = await Promise.all(watchersRes.map(async (w) => {
|
|
658
|
+
let scopeFilterName = null;
|
|
659
|
+
if (w.scopeFilterId) {
|
|
660
|
+
switch (w.scope) {
|
|
661
|
+
case 'agent': {
|
|
662
|
+
const agent = agentsRes.items.find((a) => a.id === w.scopeFilterId);
|
|
663
|
+
scopeFilterName = agent?.name ?? null;
|
|
664
|
+
break;
|
|
665
|
+
}
|
|
666
|
+
case 'profile': {
|
|
667
|
+
const profile = profilesRes.items.find((p) => p.id === w.scopeFilterId);
|
|
668
|
+
scopeFilterName = profile?.name ?? null;
|
|
669
|
+
break;
|
|
670
|
+
}
|
|
671
|
+
case 'provider': {
|
|
672
|
+
try {
|
|
673
|
+
const provider = await this.storage.getProvider(w.scopeFilterId);
|
|
674
|
+
scopeFilterName = provider?.name ?? null;
|
|
675
|
+
}
|
|
676
|
+
catch {
|
|
677
|
+
scopeFilterName = null;
|
|
678
|
+
}
|
|
679
|
+
break;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
return {
|
|
684
|
+
id: w.id,
|
|
685
|
+
name: w.name,
|
|
686
|
+
description: w.description,
|
|
687
|
+
enabled: w.enabled,
|
|
688
|
+
scope: w.scope,
|
|
689
|
+
scopeFilterName,
|
|
690
|
+
pollIntervalMs: w.pollIntervalMs,
|
|
691
|
+
viewportLines: w.viewportLines,
|
|
692
|
+
condition: w.condition,
|
|
693
|
+
cooldownMs: w.cooldownMs,
|
|
694
|
+
cooldownMode: w.cooldownMode,
|
|
695
|
+
eventName: w.eventName,
|
|
696
|
+
};
|
|
697
|
+
}));
|
|
698
|
+
const subscribers = subscribersRes.map((s) => ({
|
|
699
|
+
id: s.id,
|
|
700
|
+
name: s.name,
|
|
701
|
+
description: s.description,
|
|
702
|
+
enabled: s.enabled,
|
|
703
|
+
eventName: s.eventName,
|
|
704
|
+
eventFilter: s.eventFilter,
|
|
705
|
+
actionType: s.actionType,
|
|
706
|
+
actionInputs: s.actionInputs,
|
|
707
|
+
delayMs: s.delayMs,
|
|
708
|
+
cooldownMs: s.cooldownMs,
|
|
709
|
+
retryOnError: s.retryOnError,
|
|
710
|
+
groupName: s.groupName,
|
|
711
|
+
position: s.position,
|
|
712
|
+
priority: s.priority,
|
|
713
|
+
}));
|
|
493
714
|
const exportPayload = {
|
|
494
715
|
version: 1,
|
|
495
716
|
exportedAt: new Date().toISOString(),
|
|
@@ -501,6 +722,8 @@ let ProjectsService = class ProjectsService {
|
|
|
501
722
|
? { promptId: initialPrompt.id, title: initialPrompt.title }
|
|
502
723
|
: null,
|
|
503
724
|
...(Object.keys(projectSettings).length > 0 && { projectSettings }),
|
|
725
|
+
watchers,
|
|
726
|
+
subscribers,
|
|
504
727
|
};
|
|
505
728
|
return exportPayload;
|
|
506
729
|
}
|
|
@@ -515,11 +738,13 @@ let ProjectsService = class ProjectsService {
|
|
|
515
738
|
available.set(prov.name.trim().toLowerCase(), prov.id);
|
|
516
739
|
}
|
|
517
740
|
const missingProviders = Array.from(providerNames).filter((n) => !available.has(n));
|
|
518
|
-
const [existingPrompts, existingProfiles, existingAgents, existingStatuses] = await Promise.all([
|
|
519
|
-
this.storage.listPrompts(input.projectId,
|
|
741
|
+
const [existingPrompts, existingProfiles, existingAgents, existingStatuses, existingWatchers, existingSubscribers,] = await Promise.all([
|
|
742
|
+
this.storage.listPrompts({ projectId: input.projectId, limit: 10000, offset: 0 }),
|
|
520
743
|
this.storage.listAgentProfiles({ projectId: input.projectId, limit: 10000, offset: 0 }),
|
|
521
744
|
this.storage.listAgents(input.projectId, { limit: 10000, offset: 0 }),
|
|
522
745
|
this.storage.listStatuses(input.projectId, { limit: 10000, offset: 0 }),
|
|
746
|
+
this.storage.listWatchers(input.projectId),
|
|
747
|
+
this.storage.listSubscribers(input.projectId),
|
|
523
748
|
]);
|
|
524
749
|
const templateStatusLabels = new Set(payload.statuses.map((s) => s.label.trim().toLowerCase()));
|
|
525
750
|
const unmatchedStatuses = [];
|
|
@@ -552,12 +777,16 @@ let ProjectsService = class ProjectsService {
|
|
|
552
777
|
profiles: payload.profiles.length,
|
|
553
778
|
agents: payload.agents.length,
|
|
554
779
|
statuses: payload.statuses.length,
|
|
780
|
+
watchers: payload.watchers.length,
|
|
781
|
+
subscribers: payload.subscribers.length,
|
|
555
782
|
},
|
|
556
783
|
toDelete: {
|
|
557
784
|
prompts: existingPrompts.total,
|
|
558
785
|
profiles: existingProfiles.total,
|
|
559
786
|
agents: existingAgents.total,
|
|
560
787
|
statuses: existingStatuses.total,
|
|
788
|
+
watchers: existingWatchers.length,
|
|
789
|
+
subscribers: existingSubscribers.length,
|
|
561
790
|
},
|
|
562
791
|
},
|
|
563
792
|
};
|
|
@@ -591,6 +820,12 @@ let ProjectsService = class ProjectsService {
|
|
|
591
820
|
for (const pr of existingPrompts.items) {
|
|
592
821
|
await this.storage.deletePrompt(pr.id);
|
|
593
822
|
}
|
|
823
|
+
for (const w of existingWatchers) {
|
|
824
|
+
await this.watchersService.deleteWatcher(w.id);
|
|
825
|
+
}
|
|
826
|
+
for (const s of existingSubscribers) {
|
|
827
|
+
await this.storage.deleteSubscriber(s.id);
|
|
828
|
+
}
|
|
594
829
|
await this.settings.updateSettings({
|
|
595
830
|
projectId: input.projectId,
|
|
596
831
|
initialSessionPromptId: null,
|
|
@@ -603,6 +838,10 @@ let ProjectsService = class ProjectsService {
|
|
|
603
838
|
for (const s of existingStatuses.items) {
|
|
604
839
|
existingStatusByLabel.set(s.label.trim().toLowerCase(), s);
|
|
605
840
|
}
|
|
841
|
+
const TEMP_POSITION_OFFSET = 100000;
|
|
842
|
+
for (const s of existingStatuses.items) {
|
|
843
|
+
await this.storage.updateStatus(s.id, { position: s.position + TEMP_POSITION_OFFSET });
|
|
844
|
+
}
|
|
606
845
|
for (const s of payload.statuses.sort((a, b) => a.position - b.position)) {
|
|
607
846
|
const labelKey = s.label.trim().toLowerCase();
|
|
608
847
|
const existing = existingStatusByLabel.get(labelKey);
|
|
@@ -610,6 +849,7 @@ let ProjectsService = class ProjectsService {
|
|
|
610
849
|
const updated = await this.storage.updateStatus(existing.id, {
|
|
611
850
|
color: s.color,
|
|
612
851
|
position: s.position,
|
|
852
|
+
mcpHidden: s.mcpHidden,
|
|
613
853
|
});
|
|
614
854
|
if (s.id)
|
|
615
855
|
statusIdMap[s.id] = updated.id;
|
|
@@ -621,6 +861,7 @@ let ProjectsService = class ProjectsService {
|
|
|
621
861
|
label: s.label,
|
|
622
862
|
color: s.color,
|
|
623
863
|
position: s.position,
|
|
864
|
+
mcpHidden: s.mcpHidden,
|
|
624
865
|
});
|
|
625
866
|
if (s.id)
|
|
626
867
|
statusIdMap[s.id] = created.id;
|
|
@@ -660,6 +901,7 @@ let ProjectsService = class ProjectsService {
|
|
|
660
901
|
promptIdMap[p.id] = created.id;
|
|
661
902
|
createdPrompts.push({ id: created.id, title: created.title });
|
|
662
903
|
}
|
|
904
|
+
const profileNameToNewId = new Map();
|
|
663
905
|
for (const prof of payload.profiles) {
|
|
664
906
|
const providerId = available.get(prof.provider.name.trim().toLowerCase());
|
|
665
907
|
if (!providerId) {
|
|
@@ -689,7 +931,9 @@ let ProjectsService = class ProjectsService {
|
|
|
689
931
|
});
|
|
690
932
|
if (prof.id)
|
|
691
933
|
profileIdMap[prof.id] = created.id;
|
|
934
|
+
profileNameToNewId.set(prof.name.trim().toLowerCase(), created.id);
|
|
692
935
|
}
|
|
936
|
+
const agentNameToNewId = new Map();
|
|
693
937
|
for (const a of payload.agents) {
|
|
694
938
|
const oldProfileId = a.profileId ?? '';
|
|
695
939
|
const newProfileId = oldProfileId && profileIdMap[oldProfileId] ? profileIdMap[oldProfileId] : undefined;
|
|
@@ -707,14 +951,77 @@ let ProjectsService = class ProjectsService {
|
|
|
707
951
|
});
|
|
708
952
|
if (a.id)
|
|
709
953
|
agentIdMap[a.id] = created.id;
|
|
954
|
+
agentNameToNewId.set(a.name.trim().toLowerCase(), created.id);
|
|
710
955
|
}
|
|
711
|
-
const
|
|
712
|
-
for (const
|
|
713
|
-
|
|
714
|
-
if (
|
|
715
|
-
|
|
956
|
+
const watcherIdMap = {};
|
|
957
|
+
for (const w of payload.watchers) {
|
|
958
|
+
let scopeFilterId = null;
|
|
959
|
+
if (w.scopeFilterName && w.scope !== 'all') {
|
|
960
|
+
const scopeFilterNameLower = w.scopeFilterName.trim().toLowerCase();
|
|
961
|
+
switch (w.scope) {
|
|
962
|
+
case 'agent': {
|
|
963
|
+
scopeFilterId = agentNameToNewId.get(scopeFilterNameLower) ?? null;
|
|
964
|
+
break;
|
|
965
|
+
}
|
|
966
|
+
case 'profile': {
|
|
967
|
+
scopeFilterId = profileNameToNewId.get(scopeFilterNameLower) ?? null;
|
|
968
|
+
break;
|
|
969
|
+
}
|
|
970
|
+
case 'provider': {
|
|
971
|
+
const provider = providers.items.find((p) => p.name.trim().toLowerCase() === scopeFilterNameLower);
|
|
972
|
+
scopeFilterId = provider?.id ?? null;
|
|
973
|
+
break;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
if (!scopeFilterId) {
|
|
977
|
+
logger.warn({ watcherName: w.name, scope: w.scope, scopeFilterName: w.scopeFilterName }, 'Could not resolve scope filter, setting scope to "all"');
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
const created = await this.storage.createWatcher({
|
|
981
|
+
projectId: input.projectId,
|
|
982
|
+
name: w.name,
|
|
983
|
+
description: w.description ?? null,
|
|
984
|
+
enabled: w.enabled,
|
|
985
|
+
scope: scopeFilterId ? w.scope : 'all',
|
|
986
|
+
scopeFilterId,
|
|
987
|
+
pollIntervalMs: w.pollIntervalMs,
|
|
988
|
+
viewportLines: w.viewportLines,
|
|
989
|
+
condition: w.condition,
|
|
990
|
+
cooldownMs: w.cooldownMs,
|
|
991
|
+
cooldownMode: w.cooldownMode,
|
|
992
|
+
eventName: w.eventName,
|
|
993
|
+
});
|
|
994
|
+
if (w.id)
|
|
995
|
+
watcherIdMap[w.id] = created.id;
|
|
996
|
+
if (created.enabled) {
|
|
997
|
+
await this.watcherRunner.startWatcher(created);
|
|
716
998
|
}
|
|
717
999
|
}
|
|
1000
|
+
const subscriberIdMap = {};
|
|
1001
|
+
for (const s of payload.subscribers) {
|
|
1002
|
+
const created = await this.storage.createSubscriber({
|
|
1003
|
+
projectId: input.projectId,
|
|
1004
|
+
name: s.name,
|
|
1005
|
+
description: s.description ?? null,
|
|
1006
|
+
enabled: s.enabled,
|
|
1007
|
+
eventName: s.eventName,
|
|
1008
|
+
eventFilter: s.eventFilter ?? null,
|
|
1009
|
+
actionType: s.actionType,
|
|
1010
|
+
actionInputs: s.actionInputs,
|
|
1011
|
+
delayMs: s.delayMs,
|
|
1012
|
+
cooldownMs: s.cooldownMs,
|
|
1013
|
+
retryOnError: s.retryOnError,
|
|
1014
|
+
groupName: s.groupName ?? null,
|
|
1015
|
+
position: s.position ?? 0,
|
|
1016
|
+
priority: s.priority ?? 0,
|
|
1017
|
+
});
|
|
1018
|
+
if (s.id)
|
|
1019
|
+
subscriberIdMap[s.id] = created.id;
|
|
1020
|
+
}
|
|
1021
|
+
logger.info({
|
|
1022
|
+
watchersCreated: payload.watchers.length,
|
|
1023
|
+
subscribersCreated: payload.subscribers.length,
|
|
1024
|
+
}, 'Watchers and subscribers imported');
|
|
718
1025
|
const existingEpics = await this.storage.listEpics(input.projectId, {
|
|
719
1026
|
limit: 100000,
|
|
720
1027
|
offset: 0,
|
|
@@ -725,7 +1032,7 @@ let ProjectsService = class ProjectsService {
|
|
|
725
1032
|
if (epic.agentId) {
|
|
726
1033
|
const oldAgentName = oldAgentIdToName.get(epic.agentId);
|
|
727
1034
|
if (oldAgentName) {
|
|
728
|
-
const newAgentId =
|
|
1035
|
+
const newAgentId = agentNameToNewId.get(oldAgentName);
|
|
729
1036
|
if (newAgentId) {
|
|
730
1037
|
await this.storage.updateEpic(epic.id, { agentId: newAgentId }, epic.version);
|
|
731
1038
|
epicsRemapped++;
|
|
@@ -779,9 +1086,11 @@ let ProjectsService = class ProjectsService {
|
|
|
779
1086
|
.map((label) => templateLabelToStatusId.get(label.toLowerCase()))
|
|
780
1087
|
.filter((id) => !!id);
|
|
781
1088
|
if (autoCleanStatusIds.length > 0) {
|
|
1089
|
+
const currentSettings = this.settings.getSettings();
|
|
1090
|
+
const existingAutoClean = currentSettings.autoClean?.statusIds ?? {};
|
|
782
1091
|
await this.settings.updateSettings({
|
|
783
1092
|
autoClean: {
|
|
784
|
-
statusIds: { [input.projectId]: autoCleanStatusIds },
|
|
1093
|
+
statusIds: { ...existingAutoClean, [input.projectId]: autoCleanStatusIds },
|
|
785
1094
|
},
|
|
786
1095
|
});
|
|
787
1096
|
logger.info({ projectId: input.projectId, autoCleanStatusIds }, 'Applied autoClean statuses from projectSettings');
|
|
@@ -807,12 +1116,16 @@ let ProjectsService = class ProjectsService {
|
|
|
807
1116
|
profiles: payload.profiles.length,
|
|
808
1117
|
agents: payload.agents.length,
|
|
809
1118
|
statuses: payload.statuses.length,
|
|
1119
|
+
watchers: payload.watchers.length,
|
|
1120
|
+
subscribers: payload.subscribers.length,
|
|
810
1121
|
},
|
|
811
1122
|
deleted: {
|
|
812
1123
|
prompts: existingPrompts.total,
|
|
813
1124
|
profiles: existingProfiles.total,
|
|
814
1125
|
agents: existingAgents.total,
|
|
815
1126
|
statuses: 0,
|
|
1127
|
+
watchers: existingWatchers.length,
|
|
1128
|
+
subscribers: existingSubscribers.length,
|
|
816
1129
|
},
|
|
817
1130
|
epics: {
|
|
818
1131
|
preserved: existingEpics.total,
|
|
@@ -820,7 +1133,14 @@ let ProjectsService = class ProjectsService {
|
|
|
820
1133
|
agentCleared: epicsCleared,
|
|
821
1134
|
},
|
|
822
1135
|
},
|
|
823
|
-
mappings: {
|
|
1136
|
+
mappings: {
|
|
1137
|
+
promptIdMap,
|
|
1138
|
+
profileIdMap,
|
|
1139
|
+
agentIdMap,
|
|
1140
|
+
statusIdMap,
|
|
1141
|
+
watcherIdMap,
|
|
1142
|
+
subscriberIdMap,
|
|
1143
|
+
},
|
|
824
1144
|
initialPromptSet,
|
|
825
1145
|
message: 'Project configuration replaced. Epics preserved.',
|
|
826
1146
|
};
|
|
@@ -859,6 +1179,8 @@ exports.ProjectsService = ProjectsService = __decorate([
|
|
|
859
1179
|
(0, common_1.Injectable)(),
|
|
860
1180
|
__param(0, (0, common_1.Inject)(storage_interface_1.STORAGE_SERVICE)),
|
|
861
1181
|
__metadata("design:paramtypes", [Object, sessions_service_1.SessionsService,
|
|
862
|
-
settings_service_1.SettingsService
|
|
1182
|
+
settings_service_1.SettingsService,
|
|
1183
|
+
watchers_service_1.WatchersService,
|
|
1184
|
+
watcher_runner_service_1.WatcherRunnerService])
|
|
863
1185
|
], ProjectsService);
|
|
864
1186
|
//# sourceMappingURL=projects.service.js.map
|