ccjk 12.0.7 → 12.0.8
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/package.json +1 -1
- package/dist/chunks/agent-teams.mjs +0 -136
- package/dist/chunks/agent.mjs +0 -1439
- package/dist/chunks/agents.mjs +0 -3778
- package/dist/chunks/api-cli.mjs +0 -132
- package/dist/chunks/api-providers.mjs +0 -129
- package/dist/chunks/api.mjs +0 -112
- package/dist/chunks/auto-bootstrap.mjs +0 -358
- package/dist/chunks/auto-init.mjs +0 -7584
- package/dist/chunks/auto-updater.mjs +0 -410
- package/dist/chunks/banner.mjs +0 -188
- package/dist/chunks/bash.mjs +0 -187
- package/dist/chunks/boost.mjs +0 -397
- package/dist/chunks/ccjk-agents.mjs +0 -414
- package/dist/chunks/ccjk-all.mjs +0 -1028
- package/dist/chunks/ccjk-config.mjs +0 -261
- package/dist/chunks/ccjk-hooks.mjs +0 -1074
- package/dist/chunks/ccjk-mcp.mjs +0 -761
- package/dist/chunks/ccjk-setup.mjs +0 -763
- package/dist/chunks/ccjk-skills.mjs +0 -514
- package/dist/chunks/ccr.mjs +0 -98
- package/dist/chunks/ccu.mjs +0 -40
- package/dist/chunks/check-updates.mjs +0 -108
- package/dist/chunks/claude-code-config-manager.mjs +0 -750
- package/dist/chunks/claude-code-incremental-manager.mjs +0 -623
- package/dist/chunks/claude-config.mjs +0 -236
- package/dist/chunks/claude-wrapper.mjs +0 -85
- package/dist/chunks/cleanup-migration.mjs +0 -20
- package/dist/chunks/cli-hook.mjs +0 -2285
- package/dist/chunks/cloud-sync.mjs +0 -29
- package/dist/chunks/codex-config-switch.mjs +0 -451
- package/dist/chunks/codex-provider-manager.mjs +0 -236
- package/dist/chunks/codex-uninstaller.mjs +0 -404
- package/dist/chunks/codex.mjs +0 -2077
- package/dist/chunks/commands.mjs +0 -108
- package/dist/chunks/commands2.mjs +0 -413
- package/dist/chunks/commit.mjs +0 -138
- package/dist/chunks/completion.mjs +0 -515
- package/dist/chunks/config-consolidator.mjs +0 -172
- package/dist/chunks/config-switch.mjs +0 -317
- package/dist/chunks/config.mjs +0 -379
- package/dist/chunks/config2.mjs +0 -477
- package/dist/chunks/config3.mjs +0 -470
- package/dist/chunks/constants.mjs +0 -133
- package/dist/chunks/context-loader.mjs +0 -343
- package/dist/chunks/context.mjs +0 -372
- package/dist/chunks/convoy-manager.mjs +0 -880
- package/dist/chunks/dashboard.mjs +0 -476
- package/dist/chunks/doctor.mjs +0 -964
- package/dist/chunks/evolution.mjs +0 -382
- package/dist/chunks/features.mjs +0 -698
- package/dist/chunks/fish.mjs +0 -181
- package/dist/chunks/fs-operations.mjs +0 -192
- package/dist/chunks/health-alerts.mjs +0 -304
- package/dist/chunks/health-check.mjs +0 -532
- package/dist/chunks/help.mjs +0 -340
- package/dist/chunks/hook-installer.mjs +0 -45
- package/dist/chunks/index.mjs +0 -24
- package/dist/chunks/index10.mjs +0 -1171
- package/dist/chunks/index11.mjs +0 -1008
- package/dist/chunks/index12.mjs +0 -193
- package/dist/chunks/index13.mjs +0 -218
- package/dist/chunks/index14.mjs +0 -663
- package/dist/chunks/index2.mjs +0 -19
- package/dist/chunks/index3.mjs +0 -19092
- package/dist/chunks/index4.mjs +0 -8
- package/dist/chunks/index5.mjs +0 -7600
- package/dist/chunks/index6.mjs +0 -171
- package/dist/chunks/index7.mjs +0 -3583
- package/dist/chunks/index8.mjs +0 -19
- package/dist/chunks/index9.mjs +0 -616
- package/dist/chunks/init.mjs +0 -1606
- package/dist/chunks/installer.mjs +0 -690
- package/dist/chunks/installer2.mjs +0 -179
- package/dist/chunks/interview.mjs +0 -2927
- package/dist/chunks/json-config.mjs +0 -60
- package/dist/chunks/linux.mjs +0 -3863
- package/dist/chunks/macos.mjs +0 -69
- package/dist/chunks/main.mjs +0 -635
- package/dist/chunks/manager.mjs +0 -1048
- package/dist/chunks/marketplace.mjs +0 -949
- package/dist/chunks/mcp-cli.mjs +0 -204
- package/dist/chunks/mcp-performance.mjs +0 -187
- package/dist/chunks/mcp.mjs +0 -1231
- package/dist/chunks/menu.mjs +0 -652
- package/dist/chunks/metrics-display.mjs +0 -153
- package/dist/chunks/migrator.mjs +0 -178
- package/dist/chunks/monitor.mjs +0 -1856
- package/dist/chunks/notification.mjs +0 -1864
- package/dist/chunks/onboarding.mjs +0 -385
- package/dist/chunks/package.mjs +0 -3
- package/dist/chunks/paradigm.mjs +0 -74
- package/dist/chunks/permission-manager.mjs +0 -132
- package/dist/chunks/permissions.mjs +0 -265
- package/dist/chunks/persistence-manager.mjs +0 -794
- package/dist/chunks/persistence.mjs +0 -667
- package/dist/chunks/platform.mjs +0 -391
- package/dist/chunks/plugin.mjs +0 -1936
- package/dist/chunks/powershell.mjs +0 -213
- package/dist/chunks/prompts.mjs +0 -241
- package/dist/chunks/providers.mjs +0 -260
- package/dist/chunks/quick-actions.mjs +0 -320
- package/dist/chunks/quick-provider.mjs +0 -682
- package/dist/chunks/quick-setup.mjs +0 -412
- package/dist/chunks/remote.mjs +0 -497
- package/dist/chunks/session.mjs +0 -878
- package/dist/chunks/sessions.mjs +0 -106
- package/dist/chunks/silent-updater.mjs +0 -396
- package/dist/chunks/simple-config.mjs +0 -98
- package/dist/chunks/skill.mjs +0 -117
- package/dist/chunks/skill2.mjs +0 -9003
- package/dist/chunks/skills-sync.mjs +0 -6460
- package/dist/chunks/skills.mjs +0 -567
- package/dist/chunks/slash-commands.mjs +0 -207
- package/dist/chunks/smart-defaults.mjs +0 -412
- package/dist/chunks/smart-guide.mjs +0 -194
- package/dist/chunks/startup.mjs +0 -487
- package/dist/chunks/stats.mjs +0 -410
- package/dist/chunks/status.mjs +0 -289
- package/dist/chunks/team.mjs +0 -63
- package/dist/chunks/thinking.mjs +0 -626
- package/dist/chunks/trace.mjs +0 -57
- package/dist/chunks/uninstall.mjs +0 -849
- package/dist/chunks/update.mjs +0 -167
- package/dist/chunks/upgrade-manager.mjs +0 -204
- package/dist/chunks/version-checker.mjs +0 -881
- package/dist/chunks/vim.mjs +0 -903
- package/dist/chunks/windows.mjs +0 -14
- package/dist/chunks/workflows.mjs +0 -633
- package/dist/chunks/wsl.mjs +0 -129
- package/dist/chunks/zero-config.mjs +0 -374
- package/dist/chunks/zsh.mjs +0 -182
- package/dist/cli.d.mts +0 -1
- package/dist/cli.d.ts +0 -1
- package/dist/cli.mjs +0 -2199
- package/dist/i18n/locales/en/agent-teams.json +0 -18
- package/dist/i18n/locales/en/agentBrowser.json +0 -79
- package/dist/i18n/locales/en/agents.json +0 -135
- package/dist/i18n/locales/en/api.json +0 -63
- package/dist/i18n/locales/en/ccjk-agents.json +0 -33
- package/dist/i18n/locales/en/ccjk-all.json +0 -23
- package/dist/i18n/locales/en/ccjk-skills.json +0 -22
- package/dist/i18n/locales/en/ccjk.json +0 -276
- package/dist/i18n/locales/en/ccr.json +0 -65
- package/dist/i18n/locales/en/claude-md.json +0 -73
- package/dist/i18n/locales/en/cli.json +0 -152
- package/dist/i18n/locales/en/cloud-setup.json +0 -31
- package/dist/i18n/locales/en/cloud-sync.json +0 -147
- package/dist/i18n/locales/en/cloud.json +0 -40
- package/dist/i18n/locales/en/cloudPlugins.json +0 -118
- package/dist/i18n/locales/en/codex.json +0 -127
- package/dist/i18n/locales/en/cometix.json +0 -29
- package/dist/i18n/locales/en/common.json +0 -68
- package/dist/i18n/locales/en/config.json +0 -108
- package/dist/i18n/locales/en/configuration.json +0 -226
- package/dist/i18n/locales/en/context.json +0 -85
- package/dist/i18n/locales/en/dashboard.json +0 -78
- package/dist/i18n/locales/en/errors.json +0 -26
- package/dist/i18n/locales/en/evolution.json +0 -54
- package/dist/i18n/locales/en/hooks.json +0 -74
- package/dist/i18n/locales/en/hooksSync.json +0 -133
- package/dist/i18n/locales/en/installation.json +0 -83
- package/dist/i18n/locales/en/interview.json +0 -104
- package/dist/i18n/locales/en/language.json +0 -19
- package/dist/i18n/locales/en/lsp.json +0 -78
- package/dist/i18n/locales/en/marketplace.json +0 -116
- package/dist/i18n/locales/en/mcp.json +0 -178
- package/dist/i18n/locales/en/memory.json +0 -92
- package/dist/i18n/locales/en/menu.json +0 -143
- package/dist/i18n/locales/en/multi-config.json +0 -79
- package/dist/i18n/locales/en/notification.json +0 -307
- package/dist/i18n/locales/en/permissions.json +0 -95
- package/dist/i18n/locales/en/persistence.json +0 -127
- package/dist/i18n/locales/en/plugins.json +0 -146
- package/dist/i18n/locales/en/quick-actions.json +0 -78
- package/dist/i18n/locales/en/registry.json +0 -54
- package/dist/i18n/locales/en/remote.json +0 -93
- package/dist/i18n/locales/en/sandbox.json +0 -44
- package/dist/i18n/locales/en/setup.json +0 -44
- package/dist/i18n/locales/en/shencha.json +0 -14
- package/dist/i18n/locales/en/skills.json +0 -100
- package/dist/i18n/locales/en/skillsSync.json +0 -74
- package/dist/i18n/locales/en/smartGuide.json +0 -49
- package/dist/i18n/locales/en/stats.json +0 -20
- package/dist/i18n/locales/en/subagent.json +0 -69
- package/dist/i18n/locales/en/superpowers.json +0 -117
- package/dist/i18n/locales/en/team.json +0 -7
- package/dist/i18n/locales/en/thinking.json +0 -65
- package/dist/i18n/locales/en/tools.json +0 -42
- package/dist/i18n/locales/en/uninstall.json +0 -56
- package/dist/i18n/locales/en/updater.json +0 -29
- package/dist/i18n/locales/en/vim.json +0 -169
- package/dist/i18n/locales/en/workflow.json +0 -55
- package/dist/i18n/locales/en/workspace.json +0 -108
- package/dist/i18n/locales/zh-CN/agent-teams.json +0 -18
- package/dist/i18n/locales/zh-CN/agentBrowser.json +0 -79
- package/dist/i18n/locales/zh-CN/agents.json +0 -135
- package/dist/i18n/locales/zh-CN/api.json +0 -63
- package/dist/i18n/locales/zh-CN/ccjk-agents.json +0 -33
- package/dist/i18n/locales/zh-CN/ccjk-all.json +0 -23
- package/dist/i18n/locales/zh-CN/ccjk-skills.json +0 -22
- package/dist/i18n/locales/zh-CN/ccjk.json +0 -276
- package/dist/i18n/locales/zh-CN/ccr.json +0 -65
- package/dist/i18n/locales/zh-CN/claude-md.json +0 -73
- package/dist/i18n/locales/zh-CN/cli.json +0 -152
- package/dist/i18n/locales/zh-CN/cloud-setup.json +0 -31
- package/dist/i18n/locales/zh-CN/cloud-sync.json +0 -147
- package/dist/i18n/locales/zh-CN/cloud.json +0 -40
- package/dist/i18n/locales/zh-CN/cloudPlugins.json +0 -118
- package/dist/i18n/locales/zh-CN/codex.json +0 -127
- package/dist/i18n/locales/zh-CN/cometix.json +0 -29
- package/dist/i18n/locales/zh-CN/common.json +0 -68
- package/dist/i18n/locales/zh-CN/config.json +0 -108
- package/dist/i18n/locales/zh-CN/configuration.json +0 -224
- package/dist/i18n/locales/zh-CN/context.json +0 -85
- package/dist/i18n/locales/zh-CN/dashboard.json +0 -78
- package/dist/i18n/locales/zh-CN/errors.json +0 -26
- package/dist/i18n/locales/zh-CN/evolution.json +0 -54
- package/dist/i18n/locales/zh-CN/hooks.json +0 -74
- package/dist/i18n/locales/zh-CN/hooksSync.json +0 -133
- package/dist/i18n/locales/zh-CN/installation.json +0 -83
- package/dist/i18n/locales/zh-CN/interview.json +0 -104
- package/dist/i18n/locales/zh-CN/language.json +0 -19
- package/dist/i18n/locales/zh-CN/lsp.json +0 -78
- package/dist/i18n/locales/zh-CN/marketplace.json +0 -116
- package/dist/i18n/locales/zh-CN/mcp.json +0 -178
- package/dist/i18n/locales/zh-CN/memory.json +0 -92
- package/dist/i18n/locales/zh-CN/menu.json +0 -143
- package/dist/i18n/locales/zh-CN/multi-config.json +0 -79
- package/dist/i18n/locales/zh-CN/notification.json +0 -307
- package/dist/i18n/locales/zh-CN/permissions.json +0 -95
- package/dist/i18n/locales/zh-CN/persistence.json +0 -127
- package/dist/i18n/locales/zh-CN/plugins.json +0 -146
- package/dist/i18n/locales/zh-CN/quick-actions.json +0 -78
- package/dist/i18n/locales/zh-CN/registry.json +0 -54
- package/dist/i18n/locales/zh-CN/remote.json +0 -93
- package/dist/i18n/locales/zh-CN/sandbox.json +0 -44
- package/dist/i18n/locales/zh-CN/setup.json +0 -44
- package/dist/i18n/locales/zh-CN/shencha.json +0 -14
- package/dist/i18n/locales/zh-CN/skills.json +0 -100
- package/dist/i18n/locales/zh-CN/skillsSync.json +0 -74
- package/dist/i18n/locales/zh-CN/smartGuide.json +0 -49
- package/dist/i18n/locales/zh-CN/stats.json +0 -20
- package/dist/i18n/locales/zh-CN/subagent.json +0 -69
- package/dist/i18n/locales/zh-CN/superpowers.json +0 -117
- package/dist/i18n/locales/zh-CN/team.json +0 -7
- package/dist/i18n/locales/zh-CN/thinking.json +0 -65
- package/dist/i18n/locales/zh-CN/tools.json +0 -42
- package/dist/i18n/locales/zh-CN/uninstall.json +0 -56
- package/dist/i18n/locales/zh-CN/updater.json +0 -29
- package/dist/i18n/locales/zh-CN/vim.json +0 -169
- package/dist/i18n/locales/zh-CN/workflow.json +0 -55
- package/dist/i18n/locales/zh-CN/workspace.json +0 -108
- package/dist/index.d.mts +0 -5295
- package/dist/index.d.ts +0 -5295
- package/dist/index.mjs +0 -4941
- package/dist/shared/ccjk.B364Fu0N.mjs +0 -1819
- package/dist/shared/ccjk.BAGoDD49.mjs +0 -36
- package/dist/shared/ccjk.BBtCGd_g.mjs +0 -899
- package/dist/shared/ccjk.BFQ7yr5S.mjs +0 -16
- package/dist/shared/ccjk.BFxsJM0k.mjs +0 -599
- package/dist/shared/ccjk.BIxuVL3_.mjs +0 -25
- package/dist/shared/ccjk.BRZ9ww8S.mjs +0 -142
- package/dist/shared/ccjk.BoApaI4j.mjs +0 -28
- package/dist/shared/ccjk.BrPUmTqm.mjs +0 -266
- package/dist/shared/ccjk.BtB1e5jm.mjs +0 -171
- package/dist/shared/ccjk.BwfbSKN2.mjs +0 -1051
- package/dist/shared/ccjk.BxSmJ8B7.mjs +0 -243
- package/dist/shared/ccjk.Bx_rmYfN.mjs +0 -69
- package/dist/shared/ccjk.C2jHOZVP.mjs +0 -52
- package/dist/shared/ccjk.CL4Yat0G.mjs +0 -303
- package/dist/shared/ccjk.COweQ1RR.mjs +0 -5
- package/dist/shared/ccjk.CePkJq2S.mjs +0 -223
- package/dist/shared/ccjk.CfKKcvWy.mjs +0 -126
- package/dist/shared/ccjk.Cjgrln_h.mjs +0 -297
- package/dist/shared/ccjk.Cjj8SVrn.mjs +0 -54
- package/dist/shared/ccjk.CxpGa6MC.mjs +0 -2724
- package/dist/shared/ccjk.D5MFQT7w.mjs +0 -400
- package/dist/shared/ccjk.D6ycHbak.mjs +0 -270
- package/dist/shared/ccjk.D8ZLYSZZ.mjs +0 -299
- package/dist/shared/ccjk.DG_o24cZ.mjs +0 -88
- package/dist/shared/ccjk.DLLw-h4Y.mjs +0 -460
- package/dist/shared/ccjk.DOwtZMk8.mjs +0 -4019
- package/dist/shared/ccjk.DS7UESmF.mjs +0 -2451
- package/dist/shared/ccjk.DTdjs-qK.mjs +0 -1447
- package/dist/shared/ccjk.DXRAZcix.mjs +0 -66
- package/dist/shared/ccjk.DsYaCCx4.mjs +0 -317
- package/dist/shared/ccjk.J8YiPsOw.mjs +0 -259
- package/dist/shared/ccjk.KfSWcGlE.mjs +0 -38
- package/dist/shared/ccjk.RyizuzOI.mjs +0 -21
- package/dist/shared/ccjk.SPoXMvZD.mjs +0 -1242
- package/dist/shared/ccjk.T_cX87dY.mjs +0 -15
- package/dist/shared/ccjk.UIvifqNE.mjs +0 -1486
- package/dist/shared/ccjk._dESH4Rk.mjs +0 -111
- package/dist/shared/ccjk.bQ7Dh1g4.mjs +0 -249
- package/dist/shared/ccjk.c-ETfBZ_.mjs +0 -617
- package/dist/shared/ccjk.gDEDGD_t.mjs +0 -38
- package/dist/shared/ccjk.hoqrwWdN.mjs +0 -333
- package/dist/shared/ccjk.waa2ikKJ.mjs +0 -351
package/dist/chunks/cli-hook.mjs
DELETED
|
@@ -1,2285 +0,0 @@
|
|
|
1
|
-
import { EventEmitter } from 'node:events';
|
|
2
|
-
import { a as getGlobalStateManager, g as getGlobalConvoyManager } from './convoy-manager.mjs';
|
|
3
|
-
import { n as nanoid } from '../shared/ccjk.BoApaI4j.mjs';
|
|
4
|
-
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
5
|
-
import { j as join } from '../shared/ccjk.bQ7Dh1g4.mjs';
|
|
6
|
-
import 'node:os';
|
|
7
|
-
import './main.mjs';
|
|
8
|
-
import 'module';
|
|
9
|
-
import 'node:child_process';
|
|
10
|
-
import 'node:path';
|
|
11
|
-
import 'node:process';
|
|
12
|
-
import 'node:stream';
|
|
13
|
-
import 'node:readline';
|
|
14
|
-
import 'node:crypto';
|
|
15
|
-
|
|
16
|
-
class ProgressTracker extends EventEmitter {
|
|
17
|
-
config;
|
|
18
|
-
convoyManager;
|
|
19
|
-
trackedConvoys = /* @__PURE__ */ new Map();
|
|
20
|
-
taskStartTimes = /* @__PURE__ */ new Map();
|
|
21
|
-
taskDurations = /* @__PURE__ */ new Map();
|
|
22
|
-
constructor(convoyManager, config = {}) {
|
|
23
|
-
super();
|
|
24
|
-
this.convoyManager = convoyManager;
|
|
25
|
-
this.config = {
|
|
26
|
-
updateInterval: config.updateInterval ?? 1e3,
|
|
27
|
-
consoleOutput: config.consoleOutput ?? false,
|
|
28
|
-
progressBarWidth: config.progressBarWidth ?? 40
|
|
29
|
-
};
|
|
30
|
-
this.setupEventListeners();
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Start tracking a convoy
|
|
34
|
-
*/
|
|
35
|
-
track(convoyId) {
|
|
36
|
-
if (this.trackedConvoys.has(convoyId)) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
const interval = setInterval(() => {
|
|
40
|
-
this.emitProgress(convoyId);
|
|
41
|
-
}, this.config.updateInterval);
|
|
42
|
-
this.trackedConvoys.set(convoyId, interval);
|
|
43
|
-
this.taskDurations.set(convoyId, []);
|
|
44
|
-
this.emitProgress(convoyId);
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Stop tracking a convoy
|
|
48
|
-
*/
|
|
49
|
-
untrack(convoyId) {
|
|
50
|
-
const interval = this.trackedConvoys.get(convoyId);
|
|
51
|
-
if (interval) {
|
|
52
|
-
clearInterval(interval);
|
|
53
|
-
this.trackedConvoys.delete(convoyId);
|
|
54
|
-
}
|
|
55
|
-
this.taskDurations.delete(convoyId);
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Get current progress for a convoy
|
|
59
|
-
*/
|
|
60
|
-
getProgress(convoyId) {
|
|
61
|
-
const convoy = this.convoyManager.get(convoyId);
|
|
62
|
-
if (!convoy)
|
|
63
|
-
return null;
|
|
64
|
-
return this.buildProgressUpdate(convoy);
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Get progress bar string
|
|
68
|
-
*/
|
|
69
|
-
getProgressBar(convoyId) {
|
|
70
|
-
const convoy = this.convoyManager.get(convoyId);
|
|
71
|
-
if (!convoy)
|
|
72
|
-
return "";
|
|
73
|
-
return this.buildProgressBar(convoy.progress);
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Get formatted progress string
|
|
77
|
-
*/
|
|
78
|
-
getFormattedProgress(convoyId) {
|
|
79
|
-
const update = this.getProgress(convoyId);
|
|
80
|
-
if (!update)
|
|
81
|
-
return "Convoy not found";
|
|
82
|
-
const lines = [
|
|
83
|
-
`${update.convoyName} [${update.convoyId}]`,
|
|
84
|
-
this.buildProgressBar(update.progress),
|
|
85
|
-
`Status: ${this.formatStatus(update.status)}`,
|
|
86
|
-
`Progress: ${update.progress}% (${update.completedTasks}/${update.totalTasks})`
|
|
87
|
-
];
|
|
88
|
-
if (update.inProgressTasks > 0) {
|
|
89
|
-
lines.push(`In Progress: ${update.inProgressTasks}`);
|
|
90
|
-
}
|
|
91
|
-
if (update.failedTasks > 0) {
|
|
92
|
-
lines.push(`Failed: ${update.failedTasks}`);
|
|
93
|
-
}
|
|
94
|
-
if (update.currentTasks.length > 0) {
|
|
95
|
-
lines.push("\nCurrent Tasks:");
|
|
96
|
-
for (const task of update.currentTasks) {
|
|
97
|
-
lines.push(` - ${task.title} (${task.assignedTo ?? "unassigned"})`);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
if (update.estimatedCompletion) {
|
|
101
|
-
lines.push(`
|
|
102
|
-
ETA: ${this.formatTime(update.estimatedCompletion.getTime() - Date.now())}`);
|
|
103
|
-
}
|
|
104
|
-
lines.push(`Elapsed: ${this.formatTime(update.elapsedTime)}`);
|
|
105
|
-
return lines.join("\n");
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Stop all tracking
|
|
109
|
-
*/
|
|
110
|
-
stopAll() {
|
|
111
|
-
const convoyIds = Array.from(this.trackedConvoys.keys());
|
|
112
|
-
for (const convoyId of convoyIds) {
|
|
113
|
-
this.untrack(convoyId);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Destroy tracker
|
|
118
|
-
*/
|
|
119
|
-
destroy() {
|
|
120
|
-
this.stopAll();
|
|
121
|
-
this.removeAllListeners();
|
|
122
|
-
}
|
|
123
|
-
// ========================================================================
|
|
124
|
-
// Private Methods
|
|
125
|
-
// ========================================================================
|
|
126
|
-
setupEventListeners() {
|
|
127
|
-
this.convoyManager.on("task:started", (convoy, task) => {
|
|
128
|
-
this.taskStartTimes.set(task.id, Date.now());
|
|
129
|
-
});
|
|
130
|
-
this.convoyManager.on("task:completed", (convoy, task) => {
|
|
131
|
-
const startTime = this.taskStartTimes.get(task.id);
|
|
132
|
-
if (startTime) {
|
|
133
|
-
const duration = Date.now() - startTime;
|
|
134
|
-
const durations = this.taskDurations.get(convoy.id) ?? [];
|
|
135
|
-
durations.push(duration);
|
|
136
|
-
this.taskDurations.set(convoy.id, durations);
|
|
137
|
-
this.taskStartTimes.delete(task.id);
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
this.convoyManager.on("convoy:completed", (convoy) => {
|
|
141
|
-
this.untrack(convoy.id);
|
|
142
|
-
});
|
|
143
|
-
this.convoyManager.on("convoy:failed", (convoy) => {
|
|
144
|
-
this.untrack(convoy.id);
|
|
145
|
-
});
|
|
146
|
-
this.convoyManager.on("convoy:cancelled", (convoy) => {
|
|
147
|
-
this.untrack(convoy.id);
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
emitProgress(convoyId) {
|
|
151
|
-
const update = this.getProgress(convoyId);
|
|
152
|
-
if (update) {
|
|
153
|
-
this.emit("progress", update);
|
|
154
|
-
if (this.config.consoleOutput) {
|
|
155
|
-
console.log(this.getFormattedProgress(convoyId));
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
buildProgressUpdate(convoy) {
|
|
160
|
-
const inProgressTasks = convoy.tasks.filter((t) => t.status === "in_progress").length;
|
|
161
|
-
const pendingTasks = convoy.tasks.filter((t) => t.status === "pending").length;
|
|
162
|
-
const currentTasks = convoy.tasks.filter((t) => t.status === "in_progress");
|
|
163
|
-
const durations = this.taskDurations.get(convoy.id) ?? [];
|
|
164
|
-
const averageTaskTime = durations.length > 0 ? durations.reduce((a, b) => a + b, 0) / durations.length : 0;
|
|
165
|
-
const elapsedTime = convoy.startedAt ? Date.now() - new Date(convoy.startedAt).getTime() : 0;
|
|
166
|
-
let estimatedCompletion;
|
|
167
|
-
if (averageTaskTime > 0 && pendingTasks > 0) {
|
|
168
|
-
const remainingTime = (pendingTasks + inProgressTasks) * averageTaskTime;
|
|
169
|
-
estimatedCompletion = new Date(Date.now() + remainingTime);
|
|
170
|
-
}
|
|
171
|
-
return {
|
|
172
|
-
convoyId: convoy.id,
|
|
173
|
-
convoyName: convoy.name,
|
|
174
|
-
progress: convoy.progress,
|
|
175
|
-
status: convoy.status,
|
|
176
|
-
totalTasks: convoy.totalTasks,
|
|
177
|
-
completedTasks: convoy.completedTasks,
|
|
178
|
-
failedTasks: convoy.failedTasks,
|
|
179
|
-
inProgressTasks,
|
|
180
|
-
pendingTasks,
|
|
181
|
-
currentTasks,
|
|
182
|
-
estimatedCompletion,
|
|
183
|
-
elapsedTime,
|
|
184
|
-
averageTaskTime
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
buildProgressBar(progress) {
|
|
188
|
-
const width = this.config.progressBarWidth;
|
|
189
|
-
const filled = Math.round(progress / 100 * width);
|
|
190
|
-
const empty = width - filled;
|
|
191
|
-
const filledChar = "\u2588";
|
|
192
|
-
const emptyChar = "\u2591";
|
|
193
|
-
return `[${filledChar.repeat(filled)}${emptyChar.repeat(empty)}] ${progress}%`;
|
|
194
|
-
}
|
|
195
|
-
formatStatus(status) {
|
|
196
|
-
const statusMap = {
|
|
197
|
-
pending: "\u23F3 Pending",
|
|
198
|
-
in_progress: "\u{1F504} In Progress",
|
|
199
|
-
completed: "\u2705 Completed",
|
|
200
|
-
failed: "\u274C Failed",
|
|
201
|
-
cancelled: "\u{1F6AB} Cancelled",
|
|
202
|
-
paused: "\u23F8\uFE0F Paused"
|
|
203
|
-
};
|
|
204
|
-
return statusMap[status] ?? status;
|
|
205
|
-
}
|
|
206
|
-
formatTime(ms) {
|
|
207
|
-
if (ms < 0)
|
|
208
|
-
return "0s";
|
|
209
|
-
const seconds = Math.floor(ms / 1e3);
|
|
210
|
-
const minutes = Math.floor(seconds / 60);
|
|
211
|
-
const hours = Math.floor(minutes / 60);
|
|
212
|
-
if (hours > 0) {
|
|
213
|
-
return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
|
|
214
|
-
}
|
|
215
|
-
if (minutes > 0) {
|
|
216
|
-
return `${minutes}m ${seconds % 60}s`;
|
|
217
|
-
}
|
|
218
|
-
return `${seconds}s`;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
class PersistentMailboxManager extends EventEmitter {
|
|
223
|
-
stateManager;
|
|
224
|
-
mailboxes = /* @__PURE__ */ new Map();
|
|
225
|
-
expirationCheckInterval = null;
|
|
226
|
-
initialized = false;
|
|
227
|
-
constructor(stateManager) {
|
|
228
|
-
super();
|
|
229
|
-
this.stateManager = stateManager ?? getGlobalStateManager();
|
|
230
|
-
this.expirationCheckInterval = setInterval(() => {
|
|
231
|
-
this.checkExpiredMessages();
|
|
232
|
-
}, 6e4);
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Initialize mailbox manager
|
|
236
|
-
*/
|
|
237
|
-
async initialize() {
|
|
238
|
-
if (this.initialized)
|
|
239
|
-
return;
|
|
240
|
-
await this.stateManager.initialize();
|
|
241
|
-
for (const agentId of this.stateManager.getAgentIds()) {
|
|
242
|
-
await this.loadMailbox(agentId);
|
|
243
|
-
}
|
|
244
|
-
this.initialized = true;
|
|
245
|
-
}
|
|
246
|
-
/**
|
|
247
|
-
* Create mailbox for agent
|
|
248
|
-
*/
|
|
249
|
-
async createMailbox(agentId) {
|
|
250
|
-
await this.ensureInitialized();
|
|
251
|
-
if (this.mailboxes.has(agentId)) {
|
|
252
|
-
return this.mailboxes.get(agentId);
|
|
253
|
-
}
|
|
254
|
-
const mailbox = {
|
|
255
|
-
agentId,
|
|
256
|
-
inbox: [],
|
|
257
|
-
outbox: [],
|
|
258
|
-
archive: [],
|
|
259
|
-
updatedAt: Date.now()
|
|
260
|
-
};
|
|
261
|
-
this.mailboxes.set(agentId, mailbox);
|
|
262
|
-
await this.persistMailbox(agentId);
|
|
263
|
-
this.emit("mailbox:created", agentId);
|
|
264
|
-
return mailbox;
|
|
265
|
-
}
|
|
266
|
-
/**
|
|
267
|
-
* Get mailbox for agent
|
|
268
|
-
*/
|
|
269
|
-
async getMailbox(agentId) {
|
|
270
|
-
await this.ensureInitialized();
|
|
271
|
-
if (!this.mailboxes.has(agentId)) {
|
|
272
|
-
return this.createMailbox(agentId);
|
|
273
|
-
}
|
|
274
|
-
return this.mailboxes.get(agentId);
|
|
275
|
-
}
|
|
276
|
-
/**
|
|
277
|
-
* Send message to agent
|
|
278
|
-
*/
|
|
279
|
-
async send(from, to, subject, body, options = {}) {
|
|
280
|
-
await this.ensureInitialized();
|
|
281
|
-
const message = {
|
|
282
|
-
id: nanoid(),
|
|
283
|
-
from,
|
|
284
|
-
to,
|
|
285
|
-
subject,
|
|
286
|
-
body,
|
|
287
|
-
priority: options.priority ?? "normal",
|
|
288
|
-
timestamp: Date.now(),
|
|
289
|
-
read: false,
|
|
290
|
-
archived: false,
|
|
291
|
-
correlationId: options.correlationId,
|
|
292
|
-
replyTo: options.replyTo,
|
|
293
|
-
expiresAt: options.expiresIn ? Date.now() + options.expiresIn : void 0,
|
|
294
|
-
metadata: options.metadata
|
|
295
|
-
};
|
|
296
|
-
const senderMailbox = await this.getMailbox(from);
|
|
297
|
-
senderMailbox.outbox.push(message);
|
|
298
|
-
senderMailbox.updatedAt = Date.now();
|
|
299
|
-
await this.persistMailbox(from);
|
|
300
|
-
const recipientMailbox = await this.getMailbox(to);
|
|
301
|
-
recipientMailbox.inbox.push(message);
|
|
302
|
-
recipientMailbox.updatedAt = Date.now();
|
|
303
|
-
await this.persistMailbox(to);
|
|
304
|
-
this.emit("message:sent", message);
|
|
305
|
-
this.emit("message:received", message);
|
|
306
|
-
return message;
|
|
307
|
-
}
|
|
308
|
-
/**
|
|
309
|
-
* Reply to a message
|
|
310
|
-
*/
|
|
311
|
-
async reply(originalMessage, from, body, options = {}) {
|
|
312
|
-
return this.send(
|
|
313
|
-
from,
|
|
314
|
-
originalMessage.replyTo ?? originalMessage.from,
|
|
315
|
-
`Re: ${originalMessage.subject}`,
|
|
316
|
-
body,
|
|
317
|
-
{
|
|
318
|
-
...options,
|
|
319
|
-
correlationId: originalMessage.id
|
|
320
|
-
}
|
|
321
|
-
);
|
|
322
|
-
}
|
|
323
|
-
/**
|
|
324
|
-
* Broadcast message to multiple agents
|
|
325
|
-
*/
|
|
326
|
-
async broadcast(from, toAgents, subject, body, options = {}) {
|
|
327
|
-
const messages = [];
|
|
328
|
-
for (const to of toAgents) {
|
|
329
|
-
const message = await this.send(from, to, subject, body, options);
|
|
330
|
-
messages.push(message);
|
|
331
|
-
}
|
|
332
|
-
return messages;
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Check inbox for unread messages
|
|
336
|
-
*/
|
|
337
|
-
async checkInbox(agentId) {
|
|
338
|
-
await this.ensureInitialized();
|
|
339
|
-
const mailbox = await this.getMailbox(agentId);
|
|
340
|
-
return mailbox.inbox.filter((m) => !m.read && !m.archived);
|
|
341
|
-
}
|
|
342
|
-
/**
|
|
343
|
-
* Get unread message count
|
|
344
|
-
*/
|
|
345
|
-
async getUnreadCount(agentId) {
|
|
346
|
-
const unread = await this.checkInbox(agentId);
|
|
347
|
-
return unread.length;
|
|
348
|
-
}
|
|
349
|
-
/**
|
|
350
|
-
* Get messages by priority
|
|
351
|
-
*/
|
|
352
|
-
async getByPriority(agentId, priority) {
|
|
353
|
-
await this.ensureInitialized();
|
|
354
|
-
const mailbox = await this.getMailbox(agentId);
|
|
355
|
-
return mailbox.inbox.filter((m) => m.priority === priority && !m.archived);
|
|
356
|
-
}
|
|
357
|
-
/**
|
|
358
|
-
* Get messages by correlation ID
|
|
359
|
-
*/
|
|
360
|
-
async getByCorrelationId(agentId, correlationId) {
|
|
361
|
-
await this.ensureInitialized();
|
|
362
|
-
const mailbox = await this.getMailbox(agentId);
|
|
363
|
-
return [
|
|
364
|
-
...mailbox.inbox.filter((m) => m.correlationId === correlationId),
|
|
365
|
-
...mailbox.outbox.filter((m) => m.correlationId === correlationId)
|
|
366
|
-
];
|
|
367
|
-
}
|
|
368
|
-
/**
|
|
369
|
-
* Mark message as read
|
|
370
|
-
*/
|
|
371
|
-
async markAsRead(agentId, messageId) {
|
|
372
|
-
await this.ensureInitialized();
|
|
373
|
-
const mailbox = await this.getMailbox(agentId);
|
|
374
|
-
const message = mailbox.inbox.find((m) => m.id === messageId);
|
|
375
|
-
if (message && !message.read) {
|
|
376
|
-
message.read = true;
|
|
377
|
-
mailbox.updatedAt = Date.now();
|
|
378
|
-
await this.persistMailbox(agentId);
|
|
379
|
-
this.emit("message:read", messageId, agentId);
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* Mark all messages as read
|
|
384
|
-
*/
|
|
385
|
-
async markAllAsRead(agentId) {
|
|
386
|
-
await this.ensureInitialized();
|
|
387
|
-
const mailbox = await this.getMailbox(agentId);
|
|
388
|
-
let count = 0;
|
|
389
|
-
for (const message of mailbox.inbox) {
|
|
390
|
-
if (!message.read) {
|
|
391
|
-
message.read = true;
|
|
392
|
-
count++;
|
|
393
|
-
this.emit("message:read", message.id, agentId);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
if (count > 0) {
|
|
397
|
-
mailbox.updatedAt = Date.now();
|
|
398
|
-
await this.persistMailbox(agentId);
|
|
399
|
-
}
|
|
400
|
-
return count;
|
|
401
|
-
}
|
|
402
|
-
/**
|
|
403
|
-
* Archive message
|
|
404
|
-
*/
|
|
405
|
-
async archive(agentId, messageId) {
|
|
406
|
-
await this.ensureInitialized();
|
|
407
|
-
const mailbox = await this.getMailbox(agentId);
|
|
408
|
-
const inboxIndex = mailbox.inbox.findIndex((m) => m.id === messageId);
|
|
409
|
-
if (inboxIndex !== -1) {
|
|
410
|
-
const [message] = mailbox.inbox.splice(inboxIndex, 1);
|
|
411
|
-
message.archived = true;
|
|
412
|
-
mailbox.archive.push(message);
|
|
413
|
-
mailbox.updatedAt = Date.now();
|
|
414
|
-
await this.persistMailbox(agentId);
|
|
415
|
-
this.emit("message:archived", messageId, agentId);
|
|
416
|
-
return;
|
|
417
|
-
}
|
|
418
|
-
const outboxIndex = mailbox.outbox.findIndex((m) => m.id === messageId);
|
|
419
|
-
if (outboxIndex !== -1) {
|
|
420
|
-
const [message] = mailbox.outbox.splice(outboxIndex, 1);
|
|
421
|
-
message.archived = true;
|
|
422
|
-
mailbox.archive.push(message);
|
|
423
|
-
mailbox.updatedAt = Date.now();
|
|
424
|
-
await this.persistMailbox(agentId);
|
|
425
|
-
this.emit("message:archived", messageId, agentId);
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* Delete message permanently
|
|
430
|
-
*/
|
|
431
|
-
async delete(agentId, messageId) {
|
|
432
|
-
await this.ensureInitialized();
|
|
433
|
-
const mailbox = await this.getMailbox(agentId);
|
|
434
|
-
let deleted = false;
|
|
435
|
-
for (const arr of [mailbox.inbox, mailbox.outbox, mailbox.archive]) {
|
|
436
|
-
const index = arr.findIndex((m) => m.id === messageId);
|
|
437
|
-
if (index !== -1) {
|
|
438
|
-
arr.splice(index, 1);
|
|
439
|
-
deleted = true;
|
|
440
|
-
break;
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
if (deleted) {
|
|
444
|
-
mailbox.updatedAt = Date.now();
|
|
445
|
-
await this.persistMailbox(agentId);
|
|
446
|
-
}
|
|
447
|
-
return deleted;
|
|
448
|
-
}
|
|
449
|
-
/**
|
|
450
|
-
* Search messages
|
|
451
|
-
*/
|
|
452
|
-
async search(agentId, query) {
|
|
453
|
-
await this.ensureInitialized();
|
|
454
|
-
const mailbox = await this.getMailbox(agentId);
|
|
455
|
-
const allMessages = [...mailbox.inbox, ...mailbox.outbox, ...mailbox.archive];
|
|
456
|
-
return allMessages.filter((m) => {
|
|
457
|
-
if (query.subject && !m.subject.toLowerCase().includes(query.subject.toLowerCase())) {
|
|
458
|
-
return false;
|
|
459
|
-
}
|
|
460
|
-
if (query.from && m.from !== query.from) {
|
|
461
|
-
return false;
|
|
462
|
-
}
|
|
463
|
-
if (query.to && m.to !== query.to) {
|
|
464
|
-
return false;
|
|
465
|
-
}
|
|
466
|
-
if (query.read !== void 0 && m.read !== query.read) {
|
|
467
|
-
return false;
|
|
468
|
-
}
|
|
469
|
-
if (query.priority && m.priority !== query.priority) {
|
|
470
|
-
return false;
|
|
471
|
-
}
|
|
472
|
-
if (query.after && m.timestamp < query.after) {
|
|
473
|
-
return false;
|
|
474
|
-
}
|
|
475
|
-
if (query.before && m.timestamp > query.before) {
|
|
476
|
-
return false;
|
|
477
|
-
}
|
|
478
|
-
return true;
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
/**
|
|
482
|
-
* Get mailbox statistics
|
|
483
|
-
*/
|
|
484
|
-
async getStats(agentId) {
|
|
485
|
-
await this.ensureInitialized();
|
|
486
|
-
const mailbox = await this.getMailbox(agentId);
|
|
487
|
-
const unread = mailbox.inbox.filter((m) => !m.read);
|
|
488
|
-
return {
|
|
489
|
-
inboxCount: mailbox.inbox.length,
|
|
490
|
-
outboxCount: mailbox.outbox.length,
|
|
491
|
-
archiveCount: mailbox.archive.length,
|
|
492
|
-
unreadCount: unread.length,
|
|
493
|
-
oldestUnread: unread.length > 0 ? Math.min(...unread.map((m) => m.timestamp)) : null
|
|
494
|
-
};
|
|
495
|
-
}
|
|
496
|
-
/**
|
|
497
|
-
* Cleanup old archived messages
|
|
498
|
-
*/
|
|
499
|
-
async cleanupArchive(agentId, olderThanMs) {
|
|
500
|
-
await this.ensureInitialized();
|
|
501
|
-
const mailbox = await this.getMailbox(agentId);
|
|
502
|
-
const cutoff = Date.now() - olderThanMs;
|
|
503
|
-
const originalLength = mailbox.archive.length;
|
|
504
|
-
mailbox.archive = mailbox.archive.filter((m) => m.timestamp > cutoff);
|
|
505
|
-
const removed = originalLength - mailbox.archive.length;
|
|
506
|
-
if (removed > 0) {
|
|
507
|
-
mailbox.updatedAt = Date.now();
|
|
508
|
-
await this.persistMailbox(agentId);
|
|
509
|
-
}
|
|
510
|
-
return removed;
|
|
511
|
-
}
|
|
512
|
-
/**
|
|
513
|
-
* Destroy mailbox manager
|
|
514
|
-
*/
|
|
515
|
-
destroy() {
|
|
516
|
-
if (this.expirationCheckInterval) {
|
|
517
|
-
clearInterval(this.expirationCheckInterval);
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
// ========================================================================
|
|
521
|
-
// Private Methods
|
|
522
|
-
// ========================================================================
|
|
523
|
-
async ensureInitialized() {
|
|
524
|
-
if (!this.initialized) {
|
|
525
|
-
await this.initialize();
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
async loadMailbox(agentId) {
|
|
529
|
-
const agentPath = this.stateManager.getAgentPath(agentId);
|
|
530
|
-
if (!agentPath)
|
|
531
|
-
return;
|
|
532
|
-
const mailboxFile = join(agentPath, "mailbox.json");
|
|
533
|
-
if (!existsSync(mailboxFile))
|
|
534
|
-
return;
|
|
535
|
-
try {
|
|
536
|
-
const data = JSON.parse(readFileSync(mailboxFile, "utf-8"));
|
|
537
|
-
this.mailboxes.set(agentId, {
|
|
538
|
-
agentId,
|
|
539
|
-
inbox: data.inbox ?? [],
|
|
540
|
-
outbox: data.outbox ?? [],
|
|
541
|
-
archive: data.archive ?? [],
|
|
542
|
-
updatedAt: data.updatedAt ?? Date.now()
|
|
543
|
-
});
|
|
544
|
-
} catch {
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
async persistMailbox(agentId) {
|
|
548
|
-
const mailbox = this.mailboxes.get(agentId);
|
|
549
|
-
if (!mailbox)
|
|
550
|
-
return;
|
|
551
|
-
await this.stateManager.createAgentWorktree(agentId);
|
|
552
|
-
const agentPath = this.stateManager.getAgentPath(agentId);
|
|
553
|
-
if (!agentPath)
|
|
554
|
-
return;
|
|
555
|
-
const mailboxFile = join(agentPath, "mailbox.json");
|
|
556
|
-
writeFileSync(mailboxFile, JSON.stringify(mailbox, null, 2));
|
|
557
|
-
}
|
|
558
|
-
async checkExpiredMessages() {
|
|
559
|
-
const now = Date.now();
|
|
560
|
-
const entries = Array.from(this.mailboxes.entries());
|
|
561
|
-
for (const [agentId, mailbox] of entries) {
|
|
562
|
-
let changed = false;
|
|
563
|
-
for (const message of mailbox.inbox) {
|
|
564
|
-
if (message.expiresAt && message.expiresAt < now && !message.archived) {
|
|
565
|
-
message.archived = true;
|
|
566
|
-
mailbox.archive.push(message);
|
|
567
|
-
changed = true;
|
|
568
|
-
this.emit("message:expired", message.id);
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
mailbox.inbox = mailbox.inbox.filter((m) => !m.archived);
|
|
572
|
-
if (changed) {
|
|
573
|
-
mailbox.updatedAt = now;
|
|
574
|
-
await this.persistMailbox(agentId);
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
let globalMailboxManager = null;
|
|
580
|
-
function getGlobalMailboxManager() {
|
|
581
|
-
if (!globalMailboxManager) {
|
|
582
|
-
globalMailboxManager = new PersistentMailboxManager();
|
|
583
|
-
}
|
|
584
|
-
return globalMailboxManager;
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
const persistentMailbox = {
|
|
588
|
-
__proto__: null,
|
|
589
|
-
PersistentMailboxManager: PersistentMailboxManager,
|
|
590
|
-
getGlobalMailboxManager: getGlobalMailboxManager
|
|
591
|
-
};
|
|
592
|
-
|
|
593
|
-
class MayorAgent extends EventEmitter {
|
|
594
|
-
id;
|
|
595
|
-
config;
|
|
596
|
-
convoyManager;
|
|
597
|
-
mailboxManager;
|
|
598
|
-
progressTrackers = /* @__PURE__ */ new Map();
|
|
599
|
-
activeConvoys = /* @__PURE__ */ new Set();
|
|
600
|
-
constructor(config = {}) {
|
|
601
|
-
super();
|
|
602
|
-
this.id = `mayor-${nanoid(6)}`;
|
|
603
|
-
this.config = {
|
|
604
|
-
autoCreateConvoy: config.autoCreateConvoy ?? true,
|
|
605
|
-
autoSpawnWorkers: config.autoSpawnWorkers ?? true,
|
|
606
|
-
monitorProgress: config.monitorProgress ?? true,
|
|
607
|
-
progressInterval: config.progressInterval ?? 5e3,
|
|
608
|
-
notifyHuman: config.notifyHuman ?? true,
|
|
609
|
-
maxConcurrentWorkers: config.maxConcurrentWorkers ?? 5
|
|
610
|
-
};
|
|
611
|
-
this.convoyManager = getGlobalConvoyManager();
|
|
612
|
-
this.mailboxManager = getGlobalMailboxManager();
|
|
613
|
-
this.setupEventListeners();
|
|
614
|
-
}
|
|
615
|
-
/**
|
|
616
|
-
* Process user request - main entry point
|
|
617
|
-
*/
|
|
618
|
-
async processRequest(input) {
|
|
619
|
-
try {
|
|
620
|
-
const intent = await this.analyzeIntent(input);
|
|
621
|
-
this.emit("intent:analyzed", intent);
|
|
622
|
-
const plan = await this.createTaskPlan(intent);
|
|
623
|
-
this.emit("plan:created", plan);
|
|
624
|
-
let convoy = null;
|
|
625
|
-
if (this.config.autoCreateConvoy) {
|
|
626
|
-
convoy = await this.createConvoy(plan);
|
|
627
|
-
this.emit("convoy:created", convoy);
|
|
628
|
-
}
|
|
629
|
-
let workerCount = 0;
|
|
630
|
-
if (this.config.autoSpawnWorkers && convoy) {
|
|
631
|
-
workerCount = await this.spawnWorkers(convoy, plan);
|
|
632
|
-
this.emit("workers:spawned", workerCount);
|
|
633
|
-
}
|
|
634
|
-
if (this.config.monitorProgress && convoy) {
|
|
635
|
-
this.startMonitoring(convoy.id);
|
|
636
|
-
}
|
|
637
|
-
return {
|
|
638
|
-
id: nanoid(),
|
|
639
|
-
convoyId: convoy?.id ?? "",
|
|
640
|
-
plan,
|
|
641
|
-
workerCount,
|
|
642
|
-
message: this.buildResponseMessage(plan, convoy, workerCount),
|
|
643
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
644
|
-
};
|
|
645
|
-
} catch (error) {
|
|
646
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
647
|
-
this.emit("error", err);
|
|
648
|
-
throw err;
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
/**
|
|
652
|
-
* Analyze user intent from natural language
|
|
653
|
-
*/
|
|
654
|
-
async analyzeIntent(input) {
|
|
655
|
-
const lowerInput = input.toLowerCase();
|
|
656
|
-
let type = "other";
|
|
657
|
-
if (lowerInput.includes("add") || lowerInput.includes("implement") || lowerInput.includes("create")) {
|
|
658
|
-
type = "feature";
|
|
659
|
-
} else if (lowerInput.includes("fix") || lowerInput.includes("bug") || lowerInput.includes("error")) {
|
|
660
|
-
type = "bugfix";
|
|
661
|
-
} else if (lowerInput.includes("refactor") || lowerInput.includes("clean") || lowerInput.includes("improve")) {
|
|
662
|
-
type = "refactor";
|
|
663
|
-
} else if (lowerInput.includes("research") || lowerInput.includes("investigate")) {
|
|
664
|
-
type = "research";
|
|
665
|
-
} else if (lowerInput.includes("document") || lowerInput.includes("docs")) {
|
|
666
|
-
type = "documentation";
|
|
667
|
-
} else if (lowerInput.includes("test") || lowerInput.includes("spec")) {
|
|
668
|
-
type = "testing";
|
|
669
|
-
} else if (lowerInput.includes("deploy") || lowerInput.includes("release")) {
|
|
670
|
-
type = "deployment";
|
|
671
|
-
}
|
|
672
|
-
const entities = {
|
|
673
|
-
files: this.extractFiles(input),
|
|
674
|
-
functions: this.extractFunctions(input),
|
|
675
|
-
components: this.extractComponents(input),
|
|
676
|
-
technologies: this.extractTechnologies(input),
|
|
677
|
-
keywords: this.extractKeywords(input)
|
|
678
|
-
};
|
|
679
|
-
const complexity = this.estimateComplexity(input, entities);
|
|
680
|
-
const requiredRoles = this.determineRequiredRoles(type, entities);
|
|
681
|
-
return {
|
|
682
|
-
id: nanoid(),
|
|
683
|
-
originalInput: input,
|
|
684
|
-
type,
|
|
685
|
-
summary: this.generateSummary(input, type),
|
|
686
|
-
entities,
|
|
687
|
-
confidence: 0.8,
|
|
688
|
-
approach: this.suggestApproach(type, complexity),
|
|
689
|
-
complexity,
|
|
690
|
-
requiredRoles
|
|
691
|
-
};
|
|
692
|
-
}
|
|
693
|
-
/**
|
|
694
|
-
* Create task plan from intent
|
|
695
|
-
*/
|
|
696
|
-
async createTaskPlan(intent) {
|
|
697
|
-
const tasks = [];
|
|
698
|
-
switch (intent.type) {
|
|
699
|
-
case "feature":
|
|
700
|
-
tasks.push(
|
|
701
|
-
{ title: "Analyze requirements", description: `Understand: ${intent.summary}`, role: "researcher", dependsOn: [], estimatedEffort: "small" },
|
|
702
|
-
{ title: "Design implementation", description: "Create design and identify files", role: "architect", dependsOn: ["task-0"], estimatedEffort: "medium" },
|
|
703
|
-
{ title: "Implement feature", description: "Write the code", role: "coder", dependsOn: ["task-1"], estimatedEffort: "large" },
|
|
704
|
-
{ title: "Write tests", description: "Create tests", role: "tester", dependsOn: ["task-2"], estimatedEffort: "medium" },
|
|
705
|
-
{ title: "Review", description: "Code review", role: "reviewer", dependsOn: ["task-3"], estimatedEffort: "small" }
|
|
706
|
-
);
|
|
707
|
-
break;
|
|
708
|
-
case "bugfix":
|
|
709
|
-
tasks.push(
|
|
710
|
-
{ title: "Reproduce issue", description: "Understand the bug", role: "researcher", dependsOn: [], estimatedEffort: "small" },
|
|
711
|
-
{ title: "Find root cause", description: "Debug and find cause", role: "debugger", dependsOn: ["task-0"], estimatedEffort: "medium" },
|
|
712
|
-
{ title: "Implement fix", description: "Write the fix", role: "coder", dependsOn: ["task-1"], estimatedEffort: "medium" },
|
|
713
|
-
{ title: "Add regression test", description: "Prevent regression", role: "tester", dependsOn: ["task-2"], estimatedEffort: "small" }
|
|
714
|
-
);
|
|
715
|
-
break;
|
|
716
|
-
case "refactor":
|
|
717
|
-
tasks.push(
|
|
718
|
-
{ title: "Analyze code", description: "Understand current implementation", role: "researcher", dependsOn: [], estimatedEffort: "medium" },
|
|
719
|
-
{ title: "Plan refactoring", description: "Design approach", role: "architect", dependsOn: ["task-0"], estimatedEffort: "medium" },
|
|
720
|
-
{ title: "Execute refactoring", description: "Perform refactoring", role: "coder", dependsOn: ["task-1"], estimatedEffort: "large" },
|
|
721
|
-
{ title: "Verify tests", description: "Ensure tests pass", role: "tester", dependsOn: ["task-2"], estimatedEffort: "small" }
|
|
722
|
-
);
|
|
723
|
-
break;
|
|
724
|
-
default:
|
|
725
|
-
tasks.push(
|
|
726
|
-
{ title: "Analyze request", description: `Understand: ${intent.summary}`, role: "researcher", dependsOn: [], estimatedEffort: "small" },
|
|
727
|
-
{ title: "Execute task", description: "Perform the work", role: "coder", dependsOn: ["task-0"], estimatedEffort: "medium" }
|
|
728
|
-
);
|
|
729
|
-
}
|
|
730
|
-
return {
|
|
731
|
-
id: nanoid(),
|
|
732
|
-
name: intent.summary,
|
|
733
|
-
description: `Task plan for: ${intent.originalInput}`,
|
|
734
|
-
tasks,
|
|
735
|
-
totalEffort: this.calculateTotalEffort(tasks),
|
|
736
|
-
risks: this.identifyRisks(intent),
|
|
737
|
-
successCriteria: this.defineSuccessCriteria(intent)
|
|
738
|
-
};
|
|
739
|
-
}
|
|
740
|
-
/**
|
|
741
|
-
* Create convoy from task plan
|
|
742
|
-
*/
|
|
743
|
-
async createConvoy(plan) {
|
|
744
|
-
const convoy = await this.convoyManager.create(plan.name, {
|
|
745
|
-
description: plan.description,
|
|
746
|
-
createdBy: this.id,
|
|
747
|
-
notifyOnComplete: this.config.notifyHuman,
|
|
748
|
-
notifyOnFailure: true,
|
|
749
|
-
notifyOnProgress: true,
|
|
750
|
-
metadata: { planId: plan.id, totalEffort: plan.totalEffort }
|
|
751
|
-
});
|
|
752
|
-
const taskIdMap = /* @__PURE__ */ new Map();
|
|
753
|
-
for (let i = 0; i < plan.tasks.length; i++) {
|
|
754
|
-
const planTask = plan.tasks[i];
|
|
755
|
-
const dependsOn = planTask.dependsOn.map((dep) => taskIdMap.get(dep)).filter((id) => id !== void 0);
|
|
756
|
-
const task = await this.convoyManager.addTask(convoy.id, planTask.title, {
|
|
757
|
-
description: planTask.description,
|
|
758
|
-
dependsOn,
|
|
759
|
-
metadata: { role: planTask.role, estimatedEffort: planTask.estimatedEffort }
|
|
760
|
-
});
|
|
761
|
-
taskIdMap.set(`task-${i}`, task.id);
|
|
762
|
-
}
|
|
763
|
-
this.activeConvoys.add(convoy.id);
|
|
764
|
-
return this.convoyManager.get(convoy.id);
|
|
765
|
-
}
|
|
766
|
-
/**
|
|
767
|
-
* Spawn worker agents for convoy
|
|
768
|
-
*/
|
|
769
|
-
async spawnWorkers(convoy, plan) {
|
|
770
|
-
const uniqueRoles = new Set(plan.tasks.map((t) => t.role));
|
|
771
|
-
const workerCount = Math.min(uniqueRoles.size, this.config.maxConcurrentWorkers);
|
|
772
|
-
await this.convoyManager.start(convoy.id);
|
|
773
|
-
return workerCount;
|
|
774
|
-
}
|
|
775
|
-
/**
|
|
776
|
-
* Start monitoring convoy progress
|
|
777
|
-
*/
|
|
778
|
-
startMonitoring(convoyId) {
|
|
779
|
-
if (this.progressTrackers.has(convoyId))
|
|
780
|
-
return;
|
|
781
|
-
const tracker = new ProgressTracker(this.convoyManager, {
|
|
782
|
-
updateInterval: this.config.progressInterval
|
|
783
|
-
});
|
|
784
|
-
tracker.on("progress", (update) => {
|
|
785
|
-
this.emit("progress:update", update);
|
|
786
|
-
});
|
|
787
|
-
tracker.track(convoyId);
|
|
788
|
-
this.progressTrackers.set(convoyId, tracker);
|
|
789
|
-
}
|
|
790
|
-
/**
|
|
791
|
-
* Stop monitoring convoy
|
|
792
|
-
*/
|
|
793
|
-
stopMonitoring(convoyId) {
|
|
794
|
-
const tracker = this.progressTrackers.get(convoyId);
|
|
795
|
-
if (tracker) {
|
|
796
|
-
tracker.destroy();
|
|
797
|
-
this.progressTrackers.delete(convoyId);
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
/**
|
|
801
|
-
* Get convoy status
|
|
802
|
-
*/
|
|
803
|
-
getConvoyStatus(convoyId) {
|
|
804
|
-
return this.convoyManager.getSummary(convoyId);
|
|
805
|
-
}
|
|
806
|
-
/**
|
|
807
|
-
* Get all active convoys
|
|
808
|
-
*/
|
|
809
|
-
getActiveConvoys() {
|
|
810
|
-
return Array.from(this.activeConvoys).map((id) => this.convoyManager.get(id)).filter((c) => c !== void 0);
|
|
811
|
-
}
|
|
812
|
-
/**
|
|
813
|
-
* Destroy mayor agent
|
|
814
|
-
*/
|
|
815
|
-
destroy() {
|
|
816
|
-
const trackers = Array.from(this.progressTrackers.values());
|
|
817
|
-
for (const tracker of trackers) {
|
|
818
|
-
tracker.destroy();
|
|
819
|
-
}
|
|
820
|
-
this.progressTrackers.clear();
|
|
821
|
-
this.activeConvoys.clear();
|
|
822
|
-
this.removeAllListeners();
|
|
823
|
-
}
|
|
824
|
-
// ========================================================================
|
|
825
|
-
// Private Methods
|
|
826
|
-
// ========================================================================
|
|
827
|
-
setupEventListeners() {
|
|
828
|
-
this.convoyManager.on("convoy:completed", (convoy) => {
|
|
829
|
-
if (this.activeConvoys.has(convoy.id)) {
|
|
830
|
-
this.activeConvoys.delete(convoy.id);
|
|
831
|
-
this.stopMonitoring(convoy.id);
|
|
832
|
-
this.emit("convoy:completed", convoy, this.convoyManager.getSummary(convoy.id));
|
|
833
|
-
}
|
|
834
|
-
});
|
|
835
|
-
this.convoyManager.on("convoy:failed", (convoy) => {
|
|
836
|
-
if (this.activeConvoys.has(convoy.id)) {
|
|
837
|
-
this.activeConvoys.delete(convoy.id);
|
|
838
|
-
this.stopMonitoring(convoy.id);
|
|
839
|
-
this.emit("convoy:failed", convoy, "Convoy failed");
|
|
840
|
-
}
|
|
841
|
-
});
|
|
842
|
-
}
|
|
843
|
-
extractFiles(input) {
|
|
844
|
-
const filePattern = /[\w-]+\.(ts|js|tsx|jsx|json|md|yaml|yml|toml)/gi;
|
|
845
|
-
return input.match(filePattern) ?? [];
|
|
846
|
-
}
|
|
847
|
-
extractFunctions(input) {
|
|
848
|
-
const funcPattern = /\b(\w+)\s*\(/g;
|
|
849
|
-
const matches = [];
|
|
850
|
-
let match;
|
|
851
|
-
while ((match = funcPattern.exec(input)) !== null) {
|
|
852
|
-
if (!["if", "for", "while", "switch", "catch"].includes(match[1])) {
|
|
853
|
-
matches.push(match[1]);
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
return matches;
|
|
857
|
-
}
|
|
858
|
-
extractComponents(input) {
|
|
859
|
-
const componentPattern = /\b([A-Z][a-zA-Z]+)\b/g;
|
|
860
|
-
return input.match(componentPattern) ?? [];
|
|
861
|
-
}
|
|
862
|
-
extractTechnologies(input) {
|
|
863
|
-
const techs = ["react", "vue", "angular", "node", "typescript", "javascript", "python", "rust", "go", "docker", "kubernetes", "aws", "gcp", "azure"];
|
|
864
|
-
const lowerInput = input.toLowerCase();
|
|
865
|
-
return techs.filter((tech) => lowerInput.includes(tech));
|
|
866
|
-
}
|
|
867
|
-
extractKeywords(input) {
|
|
868
|
-
const words = input.toLowerCase().split(/\s+/);
|
|
869
|
-
const stopWords = /* @__PURE__ */ new Set(["the", "a", "an", "is", "are", "was", "were", "be", "been", "being", "have", "has", "had", "do", "does", "did", "will", "would", "could", "should", "may", "might", "must", "shall", "can", "need", "dare", "ought", "used", "to", "of", "in", "for", "on", "with", "at", "by", "from", "as", "into", "through", "during", "before", "after", "above", "below", "between", "under", "again", "further", "then", "once", "here", "there", "when", "where", "why", "how", "all", "each", "few", "more", "most", "other", "some", "such", "no", "nor", "not", "only", "own", "same", "so", "than", "too", "very", "just", "and", "but", "if", "or", "because", "until", "while", "although", "though", "after", "before", "when", "whenever", "where", "wherever", "whether", "which", "who", "whom", "whose", "what", "whatever", "whichever", "whoever", "whomever", "this", "that", "these", "those", "i", "me", "my", "myself", "we", "our", "ours", "ourselves", "you", "your", "yours", "yourself", "yourselves", "he", "him", "his", "himself", "she", "her", "hers", "herself", "it", "its", "itself", "they", "them", "their", "theirs", "themselves"]);
|
|
870
|
-
return words.filter((w) => w.length > 2 && !stopWords.has(w));
|
|
871
|
-
}
|
|
872
|
-
estimateComplexity(input, entities) {
|
|
873
|
-
const fileCount = entities.files?.length ?? 0;
|
|
874
|
-
const componentCount = entities.components?.length ?? 0;
|
|
875
|
-
const wordCount = input.split(/\s+/).length;
|
|
876
|
-
if (wordCount < 10 && fileCount <= 1)
|
|
877
|
-
return "trivial";
|
|
878
|
-
if (wordCount < 20 && fileCount <= 2)
|
|
879
|
-
return "simple";
|
|
880
|
-
if (wordCount < 50 && fileCount <= 5)
|
|
881
|
-
return "moderate";
|
|
882
|
-
if (wordCount < 100 || componentCount > 3)
|
|
883
|
-
return "complex";
|
|
884
|
-
return "very_complex";
|
|
885
|
-
}
|
|
886
|
-
determineRequiredRoles(type, _entities) {
|
|
887
|
-
const roles = ["researcher"];
|
|
888
|
-
switch (type) {
|
|
889
|
-
case "feature":
|
|
890
|
-
roles.push("architect", "coder", "tester", "reviewer");
|
|
891
|
-
break;
|
|
892
|
-
case "bugfix":
|
|
893
|
-
roles.push("debugger", "coder", "tester");
|
|
894
|
-
break;
|
|
895
|
-
case "refactor":
|
|
896
|
-
roles.push("architect", "coder", "tester");
|
|
897
|
-
break;
|
|
898
|
-
case "testing":
|
|
899
|
-
roles.push("tester");
|
|
900
|
-
break;
|
|
901
|
-
case "documentation":
|
|
902
|
-
roles.push("writer");
|
|
903
|
-
break;
|
|
904
|
-
default:
|
|
905
|
-
roles.push("coder");
|
|
906
|
-
}
|
|
907
|
-
return roles;
|
|
908
|
-
}
|
|
909
|
-
generateSummary(input, type) {
|
|
910
|
-
const words = input.split(/\s+/).slice(0, 10).join(" ");
|
|
911
|
-
const typeLabel = type.charAt(0).toUpperCase() + type.slice(1);
|
|
912
|
-
return `${typeLabel}: ${words}${input.split(/\s+/).length > 10 ? "..." : ""}`;
|
|
913
|
-
}
|
|
914
|
-
suggestApproach(type, _complexity) {
|
|
915
|
-
const approaches = {
|
|
916
|
-
feature: "Design-first approach with incremental implementation",
|
|
917
|
-
bugfix: "Reproduce, isolate, fix, and verify",
|
|
918
|
-
refactor: "Ensure test coverage, then refactor incrementally",
|
|
919
|
-
research: "Gather information, analyze, and document findings",
|
|
920
|
-
documentation: "Review code, document API and usage patterns",
|
|
921
|
-
testing: "Identify test cases, implement, and verify coverage",
|
|
922
|
-
deployment: "Prepare, validate, deploy, and monitor",
|
|
923
|
-
other: "Analyze requirements and implement solution"
|
|
924
|
-
};
|
|
925
|
-
return approaches[type];
|
|
926
|
-
}
|
|
927
|
-
calculateTotalEffort(tasks) {
|
|
928
|
-
const effortMap = { minimal: 1, small: 2, medium: 4, large: 8 };
|
|
929
|
-
const total = tasks.reduce((sum, t) => sum + effortMap[t.estimatedEffort], 0);
|
|
930
|
-
if (total <= 4)
|
|
931
|
-
return "Small";
|
|
932
|
-
if (total <= 10)
|
|
933
|
-
return "Medium";
|
|
934
|
-
if (total <= 20)
|
|
935
|
-
return "Large";
|
|
936
|
-
return "Very Large";
|
|
937
|
-
}
|
|
938
|
-
identifyRisks(intent) {
|
|
939
|
-
const risks = [];
|
|
940
|
-
if (intent.complexity === "complex" || intent.complexity === "very_complex") {
|
|
941
|
-
risks.push("High complexity may require multiple iterations");
|
|
942
|
-
}
|
|
943
|
-
if (intent.type === "refactor") {
|
|
944
|
-
risks.push("Refactoring may introduce regressions");
|
|
945
|
-
}
|
|
946
|
-
if (intent.entities.files && intent.entities.files.length > 5) {
|
|
947
|
-
risks.push("Multiple files affected - careful coordination needed");
|
|
948
|
-
}
|
|
949
|
-
if (risks.length === 0) {
|
|
950
|
-
risks.push("No significant risks identified");
|
|
951
|
-
}
|
|
952
|
-
return risks;
|
|
953
|
-
}
|
|
954
|
-
defineSuccessCriteria(intent) {
|
|
955
|
-
const criteria = [];
|
|
956
|
-
switch (intent.type) {
|
|
957
|
-
case "feature":
|
|
958
|
-
criteria.push("Feature implemented as specified", "Tests pass", "Code reviewed");
|
|
959
|
-
break;
|
|
960
|
-
case "bugfix":
|
|
961
|
-
criteria.push("Bug no longer reproducible", "Regression test added", "No new issues introduced");
|
|
962
|
-
break;
|
|
963
|
-
case "refactor":
|
|
964
|
-
criteria.push("All existing tests pass", "Code quality improved", "No functional changes");
|
|
965
|
-
break;
|
|
966
|
-
default:
|
|
967
|
-
criteria.push("Task completed successfully", "Results documented");
|
|
968
|
-
}
|
|
969
|
-
return criteria;
|
|
970
|
-
}
|
|
971
|
-
buildResponseMessage(plan, convoy, workerCount) {
|
|
972
|
-
const lines = [
|
|
973
|
-
`Created plan: ${plan.name}`,
|
|
974
|
-
`Tasks: ${plan.tasks.length}`,
|
|
975
|
-
`Estimated effort: ${plan.totalEffort}`
|
|
976
|
-
];
|
|
977
|
-
if (convoy) {
|
|
978
|
-
lines.push(`Convoy: ${convoy.id}`);
|
|
979
|
-
}
|
|
980
|
-
if (workerCount > 0) {
|
|
981
|
-
lines.push(`Workers: ${workerCount}`);
|
|
982
|
-
}
|
|
983
|
-
return lines.join("\n");
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
let globalMayorAgent = null;
|
|
987
|
-
function getGlobalMayorAgent(config) {
|
|
988
|
-
if (!globalMayorAgent) {
|
|
989
|
-
globalMayorAgent = new MayorAgent(config);
|
|
990
|
-
}
|
|
991
|
-
return globalMayorAgent;
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
class IntentRouter extends EventEmitter {
|
|
995
|
-
config;
|
|
996
|
-
// Keywords for intent detection
|
|
997
|
-
mayorKeywords = [
|
|
998
|
-
"implement",
|
|
999
|
-
"build",
|
|
1000
|
-
"create",
|
|
1001
|
-
"add",
|
|
1002
|
-
"develop",
|
|
1003
|
-
"integrate",
|
|
1004
|
-
"system",
|
|
1005
|
-
"architecture",
|
|
1006
|
-
"multiple",
|
|
1007
|
-
"complex",
|
|
1008
|
-
"full",
|
|
1009
|
-
"authentication",
|
|
1010
|
-
"authorization",
|
|
1011
|
-
"api",
|
|
1012
|
-
"database",
|
|
1013
|
-
"backend",
|
|
1014
|
-
"frontend",
|
|
1015
|
-
"ui",
|
|
1016
|
-
"ux",
|
|
1017
|
-
"design",
|
|
1018
|
-
"workflow"
|
|
1019
|
-
];
|
|
1020
|
-
planKeywords = [
|
|
1021
|
-
"plan",
|
|
1022
|
-
"design",
|
|
1023
|
-
"architect",
|
|
1024
|
-
"structure",
|
|
1025
|
-
"organize",
|
|
1026
|
-
"refactor",
|
|
1027
|
-
"restructure",
|
|
1028
|
-
"reorganize",
|
|
1029
|
-
"improve",
|
|
1030
|
-
"how to",
|
|
1031
|
-
"approach",
|
|
1032
|
-
"strategy",
|
|
1033
|
-
"best way"
|
|
1034
|
-
];
|
|
1035
|
-
featureKeywords = [
|
|
1036
|
-
"add",
|
|
1037
|
-
"create",
|
|
1038
|
-
"implement",
|
|
1039
|
-
"build",
|
|
1040
|
-
"make",
|
|
1041
|
-
"feature",
|
|
1042
|
-
"function",
|
|
1043
|
-
"component",
|
|
1044
|
-
"module",
|
|
1045
|
-
"button",
|
|
1046
|
-
"form",
|
|
1047
|
-
"page",
|
|
1048
|
-
"endpoint",
|
|
1049
|
-
"route"
|
|
1050
|
-
];
|
|
1051
|
-
bugFixKeywords = [
|
|
1052
|
-
"fix",
|
|
1053
|
-
"bug",
|
|
1054
|
-
"error",
|
|
1055
|
-
"issue",
|
|
1056
|
-
"problem",
|
|
1057
|
-
"broken",
|
|
1058
|
-
"not working",
|
|
1059
|
-
"crash",
|
|
1060
|
-
"fail",
|
|
1061
|
-
"debug",
|
|
1062
|
-
"resolve",
|
|
1063
|
-
"solve"
|
|
1064
|
-
];
|
|
1065
|
-
questionKeywords = [
|
|
1066
|
-
"what",
|
|
1067
|
-
"how",
|
|
1068
|
-
"why",
|
|
1069
|
-
"when",
|
|
1070
|
-
"where",
|
|
1071
|
-
"which",
|
|
1072
|
-
"explain",
|
|
1073
|
-
"tell me",
|
|
1074
|
-
"show me",
|
|
1075
|
-
"help",
|
|
1076
|
-
"can you",
|
|
1077
|
-
"could you",
|
|
1078
|
-
"would you"
|
|
1079
|
-
];
|
|
1080
|
-
constructor(config = {}) {
|
|
1081
|
-
super();
|
|
1082
|
-
this.config = {
|
|
1083
|
-
mayorComplexityThreshold: config.mayorComplexityThreshold || "complex",
|
|
1084
|
-
planComplexityThreshold: config.planComplexityThreshold || "moderate",
|
|
1085
|
-
autoRoute: config.autoRoute !== void 0 ? config.autoRoute : true,
|
|
1086
|
-
askConfirmation: config.askConfirmation !== void 0 ? config.askConfirmation : false,
|
|
1087
|
-
verbose: config.verbose !== void 0 ? config.verbose : false
|
|
1088
|
-
};
|
|
1089
|
-
}
|
|
1090
|
-
/**
|
|
1091
|
-
* Analyze user input and determine intent
|
|
1092
|
-
*/
|
|
1093
|
-
async analyze(input) {
|
|
1094
|
-
const normalized = input.toLowerCase().trim();
|
|
1095
|
-
const complexity = this.calculateComplexity(normalized);
|
|
1096
|
-
const type = this.detectIntentType(normalized);
|
|
1097
|
-
const keywords = this.extractKeywords(normalized);
|
|
1098
|
-
const requiresPlanning = this.needsPlanning(normalized, complexity);
|
|
1099
|
-
const requiresMultipleAgents = this.needsMultipleAgents(normalized, complexity);
|
|
1100
|
-
const estimatedSteps = this.estimateSteps(normalized, complexity);
|
|
1101
|
-
const confidence = this.calculateConfidence(type, complexity, keywords);
|
|
1102
|
-
const suggestedRoute = this.determineSuggestedRoute(
|
|
1103
|
-
type,
|
|
1104
|
-
complexity,
|
|
1105
|
-
requiresPlanning,
|
|
1106
|
-
requiresMultipleAgents
|
|
1107
|
-
);
|
|
1108
|
-
const reasoning = this.generateReasoning(
|
|
1109
|
-
type,
|
|
1110
|
-
complexity,
|
|
1111
|
-
suggestedRoute,
|
|
1112
|
-
requiresPlanning,
|
|
1113
|
-
requiresMultipleAgents,
|
|
1114
|
-
estimatedSteps
|
|
1115
|
-
);
|
|
1116
|
-
const intent = {
|
|
1117
|
-
type,
|
|
1118
|
-
complexity,
|
|
1119
|
-
confidence,
|
|
1120
|
-
reasoning,
|
|
1121
|
-
suggestedRoute,
|
|
1122
|
-
keywords,
|
|
1123
|
-
requiresPlanning,
|
|
1124
|
-
requiresMultipleAgents,
|
|
1125
|
-
estimatedSteps
|
|
1126
|
-
};
|
|
1127
|
-
this.emit("intent:analyzed", intent);
|
|
1128
|
-
return intent;
|
|
1129
|
-
}
|
|
1130
|
-
/**
|
|
1131
|
-
* Route user input to appropriate system
|
|
1132
|
-
*/
|
|
1133
|
-
async route(input) {
|
|
1134
|
-
const intent = await this.analyze(input);
|
|
1135
|
-
let shouldExecute = this.config.autoRoute;
|
|
1136
|
-
if (this.config.askConfirmation && intent.complexity === "very_complex") {
|
|
1137
|
-
shouldExecute = false;
|
|
1138
|
-
}
|
|
1139
|
-
const message = this.generateRouteMessage(intent);
|
|
1140
|
-
this.emit("route:determined", {
|
|
1141
|
-
route: intent.suggestedRoute,
|
|
1142
|
-
intent,
|
|
1143
|
-
shouldExecute
|
|
1144
|
-
});
|
|
1145
|
-
return {
|
|
1146
|
-
route: intent.suggestedRoute,
|
|
1147
|
-
intent,
|
|
1148
|
-
shouldExecute,
|
|
1149
|
-
message
|
|
1150
|
-
};
|
|
1151
|
-
}
|
|
1152
|
-
/**
|
|
1153
|
-
* Calculate complexity level
|
|
1154
|
-
*/
|
|
1155
|
-
calculateComplexity(input) {
|
|
1156
|
-
let score = 0;
|
|
1157
|
-
const words = input.split(/\s+/).length;
|
|
1158
|
-
if (words > 50)
|
|
1159
|
-
score += 3;
|
|
1160
|
-
else if (words > 30)
|
|
1161
|
-
score += 2;
|
|
1162
|
-
else if (words > 15)
|
|
1163
|
-
score += 1;
|
|
1164
|
-
const components = ["frontend", "backend", "database", "api", "ui", "auth", "test"];
|
|
1165
|
-
const mentionedComponents = components.filter((c) => input.includes(c)).length;
|
|
1166
|
-
score += mentionedComponents;
|
|
1167
|
-
const actions = ["create", "update", "delete", "implement", "integrate", "test", "deploy"];
|
|
1168
|
-
const mentionedActions = actions.filter((a) => input.includes(a)).length;
|
|
1169
|
-
score += mentionedActions;
|
|
1170
|
-
const technicalTerms = [
|
|
1171
|
-
"authentication",
|
|
1172
|
-
"authorization",
|
|
1173
|
-
"middleware",
|
|
1174
|
-
"validation",
|
|
1175
|
-
"encryption",
|
|
1176
|
-
"jwt",
|
|
1177
|
-
"oauth",
|
|
1178
|
-
"websocket",
|
|
1179
|
-
"graphql",
|
|
1180
|
-
"rest",
|
|
1181
|
-
"microservice",
|
|
1182
|
-
"docker",
|
|
1183
|
-
"kubernetes",
|
|
1184
|
-
"ci/cd"
|
|
1185
|
-
];
|
|
1186
|
-
const mentionedTerms = technicalTerms.filter((t) => input.includes(t)).length;
|
|
1187
|
-
score += mentionedTerms * 2;
|
|
1188
|
-
if (input.match(/\band\b/gi)?.length || 0 > 2)
|
|
1189
|
-
score += 2;
|
|
1190
|
-
if (score >= 10)
|
|
1191
|
-
return "very_complex";
|
|
1192
|
-
if (score >= 7)
|
|
1193
|
-
return "complex";
|
|
1194
|
-
if (score >= 4)
|
|
1195
|
-
return "moderate";
|
|
1196
|
-
if (score >= 2)
|
|
1197
|
-
return "simple";
|
|
1198
|
-
return "trivial";
|
|
1199
|
-
}
|
|
1200
|
-
/**
|
|
1201
|
-
* Detect intent type from input
|
|
1202
|
-
*/
|
|
1203
|
-
detectIntentType(input) {
|
|
1204
|
-
if (this.matchesKeywords(input, this.questionKeywords)) {
|
|
1205
|
-
return "question";
|
|
1206
|
-
}
|
|
1207
|
-
if (this.matchesKeywords(input, this.bugFixKeywords)) {
|
|
1208
|
-
return "bug_fix";
|
|
1209
|
-
}
|
|
1210
|
-
if (this.matchesKeywords(input, this.planKeywords)) {
|
|
1211
|
-
return "plan";
|
|
1212
|
-
}
|
|
1213
|
-
if (this.matchesKeywords(input, this.featureKeywords)) {
|
|
1214
|
-
return "feature";
|
|
1215
|
-
}
|
|
1216
|
-
if (input.includes("refactor") || input.includes("improve") || input.includes("optimize")) {
|
|
1217
|
-
return "refactor";
|
|
1218
|
-
}
|
|
1219
|
-
if (this.matchesKeywords(input, this.mayorKeywords)) {
|
|
1220
|
-
return "mayor";
|
|
1221
|
-
}
|
|
1222
|
-
return "direct";
|
|
1223
|
-
}
|
|
1224
|
-
/**
|
|
1225
|
-
* Check if input matches keywords
|
|
1226
|
-
*/
|
|
1227
|
-
matchesKeywords(input, keywords) {
|
|
1228
|
-
return keywords.some((keyword) => input.includes(keyword));
|
|
1229
|
-
}
|
|
1230
|
-
/**
|
|
1231
|
-
* Extract relevant keywords
|
|
1232
|
-
*/
|
|
1233
|
-
extractKeywords(input) {
|
|
1234
|
-
const allKeywords = [
|
|
1235
|
-
...this.mayorKeywords,
|
|
1236
|
-
...this.planKeywords,
|
|
1237
|
-
...this.featureKeywords,
|
|
1238
|
-
...this.bugFixKeywords,
|
|
1239
|
-
...this.questionKeywords
|
|
1240
|
-
];
|
|
1241
|
-
return allKeywords.filter((keyword) => input.includes(keyword));
|
|
1242
|
-
}
|
|
1243
|
-
/**
|
|
1244
|
-
* Determine if planning is needed
|
|
1245
|
-
*/
|
|
1246
|
-
needsPlanning(input, complexity) {
|
|
1247
|
-
if (complexity === "very_complex")
|
|
1248
|
-
return true;
|
|
1249
|
-
if (this.matchesKeywords(input, this.planKeywords))
|
|
1250
|
-
return true;
|
|
1251
|
-
const architecturalKeywords = [
|
|
1252
|
-
"architecture",
|
|
1253
|
-
"structure",
|
|
1254
|
-
"design",
|
|
1255
|
-
"refactor",
|
|
1256
|
-
"reorganize",
|
|
1257
|
-
"restructure",
|
|
1258
|
-
"system"
|
|
1259
|
-
];
|
|
1260
|
-
if (this.matchesKeywords(input, architecturalKeywords))
|
|
1261
|
-
return true;
|
|
1262
|
-
if (complexity === "complex" || complexity === "moderate") {
|
|
1263
|
-
const components = ["frontend", "backend", "database", "api"];
|
|
1264
|
-
const mentionedComponents = components.filter((c) => input.includes(c)).length;
|
|
1265
|
-
if (mentionedComponents >= 2)
|
|
1266
|
-
return true;
|
|
1267
|
-
}
|
|
1268
|
-
return false;
|
|
1269
|
-
}
|
|
1270
|
-
/**
|
|
1271
|
-
* Determine if multiple agents are needed
|
|
1272
|
-
*/
|
|
1273
|
-
needsMultipleAgents(input, complexity) {
|
|
1274
|
-
if (complexity === "very_complex")
|
|
1275
|
-
return true;
|
|
1276
|
-
if (complexity === "complex")
|
|
1277
|
-
return true;
|
|
1278
|
-
const components = ["frontend", "backend", "database", "api", "test", "deploy"];
|
|
1279
|
-
const mentionedComponents = components.filter((c) => input.includes(c)).length;
|
|
1280
|
-
if (mentionedComponents >= 2)
|
|
1281
|
-
return true;
|
|
1282
|
-
const actions = ["create", "update", "delete", "test", "deploy", "integrate"];
|
|
1283
|
-
const mentionedActions = actions.filter((a) => input.includes(a)).length;
|
|
1284
|
-
if (mentionedActions >= 3)
|
|
1285
|
-
return true;
|
|
1286
|
-
return false;
|
|
1287
|
-
}
|
|
1288
|
-
/**
|
|
1289
|
-
* Estimate number of steps
|
|
1290
|
-
*/
|
|
1291
|
-
estimateSteps(input, complexity) {
|
|
1292
|
-
const baseSteps = {
|
|
1293
|
-
trivial: 1,
|
|
1294
|
-
simple: 2,
|
|
1295
|
-
moderate: 4,
|
|
1296
|
-
complex: 8,
|
|
1297
|
-
very_complex: 15
|
|
1298
|
-
};
|
|
1299
|
-
let steps = baseSteps[complexity];
|
|
1300
|
-
const components = ["frontend", "backend", "database", "api", "test", "deploy"];
|
|
1301
|
-
const mentionedComponents = components.filter((c) => input.includes(c)).length;
|
|
1302
|
-
steps += mentionedComponents * 2;
|
|
1303
|
-
const actions = ["create", "update", "delete", "integrate", "test", "deploy"];
|
|
1304
|
-
const mentionedActions = actions.filter((a) => input.includes(a)).length;
|
|
1305
|
-
steps += mentionedActions;
|
|
1306
|
-
return Math.min(steps, 30);
|
|
1307
|
-
}
|
|
1308
|
-
/**
|
|
1309
|
-
* Calculate confidence score
|
|
1310
|
-
*/
|
|
1311
|
-
calculateConfidence(type, complexity, keywords) {
|
|
1312
|
-
let confidence = 0.5;
|
|
1313
|
-
confidence += Math.min(keywords.length * 0.05, 0.3);
|
|
1314
|
-
if (type !== "direct") {
|
|
1315
|
-
confidence += 0.2;
|
|
1316
|
-
}
|
|
1317
|
-
return Math.min(confidence, 1);
|
|
1318
|
-
}
|
|
1319
|
-
/**
|
|
1320
|
-
* Determine suggested route
|
|
1321
|
-
*/
|
|
1322
|
-
determineSuggestedRoute(type, complexity, requiresPlanning, requiresMultipleAgents) {
|
|
1323
|
-
if (type === "question") {
|
|
1324
|
-
return "direct";
|
|
1325
|
-
}
|
|
1326
|
-
if (complexity === "very_complex" || requiresMultipleAgents) {
|
|
1327
|
-
return "mayor";
|
|
1328
|
-
}
|
|
1329
|
-
if (complexity === "complex" && requiresPlanning) {
|
|
1330
|
-
return "mayor";
|
|
1331
|
-
}
|
|
1332
|
-
if (type === "plan" || requiresPlanning) {
|
|
1333
|
-
return "plan";
|
|
1334
|
-
}
|
|
1335
|
-
if (complexity === "moderate" && (type === "feature" || type === "bug_fix")) {
|
|
1336
|
-
return "feature";
|
|
1337
|
-
}
|
|
1338
|
-
if (complexity === "simple" || complexity === "trivial") {
|
|
1339
|
-
return "direct";
|
|
1340
|
-
}
|
|
1341
|
-
return "feature";
|
|
1342
|
-
}
|
|
1343
|
-
/**
|
|
1344
|
-
* Generate reasoning explanation
|
|
1345
|
-
*/
|
|
1346
|
-
generateReasoning(type, complexity, route, requiresPlanning, requiresMultipleAgents, estimatedSteps) {
|
|
1347
|
-
const reasons = [];
|
|
1348
|
-
reasons.push(`Complexity: ${complexity}`);
|
|
1349
|
-
reasons.push(`Intent: ${type}`);
|
|
1350
|
-
if (requiresPlanning) {
|
|
1351
|
-
reasons.push("Requires architectural planning");
|
|
1352
|
-
}
|
|
1353
|
-
if (requiresMultipleAgents) {
|
|
1354
|
-
reasons.push("Requires multiple specialized agents");
|
|
1355
|
-
}
|
|
1356
|
-
reasons.push(`Estimated ${estimatedSteps} steps`);
|
|
1357
|
-
const routeReasons = {
|
|
1358
|
-
mayor: "Using Mayor Agent for orchestration",
|
|
1359
|
-
plan: "Using Plan Mode for architectural design",
|
|
1360
|
-
feature: "Using Feature Mode for implementation",
|
|
1361
|
-
direct: "Direct execution"
|
|
1362
|
-
};
|
|
1363
|
-
reasons.push(routeReasons[route]);
|
|
1364
|
-
return reasons.join(" \u2022 ");
|
|
1365
|
-
}
|
|
1366
|
-
/**
|
|
1367
|
-
* Generate user-friendly route message
|
|
1368
|
-
*/
|
|
1369
|
-
generateRouteMessage(intent) {
|
|
1370
|
-
const messages = {
|
|
1371
|
-
mayor: `\u{1F9E0} Mayor Agent will orchestrate this ${intent.complexity} task with ${intent.estimatedSteps} steps`,
|
|
1372
|
-
plan: `\u{1F4CB} Creating architectural plan for this ${intent.complexity} task`,
|
|
1373
|
-
feature: `\u26A1 Implementing feature directly (${intent.complexity} complexity)`,
|
|
1374
|
-
direct: `\u{1F680} Executing directly`
|
|
1375
|
-
};
|
|
1376
|
-
return messages[intent.suggestedRoute];
|
|
1377
|
-
}
|
|
1378
|
-
}
|
|
1379
|
-
let globalRouter$1 = null;
|
|
1380
|
-
function getGlobalIntentRouter(config) {
|
|
1381
|
-
if (!globalRouter$1) {
|
|
1382
|
-
globalRouter$1 = new IntentRouter(config);
|
|
1383
|
-
}
|
|
1384
|
-
return globalRouter$1;
|
|
1385
|
-
}
|
|
1386
|
-
|
|
1387
|
-
class AutoExecutor extends EventEmitter {
|
|
1388
|
-
config;
|
|
1389
|
-
intentRouter = getGlobalIntentRouter();
|
|
1390
|
-
constructor(config = {}) {
|
|
1391
|
-
super();
|
|
1392
|
-
this.config = {
|
|
1393
|
-
autoCreateSkills: config.autoCreateSkills !== void 0 ? config.autoCreateSkills : true,
|
|
1394
|
-
autoCreateAgents: config.autoCreateAgents !== void 0 ? config.autoCreateAgents : true,
|
|
1395
|
-
autoSelectMcp: config.autoSelectMcp !== void 0 ? config.autoSelectMcp : true,
|
|
1396
|
-
verbose: config.verbose !== void 0 ? config.verbose : false
|
|
1397
|
-
};
|
|
1398
|
-
}
|
|
1399
|
-
/**
|
|
1400
|
-
* Execute user request automatically
|
|
1401
|
-
*/
|
|
1402
|
-
async execute(userInput) {
|
|
1403
|
-
this.emit("execution:started", { input: userInput });
|
|
1404
|
-
try {
|
|
1405
|
-
const routeResult = await this.intentRouter.route(userInput);
|
|
1406
|
-
const { route, intent } = routeResult;
|
|
1407
|
-
this.log(`Intent analyzed: ${intent.type} (${intent.complexity})`);
|
|
1408
|
-
this.log(`Suggested route: ${route}`);
|
|
1409
|
-
const skillReq = await this.detectSkillRequirement(userInput, intent);
|
|
1410
|
-
const agentReq = await this.detectAgentRequirement(userInput, intent);
|
|
1411
|
-
const mcpReq = await this.detectMcpRequirement(userInput, intent);
|
|
1412
|
-
const agentsCreated = [];
|
|
1413
|
-
const skillsCreated = [];
|
|
1414
|
-
const mcpToolsUsed = [];
|
|
1415
|
-
if (this.config.autoCreateSkills && skillReq.needed) {
|
|
1416
|
-
this.log(`Auto-creating skill: ${skillReq.skillName}`);
|
|
1417
|
-
const skillId = await this.autoCreateSkill(skillReq);
|
|
1418
|
-
skillsCreated.push(skillId);
|
|
1419
|
-
this.emit("skill:created", { skillId, skillReq });
|
|
1420
|
-
}
|
|
1421
|
-
if (this.config.autoCreateAgents && agentReq.needed) {
|
|
1422
|
-
this.log(`Auto-creating agent: ${agentReq.domain}`);
|
|
1423
|
-
const agentId = await this.autoCreateAgent(agentReq);
|
|
1424
|
-
agentsCreated.push(agentId);
|
|
1425
|
-
this.emit("agent:created", { agentId, agentReq });
|
|
1426
|
-
}
|
|
1427
|
-
if (this.config.autoSelectMcp && mcpReq.needed) {
|
|
1428
|
-
this.log(`Auto-selecting MCP tools: ${mcpReq.tools.join(", ")}`);
|
|
1429
|
-
mcpToolsUsed.push(...mcpReq.tools);
|
|
1430
|
-
this.emit("mcp:selected", { tools: mcpReq.tools, mcpReq });
|
|
1431
|
-
}
|
|
1432
|
-
let result;
|
|
1433
|
-
switch (route) {
|
|
1434
|
-
case "mayor":
|
|
1435
|
-
result = await this.executeMayor(userInput, intent, agentsCreated, skillsCreated, mcpToolsUsed);
|
|
1436
|
-
break;
|
|
1437
|
-
case "plan":
|
|
1438
|
-
result = await this.executePlan(userInput, intent, agentsCreated, skillsCreated, mcpToolsUsed);
|
|
1439
|
-
break;
|
|
1440
|
-
case "feature":
|
|
1441
|
-
result = await this.executeFeature(userInput, intent, agentsCreated, skillsCreated, mcpToolsUsed);
|
|
1442
|
-
break;
|
|
1443
|
-
case "direct":
|
|
1444
|
-
result = await this.executeDirect(userInput, intent, agentsCreated, skillsCreated, mcpToolsUsed);
|
|
1445
|
-
break;
|
|
1446
|
-
default:
|
|
1447
|
-
throw new Error(`Unknown route: ${route}`);
|
|
1448
|
-
}
|
|
1449
|
-
this.emit("execution:completed", result);
|
|
1450
|
-
return result;
|
|
1451
|
-
} catch (error) {
|
|
1452
|
-
this.emit("execution:failed", { error, input: userInput });
|
|
1453
|
-
throw error;
|
|
1454
|
-
}
|
|
1455
|
-
}
|
|
1456
|
-
/**
|
|
1457
|
-
* Detect if a new skill is needed
|
|
1458
|
-
*/
|
|
1459
|
-
async detectSkillRequirement(input, intent) {
|
|
1460
|
-
const normalized = input.toLowerCase();
|
|
1461
|
-
const technologies = [
|
|
1462
|
-
{ name: "react", type: "code" },
|
|
1463
|
-
{ name: "vue", type: "code" },
|
|
1464
|
-
{ name: "angular", type: "code" },
|
|
1465
|
-
{ name: "docker", type: "deployment" },
|
|
1466
|
-
{ name: "kubernetes", type: "deployment" },
|
|
1467
|
-
{ name: "graphql", type: "integration" },
|
|
1468
|
-
{ name: "websocket", type: "integration" },
|
|
1469
|
-
{ name: "oauth", type: "integration" },
|
|
1470
|
-
{ name: "jwt", type: "integration" }
|
|
1471
|
-
];
|
|
1472
|
-
for (const tech of technologies) {
|
|
1473
|
-
if (normalized.includes(tech.name)) {
|
|
1474
|
-
return {
|
|
1475
|
-
needed: true,
|
|
1476
|
-
skillName: `${tech.name}-specialist`,
|
|
1477
|
-
skillType: tech.type,
|
|
1478
|
-
reason: `Detected ${tech.name} technology requirement`
|
|
1479
|
-
};
|
|
1480
|
-
}
|
|
1481
|
-
}
|
|
1482
|
-
if (normalized.includes("authentication") || normalized.includes("auth")) {
|
|
1483
|
-
return {
|
|
1484
|
-
needed: true,
|
|
1485
|
-
skillName: "authentication-specialist",
|
|
1486
|
-
skillType: "integration",
|
|
1487
|
-
reason: "Authentication system requires specialized skill"
|
|
1488
|
-
};
|
|
1489
|
-
}
|
|
1490
|
-
if (normalized.includes("database") || normalized.includes("sql")) {
|
|
1491
|
-
return {
|
|
1492
|
-
needed: true,
|
|
1493
|
-
skillName: "database-specialist",
|
|
1494
|
-
skillType: "code",
|
|
1495
|
-
reason: "Database operations require specialized skill"
|
|
1496
|
-
};
|
|
1497
|
-
}
|
|
1498
|
-
if (normalized.includes("api") && normalized.includes("design")) {
|
|
1499
|
-
return {
|
|
1500
|
-
needed: true,
|
|
1501
|
-
skillName: "api-architect",
|
|
1502
|
-
skillType: "analysis",
|
|
1503
|
-
reason: "API design requires architectural skill"
|
|
1504
|
-
};
|
|
1505
|
-
}
|
|
1506
|
-
if (intent.complexity === "very_complex" || intent.complexity === "complex") {
|
|
1507
|
-
return {
|
|
1508
|
-
needed: true,
|
|
1509
|
-
skillName: `custom-${intent.type}-specialist`,
|
|
1510
|
-
skillType: "code",
|
|
1511
|
-
reason: `Complex ${intent.type} task requires specialized skill`
|
|
1512
|
-
};
|
|
1513
|
-
}
|
|
1514
|
-
return {
|
|
1515
|
-
needed: false,
|
|
1516
|
-
skillName: "",
|
|
1517
|
-
skillType: "code",
|
|
1518
|
-
reason: "No specialized skill needed"
|
|
1519
|
-
};
|
|
1520
|
-
}
|
|
1521
|
-
/**
|
|
1522
|
-
* Detect if a new agent is needed
|
|
1523
|
-
*/
|
|
1524
|
-
async detectAgentRequirement(input, intent) {
|
|
1525
|
-
const normalized = input.toLowerCase();
|
|
1526
|
-
if (normalized.includes("architecture") || normalized.includes("design system")) {
|
|
1527
|
-
return {
|
|
1528
|
-
needed: true,
|
|
1529
|
-
agentType: "architect",
|
|
1530
|
-
domain: "System Architecture",
|
|
1531
|
-
reason: "Architectural design requires architect agent"
|
|
1532
|
-
};
|
|
1533
|
-
}
|
|
1534
|
-
if (normalized.includes("deploy") || normalized.includes("ci/cd") || normalized.includes("docker")) {
|
|
1535
|
-
return {
|
|
1536
|
-
needed: true,
|
|
1537
|
-
agentType: "devops",
|
|
1538
|
-
domain: "DevOps & Deployment",
|
|
1539
|
-
reason: "Deployment tasks require DevOps agent"
|
|
1540
|
-
};
|
|
1541
|
-
}
|
|
1542
|
-
const specializations = [
|
|
1543
|
-
{ keywords: ["security", "encryption", "auth"], domain: "Security" },
|
|
1544
|
-
{ keywords: ["performance", "optimize", "cache"], domain: "Performance" },
|
|
1545
|
-
{ keywords: ["test", "testing", "qa"], domain: "Testing" },
|
|
1546
|
-
{ keywords: ["ui", "ux", "design", "frontend"], domain: "Frontend" },
|
|
1547
|
-
{ keywords: ["api", "backend", "server"], domain: "Backend" },
|
|
1548
|
-
{ keywords: ["database", "sql", "query"], domain: "Database" }
|
|
1549
|
-
];
|
|
1550
|
-
for (const spec of specializations) {
|
|
1551
|
-
if (spec.keywords.some((kw) => normalized.includes(kw))) {
|
|
1552
|
-
return {
|
|
1553
|
-
needed: true,
|
|
1554
|
-
agentType: "specialist",
|
|
1555
|
-
domain: spec.domain,
|
|
1556
|
-
reason: `${spec.domain} tasks require specialized agent`
|
|
1557
|
-
};
|
|
1558
|
-
}
|
|
1559
|
-
}
|
|
1560
|
-
if (intent.estimatedSteps > 5) {
|
|
1561
|
-
return {
|
|
1562
|
-
needed: true,
|
|
1563
|
-
agentType: "engineer",
|
|
1564
|
-
domain: "Implementation",
|
|
1565
|
-
reason: "Multi-step implementation requires engineer agent"
|
|
1566
|
-
};
|
|
1567
|
-
}
|
|
1568
|
-
return {
|
|
1569
|
-
needed: false,
|
|
1570
|
-
agentType: "engineer",
|
|
1571
|
-
domain: "",
|
|
1572
|
-
reason: "Existing agents can handle this task"
|
|
1573
|
-
};
|
|
1574
|
-
}
|
|
1575
|
-
/**
|
|
1576
|
-
* Detect which MCP tools are needed
|
|
1577
|
-
*/
|
|
1578
|
-
async detectMcpRequirement(input, _intent) {
|
|
1579
|
-
const normalized = input.toLowerCase();
|
|
1580
|
-
const tools = [];
|
|
1581
|
-
if (normalized.includes("file") || normalized.includes("directory") || normalized.includes("folder")) {
|
|
1582
|
-
tools.push("filesystem");
|
|
1583
|
-
}
|
|
1584
|
-
if (normalized.includes("github") || normalized.includes("repository") || normalized.includes("pr")) {
|
|
1585
|
-
tools.push("github");
|
|
1586
|
-
}
|
|
1587
|
-
if (normalized.includes("search") || normalized.includes("documentation") || normalized.includes("docs")) {
|
|
1588
|
-
tools.push("web-search");
|
|
1589
|
-
}
|
|
1590
|
-
if (normalized.includes("browser") || normalized.includes("webpage") || normalized.includes("ui test")) {
|
|
1591
|
-
tools.push("playwright");
|
|
1592
|
-
}
|
|
1593
|
-
if (normalized.includes("library") || normalized.includes("framework") || normalized.includes("package")) {
|
|
1594
|
-
tools.push("context7");
|
|
1595
|
-
}
|
|
1596
|
-
if (normalized.includes("diagnostic") || normalized.includes("error") || normalized.includes("lint")) {
|
|
1597
|
-
tools.push("ide");
|
|
1598
|
-
}
|
|
1599
|
-
return {
|
|
1600
|
-
needed: tools.length > 0,
|
|
1601
|
-
tools,
|
|
1602
|
-
reason: tools.length > 0 ? `Requires MCP tools: ${tools.join(", ")}` : "No MCP tools needed"
|
|
1603
|
-
};
|
|
1604
|
-
}
|
|
1605
|
-
/**
|
|
1606
|
-
* Auto-create a skill
|
|
1607
|
-
*/
|
|
1608
|
-
async autoCreateSkill(req) {
|
|
1609
|
-
const skillId = `skill-${req.skillName}-${Date.now()}`;
|
|
1610
|
-
const skillDefinition = {
|
|
1611
|
-
id: skillId,
|
|
1612
|
-
name: req.skillName,
|
|
1613
|
-
type: req.skillType,
|
|
1614
|
-
description: `Auto-generated skill for ${req.reason}`,
|
|
1615
|
-
capabilities: this.generateSkillCapabilities(req),
|
|
1616
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1617
|
-
autoGenerated: true
|
|
1618
|
-
};
|
|
1619
|
-
const stateManager = getGlobalStateManager();
|
|
1620
|
-
await stateManager.initialize();
|
|
1621
|
-
await stateManager.createAgentWorktree(skillId);
|
|
1622
|
-
await stateManager.saveState(skillId, {
|
|
1623
|
-
agentId: skillId,
|
|
1624
|
-
status: "active",
|
|
1625
|
-
currentTask: "Ready",
|
|
1626
|
-
memory: { skillDefinition }
|
|
1627
|
-
});
|
|
1628
|
-
this.log(`Skill created: ${skillId}`);
|
|
1629
|
-
return skillId;
|
|
1630
|
-
}
|
|
1631
|
-
/**
|
|
1632
|
-
* Generate skill capabilities based on requirement
|
|
1633
|
-
*/
|
|
1634
|
-
generateSkillCapabilities(req) {
|
|
1635
|
-
const capabilitiesMap = {
|
|
1636
|
-
code: ["write_code", "review_code", "refactor_code", "debug_code"],
|
|
1637
|
-
analysis: ["analyze_requirements", "design_architecture", "create_diagrams", "document_design"],
|
|
1638
|
-
integration: ["integrate_apis", "configure_services", "test_integration", "handle_auth"],
|
|
1639
|
-
deployment: ["deploy_application", "configure_infrastructure", "setup_ci_cd", "monitor_services"]
|
|
1640
|
-
};
|
|
1641
|
-
return capabilitiesMap[req.skillType] || ["general_task"];
|
|
1642
|
-
}
|
|
1643
|
-
/**
|
|
1644
|
-
* Auto-create an agent
|
|
1645
|
-
*/
|
|
1646
|
-
async autoCreateAgent(req) {
|
|
1647
|
-
const agentId = `agent-${req.agentType}-${Date.now()}`;
|
|
1648
|
-
const agentDefinition = {
|
|
1649
|
-
id: agentId,
|
|
1650
|
-
name: `${req.domain} ${req.agentType}`,
|
|
1651
|
-
type: req.agentType,
|
|
1652
|
-
domain: req.domain,
|
|
1653
|
-
status: "active",
|
|
1654
|
-
model: req.agentType === "architect" ? "opus" : "sonnet",
|
|
1655
|
-
capabilities: this.generateAgentCapabilities(req),
|
|
1656
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1657
|
-
autoGenerated: true
|
|
1658
|
-
};
|
|
1659
|
-
const stateManager = getGlobalStateManager();
|
|
1660
|
-
await stateManager.initialize();
|
|
1661
|
-
await stateManager.createAgentWorktree(agentId);
|
|
1662
|
-
await stateManager.saveState(agentId, {
|
|
1663
|
-
agentId,
|
|
1664
|
-
status: "active",
|
|
1665
|
-
currentTask: "Ready",
|
|
1666
|
-
memory: { agentDefinition }
|
|
1667
|
-
});
|
|
1668
|
-
const mailboxManager = getGlobalMailboxManager();
|
|
1669
|
-
await mailboxManager.initialize();
|
|
1670
|
-
await mailboxManager.createMailbox(agentId);
|
|
1671
|
-
this.log(`Agent created: ${agentId}`);
|
|
1672
|
-
return agentId;
|
|
1673
|
-
}
|
|
1674
|
-
/**
|
|
1675
|
-
* Generate agent capabilities based on requirement
|
|
1676
|
-
*/
|
|
1677
|
-
generateAgentCapabilities(req) {
|
|
1678
|
-
const capabilitiesMap = {
|
|
1679
|
-
architect: ["design_architecture", "create_plans", "review_design", "make_decisions"],
|
|
1680
|
-
specialist: ["deep_expertise", "solve_complex_problems", "optimize_solutions", "provide_guidance"],
|
|
1681
|
-
engineer: ["implement_features", "write_code", "test_code", "fix_bugs"],
|
|
1682
|
-
devops: ["deploy_applications", "manage_infrastructure", "setup_pipelines", "monitor_systems"]
|
|
1683
|
-
};
|
|
1684
|
-
return capabilitiesMap[req.agentType] || ["general_task"];
|
|
1685
|
-
}
|
|
1686
|
-
/**
|
|
1687
|
-
* Execute via Mayor Agent
|
|
1688
|
-
*/
|
|
1689
|
-
async executeMayor(input, intent, agentsCreated, skillsCreated, mcpToolsUsed) {
|
|
1690
|
-
this.log("Executing via Mayor Agent");
|
|
1691
|
-
const mayor = getGlobalMayorAgent({
|
|
1692
|
-
autoCreateConvoy: true,
|
|
1693
|
-
autoSpawnWorkers: true,
|
|
1694
|
-
monitorProgress: true,
|
|
1695
|
-
notifyHuman: true
|
|
1696
|
-
});
|
|
1697
|
-
const response = await mayor.processRequest(input);
|
|
1698
|
-
return {
|
|
1699
|
-
success: true,
|
|
1700
|
-
route: "mayor",
|
|
1701
|
-
intent,
|
|
1702
|
-
convoyId: response.convoyId,
|
|
1703
|
-
agentsCreated,
|
|
1704
|
-
skillsCreated,
|
|
1705
|
-
mcpToolsUsed,
|
|
1706
|
-
message: response.message,
|
|
1707
|
-
details: response
|
|
1708
|
-
};
|
|
1709
|
-
}
|
|
1710
|
-
/**
|
|
1711
|
-
* Execute via Plan Mode
|
|
1712
|
-
*/
|
|
1713
|
-
async executePlan(input, intent, agentsCreated, skillsCreated, mcpToolsUsed) {
|
|
1714
|
-
this.log("Executing via Plan Mode");
|
|
1715
|
-
const convoyManager = getGlobalConvoyManager();
|
|
1716
|
-
await convoyManager.initialize();
|
|
1717
|
-
const convoy = await convoyManager.create(`Plan: ${input.substring(0, 50)}`, {
|
|
1718
|
-
description: input,
|
|
1719
|
-
createdBy: "auto-executor"
|
|
1720
|
-
});
|
|
1721
|
-
await convoyManager.addTask(convoy.id, "Analyze requirements");
|
|
1722
|
-
await convoyManager.addTask(convoy.id, "Design architecture");
|
|
1723
|
-
await convoyManager.addTask(convoy.id, "Create implementation plan");
|
|
1724
|
-
await convoyManager.start(convoy.id);
|
|
1725
|
-
return {
|
|
1726
|
-
success: true,
|
|
1727
|
-
route: "plan",
|
|
1728
|
-
intent,
|
|
1729
|
-
convoyId: convoy.id,
|
|
1730
|
-
agentsCreated,
|
|
1731
|
-
skillsCreated,
|
|
1732
|
-
mcpToolsUsed,
|
|
1733
|
-
message: `Planning convoy created: ${convoy.id}`,
|
|
1734
|
-
details: { convoy }
|
|
1735
|
-
};
|
|
1736
|
-
}
|
|
1737
|
-
/**
|
|
1738
|
-
* Execute via Feature Mode
|
|
1739
|
-
*/
|
|
1740
|
-
async executeFeature(input, intent, agentsCreated, skillsCreated, mcpToolsUsed) {
|
|
1741
|
-
this.log("Executing via Feature Mode");
|
|
1742
|
-
const convoyManager = getGlobalConvoyManager();
|
|
1743
|
-
await convoyManager.initialize();
|
|
1744
|
-
const convoy = await convoyManager.create(`Feature: ${input.substring(0, 50)}`, {
|
|
1745
|
-
description: input,
|
|
1746
|
-
createdBy: "auto-executor"
|
|
1747
|
-
});
|
|
1748
|
-
await convoyManager.addTask(convoy.id, "Implement feature");
|
|
1749
|
-
await convoyManager.addTask(convoy.id, "Write tests");
|
|
1750
|
-
await convoyManager.addTask(convoy.id, "Update documentation");
|
|
1751
|
-
await convoyManager.start(convoy.id);
|
|
1752
|
-
return {
|
|
1753
|
-
success: true,
|
|
1754
|
-
route: "feature",
|
|
1755
|
-
intent,
|
|
1756
|
-
convoyId: convoy.id,
|
|
1757
|
-
agentsCreated,
|
|
1758
|
-
skillsCreated,
|
|
1759
|
-
mcpToolsUsed,
|
|
1760
|
-
message: `Feature convoy created: ${convoy.id}`,
|
|
1761
|
-
details: { convoy }
|
|
1762
|
-
};
|
|
1763
|
-
}
|
|
1764
|
-
/**
|
|
1765
|
-
* Execute directly
|
|
1766
|
-
*/
|
|
1767
|
-
async executeDirect(input, intent, agentsCreated, skillsCreated, mcpToolsUsed) {
|
|
1768
|
-
this.log("Executing directly");
|
|
1769
|
-
return {
|
|
1770
|
-
success: true,
|
|
1771
|
-
route: "direct",
|
|
1772
|
-
intent,
|
|
1773
|
-
agentsCreated,
|
|
1774
|
-
skillsCreated,
|
|
1775
|
-
mcpToolsUsed,
|
|
1776
|
-
message: `Direct execution: ${input}`,
|
|
1777
|
-
details: { input }
|
|
1778
|
-
};
|
|
1779
|
-
}
|
|
1780
|
-
/**
|
|
1781
|
-
* Log message if verbose
|
|
1782
|
-
*/
|
|
1783
|
-
log(message) {
|
|
1784
|
-
if (this.config.verbose) {
|
|
1785
|
-
console.log(`[AutoExecutor] ${message}`);
|
|
1786
|
-
}
|
|
1787
|
-
}
|
|
1788
|
-
}
|
|
1789
|
-
let globalExecutor = null;
|
|
1790
|
-
function getGlobalAutoExecutor(config) {
|
|
1791
|
-
if (!globalExecutor) {
|
|
1792
|
-
globalExecutor = new AutoExecutor(config);
|
|
1793
|
-
}
|
|
1794
|
-
return globalExecutor;
|
|
1795
|
-
}
|
|
1796
|
-
|
|
1797
|
-
class CliInterceptor extends EventEmitter {
|
|
1798
|
-
config;
|
|
1799
|
-
autoExecutor = getGlobalAutoExecutor({
|
|
1800
|
-
autoCreateSkills: true,
|
|
1801
|
-
autoCreateAgents: true,
|
|
1802
|
-
autoSelectMcp: true,
|
|
1803
|
-
verbose: false
|
|
1804
|
-
});
|
|
1805
|
-
// Claude Code native commands that should bypass interception
|
|
1806
|
-
// Reference: https://deepwiki.com/FlorianBruniaux/claude-code-ultimate-guide/16-command-reference
|
|
1807
|
-
systemCommands = [
|
|
1808
|
-
// Session Management
|
|
1809
|
-
"/help",
|
|
1810
|
-
"/clear",
|
|
1811
|
-
"/exit",
|
|
1812
|
-
"/quit",
|
|
1813
|
-
"/resume",
|
|
1814
|
-
// Context Management
|
|
1815
|
-
"/compact",
|
|
1816
|
-
"/context",
|
|
1817
|
-
"/status",
|
|
1818
|
-
// Mode Control
|
|
1819
|
-
"/plan",
|
|
1820
|
-
"/execute",
|
|
1821
|
-
// History
|
|
1822
|
-
"/rewind",
|
|
1823
|
-
// Diagnostic
|
|
1824
|
-
"/mcp",
|
|
1825
|
-
"/doctor",
|
|
1826
|
-
// Configuration
|
|
1827
|
-
"/settings",
|
|
1828
|
-
"/config",
|
|
1829
|
-
"/version",
|
|
1830
|
-
// Extension System
|
|
1831
|
-
"/agents",
|
|
1832
|
-
"/skills",
|
|
1833
|
-
"/commands",
|
|
1834
|
-
// Plugin/Marketplace - CCJK 接管,不在此列表
|
|
1835
|
-
// '/plugin',
|
|
1836
|
-
// '/plugins',
|
|
1837
|
-
// Tasks
|
|
1838
|
-
"/tasks",
|
|
1839
|
-
// Memory
|
|
1840
|
-
"/memory",
|
|
1841
|
-
"/memories",
|
|
1842
|
-
// Model
|
|
1843
|
-
"/model",
|
|
1844
|
-
// Cost
|
|
1845
|
-
"/cost",
|
|
1846
|
-
// Permissions
|
|
1847
|
-
"/permissions",
|
|
1848
|
-
// Hooks
|
|
1849
|
-
"/hooks",
|
|
1850
|
-
// Init
|
|
1851
|
-
"/init",
|
|
1852
|
-
// Login/Logout
|
|
1853
|
-
"/login",
|
|
1854
|
-
"/logout",
|
|
1855
|
-
// Bug report
|
|
1856
|
-
"/bug",
|
|
1857
|
-
// Terminal
|
|
1858
|
-
"/terminal",
|
|
1859
|
-
// IDE
|
|
1860
|
-
"/ide",
|
|
1861
|
-
// Review
|
|
1862
|
-
"/review",
|
|
1863
|
-
// PR
|
|
1864
|
-
"/pr",
|
|
1865
|
-
// Vim mode
|
|
1866
|
-
"/vim",
|
|
1867
|
-
// Listen mode
|
|
1868
|
-
"/listen",
|
|
1869
|
-
// Add files
|
|
1870
|
-
"/add",
|
|
1871
|
-
// Install
|
|
1872
|
-
"/install",
|
|
1873
|
-
// Allowed tools
|
|
1874
|
-
"/allowed-tools",
|
|
1875
|
-
// Thinking
|
|
1876
|
-
"/think",
|
|
1877
|
-
"/thinking"
|
|
1878
|
-
];
|
|
1879
|
-
// Simple queries that don't need interception
|
|
1880
|
-
simpleQueryPatterns = [
|
|
1881
|
-
/^what is/i,
|
|
1882
|
-
/^who is/i,
|
|
1883
|
-
/^when was/i,
|
|
1884
|
-
/^where is/i,
|
|
1885
|
-
/^how do i/i,
|
|
1886
|
-
/^can you explain/i,
|
|
1887
|
-
/^tell me about/i
|
|
1888
|
-
];
|
|
1889
|
-
constructor(config = {}) {
|
|
1890
|
-
super();
|
|
1891
|
-
this.config = {
|
|
1892
|
-
enabled: config.enabled !== void 0 ? config.enabled : true,
|
|
1893
|
-
autoExecute: config.autoExecute !== void 0 ? config.autoExecute : true,
|
|
1894
|
-
showIntent: config.showIntent !== void 0 ? config.showIntent : true,
|
|
1895
|
-
bypassKeywords: config.bypassKeywords || [],
|
|
1896
|
-
verbose: config.verbose !== void 0 ? config.verbose : false
|
|
1897
|
-
};
|
|
1898
|
-
}
|
|
1899
|
-
/**
|
|
1900
|
-
* Intercept user input and route automatically
|
|
1901
|
-
*/
|
|
1902
|
-
async intercept(userInput) {
|
|
1903
|
-
if (!this.config.enabled) {
|
|
1904
|
-
return {
|
|
1905
|
-
intercepted: false,
|
|
1906
|
-
reason: "Interceptor disabled"
|
|
1907
|
-
};
|
|
1908
|
-
}
|
|
1909
|
-
this.emit("intercept:started", { input: userInput });
|
|
1910
|
-
const bypassCheck = this.shouldBypass(userInput);
|
|
1911
|
-
if (bypassCheck.bypass) {
|
|
1912
|
-
this.emit("intercept:bypassed", { input: userInput, reason: bypassCheck.reason });
|
|
1913
|
-
return {
|
|
1914
|
-
intercepted: false,
|
|
1915
|
-
reason: "Bypassed",
|
|
1916
|
-
bypassed: true,
|
|
1917
|
-
bypassReason: bypassCheck.reason
|
|
1918
|
-
};
|
|
1919
|
-
}
|
|
1920
|
-
try {
|
|
1921
|
-
this.log(`Intercepting: ${userInput.substring(0, 50)}...`);
|
|
1922
|
-
if (this.config.showIntent) {
|
|
1923
|
-
this.showIntentMessage(userInput);
|
|
1924
|
-
}
|
|
1925
|
-
const executionResult = await this.autoExecutor.execute(userInput);
|
|
1926
|
-
this.emit("intercept:completed", { input: userInput, result: executionResult });
|
|
1927
|
-
return {
|
|
1928
|
-
intercepted: true,
|
|
1929
|
-
reason: "Automatically routed and executed",
|
|
1930
|
-
executionResult
|
|
1931
|
-
};
|
|
1932
|
-
} catch (error) {
|
|
1933
|
-
this.emit("intercept:failed", { input: userInput, error });
|
|
1934
|
-
throw error;
|
|
1935
|
-
}
|
|
1936
|
-
}
|
|
1937
|
-
/**
|
|
1938
|
-
* Check if input should bypass interception
|
|
1939
|
-
*/
|
|
1940
|
-
shouldBypass(input) {
|
|
1941
|
-
const normalized = input.trim().toLowerCase();
|
|
1942
|
-
if (this.systemCommands.some((cmd) => normalized.startsWith(cmd))) {
|
|
1943
|
-
return { bypass: true, reason: "System command" };
|
|
1944
|
-
}
|
|
1945
|
-
if (this.config.bypassKeywords.some((kw) => normalized.includes(kw.toLowerCase()))) {
|
|
1946
|
-
return { bypass: true, reason: "Custom bypass keyword" };
|
|
1947
|
-
}
|
|
1948
|
-
if (this.simpleQueryPatterns.some((pattern) => pattern.test(input))) {
|
|
1949
|
-
return { bypass: true, reason: "Simple informational query" };
|
|
1950
|
-
}
|
|
1951
|
-
if (input.split(/\s+/).length <= 3) {
|
|
1952
|
-
return { bypass: true, reason: "Too short - likely a simple question" };
|
|
1953
|
-
}
|
|
1954
|
-
return { bypass: false, reason: "" };
|
|
1955
|
-
}
|
|
1956
|
-
/**
|
|
1957
|
-
* Show intent message to user
|
|
1958
|
-
*/
|
|
1959
|
-
showIntentMessage(_input) {
|
|
1960
|
-
console.log("\n\u{1F9E0} Analyzing your request...");
|
|
1961
|
-
console.log(" System will automatically handle: skills, agents, MCP tools\n");
|
|
1962
|
-
}
|
|
1963
|
-
/**
|
|
1964
|
-
* Enable interceptor
|
|
1965
|
-
*/
|
|
1966
|
-
enable() {
|
|
1967
|
-
this.config.enabled = true;
|
|
1968
|
-
this.emit("interceptor:enabled");
|
|
1969
|
-
}
|
|
1970
|
-
/**
|
|
1971
|
-
* Disable interceptor
|
|
1972
|
-
*/
|
|
1973
|
-
disable() {
|
|
1974
|
-
this.config.enabled = false;
|
|
1975
|
-
this.emit("interceptor:disabled");
|
|
1976
|
-
}
|
|
1977
|
-
/**
|
|
1978
|
-
* Check if interceptor is enabled
|
|
1979
|
-
*/
|
|
1980
|
-
isEnabled() {
|
|
1981
|
-
return this.config.enabled;
|
|
1982
|
-
}
|
|
1983
|
-
/**
|
|
1984
|
-
* Log message if verbose
|
|
1985
|
-
*/
|
|
1986
|
-
log(message) {
|
|
1987
|
-
if (this.config.verbose) {
|
|
1988
|
-
console.log(`[CliInterceptor] ${message}`);
|
|
1989
|
-
}
|
|
1990
|
-
}
|
|
1991
|
-
}
|
|
1992
|
-
let globalInterceptor = null;
|
|
1993
|
-
function getGlobalCliInterceptor(config) {
|
|
1994
|
-
if (!globalInterceptor) {
|
|
1995
|
-
globalInterceptor = new CliInterceptor(config);
|
|
1996
|
-
}
|
|
1997
|
-
return globalInterceptor;
|
|
1998
|
-
}
|
|
1999
|
-
|
|
2000
|
-
class BrainRouter extends EventEmitter {
|
|
2001
|
-
interceptor = getGlobalCliInterceptor({
|
|
2002
|
-
enabled: true,
|
|
2003
|
-
autoExecute: true,
|
|
2004
|
-
showIntent: true,
|
|
2005
|
-
verbose: false
|
|
2006
|
-
});
|
|
2007
|
-
constructor() {
|
|
2008
|
-
super();
|
|
2009
|
-
this.interceptor.on("intercept:started", (data) => {
|
|
2010
|
-
this.emit("router:started", data);
|
|
2011
|
-
});
|
|
2012
|
-
this.interceptor.on("intercept:completed", (data) => {
|
|
2013
|
-
this.emit("router:completed", data);
|
|
2014
|
-
});
|
|
2015
|
-
this.interceptor.on("intercept:failed", (data) => {
|
|
2016
|
-
this.emit("router:failed", data);
|
|
2017
|
-
});
|
|
2018
|
-
this.interceptor.on("intercept:bypassed", (data) => {
|
|
2019
|
-
this.emit("router:bypassed", data);
|
|
2020
|
-
});
|
|
2021
|
-
}
|
|
2022
|
-
/**
|
|
2023
|
-
* Process user input - main entry point
|
|
2024
|
-
*
|
|
2025
|
-
* This is the ONLY function users/CLI need to call.
|
|
2026
|
-
* Everything else is automatic.
|
|
2027
|
-
*/
|
|
2028
|
-
async process(userInput) {
|
|
2029
|
-
try {
|
|
2030
|
-
const interceptionResult = await this.interceptor.intercept(userInput);
|
|
2031
|
-
if (interceptionResult.bypassed) {
|
|
2032
|
-
return {
|
|
2033
|
-
handled: false,
|
|
2034
|
-
passthrough: true,
|
|
2035
|
-
message: `Passing through to Claude Code: ${interceptionResult.bypassReason}`
|
|
2036
|
-
};
|
|
2037
|
-
}
|
|
2038
|
-
if (interceptionResult.intercepted && interceptionResult.executionResult) {
|
|
2039
|
-
return {
|
|
2040
|
-
handled: true,
|
|
2041
|
-
result: interceptionResult.executionResult,
|
|
2042
|
-
message: interceptionResult.executionResult.message
|
|
2043
|
-
};
|
|
2044
|
-
}
|
|
2045
|
-
return {
|
|
2046
|
-
handled: false,
|
|
2047
|
-
passthrough: true,
|
|
2048
|
-
message: "No interception needed"
|
|
2049
|
-
};
|
|
2050
|
-
} catch (error) {
|
|
2051
|
-
this.emit("router:error", { error, input: userInput });
|
|
2052
|
-
throw error;
|
|
2053
|
-
}
|
|
2054
|
-
}
|
|
2055
|
-
/**
|
|
2056
|
-
* Enable automatic routing
|
|
2057
|
-
*/
|
|
2058
|
-
enable() {
|
|
2059
|
-
this.interceptor.enable();
|
|
2060
|
-
this.emit("router:enabled");
|
|
2061
|
-
}
|
|
2062
|
-
/**
|
|
2063
|
-
* Disable automatic routing
|
|
2064
|
-
*/
|
|
2065
|
-
disable() {
|
|
2066
|
-
this.interceptor.disable();
|
|
2067
|
-
this.emit("router:disabled");
|
|
2068
|
-
}
|
|
2069
|
-
/**
|
|
2070
|
-
* Check if router is enabled
|
|
2071
|
-
*/
|
|
2072
|
-
isEnabled() {
|
|
2073
|
-
return this.interceptor.isEnabled();
|
|
2074
|
-
}
|
|
2075
|
-
}
|
|
2076
|
-
let globalRouter = null;
|
|
2077
|
-
function getGlobalBrainRouter() {
|
|
2078
|
-
if (!globalRouter) {
|
|
2079
|
-
globalRouter = new BrainRouter();
|
|
2080
|
-
}
|
|
2081
|
-
return globalRouter;
|
|
2082
|
-
}
|
|
2083
|
-
async function processUserInput(userInput) {
|
|
2084
|
-
const router = getGlobalBrainRouter();
|
|
2085
|
-
return await router.process(userInput);
|
|
2086
|
-
}
|
|
2087
|
-
|
|
2088
|
-
class BrainCliHook extends EventEmitter {
|
|
2089
|
-
config;
|
|
2090
|
-
initialized = false;
|
|
2091
|
-
constructor(config = {}) {
|
|
2092
|
-
super();
|
|
2093
|
-
this.config = {
|
|
2094
|
-
enabled: config.enabled !== void 0 ? config.enabled : true,
|
|
2095
|
-
silent: config.silent !== void 0 ? config.silent : false,
|
|
2096
|
-
fallbackToClaudeCode: config.fallbackToClaudeCode !== void 0 ? config.fallbackToClaudeCode : true
|
|
2097
|
-
};
|
|
2098
|
-
}
|
|
2099
|
-
/**
|
|
2100
|
-
* Initialize the hook
|
|
2101
|
-
*/
|
|
2102
|
-
async initialize() {
|
|
2103
|
-
if (this.initialized) {
|
|
2104
|
-
return;
|
|
2105
|
-
}
|
|
2106
|
-
const { getGlobalStateManager } = await import('./convoy-manager.mjs').then(function (n) { return n.b; });
|
|
2107
|
-
const { getGlobalMailboxManager } = await Promise.resolve().then(function () { return persistentMailbox; });
|
|
2108
|
-
const { getGlobalConvoyManager } = await import('./convoy-manager.mjs').then(function (n) { return n.c; });
|
|
2109
|
-
const stateManager = getGlobalStateManager();
|
|
2110
|
-
const mailboxManager = getGlobalMailboxManager();
|
|
2111
|
-
const convoyManager = getGlobalConvoyManager();
|
|
2112
|
-
await stateManager.initialize();
|
|
2113
|
-
await mailboxManager.initialize();
|
|
2114
|
-
await convoyManager.initialize();
|
|
2115
|
-
this.initialized = true;
|
|
2116
|
-
this.emit("hook:initialized");
|
|
2117
|
-
if (!this.config.silent) {
|
|
2118
|
-
console.log("\u{1F9E0} Brain system initialized - automatic routing enabled");
|
|
2119
|
-
}
|
|
2120
|
-
}
|
|
2121
|
-
/**
|
|
2122
|
-
* Process user input through the hook
|
|
2123
|
-
*/
|
|
2124
|
-
async processInput(userInput) {
|
|
2125
|
-
if (!this.config.enabled) {
|
|
2126
|
-
return {
|
|
2127
|
-
intercepted: false,
|
|
2128
|
-
handled: false,
|
|
2129
|
-
shouldContinue: true,
|
|
2130
|
-
message: "Hook disabled"
|
|
2131
|
-
};
|
|
2132
|
-
}
|
|
2133
|
-
if (!this.initialized) {
|
|
2134
|
-
await this.initialize();
|
|
2135
|
-
}
|
|
2136
|
-
try {
|
|
2137
|
-
const result = await processUserInput(userInput);
|
|
2138
|
-
if (result.handled && result.result) {
|
|
2139
|
-
this.emit("hook:handled", { input: userInput, result: result.result });
|
|
2140
|
-
if (!this.config.silent) {
|
|
2141
|
-
this.displayResult(result.result);
|
|
2142
|
-
}
|
|
2143
|
-
return {
|
|
2144
|
-
intercepted: true,
|
|
2145
|
-
handled: true,
|
|
2146
|
-
executionResult: result.result,
|
|
2147
|
-
shouldContinue: false,
|
|
2148
|
-
// Don't pass to Claude Code
|
|
2149
|
-
message: result.message
|
|
2150
|
-
};
|
|
2151
|
-
}
|
|
2152
|
-
if (result.passthrough) {
|
|
2153
|
-
this.emit("hook:passthrough", { input: userInput, reason: result.message });
|
|
2154
|
-
const additionalContext = this.config.silent ? void 0 : await this.buildAdditionalContext();
|
|
2155
|
-
return {
|
|
2156
|
-
intercepted: true,
|
|
2157
|
-
handled: false,
|
|
2158
|
-
shouldContinue: true,
|
|
2159
|
-
// Pass to Claude Code
|
|
2160
|
-
message: result.message,
|
|
2161
|
-
additionalContext
|
|
2162
|
-
};
|
|
2163
|
-
}
|
|
2164
|
-
return {
|
|
2165
|
-
intercepted: false,
|
|
2166
|
-
handled: false,
|
|
2167
|
-
shouldContinue: this.config.fallbackToClaudeCode,
|
|
2168
|
-
message: "No interception"
|
|
2169
|
-
};
|
|
2170
|
-
} catch (error) {
|
|
2171
|
-
this.emit("hook:error", { error, input: userInput });
|
|
2172
|
-
if (this.config.fallbackToClaudeCode) {
|
|
2173
|
-
console.error("Brain system error, falling back to Claude Code:", error);
|
|
2174
|
-
return {
|
|
2175
|
-
intercepted: true,
|
|
2176
|
-
handled: false,
|
|
2177
|
-
shouldContinue: true,
|
|
2178
|
-
message: "Error - falling back to Claude Code"
|
|
2179
|
-
};
|
|
2180
|
-
}
|
|
2181
|
-
throw error;
|
|
2182
|
-
}
|
|
2183
|
-
}
|
|
2184
|
-
/**
|
|
2185
|
-
* Display execution result to user
|
|
2186
|
-
*/
|
|
2187
|
-
displayResult(result) {
|
|
2188
|
-
console.log(`
|
|
2189
|
-
${"=".repeat(60)}`);
|
|
2190
|
-
console.log("\u{1F9E0} Brain System Result");
|
|
2191
|
-
console.log("=".repeat(60));
|
|
2192
|
-
console.log();
|
|
2193
|
-
const routeEmoji = {
|
|
2194
|
-
mayor: "\u{1F454}",
|
|
2195
|
-
plan: "\u{1F4CB}",
|
|
2196
|
-
feature: "\u26A1",
|
|
2197
|
-
direct: "\u{1F680}"
|
|
2198
|
-
};
|
|
2199
|
-
console.log(`${routeEmoji[result.route]} Route: ${result.route.toUpperCase()}`);
|
|
2200
|
-
console.log(`\u{1F4CA} Complexity: ${result.intent.complexity}`);
|
|
2201
|
-
console.log(`\u{1F3AF} Intent: ${result.intent.type}`);
|
|
2202
|
-
console.log();
|
|
2203
|
-
if (result.agentsCreated.length > 0) {
|
|
2204
|
-
console.log("\u{1F916} Agents Created:");
|
|
2205
|
-
for (const agent of result.agentsCreated) {
|
|
2206
|
-
console.log(` \u2713 ${agent}`);
|
|
2207
|
-
}
|
|
2208
|
-
console.log();
|
|
2209
|
-
}
|
|
2210
|
-
if (result.skillsCreated.length > 0) {
|
|
2211
|
-
console.log("\u{1F393} Skills Created:");
|
|
2212
|
-
for (const skill of result.skillsCreated) {
|
|
2213
|
-
console.log(` \u2713 ${skill}`);
|
|
2214
|
-
}
|
|
2215
|
-
console.log();
|
|
2216
|
-
}
|
|
2217
|
-
if (result.mcpToolsUsed.length > 0) {
|
|
2218
|
-
console.log("\u{1F527} MCP Tools Selected:");
|
|
2219
|
-
for (const tool of result.mcpToolsUsed) {
|
|
2220
|
-
console.log(` \u2713 ${tool}`);
|
|
2221
|
-
}
|
|
2222
|
-
console.log();
|
|
2223
|
-
}
|
|
2224
|
-
if (result.convoyId) {
|
|
2225
|
-
console.log(`\u{1F4E6} Convoy: ${result.convoyId}`);
|
|
2226
|
-
console.log();
|
|
2227
|
-
}
|
|
2228
|
-
console.log("\u{1F4AC} Message:");
|
|
2229
|
-
console.log(` ${result.message}`);
|
|
2230
|
-
console.log();
|
|
2231
|
-
console.log("=".repeat(60));
|
|
2232
|
-
console.log();
|
|
2233
|
-
}
|
|
2234
|
-
/**
|
|
2235
|
-
* Build additional context string for PreToolUse hook injection.
|
|
2236
|
-
* Provides brain insights (task state, session context) to the model
|
|
2237
|
-
* without blocking tool execution. Claude Code 2.1+ feature.
|
|
2238
|
-
*/
|
|
2239
|
-
async buildAdditionalContext() {
|
|
2240
|
-
try {
|
|
2241
|
-
const { loadContextAtDepth } = await import('./context-loader.mjs');
|
|
2242
|
-
const ctx = await loadContextAtDepth("L0");
|
|
2243
|
-
if (ctx.totalTokens > 0) {
|
|
2244
|
-
return `[Brain Context: ${ctx.layers.size} layers, ~${ctx.totalTokens} tokens, depth=${ctx.depth}]`;
|
|
2245
|
-
}
|
|
2246
|
-
return void 0;
|
|
2247
|
-
} catch {
|
|
2248
|
-
return void 0;
|
|
2249
|
-
}
|
|
2250
|
-
}
|
|
2251
|
-
/**
|
|
2252
|
-
* Enable the hook
|
|
2253
|
-
*/
|
|
2254
|
-
enable() {
|
|
2255
|
-
this.config.enabled = true;
|
|
2256
|
-
this.emit("hook:enabled");
|
|
2257
|
-
}
|
|
2258
|
-
/**
|
|
2259
|
-
* Disable the hook
|
|
2260
|
-
*/
|
|
2261
|
-
disable() {
|
|
2262
|
-
this.config.enabled = false;
|
|
2263
|
-
this.emit("hook:disabled");
|
|
2264
|
-
}
|
|
2265
|
-
/**
|
|
2266
|
-
* Check if hook is enabled
|
|
2267
|
-
*/
|
|
2268
|
-
isEnabled() {
|
|
2269
|
-
return this.config.enabled;
|
|
2270
|
-
}
|
|
2271
|
-
}
|
|
2272
|
-
let globalHook = null;
|
|
2273
|
-
function getGlobalBrainHook(config) {
|
|
2274
|
-
if (!globalHook) {
|
|
2275
|
-
globalHook = new BrainCliHook(config);
|
|
2276
|
-
}
|
|
2277
|
-
return globalHook;
|
|
2278
|
-
}
|
|
2279
|
-
async function setupBrainHook(config) {
|
|
2280
|
-
const hook = getGlobalBrainHook(config);
|
|
2281
|
-
await hook.initialize();
|
|
2282
|
-
return hook;
|
|
2283
|
-
}
|
|
2284
|
-
|
|
2285
|
-
export { BrainCliHook, getGlobalBrainHook, setupBrainHook };
|