ccjk 14.2.2 → 15.0.0
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/LICENSE +1 -1
- package/README.md +58 -341
- package/dist/cli.js +59 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/detect.js +15 -0
- package/dist/commands/detect.js.map +1 -0
- package/dist/commands/doctor.js +68 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/git-install.js +50 -0
- package/dist/commands/git-install.js.map +1 -0
- package/dist/commands/init.js +102 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/mcp.js +66 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/menu.js +33 -0
- package/dist/commands/menu.js.map +1 -0
- package/dist/core/detect.js +24 -0
- package/dist/core/detect.js.map +1 -0
- package/dist/core/lint.js +49 -0
- package/dist/core/lint.js.map +1 -0
- package/dist/core/mcp.js +41 -0
- package/dist/core/mcp.js.map +1 -0
- package/dist/core/paths.js +9 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/providers.js +53 -0
- package/dist/core/providers.js.map +1 -0
- package/dist/core/settings.js +31 -0
- package/dist/core/settings.js.map +1 -0
- package/dist/core/slash-templates.js +56 -0
- package/dist/core/slash-templates.js.map +1 -0
- package/dist/core/tools.js +27 -0
- package/dist/core/tools.js.map +1 -0
- package/package.json +43 -164
- package/README.HONEST.md +0 -176
- package/README.en.md +0 -67
- package/README.ja.md +0 -67
- package/README.ko.md +0 -67
- package/README.zh-CN.md +0 -86
- package/bin/ccjk.mjs +0 -5
- package/bin/ccjk.ts +0 -222
- package/dist/chunks/agent-teams.mjs +0 -145
- package/dist/chunks/agent.mjs +0 -1439
- package/dist/chunks/agents.mjs +0 -3783
- package/dist/chunks/api-cli.mjs +0 -135
- package/dist/chunks/api-config-selector.mjs +0 -159
- package/dist/chunks/api-providers.mjs +0 -144
- package/dist/chunks/api.mjs +0 -115
- package/dist/chunks/auto-bootstrap.mjs +0 -358
- package/dist/chunks/auto-fixer.mjs +0 -95
- package/dist/chunks/auto-updater.mjs +0 -507
- package/dist/chunks/banner.mjs +0 -173
- package/dist/chunks/bash.mjs +0 -187
- package/dist/chunks/boost.mjs +0 -474
- package/dist/chunks/brain-config.mjs +0 -75
- package/dist/chunks/brain-status.mjs +0 -89
- package/dist/chunks/ccjk-agents.mjs +0 -416
- package/dist/chunks/ccjk-all.mjs +0 -1046
- package/dist/chunks/ccjk-config.mjs +0 -445
- package/dist/chunks/ccjk-hooks.mjs +0 -1074
- package/dist/chunks/ccjk-mcp.mjs +0 -763
- package/dist/chunks/ccjk-setup.mjs +0 -765
- package/dist/chunks/ccjk-skills.mjs +0 -518
- package/dist/chunks/ccr.mjs +0 -109
- package/dist/chunks/ccu.mjs +0 -40
- package/dist/chunks/check-updates.mjs +0 -117
- package/dist/chunks/claude-code-incremental-manager.mjs +0 -761
- package/dist/chunks/claude-config.mjs +0 -606
- package/dist/chunks/claude-config2.mjs +0 -62
- package/dist/chunks/claude-wrapper.mjs +0 -85
- package/dist/chunks/clavue-config.mjs +0 -1454
- package/dist/chunks/cleanup-migration.mjs +0 -20
- package/dist/chunks/cli-hook.mjs +0 -4096
- package/dist/chunks/cloud-sync.mjs +0 -29
- package/dist/chunks/code-type-resolver.mjs +0 -880
- package/dist/chunks/codex-config-switch.mjs +0 -452
- package/dist/chunks/codex-provider-manager.mjs +0 -238
- package/dist/chunks/codex-uninstaller.mjs +0 -404
- package/dist/chunks/codex.mjs +0 -2141
- package/dist/chunks/commands.mjs +0 -108
- package/dist/chunks/commands2.mjs +0 -421
- package/dist/chunks/commit.mjs +0 -140
- package/dist/chunks/completion.mjs +0 -517
- package/dist/chunks/config-consolidator.mjs +0 -172
- package/dist/chunks/config-switch.mjs +0 -334
- package/dist/chunks/config.mjs +0 -558
- package/dist/chunks/config2.mjs +0 -484
- package/dist/chunks/config3.mjs +0 -486
- package/dist/chunks/constants.mjs +0 -323
- package/dist/chunks/context-opt.mjs +0 -444
- package/dist/chunks/context.mjs +0 -974
- package/dist/chunks/dashboard.mjs +0 -481
- package/dist/chunks/doctor.mjs +0 -1301
- package/dist/chunks/eval.mjs +0 -502
- package/dist/chunks/evolution.mjs +0 -322
- package/dist/chunks/features.mjs +0 -715
- package/dist/chunks/fish.mjs +0 -181
- package/dist/chunks/fs-operations.mjs +0 -180
- package/dist/chunks/health-alerts.mjs +0 -830
- package/dist/chunks/help.mjs +0 -341
- package/dist/chunks/hook-installer.mjs +0 -48
- package/dist/chunks/impact.mjs +0 -651
- package/dist/chunks/index.mjs +0 -23
- package/dist/chunks/index10.mjs +0 -19
- package/dist/chunks/index11.mjs +0 -1171
- package/dist/chunks/index12.mjs +0 -218
- package/dist/chunks/index13.mjs +0 -679
- package/dist/chunks/index14.mjs +0 -1009
- package/dist/chunks/index15.mjs +0 -194
- package/dist/chunks/index2.mjs +0 -7637
- package/dist/chunks/index3.mjs +0 -171
- package/dist/chunks/index4.mjs +0 -26
- package/dist/chunks/index5.mjs +0 -19
- package/dist/chunks/index6.mjs +0 -19092
- package/dist/chunks/index7.mjs +0 -616
- package/dist/chunks/index8.mjs +0 -1602
- package/dist/chunks/index9.mjs +0 -5384
- package/dist/chunks/init.mjs +0 -1911
- package/dist/chunks/installer.mjs +0 -757
- package/dist/chunks/installer2.mjs +0 -103
- 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 -265
- package/dist/chunks/mcp-cli.mjs +0 -205
- package/dist/chunks/mcp-performance.mjs +0 -187
- package/dist/chunks/mcp.mjs +0 -667
- package/dist/chunks/memory-check.mjs +0 -2973
- package/dist/chunks/memory-paths.mjs +0 -259
- package/dist/chunks/memory-sync.mjs +0 -209
- package/dist/chunks/memory.mjs +0 -354
- package/dist/chunks/metrics-display.mjs +0 -153
- package/dist/chunks/monitor.mjs +0 -1856
- package/dist/chunks/notification.mjs +0 -1864
- package/dist/chunks/onboarding.mjs +0 -386
- package/dist/chunks/package.mjs +0 -3
- package/dist/chunks/paradigm.mjs +0 -74
- package/dist/chunks/permission-manager.mjs +0 -250
- package/dist/chunks/permissions.mjs +0 -265
- package/dist/chunks/persistence-manager.mjs +0 -801
- package/dist/chunks/persistence.mjs +0 -707
- package/dist/chunks/platform.mjs +0 -395
- package/dist/chunks/plugin.mjs +0 -1936
- package/dist/chunks/powershell.mjs +0 -213
- package/dist/chunks/prompts.mjs +0 -244
- package/dist/chunks/providers.mjs +0 -263
- package/dist/chunks/quick-actions.mjs +0 -335
- package/dist/chunks/quick-provider.mjs +0 -755
- package/dist/chunks/quick-setup.mjs +0 -421
- package/dist/chunks/remote.mjs +0 -497
- package/dist/chunks/research.mjs +0 -1904
- package/dist/chunks/rollback.mjs +0 -38
- package/dist/chunks/session-manager.mjs +0 -1371
- 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 -122
- package/dist/chunks/skill.mjs +0 -117
- package/dist/chunks/skill2.mjs +0 -9052
- package/dist/chunks/skills-sync.mjs +0 -1343
- package/dist/chunks/skills.mjs +0 -577
- package/dist/chunks/slash-commands.mjs +0 -208
- package/dist/chunks/smart-guide.mjs +0 -247
- package/dist/chunks/snapshot.mjs +0 -58
- package/dist/chunks/startup.mjs +0 -487
- package/dist/chunks/stats.mjs +0 -191
- package/dist/chunks/status.mjs +0 -471
- 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 -852
- package/dist/chunks/update.mjs +0 -174
- package/dist/chunks/upgrade-manager.mjs +0 -204
- package/dist/chunks/upgrade.mjs +0 -133
- package/dist/chunks/version-checker.mjs +0 -891
- 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 -871
- 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 -2684
- package/dist/i18n/locales/en/agent-teams.json +0 -18
- package/dist/i18n/locales/en/agentBrowser.json +0 -80
- 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 -148
- 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 -184
- 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 -236
- 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 -180
- package/dist/i18n/locales/en/memory.json +0 -23
- package/dist/i18n/locales/en/menu.json +0 -299
- 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 -80
- 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 -148
- 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 -184
- 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 -234
- 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 -180
- package/dist/i18n/locales/zh-CN/memory.json +0 -23
- package/dist/i18n/locales/zh-CN/menu.json +0 -299
- 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 -5658
- package/dist/index.d.ts +0 -5658
- package/dist/index.mjs +0 -3732
- package/dist/shared/ccjk.5bEolFrk.mjs +0 -254
- package/dist/shared/ccjk.8oaxX4iR.mjs +0 -90
- package/dist/shared/ccjk.B2U7DsPy.mjs +0 -31
- package/dist/shared/ccjk.B2f-cwUP.mjs +0 -468
- 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.BLsIiTqO.mjs +0 -449
- package/dist/shared/ccjk.BXv8aYs1.mjs +0 -170
- package/dist/shared/ccjk.BnsY5WxD.mjs +0 -171
- package/dist/shared/ccjk.BoApaI4j.mjs +0 -28
- package/dist/shared/ccjk.Bq8TqZG_.mjs +0 -189
- package/dist/shared/ccjk.BtrioX1Z.mjs +0 -25
- package/dist/shared/ccjk.Bx_rmYfN.mjs +0 -69
- package/dist/shared/ccjk.BzPbSEP2.mjs +0 -115
- package/dist/shared/ccjk.C0WLUnFV.mjs +0 -293
- package/dist/shared/ccjk.C1hANZTu.mjs +0 -19
- package/dist/shared/ccjk.C2jHOZVP.mjs +0 -52
- package/dist/shared/ccjk.CNhnT6uQ.mjs +0 -636
- package/dist/shared/ccjk.COweQ1RR.mjs +0 -5
- package/dist/shared/ccjk.CfKKcvWy.mjs +0 -126
- package/dist/shared/ccjk.Cjgrln_h.mjs +0 -297
- package/dist/shared/ccjk.CoCHVXl3.mjs +0 -3951
- package/dist/shared/ccjk.CwGZSTAK.mjs +0 -319
- package/dist/shared/ccjk.CxpGa6MC.mjs +0 -2724
- package/dist/shared/ccjk.D-magaEx.mjs +0 -763
- package/dist/shared/ccjk.D0g2ABGg.mjs +0 -171
- package/dist/shared/ccjk.D6ycHbak.mjs +0 -270
- package/dist/shared/ccjk.D75wivnp.mjs +0 -142
- package/dist/shared/ccjk.DDL-4C-k.mjs +0 -100
- package/dist/shared/ccjk.DFRPtmK_.mjs +0 -75
- package/dist/shared/ccjk.DMV3x5Sd.mjs +0 -299
- package/dist/shared/ccjk.DZ2LLOa-.mjs +0 -2195
- package/dist/shared/ccjk.DbigonEQ.mjs +0 -698
- package/dist/shared/ccjk.DcMvE7lf.mjs +0 -618
- package/dist/shared/ccjk.DeWpAShp.mjs +0 -1828
- package/dist/shared/ccjk.DhJ1kyDR.mjs +0 -30
- package/dist/shared/ccjk.DlTXS9rP.mjs +0 -224
- package/dist/shared/ccjk.DopKzo3z.mjs +0 -305
- package/dist/shared/ccjk.DsZsc4LR.mjs +0 -1280
- package/dist/shared/ccjk.DuzJZlgj.mjs +0 -418
- package/dist/shared/ccjk.Dxgd2vjc.mjs +0 -444
- package/dist/shared/ccjk.J8YiPsOw.mjs +0 -259
- package/dist/shared/ccjk.KfSWcGlE.mjs +0 -38
- package/dist/shared/ccjk.L7yC58_i.mjs +0 -225
- package/dist/shared/ccjk.MwtjAULc.mjs +0 -1447
- package/dist/shared/ccjk.OJKHVSOb.mjs +0 -2005
- package/dist/shared/ccjk.OTnevPNE.mjs +0 -225
- package/dist/shared/ccjk.RyizuzOI.mjs +0 -21
- package/dist/shared/ccjk.T_cX87dY.mjs +0 -15
- package/dist/shared/ccjk.bQ7Dh1g4.mjs +0 -249
- package/dist/shared/ccjk.gDEDGD_t.mjs +0 -38
- package/dist/shared/ccjk.hoqrwWdN.mjs +0 -333
- package/dist/shared/ccjk.i_vn-9C3.mjs +0 -317
- package/dist/shared/ccjk.lG3ccFjm.mjs +0 -885
- package/dist/shared/ccjk.wLJHO0Af.mjs +0 -244
- package/dist/shared/ccjk.y-a_1vK4.mjs +0 -5127
- package/dist/templates/agents/README.md +0 -78
- package/dist/templates/agents/fullstack-developer.json +0 -70
- package/dist/templates/agents/go-expert.json +0 -69
- package/dist/templates/agents/index.json +0 -64
- package/dist/templates/agents/python-expert.json +0 -69
- package/dist/templates/agents/react-specialist.json +0 -69
- package/dist/templates/agents/testing-automation-expert.json +0 -70
- package/dist/templates/agents/typescript-architect.json +0 -69
- package/dist/templates/claude-code/common/settings.json +0 -109
- package/dist/templates/common/error-prevention.md +0 -267
- package/dist/templates/common/karpathy-baseline.md +0 -83
- package/dist/templates/common/output-styles/zh-CN/carmack-mode.md +0 -381
- package/dist/templates/common/output-styles/zh-CN/codex-rigor-mode.md +0 -114
- package/dist/templates/common/output-styles/zh-CN/dhh-mode.md +0 -265
- package/dist/templates/common/output-styles/zh-CN/evan-you-mode.md +0 -539
- package/dist/templates/common/output-styles/zh-CN/jobs-mode.md +0 -369
- package/dist/templates/common/output-styles/zh-CN/linus-mode.md +0 -135
- package/dist/templates/common/output-styles/zh-CN/uncle-bob-mode.md +0 -221
- package/dist/templates/common/workflow/continuousDelivery/en/continuous-delivery.md +0 -628
- package/dist/templates/common/workflow/continuousDelivery/zh-CN/continuous-delivery.md +0 -628
- package/dist/templates/common/workflow/essential/en/agents/ccjk-config-agent.md +0 -187
- package/dist/templates/common/workflow/essential/en/agents/ccjk-mcp-agent.md +0 -191
- package/dist/templates/common/workflow/essential/en/agents/ccjk-skill-agent.md +0 -249
- package/dist/templates/common/workflow/essential/en/agents/ccjk-workflow-agent.md +0 -277
- package/dist/templates/common/workflow/essential/en/agents/get-current-datetime.md +0 -29
- package/dist/templates/common/workflow/essential/en/agents/init-architect.md +0 -115
- package/dist/templates/common/workflow/essential/en/agents/ui-ux-designer.md +0 -91
- package/dist/templates/common/workflow/essential/en/feat.md +0 -92
- package/dist/templates/common/workflow/essential/en/goal.md +0 -147
- package/dist/templates/common/workflow/essential/en/init-project.md +0 -53
- package/dist/templates/common/workflow/essential/zh-CN/agents/get-current-datetime.md +0 -29
- package/dist/templates/common/workflow/essential/zh-CN/agents/init-architect.md +0 -115
- package/dist/templates/common/workflow/essential/zh-CN/agents/ui-ux-designer.md +0 -91
- package/dist/templates/common/workflow/essential/zh-CN/feat.md +0 -315
- package/dist/templates/common/workflow/essential/zh-CN/goal.md +0 -146
- package/dist/templates/common/workflow/essential/zh-CN/init-project.md +0 -53
- package/dist/templates/common/workflow/git/en/git-cleanBranches.md +0 -102
- package/dist/templates/common/workflow/git/en/git-commit.md +0 -205
- package/dist/templates/common/workflow/git/en/git-rollback.md +0 -90
- package/dist/templates/common/workflow/git/en/git-worktree.md +0 -276
- package/dist/templates/common/workflow/git/zh-CN/git-cleanBranches.md +0 -102
- package/dist/templates/common/workflow/git/zh-CN/git-commit.md +0 -205
- package/dist/templates/common/workflow/git/zh-CN/git-rollback.md +0 -90
- package/dist/templates/common/workflow/git/zh-CN/git-worktree.md +0 -276
- package/dist/templates/common/workflow/interview/en/interview.md +0 -67
- package/dist/templates/common/workflow/interview/zh-CN/interview.md +0 -67
- package/dist/templates/common/workflow/linearMethod/en/linear-method.md +0 -651
- package/dist/templates/common/workflow/linearMethod/zh-CN/linear-method.md +0 -752
- package/dist/templates/common/workflow/refactoringMaster/en/refactoring-master.md +0 -516
- package/dist/templates/common/workflow/refactoringMaster/zh-CN/refactoring-master.md +0 -812
- package/dist/templates/common/workflow/sixStep/en/workflow.md +0 -83
- package/dist/templates/common/workflow/sixStep/zh-CN/workflow.md +0 -359
- package/dist/templates/common/workflow/specFirstTDD/en/spec-first-tdd.md +0 -364
- package/dist/templates/common/workflow/specFirstTDD/zh-CN/spec-first-tdd.md +0 -366
- package/dist/templates/hooks/README.md +0 -212
- package/dist/templates/hooks/git-workflow-hooks.md +0 -551
- package/dist/templates/hooks/post-test/coverage.json +0 -21
- package/dist/templates/hooks/post-test/summary.json +0 -21
- package/dist/templates/hooks/post-test-coverage.md +0 -434
- package/dist/templates/hooks/pre-commit/eslint.json +0 -22
- package/dist/templates/hooks/pre-commit/prettier.json +0 -22
- package/dist/templates/hooks/pre-commit-black.md +0 -274
- package/dist/templates/hooks/pre-commit-eslint.md +0 -153
- package/dist/templates/hooks/pre-commit-gofmt.md +0 -284
- package/dist/templates/hooks/pre-commit-prettier.md +0 -212
- package/dist/templates/hooks/pre-commit-type-check.md +0 -377
- package/dist/templates/skills/ccjk-init.md +0 -154
- package/dist/templates/skills/ccjk-mcp-setup.md +0 -205
- package/dist/templates/skills/ccjk-troubleshoot.md +0 -228
- package/dist/templates/skills/django-patterns.md +0 -1016
- package/dist/templates/skills/git-workflow.md +0 -748
- package/dist/templates/skills/go-idioms.md +0 -963
- package/dist/templates/skills/index.json +0 -132
- package/dist/templates/skills/nextjs-optimization.md +0 -694
- package/dist/templates/skills/python-pep8.md +0 -852
- package/dist/templates/skills/react-patterns.md +0 -686
- package/dist/templates/skills/rust-patterns.md +0 -1057
- package/dist/templates/skills/security-best-practices.md +0 -1413
- package/dist/templates/skills/testing-best-practices.md +0 -1315
- package/dist/templates/skills/ts-best-practices.md +0 -354
- package/templates/agents/README.md +0 -78
- package/templates/agents/fullstack-developer.json +0 -70
- package/templates/agents/go-expert.json +0 -69
- package/templates/agents/index.json +0 -64
- package/templates/agents/python-expert.json +0 -69
- package/templates/agents/react-specialist.json +0 -69
- package/templates/agents/testing-automation-expert.json +0 -70
- package/templates/agents/typescript-architect.json +0 -69
- package/templates/claude-code/common/settings.json +0 -109
- package/templates/common/error-prevention.md +0 -267
- package/templates/common/karpathy-baseline.md +0 -83
- package/templates/common/output-styles/zh-CN/carmack-mode.md +0 -381
- package/templates/common/output-styles/zh-CN/codex-rigor-mode.md +0 -114
- package/templates/common/output-styles/zh-CN/dhh-mode.md +0 -265
- package/templates/common/output-styles/zh-CN/evan-you-mode.md +0 -539
- package/templates/common/output-styles/zh-CN/jobs-mode.md +0 -369
- package/templates/common/output-styles/zh-CN/linus-mode.md +0 -135
- package/templates/common/output-styles/zh-CN/uncle-bob-mode.md +0 -221
- package/templates/common/workflow/continuousDelivery/en/continuous-delivery.md +0 -628
- package/templates/common/workflow/continuousDelivery/zh-CN/continuous-delivery.md +0 -628
- package/templates/common/workflow/essential/en/agents/ccjk-config-agent.md +0 -187
- package/templates/common/workflow/essential/en/agents/ccjk-mcp-agent.md +0 -191
- package/templates/common/workflow/essential/en/agents/ccjk-skill-agent.md +0 -249
- package/templates/common/workflow/essential/en/agents/ccjk-workflow-agent.md +0 -277
- package/templates/common/workflow/essential/en/agents/get-current-datetime.md +0 -29
- package/templates/common/workflow/essential/en/agents/init-architect.md +0 -115
- package/templates/common/workflow/essential/en/agents/ui-ux-designer.md +0 -91
- package/templates/common/workflow/essential/en/feat.md +0 -92
- package/templates/common/workflow/essential/en/goal.md +0 -147
- package/templates/common/workflow/essential/en/init-project.md +0 -53
- package/templates/common/workflow/essential/zh-CN/agents/get-current-datetime.md +0 -29
- package/templates/common/workflow/essential/zh-CN/agents/init-architect.md +0 -115
- package/templates/common/workflow/essential/zh-CN/agents/ui-ux-designer.md +0 -91
- package/templates/common/workflow/essential/zh-CN/feat.md +0 -315
- package/templates/common/workflow/essential/zh-CN/goal.md +0 -146
- package/templates/common/workflow/essential/zh-CN/init-project.md +0 -53
- package/templates/common/workflow/git/en/git-cleanBranches.md +0 -102
- package/templates/common/workflow/git/en/git-commit.md +0 -205
- package/templates/common/workflow/git/en/git-rollback.md +0 -90
- package/templates/common/workflow/git/en/git-worktree.md +0 -276
- package/templates/common/workflow/git/zh-CN/git-cleanBranches.md +0 -102
- package/templates/common/workflow/git/zh-CN/git-commit.md +0 -205
- package/templates/common/workflow/git/zh-CN/git-rollback.md +0 -90
- package/templates/common/workflow/git/zh-CN/git-worktree.md +0 -276
- package/templates/common/workflow/interview/en/interview.md +0 -67
- package/templates/common/workflow/interview/zh-CN/interview.md +0 -67
- package/templates/common/workflow/linearMethod/en/linear-method.md +0 -651
- package/templates/common/workflow/linearMethod/zh-CN/linear-method.md +0 -752
- package/templates/common/workflow/refactoringMaster/en/refactoring-master.md +0 -516
- package/templates/common/workflow/refactoringMaster/zh-CN/refactoring-master.md +0 -812
- package/templates/common/workflow/sixStep/en/workflow.md +0 -83
- package/templates/common/workflow/sixStep/zh-CN/workflow.md +0 -359
- package/templates/common/workflow/specFirstTDD/en/spec-first-tdd.md +0 -364
- package/templates/common/workflow/specFirstTDD/zh-CN/spec-first-tdd.md +0 -366
- package/templates/hooks/README.md +0 -212
- package/templates/hooks/git-workflow-hooks.md +0 -551
- package/templates/hooks/post-test/coverage.json +0 -21
- package/templates/hooks/post-test/summary.json +0 -21
- package/templates/hooks/post-test-coverage.md +0 -434
- package/templates/hooks/pre-commit/eslint.json +0 -22
- package/templates/hooks/pre-commit/prettier.json +0 -22
- package/templates/hooks/pre-commit-black.md +0 -274
- package/templates/hooks/pre-commit-eslint.md +0 -153
- package/templates/hooks/pre-commit-gofmt.md +0 -284
- package/templates/hooks/pre-commit-prettier.md +0 -212
- package/templates/hooks/pre-commit-type-check.md +0 -377
- package/templates/skills/basic.hbs +0 -72
- package/templates/skills/ccjk-init.md +0 -154
- package/templates/skills/ccjk-mcp-setup.md +0 -205
- package/templates/skills/ccjk-troubleshoot.md +0 -228
- package/templates/skills/code-refactor.hbs +0 -133
- package/templates/skills/code-review.hbs +0 -141
- package/templates/skills/django-patterns.md +0 -1016
- package/templates/skills/git-workflow.md +0 -748
- package/templates/skills/go-idioms.md +0 -963
- package/templates/skills/index.json +0 -132
- package/templates/skills/nextjs-optimization.md +0 -694
- package/templates/skills/python-pep8.md +0 -852
- package/templates/skills/react-patterns.md +0 -686
- package/templates/skills/rust-patterns.md +0 -1057
- package/templates/skills/security-best-practices.md +0 -1413
- package/templates/skills/testing-best-practices.md +0 -1315
- package/templates/skills/ts-best-practices.md +0 -354
- package/templates/skills/type-fix.hbs +0 -132
package/dist/chunks/agents.mjs
DELETED
|
@@ -1,3783 +0,0 @@
|
|
|
1
|
-
import a from './index5.mjs';
|
|
2
|
-
import { n as nanoid } from '../shared/ccjk.BoApaI4j.mjs';
|
|
3
|
-
import ora from './index8.mjs';
|
|
4
|
-
import { c as contextLoader, S as SessionIntelligence, g as getGlobalConvoyManager } from './session-manager.mjs';
|
|
5
|
-
import { EventEmitter } from 'node:events';
|
|
6
|
-
import { c as resolve } from '../shared/ccjk.bQ7Dh1g4.mjs';
|
|
7
|
-
import { e as executionTracer } from '../shared/ccjk.DlTXS9rP.mjs';
|
|
8
|
-
import { t as taskPersistence } from '../shared/ccjk.CNhnT6uQ.mjs';
|
|
9
|
-
import '../shared/ccjk.BAGoDD49.mjs';
|
|
10
|
-
import 'node:crypto';
|
|
11
|
-
import 'node:process';
|
|
12
|
-
import '../shared/ccjk.Cjgrln_h.mjs';
|
|
13
|
-
import '../shared/ccjk.DeWpAShp.mjs';
|
|
14
|
-
import 'node:fs';
|
|
15
|
-
import 'node:os';
|
|
16
|
-
import './main.mjs';
|
|
17
|
-
import 'module';
|
|
18
|
-
import 'node:child_process';
|
|
19
|
-
import 'node:path';
|
|
20
|
-
import 'node:stream';
|
|
21
|
-
import 'node:readline';
|
|
22
|
-
import 'tinyglobby';
|
|
23
|
-
import '../shared/ccjk.wLJHO0Af.mjs';
|
|
24
|
-
import 'node:fs/promises';
|
|
25
|
-
import 'better-sqlite3';
|
|
26
|
-
|
|
27
|
-
const DEFAULT_AGENT_TYPE_MAPPINGS = {
|
|
28
|
-
"typescript": "coder",
|
|
29
|
-
"typescript-cli": "coder",
|
|
30
|
-
"ts-cli-architect": "architect",
|
|
31
|
-
"ts-architect": "architect",
|
|
32
|
-
"i18n": "specialist",
|
|
33
|
-
"internationalization": "specialist",
|
|
34
|
-
"i18n-specialist": "specialist",
|
|
35
|
-
"tools": "specialist",
|
|
36
|
-
"integration": "specialist",
|
|
37
|
-
"tools-integration": "specialist",
|
|
38
|
-
"template": "specialist",
|
|
39
|
-
"templating": "specialist",
|
|
40
|
-
"template-engine": "specialist",
|
|
41
|
-
"config": "architect",
|
|
42
|
-
"configuration": "architect",
|
|
43
|
-
"config-architect": "architect",
|
|
44
|
-
"testing": "tester",
|
|
45
|
-
"test": "tester",
|
|
46
|
-
"testing-specialist": "tester",
|
|
47
|
-
"devops": "specialist",
|
|
48
|
-
"deployment": "specialist",
|
|
49
|
-
"devops-engineer": "specialist",
|
|
50
|
-
"code": "coder",
|
|
51
|
-
"general": "coordinator",
|
|
52
|
-
"default": "coordinator"
|
|
53
|
-
};
|
|
54
|
-
const DEFAULT_DISPATCHER_OPTIONS = {
|
|
55
|
-
defaultTimeout: 3e5,
|
|
56
|
-
maxParallelExecutions: 5,
|
|
57
|
-
enableLoadBalancing: true,
|
|
58
|
-
enableAgentCaching: true,
|
|
59
|
-
agentCacheTtl: 36e5,
|
|
60
|
-
// 1 hour
|
|
61
|
-
verbose: false,
|
|
62
|
-
agentTypeMappings: DEFAULT_AGENT_TYPE_MAPPINGS
|
|
63
|
-
};
|
|
64
|
-
class AgentDispatcher {
|
|
65
|
-
options;
|
|
66
|
-
agentRegistry = /* @__PURE__ */ new Map();
|
|
67
|
-
cloudAgents = /* @__PURE__ */ new Map();
|
|
68
|
-
activeExecutions = /* @__PURE__ */ new Map();
|
|
69
|
-
constructor(options = {}) {
|
|
70
|
-
this.options = {
|
|
71
|
-
...DEFAULT_DISPATCHER_OPTIONS,
|
|
72
|
-
...options,
|
|
73
|
-
agentTypeMappings: {
|
|
74
|
-
...DEFAULT_AGENT_TYPE_MAPPINGS,
|
|
75
|
-
...options.agentTypeMappings
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Register a cloud agent
|
|
81
|
-
*
|
|
82
|
-
* @param agentType - Agent type identifier
|
|
83
|
-
* @param agent - Cloud agent definition
|
|
84
|
-
*/
|
|
85
|
-
registerCloudAgent(agentType, agent) {
|
|
86
|
-
this.cloudAgents.set(agentType, agent);
|
|
87
|
-
if (this.options.verbose) {
|
|
88
|
-
console.log(`[AgentDispatcher] Registered cloud agent: ${agentType}`);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Unregister a cloud agent
|
|
93
|
-
*
|
|
94
|
-
* @param agentType - Agent type identifier
|
|
95
|
-
*/
|
|
96
|
-
unregisterCloudAgent(agentType) {
|
|
97
|
-
this.cloudAgents.delete(agentType);
|
|
98
|
-
if (this.options.verbose) {
|
|
99
|
-
console.log(`[AgentDispatcher] Unregistered cloud agent: ${agentType}`);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Dispatch a task to an agent based on skill configuration
|
|
104
|
-
*
|
|
105
|
-
* @param task - Task to execute
|
|
106
|
-
* @param skill - Skill file with agent configuration
|
|
107
|
-
* @param executeFn - Execution function
|
|
108
|
-
* @returns Dispatch result
|
|
109
|
-
*/
|
|
110
|
-
async dispatch(task, skill, executeFn) {
|
|
111
|
-
const startTime = Date.now();
|
|
112
|
-
try {
|
|
113
|
-
const config = this.buildDispatchConfig(skill);
|
|
114
|
-
const agent = await this.selectAgent(config);
|
|
115
|
-
if (!agent) {
|
|
116
|
-
return {
|
|
117
|
-
success: false,
|
|
118
|
-
durationMs: Date.now() - startTime,
|
|
119
|
-
error: `No suitable agent found for type: ${config.agentType}`
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
agent.status = "busy";
|
|
123
|
-
agent.currentTask = task;
|
|
124
|
-
const result = await this.executeWithAgent(agent, task, config, executeFn);
|
|
125
|
-
agent.status = "idle";
|
|
126
|
-
agent.currentTask = void 0;
|
|
127
|
-
this.updateAgentMetrics(agent, task, result.success);
|
|
128
|
-
if (this.options.enableAgentCaching) {
|
|
129
|
-
this.cacheAgent(agent);
|
|
130
|
-
}
|
|
131
|
-
return {
|
|
132
|
-
success: result.success,
|
|
133
|
-
agent,
|
|
134
|
-
output: result.results?.aggregated,
|
|
135
|
-
durationMs: Date.now() - startTime,
|
|
136
|
-
metadata: {
|
|
137
|
-
agentType: config.agentType,
|
|
138
|
-
agentRole: config.agentRole,
|
|
139
|
-
sessionId: config.sessionId
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
} catch (error) {
|
|
143
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
144
|
-
return {
|
|
145
|
-
success: false,
|
|
146
|
-
durationMs: Date.now() - startTime,
|
|
147
|
-
error: errorMessage
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Dispatch to multiple agents in parallel
|
|
153
|
-
*
|
|
154
|
-
* @param execution - Parallel execution configuration
|
|
155
|
-
* @param executeFn - Execution function
|
|
156
|
-
* @returns Parallel execution result
|
|
157
|
-
*/
|
|
158
|
-
async dispatchParallel(execution, executeFn) {
|
|
159
|
-
const startTime = Date.now();
|
|
160
|
-
const results = [];
|
|
161
|
-
let successfulCount = 0;
|
|
162
|
-
let failedCount = 0;
|
|
163
|
-
const maxParallel = execution.maxParallel ?? this.options.maxParallelExecutions;
|
|
164
|
-
for (let i = 0; i < execution.tasks.length; i += maxParallel) {
|
|
165
|
-
const batch = execution.tasks.slice(i, i + maxParallel);
|
|
166
|
-
const batchResults = await Promise.allSettled(
|
|
167
|
-
batch.map(async ({ task, config }) => {
|
|
168
|
-
const result = await this.executeDispatch(task, config, executeFn);
|
|
169
|
-
if (result.success) {
|
|
170
|
-
successfulCount++;
|
|
171
|
-
} else {
|
|
172
|
-
failedCount++;
|
|
173
|
-
if (execution.stopOnError) {
|
|
174
|
-
throw new Error(`Execution failed: ${result.error}`);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
return result;
|
|
178
|
-
})
|
|
179
|
-
);
|
|
180
|
-
for (const batchResult of batchResults) {
|
|
181
|
-
if (batchResult.status === "fulfilled") {
|
|
182
|
-
results.push(batchResult.value);
|
|
183
|
-
} else {
|
|
184
|
-
results.push({
|
|
185
|
-
success: false,
|
|
186
|
-
durationMs: Date.now() - startTime,
|
|
187
|
-
error: batchResult.reason?.message || "Unknown error"
|
|
188
|
-
});
|
|
189
|
-
failedCount++;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
const success = failedCount === 0;
|
|
194
|
-
return {
|
|
195
|
-
id: execution.id,
|
|
196
|
-
success,
|
|
197
|
-
results,
|
|
198
|
-
durationMs: Date.now() - startTime,
|
|
199
|
-
successfulCount,
|
|
200
|
-
failedCount,
|
|
201
|
-
aggregatedOutput: execution.aggregateResults ? this.aggregateOutputs(results) : void 0
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
/**
|
|
205
|
-
* Execute a single dispatch
|
|
206
|
-
*
|
|
207
|
-
* @param task - Task to execute
|
|
208
|
-
* @param config - Dispatch configuration
|
|
209
|
-
* @param executeFn - Execution function
|
|
210
|
-
* @returns Dispatch result
|
|
211
|
-
*/
|
|
212
|
-
async executeDispatch(task, config, executeFn) {
|
|
213
|
-
const startTime = Date.now();
|
|
214
|
-
try {
|
|
215
|
-
const agent = await this.selectAgent(config);
|
|
216
|
-
if (!agent) {
|
|
217
|
-
return {
|
|
218
|
-
success: false,
|
|
219
|
-
durationMs: Date.now() - startTime,
|
|
220
|
-
error: `No suitable agent found for type: ${config.agentType}`
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
agent.status = "busy";
|
|
224
|
-
agent.currentTask = task;
|
|
225
|
-
const result = await this.executeWithAgent(agent, task, config, executeFn);
|
|
226
|
-
agent.status = "idle";
|
|
227
|
-
agent.currentTask = void 0;
|
|
228
|
-
this.updateAgentMetrics(agent, task, result.success);
|
|
229
|
-
return {
|
|
230
|
-
success: result.success,
|
|
231
|
-
agent,
|
|
232
|
-
output: result.results?.aggregated,
|
|
233
|
-
durationMs: Date.now() - startTime
|
|
234
|
-
};
|
|
235
|
-
} catch (error) {
|
|
236
|
-
return {
|
|
237
|
-
success: false,
|
|
238
|
-
durationMs: Date.now() - startTime,
|
|
239
|
-
error: error instanceof Error ? error.message : String(error)
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Execute task with agent
|
|
245
|
-
*
|
|
246
|
-
* @param agent - Agent instance
|
|
247
|
-
* @param task - Task to execute
|
|
248
|
-
* @param config - Dispatch configuration
|
|
249
|
-
* @param executeFn - Execution function
|
|
250
|
-
* @returns Orchestration result
|
|
251
|
-
*/
|
|
252
|
-
async executeWithAgent(agent, task, config, executeFn) {
|
|
253
|
-
const filteredConfig = this.applyToolFiltering(config);
|
|
254
|
-
const timeout = filteredConfig.timeout ?? this.options.defaultTimeout;
|
|
255
|
-
const softTimeout = Math.floor(timeout * 0.8);
|
|
256
|
-
const warningTimeout = Math.floor(timeout * 0.6);
|
|
257
|
-
const warningTimer = setTimeout(() => {
|
|
258
|
-
if (this.options.verbose) {
|
|
259
|
-
console.log(`
|
|
260
|
-
\u{1F4AD} Agent ${agent.id} \u6B63\u5728\u6267\u884C\u4E2D\uFF0C\u8BF7\u7A0D\u5019...`);
|
|
261
|
-
}
|
|
262
|
-
}, warningTimeout);
|
|
263
|
-
const softTimer = setTimeout(() => {
|
|
264
|
-
console.log(`
|
|
265
|
-
\u26A0\uFE0F \u4EFB\u52A1\u6267\u884C\u65F6\u95F4\u8F83\u957F (\u5DF2\u8D85\u8FC7 ${Math.floor(softTimeout / 1e3)}s)\uFF0C\u53EF\u80FD\u9700\u8981\uFF1A`);
|
|
266
|
-
console.log(` 1. \u7B49\u5F85\u5B8C\u6210\uFF08\u5269\u4F59\u7EA6 ${Math.floor((timeout - softTimeout) / 1e3)}s\uFF09`);
|
|
267
|
-
console.log(" 2. \u4F7F\u7528 Ctrl+C \u4E2D\u65AD\u540E\u6267\u884C /compact \u6E05\u7406\u4E0A\u4E0B\u6587");
|
|
268
|
-
console.log(" 3. \u5C06\u4EFB\u52A1\u5206\u89E3\u4E3A\u66F4\u5C0F\u7684\u6B65\u9AA4\n");
|
|
269
|
-
}, softTimeout);
|
|
270
|
-
try {
|
|
271
|
-
const result = await Promise.race([
|
|
272
|
-
executeFn(filteredConfig),
|
|
273
|
-
new Promise(
|
|
274
|
-
(_, reject) => setTimeout(() => {
|
|
275
|
-
reject(new Error("Agent execution timeout"));
|
|
276
|
-
}, timeout)
|
|
277
|
-
)
|
|
278
|
-
]);
|
|
279
|
-
clearTimeout(warningTimer);
|
|
280
|
-
clearTimeout(softTimer);
|
|
281
|
-
return result;
|
|
282
|
-
} catch (error) {
|
|
283
|
-
clearTimeout(warningTimer);
|
|
284
|
-
clearTimeout(softTimer);
|
|
285
|
-
if (error instanceof Error && error.message === "Agent execution timeout") {
|
|
286
|
-
const friendlyError = new Error(
|
|
287
|
-
`\u4EFB\u52A1\u6267\u884C\u8D85\u65F6 (${Math.floor(timeout / 1e3)}s)\u3002\u5EFA\u8BAE\uFF1A
|
|
288
|
-
1. \u4F7F\u7528 /compact \u6E05\u7406\u4E0A\u4E0B\u6587\u540E\u91CD\u8BD5
|
|
289
|
-
2. \u5C06\u4EFB\u52A1\u5206\u89E3\u4E3A\u66F4\u5C0F\u7684\u6B65\u9AA4
|
|
290
|
-
3. \u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5\u662F\u5426\u7A33\u5B9A`
|
|
291
|
-
);
|
|
292
|
-
friendlyError.name = "TimeoutError";
|
|
293
|
-
throw friendlyError;
|
|
294
|
-
}
|
|
295
|
-
throw error;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
/**
|
|
299
|
-
* Build dispatch config from skill file
|
|
300
|
-
*
|
|
301
|
-
* @param skill - Skill file
|
|
302
|
-
* @returns Dispatch configuration
|
|
303
|
-
*/
|
|
304
|
-
buildDispatchConfig(skill) {
|
|
305
|
-
const metadata = skill.metadata;
|
|
306
|
-
const agentType = metadata.agent || "default";
|
|
307
|
-
const agentRole = this.mapAgentTypeToRole(agentType);
|
|
308
|
-
return {
|
|
309
|
-
agentType,
|
|
310
|
-
agentRole,
|
|
311
|
-
mode: metadata.context || "inherit",
|
|
312
|
-
sessionId: this.generateSessionId(),
|
|
313
|
-
disallowedTools: this.extractDisallowedTools(metadata),
|
|
314
|
-
allowedTools: metadata.allowed_tools,
|
|
315
|
-
workingDirectory: process.cwd(),
|
|
316
|
-
env: { ...process.env },
|
|
317
|
-
timeout: metadata.timeout ? metadata.timeout * 1e3 : void 0,
|
|
318
|
-
verbose: false
|
|
319
|
-
};
|
|
320
|
-
}
|
|
321
|
-
/**
|
|
322
|
-
* Map agent type string to AgentRole
|
|
323
|
-
*
|
|
324
|
-
* @param agentType - Agent type string
|
|
325
|
-
* @returns Mapped agent role
|
|
326
|
-
*/
|
|
327
|
-
mapAgentTypeToRole(agentType) {
|
|
328
|
-
if (this.options.agentTypeMappings[agentType]) {
|
|
329
|
-
return this.options.agentTypeMappings[agentType];
|
|
330
|
-
}
|
|
331
|
-
const lowerKey = agentType.toLowerCase();
|
|
332
|
-
if (this.options.agentTypeMappings[lowerKey]) {
|
|
333
|
-
return this.options.agentTypeMappings[lowerKey];
|
|
334
|
-
}
|
|
335
|
-
const validRoles = [
|
|
336
|
-
"researcher",
|
|
337
|
-
"architect",
|
|
338
|
-
"coder",
|
|
339
|
-
"debugger",
|
|
340
|
-
"tester",
|
|
341
|
-
"reviewer",
|
|
342
|
-
"writer",
|
|
343
|
-
"analyst",
|
|
344
|
-
"coordinator",
|
|
345
|
-
"specialist"
|
|
346
|
-
];
|
|
347
|
-
if (validRoles.includes(agentType)) {
|
|
348
|
-
return agentType;
|
|
349
|
-
}
|
|
350
|
-
return void 0;
|
|
351
|
-
}
|
|
352
|
-
/**
|
|
353
|
-
* Extract disallowed tools from skill metadata
|
|
354
|
-
*
|
|
355
|
-
* @param metadata - Skill metadata
|
|
356
|
-
* @returns Disallowed tools array
|
|
357
|
-
*/
|
|
358
|
-
extractDisallowedTools(metadata) {
|
|
359
|
-
if (metadata.allowed_tools) {
|
|
360
|
-
return void 0;
|
|
361
|
-
}
|
|
362
|
-
const skillData = metadata;
|
|
363
|
-
if (skillData.disallowed_tools && Array.isArray(skillData.disallowed_tools)) {
|
|
364
|
-
return skillData.disallowed_tools;
|
|
365
|
-
}
|
|
366
|
-
return void 0;
|
|
367
|
-
}
|
|
368
|
-
/**
|
|
369
|
-
* Apply tool filtering to dispatch config
|
|
370
|
-
*
|
|
371
|
-
* @param config - Original dispatch config
|
|
372
|
-
* @returns Filtered dispatch config
|
|
373
|
-
*/
|
|
374
|
-
applyToolFiltering(config) {
|
|
375
|
-
const filtered = { ...config };
|
|
376
|
-
if (config.allowedTools && config.allowedTools.length > 0) {
|
|
377
|
-
filtered.allowedTools = config.allowedTools;
|
|
378
|
-
}
|
|
379
|
-
if (config.disallowedTools && config.disallowedTools.length > 0) {
|
|
380
|
-
filtered.disallowedTools = config.disallowedTools;
|
|
381
|
-
}
|
|
382
|
-
return filtered;
|
|
383
|
-
}
|
|
384
|
-
/**
|
|
385
|
-
* Select an agent for dispatch
|
|
386
|
-
*
|
|
387
|
-
* @param config - Dispatch configuration
|
|
388
|
-
* @returns Selected agent instance or null
|
|
389
|
-
*/
|
|
390
|
-
async selectAgent(config) {
|
|
391
|
-
if (this.options.enableAgentCaching) {
|
|
392
|
-
const cached = this.getCachedAgent(config);
|
|
393
|
-
if (cached) {
|
|
394
|
-
return cached;
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
const cloudAgent = this.cloudAgents.get(config.agentType);
|
|
398
|
-
if (cloudAgent) {
|
|
399
|
-
return this.createAgentInstance(cloudAgent, config);
|
|
400
|
-
}
|
|
401
|
-
return this.createGenericAgent(config);
|
|
402
|
-
}
|
|
403
|
-
/**
|
|
404
|
-
* Create agent instance from cloud agent
|
|
405
|
-
*
|
|
406
|
-
* @param cloudAgent - Cloud agent definition
|
|
407
|
-
* @param config - Dispatch configuration
|
|
408
|
-
* @returns Agent instance
|
|
409
|
-
*/
|
|
410
|
-
createAgentInstance(cloudAgent, config) {
|
|
411
|
-
const now = /* @__PURE__ */ new Date();
|
|
412
|
-
const capabilities = cloudAgent.definition.capabilities.map((cap, index) => ({
|
|
413
|
-
id: `${cloudAgent.id}-cap-${index}`,
|
|
414
|
-
name: cap,
|
|
415
|
-
model: "inherit",
|
|
416
|
-
specialties: [cap],
|
|
417
|
-
strength: 1,
|
|
418
|
-
costFactor: 1
|
|
419
|
-
}));
|
|
420
|
-
return {
|
|
421
|
-
id: nanoid(),
|
|
422
|
-
role: this.mapAgentTypeToRole(config.agentType) || "coordinator",
|
|
423
|
-
agent: cloudAgent,
|
|
424
|
-
status: "idle",
|
|
425
|
-
taskHistory: [],
|
|
426
|
-
capabilities,
|
|
427
|
-
metrics: this.createEmptyMetrics(),
|
|
428
|
-
createdAt: now.toISOString(),
|
|
429
|
-
config: {
|
|
430
|
-
maxConcurrentTasks: 1,
|
|
431
|
-
taskTimeout: config.timeout || this.options.defaultTimeout,
|
|
432
|
-
verboseLogging: config.verbose || false
|
|
433
|
-
}
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
/**
|
|
437
|
-
* Create a generic agent instance
|
|
438
|
-
*
|
|
439
|
-
* @param config - Dispatch configuration
|
|
440
|
-
* @returns Agent instance
|
|
441
|
-
*/
|
|
442
|
-
createGenericAgent(config) {
|
|
443
|
-
const now = /* @__PURE__ */ new Date();
|
|
444
|
-
return {
|
|
445
|
-
id: nanoid(),
|
|
446
|
-
role: config.agentRole || "coordinator",
|
|
447
|
-
agent: {
|
|
448
|
-
id: config.agentType,
|
|
449
|
-
name: config.agentType,
|
|
450
|
-
version: "1.0.0",
|
|
451
|
-
definition: {
|
|
452
|
-
role: config.agentType,
|
|
453
|
-
systemPrompt: `You are a ${config.agentType} agent.`,
|
|
454
|
-
capabilities: [],
|
|
455
|
-
tools: [],
|
|
456
|
-
constraints: []
|
|
457
|
-
},
|
|
458
|
-
metadata: {
|
|
459
|
-
author: "CCJK",
|
|
460
|
-
description: { "en": config.agentType, "zh-CN": config.agentType },
|
|
461
|
-
category: "general",
|
|
462
|
-
createdAt: now.toISOString(),
|
|
463
|
-
updatedAt: now.toISOString(),
|
|
464
|
-
usageCount: 0,
|
|
465
|
-
rating: 0,
|
|
466
|
-
ratingCount: 0
|
|
467
|
-
},
|
|
468
|
-
privacy: "private"
|
|
469
|
-
},
|
|
470
|
-
status: "idle",
|
|
471
|
-
taskHistory: [],
|
|
472
|
-
capabilities: [],
|
|
473
|
-
metrics: this.createEmptyMetrics(),
|
|
474
|
-
createdAt: now.toISOString(),
|
|
475
|
-
config: {
|
|
476
|
-
maxConcurrentTasks: 1,
|
|
477
|
-
taskTimeout: config.timeout || this.options.defaultTimeout,
|
|
478
|
-
verboseLogging: config.verbose || false
|
|
479
|
-
}
|
|
480
|
-
};
|
|
481
|
-
}
|
|
482
|
-
/**
|
|
483
|
-
* Create empty metrics object
|
|
484
|
-
*
|
|
485
|
-
* @returns Empty metrics
|
|
486
|
-
*/
|
|
487
|
-
createEmptyMetrics() {
|
|
488
|
-
return {
|
|
489
|
-
tasksExecuted: 0,
|
|
490
|
-
tasksSucceeded: 0,
|
|
491
|
-
tasksFailed: 0,
|
|
492
|
-
avgTaskDuration: 0,
|
|
493
|
-
successRate: 0,
|
|
494
|
-
totalExecutionTime: 0,
|
|
495
|
-
avgConfidence: 0,
|
|
496
|
-
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
497
|
-
};
|
|
498
|
-
}
|
|
499
|
-
/**
|
|
500
|
-
* Update agent metrics after execution
|
|
501
|
-
*
|
|
502
|
-
* @param agent - Agent instance
|
|
503
|
-
* @param task - Executed task
|
|
504
|
-
* @param success - Whether execution succeeded
|
|
505
|
-
*/
|
|
506
|
-
updateAgentMetrics(agent, task, success) {
|
|
507
|
-
const metrics = agent.metrics;
|
|
508
|
-
metrics.tasksExecuted++;
|
|
509
|
-
if (success) {
|
|
510
|
-
metrics.tasksSucceeded++;
|
|
511
|
-
} else {
|
|
512
|
-
metrics.tasksFailed++;
|
|
513
|
-
}
|
|
514
|
-
metrics.successRate = metrics.tasksSucceeded / metrics.tasksExecuted;
|
|
515
|
-
if (task.actualDuration) {
|
|
516
|
-
metrics.totalExecutionTime += task.actualDuration;
|
|
517
|
-
metrics.avgTaskDuration = metrics.totalExecutionTime / metrics.tasksExecuted;
|
|
518
|
-
}
|
|
519
|
-
metrics.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
520
|
-
agent.taskHistory.push({
|
|
521
|
-
taskId: task.id,
|
|
522
|
-
taskName: task.name,
|
|
523
|
-
status: task.status,
|
|
524
|
-
startedAt: task.startedAt || (/* @__PURE__ */ new Date()).toISOString(),
|
|
525
|
-
completedAt: task.completedAt,
|
|
526
|
-
duration: task.actualDuration,
|
|
527
|
-
success
|
|
528
|
-
});
|
|
529
|
-
}
|
|
530
|
-
/**
|
|
531
|
-
* Cache an agent instance
|
|
532
|
-
*
|
|
533
|
-
* @param agent - Agent instance to cache
|
|
534
|
-
*/
|
|
535
|
-
cacheAgent(agent) {
|
|
536
|
-
const key = `${agent.role}-${agent.id}`;
|
|
537
|
-
this.agentRegistry.set(key, {
|
|
538
|
-
agent,
|
|
539
|
-
lastUsed: /* @__PURE__ */ new Date(),
|
|
540
|
-
usageCount: 1,
|
|
541
|
-
expiresAt: new Date(Date.now() + this.options.agentCacheTtl)
|
|
542
|
-
});
|
|
543
|
-
}
|
|
544
|
-
/**
|
|
545
|
-
* Get cached agent
|
|
546
|
-
*
|
|
547
|
-
* @param config - Dispatch configuration
|
|
548
|
-
* @returns Cached agent or null
|
|
549
|
-
*/
|
|
550
|
-
getCachedAgent(config) {
|
|
551
|
-
const role = config.agentRole || "system";
|
|
552
|
-
const registryEntries = Array.from(this.agentRegistry.entries());
|
|
553
|
-
for (const [key, entry] of registryEntries) {
|
|
554
|
-
if (entry.agent.role === role && entry.agent.status === "idle") {
|
|
555
|
-
if (entry.expiresAt && entry.expiresAt < /* @__PURE__ */ new Date()) {
|
|
556
|
-
this.agentRegistry.delete(key);
|
|
557
|
-
continue;
|
|
558
|
-
}
|
|
559
|
-
entry.lastUsed = /* @__PURE__ */ new Date();
|
|
560
|
-
entry.usageCount++;
|
|
561
|
-
if (this.options.verbose) {
|
|
562
|
-
console.log(`[AgentDispatcher] Using cached agent: ${key}`);
|
|
563
|
-
}
|
|
564
|
-
return entry.agent;
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
return null;
|
|
568
|
-
}
|
|
569
|
-
/**
|
|
570
|
-
* Aggregate outputs from multiple dispatch results
|
|
571
|
-
*
|
|
572
|
-
* @param results - Dispatch results
|
|
573
|
-
* @returns Aggregated output
|
|
574
|
-
*/
|
|
575
|
-
aggregateOutputs(results) {
|
|
576
|
-
const successfulResults = results.filter((r) => r.success && r.output);
|
|
577
|
-
return {
|
|
578
|
-
data: {
|
|
579
|
-
results: successfulResults.map((r) => r.output?.data),
|
|
580
|
-
count: successfulResults.length,
|
|
581
|
-
total: results.length
|
|
582
|
-
},
|
|
583
|
-
files: successfulResults.flatMap((r) => r.output?.files || []),
|
|
584
|
-
logs: successfulResults.flatMap((r) => r.output?.logs || []),
|
|
585
|
-
confidence: successfulResults.length / results.length,
|
|
586
|
-
metadata: {
|
|
587
|
-
aggregatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
588
|
-
sourceResults: results.length
|
|
589
|
-
}
|
|
590
|
-
};
|
|
591
|
-
}
|
|
592
|
-
/**
|
|
593
|
-
* Generate a unique session ID
|
|
594
|
-
*
|
|
595
|
-
* @returns Session ID
|
|
596
|
-
*/
|
|
597
|
-
generateSessionId() {
|
|
598
|
-
return `ccjk-dispatch-${Date.now()}-${nanoid(8)}`;
|
|
599
|
-
}
|
|
600
|
-
/**
|
|
601
|
-
* Filter available agents by criteria
|
|
602
|
-
*
|
|
603
|
-
* @param criteria - Filter criteria
|
|
604
|
-
* @returns Filtered agents
|
|
605
|
-
*/
|
|
606
|
-
filterAgents(criteria) {
|
|
607
|
-
const agents = [];
|
|
608
|
-
const cloudAgentsEntries = Array.from(this.cloudAgents.entries());
|
|
609
|
-
for (const [type, cloudAgent] of cloudAgentsEntries) {
|
|
610
|
-
if (this.matchesCriteria(cloudAgent, criteria)) {
|
|
611
|
-
agents.push(this.createAgentInstance(cloudAgent, {
|
|
612
|
-
agentType: type,
|
|
613
|
-
agentRole: this.mapAgentTypeToRole(type),
|
|
614
|
-
mode: "inherit",
|
|
615
|
-
workingDirectory: process.cwd(),
|
|
616
|
-
env: {}
|
|
617
|
-
}));
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
const registryEntries = Array.from(this.agentRegistry.values());
|
|
621
|
-
for (const entry of registryEntries) {
|
|
622
|
-
if (this.matchesInstanceCriteria(entry.agent, criteria)) {
|
|
623
|
-
agents.push(entry.agent);
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
return agents;
|
|
627
|
-
}
|
|
628
|
-
/**
|
|
629
|
-
* Check if cloud agent matches criteria
|
|
630
|
-
*
|
|
631
|
-
* @param agent - Cloud agent
|
|
632
|
-
* @param criteria - Filter criteria
|
|
633
|
-
* @returns Whether agent matches
|
|
634
|
-
*/
|
|
635
|
-
matchesCriteria(agent, criteria) {
|
|
636
|
-
if (criteria.capabilities && criteria.capabilities.length > 0) {
|
|
637
|
-
const hasAllCapabilities = criteria.capabilities.every((cap) => {
|
|
638
|
-
const capName = typeof cap === "string" ? cap : cap.name;
|
|
639
|
-
return agent.definition.capabilities.includes(capName);
|
|
640
|
-
});
|
|
641
|
-
if (!hasAllCapabilities) {
|
|
642
|
-
return false;
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
if (criteria.agentType) {
|
|
646
|
-
const pattern = new RegExp(criteria.agentType.replace(/\*/g, ".*"));
|
|
647
|
-
if (!pattern.test(agent.id)) {
|
|
648
|
-
return false;
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
if (criteria.hasTool) {
|
|
652
|
-
const hasTool = agent.definition.tools.includes(criteria.hasTool);
|
|
653
|
-
if (!hasTool) {
|
|
654
|
-
return false;
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
return true;
|
|
658
|
-
}
|
|
659
|
-
/**
|
|
660
|
-
* Check if agent instance matches criteria
|
|
661
|
-
*
|
|
662
|
-
* @param agent - Agent instance
|
|
663
|
-
* @param criteria - Filter criteria
|
|
664
|
-
* @returns Whether agent matches
|
|
665
|
-
*/
|
|
666
|
-
matchesInstanceCriteria(agent, criteria) {
|
|
667
|
-
if (criteria.agentRole && agent.role !== criteria.agentRole) {
|
|
668
|
-
return false;
|
|
669
|
-
}
|
|
670
|
-
if (criteria.minSuccessRate !== void 0) {
|
|
671
|
-
if (agent.metrics.successRate < criteria.minSuccessRate) {
|
|
672
|
-
return false;
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
if (criteria.maxCurrentLoad !== void 0) {
|
|
676
|
-
const load = agent.status === "busy" ? 1 : 0;
|
|
677
|
-
if (load > criteria.maxCurrentLoad) {
|
|
678
|
-
return false;
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
return true;
|
|
682
|
-
}
|
|
683
|
-
/**
|
|
684
|
-
* Clear expired cached agents
|
|
685
|
-
*
|
|
686
|
-
* @returns Number of agents cleared
|
|
687
|
-
*/
|
|
688
|
-
clearExpiredCache() {
|
|
689
|
-
const now = /* @__PURE__ */ new Date();
|
|
690
|
-
let cleared = 0;
|
|
691
|
-
const registryEntries = Array.from(this.agentRegistry.entries());
|
|
692
|
-
for (const [key, entry] of registryEntries) {
|
|
693
|
-
if (entry.expiresAt && entry.expiresAt < now) {
|
|
694
|
-
this.agentRegistry.delete(key);
|
|
695
|
-
cleared++;
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
if (this.options.verbose && cleared > 0) {
|
|
699
|
-
console.log(`[AgentDispatcher] Cleared ${cleared} expired cached agents`);
|
|
700
|
-
}
|
|
701
|
-
return cleared;
|
|
702
|
-
}
|
|
703
|
-
/**
|
|
704
|
-
* Get dispatcher statistics
|
|
705
|
-
*
|
|
706
|
-
* @returns Statistics
|
|
707
|
-
*/
|
|
708
|
-
getStats() {
|
|
709
|
-
return {
|
|
710
|
-
registeredCloudAgents: this.cloudAgents.size,
|
|
711
|
-
cachedAgents: this.agentRegistry.size,
|
|
712
|
-
activeExecutions: this.activeExecutions.size,
|
|
713
|
-
totalExecutions: 0
|
|
714
|
-
// Would need tracking
|
|
715
|
-
};
|
|
716
|
-
}
|
|
717
|
-
/**
|
|
718
|
-
* Clean up resources
|
|
719
|
-
*/
|
|
720
|
-
cleanup() {
|
|
721
|
-
this.agentRegistry.clear();
|
|
722
|
-
this.cloudAgents.clear();
|
|
723
|
-
this.activeExecutions.clear();
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
const DEFAULT_FORK_OPTIONS = {
|
|
728
|
-
defaultTimeout: 3e5,
|
|
729
|
-
// 5 minutes
|
|
730
|
-
maxConcurrentForks: 10,
|
|
731
|
-
enableTranscriptSaving: true,
|
|
732
|
-
transcriptDir: process.env.HOME ? resolve(process.env.HOME, ".claude", "fork-transcripts") : resolve(".claude", "fork-transcripts"),
|
|
733
|
-
enableHooks: true,
|
|
734
|
-
defaultHookTimeout: 30,
|
|
735
|
-
verbose: false
|
|
736
|
-
};
|
|
737
|
-
const SESSION_ID_ENV_VAR = "CLAUDE_SESSION_ID";
|
|
738
|
-
function generateSessionId() {
|
|
739
|
-
return `ccjk-fork-${Date.now()}-${nanoid(8)}`;
|
|
740
|
-
}
|
|
741
|
-
function parseSkillForkConfig(skill) {
|
|
742
|
-
const config = {
|
|
743
|
-
skill
|
|
744
|
-
};
|
|
745
|
-
const metadata = skill.metadata;
|
|
746
|
-
if (metadata.context) {
|
|
747
|
-
config.mode = metadata.context;
|
|
748
|
-
}
|
|
749
|
-
if (metadata.agent) {
|
|
750
|
-
config.agentType = metadata.agent;
|
|
751
|
-
}
|
|
752
|
-
if (metadata.allowed_tools) {
|
|
753
|
-
config.allowedTools = metadata.allowed_tools;
|
|
754
|
-
}
|
|
755
|
-
if (metadata.hooks) {
|
|
756
|
-
config.hooks = metadata.hooks.map((h) => ({
|
|
757
|
-
type: h.type,
|
|
758
|
-
matcher: h.matcher,
|
|
759
|
-
command: h.command,
|
|
760
|
-
script: h.script,
|
|
761
|
-
timeout: h.timeout,
|
|
762
|
-
enabled: true
|
|
763
|
-
}));
|
|
764
|
-
}
|
|
765
|
-
if (metadata.timeout) {
|
|
766
|
-
config.timeout = metadata.timeout * 1e3;
|
|
767
|
-
}
|
|
768
|
-
return config;
|
|
769
|
-
}
|
|
770
|
-
class AgentForkManager {
|
|
771
|
-
options;
|
|
772
|
-
forks = /* @__PURE__ */ new Map();
|
|
773
|
-
listeners = /* @__PURE__ */ new Map();
|
|
774
|
-
activeForksCount = 0;
|
|
775
|
-
constructor(options = {}) {
|
|
776
|
-
this.options = { ...DEFAULT_FORK_OPTIONS, ...options };
|
|
777
|
-
}
|
|
778
|
-
/**
|
|
779
|
-
* Create a new fork context from a skill
|
|
780
|
-
*
|
|
781
|
-
* @param skill - Parsed SKILL.md file
|
|
782
|
-
* @param overrides - Optional configuration overrides
|
|
783
|
-
* @returns Fork context state
|
|
784
|
-
*/
|
|
785
|
-
createFork(skill, overrides = {}) {
|
|
786
|
-
const skillConfig = parseSkillForkConfig(skill);
|
|
787
|
-
const config = {
|
|
788
|
-
id: overrides.id || nanoid(),
|
|
789
|
-
sessionId: overrides.sessionId || generateSessionId(),
|
|
790
|
-
workingDirectory: overrides.workingDirectory || skillConfig.workingDirectory || process.cwd(),
|
|
791
|
-
env: overrides.env || skillConfig.env || { ...process.env },
|
|
792
|
-
mode: overrides.mode || skillConfig.mode || "fork",
|
|
793
|
-
// Optional fields
|
|
794
|
-
...overrides.parentId && { parentId: overrides.parentId },
|
|
795
|
-
...skillConfig.agentType && { agentType: skillConfig.agentType },
|
|
796
|
-
...skillConfig.agentRole && { agentRole: skillConfig.agentRole },
|
|
797
|
-
...skillConfig.disallowedTools && { disallowedTools: skillConfig.disallowedTools },
|
|
798
|
-
...skillConfig.allowedTools && { allowedTools: skillConfig.allowedTools },
|
|
799
|
-
...skillConfig.timeout && { timeout: skillConfig.timeout },
|
|
800
|
-
...skillConfig.hooks && { hooks: skillConfig.hooks },
|
|
801
|
-
...overrides.verbose !== void 0 && { verbose: overrides.verbose },
|
|
802
|
-
...skillConfig.metadata && { metadata: skillConfig.metadata },
|
|
803
|
-
...overrides.metadata && { metadata: overrides.metadata }
|
|
804
|
-
};
|
|
805
|
-
config.env[SESSION_ID_ENV_VAR] = config.sessionId;
|
|
806
|
-
this.checkConcurrentLimit();
|
|
807
|
-
const fork = {
|
|
808
|
-
id: config.id,
|
|
809
|
-
status: "pending",
|
|
810
|
-
transcript: [],
|
|
811
|
-
startedAt: /* @__PURE__ */ new Date(),
|
|
812
|
-
children: []
|
|
813
|
-
};
|
|
814
|
-
this.forks.set(config.id, fork);
|
|
815
|
-
if (this.options.verbose) {
|
|
816
|
-
console.log(`[AgentForkManager] Created fork: ${config.id} (session: ${config.sessionId})`);
|
|
817
|
-
}
|
|
818
|
-
this.emit("created", fork);
|
|
819
|
-
return fork;
|
|
820
|
-
}
|
|
821
|
-
/**
|
|
822
|
-
* Execute a fork context
|
|
823
|
-
*
|
|
824
|
-
* @param forkId - Fork context ID
|
|
825
|
-
* @param task - Task to execute
|
|
826
|
-
* @param executeFn - Execution function
|
|
827
|
-
* @returns Execution result
|
|
828
|
-
*/
|
|
829
|
-
async executeFork(forkId, task, executeFn) {
|
|
830
|
-
const fork = this.getForkOrThrow(forkId);
|
|
831
|
-
this.changeStatus(forkId, "running");
|
|
832
|
-
fork.task = task;
|
|
833
|
-
this.addTranscript(forkId, {
|
|
834
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
835
|
-
type: "system",
|
|
836
|
-
content: `Starting fork execution: ${task.name}`,
|
|
837
|
-
metadata: { taskId: task.id }
|
|
838
|
-
});
|
|
839
|
-
const startTime = Date.now();
|
|
840
|
-
const config = this.buildForkConfig(forkId);
|
|
841
|
-
try {
|
|
842
|
-
const timeout = config.timeout ?? this.options.defaultTimeout;
|
|
843
|
-
const result = await this.executeWithTimeout(
|
|
844
|
-
() => this.executeWithHooks(forkId, task, executeFn),
|
|
845
|
-
timeout
|
|
846
|
-
);
|
|
847
|
-
fork.endedAt = /* @__PURE__ */ new Date();
|
|
848
|
-
fork.result = {
|
|
849
|
-
success: true,
|
|
850
|
-
durationMs: Date.now() - startTime,
|
|
851
|
-
transcript: fork.transcript,
|
|
852
|
-
output: result.results
|
|
853
|
-
};
|
|
854
|
-
this.changeStatus(forkId, "completed");
|
|
855
|
-
this.emit("completed", fork, fork.result);
|
|
856
|
-
if (this.options.enableTranscriptSaving) {
|
|
857
|
-
this.saveTranscript(forkId);
|
|
858
|
-
}
|
|
859
|
-
return fork.result;
|
|
860
|
-
} catch (error) {
|
|
861
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
862
|
-
fork.endedAt = /* @__PURE__ */ new Date();
|
|
863
|
-
fork.error = errorMessage;
|
|
864
|
-
fork.result = {
|
|
865
|
-
success: false,
|
|
866
|
-
durationMs: Date.now() - startTime,
|
|
867
|
-
transcript: fork.transcript,
|
|
868
|
-
error: errorMessage
|
|
869
|
-
};
|
|
870
|
-
this.changeStatus(forkId, "failed");
|
|
871
|
-
this.emit("failed", fork, errorMessage);
|
|
872
|
-
if (this.options.enableTranscriptSaving) {
|
|
873
|
-
this.saveTranscript(forkId);
|
|
874
|
-
}
|
|
875
|
-
return fork.result;
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
/**
|
|
879
|
-
* Execute fork with hooks
|
|
880
|
-
*
|
|
881
|
-
* @param forkId - Fork context ID
|
|
882
|
-
* @param task - Task to execute
|
|
883
|
-
* @param executeFn - Execution function
|
|
884
|
-
* @returns Execution result
|
|
885
|
-
*/
|
|
886
|
-
async executeWithHooks(forkId, task, executeFn) {
|
|
887
|
-
const config = this.buildForkConfig(forkId);
|
|
888
|
-
if (this.options.enableHooks && config.hooks) {
|
|
889
|
-
for (const hook of config.hooks) {
|
|
890
|
-
if (hook.type === "PreToolUse" && this.shouldExecuteHook(hook, "start")) {
|
|
891
|
-
await this.executeHook(forkId, hook, "start");
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
const result = await executeFn(config);
|
|
896
|
-
if (this.options.enableHooks && config.hooks) {
|
|
897
|
-
for (const hook of config.hooks) {
|
|
898
|
-
if (hook.type === "PostToolUse" && this.shouldExecuteHook(hook, "complete")) {
|
|
899
|
-
await this.executeHook(forkId, hook, "complete");
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
return result;
|
|
904
|
-
}
|
|
905
|
-
/**
|
|
906
|
-
* Execute a single hook
|
|
907
|
-
*
|
|
908
|
-
* @param forkId - Fork context ID
|
|
909
|
-
* @param hook - Hook to execute
|
|
910
|
-
* @param trigger - Trigger event
|
|
911
|
-
*/
|
|
912
|
-
async executeHook(forkId, hook, trigger) {
|
|
913
|
-
if (hook.enabled === false) {
|
|
914
|
-
return;
|
|
915
|
-
}
|
|
916
|
-
this.getForkOrThrow(forkId);
|
|
917
|
-
const timeout = (hook.timeout ?? this.options.defaultHookTimeout) * 1e3;
|
|
918
|
-
this.addTranscript(forkId, {
|
|
919
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
920
|
-
type: "hook",
|
|
921
|
-
content: `Executing ${hook.type} hook`,
|
|
922
|
-
hookType: hook.type,
|
|
923
|
-
metadata: { trigger, matcher: hook.matcher }
|
|
924
|
-
});
|
|
925
|
-
try {
|
|
926
|
-
await this.executeWithTimeout(async () => {
|
|
927
|
-
if (hook.command) {
|
|
928
|
-
const { exec } = await import('./main.mjs');
|
|
929
|
-
const execOptions = { env: this.buildForkConfig(forkId).env };
|
|
930
|
-
await exec("sh", ["-c", hook.command], execOptions);
|
|
931
|
-
} else if (hook.script) {
|
|
932
|
-
const { exec } = await import('./main.mjs');
|
|
933
|
-
const execOptions = { env: this.buildForkConfig(forkId).env };
|
|
934
|
-
await exec("node", ["-e", hook.script], execOptions);
|
|
935
|
-
}
|
|
936
|
-
}, timeout);
|
|
937
|
-
} catch (error) {
|
|
938
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
939
|
-
this.addTranscript(forkId, {
|
|
940
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
941
|
-
type: "error",
|
|
942
|
-
content: `Hook execution failed: ${message}`,
|
|
943
|
-
hookType: hook.type
|
|
944
|
-
});
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
/**
|
|
948
|
-
* Check if a hook should be executed
|
|
949
|
-
*
|
|
950
|
-
* @param hook - Hook definition
|
|
951
|
-
* @param trigger - Trigger event
|
|
952
|
-
* @returns Whether to execute
|
|
953
|
-
*/
|
|
954
|
-
shouldExecuteHook(hook, trigger) {
|
|
955
|
-
if (!hook.matcher) {
|
|
956
|
-
return true;
|
|
957
|
-
}
|
|
958
|
-
const pattern = hook.matcher.replace(/\*/g, ".*");
|
|
959
|
-
const regex = new RegExp(pattern);
|
|
960
|
-
return regex.test(trigger);
|
|
961
|
-
}
|
|
962
|
-
/**
|
|
963
|
-
* Execute with timeout
|
|
964
|
-
*
|
|
965
|
-
* @param fn - Function to execute
|
|
966
|
-
* @param timeout - Timeout in milliseconds
|
|
967
|
-
* @returns Function result
|
|
968
|
-
*/
|
|
969
|
-
async executeWithTimeout(fn, timeout) {
|
|
970
|
-
return Promise.race([
|
|
971
|
-
fn(),
|
|
972
|
-
new Promise(
|
|
973
|
-
(_, reject) => setTimeout(() => reject(new Error(`Execution timed out after ${timeout}ms`)), timeout)
|
|
974
|
-
)
|
|
975
|
-
]);
|
|
976
|
-
}
|
|
977
|
-
/**
|
|
978
|
-
* Build fork configuration from state
|
|
979
|
-
*
|
|
980
|
-
* @param forkId - Fork context ID
|
|
981
|
-
* @returns Fork configuration
|
|
982
|
-
*/
|
|
983
|
-
buildForkConfig(forkId) {
|
|
984
|
-
this.getForkOrThrow(forkId);
|
|
985
|
-
const skill = this.findSkillForFork(forkId);
|
|
986
|
-
return {
|
|
987
|
-
id: forkId,
|
|
988
|
-
sessionId: this.getSessionIdForFork(forkId),
|
|
989
|
-
skill,
|
|
990
|
-
workingDirectory: process.cwd(),
|
|
991
|
-
env: { ...process.env, [SESSION_ID_ENV_VAR]: this.getSessionIdForFork(forkId) },
|
|
992
|
-
mode: "fork"
|
|
993
|
-
};
|
|
994
|
-
}
|
|
995
|
-
/**
|
|
996
|
-
* Find the skill for a fork (placeholder implementation)
|
|
997
|
-
*
|
|
998
|
-
* @param forkId - Fork context ID
|
|
999
|
-
* @returns Skill file
|
|
1000
|
-
*/
|
|
1001
|
-
findSkillForFork(_forkId) {
|
|
1002
|
-
return {
|
|
1003
|
-
metadata: {
|
|
1004
|
-
name: "unknown",
|
|
1005
|
-
description: "Unknown skill",
|
|
1006
|
-
version: "1.0.0",
|
|
1007
|
-
category: "custom",
|
|
1008
|
-
triggers: [],
|
|
1009
|
-
use_when: []
|
|
1010
|
-
},
|
|
1011
|
-
content: "",
|
|
1012
|
-
filePath: ""
|
|
1013
|
-
};
|
|
1014
|
-
}
|
|
1015
|
-
/**
|
|
1016
|
-
* Get the session ID for a fork
|
|
1017
|
-
*
|
|
1018
|
-
* @param forkId - Fork context ID
|
|
1019
|
-
* @returns Session ID
|
|
1020
|
-
*/
|
|
1021
|
-
getSessionIdForFork(_forkId) {
|
|
1022
|
-
return generateSessionId();
|
|
1023
|
-
}
|
|
1024
|
-
/**
|
|
1025
|
-
* Add a transcript entry to a fork
|
|
1026
|
-
*
|
|
1027
|
-
* @param forkId - Fork context ID
|
|
1028
|
-
* @param entry - Transcript entry
|
|
1029
|
-
*/
|
|
1030
|
-
addTranscript(forkId, entry) {
|
|
1031
|
-
const fork = this.getForkOrThrow(forkId);
|
|
1032
|
-
const fullEntry = {
|
|
1033
|
-
...entry,
|
|
1034
|
-
timestamp: entry.timestamp || /* @__PURE__ */ new Date()
|
|
1035
|
-
};
|
|
1036
|
-
fork.transcript.push(fullEntry);
|
|
1037
|
-
if (this.options.verbose) {
|
|
1038
|
-
console.log(`[AgentForkManager] Transcript [${forkId}] ${fullEntry.type}: ${fullEntry.content.substring(0, 100)}`);
|
|
1039
|
-
}
|
|
1040
|
-
this.emit("transcript", fork, fullEntry);
|
|
1041
|
-
}
|
|
1042
|
-
/**
|
|
1043
|
-
* Save fork transcript to file
|
|
1044
|
-
*
|
|
1045
|
-
* @param forkId - Fork context ID
|
|
1046
|
-
* @returns Saved file path
|
|
1047
|
-
*/
|
|
1048
|
-
saveTranscript(forkId) {
|
|
1049
|
-
const fork = this.getForkOrThrow(forkId);
|
|
1050
|
-
const fs = require("node:fs/promises");
|
|
1051
|
-
const { join } = require("pathe");
|
|
1052
|
-
const filename = `fork-${fork.id}-${Date.now()}.json`;
|
|
1053
|
-
const filePath = join(this.options.transcriptDir, filename);
|
|
1054
|
-
fs.mkdir(this.options.transcriptDir, { recursive: true }).then(() => fs.writeFile(filePath, JSON.stringify({
|
|
1055
|
-
forkId: fork.id,
|
|
1056
|
-
status: fork.status,
|
|
1057
|
-
transcript: fork.transcript,
|
|
1058
|
-
startedAt: fork.startedAt,
|
|
1059
|
-
endedAt: fork.endedAt,
|
|
1060
|
-
result: fork.result
|
|
1061
|
-
}, null, 2))).catch(console.error);
|
|
1062
|
-
return filePath;
|
|
1063
|
-
}
|
|
1064
|
-
/**
|
|
1065
|
-
* Get a fork context by ID
|
|
1066
|
-
*
|
|
1067
|
-
* @param forkId - Fork context ID
|
|
1068
|
-
* @returns Fork state or null
|
|
1069
|
-
*/
|
|
1070
|
-
getFork(forkId) {
|
|
1071
|
-
return this.forks.get(forkId) || null;
|
|
1072
|
-
}
|
|
1073
|
-
/**
|
|
1074
|
-
* Cancel a running fork
|
|
1075
|
-
*
|
|
1076
|
-
* @param forkId - Fork context ID
|
|
1077
|
-
*/
|
|
1078
|
-
cancel(forkId) {
|
|
1079
|
-
const fork = this.getForkOrThrow(forkId);
|
|
1080
|
-
if (fork.status === "completed" || fork.status === "failed") {
|
|
1081
|
-
throw new Error(`Cannot cancel fork ${forkId} with status: ${fork.status}`);
|
|
1082
|
-
}
|
|
1083
|
-
fork.endedAt = /* @__PURE__ */ new Date();
|
|
1084
|
-
this.changeStatus(forkId, "cancelled");
|
|
1085
|
-
if (this.options.verbose) {
|
|
1086
|
-
console.log(`[AgentForkManager] Cancelled fork: ${forkId}`);
|
|
1087
|
-
}
|
|
1088
|
-
this.emit("cancelled", fork);
|
|
1089
|
-
}
|
|
1090
|
-
/**
|
|
1091
|
-
* Remove a fork context
|
|
1092
|
-
*
|
|
1093
|
-
* @param forkId - Fork context ID
|
|
1094
|
-
* @returns True if removed
|
|
1095
|
-
*/
|
|
1096
|
-
remove(forkId) {
|
|
1097
|
-
const fork = this.forks.get(forkId);
|
|
1098
|
-
if (!fork) {
|
|
1099
|
-
return false;
|
|
1100
|
-
}
|
|
1101
|
-
this.forks.delete(forkId);
|
|
1102
|
-
this.activeForksCount--;
|
|
1103
|
-
if (this.options.verbose) {
|
|
1104
|
-
console.log(`[AgentForkManager] Removed fork: ${forkId}`);
|
|
1105
|
-
}
|
|
1106
|
-
return true;
|
|
1107
|
-
}
|
|
1108
|
-
/**
|
|
1109
|
-
* Clear finished forks
|
|
1110
|
-
*
|
|
1111
|
-
* @returns Number cleared
|
|
1112
|
-
*/
|
|
1113
|
-
clearFinished() {
|
|
1114
|
-
const toRemove = Array.from(this.forks.values()).filter(
|
|
1115
|
-
(f) => ["completed", "failed", "cancelled", "timeout"].includes(f.status)
|
|
1116
|
-
);
|
|
1117
|
-
toRemove.forEach((f) => this.remove(f.id));
|
|
1118
|
-
if (this.options.verbose) {
|
|
1119
|
-
console.log(`[AgentForkManager] Cleared ${toRemove.length} finished forks`);
|
|
1120
|
-
}
|
|
1121
|
-
return toRemove.length;
|
|
1122
|
-
}
|
|
1123
|
-
/**
|
|
1124
|
-
* Get all forks
|
|
1125
|
-
*
|
|
1126
|
-
* @returns Array of fork states
|
|
1127
|
-
*/
|
|
1128
|
-
listAll() {
|
|
1129
|
-
return Array.from(this.forks.values());
|
|
1130
|
-
}
|
|
1131
|
-
/**
|
|
1132
|
-
* Get active forks
|
|
1133
|
-
*
|
|
1134
|
-
* @returns Array of active fork states
|
|
1135
|
-
*/
|
|
1136
|
-
listActive() {
|
|
1137
|
-
return Array.from(this.forks.values()).filter(
|
|
1138
|
-
(f) => f.status === "running" || f.status === "pending"
|
|
1139
|
-
);
|
|
1140
|
-
}
|
|
1141
|
-
/**
|
|
1142
|
-
* Get fork statistics
|
|
1143
|
-
*
|
|
1144
|
-
* @returns Statistics
|
|
1145
|
-
*/
|
|
1146
|
-
getStats() {
|
|
1147
|
-
const forks = Array.from(this.forks.values());
|
|
1148
|
-
return {
|
|
1149
|
-
total: forks.length,
|
|
1150
|
-
pending: forks.filter((f) => f.status === "pending").length,
|
|
1151
|
-
running: forks.filter((f) => f.status === "running").length,
|
|
1152
|
-
completed: forks.filter((f) => f.status === "completed").length,
|
|
1153
|
-
failed: forks.filter((f) => f.status === "failed").length,
|
|
1154
|
-
timeout: forks.filter((f) => f.status === "timeout").length,
|
|
1155
|
-
cancelled: forks.filter((f) => f.status === "cancelled").length,
|
|
1156
|
-
active: forks.filter((f) => f.status === "running" || f.status === "pending").length
|
|
1157
|
-
};
|
|
1158
|
-
}
|
|
1159
|
-
/**
|
|
1160
|
-
* Register event listener
|
|
1161
|
-
*
|
|
1162
|
-
* @param event - Event name
|
|
1163
|
-
* @param listener - Event listener
|
|
1164
|
-
*/
|
|
1165
|
-
on(event, listener) {
|
|
1166
|
-
if (!this.listeners.has(event)) {
|
|
1167
|
-
this.listeners.set(event, /* @__PURE__ */ new Set());
|
|
1168
|
-
}
|
|
1169
|
-
this.listeners.get(event).add(listener);
|
|
1170
|
-
}
|
|
1171
|
-
/**
|
|
1172
|
-
* Unregister event listener
|
|
1173
|
-
*
|
|
1174
|
-
* @param event - Event name
|
|
1175
|
-
* @param listener - Event listener
|
|
1176
|
-
*/
|
|
1177
|
-
off(event, listener) {
|
|
1178
|
-
const set = this.listeners.get(event);
|
|
1179
|
-
if (set) {
|
|
1180
|
-
set.delete(listener);
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
/**
|
|
1184
|
-
* Emit event
|
|
1185
|
-
*
|
|
1186
|
-
* @param event - Event name
|
|
1187
|
-
* @param args - Event arguments
|
|
1188
|
-
*/
|
|
1189
|
-
emit(event, ...args) {
|
|
1190
|
-
const set = this.listeners.get(event);
|
|
1191
|
-
if (set) {
|
|
1192
|
-
const listenersArray = Array.from(set);
|
|
1193
|
-
for (const listener of listenersArray) {
|
|
1194
|
-
try {
|
|
1195
|
-
listener(...args);
|
|
1196
|
-
} catch (error) {
|
|
1197
|
-
console.error(`[AgentForkManager] Error in ${event} listener:`, error);
|
|
1198
|
-
}
|
|
1199
|
-
}
|
|
1200
|
-
}
|
|
1201
|
-
}
|
|
1202
|
-
/**
|
|
1203
|
-
* Change fork status and emit event
|
|
1204
|
-
*
|
|
1205
|
-
* @param forkId - Fork context ID
|
|
1206
|
-
* @param newStatus - New status
|
|
1207
|
-
*/
|
|
1208
|
-
changeStatus(forkId, newStatus) {
|
|
1209
|
-
const fork = this.getForkOrThrow(forkId);
|
|
1210
|
-
const oldStatus = fork.status;
|
|
1211
|
-
fork.status = newStatus;
|
|
1212
|
-
if (oldStatus === "pending" && newStatus === "running") {
|
|
1213
|
-
this.activeForksCount++;
|
|
1214
|
-
} else if (oldStatus === "running" && ["completed", "failed", "cancelled", "timeout"].includes(newStatus)) {
|
|
1215
|
-
this.activeForksCount--;
|
|
1216
|
-
}
|
|
1217
|
-
this.emit("statusChange", fork, oldStatus, newStatus);
|
|
1218
|
-
}
|
|
1219
|
-
/**
|
|
1220
|
-
* Check concurrent limit
|
|
1221
|
-
*
|
|
1222
|
-
* @throws Error if limit reached
|
|
1223
|
-
*/
|
|
1224
|
-
checkConcurrentLimit() {
|
|
1225
|
-
if (this.activeForksCount >= this.options.maxConcurrentForks) {
|
|
1226
|
-
throw new Error(
|
|
1227
|
-
`Maximum concurrent forks limit reached (${this.options.maxConcurrentForks}). Active: ${this.activeForksCount}`
|
|
1228
|
-
);
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
/**
|
|
1232
|
-
* Get fork or throw error
|
|
1233
|
-
*
|
|
1234
|
-
* @param forkId - Fork context ID
|
|
1235
|
-
* @returns Fork state
|
|
1236
|
-
* @throws Error if not found
|
|
1237
|
-
*/
|
|
1238
|
-
getForkOrThrow(forkId) {
|
|
1239
|
-
const fork = this.forks.get(forkId);
|
|
1240
|
-
if (!fork) {
|
|
1241
|
-
throw new Error(`Fork not found: ${forkId}`);
|
|
1242
|
-
}
|
|
1243
|
-
return fork;
|
|
1244
|
-
}
|
|
1245
|
-
/**
|
|
1246
|
-
* Clean up all forks
|
|
1247
|
-
*/
|
|
1248
|
-
cleanup() {
|
|
1249
|
-
this.forks.clear();
|
|
1250
|
-
this.listeners.clear();
|
|
1251
|
-
this.activeForksCount = 0;
|
|
1252
|
-
}
|
|
1253
|
-
}
|
|
1254
|
-
|
|
1255
|
-
class ResultAggregator {
|
|
1256
|
-
options;
|
|
1257
|
-
validator;
|
|
1258
|
-
constructor(options = {}) {
|
|
1259
|
-
this.options = {
|
|
1260
|
-
defaultStrategy: options.defaultStrategy ?? "highest-confidence",
|
|
1261
|
-
autoDetectConflicts: options.autoDetectConflicts ?? true,
|
|
1262
|
-
enableValidation: options.enableValidation ?? true,
|
|
1263
|
-
minConfidenceThreshold: options.minConfidenceThreshold ?? 0.7,
|
|
1264
|
-
enableMerging: options.enableMerging ?? true,
|
|
1265
|
-
maxMergeAttempts: options.maxMergeAttempts ?? 3
|
|
1266
|
-
};
|
|
1267
|
-
this.validator = this.createValidator();
|
|
1268
|
-
}
|
|
1269
|
-
/**
|
|
1270
|
-
* Aggregate results from multiple tasks
|
|
1271
|
-
*
|
|
1272
|
-
* @param tasks - Tasks with outputs to aggregate
|
|
1273
|
-
* @param context - Aggregation context
|
|
1274
|
-
* @returns Aggregation result
|
|
1275
|
-
*/
|
|
1276
|
-
async aggregate(tasks, context) {
|
|
1277
|
-
const aggregationContext = {
|
|
1278
|
-
tasks,
|
|
1279
|
-
strategy: context?.strategy ?? this.options.defaultStrategy,
|
|
1280
|
-
expectedSchema: context?.expectedSchema,
|
|
1281
|
-
metadata: context?.metadata
|
|
1282
|
-
};
|
|
1283
|
-
const tasksWithOutputs = tasks.filter((t) => t.output !== void 0);
|
|
1284
|
-
if (tasksWithOutputs.length === 0) {
|
|
1285
|
-
return this.createEmptyResult(tasks);
|
|
1286
|
-
}
|
|
1287
|
-
const validationErrors = [];
|
|
1288
|
-
if (this.options.enableValidation) {
|
|
1289
|
-
for (const task of tasksWithOutputs) {
|
|
1290
|
-
const validation = this.validator.validate(task.output, aggregationContext.expectedSchema);
|
|
1291
|
-
if (!validation.valid) {
|
|
1292
|
-
validationErrors.push(
|
|
1293
|
-
...validation.errors.map((err) => ({
|
|
1294
|
-
taskId: task.id,
|
|
1295
|
-
field: err.field,
|
|
1296
|
-
message: err.message
|
|
1297
|
-
}))
|
|
1298
|
-
);
|
|
1299
|
-
}
|
|
1300
|
-
}
|
|
1301
|
-
}
|
|
1302
|
-
const conflicts = [];
|
|
1303
|
-
if (this.options.autoDetectConflicts) {
|
|
1304
|
-
conflicts.push(...this.detectConflicts(tasksWithOutputs));
|
|
1305
|
-
}
|
|
1306
|
-
const resolvedConflicts = [];
|
|
1307
|
-
const unresolvedConflicts = [];
|
|
1308
|
-
for (const conflict of conflicts) {
|
|
1309
|
-
const resolution = await this.resolveConflict(conflict);
|
|
1310
|
-
if (resolution.resolved) {
|
|
1311
|
-
resolvedConflicts.push(resolution);
|
|
1312
|
-
} else {
|
|
1313
|
-
unresolvedConflicts.push(conflict);
|
|
1314
|
-
}
|
|
1315
|
-
}
|
|
1316
|
-
const aggregatedOutput = await this.aggregateOutputs(
|
|
1317
|
-
tasksWithOutputs,
|
|
1318
|
-
aggregationContext,
|
|
1319
|
-
resolvedConflicts
|
|
1320
|
-
);
|
|
1321
|
-
const successfulTasks = tasksWithOutputs.filter((t) => t.status === "completed");
|
|
1322
|
-
const failedTasks = tasks.filter((t) => t.status === "failed");
|
|
1323
|
-
const averageConfidence = this.calculateAverageConfidence(tasksWithOutputs);
|
|
1324
|
-
const warnings = [];
|
|
1325
|
-
if (averageConfidence < this.options.minConfidenceThreshold) {
|
|
1326
|
-
warnings.push(`Average confidence ${averageConfidence.toFixed(2)} is below threshold ${this.options.minConfidenceThreshold}`);
|
|
1327
|
-
}
|
|
1328
|
-
if (unresolvedConflicts.length > 0) {
|
|
1329
|
-
warnings.push(`${unresolvedConflicts.length} conflicts remain unresolved`);
|
|
1330
|
-
}
|
|
1331
|
-
return {
|
|
1332
|
-
success: unresolvedConflicts.length === 0 && validationErrors.length === 0,
|
|
1333
|
-
output: aggregatedOutput,
|
|
1334
|
-
conflicts,
|
|
1335
|
-
resolvedConflicts,
|
|
1336
|
-
unresolvedConflicts,
|
|
1337
|
-
validationErrors,
|
|
1338
|
-
warnings,
|
|
1339
|
-
metadata: {
|
|
1340
|
-
totalTasks: tasks.length,
|
|
1341
|
-
successfulTasks: successfulTasks.length,
|
|
1342
|
-
failedTasks: failedTasks.length,
|
|
1343
|
-
averageConfidence,
|
|
1344
|
-
aggregationTimestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1345
|
-
}
|
|
1346
|
-
};
|
|
1347
|
-
}
|
|
1348
|
-
/**
|
|
1349
|
-
* Detect conflicts between task outputs
|
|
1350
|
-
*
|
|
1351
|
-
* @param tasks - Tasks to check for conflicts
|
|
1352
|
-
* @returns Detected conflicts
|
|
1353
|
-
*/
|
|
1354
|
-
detectConflicts(tasks) {
|
|
1355
|
-
const conflicts = [];
|
|
1356
|
-
const tasksByType = this.groupTasksByType(tasks);
|
|
1357
|
-
for (const [_type, typeTasks] of tasksByType) {
|
|
1358
|
-
if (typeTasks.length < 2)
|
|
1359
|
-
continue;
|
|
1360
|
-
const dataConflicts = this.detectDataConflicts(typeTasks);
|
|
1361
|
-
conflicts.push(...dataConflicts);
|
|
1362
|
-
const fileConflicts = this.detectFileConflicts(typeTasks);
|
|
1363
|
-
conflicts.push(...fileConflicts);
|
|
1364
|
-
const decisionConflicts = this.detectDecisionConflicts(typeTasks);
|
|
1365
|
-
conflicts.push(...decisionConflicts);
|
|
1366
|
-
}
|
|
1367
|
-
return conflicts;
|
|
1368
|
-
}
|
|
1369
|
-
/**
|
|
1370
|
-
* Detect data conflicts between tasks
|
|
1371
|
-
*
|
|
1372
|
-
* @param tasks - Tasks to check
|
|
1373
|
-
* @returns Data conflicts
|
|
1374
|
-
*/
|
|
1375
|
-
detectDataConflicts(tasks) {
|
|
1376
|
-
const conflicts = [];
|
|
1377
|
-
const dataFields = this.extractDataFields(tasks);
|
|
1378
|
-
for (const field of dataFields) {
|
|
1379
|
-
const values = tasks.map((t) => ({ taskId: t.id, value: this.getFieldValue(t.output, field) })).filter((v) => v.value !== void 0);
|
|
1380
|
-
if (values.length < 2)
|
|
1381
|
-
continue;
|
|
1382
|
-
const uniqueValues = new Set(values.map((v) => JSON.stringify(v.value)));
|
|
1383
|
-
if (uniqueValues.size > 1) {
|
|
1384
|
-
conflicts.push({
|
|
1385
|
-
conflictingTasks: values.map((v) => v.taskId),
|
|
1386
|
-
results: tasks.map((t) => t.output),
|
|
1387
|
-
strategy: this.options.defaultStrategy,
|
|
1388
|
-
conflictType: "data",
|
|
1389
|
-
description: `Conflicting values for field "${field}"`,
|
|
1390
|
-
metadata: {
|
|
1391
|
-
field,
|
|
1392
|
-
values: values.map((v) => v.value)
|
|
1393
|
-
}
|
|
1394
|
-
});
|
|
1395
|
-
}
|
|
1396
|
-
}
|
|
1397
|
-
return conflicts;
|
|
1398
|
-
}
|
|
1399
|
-
/**
|
|
1400
|
-
* Detect file conflicts between tasks
|
|
1401
|
-
*
|
|
1402
|
-
* @param tasks - Tasks to check
|
|
1403
|
-
* @returns File conflicts
|
|
1404
|
-
*/
|
|
1405
|
-
detectFileConflicts(tasks) {
|
|
1406
|
-
const conflicts = [];
|
|
1407
|
-
const filesByPath = /* @__PURE__ */ new Map();
|
|
1408
|
-
for (const task of tasks) {
|
|
1409
|
-
if (!task.output?.files)
|
|
1410
|
-
continue;
|
|
1411
|
-
for (const file of task.output.files) {
|
|
1412
|
-
if (!filesByPath.has(file)) {
|
|
1413
|
-
filesByPath.set(file, []);
|
|
1414
|
-
}
|
|
1415
|
-
filesByPath.get(file).push({ taskId: task.id, file });
|
|
1416
|
-
}
|
|
1417
|
-
}
|
|
1418
|
-
for (const [path, files] of filesByPath) {
|
|
1419
|
-
if (files.length > 1) {
|
|
1420
|
-
conflicts.push({
|
|
1421
|
-
conflictingTasks: files.map((f) => f.taskId),
|
|
1422
|
-
results: tasks.filter((t) => files.some((f) => f.taskId === t.id)).map((t) => t.output),
|
|
1423
|
-
strategy: this.options.defaultStrategy,
|
|
1424
|
-
conflictType: "file",
|
|
1425
|
-
description: `Multiple tasks produced file "${path}"`,
|
|
1426
|
-
metadata: {
|
|
1427
|
-
filePath: path,
|
|
1428
|
-
taskCount: files.length
|
|
1429
|
-
}
|
|
1430
|
-
});
|
|
1431
|
-
}
|
|
1432
|
-
}
|
|
1433
|
-
return conflicts;
|
|
1434
|
-
}
|
|
1435
|
-
/**
|
|
1436
|
-
* Detect decision conflicts between tasks
|
|
1437
|
-
*
|
|
1438
|
-
* @param tasks - Tasks to check
|
|
1439
|
-
* @returns Decision conflicts
|
|
1440
|
-
*/
|
|
1441
|
-
detectDecisionConflicts(tasks) {
|
|
1442
|
-
const conflicts = [];
|
|
1443
|
-
const decisions = tasks.map((t) => ({
|
|
1444
|
-
taskId: t.id,
|
|
1445
|
-
decision: t.output?.metadata?.decision
|
|
1446
|
-
})).filter((d) => d.decision !== void 0);
|
|
1447
|
-
if (decisions.length < 2)
|
|
1448
|
-
return conflicts;
|
|
1449
|
-
const uniqueDecisions = new Set(decisions.map((d) => d.decision));
|
|
1450
|
-
if (uniqueDecisions.size > 1) {
|
|
1451
|
-
conflicts.push({
|
|
1452
|
-
conflictingTasks: decisions.map((d) => d.taskId),
|
|
1453
|
-
results: tasks.map((t) => t.output),
|
|
1454
|
-
strategy: this.options.defaultStrategy,
|
|
1455
|
-
conflictType: "decision",
|
|
1456
|
-
description: "Tasks made conflicting decisions",
|
|
1457
|
-
metadata: {
|
|
1458
|
-
decisions: decisions.map((d) => d.decision)
|
|
1459
|
-
}
|
|
1460
|
-
});
|
|
1461
|
-
}
|
|
1462
|
-
return conflicts;
|
|
1463
|
-
}
|
|
1464
|
-
/**
|
|
1465
|
-
* Resolve a conflict using the specified strategy
|
|
1466
|
-
*
|
|
1467
|
-
* @param conflict - Conflict to resolve
|
|
1468
|
-
* @returns Resolution result
|
|
1469
|
-
*/
|
|
1470
|
-
async resolveConflict(conflict) {
|
|
1471
|
-
switch (conflict.strategy) {
|
|
1472
|
-
case "first-wins":
|
|
1473
|
-
return this.resolveFirstWins(conflict);
|
|
1474
|
-
case "last-wins":
|
|
1475
|
-
return this.resolveLastWins(conflict);
|
|
1476
|
-
case "vote":
|
|
1477
|
-
return this.resolveByVote(conflict);
|
|
1478
|
-
case "merge":
|
|
1479
|
-
return this.resolveByMerge(conflict);
|
|
1480
|
-
case "highest-confidence":
|
|
1481
|
-
return this.resolveByConfidence(conflict);
|
|
1482
|
-
case "manual":
|
|
1483
|
-
return this.resolveManually(conflict);
|
|
1484
|
-
default:
|
|
1485
|
-
return {
|
|
1486
|
-
resolved: false,
|
|
1487
|
-
method: "unknown",
|
|
1488
|
-
confidence: 0,
|
|
1489
|
-
explanation: `Unknown resolution strategy: ${conflict.strategy}`
|
|
1490
|
-
};
|
|
1491
|
-
}
|
|
1492
|
-
}
|
|
1493
|
-
/**
|
|
1494
|
-
* Resolve conflict using first-wins strategy
|
|
1495
|
-
*
|
|
1496
|
-
* @param conflict - Conflict to resolve
|
|
1497
|
-
* @returns Resolution result
|
|
1498
|
-
*/
|
|
1499
|
-
resolveFirstWins(conflict) {
|
|
1500
|
-
return {
|
|
1501
|
-
resolved: true,
|
|
1502
|
-
result: conflict.results[0],
|
|
1503
|
-
method: "first-wins",
|
|
1504
|
-
confidence: 0.5,
|
|
1505
|
-
explanation: "Used first completed result",
|
|
1506
|
-
discarded: conflict.results.slice(1)
|
|
1507
|
-
};
|
|
1508
|
-
}
|
|
1509
|
-
/**
|
|
1510
|
-
* Resolve conflict using last-wins strategy
|
|
1511
|
-
*
|
|
1512
|
-
* @param conflict - Conflict to resolve
|
|
1513
|
-
* @returns Resolution result
|
|
1514
|
-
*/
|
|
1515
|
-
resolveLastWins(conflict) {
|
|
1516
|
-
const lastResult = conflict.results[conflict.results.length - 1];
|
|
1517
|
-
return {
|
|
1518
|
-
resolved: true,
|
|
1519
|
-
result: lastResult,
|
|
1520
|
-
method: "last-wins",
|
|
1521
|
-
confidence: 0.5,
|
|
1522
|
-
explanation: "Used last completed result",
|
|
1523
|
-
discarded: conflict.results.slice(0, -1)
|
|
1524
|
-
};
|
|
1525
|
-
}
|
|
1526
|
-
/**
|
|
1527
|
-
* Resolve conflict using voting strategy
|
|
1528
|
-
*
|
|
1529
|
-
* @param conflict - Conflict to resolve
|
|
1530
|
-
* @returns Resolution result
|
|
1531
|
-
*/
|
|
1532
|
-
resolveByVote(conflict) {
|
|
1533
|
-
const resultCounts = /* @__PURE__ */ new Map();
|
|
1534
|
-
for (const result of conflict.results) {
|
|
1535
|
-
const key = JSON.stringify(result.data);
|
|
1536
|
-
const existing = resultCounts.get(key);
|
|
1537
|
-
if (existing) {
|
|
1538
|
-
existing.count++;
|
|
1539
|
-
} else {
|
|
1540
|
-
resultCounts.set(key, { count: 1, result });
|
|
1541
|
-
}
|
|
1542
|
-
}
|
|
1543
|
-
let maxCount = 0;
|
|
1544
|
-
let winningResult;
|
|
1545
|
-
for (const [_, { count, result }] of resultCounts) {
|
|
1546
|
-
if (count > maxCount) {
|
|
1547
|
-
maxCount = count;
|
|
1548
|
-
winningResult = result;
|
|
1549
|
-
}
|
|
1550
|
-
}
|
|
1551
|
-
const confidence = maxCount / conflict.results.length;
|
|
1552
|
-
return {
|
|
1553
|
-
resolved: winningResult !== void 0,
|
|
1554
|
-
result: winningResult,
|
|
1555
|
-
method: "vote",
|
|
1556
|
-
confidence,
|
|
1557
|
-
explanation: `Result won with ${maxCount}/${conflict.results.length} votes`,
|
|
1558
|
-
discarded: conflict.results.filter((r) => r !== winningResult)
|
|
1559
|
-
};
|
|
1560
|
-
}
|
|
1561
|
-
/**
|
|
1562
|
-
* Resolve conflict by merging results
|
|
1563
|
-
*
|
|
1564
|
-
* @param conflict - Conflict to resolve
|
|
1565
|
-
* @returns Resolution result
|
|
1566
|
-
*/
|
|
1567
|
-
async resolveByMerge(conflict) {
|
|
1568
|
-
if (!this.options.enableMerging) {
|
|
1569
|
-
return {
|
|
1570
|
-
resolved: false,
|
|
1571
|
-
method: "merge",
|
|
1572
|
-
confidence: 0,
|
|
1573
|
-
explanation: "Merging is disabled"
|
|
1574
|
-
};
|
|
1575
|
-
}
|
|
1576
|
-
try {
|
|
1577
|
-
const mergedResult = await this.mergeResults(conflict.results, conflict.conflictType);
|
|
1578
|
-
return {
|
|
1579
|
-
resolved: true,
|
|
1580
|
-
result: mergedResult,
|
|
1581
|
-
method: "merge",
|
|
1582
|
-
confidence: 0.8,
|
|
1583
|
-
explanation: "Successfully merged conflicting results"
|
|
1584
|
-
};
|
|
1585
|
-
} catch (error) {
|
|
1586
|
-
return {
|
|
1587
|
-
resolved: false,
|
|
1588
|
-
method: "merge",
|
|
1589
|
-
confidence: 0,
|
|
1590
|
-
explanation: `Merge failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
1591
|
-
};
|
|
1592
|
-
}
|
|
1593
|
-
}
|
|
1594
|
-
/**
|
|
1595
|
-
* Resolve conflict using highest confidence strategy
|
|
1596
|
-
*
|
|
1597
|
-
* @param conflict - Conflict to resolve
|
|
1598
|
-
* @returns Resolution result
|
|
1599
|
-
*/
|
|
1600
|
-
resolveByConfidence(conflict) {
|
|
1601
|
-
let maxConfidence = 0;
|
|
1602
|
-
let bestResult;
|
|
1603
|
-
for (const result of conflict.results) {
|
|
1604
|
-
const confidence = result.confidence ?? 0;
|
|
1605
|
-
if (confidence > maxConfidence) {
|
|
1606
|
-
maxConfidence = confidence;
|
|
1607
|
-
bestResult = result;
|
|
1608
|
-
}
|
|
1609
|
-
}
|
|
1610
|
-
return {
|
|
1611
|
-
resolved: bestResult !== void 0,
|
|
1612
|
-
result: bestResult,
|
|
1613
|
-
method: "highest-confidence",
|
|
1614
|
-
confidence: maxConfidence,
|
|
1615
|
-
explanation: `Selected result with confidence ${maxConfidence.toFixed(2)}`,
|
|
1616
|
-
discarded: conflict.results.filter((r) => r !== bestResult)
|
|
1617
|
-
};
|
|
1618
|
-
}
|
|
1619
|
-
/**
|
|
1620
|
-
* Resolve conflict manually (placeholder for user intervention)
|
|
1621
|
-
*
|
|
1622
|
-
* @param _conflict - Conflict to resolve
|
|
1623
|
-
* @returns Resolution result
|
|
1624
|
-
*/
|
|
1625
|
-
resolveManually(_conflict) {
|
|
1626
|
-
return {
|
|
1627
|
-
resolved: false,
|
|
1628
|
-
method: "manual",
|
|
1629
|
-
confidence: 0,
|
|
1630
|
-
explanation: "Manual resolution required"
|
|
1631
|
-
};
|
|
1632
|
-
}
|
|
1633
|
-
/**
|
|
1634
|
-
* Merge multiple results into a single result
|
|
1635
|
-
*
|
|
1636
|
-
* @param results - Results to merge
|
|
1637
|
-
* @returns Merged result
|
|
1638
|
-
*/
|
|
1639
|
-
async mergeResults(results, _conflictType) {
|
|
1640
|
-
const mergedData = {};
|
|
1641
|
-
const mergedFiles = [];
|
|
1642
|
-
const mergedArtifacts = [];
|
|
1643
|
-
const mergedLogs = [];
|
|
1644
|
-
for (const result of results) {
|
|
1645
|
-
for (const [key, value] of Object.entries(result.data)) {
|
|
1646
|
-
if (!(key in mergedData)) {
|
|
1647
|
-
mergedData[key] = value;
|
|
1648
|
-
} else if (Array.isArray(mergedData[key]) && Array.isArray(value)) {
|
|
1649
|
-
mergedData[key] = [...mergedData[key], ...value];
|
|
1650
|
-
} else if (typeof mergedData[key] === "object" && typeof value === "object") {
|
|
1651
|
-
mergedData[key] = { ...mergedData[key], ...value };
|
|
1652
|
-
}
|
|
1653
|
-
}
|
|
1654
|
-
if (result.files) {
|
|
1655
|
-
for (const file of result.files) {
|
|
1656
|
-
if (!mergedFiles.includes(file)) {
|
|
1657
|
-
mergedFiles.push(file);
|
|
1658
|
-
}
|
|
1659
|
-
}
|
|
1660
|
-
}
|
|
1661
|
-
if (result.artifacts) {
|
|
1662
|
-
mergedArtifacts.push(...result.artifacts);
|
|
1663
|
-
}
|
|
1664
|
-
if (result.logs) {
|
|
1665
|
-
mergedLogs.push(...result.logs);
|
|
1666
|
-
}
|
|
1667
|
-
}
|
|
1668
|
-
const confidences = results.map((r) => r.confidence ?? 0).filter((c) => c > 0);
|
|
1669
|
-
const avgConfidence = confidences.length > 0 ? confidences.reduce((sum, c) => sum + c, 0) / confidences.length : void 0;
|
|
1670
|
-
return {
|
|
1671
|
-
data: mergedData,
|
|
1672
|
-
files: mergedFiles.length > 0 ? mergedFiles : void 0,
|
|
1673
|
-
artifacts: mergedArtifacts.length > 0 ? mergedArtifacts : void 0,
|
|
1674
|
-
logs: mergedLogs.length > 0 ? mergedLogs : void 0,
|
|
1675
|
-
confidence: avgConfidence,
|
|
1676
|
-
metadata: {
|
|
1677
|
-
merged: true,
|
|
1678
|
-
sourceCount: results.length,
|
|
1679
|
-
mergeTimestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1680
|
-
}
|
|
1681
|
-
};
|
|
1682
|
-
}
|
|
1683
|
-
/**
|
|
1684
|
-
* Aggregate outputs from multiple tasks
|
|
1685
|
-
*
|
|
1686
|
-
* @param tasks - Tasks with outputs
|
|
1687
|
-
* @param context - Aggregation context
|
|
1688
|
-
* @param resolvedConflicts - Resolved conflicts
|
|
1689
|
-
* @returns Aggregated output
|
|
1690
|
-
*/
|
|
1691
|
-
async aggregateOutputs(tasks, context, resolvedConflicts) {
|
|
1692
|
-
const aggregated = {
|
|
1693
|
-
data: {},
|
|
1694
|
-
files: [],
|
|
1695
|
-
artifacts: [],
|
|
1696
|
-
logs: []
|
|
1697
|
-
};
|
|
1698
|
-
for (const resolution of resolvedConflicts) {
|
|
1699
|
-
if (resolution.result) {
|
|
1700
|
-
this.mergeIntoAggregated(aggregated, resolution.result);
|
|
1701
|
-
}
|
|
1702
|
-
}
|
|
1703
|
-
for (const task of tasks) {
|
|
1704
|
-
if (!task.output)
|
|
1705
|
-
continue;
|
|
1706
|
-
const taskOutput = task.output;
|
|
1707
|
-
const wasInConflict = resolvedConflicts.some(
|
|
1708
|
-
(r) => r.discarded?.includes(taskOutput)
|
|
1709
|
-
);
|
|
1710
|
-
if (!wasInConflict) {
|
|
1711
|
-
this.mergeIntoAggregated(aggregated, taskOutput);
|
|
1712
|
-
}
|
|
1713
|
-
}
|
|
1714
|
-
const confidences = tasks.map((t) => t.output?.confidence ?? 0).filter((c) => c > 0);
|
|
1715
|
-
aggregated.confidence = confidences.length > 0 ? confidences.reduce((sum, c) => sum + c, 0) / confidences.length : void 0;
|
|
1716
|
-
aggregated.metadata = {
|
|
1717
|
-
...aggregated.metadata,
|
|
1718
|
-
aggregated: true,
|
|
1719
|
-
taskCount: tasks.length,
|
|
1720
|
-
aggregationStrategy: context.strategy,
|
|
1721
|
-
aggregationTimestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1722
|
-
};
|
|
1723
|
-
return aggregated;
|
|
1724
|
-
}
|
|
1725
|
-
/**
|
|
1726
|
-
* Merge an output into the aggregated result
|
|
1727
|
-
*
|
|
1728
|
-
* @param aggregated - Aggregated output
|
|
1729
|
-
* @param output - Output to merge
|
|
1730
|
-
*/
|
|
1731
|
-
mergeIntoAggregated(aggregated, output) {
|
|
1732
|
-
Object.assign(aggregated.data, output.data);
|
|
1733
|
-
if (output.files) {
|
|
1734
|
-
aggregated.files = [...aggregated.files ?? [], ...output.files];
|
|
1735
|
-
}
|
|
1736
|
-
if (output.artifacts) {
|
|
1737
|
-
aggregated.artifacts = [...aggregated.artifacts ?? [], ...output.artifacts];
|
|
1738
|
-
}
|
|
1739
|
-
if (output.logs) {
|
|
1740
|
-
aggregated.logs = [...aggregated.logs ?? [], ...output.logs];
|
|
1741
|
-
}
|
|
1742
|
-
}
|
|
1743
|
-
/**
|
|
1744
|
-
* Create empty aggregation result
|
|
1745
|
-
*
|
|
1746
|
-
* @param tasks - Tasks
|
|
1747
|
-
* @returns Empty result
|
|
1748
|
-
*/
|
|
1749
|
-
createEmptyResult(tasks) {
|
|
1750
|
-
return {
|
|
1751
|
-
success: false,
|
|
1752
|
-
conflicts: [],
|
|
1753
|
-
resolvedConflicts: [],
|
|
1754
|
-
unresolvedConflicts: [],
|
|
1755
|
-
validationErrors: [],
|
|
1756
|
-
warnings: ["No task outputs to aggregate"],
|
|
1757
|
-
metadata: {
|
|
1758
|
-
totalTasks: tasks.length,
|
|
1759
|
-
successfulTasks: 0,
|
|
1760
|
-
failedTasks: tasks.filter((t) => t.status === "failed").length,
|
|
1761
|
-
averageConfidence: 0,
|
|
1762
|
-
aggregationTimestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1763
|
-
}
|
|
1764
|
-
};
|
|
1765
|
-
}
|
|
1766
|
-
/**
|
|
1767
|
-
* Group tasks by type
|
|
1768
|
-
*
|
|
1769
|
-
* @param tasks - Tasks to group
|
|
1770
|
-
* @returns Tasks grouped by type
|
|
1771
|
-
*/
|
|
1772
|
-
groupTasksByType(tasks) {
|
|
1773
|
-
const groups = /* @__PURE__ */ new Map();
|
|
1774
|
-
for (const task of tasks) {
|
|
1775
|
-
if (!groups.has(task.type)) {
|
|
1776
|
-
groups.set(task.type, []);
|
|
1777
|
-
}
|
|
1778
|
-
groups.get(task.type).push(task);
|
|
1779
|
-
}
|
|
1780
|
-
return groups;
|
|
1781
|
-
}
|
|
1782
|
-
/**
|
|
1783
|
-
* Extract data fields from tasks
|
|
1784
|
-
*
|
|
1785
|
-
* @param tasks - Tasks to analyze
|
|
1786
|
-
* @returns Data field names
|
|
1787
|
-
*/
|
|
1788
|
-
extractDataFields(tasks) {
|
|
1789
|
-
const fields = /* @__PURE__ */ new Set();
|
|
1790
|
-
for (const task of tasks) {
|
|
1791
|
-
if (!task.output)
|
|
1792
|
-
continue;
|
|
1793
|
-
for (const key of Object.keys(task.output.data)) {
|
|
1794
|
-
fields.add(key);
|
|
1795
|
-
}
|
|
1796
|
-
}
|
|
1797
|
-
return Array.from(fields);
|
|
1798
|
-
}
|
|
1799
|
-
/**
|
|
1800
|
-
* Get field value from output
|
|
1801
|
-
*
|
|
1802
|
-
* @param output - Task output
|
|
1803
|
-
* @param field - Field name
|
|
1804
|
-
* @returns Field value
|
|
1805
|
-
*/
|
|
1806
|
-
getFieldValue(output, field) {
|
|
1807
|
-
return output.data[field];
|
|
1808
|
-
}
|
|
1809
|
-
/**
|
|
1810
|
-
* Calculate average confidence from tasks
|
|
1811
|
-
*
|
|
1812
|
-
* @param tasks - Tasks with outputs
|
|
1813
|
-
* @returns Average confidence
|
|
1814
|
-
*/
|
|
1815
|
-
calculateAverageConfidence(tasks) {
|
|
1816
|
-
const confidences = tasks.map((t) => t.output?.confidence ?? 0).filter((c) => c > 0);
|
|
1817
|
-
if (confidences.length === 0)
|
|
1818
|
-
return 0;
|
|
1819
|
-
return confidences.reduce((sum, c) => sum + c, 0) / confidences.length;
|
|
1820
|
-
}
|
|
1821
|
-
/**
|
|
1822
|
-
* Create result validator
|
|
1823
|
-
*
|
|
1824
|
-
* @returns Result validator
|
|
1825
|
-
*/
|
|
1826
|
-
createValidator() {
|
|
1827
|
-
return {
|
|
1828
|
-
validate: (output, schema) => {
|
|
1829
|
-
const errors = [];
|
|
1830
|
-
const warnings = [];
|
|
1831
|
-
if (!output.data || Object.keys(output.data).length === 0) {
|
|
1832
|
-
errors.push({
|
|
1833
|
-
field: "data",
|
|
1834
|
-
message: "Output data is empty",
|
|
1835
|
-
code: "EMPTY_DATA"
|
|
1836
|
-
});
|
|
1837
|
-
}
|
|
1838
|
-
if (schema) {
|
|
1839
|
-
for (const [field, _type] of Object.entries(schema)) {
|
|
1840
|
-
if (!(field in output.data)) {
|
|
1841
|
-
errors.push({
|
|
1842
|
-
field,
|
|
1843
|
-
message: `Required field "${field}" is missing`,
|
|
1844
|
-
code: "MISSING_FIELD"
|
|
1845
|
-
});
|
|
1846
|
-
}
|
|
1847
|
-
}
|
|
1848
|
-
}
|
|
1849
|
-
if (output.confidence !== void 0 && (output.confidence < 0 || output.confidence > 1)) {
|
|
1850
|
-
warnings.push({
|
|
1851
|
-
field: "confidence",
|
|
1852
|
-
message: "Confidence score should be between 0 and 1",
|
|
1853
|
-
code: "INVALID_CONFIDENCE"
|
|
1854
|
-
});
|
|
1855
|
-
}
|
|
1856
|
-
return {
|
|
1857
|
-
valid: errors.length === 0,
|
|
1858
|
-
errors,
|
|
1859
|
-
warnings
|
|
1860
|
-
};
|
|
1861
|
-
}
|
|
1862
|
-
};
|
|
1863
|
-
}
|
|
1864
|
-
}
|
|
1865
|
-
|
|
1866
|
-
function toAgentCapabilities$1(names) {
|
|
1867
|
-
return names.map((name) => ({
|
|
1868
|
-
id: name,
|
|
1869
|
-
name,
|
|
1870
|
-
model: "sonnet",
|
|
1871
|
-
specialties: [name],
|
|
1872
|
-
strength: 0.8,
|
|
1873
|
-
costFactor: 1
|
|
1874
|
-
}));
|
|
1875
|
-
}
|
|
1876
|
-
function fromAgentCapabilities$1(capabilities) {
|
|
1877
|
-
return capabilities.map((cap) => cap.id);
|
|
1878
|
-
}
|
|
1879
|
-
class TaskDecomposer {
|
|
1880
|
-
options;
|
|
1881
|
-
constructor(options = {}) {
|
|
1882
|
-
this.options = {
|
|
1883
|
-
strategy: options.strategy ?? "hierarchical",
|
|
1884
|
-
maxDepth: options.maxDepth ?? 5,
|
|
1885
|
-
maxParallelTasks: options.maxParallelTasks ?? 10,
|
|
1886
|
-
minTaskGranularity: options.minTaskGranularity ?? 1e3,
|
|
1887
|
-
autoDetectDependencies: options.autoDetectDependencies ?? true,
|
|
1888
|
-
enableOptimization: options.enableOptimization ?? true
|
|
1889
|
-
};
|
|
1890
|
-
}
|
|
1891
|
-
/**
|
|
1892
|
-
* Decompose a complex task into subtasks
|
|
1893
|
-
*
|
|
1894
|
-
* @param task - The task to decompose
|
|
1895
|
-
* @param strategy - Optional strategy override
|
|
1896
|
-
* @returns Decomposition result with subtasks and dependencies
|
|
1897
|
-
*/
|
|
1898
|
-
async decompose(task, strategy) {
|
|
1899
|
-
const decompositionStrategy = strategy ?? this.options.strategy;
|
|
1900
|
-
const complexity = this.analyzeComplexity(task);
|
|
1901
|
-
const effectiveStrategy = this.selectStrategy(task, complexity, decompositionStrategy);
|
|
1902
|
-
let subtasks;
|
|
1903
|
-
let dependencies;
|
|
1904
|
-
switch (effectiveStrategy) {
|
|
1905
|
-
case "sequential":
|
|
1906
|
-
({ subtasks, dependencies } = await this.decomposeSequential(task));
|
|
1907
|
-
break;
|
|
1908
|
-
case "parallel":
|
|
1909
|
-
({ subtasks, dependencies } = await this.decomposeParallel(task));
|
|
1910
|
-
break;
|
|
1911
|
-
case "hierarchical":
|
|
1912
|
-
({ subtasks, dependencies } = await this.decomposeHierarchical(task));
|
|
1913
|
-
break;
|
|
1914
|
-
case "pipeline":
|
|
1915
|
-
({ subtasks, dependencies } = await this.decomposePipeline(task));
|
|
1916
|
-
break;
|
|
1917
|
-
case "map-reduce":
|
|
1918
|
-
({ subtasks, dependencies } = await this.decomposeMapReduce(task));
|
|
1919
|
-
break;
|
|
1920
|
-
default:
|
|
1921
|
-
throw new Error(`Unknown decomposition strategy: ${effectiveStrategy}`);
|
|
1922
|
-
}
|
|
1923
|
-
if (this.options.autoDetectDependencies) {
|
|
1924
|
-
dependencies = this.detectDependencies(subtasks, dependencies);
|
|
1925
|
-
}
|
|
1926
|
-
const executionGraph = this.buildExecutionGraph(subtasks, dependencies);
|
|
1927
|
-
if (this.options.enableOptimization) {
|
|
1928
|
-
this.optimizeExecutionGraph(executionGraph, subtasks);
|
|
1929
|
-
}
|
|
1930
|
-
const estimatedDuration = this.calculateEstimatedDuration(subtasks, executionGraph);
|
|
1931
|
-
return {
|
|
1932
|
-
originalTask: task,
|
|
1933
|
-
subtasks,
|
|
1934
|
-
dependencies,
|
|
1935
|
-
strategy: effectiveStrategy,
|
|
1936
|
-
executionGraph,
|
|
1937
|
-
estimatedDuration,
|
|
1938
|
-
metadata: {
|
|
1939
|
-
complexity,
|
|
1940
|
-
decompositionTimestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1941
|
-
subtaskCount: subtasks.length,
|
|
1942
|
-
dependencyCount: dependencies.length
|
|
1943
|
-
}
|
|
1944
|
-
};
|
|
1945
|
-
}
|
|
1946
|
-
/**
|
|
1947
|
-
* Analyze task complexity
|
|
1948
|
-
*
|
|
1949
|
-
* @param task - Task to analyze
|
|
1950
|
-
* @returns Complexity score (0-1)
|
|
1951
|
-
*/
|
|
1952
|
-
analyzeComplexity(task) {
|
|
1953
|
-
let complexity = 0;
|
|
1954
|
-
complexity += Math.min(task.requiredCapabilities.length / 10, 0.3);
|
|
1955
|
-
complexity += Math.min(task.description.length / 1e3, 0.2);
|
|
1956
|
-
complexity += Math.min(Object.keys(task.input.parameters).length / 20, 0.2);
|
|
1957
|
-
complexity += Math.min((task.input.constraints?.length ?? 0) / 10, 0.15);
|
|
1958
|
-
if (task.estimatedDuration) {
|
|
1959
|
-
complexity += Math.min(task.estimatedDuration / 3e5, 0.15);
|
|
1960
|
-
}
|
|
1961
|
-
return Math.min(complexity, 1);
|
|
1962
|
-
}
|
|
1963
|
-
/**
|
|
1964
|
-
* Select appropriate decomposition strategy
|
|
1965
|
-
*
|
|
1966
|
-
* @param task - Task to decompose
|
|
1967
|
-
* @param complexity - Task complexity score
|
|
1968
|
-
* @param preferredStrategy - Preferred strategy
|
|
1969
|
-
* @returns Selected strategy
|
|
1970
|
-
*/
|
|
1971
|
-
selectStrategy(task, complexity, preferredStrategy) {
|
|
1972
|
-
if (complexity < 0.3) {
|
|
1973
|
-
return "sequential";
|
|
1974
|
-
}
|
|
1975
|
-
if (task.type.includes("data") || task.type.includes("process")) {
|
|
1976
|
-
return task.input.files && task.input.files.length > 1 ? "map-reduce" : "pipeline";
|
|
1977
|
-
}
|
|
1978
|
-
if (task.type.includes("analysis") || task.type.includes("review")) {
|
|
1979
|
-
return "parallel";
|
|
1980
|
-
}
|
|
1981
|
-
return preferredStrategy;
|
|
1982
|
-
}
|
|
1983
|
-
/**
|
|
1984
|
-
* Decompose task sequentially
|
|
1985
|
-
*
|
|
1986
|
-
* @param task - Task to decompose
|
|
1987
|
-
* @returns Subtasks and dependencies
|
|
1988
|
-
*/
|
|
1989
|
-
async decomposeSequential(task) {
|
|
1990
|
-
const subtasks = [];
|
|
1991
|
-
const dependencies = [];
|
|
1992
|
-
const steps = this.identifySequentialSteps(task);
|
|
1993
|
-
for (let i = 0; i < steps.length; i++) {
|
|
1994
|
-
const step = steps[i];
|
|
1995
|
-
const subtask = this.createSubtask(task, step, i);
|
|
1996
|
-
subtasks.push(subtask);
|
|
1997
|
-
if (i > 0) {
|
|
1998
|
-
dependencies.push({
|
|
1999
|
-
taskId: subtasks[i - 1].id,
|
|
2000
|
-
type: "sequential",
|
|
2001
|
-
required: true
|
|
2002
|
-
});
|
|
2003
|
-
}
|
|
2004
|
-
}
|
|
2005
|
-
return { subtasks, dependencies };
|
|
2006
|
-
}
|
|
2007
|
-
/**
|
|
2008
|
-
* Decompose task into parallel subtasks
|
|
2009
|
-
*
|
|
2010
|
-
* @param task - Task to decompose
|
|
2011
|
-
* @returns Subtasks and dependencies
|
|
2012
|
-
*/
|
|
2013
|
-
async decomposeParallel(task) {
|
|
2014
|
-
const subtasks = [];
|
|
2015
|
-
const dependencies = [];
|
|
2016
|
-
const parallelSteps = this.identifyParallelSteps(task);
|
|
2017
|
-
for (let i = 0; i < parallelSteps.length; i++) {
|
|
2018
|
-
const step = parallelSteps[i];
|
|
2019
|
-
const subtask = this.createSubtask(task, step, i);
|
|
2020
|
-
subtasks.push(subtask);
|
|
2021
|
-
}
|
|
2022
|
-
return { subtasks, dependencies };
|
|
2023
|
-
}
|
|
2024
|
-
/**
|
|
2025
|
-
* Decompose task hierarchically
|
|
2026
|
-
*
|
|
2027
|
-
* @param task - Task to decompose
|
|
2028
|
-
* @returns Subtasks and dependencies
|
|
2029
|
-
*/
|
|
2030
|
-
async decomposeHierarchical(task, depth = 0) {
|
|
2031
|
-
const subtasks = [];
|
|
2032
|
-
const dependencies = [];
|
|
2033
|
-
if (depth >= this.options.maxDepth) {
|
|
2034
|
-
return { subtasks: [task], dependencies: [] };
|
|
2035
|
-
}
|
|
2036
|
-
const phases = this.identifyPhases(task);
|
|
2037
|
-
for (let i = 0; i < phases.length; i++) {
|
|
2038
|
-
const phase = phases[i];
|
|
2039
|
-
const phaseTask = this.createSubtask(task, phase, i);
|
|
2040
|
-
const phaseComplexity = this.analyzeComplexity(phaseTask);
|
|
2041
|
-
if (phaseComplexity > 0.5 && depth < this.options.maxDepth - 1) {
|
|
2042
|
-
const { subtasks: phaseSubtasks, dependencies: phaseDeps } = await this.decomposeHierarchical(phaseTask, depth + 1);
|
|
2043
|
-
subtasks.push(...phaseSubtasks);
|
|
2044
|
-
dependencies.push(...phaseDeps);
|
|
2045
|
-
} else {
|
|
2046
|
-
subtasks.push(phaseTask);
|
|
2047
|
-
}
|
|
2048
|
-
if (i > 0 && subtasks.length > 1) {
|
|
2049
|
-
dependencies.push({
|
|
2050
|
-
taskId: subtasks[subtasks.length - 2].id,
|
|
2051
|
-
type: "sequential",
|
|
2052
|
-
required: true
|
|
2053
|
-
});
|
|
2054
|
-
}
|
|
2055
|
-
}
|
|
2056
|
-
return { subtasks, dependencies };
|
|
2057
|
-
}
|
|
2058
|
-
/**
|
|
2059
|
-
* Decompose task as a pipeline
|
|
2060
|
-
*
|
|
2061
|
-
* @param task - Task to decompose
|
|
2062
|
-
* @returns Subtasks and dependencies
|
|
2063
|
-
*/
|
|
2064
|
-
async decomposePipeline(task) {
|
|
2065
|
-
const subtasks = [];
|
|
2066
|
-
const dependencies = [];
|
|
2067
|
-
const stages = this.identifyPipelineStages(task);
|
|
2068
|
-
for (let i = 0; i < stages.length; i++) {
|
|
2069
|
-
const stage = stages[i];
|
|
2070
|
-
const subtask = this.createSubtask(task, stage, i);
|
|
2071
|
-
subtasks.push(subtask);
|
|
2072
|
-
if (i > 0) {
|
|
2073
|
-
dependencies.push({
|
|
2074
|
-
taskId: subtasks[i - 1].id,
|
|
2075
|
-
type: "data",
|
|
2076
|
-
required: true,
|
|
2077
|
-
dataMapping: {
|
|
2078
|
-
output: "input"
|
|
2079
|
-
}
|
|
2080
|
-
});
|
|
2081
|
-
}
|
|
2082
|
-
}
|
|
2083
|
-
return { subtasks, dependencies };
|
|
2084
|
-
}
|
|
2085
|
-
/**
|
|
2086
|
-
* Decompose task using map-reduce pattern
|
|
2087
|
-
*
|
|
2088
|
-
* @param task - Task to decompose
|
|
2089
|
-
* @returns Subtasks and dependencies
|
|
2090
|
-
*/
|
|
2091
|
-
async decomposeMapReduce(task) {
|
|
2092
|
-
const subtasks = [];
|
|
2093
|
-
const dependencies = [];
|
|
2094
|
-
const mapTasks = this.createMapTasks(task);
|
|
2095
|
-
subtasks.push(...mapTasks);
|
|
2096
|
-
const reduceTask = this.createReduceTask(task, mapTasks.length);
|
|
2097
|
-
subtasks.push(reduceTask);
|
|
2098
|
-
for (const mapTask of mapTasks) {
|
|
2099
|
-
dependencies.push({
|
|
2100
|
-
taskId: mapTask.id,
|
|
2101
|
-
type: "data",
|
|
2102
|
-
required: true,
|
|
2103
|
-
dataMapping: {
|
|
2104
|
-
output: "input"
|
|
2105
|
-
}
|
|
2106
|
-
});
|
|
2107
|
-
}
|
|
2108
|
-
return { subtasks, dependencies };
|
|
2109
|
-
}
|
|
2110
|
-
/**
|
|
2111
|
-
* Identify sequential steps in a task
|
|
2112
|
-
*
|
|
2113
|
-
* @param task - Task to analyze
|
|
2114
|
-
* @returns Sequential steps
|
|
2115
|
-
*/
|
|
2116
|
-
identifySequentialSteps(task) {
|
|
2117
|
-
const steps = [];
|
|
2118
|
-
steps.push({
|
|
2119
|
-
name: `${task.name} - Preparation`,
|
|
2120
|
-
description: `Prepare for ${task.description}`,
|
|
2121
|
-
capabilities: fromAgentCapabilities$1(task.requiredCapabilities)
|
|
2122
|
-
});
|
|
2123
|
-
steps.push({
|
|
2124
|
-
name: `${task.name} - Execution`,
|
|
2125
|
-
description: `Execute ${task.description}`,
|
|
2126
|
-
capabilities: fromAgentCapabilities$1(task.requiredCapabilities)
|
|
2127
|
-
});
|
|
2128
|
-
steps.push({
|
|
2129
|
-
name: `${task.name} - Validation`,
|
|
2130
|
-
description: `Validate results of ${task.description}`,
|
|
2131
|
-
capabilities: ["code-analysis"]
|
|
2132
|
-
});
|
|
2133
|
-
return steps;
|
|
2134
|
-
}
|
|
2135
|
-
/**
|
|
2136
|
-
* Identify parallel steps in a task
|
|
2137
|
-
*
|
|
2138
|
-
* @param task - Task to analyze
|
|
2139
|
-
* @returns Parallel steps
|
|
2140
|
-
*/
|
|
2141
|
-
identifyParallelSteps(task) {
|
|
2142
|
-
const steps = [];
|
|
2143
|
-
if (task.input.files && task.input.files.length > 1) {
|
|
2144
|
-
for (const file of task.input.files) {
|
|
2145
|
-
steps.push({
|
|
2146
|
-
name: `${task.name} - ${file}`,
|
|
2147
|
-
description: `${task.description} for ${file}`,
|
|
2148
|
-
capabilities: fromAgentCapabilities$1(task.requiredCapabilities)
|
|
2149
|
-
});
|
|
2150
|
-
}
|
|
2151
|
-
} else {
|
|
2152
|
-
const capabilityGroups = this.groupCapabilities(fromAgentCapabilities$1(task.requiredCapabilities));
|
|
2153
|
-
for (const [group, capabilities] of capabilityGroups) {
|
|
2154
|
-
steps.push({
|
|
2155
|
-
name: `${task.name} - ${group}`,
|
|
2156
|
-
description: `${task.description} (${group})`,
|
|
2157
|
-
capabilities
|
|
2158
|
-
});
|
|
2159
|
-
}
|
|
2160
|
-
}
|
|
2161
|
-
return steps;
|
|
2162
|
-
}
|
|
2163
|
-
/**
|
|
2164
|
-
* Identify high-level phases in a task
|
|
2165
|
-
*
|
|
2166
|
-
* @param task - Task to analyze
|
|
2167
|
-
* @returns Task phases
|
|
2168
|
-
*/
|
|
2169
|
-
identifyPhases(task) {
|
|
2170
|
-
const phases = [];
|
|
2171
|
-
phases.push({
|
|
2172
|
-
name: `${task.name} - Planning`,
|
|
2173
|
-
description: `Plan approach for ${task.description}`,
|
|
2174
|
-
capabilities: ["architecture-design"]
|
|
2175
|
-
});
|
|
2176
|
-
phases.push({
|
|
2177
|
-
name: `${task.name} - Implementation`,
|
|
2178
|
-
description: `Implement ${task.description}`,
|
|
2179
|
-
capabilities: fromAgentCapabilities$1(task.requiredCapabilities)
|
|
2180
|
-
});
|
|
2181
|
-
phases.push({
|
|
2182
|
-
name: `${task.name} - Testing`,
|
|
2183
|
-
description: `Test ${task.description}`,
|
|
2184
|
-
capabilities: ["test-generation", "code-analysis"]
|
|
2185
|
-
});
|
|
2186
|
-
return phases;
|
|
2187
|
-
}
|
|
2188
|
-
/**
|
|
2189
|
-
* Identify pipeline stages in a task
|
|
2190
|
-
*
|
|
2191
|
-
* @param task - Task to analyze
|
|
2192
|
-
* @returns Pipeline stages
|
|
2193
|
-
*/
|
|
2194
|
-
identifyPipelineStages(task) {
|
|
2195
|
-
const stages = [];
|
|
2196
|
-
stages.push({
|
|
2197
|
-
name: `${task.name} - Input Processing`,
|
|
2198
|
-
description: `Process input for ${task.description}`,
|
|
2199
|
-
capabilities: fromAgentCapabilities$1(task.requiredCapabilities)
|
|
2200
|
-
});
|
|
2201
|
-
stages.push({
|
|
2202
|
-
name: `${task.name} - Transformation`,
|
|
2203
|
-
description: `Transform data for ${task.description}`,
|
|
2204
|
-
capabilities: fromAgentCapabilities$1(task.requiredCapabilities)
|
|
2205
|
-
});
|
|
2206
|
-
stages.push({
|
|
2207
|
-
name: `${task.name} - Output Generation`,
|
|
2208
|
-
description: `Generate output for ${task.description}`,
|
|
2209
|
-
capabilities: fromAgentCapabilities$1(task.requiredCapabilities)
|
|
2210
|
-
});
|
|
2211
|
-
return stages;
|
|
2212
|
-
}
|
|
2213
|
-
/**
|
|
2214
|
-
* Create map tasks for map-reduce pattern
|
|
2215
|
-
*
|
|
2216
|
-
* @param task - Original task
|
|
2217
|
-
* @returns Map tasks
|
|
2218
|
-
*/
|
|
2219
|
-
createMapTasks(task) {
|
|
2220
|
-
const mapTasks = [];
|
|
2221
|
-
const items = task.input.files ?? [task.input.parameters];
|
|
2222
|
-
for (let i = 0; i < items.length; i++) {
|
|
2223
|
-
const item = items[i];
|
|
2224
|
-
mapTasks.push(this.createSubtask(task, {
|
|
2225
|
-
name: `${task.name} - Map ${i + 1}`,
|
|
2226
|
-
description: `Process ${typeof item === "string" ? item : `item ${i + 1}`}`,
|
|
2227
|
-
capabilities: fromAgentCapabilities$1(task.requiredCapabilities)
|
|
2228
|
-
}, i));
|
|
2229
|
-
}
|
|
2230
|
-
return mapTasks;
|
|
2231
|
-
}
|
|
2232
|
-
/**
|
|
2233
|
-
* Create reduce task for map-reduce pattern
|
|
2234
|
-
*
|
|
2235
|
-
* @param task - Original task
|
|
2236
|
-
* @param mapTaskCount - Number of map tasks
|
|
2237
|
-
* @returns Reduce task
|
|
2238
|
-
*/
|
|
2239
|
-
createReduceTask(task, mapTaskCount) {
|
|
2240
|
-
return this.createSubtask(task, {
|
|
2241
|
-
name: `${task.name} - Reduce`,
|
|
2242
|
-
description: `Aggregate results from ${mapTaskCount} map tasks`,
|
|
2243
|
-
capabilities: ["code-analysis"]
|
|
2244
|
-
}, mapTaskCount);
|
|
2245
|
-
}
|
|
2246
|
-
/**
|
|
2247
|
-
* Create a subtask from a task and step definition
|
|
2248
|
-
*
|
|
2249
|
-
* @param parentTask - Parent task
|
|
2250
|
-
* @param step - Step definition object
|
|
2251
|
-
* @param step.name - Step name
|
|
2252
|
-
* @param step.description - Step description
|
|
2253
|
-
* @param step.capabilities - Required agent capabilities
|
|
2254
|
-
* @param index - Step index
|
|
2255
|
-
* @returns Created subtask
|
|
2256
|
-
*/
|
|
2257
|
-
createSubtask(parentTask, step, index) {
|
|
2258
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2259
|
-
return {
|
|
2260
|
-
id: nanoid(),
|
|
2261
|
-
name: step.name,
|
|
2262
|
-
description: step.description,
|
|
2263
|
-
type: parentTask.type,
|
|
2264
|
-
priority: parentTask.priority,
|
|
2265
|
-
status: "pending",
|
|
2266
|
-
requiredCapabilities: toAgentCapabilities$1(step.capabilities),
|
|
2267
|
-
input: {
|
|
2268
|
-
parameters: parentTask.input.parameters,
|
|
2269
|
-
files: parentTask.input.files,
|
|
2270
|
-
context: parentTask.input.context,
|
|
2271
|
-
instructions: parentTask.input.instructions,
|
|
2272
|
-
constraints: parentTask.input.constraints
|
|
2273
|
-
},
|
|
2274
|
-
dependencies: [],
|
|
2275
|
-
estimatedDuration: parentTask.estimatedDuration ? Math.floor(parentTask.estimatedDuration / 3) : void 0,
|
|
2276
|
-
maxRetries: parentTask.maxRetries,
|
|
2277
|
-
retryCount: 0,
|
|
2278
|
-
timeout: parentTask.timeout,
|
|
2279
|
-
metadata: {
|
|
2280
|
-
...parentTask.metadata,
|
|
2281
|
-
tags: [...parentTask.metadata.tags, "subtask"],
|
|
2282
|
-
custom: {
|
|
2283
|
-
...parentTask.metadata.custom,
|
|
2284
|
-
parentTaskId: parentTask.id,
|
|
2285
|
-
subtaskIndex: index
|
|
2286
|
-
}
|
|
2287
|
-
},
|
|
2288
|
-
createdAt: now,
|
|
2289
|
-
progress: 0,
|
|
2290
|
-
parentId: parentTask.id
|
|
2291
|
-
};
|
|
2292
|
-
}
|
|
2293
|
-
/**
|
|
2294
|
-
* Group capabilities by category
|
|
2295
|
-
*
|
|
2296
|
-
* @param capabilities - Capabilities to group
|
|
2297
|
-
* @returns Grouped capabilities
|
|
2298
|
-
*/
|
|
2299
|
-
groupCapabilities(capabilities) {
|
|
2300
|
-
const groups = /* @__PURE__ */ new Map();
|
|
2301
|
-
for (const capability of capabilities) {
|
|
2302
|
-
const category = capability.split("-")[0];
|
|
2303
|
-
if (!groups.has(category)) {
|
|
2304
|
-
groups.set(category, []);
|
|
2305
|
-
}
|
|
2306
|
-
groups.get(category).push(capability);
|
|
2307
|
-
}
|
|
2308
|
-
return groups;
|
|
2309
|
-
}
|
|
2310
|
-
/**
|
|
2311
|
-
* Detect additional dependencies between tasks
|
|
2312
|
-
*
|
|
2313
|
-
* @param subtasks - Subtasks to analyze
|
|
2314
|
-
* @param existingDeps - Existing dependencies
|
|
2315
|
-
* @returns Updated dependencies
|
|
2316
|
-
*/
|
|
2317
|
-
detectDependencies(subtasks, existingDeps) {
|
|
2318
|
-
const dependencies = [...existingDeps];
|
|
2319
|
-
for (let i = 0; i < subtasks.length; i++) {
|
|
2320
|
-
for (let j = i + 1; j < subtasks.length; j++) {
|
|
2321
|
-
const task1 = subtasks[i];
|
|
2322
|
-
const task2 = subtasks[j];
|
|
2323
|
-
if (this.hasDataDependency(task1, task2)) {
|
|
2324
|
-
const exists = dependencies.some(
|
|
2325
|
-
(dep) => dep.taskId === task1.id && subtasks[j].id === task2.id
|
|
2326
|
-
);
|
|
2327
|
-
if (!exists) {
|
|
2328
|
-
dependencies.push({
|
|
2329
|
-
taskId: task1.id,
|
|
2330
|
-
type: "data",
|
|
2331
|
-
required: false
|
|
2332
|
-
});
|
|
2333
|
-
}
|
|
2334
|
-
}
|
|
2335
|
-
}
|
|
2336
|
-
}
|
|
2337
|
-
return dependencies;
|
|
2338
|
-
}
|
|
2339
|
-
/**
|
|
2340
|
-
* Check if one task has a data dependency on another
|
|
2341
|
-
*
|
|
2342
|
-
* @param producer - Potential producer task
|
|
2343
|
-
* @param consumer - Potential consumer task
|
|
2344
|
-
* @returns Whether dependency exists
|
|
2345
|
-
*/
|
|
2346
|
-
hasDataDependency(producer, consumer) {
|
|
2347
|
-
const producerKeywords = producer.name.toLowerCase().split(/\s+/);
|
|
2348
|
-
const consumerDesc = consumer.description.toLowerCase();
|
|
2349
|
-
return producerKeywords.some((keyword) => consumerDesc.includes(keyword));
|
|
2350
|
-
}
|
|
2351
|
-
/**
|
|
2352
|
-
* Build execution graph from tasks and dependencies
|
|
2353
|
-
*
|
|
2354
|
-
* @param subtasks - Subtasks
|
|
2355
|
-
* @param dependencies - Task dependencies
|
|
2356
|
-
* @returns Execution graph
|
|
2357
|
-
*/
|
|
2358
|
-
buildExecutionGraph(subtasks, dependencies) {
|
|
2359
|
-
const nodes = [];
|
|
2360
|
-
const edges = [];
|
|
2361
|
-
for (const task of subtasks) {
|
|
2362
|
-
const incomingEdges = dependencies.filter((dep) => {
|
|
2363
|
-
const dependentTask = subtasks.find(
|
|
2364
|
-
(t) => t.dependencies.some((d) => d.taskId === dep.taskId)
|
|
2365
|
-
);
|
|
2366
|
-
return dependentTask?.id === task.id;
|
|
2367
|
-
}).map((dep) => dep.taskId);
|
|
2368
|
-
const outgoingEdges = dependencies.filter((dep) => dep.taskId === task.id).map((dep) => {
|
|
2369
|
-
const dependentTask = subtasks.find(
|
|
2370
|
-
(t) => t.dependencies.includes(dep)
|
|
2371
|
-
);
|
|
2372
|
-
return dependentTask?.id ?? "";
|
|
2373
|
-
}).filter((id) => id !== "");
|
|
2374
|
-
nodes.push({
|
|
2375
|
-
taskId: task.id,
|
|
2376
|
-
level: 0,
|
|
2377
|
-
// Will be calculated later
|
|
2378
|
-
isLeaf: outgoingEdges.length === 0,
|
|
2379
|
-
isRoot: incomingEdges.length === 0,
|
|
2380
|
-
incomingEdges,
|
|
2381
|
-
outgoingEdges
|
|
2382
|
-
});
|
|
2383
|
-
}
|
|
2384
|
-
for (const dep of dependencies) {
|
|
2385
|
-
const dependentTask = subtasks.find(
|
|
2386
|
-
(t) => t.dependencies.includes(dep)
|
|
2387
|
-
);
|
|
2388
|
-
if (dependentTask) {
|
|
2389
|
-
edges.push({
|
|
2390
|
-
id: nanoid(),
|
|
2391
|
-
from: dep.taskId,
|
|
2392
|
-
to: dependentTask.id,
|
|
2393
|
-
type: dep.type,
|
|
2394
|
-
weight: dep.required ? 1 : 0.5
|
|
2395
|
-
});
|
|
2396
|
-
}
|
|
2397
|
-
}
|
|
2398
|
-
this.calculateNodeLevels(nodes, edges);
|
|
2399
|
-
const stages = this.buildExecutionStages(nodes, subtasks);
|
|
2400
|
-
return { nodes, edges, stages };
|
|
2401
|
-
}
|
|
2402
|
-
/**
|
|
2403
|
-
* Calculate node levels in the graph
|
|
2404
|
-
*
|
|
2405
|
-
* @param nodes - Graph nodes
|
|
2406
|
-
* @param edges - Graph edges
|
|
2407
|
-
*/
|
|
2408
|
-
calculateNodeLevels(nodes, edges) {
|
|
2409
|
-
const visited = /* @__PURE__ */ new Set();
|
|
2410
|
-
const levels = /* @__PURE__ */ new Map();
|
|
2411
|
-
for (const node of nodes) {
|
|
2412
|
-
if (node.isRoot) {
|
|
2413
|
-
levels.set(node.taskId, 0);
|
|
2414
|
-
}
|
|
2415
|
-
}
|
|
2416
|
-
const queue = nodes.filter((n) => n.isRoot).map((n) => n.taskId);
|
|
2417
|
-
while (queue.length > 0) {
|
|
2418
|
-
const taskId = queue.shift();
|
|
2419
|
-
if (visited.has(taskId))
|
|
2420
|
-
continue;
|
|
2421
|
-
visited.add(taskId);
|
|
2422
|
-
const currentLevel = levels.get(taskId) ?? 0;
|
|
2423
|
-
const outgoingEdges = edges.filter((e) => e.from === taskId);
|
|
2424
|
-
for (const edge of outgoingEdges) {
|
|
2425
|
-
const newLevel = currentLevel + 1;
|
|
2426
|
-
const existingLevel = levels.get(edge.to) ?? -1;
|
|
2427
|
-
if (newLevel > existingLevel) {
|
|
2428
|
-
levels.set(edge.to, newLevel);
|
|
2429
|
-
}
|
|
2430
|
-
queue.push(edge.to);
|
|
2431
|
-
}
|
|
2432
|
-
}
|
|
2433
|
-
for (const node of nodes) {
|
|
2434
|
-
node.level = levels.get(node.taskId) ?? 0;
|
|
2435
|
-
}
|
|
2436
|
-
}
|
|
2437
|
-
/**
|
|
2438
|
-
* Build execution stages from graph nodes
|
|
2439
|
-
*
|
|
2440
|
-
* @param nodes - Graph nodes
|
|
2441
|
-
* @param subtasks - Subtasks
|
|
2442
|
-
* @returns Execution stages
|
|
2443
|
-
*/
|
|
2444
|
-
buildExecutionStages(nodes, subtasks) {
|
|
2445
|
-
const stages = [];
|
|
2446
|
-
const maxLevel = Math.max(...nodes.map((n) => n.level));
|
|
2447
|
-
for (let level = 0; level <= maxLevel; level++) {
|
|
2448
|
-
const stageTasks = nodes.filter((n) => n.level === level).map((n) => n.taskId);
|
|
2449
|
-
const estimatedDuration = Math.max(
|
|
2450
|
-
...stageTasks.map((taskId) => {
|
|
2451
|
-
const task = subtasks.find((t) => t.id === taskId);
|
|
2452
|
-
return task?.estimatedDuration ?? 0;
|
|
2453
|
-
})
|
|
2454
|
-
);
|
|
2455
|
-
stages.push({
|
|
2456
|
-
stage: level,
|
|
2457
|
-
tasks: stageTasks,
|
|
2458
|
-
estimatedDuration
|
|
2459
|
-
});
|
|
2460
|
-
}
|
|
2461
|
-
return stages;
|
|
2462
|
-
}
|
|
2463
|
-
/**
|
|
2464
|
-
* Optimize execution graph for better performance
|
|
2465
|
-
*
|
|
2466
|
-
* @param graph - Execution graph
|
|
2467
|
-
* @param subtasks - Subtasks
|
|
2468
|
-
*/
|
|
2469
|
-
optimizeExecutionGraph(graph, subtasks) {
|
|
2470
|
-
this.mergeSmallTasks(graph, subtasks);
|
|
2471
|
-
this.reorderTasksInStages(graph, subtasks);
|
|
2472
|
-
this.identifyCriticalPath(graph, subtasks);
|
|
2473
|
-
}
|
|
2474
|
-
/**
|
|
2475
|
-
* Merge small sequential tasks
|
|
2476
|
-
*
|
|
2477
|
-
* @param graph - Execution graph
|
|
2478
|
-
* @param subtasks - Subtasks
|
|
2479
|
-
*/
|
|
2480
|
-
mergeSmallTasks(graph, subtasks) {
|
|
2481
|
-
for (const stage of graph.stages) {
|
|
2482
|
-
if (stage.tasks.length === 1) {
|
|
2483
|
-
const task = subtasks.find((t) => t.id === stage.tasks[0]);
|
|
2484
|
-
if (task && (task.estimatedDuration ?? 0) < this.options.minTaskGranularity) {
|
|
2485
|
-
task.metadata.custom = {
|
|
2486
|
-
...task.metadata.custom,
|
|
2487
|
-
mergeable: true
|
|
2488
|
-
};
|
|
2489
|
-
}
|
|
2490
|
-
}
|
|
2491
|
-
}
|
|
2492
|
-
}
|
|
2493
|
-
/**
|
|
2494
|
-
* Reorder tasks within stages for load balancing
|
|
2495
|
-
*
|
|
2496
|
-
* @param graph - Execution graph
|
|
2497
|
-
* @param subtasks - Subtasks
|
|
2498
|
-
*/
|
|
2499
|
-
reorderTasksInStages(graph, subtasks) {
|
|
2500
|
-
for (const stage of graph.stages) {
|
|
2501
|
-
stage.tasks.sort((a, b) => {
|
|
2502
|
-
const taskA = subtasks.find((t) => t.id === a);
|
|
2503
|
-
const taskB = subtasks.find((t) => t.id === b);
|
|
2504
|
-
const durationA = taskA?.estimatedDuration ?? 0;
|
|
2505
|
-
const durationB = taskB?.estimatedDuration ?? 0;
|
|
2506
|
-
return durationB - durationA;
|
|
2507
|
-
});
|
|
2508
|
-
}
|
|
2509
|
-
}
|
|
2510
|
-
/**
|
|
2511
|
-
* Identify critical path in the execution graph
|
|
2512
|
-
*
|
|
2513
|
-
* @param graph - Execution graph
|
|
2514
|
-
* @param subtasks - Subtasks
|
|
2515
|
-
*/
|
|
2516
|
-
identifyCriticalPath(graph, subtasks) {
|
|
2517
|
-
const earliestStart = /* @__PURE__ */ new Map();
|
|
2518
|
-
for (const stage of graph.stages) {
|
|
2519
|
-
for (const taskId of stage.tasks) {
|
|
2520
|
-
const task = subtasks.find((t) => t.id === taskId);
|
|
2521
|
-
const node = graph.nodes.find((n) => n.taskId === taskId);
|
|
2522
|
-
if (!node || !task)
|
|
2523
|
-
continue;
|
|
2524
|
-
let maxPredecessorFinish = 0;
|
|
2525
|
-
for (const predId of node.incomingEdges) {
|
|
2526
|
-
const predTask = subtasks.find((t) => t.id === predId);
|
|
2527
|
-
const predStart = earliestStart.get(predId) ?? 0;
|
|
2528
|
-
const predDuration = predTask?.estimatedDuration ?? 0;
|
|
2529
|
-
maxPredecessorFinish = Math.max(maxPredecessorFinish, predStart + predDuration);
|
|
2530
|
-
}
|
|
2531
|
-
earliestStart.set(taskId, maxPredecessorFinish);
|
|
2532
|
-
}
|
|
2533
|
-
}
|
|
2534
|
-
for (const [taskId, _] of earliestStart) {
|
|
2535
|
-
const task = subtasks.find((t) => t.id === taskId);
|
|
2536
|
-
if (task) {
|
|
2537
|
-
task.metadata.custom = {
|
|
2538
|
-
...task.metadata.custom,
|
|
2539
|
-
onCriticalPath: true
|
|
2540
|
-
};
|
|
2541
|
-
}
|
|
2542
|
-
}
|
|
2543
|
-
}
|
|
2544
|
-
/**
|
|
2545
|
-
* Calculate estimated total duration
|
|
2546
|
-
*
|
|
2547
|
-
* @param _subtasks - Subtasks (unused but kept for API consistency)
|
|
2548
|
-
* @param graph - Execution graph
|
|
2549
|
-
* @returns Estimated duration in milliseconds
|
|
2550
|
-
*/
|
|
2551
|
-
calculateEstimatedDuration(_subtasks, graph) {
|
|
2552
|
-
return graph.stages.reduce((total, stage) => {
|
|
2553
|
-
return total + stage.estimatedDuration;
|
|
2554
|
-
}, 0);
|
|
2555
|
-
}
|
|
2556
|
-
}
|
|
2557
|
-
|
|
2558
|
-
function fromAgentCapabilities(capabilities) {
|
|
2559
|
-
return capabilities.map((cap) => cap.id);
|
|
2560
|
-
}
|
|
2561
|
-
function toAgentCapabilities(capabilities) {
|
|
2562
|
-
return capabilities.map((id) => ({
|
|
2563
|
-
id,
|
|
2564
|
-
name: id,
|
|
2565
|
-
model: "sonnet",
|
|
2566
|
-
specialties: [id],
|
|
2567
|
-
strength: 0.8,
|
|
2568
|
-
costFactor: 1
|
|
2569
|
-
}));
|
|
2570
|
-
}
|
|
2571
|
-
class BrainOrchestrator extends EventEmitter {
|
|
2572
|
-
config;
|
|
2573
|
-
taskDecomposer;
|
|
2574
|
-
resultAggregator;
|
|
2575
|
-
state;
|
|
2576
|
-
availableAgents;
|
|
2577
|
-
forkManager;
|
|
2578
|
-
dispatcher;
|
|
2579
|
-
constructor(config = {}) {
|
|
2580
|
-
super();
|
|
2581
|
-
this.config = {
|
|
2582
|
-
maxConcurrentTasks: config.maxConcurrentTasks ?? 10,
|
|
2583
|
-
maxConcurrentAgents: config.maxConcurrentAgents ?? 5,
|
|
2584
|
-
defaultTaskTimeout: config.defaultTaskTimeout ?? 3e5,
|
|
2585
|
-
// 5 minutes
|
|
2586
|
-
defaultRetryCount: config.defaultRetryCount ?? 3,
|
|
2587
|
-
autoRetry: config.autoRetry ?? true,
|
|
2588
|
-
conflictResolutionStrategy: config.conflictResolutionStrategy ?? "highest-confidence",
|
|
2589
|
-
enableParallelExecution: config.enableParallelExecution ?? true,
|
|
2590
|
-
enableCaching: config.enableCaching ?? false,
|
|
2591
|
-
cacheTtl: config.cacheTtl ?? 36e5,
|
|
2592
|
-
// 1 hour
|
|
2593
|
-
verboseLogging: config.verboseLogging ?? false,
|
|
2594
|
-
custom: config.custom ?? {},
|
|
2595
|
-
// v3.8 options
|
|
2596
|
-
forkContextOptions: config.forkContextOptions ?? {},
|
|
2597
|
-
dispatcherOptions: config.dispatcherOptions ?? {},
|
|
2598
|
-
enableForkContext: config.enableForkContext ?? true,
|
|
2599
|
-
enableDispatcher: config.enableDispatcher ?? true
|
|
2600
|
-
};
|
|
2601
|
-
this.taskDecomposer = new TaskDecomposer({
|
|
2602
|
-
strategy: "hierarchical",
|
|
2603
|
-
maxDepth: 5,
|
|
2604
|
-
maxParallelTasks: this.config.maxConcurrentTasks,
|
|
2605
|
-
enableOptimization: true
|
|
2606
|
-
});
|
|
2607
|
-
this.resultAggregator = new ResultAggregator({
|
|
2608
|
-
defaultStrategy: this.config.conflictResolutionStrategy,
|
|
2609
|
-
autoDetectConflicts: true,
|
|
2610
|
-
enableValidation: true,
|
|
2611
|
-
enableMerging: true
|
|
2612
|
-
});
|
|
2613
|
-
this.state = {
|
|
2614
|
-
activeTasks: /* @__PURE__ */ new Map(),
|
|
2615
|
-
activeAgents: /* @__PURE__ */ new Map(),
|
|
2616
|
-
taskQueue: [],
|
|
2617
|
-
completedTasks: /* @__PURE__ */ new Map(),
|
|
2618
|
-
failedTasks: /* @__PURE__ */ new Map(),
|
|
2619
|
-
status: "idle",
|
|
2620
|
-
totalTasksProcessed: 0,
|
|
2621
|
-
metrics: this.createEmptyMetrics()
|
|
2622
|
-
};
|
|
2623
|
-
this.availableAgents = /* @__PURE__ */ new Map();
|
|
2624
|
-
this.forkManager = new AgentForkManager(this.config.forkContextOptions);
|
|
2625
|
-
this.setupForkManagerEvents();
|
|
2626
|
-
this.dispatcher = new AgentDispatcher(this.config.dispatcherOptions);
|
|
2627
|
-
}
|
|
2628
|
-
/**
|
|
2629
|
-
* Register an agent for use by the orchestrator
|
|
2630
|
-
*
|
|
2631
|
-
* @param role - Agent role
|
|
2632
|
-
* @param agent - Agent definition
|
|
2633
|
-
*/
|
|
2634
|
-
registerAgent(role, agent) {
|
|
2635
|
-
this.availableAgents.set(role, agent);
|
|
2636
|
-
this.log(`Registered agent: ${role}`);
|
|
2637
|
-
}
|
|
2638
|
-
/**
|
|
2639
|
-
* Unregister an agent
|
|
2640
|
-
*
|
|
2641
|
-
* @param role - Agent role
|
|
2642
|
-
*/
|
|
2643
|
-
unregisterAgent(role) {
|
|
2644
|
-
this.availableAgents.delete(role);
|
|
2645
|
-
this.log(`Unregistered agent: ${role}`);
|
|
2646
|
-
}
|
|
2647
|
-
/**
|
|
2648
|
-
* Execute a complex task through orchestration
|
|
2649
|
-
*
|
|
2650
|
-
* @param task - Root task to execute
|
|
2651
|
-
* @param strategy - Optional decomposition strategy
|
|
2652
|
-
* @returns Orchestration result
|
|
2653
|
-
*/
|
|
2654
|
-
async execute(task, strategy) {
|
|
2655
|
-
const sessionId = `orchestration-${nanoid()}`;
|
|
2656
|
-
executionTracer.startSession(sessionId);
|
|
2657
|
-
executionTracer.logEvent("agent-start", {
|
|
2658
|
-
task: task.name,
|
|
2659
|
-
strategy: strategy || "auto"
|
|
2660
|
-
});
|
|
2661
|
-
taskPersistence.saveSession(sessionId, {
|
|
2662
|
-
rootTask: task.name,
|
|
2663
|
-
strategy: strategy || "auto"
|
|
2664
|
-
});
|
|
2665
|
-
taskPersistence.saveTask(task, sessionId);
|
|
2666
|
-
const context = await contextLoader.load({
|
|
2667
|
-
projectRoot: process.cwd(),
|
|
2668
|
-
task,
|
|
2669
|
-
layers: ["project", "domain", "task"],
|
|
2670
|
-
tokenBudget: 4e3
|
|
2671
|
-
// ~L1 depth, keeps orchestration context lean
|
|
2672
|
-
});
|
|
2673
|
-
task.metadata = task.metadata || { tags: [] };
|
|
2674
|
-
if (!task.metadata.custom) {
|
|
2675
|
-
task.metadata.custom = {};
|
|
2676
|
-
}
|
|
2677
|
-
task.metadata.custom.context = contextLoader.formatForLLM(context);
|
|
2678
|
-
const intel = SessionIntelligence.getInstance();
|
|
2679
|
-
intel.recordMessage("user", task.name);
|
|
2680
|
-
try {
|
|
2681
|
-
this.state.status = "planning";
|
|
2682
|
-
intel.updatePhase("exploring");
|
|
2683
|
-
this.log(`Starting orchestration for task: ${task.name}`);
|
|
2684
|
-
executionTracer.logDecision("orchestrator", `Planning task: ${task.name}`);
|
|
2685
|
-
const plan = await this.createPlan(task, strategy);
|
|
2686
|
-
this.emit("plan:created", plan);
|
|
2687
|
-
this.state.status = "executing";
|
|
2688
|
-
intel.updatePhase("executing");
|
|
2689
|
-
this.state.currentPlan = plan;
|
|
2690
|
-
this.state.startTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
2691
|
-
this.emit("plan:started", plan.id);
|
|
2692
|
-
const result = await this.executePlan(plan);
|
|
2693
|
-
this.state.status = "idle";
|
|
2694
|
-
intel.updatePhase("reviewing");
|
|
2695
|
-
this.emit("plan:completed", result);
|
|
2696
|
-
executionTracer.logAgentEnd("orchestrator", { success: true });
|
|
2697
|
-
executionTracer.endSession(sessionId);
|
|
2698
|
-
taskPersistence.updateTaskStatus(task.id, "completed", result);
|
|
2699
|
-
return result;
|
|
2700
|
-
} catch (error) {
|
|
2701
|
-
this.state.status = "error";
|
|
2702
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
2703
|
-
this.emit("error", err);
|
|
2704
|
-
executionTracer.logError(err, "orchestrator");
|
|
2705
|
-
executionTracer.endSession(sessionId);
|
|
2706
|
-
taskPersistence.updateTaskStatus(task.id, "failed", void 0, err);
|
|
2707
|
-
return this.createFailedResult(task, err);
|
|
2708
|
-
}
|
|
2709
|
-
}
|
|
2710
|
-
/**
|
|
2711
|
-
* Create an orchestration plan from a task
|
|
2712
|
-
*
|
|
2713
|
-
* @param task - Root task
|
|
2714
|
-
* @param strategy - Decomposition strategy
|
|
2715
|
-
* @returns Orchestration plan
|
|
2716
|
-
*/
|
|
2717
|
-
async createPlan(task, strategy) {
|
|
2718
|
-
this.log(`Creating orchestration plan for: ${task.name}`);
|
|
2719
|
-
const decomposition = await this.taskDecomposer.decompose(task, strategy);
|
|
2720
|
-
const requiredAgents = this.analyzeRequiredAgents(decomposition.subtasks);
|
|
2721
|
-
const executionGraph = decomposition.executionGraph;
|
|
2722
|
-
const estimatedDuration = decomposition.estimatedDuration;
|
|
2723
|
-
const plan = {
|
|
2724
|
-
id: nanoid(),
|
|
2725
|
-
name: `Plan: ${task.name}`,
|
|
2726
|
-
description: `Orchestration plan for ${task.name}`,
|
|
2727
|
-
rootTask: task,
|
|
2728
|
-
tasks: decomposition.subtasks,
|
|
2729
|
-
executionGraph,
|
|
2730
|
-
requiredAgents,
|
|
2731
|
-
decompositionStrategy: decomposition.strategy,
|
|
2732
|
-
estimatedDuration,
|
|
2733
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2734
|
-
metadata: {
|
|
2735
|
-
originalTaskId: task.id,
|
|
2736
|
-
decompositionMetadata: decomposition.metadata
|
|
2737
|
-
}
|
|
2738
|
-
};
|
|
2739
|
-
return plan;
|
|
2740
|
-
}
|
|
2741
|
-
/**
|
|
2742
|
-
* Execute an orchestration plan
|
|
2743
|
-
*
|
|
2744
|
-
* @param plan - Orchestration plan to execute
|
|
2745
|
-
* @returns Orchestration result
|
|
2746
|
-
*/
|
|
2747
|
-
async executePlan(plan) {
|
|
2748
|
-
const startTime = Date.now();
|
|
2749
|
-
const completed = [];
|
|
2750
|
-
const failed = [];
|
|
2751
|
-
const cancelled = [];
|
|
2752
|
-
const results = {};
|
|
2753
|
-
const errors = [];
|
|
2754
|
-
const warnings = [];
|
|
2755
|
-
this.log(`Executing plan: ${plan.id}`);
|
|
2756
|
-
for (const task of plan.tasks) {
|
|
2757
|
-
this.state.taskQueue.push(task);
|
|
2758
|
-
this.emit("task:created", task);
|
|
2759
|
-
}
|
|
2760
|
-
for (const stage of plan.executionGraph.stages) {
|
|
2761
|
-
const stageTasks = plan.tasks.filter((t) => stage.tasks.includes(t.id));
|
|
2762
|
-
const stagePromises = stageTasks.map(async (task) => {
|
|
2763
|
-
this.emit("task:started", task);
|
|
2764
|
-
task.status = "running";
|
|
2765
|
-
task.startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2766
|
-
try {
|
|
2767
|
-
const agent = this.selectAgentForTask(task);
|
|
2768
|
-
if (!agent) {
|
|
2769
|
-
throw new Error(`No available agent for task: ${task.name}`);
|
|
2770
|
-
}
|
|
2771
|
-
task.assignedAgentId = agent.id;
|
|
2772
|
-
this.emit("agent:assigned", agent, task);
|
|
2773
|
-
await this.executeTask(agent, task);
|
|
2774
|
-
task.status = "completed";
|
|
2775
|
-
task.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2776
|
-
task.actualDuration = Date.now() - new Date(task.startedAt).getTime();
|
|
2777
|
-
task.progress = 100;
|
|
2778
|
-
completed.push(task.id);
|
|
2779
|
-
this.emit("task:completed", task);
|
|
2780
|
-
this.updateAgentMetrics(agent, task, true);
|
|
2781
|
-
if (task.output) {
|
|
2782
|
-
results[task.id] = task.output;
|
|
2783
|
-
}
|
|
2784
|
-
return { taskId: task.id, success: true };
|
|
2785
|
-
} catch (error) {
|
|
2786
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
2787
|
-
task.status = "failed";
|
|
2788
|
-
task.error = {
|
|
2789
|
-
code: "TASK_EXECUTION_FAILED",
|
|
2790
|
-
message: err.message,
|
|
2791
|
-
stack: err.stack,
|
|
2792
|
-
recoverable: this.config.autoRetry && task.retryCount < task.maxRetries
|
|
2793
|
-
};
|
|
2794
|
-
task.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2795
|
-
failed.push(task.id);
|
|
2796
|
-
this.emit("task:failed", task, task.error);
|
|
2797
|
-
if (task.error) {
|
|
2798
|
-
errors.push(task.error);
|
|
2799
|
-
}
|
|
2800
|
-
if (this.config.autoRetry && task.retryCount < task.maxRetries && task.error?.recoverable) {
|
|
2801
|
-
task.retryCount++;
|
|
2802
|
-
task.status = "pending";
|
|
2803
|
-
warnings.push(`Retrying task ${task.name} (attempt ${task.retryCount}/${task.maxRetries})`);
|
|
2804
|
-
return { taskId: task.id, success: false, retry: true };
|
|
2805
|
-
}
|
|
2806
|
-
return { taskId: task.id, success: false };
|
|
2807
|
-
}
|
|
2808
|
-
});
|
|
2809
|
-
await Promise.all(stagePromises);
|
|
2810
|
-
if (this.hasCriticalFailures(stageTasks)) {
|
|
2811
|
-
this.log("Critical failure detected, cancelling remaining tasks");
|
|
2812
|
-
for (const remainingTask of plan.tasks.filter((t) => t.status === "pending")) {
|
|
2813
|
-
remainingTask.status = "cancelled";
|
|
2814
|
-
cancelled.push(remainingTask.id);
|
|
2815
|
-
this.emit("task:cancelled", remainingTask);
|
|
2816
|
-
}
|
|
2817
|
-
break;
|
|
2818
|
-
}
|
|
2819
|
-
}
|
|
2820
|
-
const duration = Date.now() - startTime;
|
|
2821
|
-
const metrics = this.calculateMetrics(plan, completed, failed, cancelled, duration);
|
|
2822
|
-
const status = this.determineStatus(completed, failed, cancelled, plan.tasks.length);
|
|
2823
|
-
const aggregationResult = await this.resultAggregator.aggregate(
|
|
2824
|
-
plan.tasks.filter((t) => t.output !== void 0)
|
|
2825
|
-
);
|
|
2826
|
-
const finalResults = {};
|
|
2827
|
-
for (const task of plan.tasks) {
|
|
2828
|
-
if (task.output) {
|
|
2829
|
-
finalResults[task.id] = task.output;
|
|
2830
|
-
}
|
|
2831
|
-
}
|
|
2832
|
-
if (aggregationResult.output) {
|
|
2833
|
-
finalResults._aggregated = aggregationResult.output;
|
|
2834
|
-
}
|
|
2835
|
-
return {
|
|
2836
|
-
planId: plan.id,
|
|
2837
|
-
success: status === "completed",
|
|
2838
|
-
status,
|
|
2839
|
-
completedTasks: completed,
|
|
2840
|
-
failedTasks: failed,
|
|
2841
|
-
cancelledTasks: cancelled,
|
|
2842
|
-
results: finalResults,
|
|
2843
|
-
metrics,
|
|
2844
|
-
errors,
|
|
2845
|
-
warnings,
|
|
2846
|
-
startedAt: new Date(startTime).toISOString(),
|
|
2847
|
-
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2848
|
-
duration
|
|
2849
|
-
};
|
|
2850
|
-
}
|
|
2851
|
-
/**
|
|
2852
|
-
* Select an agent for a task
|
|
2853
|
-
*
|
|
2854
|
-
* @param task - Task to execute
|
|
2855
|
-
* @returns Selected agent instance or undefined
|
|
2856
|
-
*/
|
|
2857
|
-
selectAgentForTask(task) {
|
|
2858
|
-
const candidates = [];
|
|
2859
|
-
const agentEntries = Array.from(this.availableAgents.entries());
|
|
2860
|
-
for (const [role, agent] of agentEntries) {
|
|
2861
|
-
const requiredCaps = fromAgentCapabilities(task.requiredCapabilities);
|
|
2862
|
-
const hasCapabilities = requiredCaps.every(
|
|
2863
|
-
(cap) => agent.definition.capabilities.includes(cap)
|
|
2864
|
-
);
|
|
2865
|
-
if (!hasCapabilities)
|
|
2866
|
-
continue;
|
|
2867
|
-
let instance = Array.from(this.state.activeAgents.values()).find(
|
|
2868
|
-
(a) => a.role === role && a.status === "idle"
|
|
2869
|
-
);
|
|
2870
|
-
if (!instance && this.state.activeAgents.size < this.config.maxConcurrentAgents) {
|
|
2871
|
-
instance = this.createAgentInstance(role, agent);
|
|
2872
|
-
}
|
|
2873
|
-
if (instance && instance.status === "idle") {
|
|
2874
|
-
candidates.push(instance);
|
|
2875
|
-
}
|
|
2876
|
-
}
|
|
2877
|
-
if (candidates.length === 0) {
|
|
2878
|
-
return void 0;
|
|
2879
|
-
}
|
|
2880
|
-
const criteria = {
|
|
2881
|
-
requiredCapabilities: task.requiredCapabilities,
|
|
2882
|
-
strategy: "best-fit"
|
|
2883
|
-
};
|
|
2884
|
-
const selected = this.selectBestAgent(candidates, criteria);
|
|
2885
|
-
return selected;
|
|
2886
|
-
}
|
|
2887
|
-
/**
|
|
2888
|
-
* Execute a task on an agent
|
|
2889
|
-
*
|
|
2890
|
-
* @param agent - Agent instance
|
|
2891
|
-
* @param task - Task to execute
|
|
2892
|
-
*/
|
|
2893
|
-
async executeTask(agent, task) {
|
|
2894
|
-
agent.status = "busy";
|
|
2895
|
-
agent.currentTask = task;
|
|
2896
|
-
agent.lastActivityAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2897
|
-
this.state.activeTasks.set(task.id, task);
|
|
2898
|
-
await this.sleep(100);
|
|
2899
|
-
task.output = {
|
|
2900
|
-
data: {
|
|
2901
|
-
message: `Task ${task.name} completed by ${agent.role}`,
|
|
2902
|
-
agentId: agent.id
|
|
2903
|
-
},
|
|
2904
|
-
confidence: 0.9
|
|
2905
|
-
};
|
|
2906
|
-
agent.status = "idle";
|
|
2907
|
-
agent.currentTask = void 0;
|
|
2908
|
-
this.state.activeTasks.delete(task.id);
|
|
2909
|
-
}
|
|
2910
|
-
/**
|
|
2911
|
-
* Select best agent from candidates
|
|
2912
|
-
*
|
|
2913
|
-
* @param candidates - Candidate agents
|
|
2914
|
-
* @param criteria - Selection criteria
|
|
2915
|
-
* @returns Selected agent
|
|
2916
|
-
*/
|
|
2917
|
-
selectBestAgent(candidates, criteria) {
|
|
2918
|
-
switch (criteria.strategy) {
|
|
2919
|
-
case "best-fit":
|
|
2920
|
-
return candidates.reduce(
|
|
2921
|
-
(best, current) => current.metrics.successRate > best.metrics.successRate ? current : best
|
|
2922
|
-
);
|
|
2923
|
-
case "least-loaded":
|
|
2924
|
-
return candidates.reduce(
|
|
2925
|
-
(best, current) => current.taskHistory.length < best.taskHistory.length ? current : best
|
|
2926
|
-
);
|
|
2927
|
-
case "fastest":
|
|
2928
|
-
return candidates.reduce(
|
|
2929
|
-
(best, current) => current.metrics.avgTaskDuration < best.metrics.avgTaskDuration ? current : best
|
|
2930
|
-
);
|
|
2931
|
-
case "round-robin":
|
|
2932
|
-
case "random":
|
|
2933
|
-
default:
|
|
2934
|
-
return candidates[Math.floor(Math.random() * candidates.length)];
|
|
2935
|
-
}
|
|
2936
|
-
}
|
|
2937
|
-
/**
|
|
2938
|
-
* Create an agent instance
|
|
2939
|
-
*
|
|
2940
|
-
* @param role - Agent role
|
|
2941
|
-
* @param agent - Agent definition
|
|
2942
|
-
* @returns Agent instance
|
|
2943
|
-
*/
|
|
2944
|
-
createAgentInstance(role, agent) {
|
|
2945
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2946
|
-
const instance = {
|
|
2947
|
-
id: nanoid(),
|
|
2948
|
-
role,
|
|
2949
|
-
agent,
|
|
2950
|
-
status: "idle",
|
|
2951
|
-
taskHistory: [],
|
|
2952
|
-
capabilities: toAgentCapabilities(agent.definition.capabilities),
|
|
2953
|
-
metrics: {
|
|
2954
|
-
tasksExecuted: 0,
|
|
2955
|
-
tasksSucceeded: 0,
|
|
2956
|
-
tasksFailed: 0,
|
|
2957
|
-
avgTaskDuration: 0,
|
|
2958
|
-
successRate: 0,
|
|
2959
|
-
totalExecutionTime: 0,
|
|
2960
|
-
avgConfidence: 0,
|
|
2961
|
-
lastUpdated: now
|
|
2962
|
-
},
|
|
2963
|
-
createdAt: now,
|
|
2964
|
-
config: {
|
|
2965
|
-
maxConcurrentTasks: 1,
|
|
2966
|
-
taskTimeout: this.config.defaultTaskTimeout,
|
|
2967
|
-
verboseLogging: this.config.verboseLogging
|
|
2968
|
-
}
|
|
2969
|
-
};
|
|
2970
|
-
this.state.activeAgents.set(instance.id, instance);
|
|
2971
|
-
this.emit("agent:created", instance);
|
|
2972
|
-
return instance;
|
|
2973
|
-
}
|
|
2974
|
-
/**
|
|
2975
|
-
* Update agent metrics after task execution
|
|
2976
|
-
*
|
|
2977
|
-
* @param agent - Agent instance
|
|
2978
|
-
* @param task - Executed task
|
|
2979
|
-
* @param success - Whether task succeeded
|
|
2980
|
-
*/
|
|
2981
|
-
updateAgentMetrics(agent, task, success) {
|
|
2982
|
-
const metrics = agent.metrics;
|
|
2983
|
-
metrics.tasksExecuted++;
|
|
2984
|
-
if (success) {
|
|
2985
|
-
metrics.tasksSucceeded++;
|
|
2986
|
-
} else {
|
|
2987
|
-
metrics.tasksFailed++;
|
|
2988
|
-
}
|
|
2989
|
-
metrics.successRate = metrics.tasksSucceeded / metrics.tasksExecuted;
|
|
2990
|
-
if (task.actualDuration) {
|
|
2991
|
-
metrics.totalExecutionTime += task.actualDuration;
|
|
2992
|
-
metrics.avgTaskDuration = metrics.totalExecutionTime / metrics.tasksExecuted;
|
|
2993
|
-
}
|
|
2994
|
-
if (task.output?.confidence) {
|
|
2995
|
-
const totalConfidence = metrics.avgConfidence * (metrics.tasksExecuted - 1) + task.output.confidence;
|
|
2996
|
-
metrics.avgConfidence = totalConfidence / metrics.tasksExecuted;
|
|
2997
|
-
}
|
|
2998
|
-
metrics.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
2999
|
-
agent.taskHistory.push({
|
|
3000
|
-
taskId: task.id,
|
|
3001
|
-
taskName: task.name,
|
|
3002
|
-
status: task.status,
|
|
3003
|
-
startedAt: task.startedAt,
|
|
3004
|
-
completedAt: task.completedAt,
|
|
3005
|
-
duration: task.actualDuration,
|
|
3006
|
-
success,
|
|
3007
|
-
error: task.error?.message
|
|
3008
|
-
});
|
|
3009
|
-
}
|
|
3010
|
-
/**
|
|
3011
|
-
* Analyze required agents for tasks
|
|
3012
|
-
*
|
|
3013
|
-
* @param tasks - Tasks to analyze
|
|
3014
|
-
* @returns Agent requirements
|
|
3015
|
-
*/
|
|
3016
|
-
analyzeRequiredAgents(tasks) {
|
|
3017
|
-
const capabilityGroups = /* @__PURE__ */ new Map();
|
|
3018
|
-
for (const task of tasks) {
|
|
3019
|
-
const key = task.requiredCapabilities.sort().join(",");
|
|
3020
|
-
if (!capabilityGroups.has(key)) {
|
|
3021
|
-
capabilityGroups.set(key, task.requiredCapabilities);
|
|
3022
|
-
}
|
|
3023
|
-
}
|
|
3024
|
-
return Array.from(capabilityGroups.values()).map((capabilities) => ({
|
|
3025
|
-
capabilities,
|
|
3026
|
-
minInstances: 1,
|
|
3027
|
-
maxInstances: this.config.maxConcurrentAgents
|
|
3028
|
-
}));
|
|
3029
|
-
}
|
|
3030
|
-
/**
|
|
3031
|
-
* Check if there are critical failures
|
|
3032
|
-
*
|
|
3033
|
-
* @param tasks - Tasks to check
|
|
3034
|
-
* @returns Whether there are critical failures
|
|
3035
|
-
*/
|
|
3036
|
-
hasCriticalFailures(tasks) {
|
|
3037
|
-
return tasks.some((t) => t.status === "failed" && t.priority === "critical");
|
|
3038
|
-
}
|
|
3039
|
-
/**
|
|
3040
|
-
* Calculate orchestration metrics
|
|
3041
|
-
*
|
|
3042
|
-
* @param plan - Orchestration plan
|
|
3043
|
-
* @param completed - Completed task IDs
|
|
3044
|
-
* @param failed - Failed task IDs
|
|
3045
|
-
* @param cancelled - Cancelled task IDs
|
|
3046
|
-
* @param duration - Total duration
|
|
3047
|
-
* @returns Metrics
|
|
3048
|
-
*/
|
|
3049
|
-
calculateMetrics(plan, completed, failed, cancelled, duration) {
|
|
3050
|
-
const totalTasks = plan.tasks.length;
|
|
3051
|
-
const tasksCompleted = completed.length;
|
|
3052
|
-
const tasksFailed = failed.length;
|
|
3053
|
-
const tasksCancelled = cancelled.length;
|
|
3054
|
-
const completedTasks = plan.tasks.filter((t) => completed.includes(t.id));
|
|
3055
|
-
const avgTaskDuration = completedTasks.length > 0 ? completedTasks.reduce((sum, t) => sum + (t.actualDuration ?? 0), 0) / completedTasks.length : 0;
|
|
3056
|
-
const parallelEfficiency = plan.estimatedDuration > 0 ? Math.min(plan.estimatedDuration / duration, 1) : 0;
|
|
3057
|
-
const agentUtilization = this.state.activeAgents.size > 0 ? this.state.activeTasks.size / this.state.activeAgents.size : 0;
|
|
3058
|
-
return {
|
|
3059
|
-
totalTasks,
|
|
3060
|
-
tasksCompleted,
|
|
3061
|
-
tasksFailed,
|
|
3062
|
-
tasksCancelled,
|
|
3063
|
-
successRate: totalTasks > 0 ? tasksCompleted / totalTasks : 0,
|
|
3064
|
-
avgTaskDuration,
|
|
3065
|
-
totalExecutionTime: duration,
|
|
3066
|
-
parallelEfficiency,
|
|
3067
|
-
agentUtilization
|
|
3068
|
-
};
|
|
3069
|
-
}
|
|
3070
|
-
/**
|
|
3071
|
-
* Determine overall orchestration status
|
|
3072
|
-
*
|
|
3073
|
-
* @param completed - Completed task count
|
|
3074
|
-
* @param failed - Failed task count
|
|
3075
|
-
* @param cancelled - Cancelled task count
|
|
3076
|
-
* @param total - Total task count
|
|
3077
|
-
* @returns Status
|
|
3078
|
-
*/
|
|
3079
|
-
determineStatus(completed, failed, cancelled, total) {
|
|
3080
|
-
if (completed.length === total) {
|
|
3081
|
-
return "completed";
|
|
3082
|
-
}
|
|
3083
|
-
if (failed.length === total) {
|
|
3084
|
-
return "failed";
|
|
3085
|
-
}
|
|
3086
|
-
if (cancelled.length === total) {
|
|
3087
|
-
return "cancelled";
|
|
3088
|
-
}
|
|
3089
|
-
return "partial";
|
|
3090
|
-
}
|
|
3091
|
-
/**
|
|
3092
|
-
* Create empty metrics
|
|
3093
|
-
*
|
|
3094
|
-
* @returns Empty metrics
|
|
3095
|
-
*/
|
|
3096
|
-
createEmptyMetrics() {
|
|
3097
|
-
return {
|
|
3098
|
-
totalTasks: 0,
|
|
3099
|
-
tasksCompleted: 0,
|
|
3100
|
-
tasksFailed: 0,
|
|
3101
|
-
tasksCancelled: 0,
|
|
3102
|
-
successRate: 0,
|
|
3103
|
-
avgTaskDuration: 0,
|
|
3104
|
-
totalExecutionTime: 0,
|
|
3105
|
-
parallelEfficiency: 0,
|
|
3106
|
-
agentUtilization: 0
|
|
3107
|
-
};
|
|
3108
|
-
}
|
|
3109
|
-
/**
|
|
3110
|
-
* Create failed orchestration result
|
|
3111
|
-
*
|
|
3112
|
-
* @param task - Root task
|
|
3113
|
-
* @param error - Error that occurred
|
|
3114
|
-
* @returns Failed result
|
|
3115
|
-
*/
|
|
3116
|
-
createFailedResult(task, error) {
|
|
3117
|
-
return {
|
|
3118
|
-
planId: "failed",
|
|
3119
|
-
success: false,
|
|
3120
|
-
status: "failed",
|
|
3121
|
-
completedTasks: [],
|
|
3122
|
-
failedTasks: [task.id],
|
|
3123
|
-
cancelledTasks: [],
|
|
3124
|
-
results: {},
|
|
3125
|
-
metrics: this.createEmptyMetrics(),
|
|
3126
|
-
errors: [{
|
|
3127
|
-
code: "ORCHESTRATION_FAILED",
|
|
3128
|
-
message: error.message,
|
|
3129
|
-
stack: error.stack,
|
|
3130
|
-
recoverable: false
|
|
3131
|
-
}],
|
|
3132
|
-
warnings: [],
|
|
3133
|
-
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3134
|
-
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3135
|
-
duration: 0
|
|
3136
|
-
};
|
|
3137
|
-
}
|
|
3138
|
-
/**
|
|
3139
|
-
* Get current orchestrator state
|
|
3140
|
-
*
|
|
3141
|
-
* @returns Current state
|
|
3142
|
-
*/
|
|
3143
|
-
getState() {
|
|
3144
|
-
return { ...this.state };
|
|
3145
|
-
}
|
|
3146
|
-
/**
|
|
3147
|
-
* Pause orchestration
|
|
3148
|
-
*/
|
|
3149
|
-
pause() {
|
|
3150
|
-
if (this.state.status === "executing") {
|
|
3151
|
-
this.state.status = "paused";
|
|
3152
|
-
this.log("Orchestration paused");
|
|
3153
|
-
}
|
|
3154
|
-
}
|
|
3155
|
-
/**
|
|
3156
|
-
* Resume orchestration
|
|
3157
|
-
*/
|
|
3158
|
-
resume() {
|
|
3159
|
-
if (this.state.status === "paused") {
|
|
3160
|
-
this.state.status = "executing";
|
|
3161
|
-
this.log("Orchestration resumed");
|
|
3162
|
-
}
|
|
3163
|
-
}
|
|
3164
|
-
/**
|
|
3165
|
-
* Cancel orchestration
|
|
3166
|
-
*/
|
|
3167
|
-
cancel() {
|
|
3168
|
-
this.state.status = "idle";
|
|
3169
|
-
const activeTaskValues = Array.from(this.state.activeTasks.values());
|
|
3170
|
-
for (const task of activeTaskValues) {
|
|
3171
|
-
task.status = "cancelled";
|
|
3172
|
-
this.emit("task:cancelled", task);
|
|
3173
|
-
}
|
|
3174
|
-
this.state.activeTasks.clear();
|
|
3175
|
-
this.log("Orchestration cancelled");
|
|
3176
|
-
}
|
|
3177
|
-
/**
|
|
3178
|
-
* Terminate all agents
|
|
3179
|
-
*/
|
|
3180
|
-
terminateAllAgents() {
|
|
3181
|
-
const activeAgentValues = Array.from(this.state.activeAgents.values());
|
|
3182
|
-
for (const agent of activeAgentValues) {
|
|
3183
|
-
agent.status = "terminated";
|
|
3184
|
-
this.emit("agent:terminated", agent);
|
|
3185
|
-
}
|
|
3186
|
-
this.state.activeAgents.clear();
|
|
3187
|
-
this.log("All agents terminated");
|
|
3188
|
-
}
|
|
3189
|
-
/**
|
|
3190
|
-
* Log message if verbose logging is enabled
|
|
3191
|
-
*
|
|
3192
|
-
* @param message - Message to log
|
|
3193
|
-
*/
|
|
3194
|
-
log(message) {
|
|
3195
|
-
if (this.config.verboseLogging) {
|
|
3196
|
-
console.log(`[BrainOrchestrator] ${message}`);
|
|
3197
|
-
}
|
|
3198
|
-
}
|
|
3199
|
-
/**
|
|
3200
|
-
* Sleep for specified duration
|
|
3201
|
-
*
|
|
3202
|
-
* @param ms - Duration in milliseconds
|
|
3203
|
-
*/
|
|
3204
|
-
sleep(ms) {
|
|
3205
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3206
|
-
}
|
|
3207
|
-
// ========================================================================
|
|
3208
|
-
// FORK CONTEXT METHODS (v3.8)
|
|
3209
|
-
// ========================================================================
|
|
3210
|
-
/**
|
|
3211
|
-
* Execute a task in a fork context
|
|
3212
|
-
*
|
|
3213
|
-
* Creates an isolated sub-agent context for executing a skill-based task.
|
|
3214
|
-
*
|
|
3215
|
-
* @param skill - Skill file with fork configuration
|
|
3216
|
-
* @param task - Task to execute
|
|
3217
|
-
* @param executeFn - Execution function
|
|
3218
|
-
* @returns Fork context result
|
|
3219
|
-
*/
|
|
3220
|
-
async executeInForkContext(skill, task, executeFn) {
|
|
3221
|
-
if (!this.config.enableForkContext) {
|
|
3222
|
-
throw new Error("Fork context execution is disabled");
|
|
3223
|
-
}
|
|
3224
|
-
this.log(`Executing task in fork context: ${task.name} (skill: ${skill.metadata.name})`);
|
|
3225
|
-
const fork = this.forkManager.createFork(skill);
|
|
3226
|
-
this.emit("fork:created", fork.id, skill);
|
|
3227
|
-
const result = await this.forkManager.executeFork(fork.id, task, executeFn);
|
|
3228
|
-
if (result.success) {
|
|
3229
|
-
this.emit("fork:completed", fork.id, result);
|
|
3230
|
-
} else {
|
|
3231
|
-
this.emit("fork:failed", fork.id, result.error || "Unknown error");
|
|
3232
|
-
}
|
|
3233
|
-
return result;
|
|
3234
|
-
}
|
|
3235
|
-
/**
|
|
3236
|
-
* Execute multiple tasks in parallel fork contexts
|
|
3237
|
-
*
|
|
3238
|
-
* @param execution - Parallel execution configuration
|
|
3239
|
-
* @param executeFn - Execution function
|
|
3240
|
-
* @returns Parallel execution result
|
|
3241
|
-
*/
|
|
3242
|
-
async executeParallelForks(execution, executeFn) {
|
|
3243
|
-
this.log(`Executing ${execution.tasks.length} parallel forks`);
|
|
3244
|
-
this.emit("parallel:started", execution.id);
|
|
3245
|
-
try {
|
|
3246
|
-
const result = await this.dispatcher.dispatchParallel(execution, async (config) => {
|
|
3247
|
-
const forkConfig = {
|
|
3248
|
-
id: nanoid(),
|
|
3249
|
-
sessionId: config.sessionId || nanoid(),
|
|
3250
|
-
skill: {
|
|
3251
|
-
metadata: {
|
|
3252
|
-
name: config.agentType,
|
|
3253
|
-
description: "",
|
|
3254
|
-
version: "1.0.0",
|
|
3255
|
-
category: "custom",
|
|
3256
|
-
triggers: [],
|
|
3257
|
-
use_when: []
|
|
3258
|
-
},
|
|
3259
|
-
content: "",
|
|
3260
|
-
filePath: ""
|
|
3261
|
-
},
|
|
3262
|
-
agentType: config.agentType,
|
|
3263
|
-
agentRole: config.agentRole,
|
|
3264
|
-
mode: config.mode,
|
|
3265
|
-
workingDirectory: config.workingDirectory,
|
|
3266
|
-
env: config.env,
|
|
3267
|
-
allowedTools: config.allowedTools,
|
|
3268
|
-
disallowedTools: config.disallowedTools,
|
|
3269
|
-
timeout: config.timeout
|
|
3270
|
-
};
|
|
3271
|
-
return executeFn(forkConfig);
|
|
3272
|
-
});
|
|
3273
|
-
this.emit("parallel:completed", execution.id, result);
|
|
3274
|
-
return result;
|
|
3275
|
-
} catch (error) {
|
|
3276
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3277
|
-
this.emit("parallel:failed", execution.id, errorMessage);
|
|
3278
|
-
return {
|
|
3279
|
-
id: execution.id,
|
|
3280
|
-
success: false,
|
|
3281
|
-
results: [],
|
|
3282
|
-
durationMs: 0,
|
|
3283
|
-
successfulCount: 0,
|
|
3284
|
-
failedCount: execution.tasks.length
|
|
3285
|
-
};
|
|
3286
|
-
}
|
|
3287
|
-
}
|
|
3288
|
-
/**
|
|
3289
|
-
* Execute a task with agent dispatching
|
|
3290
|
-
*
|
|
3291
|
-
* Routes the task to the appropriate agent based on skill configuration.
|
|
3292
|
-
*
|
|
3293
|
-
* @param skill - Skill file with agent configuration
|
|
3294
|
-
* @param task - Task to execute
|
|
3295
|
-
* @param executeFn - Execution function
|
|
3296
|
-
* @returns Dispatch result
|
|
3297
|
-
*/
|
|
3298
|
-
async executeWithAgentDispatch(skill, task, executeFn) {
|
|
3299
|
-
if (!this.config.enableDispatcher) {
|
|
3300
|
-
throw new Error("Agent dispatcher is disabled");
|
|
3301
|
-
}
|
|
3302
|
-
this.log(`Dispatching task: ${task.name} to agent: ${skill.metadata.agent || "default"}`);
|
|
3303
|
-
const dispatchResult = await this.dispatcher.dispatch(task, skill, async (config) => {
|
|
3304
|
-
const forkConfig = {
|
|
3305
|
-
id: nanoid(),
|
|
3306
|
-
sessionId: config.sessionId || nanoid(),
|
|
3307
|
-
skill,
|
|
3308
|
-
agentType: config.agentType,
|
|
3309
|
-
agentRole: config.agentRole,
|
|
3310
|
-
mode: config.mode,
|
|
3311
|
-
workingDirectory: config.workingDirectory,
|
|
3312
|
-
env: config.env,
|
|
3313
|
-
allowedTools: config.allowedTools,
|
|
3314
|
-
disallowedTools: config.disallowedTools,
|
|
3315
|
-
timeout: config.timeout
|
|
3316
|
-
};
|
|
3317
|
-
return executeFn(forkConfig);
|
|
3318
|
-
});
|
|
3319
|
-
if (!dispatchResult.success) {
|
|
3320
|
-
throw new Error(dispatchResult.error || "Agent dispatch failed");
|
|
3321
|
-
}
|
|
3322
|
-
return dispatchResult.output;
|
|
3323
|
-
}
|
|
3324
|
-
/**
|
|
3325
|
-
* Cancel a running fork context
|
|
3326
|
-
*
|
|
3327
|
-
* @param forkId - Fork context ID
|
|
3328
|
-
*/
|
|
3329
|
-
cancelFork(forkId) {
|
|
3330
|
-
this.forkManager.cancel(forkId);
|
|
3331
|
-
this.emit("fork:cancelled", forkId);
|
|
3332
|
-
this.log(`Cancelled fork: ${forkId}`);
|
|
3333
|
-
}
|
|
3334
|
-
/**
|
|
3335
|
-
* Get fork context state
|
|
3336
|
-
*
|
|
3337
|
-
* @param forkId - Fork context ID
|
|
3338
|
-
* @returns Fork state or null
|
|
3339
|
-
*/
|
|
3340
|
-
getForkState(forkId) {
|
|
3341
|
-
return this.forkManager.getFork(forkId);
|
|
3342
|
-
}
|
|
3343
|
-
/**
|
|
3344
|
-
* Get all active fork contexts
|
|
3345
|
-
*
|
|
3346
|
-
* @returns Array of active fork states
|
|
3347
|
-
*/
|
|
3348
|
-
getActiveForks() {
|
|
3349
|
-
return this.forkManager.listActive();
|
|
3350
|
-
}
|
|
3351
|
-
/**
|
|
3352
|
-
* Get fork context statistics
|
|
3353
|
-
*
|
|
3354
|
-
* @returns Fork statistics
|
|
3355
|
-
*/
|
|
3356
|
-
getForkStats() {
|
|
3357
|
-
return this.forkManager.getStats();
|
|
3358
|
-
}
|
|
3359
|
-
/**
|
|
3360
|
-
* Get dispatcher statistics
|
|
3361
|
-
*
|
|
3362
|
-
* @returns Dispatcher statistics
|
|
3363
|
-
*/
|
|
3364
|
-
getDispatcherStats() {
|
|
3365
|
-
return this.dispatcher.getStats();
|
|
3366
|
-
}
|
|
3367
|
-
/**
|
|
3368
|
-
* Setup fork manager event handlers
|
|
3369
|
-
*/
|
|
3370
|
-
setupForkManagerEvents() {
|
|
3371
|
-
this.forkManager.on("created", (fork) => {
|
|
3372
|
-
this.log(`Fork context created: ${fork.id}`);
|
|
3373
|
-
});
|
|
3374
|
-
this.forkManager.on("started", (fork) => {
|
|
3375
|
-
this.log(`Fork context started: ${fork.id}`);
|
|
3376
|
-
this.emit("fork:started", fork.id);
|
|
3377
|
-
});
|
|
3378
|
-
this.forkManager.on("completed", (fork, result) => {
|
|
3379
|
-
this.log(`Fork context completed: ${fork.id} (${result.durationMs}ms)`);
|
|
3380
|
-
});
|
|
3381
|
-
this.forkManager.on("failed", (fork, error) => {
|
|
3382
|
-
this.log(`Fork context failed: ${fork.id} - ${error}`);
|
|
3383
|
-
});
|
|
3384
|
-
this.forkManager.on("timeout", (fork) => {
|
|
3385
|
-
this.log(`Fork context timed out: ${fork.id}`);
|
|
3386
|
-
this.emit("fork:failed", fork.id, "Timeout");
|
|
3387
|
-
});
|
|
3388
|
-
this.forkManager.on("cancelled", (fork) => {
|
|
3389
|
-
this.log(`Fork context cancelled: ${fork.id}`);
|
|
3390
|
-
});
|
|
3391
|
-
}
|
|
3392
|
-
}
|
|
3393
|
-
|
|
3394
|
-
const WORKFLOW_PRESETS = [
|
|
3395
|
-
{
|
|
3396
|
-
id: "analyze",
|
|
3397
|
-
name: "Code Analysis",
|
|
3398
|
-
description: "Analyze codebase structure, dependencies, and quality",
|
|
3399
|
-
taskTemplate: (input) => ({
|
|
3400
|
-
id: nanoid(),
|
|
3401
|
-
name: "Analyze Codebase",
|
|
3402
|
-
description: input || "Analyze the codebase for structure, dependencies, and quality issues",
|
|
3403
|
-
type: "analysis",
|
|
3404
|
-
priority: "normal",
|
|
3405
|
-
status: "pending",
|
|
3406
|
-
requiredCapabilities: [
|
|
3407
|
-
{
|
|
3408
|
-
id: "code-analysis",
|
|
3409
|
-
name: "Code Analysis",
|
|
3410
|
-
model: "sonnet",
|
|
3411
|
-
specialties: ["static-analysis", "dependency-analysis"],
|
|
3412
|
-
strength: 0.9,
|
|
3413
|
-
costFactor: 1
|
|
3414
|
-
}
|
|
3415
|
-
],
|
|
3416
|
-
input: {
|
|
3417
|
-
parameters: { task: input },
|
|
3418
|
-
instructions: input
|
|
3419
|
-
},
|
|
3420
|
-
dependencies: [],
|
|
3421
|
-
maxRetries: 3,
|
|
3422
|
-
retryCount: 0,
|
|
3423
|
-
metadata: {
|
|
3424
|
-
tags: ["analysis", "code-quality"]
|
|
3425
|
-
},
|
|
3426
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3427
|
-
progress: 0
|
|
3428
|
-
})
|
|
3429
|
-
},
|
|
3430
|
-
{
|
|
3431
|
-
id: "fix",
|
|
3432
|
-
name: "Bug Fix",
|
|
3433
|
-
description: "Identify and fix bugs in the codebase",
|
|
3434
|
-
taskTemplate: (input) => ({
|
|
3435
|
-
id: nanoid(),
|
|
3436
|
-
name: "Fix Bugs",
|
|
3437
|
-
description: input || "Identify and fix bugs in the codebase",
|
|
3438
|
-
type: "bug-fix",
|
|
3439
|
-
priority: "high",
|
|
3440
|
-
status: "pending",
|
|
3441
|
-
requiredCapabilities: [
|
|
3442
|
-
{
|
|
3443
|
-
id: "debugging",
|
|
3444
|
-
name: "Debugging",
|
|
3445
|
-
model: "sonnet",
|
|
3446
|
-
specialties: ["bug-detection", "code-repair"],
|
|
3447
|
-
strength: 0.85,
|
|
3448
|
-
costFactor: 1.2
|
|
3449
|
-
}
|
|
3450
|
-
],
|
|
3451
|
-
input: {
|
|
3452
|
-
parameters: { task: input },
|
|
3453
|
-
instructions: input
|
|
3454
|
-
},
|
|
3455
|
-
dependencies: [],
|
|
3456
|
-
maxRetries: 3,
|
|
3457
|
-
retryCount: 0,
|
|
3458
|
-
metadata: {
|
|
3459
|
-
tags: ["bug-fix", "debugging"]
|
|
3460
|
-
},
|
|
3461
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3462
|
-
progress: 0
|
|
3463
|
-
})
|
|
3464
|
-
},
|
|
3465
|
-
{
|
|
3466
|
-
id: "test",
|
|
3467
|
-
name: "Test Generation",
|
|
3468
|
-
description: "Generate comprehensive test suites",
|
|
3469
|
-
taskTemplate: (input) => ({
|
|
3470
|
-
id: nanoid(),
|
|
3471
|
-
name: "Generate Tests",
|
|
3472
|
-
description: input || "Generate comprehensive test suites for the codebase",
|
|
3473
|
-
type: "testing",
|
|
3474
|
-
priority: "normal",
|
|
3475
|
-
status: "pending",
|
|
3476
|
-
requiredCapabilities: [
|
|
3477
|
-
{
|
|
3478
|
-
id: "test-generation",
|
|
3479
|
-
name: "Test Generation",
|
|
3480
|
-
model: "sonnet",
|
|
3481
|
-
specialties: ["unit-testing", "integration-testing"],
|
|
3482
|
-
strength: 0.8,
|
|
3483
|
-
costFactor: 1
|
|
3484
|
-
}
|
|
3485
|
-
],
|
|
3486
|
-
input: {
|
|
3487
|
-
parameters: { task: input },
|
|
3488
|
-
instructions: input
|
|
3489
|
-
},
|
|
3490
|
-
dependencies: [],
|
|
3491
|
-
maxRetries: 3,
|
|
3492
|
-
retryCount: 0,
|
|
3493
|
-
metadata: {
|
|
3494
|
-
tags: ["testing", "quality-assurance"]
|
|
3495
|
-
},
|
|
3496
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3497
|
-
progress: 0
|
|
3498
|
-
})
|
|
3499
|
-
},
|
|
3500
|
-
{
|
|
3501
|
-
id: "optimize",
|
|
3502
|
-
name: "Code Optimization",
|
|
3503
|
-
description: "Optimize code for performance and efficiency",
|
|
3504
|
-
taskTemplate: (input) => ({
|
|
3505
|
-
id: nanoid(),
|
|
3506
|
-
name: "Optimize Code",
|
|
3507
|
-
description: input || "Optimize code for performance and efficiency",
|
|
3508
|
-
type: "optimization",
|
|
3509
|
-
priority: "normal",
|
|
3510
|
-
status: "pending",
|
|
3511
|
-
requiredCapabilities: [
|
|
3512
|
-
{
|
|
3513
|
-
id: "optimization",
|
|
3514
|
-
name: "Code Optimization",
|
|
3515
|
-
model: "sonnet",
|
|
3516
|
-
specialties: ["performance-tuning", "refactoring"],
|
|
3517
|
-
strength: 0.85,
|
|
3518
|
-
costFactor: 1.1
|
|
3519
|
-
}
|
|
3520
|
-
],
|
|
3521
|
-
input: {
|
|
3522
|
-
parameters: { task: input },
|
|
3523
|
-
instructions: input
|
|
3524
|
-
},
|
|
3525
|
-
dependencies: [],
|
|
3526
|
-
maxRetries: 3,
|
|
3527
|
-
retryCount: 0,
|
|
3528
|
-
metadata: {
|
|
3529
|
-
tags: ["optimization", "performance"]
|
|
3530
|
-
},
|
|
3531
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3532
|
-
progress: 0
|
|
3533
|
-
})
|
|
3534
|
-
}
|
|
3535
|
-
];
|
|
3536
|
-
async function handleAgentsCommand(args, options = {}) {
|
|
3537
|
-
const subcommand = args[0];
|
|
3538
|
-
switch (subcommand) {
|
|
3539
|
-
case "run":
|
|
3540
|
-
await runAgentTeam(options);
|
|
3541
|
-
break;
|
|
3542
|
-
case "status":
|
|
3543
|
-
await showStatus(options);
|
|
3544
|
-
break;
|
|
3545
|
-
case "list":
|
|
3546
|
-
await listWorkflows(options);
|
|
3547
|
-
break;
|
|
3548
|
-
case "cancel":
|
|
3549
|
-
await cancelConvoy(args[1]);
|
|
3550
|
-
break;
|
|
3551
|
-
default:
|
|
3552
|
-
showHelp();
|
|
3553
|
-
}
|
|
3554
|
-
}
|
|
3555
|
-
async function runAgentTeam(options) {
|
|
3556
|
-
if (!options.task) {
|
|
3557
|
-
console.log(a.red("Error: Please specify a task with --task"));
|
|
3558
|
-
console.log(a.dim('Example: agents run --task "Analyze the codebase"'));
|
|
3559
|
-
return;
|
|
3560
|
-
}
|
|
3561
|
-
const workflow = options.workflow ? WORKFLOW_PRESETS.find((w) => w.id === options.workflow) : WORKFLOW_PRESETS[0];
|
|
3562
|
-
if (options.workflow && !workflow) {
|
|
3563
|
-
console.log(a.red(`Error: Unknown workflow: ${options.workflow}`));
|
|
3564
|
-
console.log(a.dim('Run "agents list" to see available workflows'));
|
|
3565
|
-
return;
|
|
3566
|
-
}
|
|
3567
|
-
console.log(a.cyan("\n\u{1F916} Starting Agent Team\n"));
|
|
3568
|
-
console.log(a.bold("Task:"), options.task);
|
|
3569
|
-
if (workflow) {
|
|
3570
|
-
console.log(a.bold("Workflow:"), workflow.name);
|
|
3571
|
-
}
|
|
3572
|
-
console.log("");
|
|
3573
|
-
const task = workflow.taskTemplate(options.task);
|
|
3574
|
-
const convoyManager = getGlobalConvoyManager();
|
|
3575
|
-
await convoyManager.initialize();
|
|
3576
|
-
const convoy = await convoyManager.create(`Agent Team: ${task.name}`, {
|
|
3577
|
-
description: task.description,
|
|
3578
|
-
createdBy: "cli",
|
|
3579
|
-
notifyOnComplete: true,
|
|
3580
|
-
notifyOnFailure: true,
|
|
3581
|
-
tags: ["agent-team", workflow?.id || "custom"]
|
|
3582
|
-
});
|
|
3583
|
-
await convoyManager.addTask(convoy.id, task.name, {
|
|
3584
|
-
description: task.description
|
|
3585
|
-
});
|
|
3586
|
-
await convoyManager.start(convoy.id);
|
|
3587
|
-
const orchestrator = new BrainOrchestrator({
|
|
3588
|
-
maxConcurrentTasks: 10,
|
|
3589
|
-
maxConcurrentAgents: 5,
|
|
3590
|
-
verboseLogging: options.verbose || false,
|
|
3591
|
-
enableParallelExecution: true
|
|
3592
|
-
});
|
|
3593
|
-
const spinner = ora("Initializing agent team...").start();
|
|
3594
|
-
orchestrator.on("plan:created", (plan) => {
|
|
3595
|
-
spinner.text = `Created plan with ${plan.tasks.length} tasks`;
|
|
3596
|
-
});
|
|
3597
|
-
orchestrator.on("task:started", (task2) => {
|
|
3598
|
-
spinner.text = `Executing: ${task2.name}`;
|
|
3599
|
-
});
|
|
3600
|
-
orchestrator.on("task:completed", (task2) => {
|
|
3601
|
-
spinner.succeed(`Completed: ${task2.name}`);
|
|
3602
|
-
spinner.start();
|
|
3603
|
-
});
|
|
3604
|
-
orchestrator.on("task:failed", (task2, error) => {
|
|
3605
|
-
spinner.fail(`Failed: ${task2.name} - ${error.message}`);
|
|
3606
|
-
spinner.start();
|
|
3607
|
-
});
|
|
3608
|
-
try {
|
|
3609
|
-
const result = await orchestrator.execute(task);
|
|
3610
|
-
spinner.stop();
|
|
3611
|
-
const convoyTask = convoy.tasks[0];
|
|
3612
|
-
if (result.success) {
|
|
3613
|
-
await convoyManager.completeTask(convoy.id, convoyTask.id, result);
|
|
3614
|
-
} else {
|
|
3615
|
-
await convoyManager.failTask(
|
|
3616
|
-
convoy.id,
|
|
3617
|
-
convoyTask.id,
|
|
3618
|
-
result.errors[0]?.message || "Unknown error"
|
|
3619
|
-
);
|
|
3620
|
-
}
|
|
3621
|
-
console.log("");
|
|
3622
|
-
if (result.success) {
|
|
3623
|
-
console.log(a.green("\u2705 Agent team completed successfully!"));
|
|
3624
|
-
} else {
|
|
3625
|
-
console.log(a.red("\u274C Agent team failed"));
|
|
3626
|
-
}
|
|
3627
|
-
console.log("");
|
|
3628
|
-
console.log(a.bold("Results:"));
|
|
3629
|
-
console.log(a.dim("\u2500".repeat(60)));
|
|
3630
|
-
if (options.json) {
|
|
3631
|
-
console.log(JSON.stringify(result, null, 2));
|
|
3632
|
-
} else {
|
|
3633
|
-
console.log(a.dim(`Status: ${result.status}`));
|
|
3634
|
-
console.log(a.dim(`Tasks Completed: ${result.completedTasks.length}`));
|
|
3635
|
-
console.log(a.dim(`Tasks Failed: ${result.failedTasks.length}`));
|
|
3636
|
-
console.log(a.dim(`Duration: ${result.duration}ms`));
|
|
3637
|
-
console.log(a.dim(`Success Rate: ${(result.metrics.successRate * 100).toFixed(1)}%`));
|
|
3638
|
-
if (result.errors.length > 0) {
|
|
3639
|
-
console.log("");
|
|
3640
|
-
console.log(a.bold("Errors:"));
|
|
3641
|
-
for (const error of result.errors) {
|
|
3642
|
-
console.log(a.red(` \u2022 ${error.message}`));
|
|
3643
|
-
}
|
|
3644
|
-
}
|
|
3645
|
-
if (result.warnings.length > 0) {
|
|
3646
|
-
console.log("");
|
|
3647
|
-
console.log(a.bold("Warnings:"));
|
|
3648
|
-
for (const warning of result.warnings) {
|
|
3649
|
-
console.log(a.yellow(` \u2022 ${warning}`));
|
|
3650
|
-
}
|
|
3651
|
-
}
|
|
3652
|
-
}
|
|
3653
|
-
console.log(a.dim("\u2500".repeat(60)));
|
|
3654
|
-
console.log("");
|
|
3655
|
-
console.log(a.dim(`Convoy ID: ${convoy.id}`));
|
|
3656
|
-
console.log(a.dim('Run "agents status" to see all convoys'));
|
|
3657
|
-
} catch (error) {
|
|
3658
|
-
spinner.fail("Agent team execution failed");
|
|
3659
|
-
console.log(a.red(`
|
|
3660
|
-
\u274C Error: ${error instanceof Error ? error.message : error}`));
|
|
3661
|
-
const convoyTask = convoy.tasks[0];
|
|
3662
|
-
await convoyManager.failTask(
|
|
3663
|
-
convoy.id,
|
|
3664
|
-
convoyTask.id,
|
|
3665
|
-
error instanceof Error ? error.message : String(error)
|
|
3666
|
-
);
|
|
3667
|
-
}
|
|
3668
|
-
}
|
|
3669
|
-
async function showStatus(options) {
|
|
3670
|
-
const convoyManager = getGlobalConvoyManager();
|
|
3671
|
-
await convoyManager.initialize();
|
|
3672
|
-
const activeConvoys = convoyManager.getActive();
|
|
3673
|
-
const allConvoys = convoyManager.list();
|
|
3674
|
-
if (options.json) {
|
|
3675
|
-
console.log(JSON.stringify({ active: activeConvoys, all: allConvoys }, null, 2));
|
|
3676
|
-
return;
|
|
3677
|
-
}
|
|
3678
|
-
console.log(a.cyan("\n\u{1F680} Agent Teams Status\n"));
|
|
3679
|
-
if (activeConvoys.length === 0) {
|
|
3680
|
-
console.log(a.dim("No active convoys"));
|
|
3681
|
-
} else {
|
|
3682
|
-
console.log(a.bold("Active Convoys:"));
|
|
3683
|
-
console.log("");
|
|
3684
|
-
for (const convoy of activeConvoys) {
|
|
3685
|
-
console.log(` ${a.bold(convoy.name)} ${a.dim(`(${convoy.id})`)}`);
|
|
3686
|
-
console.log(a.dim(` Status: ${convoy.status}`));
|
|
3687
|
-
console.log(a.dim(` Progress: ${convoy.progress}%`));
|
|
3688
|
-
console.log(a.dim(` Tasks: ${convoy.completedTasks}/${convoy.totalTasks}`));
|
|
3689
|
-
console.log("");
|
|
3690
|
-
}
|
|
3691
|
-
}
|
|
3692
|
-
const recentConvoys = allConvoys.slice(0, 5);
|
|
3693
|
-
if (recentConvoys.length > 0) {
|
|
3694
|
-
console.log(a.bold("Recent Convoys:"));
|
|
3695
|
-
console.log("");
|
|
3696
|
-
for (const convoy of recentConvoys) {
|
|
3697
|
-
const statusIcon = convoy.status === "completed" ? "\u2705" : convoy.status === "failed" ? "\u274C" : "\u23F8\uFE0F";
|
|
3698
|
-
console.log(` ${statusIcon} ${a.bold(convoy.name)} ${a.dim(`(${convoy.id})`)}`);
|
|
3699
|
-
console.log(a.dim(` Status: ${convoy.status}`));
|
|
3700
|
-
console.log(a.dim(` Progress: ${convoy.progress}%`));
|
|
3701
|
-
console.log(a.dim(` Created: ${new Date(convoy.createdAt).toLocaleString()}`));
|
|
3702
|
-
console.log("");
|
|
3703
|
-
}
|
|
3704
|
-
}
|
|
3705
|
-
console.log(a.dim(`Total convoys: ${allConvoys.length}`));
|
|
3706
|
-
}
|
|
3707
|
-
async function listWorkflows(options) {
|
|
3708
|
-
if (options.json) {
|
|
3709
|
-
console.log(JSON.stringify(WORKFLOW_PRESETS, null, 2));
|
|
3710
|
-
return;
|
|
3711
|
-
}
|
|
3712
|
-
console.log(a.cyan("\n\u{1F4CB} Available Workflow Presets\n"));
|
|
3713
|
-
for (const workflow of WORKFLOW_PRESETS) {
|
|
3714
|
-
console.log(` ${a.bold(workflow.name)} ${a.dim(`(${workflow.id})`)}`);
|
|
3715
|
-
console.log(a.dim(` ${workflow.description}`));
|
|
3716
|
-
console.log("");
|
|
3717
|
-
}
|
|
3718
|
-
console.log(a.dim("Usage:"));
|
|
3719
|
-
console.log(a.dim(' agents run --task "Your task" --workflow <id>'));
|
|
3720
|
-
console.log("");
|
|
3721
|
-
console.log(a.dim("Example:"));
|
|
3722
|
-
console.log(a.dim(' agents run --task "Find performance bottlenecks" --workflow optimize'));
|
|
3723
|
-
}
|
|
3724
|
-
async function cancelConvoy(convoyId, _options) {
|
|
3725
|
-
if (!convoyId) {
|
|
3726
|
-
console.log(a.red("Error: Please specify a convoy ID"));
|
|
3727
|
-
console.log(a.dim("Example: agents cancel cv-abc123"));
|
|
3728
|
-
return;
|
|
3729
|
-
}
|
|
3730
|
-
const convoyManager = getGlobalConvoyManager();
|
|
3731
|
-
await convoyManager.initialize();
|
|
3732
|
-
const convoy = convoyManager.get(convoyId);
|
|
3733
|
-
if (!convoy) {
|
|
3734
|
-
console.log(a.red(`Error: Convoy not found: ${convoyId}`));
|
|
3735
|
-
return;
|
|
3736
|
-
}
|
|
3737
|
-
await convoyManager.cancel(convoyId);
|
|
3738
|
-
console.log(a.green(`\u2705 Cancelled convoy: ${convoy.name}`));
|
|
3739
|
-
}
|
|
3740
|
-
function showHelp() {
|
|
3741
|
-
console.log(`
|
|
3742
|
-
${a.bold(a.cyan("\u{1F916} Agent Teams Command"))}
|
|
3743
|
-
|
|
3744
|
-
${a.bold("Usage:")}
|
|
3745
|
-
agents <command> [options]
|
|
3746
|
-
|
|
3747
|
-
${a.bold("Commands:")}
|
|
3748
|
-
${a.green("run")} Execute a task with agent teams
|
|
3749
|
-
${a.green("status")} Show active convoys and status
|
|
3750
|
-
${a.green("list")} List available workflow presets
|
|
3751
|
-
${a.green("cancel")} <id> Cancel a running convoy
|
|
3752
|
-
|
|
3753
|
-
${a.bold("Options:")}
|
|
3754
|
-
--task <task> Task description (required for run)
|
|
3755
|
-
--workflow <id> Workflow preset (analyze, fix, test, optimize)
|
|
3756
|
-
--verbose, -v Enable verbose logging
|
|
3757
|
-
--json Output as JSON
|
|
3758
|
-
|
|
3759
|
-
${a.bold("Examples:")}
|
|
3760
|
-
${a.dim("# Run code analysis")}
|
|
3761
|
-
agents run --task "Analyze the codebase for issues"
|
|
3762
|
-
|
|
3763
|
-
${a.dim("# Run with specific workflow")}
|
|
3764
|
-
agents run --task "Fix memory leaks" --workflow fix
|
|
3765
|
-
|
|
3766
|
-
${a.dim("# Show status")}
|
|
3767
|
-
agents status
|
|
3768
|
-
|
|
3769
|
-
${a.dim("# List workflows")}
|
|
3770
|
-
agents list
|
|
3771
|
-
|
|
3772
|
-
${a.dim("# Cancel convoy")}
|
|
3773
|
-
agents cancel cv-abc123
|
|
3774
|
-
|
|
3775
|
-
${a.bold("Workflow Presets:")}
|
|
3776
|
-
${a.green("analyze")} - Code analysis and quality checks
|
|
3777
|
-
${a.green("fix")} - Bug detection and fixing
|
|
3778
|
-
${a.green("test")} - Test generation and coverage
|
|
3779
|
-
${a.green("optimize")} - Performance optimization
|
|
3780
|
-
`);
|
|
3781
|
-
}
|
|
3782
|
-
|
|
3783
|
-
export { handleAgentsCommand as default, handleAgentsCommand };
|