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
|
@@ -1,1371 +0,0 @@
|
|
|
1
|
-
import { EventEmitter } from 'node:events';
|
|
2
|
-
import { n as nanoid } from '../shared/ccjk.BoApaI4j.mjs';
|
|
3
|
-
import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';
|
|
4
|
-
import { homedir } from 'node:os';
|
|
5
|
-
import { x as K } from './main.mjs';
|
|
6
|
-
import { j as join } from '../shared/ccjk.bQ7Dh1g4.mjs';
|
|
7
|
-
import { glob } from 'tinyglobby';
|
|
8
|
-
import { e as executionTracer } from '../shared/ccjk.DlTXS9rP.mjs';
|
|
9
|
-
import { f as fsParadigm } from '../shared/ccjk.wLJHO0Af.mjs';
|
|
10
|
-
import 'node:child_process';
|
|
11
|
-
import 'node:fs/promises';
|
|
12
|
-
import 'node:path';
|
|
13
|
-
|
|
14
|
-
class GitBackedStateManager extends EventEmitter {
|
|
15
|
-
config;
|
|
16
|
-
worktrees = /* @__PURE__ */ new Map();
|
|
17
|
-
initialized = false;
|
|
18
|
-
pendingCommits = /* @__PURE__ */ new Map();
|
|
19
|
-
constructor(config = {}) {
|
|
20
|
-
super();
|
|
21
|
-
this.config = {
|
|
22
|
-
workspaceRoot: config.workspaceRoot ?? join(homedir(), ".ccjk", "workspace"),
|
|
23
|
-
useWorktrees: config.useWorktrees ?? true,
|
|
24
|
-
autoCommit: config.autoCommit ?? true,
|
|
25
|
-
compressionLevel: config.compressionLevel ?? 6,
|
|
26
|
-
verbose: config.verbose ?? false,
|
|
27
|
-
commitBatchInterval: config.commitBatchInterval ?? 1e3
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Initialize the workspace with Git
|
|
32
|
-
*/
|
|
33
|
-
async initialize() {
|
|
34
|
-
if (this.initialized)
|
|
35
|
-
return;
|
|
36
|
-
const { workspaceRoot } = this.config;
|
|
37
|
-
try {
|
|
38
|
-
if (!existsSync(workspaceRoot)) {
|
|
39
|
-
mkdirSync(workspaceRoot, { recursive: true });
|
|
40
|
-
this.log(`Created workspace: ${workspaceRoot}`);
|
|
41
|
-
}
|
|
42
|
-
const gitDir = join(workspaceRoot, ".git");
|
|
43
|
-
if (!existsSync(gitDir)) {
|
|
44
|
-
await this.exec("git", ["init"], workspaceRoot);
|
|
45
|
-
this.log("Initialized Git repository");
|
|
46
|
-
const gitignore = `
|
|
47
|
-
# Sensitive data
|
|
48
|
-
*.env
|
|
49
|
-
*.key
|
|
50
|
-
*.pem
|
|
51
|
-
credentials.json
|
|
52
|
-
|
|
53
|
-
# Temporary files
|
|
54
|
-
*.tmp
|
|
55
|
-
*.log
|
|
56
|
-
*.swp
|
|
57
|
-
|
|
58
|
-
# OS files
|
|
59
|
-
.DS_Store
|
|
60
|
-
Thumbs.db
|
|
61
|
-
`;
|
|
62
|
-
writeFileSync(join(workspaceRoot, ".gitignore"), gitignore.trim());
|
|
63
|
-
await this.exec("git", ["add", ".gitignore"], workspaceRoot);
|
|
64
|
-
await this.exec("git", ["commit", "-m", "Initial commit"], workspaceRoot);
|
|
65
|
-
this.log("Created initial commit");
|
|
66
|
-
}
|
|
67
|
-
const agentsDir = join(workspaceRoot, "agents");
|
|
68
|
-
if (!existsSync(agentsDir)) {
|
|
69
|
-
mkdirSync(agentsDir, { recursive: true });
|
|
70
|
-
}
|
|
71
|
-
await this.loadExistingWorktrees();
|
|
72
|
-
this.initialized = true;
|
|
73
|
-
this.emit("initialized");
|
|
74
|
-
this.log("GitBackedStateManager initialized");
|
|
75
|
-
} catch (error) {
|
|
76
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
77
|
-
this.emit("error", err);
|
|
78
|
-
throw err;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Create isolated worktree for agent
|
|
83
|
-
*/
|
|
84
|
-
async createAgentWorktree(agentId) {
|
|
85
|
-
await this.ensureInitialized();
|
|
86
|
-
const { workspaceRoot, useWorktrees } = this.config;
|
|
87
|
-
if (this.worktrees.has(agentId)) {
|
|
88
|
-
return this.worktrees.get(agentId);
|
|
89
|
-
}
|
|
90
|
-
const agentPath = join(workspaceRoot, "agents", agentId);
|
|
91
|
-
if (useWorktrees) {
|
|
92
|
-
const branchName = `agent/${agentId}`;
|
|
93
|
-
try {
|
|
94
|
-
await this.exec("git", ["checkout", "--orphan", branchName], workspaceRoot);
|
|
95
|
-
await this.exec("git", ["reset", "--hard"], workspaceRoot);
|
|
96
|
-
await this.exec("git", ["checkout", "main"], workspaceRoot).catch(() => {
|
|
97
|
-
return this.exec("git", ["checkout", "master"], workspaceRoot);
|
|
98
|
-
});
|
|
99
|
-
if (!existsSync(agentPath)) {
|
|
100
|
-
await this.exec("git", ["worktree", "add", agentPath, branchName], workspaceRoot);
|
|
101
|
-
}
|
|
102
|
-
} catch {
|
|
103
|
-
if (!existsSync(agentPath)) {
|
|
104
|
-
mkdirSync(agentPath, { recursive: true });
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
} else {
|
|
108
|
-
if (!existsSync(agentPath)) {
|
|
109
|
-
mkdirSync(agentPath, { recursive: true });
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
const stateFile = join(agentPath, "state.json");
|
|
113
|
-
const mailboxFile = join(agentPath, "mailbox.json");
|
|
114
|
-
if (!existsSync(stateFile)) {
|
|
115
|
-
writeFileSync(stateFile, JSON.stringify({ agentId, createdAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
116
|
-
}
|
|
117
|
-
if (!existsSync(mailboxFile)) {
|
|
118
|
-
writeFileSync(mailboxFile, JSON.stringify({ inbox: [], outbox: [], archive: [] }, null, 2));
|
|
119
|
-
}
|
|
120
|
-
this.worktrees.set(agentId, agentPath);
|
|
121
|
-
this.emit("worktree:created", agentId, agentPath);
|
|
122
|
-
this.log(`Created worktree for agent: ${agentId}`);
|
|
123
|
-
return agentPath;
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Save agent state to Git
|
|
127
|
-
*/
|
|
128
|
-
async saveState(agentId, state) {
|
|
129
|
-
await this.ensureInitialized();
|
|
130
|
-
const agentPath = await this.getOrCreateAgentPath(agentId);
|
|
131
|
-
const stateFile = join(agentPath, "state.json");
|
|
132
|
-
let existingState = {};
|
|
133
|
-
if (existsSync(stateFile)) {
|
|
134
|
-
try {
|
|
135
|
-
existingState = JSON.parse(readFileSync(stateFile, "utf-8"));
|
|
136
|
-
} catch {
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
const newState = {
|
|
140
|
-
...existingState,
|
|
141
|
-
...state,
|
|
142
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
143
|
-
};
|
|
144
|
-
writeFileSync(stateFile, JSON.stringify(newState, null, 2));
|
|
145
|
-
let commitId = "";
|
|
146
|
-
if (this.config.autoCommit) {
|
|
147
|
-
commitId = await this.batchCommit(agentId, `Update state: ${agentId}`);
|
|
148
|
-
}
|
|
149
|
-
this.emit("state:saved", agentId, commitId);
|
|
150
|
-
this.log(`Saved state for agent: ${agentId}`);
|
|
151
|
-
return commitId;
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Load agent state from Git
|
|
155
|
-
*/
|
|
156
|
-
async loadState(agentId) {
|
|
157
|
-
await this.ensureInitialized();
|
|
158
|
-
const agentPath = this.worktrees.get(agentId);
|
|
159
|
-
if (!agentPath) {
|
|
160
|
-
return null;
|
|
161
|
-
}
|
|
162
|
-
const stateFile = join(agentPath, "state.json");
|
|
163
|
-
if (!existsSync(stateFile)) {
|
|
164
|
-
return null;
|
|
165
|
-
}
|
|
166
|
-
try {
|
|
167
|
-
const state = JSON.parse(readFileSync(stateFile, "utf-8"));
|
|
168
|
-
this.emit("state:loaded", agentId);
|
|
169
|
-
this.log(`Loaded state for agent: ${agentId}`);
|
|
170
|
-
return state;
|
|
171
|
-
} catch {
|
|
172
|
-
return null;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* Rollback to previous state
|
|
177
|
-
*/
|
|
178
|
-
async rollback(agentId, commitId) {
|
|
179
|
-
await this.ensureInitialized();
|
|
180
|
-
const agentPath = this.worktrees.get(agentId);
|
|
181
|
-
if (!agentPath) {
|
|
182
|
-
throw new Error(`Agent not found: ${agentId}`);
|
|
183
|
-
}
|
|
184
|
-
try {
|
|
185
|
-
await this.exec("git", ["reset", "--hard", commitId], agentPath);
|
|
186
|
-
this.emit("state:rolled-back", agentId, commitId);
|
|
187
|
-
this.log(`Rolled back agent ${agentId} to commit ${commitId}`);
|
|
188
|
-
} catch (error) {
|
|
189
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
190
|
-
this.emit("error", err);
|
|
191
|
-
throw err;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Get state history for agent
|
|
196
|
-
*/
|
|
197
|
-
async getHistory(agentId, limit = 10) {
|
|
198
|
-
await this.ensureInitialized();
|
|
199
|
-
const agentPath = this.worktrees.get(agentId);
|
|
200
|
-
if (!agentPath) {
|
|
201
|
-
return [];
|
|
202
|
-
}
|
|
203
|
-
try {
|
|
204
|
-
const result = await this.exec(
|
|
205
|
-
"git",
|
|
206
|
-
["log", `--max-count=${limit}`, "--format=%H|%s|%ct", "--", "state.json"],
|
|
207
|
-
agentPath
|
|
208
|
-
);
|
|
209
|
-
const snapshots = [];
|
|
210
|
-
for (const line of result.stdout.split("\n").filter(Boolean)) {
|
|
211
|
-
const [commitId, message, timestamp] = line.split("|");
|
|
212
|
-
const stateResult = await this.exec(
|
|
213
|
-
"git",
|
|
214
|
-
["show", `${commitId}:state.json`],
|
|
215
|
-
agentPath
|
|
216
|
-
).catch(() => ({ stdout: "{}" }));
|
|
217
|
-
let state;
|
|
218
|
-
try {
|
|
219
|
-
state = JSON.parse(stateResult.stdout);
|
|
220
|
-
} catch {
|
|
221
|
-
state = {};
|
|
222
|
-
}
|
|
223
|
-
snapshots.push({
|
|
224
|
-
id: nanoid(),
|
|
225
|
-
agentId,
|
|
226
|
-
commitId,
|
|
227
|
-
timestamp: Number.parseInt(timestamp, 10) * 1e3,
|
|
228
|
-
message,
|
|
229
|
-
state
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
return snapshots;
|
|
233
|
-
} catch {
|
|
234
|
-
return [];
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* Cleanup agent worktree
|
|
239
|
-
*/
|
|
240
|
-
async cleanup(agentId) {
|
|
241
|
-
await this.ensureInitialized();
|
|
242
|
-
const agentPath = this.worktrees.get(agentId);
|
|
243
|
-
if (!agentPath) {
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
try {
|
|
247
|
-
if (this.config.useWorktrees) {
|
|
248
|
-
await this.exec("git", ["worktree", "remove", agentPath, "--force"], this.config.workspaceRoot);
|
|
249
|
-
}
|
|
250
|
-
this.worktrees.delete(agentId);
|
|
251
|
-
this.emit("worktree:removed", agentId);
|
|
252
|
-
this.log(`Cleaned up worktree for agent: ${agentId}`);
|
|
253
|
-
} catch (error) {
|
|
254
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
255
|
-
this.emit("error", err);
|
|
256
|
-
throw err;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* Get all agent IDs
|
|
261
|
-
*/
|
|
262
|
-
getAgentIds() {
|
|
263
|
-
return Array.from(this.worktrees.keys());
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Check if agent exists
|
|
267
|
-
*/
|
|
268
|
-
hasAgent(agentId) {
|
|
269
|
-
return this.worktrees.has(agentId);
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Get workspace root path
|
|
273
|
-
*/
|
|
274
|
-
getWorkspaceRoot() {
|
|
275
|
-
return this.config.workspaceRoot;
|
|
276
|
-
}
|
|
277
|
-
/**
|
|
278
|
-
* Get agent path
|
|
279
|
-
*/
|
|
280
|
-
getAgentPath(agentId) {
|
|
281
|
-
return this.worktrees.get(agentId);
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* Get state history for agent
|
|
285
|
-
*/
|
|
286
|
-
async getStateHistory(agentId, limit = 20) {
|
|
287
|
-
await this.ensureInitialized();
|
|
288
|
-
const agentPath = this.worktrees.get(agentId);
|
|
289
|
-
if (!agentPath) {
|
|
290
|
-
return { agentId, commits: [], totalCommits: 0 };
|
|
291
|
-
}
|
|
292
|
-
try {
|
|
293
|
-
const result = await this.exec(
|
|
294
|
-
"git",
|
|
295
|
-
["log", `--max-count=${limit}`, "--format=%H|%s|%ct", "--", "state.json"],
|
|
296
|
-
agentPath
|
|
297
|
-
);
|
|
298
|
-
const commits = result.stdout.split("\n").filter(Boolean).map((line) => {
|
|
299
|
-
const [id, message, timestamp] = line.split("|");
|
|
300
|
-
return {
|
|
301
|
-
id,
|
|
302
|
-
message,
|
|
303
|
-
timestamp: Number.parseInt(timestamp, 10) * 1e3
|
|
304
|
-
};
|
|
305
|
-
});
|
|
306
|
-
const countResult = await this.exec(
|
|
307
|
-
"git",
|
|
308
|
-
["rev-list", "--count", "HEAD", "--", "state.json"],
|
|
309
|
-
agentPath
|
|
310
|
-
).catch(() => ({ stdout: "0" }));
|
|
311
|
-
return {
|
|
312
|
-
agentId,
|
|
313
|
-
commits,
|
|
314
|
-
totalCommits: Number.parseInt(countResult.stdout.trim(), 10) || commits.length
|
|
315
|
-
};
|
|
316
|
-
} catch {
|
|
317
|
-
return { agentId, commits: [], totalCommits: 0 };
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
/**
|
|
321
|
-
* Create a named snapshot of current state
|
|
322
|
-
*/
|
|
323
|
-
async createSnapshot(agentId, description) {
|
|
324
|
-
await this.ensureInitialized();
|
|
325
|
-
const agentPath = this.worktrees.get(agentId);
|
|
326
|
-
if (!agentPath) {
|
|
327
|
-
throw new Error(`Agent not found: ${agentId}`);
|
|
328
|
-
}
|
|
329
|
-
const commitId = await this.commit(agentId, `Snapshot: ${description}`);
|
|
330
|
-
if (!commitId) {
|
|
331
|
-
const result = await this.exec("git", ["rev-parse", "HEAD"], agentPath);
|
|
332
|
-
const currentCommitId = result.stdout.trim();
|
|
333
|
-
const state2 = await this.loadState(agentId);
|
|
334
|
-
return {
|
|
335
|
-
id: nanoid(),
|
|
336
|
-
agentId,
|
|
337
|
-
commitId: currentCommitId,
|
|
338
|
-
timestamp: Date.now(),
|
|
339
|
-
message: description,
|
|
340
|
-
state: state2 ?? {}
|
|
341
|
-
};
|
|
342
|
-
}
|
|
343
|
-
const state = await this.loadState(agentId);
|
|
344
|
-
return {
|
|
345
|
-
id: nanoid(),
|
|
346
|
-
agentId,
|
|
347
|
-
commitId,
|
|
348
|
-
timestamp: Date.now(),
|
|
349
|
-
message: description,
|
|
350
|
-
state: state ?? {}
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
/**
|
|
354
|
-
* Restore state from a snapshot
|
|
355
|
-
*/
|
|
356
|
-
async restoreSnapshot(agentId, snapshotId) {
|
|
357
|
-
await this.rollback(agentId, snapshotId);
|
|
358
|
-
}
|
|
359
|
-
/**
|
|
360
|
-
* Sync with remote (if configured)
|
|
361
|
-
*/
|
|
362
|
-
async syncWithRemote() {
|
|
363
|
-
await this.ensureInitialized();
|
|
364
|
-
try {
|
|
365
|
-
const remoteResult = await this.exec("git", ["remote"], this.config.workspaceRoot);
|
|
366
|
-
if (!remoteResult.stdout.trim()) {
|
|
367
|
-
this.log("No remote configured, skipping sync");
|
|
368
|
-
return;
|
|
369
|
-
}
|
|
370
|
-
await this.exec("git", ["pull", "--rebase"], this.config.workspaceRoot);
|
|
371
|
-
await this.exec("git", ["push"], this.config.workspaceRoot);
|
|
372
|
-
this.log("Synced with remote");
|
|
373
|
-
} catch (error) {
|
|
374
|
-
this.log(`Sync failed: ${error}`);
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
// ========================================================================
|
|
378
|
-
// Private Methods
|
|
379
|
-
// ========================================================================
|
|
380
|
-
async ensureInitialized() {
|
|
381
|
-
if (!this.initialized) {
|
|
382
|
-
await this.initialize();
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
async getOrCreateAgentPath(agentId) {
|
|
386
|
-
if (!this.worktrees.has(agentId)) {
|
|
387
|
-
await this.createAgentWorktree(agentId);
|
|
388
|
-
}
|
|
389
|
-
return this.worktrees.get(agentId);
|
|
390
|
-
}
|
|
391
|
-
async loadExistingWorktrees() {
|
|
392
|
-
const agentsDir = join(this.config.workspaceRoot, "agents");
|
|
393
|
-
if (!existsSync(agentsDir)) {
|
|
394
|
-
return;
|
|
395
|
-
}
|
|
396
|
-
try {
|
|
397
|
-
const { readdirSync, statSync } = await import('node:fs');
|
|
398
|
-
const entries = readdirSync(agentsDir);
|
|
399
|
-
for (const entry of entries) {
|
|
400
|
-
const entryPath = join(agentsDir, entry);
|
|
401
|
-
if (statSync(entryPath).isDirectory()) {
|
|
402
|
-
this.worktrees.set(entry, entryPath);
|
|
403
|
-
this.log(`Loaded existing worktree: ${entry}`);
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
} catch {
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
async batchCommit(agentId, message) {
|
|
410
|
-
const existing = this.pendingCommits.get(agentId);
|
|
411
|
-
if (existing) {
|
|
412
|
-
clearTimeout(existing);
|
|
413
|
-
}
|
|
414
|
-
return new Promise((resolve) => {
|
|
415
|
-
const timeout = setTimeout(async () => {
|
|
416
|
-
this.pendingCommits.delete(agentId);
|
|
417
|
-
const commitId = await this.commit(agentId, message);
|
|
418
|
-
resolve(commitId);
|
|
419
|
-
}, this.config.commitBatchInterval);
|
|
420
|
-
this.pendingCommits.set(agentId, timeout);
|
|
421
|
-
});
|
|
422
|
-
}
|
|
423
|
-
async commit(agentId, message) {
|
|
424
|
-
const agentPath = this.worktrees.get(agentId);
|
|
425
|
-
if (!agentPath) {
|
|
426
|
-
return "";
|
|
427
|
-
}
|
|
428
|
-
try {
|
|
429
|
-
await this.exec("git", ["add", "-A"], agentPath);
|
|
430
|
-
const statusResult = await this.exec("git", ["status", "--porcelain"], agentPath);
|
|
431
|
-
if (!statusResult.stdout.trim()) {
|
|
432
|
-
return "";
|
|
433
|
-
}
|
|
434
|
-
await this.exec("git", ["commit", "-m", message], agentPath);
|
|
435
|
-
const result = await this.exec("git", ["rev-parse", "HEAD"], agentPath);
|
|
436
|
-
return result.stdout.trim();
|
|
437
|
-
} catch {
|
|
438
|
-
return "";
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
async exec(cmd, args, cwd) {
|
|
442
|
-
const result = await K(cmd, args, { nodeOptions: { cwd } });
|
|
443
|
-
return {
|
|
444
|
-
stdout: result.stdout,
|
|
445
|
-
stderr: result.stderr
|
|
446
|
-
};
|
|
447
|
-
}
|
|
448
|
-
log(message) {
|
|
449
|
-
if (this.config.verbose) {
|
|
450
|
-
console.log(`[GitBackedState] ${message}`);
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
let globalStateManager = null;
|
|
455
|
-
function getGlobalStateManager(config) {
|
|
456
|
-
if (!globalStateManager) {
|
|
457
|
-
globalStateManager = new GitBackedStateManager(config);
|
|
458
|
-
}
|
|
459
|
-
return globalStateManager;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
const gitBackedState = {
|
|
463
|
-
__proto__: null,
|
|
464
|
-
GitBackedStateManager: GitBackedStateManager,
|
|
465
|
-
getGlobalStateManager: getGlobalStateManager
|
|
466
|
-
};
|
|
467
|
-
|
|
468
|
-
class ConvoyManager extends EventEmitter {
|
|
469
|
-
stateManager;
|
|
470
|
-
convoys = /* @__PURE__ */ new Map();
|
|
471
|
-
initialized = false;
|
|
472
|
-
constructor(stateManager) {
|
|
473
|
-
super();
|
|
474
|
-
this.stateManager = stateManager ?? getGlobalStateManager();
|
|
475
|
-
}
|
|
476
|
-
/**
|
|
477
|
-
* Initialize convoy manager
|
|
478
|
-
*/
|
|
479
|
-
async initialize() {
|
|
480
|
-
if (this.initialized)
|
|
481
|
-
return;
|
|
482
|
-
await this.stateManager.initialize();
|
|
483
|
-
await this.loadConvoys();
|
|
484
|
-
this.initialized = true;
|
|
485
|
-
}
|
|
486
|
-
/**
|
|
487
|
-
* Create new convoy
|
|
488
|
-
*/
|
|
489
|
-
async create(name, options = {}) {
|
|
490
|
-
await this.ensureInitialized();
|
|
491
|
-
const convoy = {
|
|
492
|
-
id: `cv-${nanoid(6)}`,
|
|
493
|
-
name,
|
|
494
|
-
description: options.description ?? "",
|
|
495
|
-
tasks: [],
|
|
496
|
-
status: "pending",
|
|
497
|
-
progress: 0,
|
|
498
|
-
totalTasks: 0,
|
|
499
|
-
completedTasks: 0,
|
|
500
|
-
failedTasks: 0,
|
|
501
|
-
cancelledTasks: 0,
|
|
502
|
-
skippedTasks: 0,
|
|
503
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
504
|
-
createdBy: options.createdBy ?? "system",
|
|
505
|
-
notifications: {
|
|
506
|
-
onComplete: options.notifyOnComplete ?? false,
|
|
507
|
-
onFailure: options.notifyOnFailure ?? true,
|
|
508
|
-
onProgress: options.notifyOnProgress ?? false,
|
|
509
|
-
notifyHuman: options.notifyHuman ?? false
|
|
510
|
-
},
|
|
511
|
-
metadata: options.metadata,
|
|
512
|
-
tags: options.tags ?? []
|
|
513
|
-
};
|
|
514
|
-
this.convoys.set(convoy.id, convoy);
|
|
515
|
-
await this.persistConvoy(convoy);
|
|
516
|
-
this.emit("convoy:created", convoy);
|
|
517
|
-
return convoy;
|
|
518
|
-
}
|
|
519
|
-
/**
|
|
520
|
-
* Add task to convoy
|
|
521
|
-
*/
|
|
522
|
-
async addTask(convoyId, title, options = {}) {
|
|
523
|
-
await this.ensureInitialized();
|
|
524
|
-
const convoy = this.convoys.get(convoyId);
|
|
525
|
-
if (!convoy) {
|
|
526
|
-
throw new Error(`Convoy not found: ${convoyId}`);
|
|
527
|
-
}
|
|
528
|
-
const task = {
|
|
529
|
-
id: `task-${nanoid(6)}`,
|
|
530
|
-
title,
|
|
531
|
-
description: options.description ?? "",
|
|
532
|
-
status: "pending",
|
|
533
|
-
assignedTo: options.assignedTo,
|
|
534
|
-
dependsOn: options.dependsOn ?? [],
|
|
535
|
-
metadata: options.metadata
|
|
536
|
-
};
|
|
537
|
-
convoy.tasks.push(task);
|
|
538
|
-
convoy.totalTasks = convoy.tasks.length;
|
|
539
|
-
this.updateProgress(convoy);
|
|
540
|
-
await this.persistConvoy(convoy);
|
|
541
|
-
return task;
|
|
542
|
-
}
|
|
543
|
-
/**
|
|
544
|
-
* Add multiple tasks to convoy
|
|
545
|
-
*/
|
|
546
|
-
async addTasks(convoyId, tasks) {
|
|
547
|
-
const addedTasks = [];
|
|
548
|
-
for (const { title, options } of tasks) {
|
|
549
|
-
const task = await this.addTask(convoyId, title, options);
|
|
550
|
-
addedTasks.push(task);
|
|
551
|
-
}
|
|
552
|
-
return addedTasks;
|
|
553
|
-
}
|
|
554
|
-
/**
|
|
555
|
-
* Start convoy execution
|
|
556
|
-
*/
|
|
557
|
-
async start(convoyId) {
|
|
558
|
-
await this.ensureInitialized();
|
|
559
|
-
const convoy = this.convoys.get(convoyId);
|
|
560
|
-
if (!convoy) {
|
|
561
|
-
throw new Error(`Convoy not found: ${convoyId}`);
|
|
562
|
-
}
|
|
563
|
-
if (convoy.status !== "pending" && convoy.status !== "paused") {
|
|
564
|
-
throw new Error(`Cannot start convoy in status: ${convoy.status}`);
|
|
565
|
-
}
|
|
566
|
-
convoy.status = "in_progress";
|
|
567
|
-
convoy.startedAt = convoy.startedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
568
|
-
await this.persistConvoy(convoy);
|
|
569
|
-
this.emit("convoy:started", convoy);
|
|
570
|
-
}
|
|
571
|
-
/**
|
|
572
|
-
* Start a task
|
|
573
|
-
*/
|
|
574
|
-
async startTask(convoyId, taskId, assignedTo) {
|
|
575
|
-
await this.ensureInitialized();
|
|
576
|
-
const convoy = this.convoys.get(convoyId);
|
|
577
|
-
if (!convoy) {
|
|
578
|
-
throw new Error(`Convoy not found: ${convoyId}`);
|
|
579
|
-
}
|
|
580
|
-
const task = convoy.tasks.find((t) => t.id === taskId);
|
|
581
|
-
if (!task) {
|
|
582
|
-
throw new Error(`Task not found: ${taskId}`);
|
|
583
|
-
}
|
|
584
|
-
const unmetDeps = this.getUnmetDependencies(convoy, task);
|
|
585
|
-
if (unmetDeps.length > 0) {
|
|
586
|
-
throw new Error(`Task has unmet dependencies: ${unmetDeps.join(", ")}`);
|
|
587
|
-
}
|
|
588
|
-
task.status = "in_progress";
|
|
589
|
-
task.startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
590
|
-
if (assignedTo) {
|
|
591
|
-
task.assignedTo = assignedTo;
|
|
592
|
-
}
|
|
593
|
-
if (convoy.status === "pending") {
|
|
594
|
-
convoy.status = "in_progress";
|
|
595
|
-
convoy.startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
596
|
-
}
|
|
597
|
-
await this.persistConvoy(convoy);
|
|
598
|
-
this.emit("task:started", convoy, task);
|
|
599
|
-
}
|
|
600
|
-
/**
|
|
601
|
-
* Complete a task
|
|
602
|
-
*/
|
|
603
|
-
async completeTask(convoyId, taskId, result) {
|
|
604
|
-
await this.ensureInitialized();
|
|
605
|
-
const convoy = this.convoys.get(convoyId);
|
|
606
|
-
if (!convoy) {
|
|
607
|
-
throw new Error(`Convoy not found: ${convoyId}`);
|
|
608
|
-
}
|
|
609
|
-
const task = convoy.tasks.find((t) => t.id === taskId);
|
|
610
|
-
if (!task) {
|
|
611
|
-
throw new Error(`Task not found: ${taskId}`);
|
|
612
|
-
}
|
|
613
|
-
task.status = "completed";
|
|
614
|
-
task.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
615
|
-
task.result = result;
|
|
616
|
-
convoy.completedTasks++;
|
|
617
|
-
this.updateProgress(convoy);
|
|
618
|
-
this.checkConvoyCompletion(convoy);
|
|
619
|
-
await this.persistConvoy(convoy);
|
|
620
|
-
this.emit("task:completed", convoy, task);
|
|
621
|
-
if (convoy.notifications.onProgress) {
|
|
622
|
-
this.emit("convoy:progress", convoy, convoy.progress);
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
/**
|
|
626
|
-
* Fail a task
|
|
627
|
-
*/
|
|
628
|
-
async failTask(convoyId, taskId, error) {
|
|
629
|
-
await this.ensureInitialized();
|
|
630
|
-
const convoy = this.convoys.get(convoyId);
|
|
631
|
-
if (!convoy) {
|
|
632
|
-
throw new Error(`Convoy not found: ${convoyId}`);
|
|
633
|
-
}
|
|
634
|
-
const task = convoy.tasks.find((t) => t.id === taskId);
|
|
635
|
-
if (!task) {
|
|
636
|
-
throw new Error(`Task not found: ${taskId}`);
|
|
637
|
-
}
|
|
638
|
-
task.status = "failed";
|
|
639
|
-
task.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
640
|
-
task.error = error;
|
|
641
|
-
convoy.failedTasks++;
|
|
642
|
-
this.updateProgress(convoy);
|
|
643
|
-
await this.skipDependentTasks(convoy, taskId);
|
|
644
|
-
this.checkConvoyCompletion(convoy);
|
|
645
|
-
await this.persistConvoy(convoy);
|
|
646
|
-
this.emit("task:failed", convoy, task);
|
|
647
|
-
if (convoy.notifications.onFailure) {
|
|
648
|
-
this.emit("convoy:failed", convoy);
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
/**
|
|
652
|
-
* Cancel a task
|
|
653
|
-
*/
|
|
654
|
-
async cancelTask(convoyId, taskId) {
|
|
655
|
-
await this.ensureInitialized();
|
|
656
|
-
const convoy = this.convoys.get(convoyId);
|
|
657
|
-
if (!convoy) {
|
|
658
|
-
throw new Error(`Convoy not found: ${convoyId}`);
|
|
659
|
-
}
|
|
660
|
-
const task = convoy.tasks.find((t) => t.id === taskId);
|
|
661
|
-
if (!task) {
|
|
662
|
-
throw new Error(`Task not found: ${taskId}`);
|
|
663
|
-
}
|
|
664
|
-
task.status = "cancelled";
|
|
665
|
-
task.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
666
|
-
convoy.cancelledTasks++;
|
|
667
|
-
this.updateProgress(convoy);
|
|
668
|
-
await this.skipDependentTasks(convoy, taskId);
|
|
669
|
-
this.checkConvoyCompletion(convoy);
|
|
670
|
-
await this.persistConvoy(convoy);
|
|
671
|
-
this.emit("task:cancelled", convoy, task);
|
|
672
|
-
}
|
|
673
|
-
/**
|
|
674
|
-
* Pause convoy
|
|
675
|
-
*/
|
|
676
|
-
async pause(convoyId) {
|
|
677
|
-
await this.ensureInitialized();
|
|
678
|
-
const convoy = this.convoys.get(convoyId);
|
|
679
|
-
if (!convoy) {
|
|
680
|
-
throw new Error(`Convoy not found: ${convoyId}`);
|
|
681
|
-
}
|
|
682
|
-
if (convoy.status !== "in_progress") {
|
|
683
|
-
throw new Error(`Cannot pause convoy in status: ${convoy.status}`);
|
|
684
|
-
}
|
|
685
|
-
convoy.status = "paused";
|
|
686
|
-
await this.persistConvoy(convoy);
|
|
687
|
-
this.emit("convoy:paused", convoy);
|
|
688
|
-
}
|
|
689
|
-
/**
|
|
690
|
-
* Resume convoy
|
|
691
|
-
*/
|
|
692
|
-
async resume(convoyId) {
|
|
693
|
-
await this.ensureInitialized();
|
|
694
|
-
const convoy = this.convoys.get(convoyId);
|
|
695
|
-
if (!convoy) {
|
|
696
|
-
throw new Error(`Convoy not found: ${convoyId}`);
|
|
697
|
-
}
|
|
698
|
-
if (convoy.status !== "paused") {
|
|
699
|
-
throw new Error(`Cannot resume convoy in status: ${convoy.status}`);
|
|
700
|
-
}
|
|
701
|
-
convoy.status = "in_progress";
|
|
702
|
-
await this.persistConvoy(convoy);
|
|
703
|
-
this.emit("convoy:resumed", convoy);
|
|
704
|
-
}
|
|
705
|
-
/**
|
|
706
|
-
* Cancel convoy
|
|
707
|
-
*/
|
|
708
|
-
async cancel(convoyId) {
|
|
709
|
-
await this.ensureInitialized();
|
|
710
|
-
const convoy = this.convoys.get(convoyId);
|
|
711
|
-
if (!convoy) {
|
|
712
|
-
throw new Error(`Convoy not found: ${convoyId}`);
|
|
713
|
-
}
|
|
714
|
-
convoy.status = "cancelled";
|
|
715
|
-
convoy.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
716
|
-
for (const task of convoy.tasks) {
|
|
717
|
-
if (task.status === "pending" || task.status === "in_progress") {
|
|
718
|
-
task.status = "cancelled";
|
|
719
|
-
task.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
720
|
-
convoy.cancelledTasks++;
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
this.updateProgress(convoy);
|
|
724
|
-
await this.persistConvoy(convoy);
|
|
725
|
-
this.emit("convoy:cancelled", convoy);
|
|
726
|
-
}
|
|
727
|
-
/**
|
|
728
|
-
* Get convoy by ID
|
|
729
|
-
*/
|
|
730
|
-
get(convoyId) {
|
|
731
|
-
return this.convoys.get(convoyId);
|
|
732
|
-
}
|
|
733
|
-
/**
|
|
734
|
-
* List all convoys
|
|
735
|
-
*/
|
|
736
|
-
list(filter) {
|
|
737
|
-
let convoys = Array.from(this.convoys.values());
|
|
738
|
-
if (filter) {
|
|
739
|
-
if (filter.status) {
|
|
740
|
-
convoys = convoys.filter((c) => c.status === filter.status);
|
|
741
|
-
}
|
|
742
|
-
if (filter.createdBy) {
|
|
743
|
-
convoys = convoys.filter((c) => c.createdBy === filter.createdBy);
|
|
744
|
-
}
|
|
745
|
-
if (filter.tags && filter.tags.length > 0) {
|
|
746
|
-
convoys = convoys.filter(
|
|
747
|
-
(c) => filter.tags.some((tag) => c.tags.includes(tag))
|
|
748
|
-
);
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
return convoys.sort(
|
|
752
|
-
(a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
|
|
753
|
-
);
|
|
754
|
-
}
|
|
755
|
-
/**
|
|
756
|
-
* Get active convoys
|
|
757
|
-
*/
|
|
758
|
-
getActive() {
|
|
759
|
-
return this.list({ status: "in_progress" });
|
|
760
|
-
}
|
|
761
|
-
/**
|
|
762
|
-
* Get next available tasks (no unmet dependencies)
|
|
763
|
-
*/
|
|
764
|
-
getNextTasks(convoyId) {
|
|
765
|
-
const convoy = this.convoys.get(convoyId);
|
|
766
|
-
if (!convoy)
|
|
767
|
-
return [];
|
|
768
|
-
return convoy.tasks.filter((task) => {
|
|
769
|
-
if (task.status !== "pending")
|
|
770
|
-
return false;
|
|
771
|
-
return this.getUnmetDependencies(convoy, task).length === 0;
|
|
772
|
-
});
|
|
773
|
-
}
|
|
774
|
-
/**
|
|
775
|
-
* Get convoy summary
|
|
776
|
-
*/
|
|
777
|
-
getSummary(convoyId) {
|
|
778
|
-
const convoy = this.convoys.get(convoyId);
|
|
779
|
-
if (!convoy)
|
|
780
|
-
return "Convoy not found";
|
|
781
|
-
const lines = [
|
|
782
|
-
`Convoy: ${convoy.name} (${convoy.id})`,
|
|
783
|
-
`Status: ${convoy.status}`,
|
|
784
|
-
`Progress: ${convoy.progress}%`,
|
|
785
|
-
`Tasks: ${convoy.completedTasks}/${convoy.totalTasks} completed`
|
|
786
|
-
];
|
|
787
|
-
if (convoy.failedTasks > 0) {
|
|
788
|
-
lines.push(`Failed: ${convoy.failedTasks}`);
|
|
789
|
-
}
|
|
790
|
-
if (convoy.cancelledTasks > 0) {
|
|
791
|
-
lines.push(`Cancelled: ${convoy.cancelledTasks}`);
|
|
792
|
-
}
|
|
793
|
-
if (convoy.skippedTasks > 0) {
|
|
794
|
-
lines.push(`Skipped: ${convoy.skippedTasks}`);
|
|
795
|
-
}
|
|
796
|
-
return lines.join("\n");
|
|
797
|
-
}
|
|
798
|
-
/**
|
|
799
|
-
* Delete convoy
|
|
800
|
-
*/
|
|
801
|
-
async delete(convoyId) {
|
|
802
|
-
await this.ensureInitialized();
|
|
803
|
-
const convoy = this.convoys.get(convoyId);
|
|
804
|
-
if (!convoy)
|
|
805
|
-
return false;
|
|
806
|
-
this.convoys.delete(convoyId);
|
|
807
|
-
return true;
|
|
808
|
-
}
|
|
809
|
-
// ========================================================================
|
|
810
|
-
// Private Methods
|
|
811
|
-
// ========================================================================
|
|
812
|
-
async ensureInitialized() {
|
|
813
|
-
if (!this.initialized) {
|
|
814
|
-
await this.initialize();
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
updateProgress(convoy) {
|
|
818
|
-
const processed = convoy.completedTasks + convoy.failedTasks + convoy.cancelledTasks + convoy.skippedTasks;
|
|
819
|
-
convoy.progress = convoy.totalTasks > 0 ? Math.round(processed / convoy.totalTasks * 100) : 0;
|
|
820
|
-
}
|
|
821
|
-
checkConvoyCompletion(convoy) {
|
|
822
|
-
const processed = convoy.completedTasks + convoy.failedTasks + convoy.cancelledTasks + convoy.skippedTasks;
|
|
823
|
-
if (processed === convoy.totalTasks) {
|
|
824
|
-
convoy.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
825
|
-
if (convoy.failedTasks === 0 && convoy.cancelledTasks === 0) {
|
|
826
|
-
convoy.status = "completed";
|
|
827
|
-
if (convoy.notifications.onComplete) {
|
|
828
|
-
this.emit("convoy:completed", convoy);
|
|
829
|
-
}
|
|
830
|
-
} else {
|
|
831
|
-
convoy.status = "failed";
|
|
832
|
-
if (convoy.notifications.onFailure) {
|
|
833
|
-
this.emit("convoy:failed", convoy);
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
getUnmetDependencies(convoy, task) {
|
|
839
|
-
return task.dependsOn.filter((depId) => {
|
|
840
|
-
const depTask = convoy.tasks.find((t) => t.id === depId);
|
|
841
|
-
return !depTask || depTask.status !== "completed";
|
|
842
|
-
});
|
|
843
|
-
}
|
|
844
|
-
async skipDependentTasks(convoy, failedTaskId) {
|
|
845
|
-
for (const task of convoy.tasks) {
|
|
846
|
-
if (task.status === "pending" && task.dependsOn.includes(failedTaskId)) {
|
|
847
|
-
task.status = "skipped";
|
|
848
|
-
task.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
849
|
-
task.error = `Skipped due to failed dependency: ${failedTaskId}`;
|
|
850
|
-
convoy.skippedTasks++;
|
|
851
|
-
this.emit("task:skipped", convoy, task);
|
|
852
|
-
await this.skipDependentTasks(convoy, task.id);
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
async loadConvoys() {
|
|
857
|
-
for (const agentId of this.stateManager.getAgentIds()) {
|
|
858
|
-
if (agentId.startsWith("convoy-")) {
|
|
859
|
-
const state = await this.stateManager.loadState(agentId);
|
|
860
|
-
if (state) {
|
|
861
|
-
const convoy = state;
|
|
862
|
-
this.convoys.set(convoy.id, convoy);
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
async persistConvoy(convoy) {
|
|
868
|
-
await this.stateManager.createAgentWorktree(`convoy-${convoy.id}`);
|
|
869
|
-
await this.stateManager.saveState(`convoy-${convoy.id}`, convoy);
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
let globalConvoyManager = null;
|
|
873
|
-
function getGlobalConvoyManager() {
|
|
874
|
-
if (!globalConvoyManager) {
|
|
875
|
-
globalConvoyManager = new ConvoyManager();
|
|
876
|
-
}
|
|
877
|
-
return globalConvoyManager;
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
const convoyManager = {
|
|
881
|
-
__proto__: null,
|
|
882
|
-
ConvoyManager: ConvoyManager,
|
|
883
|
-
getGlobalConvoyManager: getGlobalConvoyManager
|
|
884
|
-
};
|
|
885
|
-
|
|
886
|
-
const DEPTH_TOKEN_BUDGETS = {
|
|
887
|
-
L0: 100,
|
|
888
|
-
// Abstract summary only
|
|
889
|
-
L1: 2e3,
|
|
890
|
-
// Overview
|
|
891
|
-
L2: Number.POSITIVE_INFINITY
|
|
892
|
-
// Full content
|
|
893
|
-
};
|
|
894
|
-
const PHASE_BUDGET_MULTIPLIERS = {
|
|
895
|
-
exploring: 2,
|
|
896
|
-
executing: 0.6,
|
|
897
|
-
generating: 0.4,
|
|
898
|
-
reviewing: 1.2,
|
|
899
|
-
idle: 1
|
|
900
|
-
};
|
|
901
|
-
const CHARS_PER_TOKEN = 4;
|
|
902
|
-
function estimateTokens(text) {
|
|
903
|
-
return Math.ceil(text.length / CHARS_PER_TOKEN);
|
|
904
|
-
}
|
|
905
|
-
function truncateToDepth(content, depth) {
|
|
906
|
-
if (depth === "L2")
|
|
907
|
-
return content;
|
|
908
|
-
const maxChars = DEPTH_TOKEN_BUDGETS[depth] * CHARS_PER_TOKEN;
|
|
909
|
-
if (content.length <= maxChars)
|
|
910
|
-
return content;
|
|
911
|
-
if (depth === "L0") {
|
|
912
|
-
const firstPara = content.split(/\n\n/)[0];
|
|
913
|
-
return firstPara.length <= maxChars ? firstPara : content.slice(0, maxChars);
|
|
914
|
-
}
|
|
915
|
-
return `${content.slice(0, maxChars)}
|
|
916
|
-
... (truncated, use L2 for full content)`;
|
|
917
|
-
}
|
|
918
|
-
class ContextLoader {
|
|
919
|
-
cache = /* @__PURE__ */ new Map();
|
|
920
|
-
defaultMaxSize = 1e5;
|
|
921
|
-
// 100KB default
|
|
922
|
-
defaultTokenBudget = 8e3;
|
|
923
|
-
// ~32KB at 4 chars/token
|
|
924
|
-
/**
|
|
925
|
-
* Resolve effective depth from options.
|
|
926
|
-
* If depth is explicit, use it. Otherwise derive from tokenBudget.
|
|
927
|
-
*/
|
|
928
|
-
resolveDepth(tokenBudget, explicitDepth) {
|
|
929
|
-
if (explicitDepth)
|
|
930
|
-
return explicitDepth;
|
|
931
|
-
if (tokenBudget <= DEPTH_TOKEN_BUDGETS.L0)
|
|
932
|
-
return "L0";
|
|
933
|
-
if (tokenBudget <= DEPTH_TOKEN_BUDGETS.L1)
|
|
934
|
-
return "L1";
|
|
935
|
-
return "L2";
|
|
936
|
-
}
|
|
937
|
-
/**
|
|
938
|
-
* Load context hierarchically with OpenViking-style tiered depth control.
|
|
939
|
-
* Pass tokenBudget to automatically select L0/L1/L2 depth.
|
|
940
|
-
*/
|
|
941
|
-
async load(options = {}) {
|
|
942
|
-
const {
|
|
943
|
-
projectRoot = process.cwd(),
|
|
944
|
-
maxSize = this.defaultMaxSize,
|
|
945
|
-
tokenBudget,
|
|
946
|
-
depth: explicitDepth,
|
|
947
|
-
layers = ["project", "domain", "task", "execution"],
|
|
948
|
-
task
|
|
949
|
-
} = options;
|
|
950
|
-
const phaseMultiplier = options.taskPhase ? PHASE_BUDGET_MULTIPLIERS[options.taskPhase] ?? 1 : 1;
|
|
951
|
-
const effectiveBudget = Math.round((tokenBudget ?? this.defaultTokenBudget) * phaseMultiplier);
|
|
952
|
-
const depth = this.resolveDepth(effectiveBudget, explicitDepth);
|
|
953
|
-
const cacheKey = this.getCacheKey(projectRoot, layers, task?.id, depth);
|
|
954
|
-
const cached = this.cache.get(cacheKey);
|
|
955
|
-
if (cached && Date.now() - cached.loadedAt < 6e4) {
|
|
956
|
-
executionTracer.logEvent("context-load", {
|
|
957
|
-
source: "cache",
|
|
958
|
-
layers: layers.length,
|
|
959
|
-
size: cached.totalSize,
|
|
960
|
-
tokens: cached.totalTokens,
|
|
961
|
-
depth
|
|
962
|
-
});
|
|
963
|
-
return cached;
|
|
964
|
-
}
|
|
965
|
-
const context = {
|
|
966
|
-
layers: /* @__PURE__ */ new Map(),
|
|
967
|
-
totalSize: 0,
|
|
968
|
-
totalTokens: 0,
|
|
969
|
-
loadedAt: Date.now(),
|
|
970
|
-
depth
|
|
971
|
-
};
|
|
972
|
-
for (const layer of layers) {
|
|
973
|
-
const entries = await this.loadLayer(layer, projectRoot, task, depth);
|
|
974
|
-
if (entries.length > 0) {
|
|
975
|
-
context.layers.set(layer, entries);
|
|
976
|
-
context.totalSize += entries.reduce((sum, e) => sum + e.content.length, 0);
|
|
977
|
-
context.totalTokens += entries.reduce((sum, e) => sum + e.tokenEstimate, 0);
|
|
978
|
-
}
|
|
979
|
-
if (context.totalSize > maxSize || context.totalTokens > effectiveBudget) {
|
|
980
|
-
break;
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
this.cache.set(cacheKey, context);
|
|
984
|
-
executionTracer.logEvent("context-load", {
|
|
985
|
-
source: "fresh",
|
|
986
|
-
layers: context.layers.size,
|
|
987
|
-
size: context.totalSize,
|
|
988
|
-
tokens: context.totalTokens,
|
|
989
|
-
depth
|
|
990
|
-
});
|
|
991
|
-
return context;
|
|
992
|
-
}
|
|
993
|
-
/**
|
|
994
|
-
* Load a specific context layer
|
|
995
|
-
*/
|
|
996
|
-
async loadLayer(layer, projectRoot, task, depth = "L2") {
|
|
997
|
-
switch (layer) {
|
|
998
|
-
case "project":
|
|
999
|
-
return this.loadProjectContext(projectRoot, depth);
|
|
1000
|
-
case "domain":
|
|
1001
|
-
return this.loadDomainContext(projectRoot, task, depth);
|
|
1002
|
-
case "task":
|
|
1003
|
-
return this.loadTaskContext(task, depth);
|
|
1004
|
-
case "execution":
|
|
1005
|
-
return this.loadExecutionContext(task, depth);
|
|
1006
|
-
default:
|
|
1007
|
-
return [];
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1010
|
-
/**
|
|
1011
|
-
* Load project-level context
|
|
1012
|
-
* - README.md
|
|
1013
|
-
* - CLAUDE.md
|
|
1014
|
-
* - package.json
|
|
1015
|
-
* - tsconfig.json
|
|
1016
|
-
*/
|
|
1017
|
-
async loadProjectContext(projectRoot, depth = "L2") {
|
|
1018
|
-
const entries = [];
|
|
1019
|
-
const files = ["README.md", "CLAUDE.md", "package.json", "tsconfig.json"];
|
|
1020
|
-
for (const file of files) {
|
|
1021
|
-
const path = join(projectRoot, file);
|
|
1022
|
-
if (existsSync(path)) {
|
|
1023
|
-
const raw = readFileSync(path, "utf-8");
|
|
1024
|
-
const content = truncateToDepth(raw, depth);
|
|
1025
|
-
entries.push({
|
|
1026
|
-
layer: "project",
|
|
1027
|
-
source: file,
|
|
1028
|
-
content,
|
|
1029
|
-
priority: 100,
|
|
1030
|
-
depth,
|
|
1031
|
-
tokenEstimate: estimateTokens(content),
|
|
1032
|
-
metadata: { path }
|
|
1033
|
-
});
|
|
1034
|
-
}
|
|
1035
|
-
}
|
|
1036
|
-
return entries;
|
|
1037
|
-
}
|
|
1038
|
-
/**
|
|
1039
|
-
* Load domain-specific context
|
|
1040
|
-
* Based on task type/domain, load relevant files
|
|
1041
|
-
*/
|
|
1042
|
-
async loadDomainContext(projectRoot, task, depth = "L2") {
|
|
1043
|
-
if (!task)
|
|
1044
|
-
return [];
|
|
1045
|
-
const entries = [];
|
|
1046
|
-
const structure = await fsParadigm.detect(projectRoot);
|
|
1047
|
-
const domain = this.inferDomain(task);
|
|
1048
|
-
if (!domain) {
|
|
1049
|
-
const sourceFiles = fsParadigm.getFilesByRole(structure, "source");
|
|
1050
|
-
for (const file of sourceFiles.slice(0, 3)) {
|
|
1051
|
-
try {
|
|
1052
|
-
const raw = readFileSync(file, "utf-8");
|
|
1053
|
-
const content = truncateToDepth(raw, depth);
|
|
1054
|
-
entries.push({
|
|
1055
|
-
layer: "domain",
|
|
1056
|
-
source: file.replace(projectRoot, ""),
|
|
1057
|
-
content,
|
|
1058
|
-
priority: 75,
|
|
1059
|
-
depth,
|
|
1060
|
-
tokenEstimate: estimateTokens(content),
|
|
1061
|
-
metadata: { paradigm: structure.paradigm, path: file }
|
|
1062
|
-
});
|
|
1063
|
-
} catch {
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
return entries;
|
|
1067
|
-
}
|
|
1068
|
-
const patterns = this.getDomainPatterns(domain, structure.paradigm);
|
|
1069
|
-
for (const pattern of patterns) {
|
|
1070
|
-
const files = await glob([pattern], {
|
|
1071
|
-
cwd: projectRoot,
|
|
1072
|
-
absolute: true,
|
|
1073
|
-
ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"]
|
|
1074
|
-
});
|
|
1075
|
-
for (const file of files.slice(0, 5)) {
|
|
1076
|
-
try {
|
|
1077
|
-
const raw = readFileSync(file, "utf-8");
|
|
1078
|
-
const content = truncateToDepth(raw, depth);
|
|
1079
|
-
entries.push({
|
|
1080
|
-
layer: "domain",
|
|
1081
|
-
source: file.replace(projectRoot, ""),
|
|
1082
|
-
content,
|
|
1083
|
-
priority: 80,
|
|
1084
|
-
depth,
|
|
1085
|
-
tokenEstimate: estimateTokens(content),
|
|
1086
|
-
metadata: { domain, paradigm: structure.paradigm, path: file }
|
|
1087
|
-
});
|
|
1088
|
-
} catch {
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
}
|
|
1092
|
-
return entries;
|
|
1093
|
-
}
|
|
1094
|
-
/**
|
|
1095
|
-
* Load task-specific context
|
|
1096
|
-
*/
|
|
1097
|
-
async loadTaskContext(task, depth = "L2") {
|
|
1098
|
-
if (!task)
|
|
1099
|
-
return [];
|
|
1100
|
-
const entries = [];
|
|
1101
|
-
if (task.description) {
|
|
1102
|
-
const content = truncateToDepth(task.description, depth);
|
|
1103
|
-
entries.push({
|
|
1104
|
-
layer: "task",
|
|
1105
|
-
source: "task-description",
|
|
1106
|
-
content,
|
|
1107
|
-
priority: 90,
|
|
1108
|
-
depth,
|
|
1109
|
-
tokenEstimate: estimateTokens(content),
|
|
1110
|
-
metadata: { taskId: task.id }
|
|
1111
|
-
});
|
|
1112
|
-
}
|
|
1113
|
-
if (task.input && depth !== "L0") {
|
|
1114
|
-
const content = truncateToDepth(JSON.stringify(task.input, null, 2), depth);
|
|
1115
|
-
entries.push({
|
|
1116
|
-
layer: "task",
|
|
1117
|
-
source: "task-input",
|
|
1118
|
-
content,
|
|
1119
|
-
priority: 85,
|
|
1120
|
-
depth,
|
|
1121
|
-
tokenEstimate: estimateTokens(content),
|
|
1122
|
-
metadata: { taskId: task.id }
|
|
1123
|
-
});
|
|
1124
|
-
}
|
|
1125
|
-
return entries;
|
|
1126
|
-
}
|
|
1127
|
-
/**
|
|
1128
|
-
* Load execution-specific context
|
|
1129
|
-
* - Recent errors
|
|
1130
|
-
* - Previous attempts
|
|
1131
|
-
* - Related task outputs
|
|
1132
|
-
*/
|
|
1133
|
-
async loadExecutionContext(task, depth = "L2") {
|
|
1134
|
-
if (!task)
|
|
1135
|
-
return [];
|
|
1136
|
-
const entries = [];
|
|
1137
|
-
if (task.output && depth !== "L0") {
|
|
1138
|
-
const content = truncateToDepth(JSON.stringify(task.output, null, 2), depth);
|
|
1139
|
-
entries.push({
|
|
1140
|
-
layer: "execution",
|
|
1141
|
-
source: "previous-output",
|
|
1142
|
-
content,
|
|
1143
|
-
priority: 70,
|
|
1144
|
-
depth,
|
|
1145
|
-
tokenEstimate: estimateTokens(content),
|
|
1146
|
-
metadata: { taskId: task.id }
|
|
1147
|
-
});
|
|
1148
|
-
}
|
|
1149
|
-
return entries;
|
|
1150
|
-
}
|
|
1151
|
-
/**
|
|
1152
|
-
* Infer domain from task
|
|
1153
|
-
*/
|
|
1154
|
-
inferDomain(task) {
|
|
1155
|
-
const text = `${task.name} ${task.description || ""}`.toLowerCase();
|
|
1156
|
-
const domains = {
|
|
1157
|
-
api: ["api", "endpoint", "route", "controller"],
|
|
1158
|
-
ui: ["ui", "component", "view", "page", "frontend"],
|
|
1159
|
-
database: ["database", "db", "schema", "migration", "model"],
|
|
1160
|
-
auth: ["auth", "login", "user", "permission", "session"],
|
|
1161
|
-
test: ["test", "spec", "e2e", "unit", "integration"],
|
|
1162
|
-
config: ["config", "settings", "env", "setup"]
|
|
1163
|
-
};
|
|
1164
|
-
for (const [domain, keywords] of Object.entries(domains)) {
|
|
1165
|
-
if (keywords.some((kw) => text.includes(kw))) {
|
|
1166
|
-
return domain;
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
return null;
|
|
1170
|
-
}
|
|
1171
|
-
/**
|
|
1172
|
-
* Get file patterns for a domain (paradigm-aware)
|
|
1173
|
-
*/
|
|
1174
|
-
getDomainPatterns(domain, paradigm) {
|
|
1175
|
-
const basePatterns = {
|
|
1176
|
-
api: ["**/api/**/*.ts", "**/routes/**/*.ts", "**/controllers/**/*.ts"],
|
|
1177
|
-
ui: ["**/components/**/*.{tsx,vue}", "**/pages/**/*.{tsx,vue}", "**/views/**/*.{tsx,vue}"],
|
|
1178
|
-
database: ["**/models/**/*.ts", "**/schema/**/*.ts", "**/migrations/**/*.ts"],
|
|
1179
|
-
auth: ["**/auth/**/*.ts", "**/middleware/auth*.ts"],
|
|
1180
|
-
test: ["**/*.test.ts", "**/*.spec.ts"],
|
|
1181
|
-
config: ["**/config/**/*.ts", "**/*.config.ts"]
|
|
1182
|
-
};
|
|
1183
|
-
let patterns = basePatterns[domain] || [];
|
|
1184
|
-
if (paradigm === "monorepo") {
|
|
1185
|
-
patterns = patterns.map((p) => `packages/*/${p}`);
|
|
1186
|
-
} else if (paradigm === "fullstack") {
|
|
1187
|
-
if (domain === "ui") {
|
|
1188
|
-
patterns = patterns.map((p) => `client/${p}`);
|
|
1189
|
-
} else if (domain === "api") {
|
|
1190
|
-
patterns = patterns.map((p) => `server/${p}`);
|
|
1191
|
-
}
|
|
1192
|
-
}
|
|
1193
|
-
return patterns;
|
|
1194
|
-
}
|
|
1195
|
-
/**
|
|
1196
|
-
* Get cache key
|
|
1197
|
-
*/
|
|
1198
|
-
getCacheKey(projectRoot, layers, taskId, depth = "L2") {
|
|
1199
|
-
return `${projectRoot}:${layers.join(",")}:${taskId || "none"}:${depth}`;
|
|
1200
|
-
}
|
|
1201
|
-
/**
|
|
1202
|
-
* Clear cache
|
|
1203
|
-
*/
|
|
1204
|
-
clearCache() {
|
|
1205
|
-
this.cache.clear();
|
|
1206
|
-
}
|
|
1207
|
-
/**
|
|
1208
|
-
* Format context for LLM consumption
|
|
1209
|
-
*/
|
|
1210
|
-
formatForLLM(context) {
|
|
1211
|
-
const sections = [];
|
|
1212
|
-
sections.push(`<!-- context depth=${context.depth} tokens\u2248${context.totalTokens} -->
|
|
1213
|
-
`);
|
|
1214
|
-
const layerOrder = ["project", "domain", "task", "execution"];
|
|
1215
|
-
for (const layer of layerOrder) {
|
|
1216
|
-
const entries = context.layers.get(layer);
|
|
1217
|
-
if (!entries || entries.length === 0)
|
|
1218
|
-
continue;
|
|
1219
|
-
sections.push(`# ${layer.toUpperCase()} CONTEXT
|
|
1220
|
-
`);
|
|
1221
|
-
const sorted = entries.sort((a, b) => b.priority - a.priority);
|
|
1222
|
-
for (const entry of sorted) {
|
|
1223
|
-
sections.push(`## ${entry.source} [${entry.depth}]
|
|
1224
|
-
`);
|
|
1225
|
-
sections.push(entry.content);
|
|
1226
|
-
sections.push("\n");
|
|
1227
|
-
}
|
|
1228
|
-
}
|
|
1229
|
-
return sections.join("\n");
|
|
1230
|
-
}
|
|
1231
|
-
}
|
|
1232
|
-
const contextLoader = new ContextLoader();
|
|
1233
|
-
async function loadContextAtDepth(depth, options = {}) {
|
|
1234
|
-
return contextLoader.load({ ...options, depth });
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
const contextLoader$1 = {
|
|
1238
|
-
__proto__: null,
|
|
1239
|
-
ContextLoader: ContextLoader,
|
|
1240
|
-
contextLoader: contextLoader,
|
|
1241
|
-
loadContextAtDepth: loadContextAtDepth
|
|
1242
|
-
};
|
|
1243
|
-
|
|
1244
|
-
function detectTaskPhase(history) {
|
|
1245
|
-
if (history.length === 0)
|
|
1246
|
-
return "idle";
|
|
1247
|
-
const recent = history.slice(-10);
|
|
1248
|
-
const recentText = recent.map((h) => h.content).join(" ").toLowerCase();
|
|
1249
|
-
if (recentText.includes("write") || recentText.includes("create") || recentText.includes("generating"))
|
|
1250
|
-
return "generating";
|
|
1251
|
-
if (recentText.includes("test") || recentText.includes("review") || recentText.includes("check"))
|
|
1252
|
-
return "reviewing";
|
|
1253
|
-
if (recentText.includes("edit") || recentText.includes("bash") || recentText.includes("run"))
|
|
1254
|
-
return "executing";
|
|
1255
|
-
if (recentText.includes("read") || recentText.includes("search") || recentText.includes("grep"))
|
|
1256
|
-
return "exploring";
|
|
1257
|
-
return "idle";
|
|
1258
|
-
}
|
|
1259
|
-
function extractFilePaths(content) {
|
|
1260
|
-
const matches = content.match(/\/[\w./\-]+\.\w+|[\w./\-]+\.(?:ts|js|json|md|py|go|rs)/g);
|
|
1261
|
-
return matches ? [...new Set(matches)] : [];
|
|
1262
|
-
}
|
|
1263
|
-
class SessionIntelligence {
|
|
1264
|
-
static instance = null;
|
|
1265
|
-
session;
|
|
1266
|
-
constructor(session) {
|
|
1267
|
-
this.session = session;
|
|
1268
|
-
if (!session.intelligence) {
|
|
1269
|
-
session.intelligence = {
|
|
1270
|
-
taskPhase: "idle",
|
|
1271
|
-
filesTouched: [],
|
|
1272
|
-
keyDecisions: [],
|
|
1273
|
-
toolCallCount: 0,
|
|
1274
|
-
compressionWatermark: 0
|
|
1275
|
-
};
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
get state() {
|
|
1279
|
-
return this.session.intelligence;
|
|
1280
|
-
}
|
|
1281
|
-
/**
|
|
1282
|
-
* Observe a new history entry and update intelligence state.
|
|
1283
|
-
* Call this after every message added to the session.
|
|
1284
|
-
*/
|
|
1285
|
-
observe(entry) {
|
|
1286
|
-
const intel = this.state;
|
|
1287
|
-
if (!intel.userOriginalIntent && entry.role === "user" && entry.content.trim().length > 10) {
|
|
1288
|
-
intel.userOriginalIntent = entry.content.slice(0, 500);
|
|
1289
|
-
}
|
|
1290
|
-
const files = extractFilePaths(entry.content);
|
|
1291
|
-
for (const f of files) {
|
|
1292
|
-
if (!intel.filesTouched.includes(f)) {
|
|
1293
|
-
intel.filesTouched.push(f);
|
|
1294
|
-
}
|
|
1295
|
-
}
|
|
1296
|
-
if (entry.role === "assistant" && /\b(bash|read|write|edit|grep|glob)\b/i.test(entry.content)) {
|
|
1297
|
-
intel.toolCallCount++;
|
|
1298
|
-
}
|
|
1299
|
-
intel.taskPhase = detectTaskPhase(this.session.history);
|
|
1300
|
-
}
|
|
1301
|
-
/**
|
|
1302
|
-
* Record a key decision explicitly.
|
|
1303
|
-
*/
|
|
1304
|
-
recordDecision(decision) {
|
|
1305
|
-
const intel = this.state;
|
|
1306
|
-
if (!intel.keyDecisions.includes(decision)) {
|
|
1307
|
-
intel.keyDecisions.push(decision.slice(0, 200));
|
|
1308
|
-
if (intel.keyDecisions.length > 20) {
|
|
1309
|
-
intel.keyDecisions.shift();
|
|
1310
|
-
}
|
|
1311
|
-
}
|
|
1312
|
-
}
|
|
1313
|
-
/**
|
|
1314
|
-
* Mark that history up to index N has been compressed.
|
|
1315
|
-
*/
|
|
1316
|
-
markCompressed(upToIndex) {
|
|
1317
|
-
this.state.compressionWatermark = upToIndex;
|
|
1318
|
-
}
|
|
1319
|
-
/**
|
|
1320
|
-
* Generate a system prompt injection that preserves intent across compaction.
|
|
1321
|
-
* Inject this whenever context is about to be compressed.
|
|
1322
|
-
*/
|
|
1323
|
-
getSystemPromptInjection() {
|
|
1324
|
-
const intel = this.state;
|
|
1325
|
-
const parts = ["<!-- session-intelligence -->"];
|
|
1326
|
-
if (intel.userOriginalIntent) {
|
|
1327
|
-
parts.push(`Original user intent: ${intel.userOriginalIntent}`);
|
|
1328
|
-
}
|
|
1329
|
-
if (intel.keyDecisions.length > 0) {
|
|
1330
|
-
parts.push(`Key decisions: ${intel.keyDecisions.join("; ")}`);
|
|
1331
|
-
}
|
|
1332
|
-
if (intel.filesTouched.length > 0) {
|
|
1333
|
-
parts.push(`Files touched: ${intel.filesTouched.slice(-20).join(", ")}`);
|
|
1334
|
-
}
|
|
1335
|
-
parts.push(`Task phase: ${intel.taskPhase} | Tool calls: ${intel.toolCallCount}`);
|
|
1336
|
-
parts.push("<!-- /session-intelligence -->");
|
|
1337
|
-
return parts.join("\n");
|
|
1338
|
-
}
|
|
1339
|
-
/**
|
|
1340
|
-
* Returns true if the session has enough context to be worth preserving.
|
|
1341
|
-
*/
|
|
1342
|
-
hasSignificantContext() {
|
|
1343
|
-
const intel = this.state;
|
|
1344
|
-
return !!intel.userOriginalIntent || intel.toolCallCount > 3 || intel.filesTouched.length > 0;
|
|
1345
|
-
}
|
|
1346
|
-
static getInstance() {
|
|
1347
|
-
if (!SessionIntelligence.instance) {
|
|
1348
|
-
SessionIntelligence.instance = new SessionIntelligence({
|
|
1349
|
-
id: "session-intelligence-singleton",
|
|
1350
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
1351
|
-
lastUsedAt: /* @__PURE__ */ new Date(),
|
|
1352
|
-
history: []
|
|
1353
|
-
});
|
|
1354
|
-
}
|
|
1355
|
-
return SessionIntelligence.instance;
|
|
1356
|
-
}
|
|
1357
|
-
recordMessage(role, content) {
|
|
1358
|
-
const entry = {
|
|
1359
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
1360
|
-
role,
|
|
1361
|
-
content
|
|
1362
|
-
};
|
|
1363
|
-
this.session.history.push(entry);
|
|
1364
|
-
this.observe(entry);
|
|
1365
|
-
}
|
|
1366
|
-
updatePhase(phase) {
|
|
1367
|
-
this.state.taskPhase = phase;
|
|
1368
|
-
}
|
|
1369
|
-
}
|
|
1370
|
-
|
|
1371
|
-
export { SessionIntelligence as S, getGlobalStateManager as a, gitBackedState as b, contextLoader as c, convoyManager as d, contextLoader$1 as e, getGlobalConvoyManager as g };
|