agents-inc 0.153.0 → 0.155.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/CHANGELOG.md +65 -0
- package/dist/chunk-2H7UWE2G.js +246 -0
- package/dist/chunk-2H7UWE2G.js.map +1 -0
- package/dist/{chunk-ZNDLUWWD.js → chunk-4A4L3YIW.js} +5 -5
- package/dist/chunk-4G2YHZIM.js +132 -0
- package/dist/chunk-4G2YHZIM.js.map +1 -0
- package/dist/{chunk-WDAO3RUY.js → chunk-5F2YR5XV.js} +3 -3
- package/dist/{chunk-JFAUQDZM.js → chunk-5OKLCVM4.js} +3 -3
- package/dist/{chunk-REKOWTIB.js → chunk-5QZAK6J7.js} +44 -10
- package/dist/chunk-5QZAK6J7.js.map +1 -0
- package/dist/{chunk-VECFAKM5.js → chunk-6RLV45HN.js} +10 -10
- package/dist/{chunk-VECFAKM5.js.map → chunk-6RLV45HN.js.map} +1 -1
- package/dist/{chunk-K7PJDWER.js → chunk-CLFHC2DK.js} +15 -106
- package/dist/chunk-CLFHC2DK.js.map +1 -0
- package/dist/chunk-D2CAV7MG.js +61 -0
- package/dist/chunk-D2CAV7MG.js.map +1 -0
- package/dist/{chunk-NXGMM5YN.js → chunk-F2AMBBIA.js} +6 -6
- package/dist/{chunk-NXGMM5YN.js.map → chunk-F2AMBBIA.js.map} +1 -1
- package/dist/{chunk-HEBPKK5L.js → chunk-F5T6TV4Z.js} +213 -92
- package/dist/chunk-F5T6TV4Z.js.map +1 -0
- package/dist/{chunk-K3O3YQYG.js → chunk-G47TDUK3.js} +2 -2
- package/dist/{chunk-U2DNAHFE.js → chunk-GS2NZ3GD.js} +8 -8
- package/dist/chunk-GS2NZ3GD.js.map +1 -0
- package/dist/{chunk-ORJ5Y222.js → chunk-H6UTKTLK.js} +176 -256
- package/dist/chunk-H6UTKTLK.js.map +1 -0
- package/dist/{chunk-M5HSTNYU.js → chunk-HG4JPXJT.js} +11 -29
- package/dist/chunk-HG4JPXJT.js.map +1 -0
- package/dist/{chunk-VGEBYCQZ.js → chunk-HTYH7CKN.js} +4 -15
- package/dist/chunk-HTYH7CKN.js.map +1 -0
- package/dist/{chunk-JC7DBPRD.js → chunk-HXKOIWLU.js} +2 -2
- package/dist/chunk-HXKOIWLU.js.map +1 -0
- package/dist/{chunk-NSJ2S7R5.js → chunk-ILUVL7WM.js} +2 -2
- package/dist/{chunk-R54KIGN2.js → chunk-IO5YBKHV.js} +13 -2
- package/dist/chunk-IO5YBKHV.js.map +1 -0
- package/dist/chunk-IXRZAHZF.js +53 -0
- package/dist/chunk-IXRZAHZF.js.map +1 -0
- package/dist/chunk-JCPANDNR.js +35 -0
- package/dist/chunk-JCPANDNR.js.map +1 -0
- package/dist/{chunk-R4SEU3DF.js → chunk-LJCNUP6M.js} +2 -2
- package/dist/{chunk-FRWKCE6R.js → chunk-MHRC3KRX.js} +5 -5
- package/dist/chunk-MHRC3KRX.js.map +1 -0
- package/dist/chunk-MO5FGLVS.js +142 -0
- package/dist/chunk-MO5FGLVS.js.map +1 -0
- package/dist/{chunk-Q5FLW4JG.js → chunk-OKH64JZE.js} +2 -2
- package/dist/{chunk-WG6V6VJV.js → chunk-PCC4LBKB.js} +2 -2
- package/dist/chunk-PMUABBPG.js +258 -0
- package/dist/chunk-PMUABBPG.js.map +1 -0
- package/dist/{chunk-EFU6P3B7.js → chunk-PNMM5HNX.js} +5 -5
- package/dist/{chunk-4VYALFQZ.js → chunk-QWVXOCXO.js} +6 -6
- package/dist/{chunk-35VOK7XE.js → chunk-RWOYPOMR.js} +4365 -4355
- package/dist/chunk-RWOYPOMR.js.map +1 -0
- package/dist/{chunk-IO4VEW5U.js → chunk-SY4X2LND.js} +4 -4
- package/dist/{chunk-XGMOXMS4.js → chunk-TBOVYLQJ.js} +2 -2
- package/dist/{chunk-BMGBA6HJ.js → chunk-TNGMF4UX.js} +20 -20
- package/dist/{chunk-BMGBA6HJ.js.map → chunk-TNGMF4UX.js.map} +1 -1
- package/dist/{chunk-TY6CAOL7.js → chunk-UMH2YZKG.js} +14 -5
- package/dist/chunk-UMH2YZKG.js.map +1 -0
- package/dist/{chunk-6CNRMCFM.js → chunk-VPASBA7P.js} +2 -2
- package/dist/{chunk-NXQAY5U7.js → chunk-WCAUUBHO.js} +5860 -5126
- package/dist/chunk-WCAUUBHO.js.map +1 -0
- package/dist/{chunk-V3ENMW7G.js → chunk-WFRTHH3A.js} +3 -3
- package/dist/{chunk-2HC2SNRP.js → chunk-WTJ3AY33.js} +1 -5
- package/dist/chunk-WTJ3AY33.js.map +1 -0
- package/dist/{chunk-F7Z5I6GU.js → chunk-WUQ3MTPF.js} +11 -5
- package/dist/{chunk-F7Z5I6GU.js.map → chunk-WUQ3MTPF.js.map} +1 -1
- package/dist/{chunk-U2YSGBHA.js → chunk-XAXJWXI4.js} +93 -43
- package/dist/chunk-XAXJWXI4.js.map +1 -0
- package/dist/{chunk-ACKC577F.js → chunk-Y5Y7XHVU.js} +4 -4
- package/dist/{chunk-X5XJ6WKO.js → chunk-YO2LTXB4.js} +107 -16
- package/dist/chunk-YO2LTXB4.js.map +1 -0
- package/dist/{chunk-FIHTAFST.js → chunk-ZUAZHDKP.js} +64 -65
- package/dist/chunk-ZUAZHDKP.js.map +1 -0
- package/dist/commands/build/marketplace.js +98 -120
- package/dist/commands/build/marketplace.js.map +1 -1
- package/dist/commands/build/plugins.js +8 -8
- package/dist/commands/compile.js +57 -24
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/doctor.js +220 -79
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +608 -100
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +26 -21
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/init.js +41 -39
- package/dist/commands/list.js +11 -11
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/new/marketplace.js +243 -0
- package/dist/commands/new/marketplace.js.map +1 -0
- package/dist/commands/search.js +34 -24
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/share.js +67 -0
- package/dist/commands/share.js.map +1 -0
- package/dist/commands/uninstall.js +234 -196
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +9 -9
- package/dist/commands/update.js.map +1 -1
- package/dist/components/common/prompt-confirm.js +1 -1
- package/dist/components/common/removal-plan-confirm.js +10 -0
- package/dist/components/common/select-list.js +2 -2
- package/dist/components/wizard/category-grid.js +5 -5
- package/dist/components/wizard/checkbox-grid.js +5 -5
- package/dist/components/wizard/domain-selection.js +11 -11
- package/dist/components/wizard/run-wizard-session.js +29 -28
- package/dist/components/wizard/scroll-affordance.js +2 -2
- package/dist/components/wizard/skill-agent-summary.js +6 -6
- package/dist/components/wizard/source-grid.js +6 -6
- package/dist/components/wizard/stack-selection.js +8 -8
- package/dist/components/wizard/step-agents.js +10 -11
- package/dist/components/wizard/step-build.js +9 -9
- package/dist/components/wizard/step-confirm.js +10 -10
- package/dist/components/wizard/step-sources.js +10 -10
- package/dist/components/wizard/step-stack.js +9 -9
- package/dist/components/wizard/summary-panel.js +9 -9
- package/dist/components/wizard/toast.js +2 -2
- package/dist/components/wizard/wizard-layout.js +14 -14
- package/dist/components/wizard/wizard-tabs.js +2 -2
- package/dist/components/wizard/wizard.js +27 -27
- package/dist/copy-local-skills-NSUTBVLJ.js +14 -0
- package/dist/hooks/init.js +42 -62
- package/dist/hooks/init.js.map +1 -1
- package/dist/load-agent-defs-X4E57I2U.js +15 -0
- package/dist/{loader-4U7UCE2Y.js → loader-G6BFG2VA.js} +3 -3
- package/dist/recompile-project-agents-JE4MM72I.js +20 -0
- package/dist/{source-loader-ZNSYJJCI.js → source-loader-3DL3NYUX.js} +7 -5
- package/dist/source-loader-3DL3NYUX.js.map +1 -0
- package/dist/src/agents/developer/ai-developer/critical-reminders.md +1 -1
- package/dist/src/agents/developer/ai-developer/critical-requirements.md +1 -1
- package/dist/src/agents/developer/ai-developer/identity.md +1 -1
- package/dist/src/agents/developer/ai-developer/playbook.md +1 -1
- package/dist/src/agents/developer/api-developer/identity.md +1 -1
- package/dist/src/agents/developer/cli-developer/identity.md +1 -1
- package/dist/src/agents/developer/web-developer/identity.md +1 -1
- package/dist/src/agents/meta/codex-keeper/identity.md +1 -1
- package/dist/src/agents/meta/convention-keeper/identity.md +1 -1
- package/dist/src/agents/meta/skill-summoner/identity.md +1 -1
- package/dist/src/agents/researcher/ai-researcher/identity.md +1 -1
- package/dist/src/agents/researcher/api-researcher/identity.md +1 -1
- package/dist/src/agents/researcher/cli-researcher/identity.md +1 -1
- package/dist/src/agents/researcher/web-researcher/identity.md +1 -1
- package/dist/src/agents/reviewer/reviewer/playbook.md +1 -1
- package/dist/src/agents/tester/ai-tester/identity.md +1 -1
- package/dist/src/agents/tester/api-tester/critical-reminders.md +1 -1
- package/dist/src/agents/tester/api-tester/critical-requirements.md +1 -1
- package/dist/src/agents/tester/api-tester/identity.md +2 -2
- package/dist/src/agents/tester/cli-tester/identity.md +1 -1
- package/dist/src/agents/tester/web-tester/identity.md +3 -3
- package/dist/stores/wizard-store.js +7 -5
- package/package.json +10 -7
- package/src/agents/developer/ai-developer/critical-reminders.md +1 -1
- package/src/agents/developer/ai-developer/critical-requirements.md +1 -1
- package/src/agents/developer/ai-developer/identity.md +1 -1
- package/src/agents/developer/ai-developer/playbook.md +1 -1
- package/src/agents/developer/api-developer/identity.md +1 -1
- package/src/agents/developer/cli-developer/identity.md +1 -1
- package/src/agents/developer/web-developer/identity.md +1 -1
- package/src/agents/meta/codex-keeper/identity.md +1 -1
- package/src/agents/meta/convention-keeper/identity.md +1 -1
- package/src/agents/meta/skill-summoner/identity.md +1 -1
- package/src/agents/researcher/ai-researcher/identity.md +1 -1
- package/src/agents/researcher/api-researcher/identity.md +1 -1
- package/src/agents/researcher/cli-researcher/identity.md +1 -1
- package/src/agents/researcher/web-researcher/identity.md +1 -1
- package/src/agents/reviewer/reviewer/playbook.md +1 -1
- package/src/agents/tester/ai-tester/identity.md +1 -1
- package/src/agents/tester/api-tester/critical-reminders.md +1 -1
- package/src/agents/tester/api-tester/critical-requirements.md +1 -1
- package/src/agents/tester/api-tester/identity.md +2 -2
- package/src/agents/tester/cli-tester/identity.md +1 -1
- package/src/agents/tester/web-tester/identity.md +3 -3
- package/src/schemas/custom-metadata.schema.json +3 -0
- package/src/schemas/metadata.schema.json +3 -0
- package/src/schemas/plugin.schema.json +3 -0
- package/src/schemas/project-config.schema.json +4 -8
- package/src/schemas/project-source-config.schema.json +2 -2
- package/dist/chunk-2HC2SNRP.js.map +0 -1
- package/dist/chunk-35VOK7XE.js.map +0 -1
- package/dist/chunk-FIHTAFST.js.map +0 -1
- package/dist/chunk-FRWKCE6R.js.map +0 -1
- package/dist/chunk-HEBPKK5L.js.map +0 -1
- package/dist/chunk-JC7DBPRD.js.map +0 -1
- package/dist/chunk-K7PJDWER.js.map +0 -1
- package/dist/chunk-KET3EVGX.js +0 -41
- package/dist/chunk-KET3EVGX.js.map +0 -1
- package/dist/chunk-M5HSTNYU.js.map +0 -1
- package/dist/chunk-NXQAY5U7.js.map +0 -1
- package/dist/chunk-OJJLYHM3.js +0 -34
- package/dist/chunk-OJJLYHM3.js.map +0 -1
- package/dist/chunk-ORJ5Y222.js.map +0 -1
- package/dist/chunk-R54KIGN2.js.map +0 -1
- package/dist/chunk-REKOWTIB.js.map +0 -1
- package/dist/chunk-TY6CAOL7.js.map +0 -1
- package/dist/chunk-U2DNAHFE.js.map +0 -1
- package/dist/chunk-U2YSGBHA.js.map +0 -1
- package/dist/chunk-VGEBYCQZ.js.map +0 -1
- package/dist/chunk-X5XJ6WKO.js.map +0 -1
- package/dist/copy-local-skills-KF2RAVD3.js +0 -14
- package/dist/load-agent-defs-DGXGBU3Q.js +0 -15
- package/dist/recompile-project-agents-CJVBAWDJ.js +0 -20
- /package/dist/{chunk-ZNDLUWWD.js.map → chunk-4A4L3YIW.js.map} +0 -0
- /package/dist/{chunk-WDAO3RUY.js.map → chunk-5F2YR5XV.js.map} +0 -0
- /package/dist/{chunk-JFAUQDZM.js.map → chunk-5OKLCVM4.js.map} +0 -0
- /package/dist/{chunk-K3O3YQYG.js.map → chunk-G47TDUK3.js.map} +0 -0
- /package/dist/{chunk-NSJ2S7R5.js.map → chunk-ILUVL7WM.js.map} +0 -0
- /package/dist/{chunk-R4SEU3DF.js.map → chunk-LJCNUP6M.js.map} +0 -0
- /package/dist/{chunk-Q5FLW4JG.js.map → chunk-OKH64JZE.js.map} +0 -0
- /package/dist/{chunk-WG6V6VJV.js.map → chunk-PCC4LBKB.js.map} +0 -0
- /package/dist/{chunk-EFU6P3B7.js.map → chunk-PNMM5HNX.js.map} +0 -0
- /package/dist/{chunk-4VYALFQZ.js.map → chunk-QWVXOCXO.js.map} +0 -0
- /package/dist/{chunk-IO4VEW5U.js.map → chunk-SY4X2LND.js.map} +0 -0
- /package/dist/{chunk-XGMOXMS4.js.map → chunk-TBOVYLQJ.js.map} +0 -0
- /package/dist/{chunk-6CNRMCFM.js.map → chunk-VPASBA7P.js.map} +0 -0
- /package/dist/{chunk-V3ENMW7G.js.map → chunk-WFRTHH3A.js.map} +0 -0
- /package/dist/{chunk-ACKC577F.js.map → chunk-Y5Y7XHVU.js.map} +0 -0
- /package/dist/{copy-local-skills-KF2RAVD3.js.map → components/common/removal-plan-confirm.js.map} +0 -0
- /package/dist/{load-agent-defs-DGXGBU3Q.js.map → copy-local-skills-NSUTBVLJ.js.map} +0 -0
- /package/dist/{loader-4U7UCE2Y.js.map → load-agent-defs-X4E57I2U.js.map} +0 -0
- /package/dist/{recompile-project-agents-CJVBAWDJ.js.map → loader-G6BFG2VA.js.map} +0 -0
- /package/dist/{source-loader-ZNSYJJCI.js.map → recompile-project-agents-JE4MM72I.js.map} +0 -0
package/dist/commands/edit.js
CHANGED
|
@@ -1,98 +1,136 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
publishSeedConfig,
|
|
4
|
+
seedPayloadForInstallation,
|
|
5
|
+
skillsAuthoredHere
|
|
6
|
+
} from "../chunk-2H7UWE2G.js";
|
|
7
|
+
import {
|
|
8
|
+
RemovalPlanConfirm
|
|
9
|
+
} from "../chunk-D2CAV7MG.js";
|
|
10
|
+
import "../chunk-OZXAJNLA.js";
|
|
11
|
+
import {
|
|
12
|
+
seedToWizardResult
|
|
13
|
+
} from "../chunk-MO5FGLVS.js";
|
|
5
14
|
import {
|
|
6
15
|
runWizardSession
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
9
|
-
import "../chunk-
|
|
10
|
-
import "../chunk-
|
|
11
|
-
import "../chunk-
|
|
12
|
-
import "../chunk-
|
|
13
|
-
import "../chunk-
|
|
14
|
-
import "../chunk-
|
|
15
|
-
import "../chunk-
|
|
16
|
-
import "../chunk-
|
|
17
|
-
import "../chunk-
|
|
18
|
-
import "../chunk-
|
|
19
|
-
import "../chunk-
|
|
16
|
+
} from "../chunk-IXRZAHZF.js";
|
|
17
|
+
import "../chunk-TNGMF4UX.js";
|
|
18
|
+
import "../chunk-LJCNUP6M.js";
|
|
19
|
+
import "../chunk-HTYH7CKN.js";
|
|
20
|
+
import "../chunk-PCC4LBKB.js";
|
|
21
|
+
import "../chunk-HG4JPXJT.js";
|
|
22
|
+
import "../chunk-6RLV45HN.js";
|
|
23
|
+
import "../chunk-ILUVL7WM.js";
|
|
24
|
+
import "../chunk-HXKOIWLU.js";
|
|
25
|
+
import "../chunk-QWVXOCXO.js";
|
|
26
|
+
import "../chunk-GS2NZ3GD.js";
|
|
27
|
+
import "../chunk-VPASBA7P.js";
|
|
28
|
+
import "../chunk-PNMM5HNX.js";
|
|
29
|
+
import "../chunk-CLFHC2DK.js";
|
|
30
|
+
import "../chunk-5OKLCVM4.js";
|
|
31
|
+
import "../chunk-5F2YR5XV.js";
|
|
20
32
|
import "../chunk-TSIU7DME.js";
|
|
21
33
|
import "../chunk-XVAQG2CV.js";
|
|
22
|
-
import
|
|
34
|
+
import {
|
|
35
|
+
Spinner
|
|
36
|
+
} from "../chunk-ZBPEFQ4G.js";
|
|
37
|
+
import "../chunk-4A4L3YIW.js";
|
|
23
38
|
import "../chunk-J27W6TXS.js";
|
|
24
|
-
import "../chunk-
|
|
25
|
-
import "../chunk-
|
|
26
|
-
import "../chunk-
|
|
27
|
-
import "../chunk-
|
|
28
|
-
import
|
|
29
|
-
|
|
30
|
-
|
|
39
|
+
import "../chunk-SY4X2LND.js";
|
|
40
|
+
import "../chunk-WFRTHH3A.js";
|
|
41
|
+
import "../chunk-WTJ3AY33.js";
|
|
42
|
+
import "../chunk-OKH64JZE.js";
|
|
43
|
+
import {
|
|
44
|
+
fetchSeedConfig,
|
|
45
|
+
registerExternalSkills,
|
|
46
|
+
writeExternalSkills
|
|
47
|
+
} from "../chunk-PMUABBPG.js";
|
|
48
|
+
import {
|
|
49
|
+
promptConfirm
|
|
50
|
+
} from "../chunk-JCPANDNR.js";
|
|
31
51
|
import {
|
|
32
52
|
compileAgentsAllScopes,
|
|
33
53
|
detectProject,
|
|
34
54
|
loadSource,
|
|
35
55
|
writeProjectConfig
|
|
36
|
-
} from "../chunk-
|
|
56
|
+
} from "../chunk-WUQ3MTPF.js";
|
|
37
57
|
import {
|
|
38
58
|
discoverInstalledSkills,
|
|
59
|
+
removeCompiledAgents,
|
|
39
60
|
uninstallPluginSkills
|
|
40
|
-
} from "../chunk-
|
|
41
|
-
import {
|
|
42
|
-
copyLocalSkills
|
|
43
|
-
} from "../chunk-NXGMM5YN.js";
|
|
61
|
+
} from "../chunk-5QZAK6J7.js";
|
|
44
62
|
import {
|
|
45
63
|
loadAgentDefs
|
|
46
|
-
} from "../chunk-
|
|
47
|
-
import
|
|
48
|
-
|
|
64
|
+
} from "../chunk-MHRC3KRX.js";
|
|
65
|
+
import {
|
|
66
|
+
copyLocalSkills
|
|
67
|
+
} from "../chunk-F2AMBBIA.js";
|
|
68
|
+
import "../chunk-ZUAZHDKP.js";
|
|
69
|
+
import "../chunk-Y5Y7XHVU.js";
|
|
49
70
|
import {
|
|
50
71
|
render
|
|
51
72
|
} from "../chunk-JFLVEFFP.js";
|
|
52
73
|
import {
|
|
53
|
-
formatScopeTag
|
|
54
|
-
|
|
74
|
+
formatScopeTag,
|
|
75
|
+
orderDomains
|
|
76
|
+
} from "../chunk-F5T6TV4Z.js";
|
|
55
77
|
import {
|
|
56
78
|
BaseCommand,
|
|
57
79
|
EXIT_CODES
|
|
58
|
-
} from "../chunk-
|
|
59
|
-
import "../chunk-
|
|
60
|
-
import "../chunk-
|
|
80
|
+
} from "../chunk-YO2LTXB4.js";
|
|
81
|
+
import "../chunk-UMH2YZKG.js";
|
|
82
|
+
import "../chunk-G47TDUK3.js";
|
|
61
83
|
import {
|
|
62
84
|
ERROR_MESSAGES,
|
|
63
85
|
INFO_MESSAGES,
|
|
64
86
|
INSTALL_MODE_DESCRIPTIONS,
|
|
87
|
+
SHARED_CONFIG_APPLY,
|
|
88
|
+
SHARED_CONFIG_ONE_DIRECTION,
|
|
65
89
|
STATUS_MESSAGES,
|
|
66
90
|
activeAgentNames,
|
|
67
91
|
activeAgentScopeMap,
|
|
68
92
|
applyMigratedGlobalSources,
|
|
93
|
+
authoredHereKept,
|
|
69
94
|
buildMarketplacePluginRef,
|
|
95
|
+
carriedSkillsWritten,
|
|
70
96
|
claudePluginInstall,
|
|
71
97
|
claudePluginUninstall,
|
|
72
98
|
deleteLocalSkill,
|
|
73
99
|
detectMigrations,
|
|
74
100
|
discoverAllPluginSkills,
|
|
101
|
+
ejectCopyFailureError,
|
|
102
|
+
execCommand,
|
|
75
103
|
executeMigration,
|
|
104
|
+
globallyInstalledRemoved,
|
|
76
105
|
installBaseDir,
|
|
77
106
|
isActiveAt,
|
|
78
107
|
isHomeDirectory,
|
|
108
|
+
loadProjectConfigFromDir,
|
|
109
|
+
localSkillsCopied,
|
|
79
110
|
migrateLocalSkillScope,
|
|
80
111
|
mutateGlobal,
|
|
112
|
+
normalizeProjectPath,
|
|
81
113
|
recompileSummary,
|
|
82
114
|
resolveInstallPaths,
|
|
115
|
+
sharedConfigDestinations,
|
|
116
|
+
sharedConfigNeedsTerminal,
|
|
117
|
+
skippedUnknownAgents,
|
|
118
|
+
skippedUnknownSkills,
|
|
83
119
|
toClaudePluginScope,
|
|
120
|
+
unplaceableKept,
|
|
84
121
|
unresolvedSkillRemovalReasons
|
|
85
|
-
} from "../chunk-
|
|
122
|
+
} from "../chunk-WCAUUBHO.js";
|
|
86
123
|
import {
|
|
87
|
-
getErrorMessage
|
|
88
|
-
|
|
89
|
-
} from "../chunk-U2YSGBHA.js";
|
|
124
|
+
getErrorMessage
|
|
125
|
+
} from "../chunk-XAXJWXI4.js";
|
|
90
126
|
import {
|
|
127
|
+
getCategoryDomain,
|
|
91
128
|
getSkillById,
|
|
92
129
|
getSkillDisplayName,
|
|
93
130
|
matrix
|
|
94
|
-
} from "../chunk-
|
|
131
|
+
} from "../chunk-RWOYPOMR.js";
|
|
95
132
|
import {
|
|
133
|
+
typedEntries,
|
|
96
134
|
typedKeys
|
|
97
135
|
} from "../chunk-VASLW636.js";
|
|
98
136
|
import {
|
|
@@ -100,15 +138,121 @@ import {
|
|
|
100
138
|
CLI_INVOKE_COMMAND,
|
|
101
139
|
EDIT_PROJECT_SETUP_FLAG,
|
|
102
140
|
EJECT_SOURCE,
|
|
141
|
+
editorConfigUrl,
|
|
103
142
|
formatSourceDisplayName
|
|
104
|
-
} from "../chunk-
|
|
143
|
+
} from "../chunk-IO5YBKHV.js";
|
|
105
144
|
import "../chunk-VZRO7RYT.js";
|
|
106
145
|
|
|
107
146
|
// src/cli/commands/edit.tsx
|
|
147
|
+
import os from "os";
|
|
108
148
|
import path from "path";
|
|
109
149
|
import chalk from "chalk";
|
|
110
150
|
import { Flags } from "@oclif/core";
|
|
111
|
-
import { difference, indexBy } from "remeda";
|
|
151
|
+
import { difference, indexBy, partition } from "remeda";
|
|
152
|
+
|
|
153
|
+
// src/cli/lib/seed/seed-apply.ts
|
|
154
|
+
var NOTHING_KEPT = {
|
|
155
|
+
authoredSkillIds: [],
|
|
156
|
+
unplaceableSkillIds: []
|
|
157
|
+
};
|
|
158
|
+
function reconcileSharedConfig(options) {
|
|
159
|
+
const { decoded, installed } = options;
|
|
160
|
+
if (!installed) return { result: decoded, kept: NOTHING_KEPT };
|
|
161
|
+
const keptSkills = skillsToKeep(options, installed);
|
|
162
|
+
if (keptSkills.length === 0) return { result: decoded, kept: NOTHING_KEPT };
|
|
163
|
+
return {
|
|
164
|
+
result: withKeptEntries(decoded, installed, keptSkills),
|
|
165
|
+
kept: describeKept(options, keptSkills)
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
function skillsToKeep(options, installed) {
|
|
169
|
+
const named = new Set(options.decoded.skills.map((skill) => skill.id));
|
|
170
|
+
return installed.skills.filter(
|
|
171
|
+
(skill) => !skill.excluded && !named.has(skill.id) && mayNotRemove(skill, options)
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
function mayNotRemove(skill, options) {
|
|
175
|
+
return options.authoredHere.has(skill.id) || options.unplaceable.has(skill.id);
|
|
176
|
+
}
|
|
177
|
+
function describeKept(options, keptSkills) {
|
|
178
|
+
const idsKeptFor = (reason) => keptSkills.filter((skill) => reasonKept(skill, options) === reason).map((skill) => skill.id);
|
|
179
|
+
return {
|
|
180
|
+
authoredSkillIds: idsKeptFor("authored"),
|
|
181
|
+
unplaceableSkillIds: idsKeptFor("unplaceable")
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
function reasonKept(skill, options) {
|
|
185
|
+
return options.authoredHere.has(skill.id) ? "authored" : "unplaceable";
|
|
186
|
+
}
|
|
187
|
+
function withKeptEntries(decoded, installed, keptSkills) {
|
|
188
|
+
return {
|
|
189
|
+
...decoded,
|
|
190
|
+
skills: [...decoded.skills, ...keptSkills],
|
|
191
|
+
selectedDomains: withKeptDomains(decoded.selectedDomains, keptSkills),
|
|
192
|
+
...decoded.assignedStack !== void 0 && {
|
|
193
|
+
assignedStack: withKeptStackRows(decoded.assignedStack, installed.stack, {
|
|
194
|
+
keptSkillIds: new Set(keptSkills.map((skill) => skill.id)),
|
|
195
|
+
survivingAgents: new Set(decoded.selectedAgents)
|
|
196
|
+
})
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function withKeptDomains(selected, keptSkills) {
|
|
201
|
+
const keptDomains = keptSkills.flatMap((skill) => domainOfSkill(skill.id) ?? []);
|
|
202
|
+
const missing = keptDomains.filter((domain) => !selected.includes(domain));
|
|
203
|
+
if (missing.length === 0) return selected;
|
|
204
|
+
return orderDomains([...selected, ...new Set(missing)]);
|
|
205
|
+
}
|
|
206
|
+
function domainOfSkill(skillId) {
|
|
207
|
+
const category = matrix.skills[skillId]?.category;
|
|
208
|
+
return category === void 0 ? void 0 : getCategoryDomain(category);
|
|
209
|
+
}
|
|
210
|
+
function withKeptStackRows(assigned, installedStack, filter) {
|
|
211
|
+
if (!installedStack) return assigned;
|
|
212
|
+
const carried = { ...assigned };
|
|
213
|
+
for (const [agent, agentStack] of typedEntries(installedStack)) {
|
|
214
|
+
if (!filter.survivingAgents.has(agent)) continue;
|
|
215
|
+
const rows = keptRowsFor(agentStack, filter.keptSkillIds);
|
|
216
|
+
if (typedKeys(rows).length === 0) continue;
|
|
217
|
+
carried[agent] = { ...carried[agent], ...rows };
|
|
218
|
+
}
|
|
219
|
+
return carried;
|
|
220
|
+
}
|
|
221
|
+
function keptRowsFor(agentStack, keptSkillIds) {
|
|
222
|
+
const rows = {};
|
|
223
|
+
for (const [category, assignments] of typedEntries(agentStack)) {
|
|
224
|
+
const carried = assignments.filter((assignment) => keptSkillIds.has(assignment.id));
|
|
225
|
+
if (carried.length > 0) rows[category] = carried;
|
|
226
|
+
}
|
|
227
|
+
return rows;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// src/cli/utils/open-url.ts
|
|
231
|
+
function browserOpenerCommand(platform, url) {
|
|
232
|
+
if (platform === "darwin") return { command: "open", args: [url] };
|
|
233
|
+
if (platform === "win32") return { command: "cmd", args: ["/c", "start", "", url] };
|
|
234
|
+
return { command: "xdg-open", args: [url] };
|
|
235
|
+
}
|
|
236
|
+
function openerRefusedMessage(command, exitCode) {
|
|
237
|
+
return `Could not open your browser \u2014 '${command}' exited ${exitCode}.`;
|
|
238
|
+
}
|
|
239
|
+
function openerUnavailableMessage(command, reason) {
|
|
240
|
+
return `Could not open your browser \u2014 '${command}' could not be run: ${reason}`;
|
|
241
|
+
}
|
|
242
|
+
async function openUrl(url) {
|
|
243
|
+
const { command, args } = browserOpenerCommand(process.platform, url);
|
|
244
|
+
try {
|
|
245
|
+
const result = await execCommand(command, args);
|
|
246
|
+
if (result.exitCode !== 0) {
|
|
247
|
+
return { ok: false, error: openerRefusedMessage(command, result.exitCode) };
|
|
248
|
+
}
|
|
249
|
+
return { ok: true };
|
|
250
|
+
} catch (error) {
|
|
251
|
+
return { ok: false, error: openerUnavailableMessage(command, getErrorMessage(error)) };
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// src/cli/commands/edit.tsx
|
|
112
256
|
import { jsx } from "react/jsx-runtime";
|
|
113
257
|
var RECOMPILE_SUBJECT = "agents";
|
|
114
258
|
function formatDualScopeTransition(displayName, to) {
|
|
@@ -140,6 +284,71 @@ function scopeArrow(change) {
|
|
|
140
284
|
function loadedSourceLabel(sourceResult) {
|
|
141
285
|
return sourceResult.marketplace ?? sourceResult.sourceConfig.source;
|
|
142
286
|
}
|
|
287
|
+
function globalScopePlan(changes, kept) {
|
|
288
|
+
const sections = removalSections(changes.removedSkills, changes.removedAgents);
|
|
289
|
+
return { heading: planHeading(sections), sections, statements: kept };
|
|
290
|
+
}
|
|
291
|
+
function projectScopePlan(changes, kept, installed, otherProjects) {
|
|
292
|
+
const { here, global } = splitRemovalsByScope(changes, installed);
|
|
293
|
+
const sections = [
|
|
294
|
+
...removalSections(here.skills, here.agents),
|
|
295
|
+
...globalRemovalSections(global.skills, global.agents)
|
|
296
|
+
];
|
|
297
|
+
return {
|
|
298
|
+
heading: planHeading(sections),
|
|
299
|
+
sections,
|
|
300
|
+
statements: [...globalReachStatement(global, otherProjects), ...kept]
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
function splitRemovalsByScope(changes, installed) {
|
|
304
|
+
const isGlobalSkill = (id) => installed.skills.some((skill) => skill.id === id && isActiveAt(skill, "global"));
|
|
305
|
+
const isGlobalAgent = (name) => installed.agents.some((agent) => agent.name === name && isActiveAt(agent, "global"));
|
|
306
|
+
const [globalSkills, projectSkills] = partition(changes.removedSkills, isGlobalSkill);
|
|
307
|
+
const [globalAgents, projectAgents] = partition(changes.removedAgents, isGlobalAgent);
|
|
308
|
+
return {
|
|
309
|
+
here: { skills: projectSkills, agents: projectAgents },
|
|
310
|
+
global: { skills: globalSkills, agents: globalAgents }
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
function removalSections(skills, agents) {
|
|
314
|
+
return [
|
|
315
|
+
{ label: SHARED_CONFIG_APPLY.SKILLS_HEADING, items: skills.map(skillLabel) },
|
|
316
|
+
{ label: SHARED_CONFIG_APPLY.AGENTS_HEADING, items: [...agents] }
|
|
317
|
+
].filter((section) => section.items.length > 0);
|
|
318
|
+
}
|
|
319
|
+
function globalRemovalSections(skills, agents) {
|
|
320
|
+
return [
|
|
321
|
+
{ label: SHARED_CONFIG_APPLY.GLOBAL_SKILLS_HEADING, items: skills.map(skillLabel) },
|
|
322
|
+
{ label: SHARED_CONFIG_APPLY.GLOBAL_AGENTS_HEADING, items: [...agents] }
|
|
323
|
+
].filter((section) => section.items.length > 0);
|
|
324
|
+
}
|
|
325
|
+
function globalReachStatement(global, otherProjects) {
|
|
326
|
+
if (global.skills.length === 0 && global.agents.length === 0) return [];
|
|
327
|
+
return [globallyInstalledRemoved(otherProjects)];
|
|
328
|
+
}
|
|
329
|
+
function planHeading(sections) {
|
|
330
|
+
if (sections.length === 0) return SHARED_CONFIG_APPLY.NOTHING_REMOVED;
|
|
331
|
+
return SHARED_CONFIG_APPLY.PREVIEW_HEADING;
|
|
332
|
+
}
|
|
333
|
+
function skillLabel(skillId) {
|
|
334
|
+
const displayName = getSkillDisplayName(skillId);
|
|
335
|
+
return displayName === skillId ? skillId : `${displayName} (${skillId})`;
|
|
336
|
+
}
|
|
337
|
+
function keptStatements(kept) {
|
|
338
|
+
return [...authorshipStatement(kept), ...catalogueStatement(kept)];
|
|
339
|
+
}
|
|
340
|
+
function authorshipStatement(kept) {
|
|
341
|
+
if (kept.authoredSkillIds.length === 0) return [];
|
|
342
|
+
return [authoredHereKept(kept.authoredSkillIds)];
|
|
343
|
+
}
|
|
344
|
+
function catalogueStatement(kept) {
|
|
345
|
+
if (kept.unplaceableSkillIds.length === 0) return [];
|
|
346
|
+
return [unplaceableKept(kept.unplaceableSkillIds)];
|
|
347
|
+
}
|
|
348
|
+
function applyAuthority(producer, cwd) {
|
|
349
|
+
if (isHomeDirectory(cwd)) return "all";
|
|
350
|
+
return producer === "shared" ? "all" : "owned";
|
|
351
|
+
}
|
|
143
352
|
var Edit = class _Edit extends BaseCommand {
|
|
144
353
|
static summary = "Edit skills in the plugin";
|
|
145
354
|
static description = "Modify the currently installed skills via interactive wizard";
|
|
@@ -147,9 +356,25 @@ var Edit = class _Edit extends BaseCommand {
|
|
|
147
356
|
{
|
|
148
357
|
description: "Open the edit wizard",
|
|
149
358
|
command: "<%= config.bin %> <%= command.id %>"
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
description: "Open this installation in the editor instead of the wizard",
|
|
362
|
+
command: "<%= config.bin %> <%= command.id %> --ui"
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
description: "Apply a configuration built in the editor, by its id",
|
|
366
|
+
command: "<%= config.bin %> <%= command.id %> --from <id>"
|
|
150
367
|
}
|
|
151
368
|
];
|
|
152
369
|
static flags = {
|
|
370
|
+
ui: Flags.boolean({
|
|
371
|
+
description: "Edit this installation in the browser at agentsinc.sh instead of the wizard",
|
|
372
|
+
default: false
|
|
373
|
+
}),
|
|
374
|
+
from: Flags.string({
|
|
375
|
+
description: "Apply a configuration shared from agentsinc.sh by its id, removing whatever it leaves out",
|
|
376
|
+
helpValue: "<id>"
|
|
377
|
+
}),
|
|
153
378
|
[EDIT_PROJECT_SETUP_FLAG]: Flags.boolean({
|
|
154
379
|
description: "Internal: this run continues an `init` project setup",
|
|
155
380
|
default: false,
|
|
@@ -160,19 +385,20 @@ var Edit = class _Edit extends BaseCommand {
|
|
|
160
385
|
const { flags } = await this.parse(_Edit);
|
|
161
386
|
const cwd = process.cwd();
|
|
162
387
|
await this.ensureConfigReadable(cwd);
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
388
|
+
if (flags.ui && flags.from !== void 0) {
|
|
389
|
+
this.error(SHARED_CONFIG_ONE_DIRECTION, { exit: EXIT_CODES.ERROR });
|
|
390
|
+
}
|
|
391
|
+
if (flags.ui) return this.openInEditor(cwd);
|
|
392
|
+
const payload = flags.from === void 0 ? null : await this.fetchSharedConfigOrFail(flags.from);
|
|
393
|
+
const context = await this.loadContextUnderSpinner();
|
|
169
394
|
await this.ensureSavedSkillsReadable(
|
|
170
395
|
context.projectConfig?.skills ?? [],
|
|
171
396
|
context.sourceResult.matrix,
|
|
172
397
|
context.projectDir
|
|
173
398
|
);
|
|
174
|
-
const
|
|
175
|
-
if (!
|
|
399
|
+
const selection = payload ? await this.selectionFromSharedConfig(payload, context, cwd) : await this.selectionFromWizard(context, cwd);
|
|
400
|
+
if (!selection) this.error("Cancelled", { exit: EXIT_CODES.CANCELLED });
|
|
401
|
+
const { result } = selection;
|
|
176
402
|
this.reportValidationErrors(result.validation);
|
|
177
403
|
const activeNewSkills = result.skills.filter((s) => !s.excluded);
|
|
178
404
|
const activeNewAgents = result.agentConfigs.filter((a) => !a.excluded);
|
|
@@ -191,10 +417,20 @@ var Edit = class _Edit extends BaseCommand {
|
|
|
191
417
|
oldAgents: context.projectConfig?.agents ?? []
|
|
192
418
|
});
|
|
193
419
|
const isProjectSetup = flags[EDIT_PROJECT_SETUP_FLAG] && !isHomeDirectory(cwd);
|
|
420
|
+
if (selection.producer === "shared") {
|
|
421
|
+
await this.confirmSharedConfigOrCancel(
|
|
422
|
+
changes,
|
|
423
|
+
selection.kept,
|
|
424
|
+
{ skills: activeOldSkills, agents: activeOldAgents },
|
|
425
|
+
cwd
|
|
426
|
+
);
|
|
427
|
+
await this.writeCarriedSkills(selection.carried);
|
|
428
|
+
}
|
|
429
|
+
const authority = applyAuthority(selection.producer, cwd);
|
|
194
430
|
if (!hasAnyChanges(changes)) {
|
|
195
431
|
this.log(chalk.hex(CLI_COLORS.NEUTRAL)("No changes made."));
|
|
196
432
|
if (!isProjectSetup) return;
|
|
197
|
-
await this.writeConfigAndCompile(result, context, cwd);
|
|
433
|
+
await this.writeConfigAndCompile(result, context, cwd, authority);
|
|
198
434
|
this.logCompletionSummary(changes);
|
|
199
435
|
return;
|
|
200
436
|
}
|
|
@@ -223,10 +459,239 @@ var Edit = class _Edit extends BaseCommand {
|
|
|
223
459
|
await this.applyPluginChanges(changes, filteredResult, activeOldSkills, context, cwd);
|
|
224
460
|
await this.copyNewLocalSkills(changes, filteredResult, context, cwd);
|
|
225
461
|
await this.removeDeletedLocalSkills(changes, activeOldSkills, cwd);
|
|
226
|
-
await this.writeConfigAndCompile(result, context, cwd);
|
|
462
|
+
await this.writeConfigAndCompile(result, context, cwd, authority);
|
|
227
463
|
await this.cleanupStaleAgentFiles(changes, activeOldAgents, cwd);
|
|
228
464
|
this.logCompletionSummary(changes);
|
|
229
465
|
}
|
|
466
|
+
/** The interactive producer: open the wizard on what is installed, return what was chosen. */
|
|
467
|
+
async selectionFromWizard(context, cwd) {
|
|
468
|
+
const result = await this.runEditWizard(context, cwd);
|
|
469
|
+
if (!result) return null;
|
|
470
|
+
return { producer: "wizard", result };
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* The `--from <id>` producer: fetch, seat what the configuration carries, decode, and put back
|
|
474
|
+
* what this run has no authority to remove.
|
|
475
|
+
*
|
|
476
|
+
* Everything a shared configuration says is a statement about the whole roster, so the apply
|
|
477
|
+
* that follows is destructive — the project is made to MATCH it. Two exceptions come back into
|
|
478
|
+
* the result: a skill written here, which the producer drops on the way out because
|
|
479
|
+
* `forkedFrom` says the CLI never wrote it, and an id the configuration NAMES that this
|
|
480
|
+
* catalogue cannot place, because a destructive apply removes on intent and never on its own
|
|
481
|
+
* inability. Both are disclosed in the confirm rather than silently excused.
|
|
482
|
+
*
|
|
483
|
+
* A globally installed entry is NOT one of them. It is removable from here, and what its scope
|
|
484
|
+
* changes is who the removal reaches — which the confirm names, rather than this putting the
|
|
485
|
+
* entry back and calling the reach impossible.
|
|
486
|
+
*/
|
|
487
|
+
async selectionFromSharedConfig(payload, context, cwd) {
|
|
488
|
+
const { matrix: sourceMatrix } = context.sourceResult;
|
|
489
|
+
const carried = this.registerExternalSkillsOrFail(payload, sourceMatrix, cwd);
|
|
490
|
+
const { result, skippedSkillIds, skippedAgentNames } = this.decodeSeedOrFail(
|
|
491
|
+
payload,
|
|
492
|
+
sourceMatrix
|
|
493
|
+
);
|
|
494
|
+
this.refuseProjectScopedContentAtHome(result, cwd);
|
|
495
|
+
if (skippedSkillIds.length > 0) this.warn(skippedUnknownSkills(skippedSkillIds));
|
|
496
|
+
if (skippedAgentNames.length > 0) this.warn(skippedUnknownAgents(skippedAgentNames));
|
|
497
|
+
const reconciled = reconcileSharedConfig({
|
|
498
|
+
decoded: result,
|
|
499
|
+
installed: context.projectConfig,
|
|
500
|
+
authoredHere: await this.readAuthoredHere(context.projectConfig, cwd),
|
|
501
|
+
// The ids the decode above could not place. They are the skips just reported, read as
|
|
502
|
+
// what STAYS rather than as what did not arrive: the payload named them, so their absence
|
|
503
|
+
// from the decode is this catalogue's limit and not an instruction to delete anything.
|
|
504
|
+
unplaceable: new Set(skippedSkillIds)
|
|
505
|
+
});
|
|
506
|
+
return {
|
|
507
|
+
producer: "shared",
|
|
508
|
+
result: reconciled.result,
|
|
509
|
+
kept: keptStatements(reconciled.kept),
|
|
510
|
+
carried
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Which installed skills the round trip does not own, asked of the disk exactly as the
|
|
515
|
+
* producing half asks it.
|
|
516
|
+
*
|
|
517
|
+
* Best-effort by nature and never fatal: the question is only ever asked to PROTECT a skill,
|
|
518
|
+
* so a directory that cannot be read protects nothing and must not fail an apply. The
|
|
519
|
+
* consequence of an unanswered question is that the entry is treated as the CLI's own, which
|
|
520
|
+
* is what every other command already assumes about it.
|
|
521
|
+
*/
|
|
522
|
+
async readAuthoredHere(projectConfig, cwd) {
|
|
523
|
+
if (!projectConfig) return /* @__PURE__ */ new Set();
|
|
524
|
+
try {
|
|
525
|
+
return await skillsAuthoredHere(projectConfig, cwd);
|
|
526
|
+
} catch (error) {
|
|
527
|
+
this.warn(`Could not tell which skills were written here: ${getErrorMessage(error)}`);
|
|
528
|
+
return /* @__PURE__ */ new Set();
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* The id, fetched — or the run refused before it is.
|
|
533
|
+
*
|
|
534
|
+
* The terminal question is answered first because nothing in the payload can change its
|
|
535
|
+
* answer: an apply that cannot be confirmed is over before the store is asked, and a refusal
|
|
536
|
+
* that had already spent a round trip would be describing work it never intended to do.
|
|
537
|
+
*/
|
|
538
|
+
async fetchSharedConfigOrFail(id) {
|
|
539
|
+
if (!process.stdin.isTTY) {
|
|
540
|
+
this.error(sharedConfigNeedsTerminal(id), { exit: EXIT_CODES.ERROR });
|
|
541
|
+
}
|
|
542
|
+
this.log(`Fetching configuration ${id}...`);
|
|
543
|
+
const fetched = await fetchSeedConfig(id);
|
|
544
|
+
if (!fetched.ok) {
|
|
545
|
+
this.error(fetched.error, { exit: EXIT_CODES.ERROR });
|
|
546
|
+
}
|
|
547
|
+
return fetched.payload;
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* The decode refuses a payload the config model has nowhere to write (see `seedToWizardResult`).
|
|
551
|
+
* That is a failure of this command, reported with this command's exit code rather than left to
|
|
552
|
+
* surface as an unhandled throw.
|
|
553
|
+
*/
|
|
554
|
+
decodeSeedOrFail(payload, sourceMatrix) {
|
|
555
|
+
try {
|
|
556
|
+
return seedToWizardResult(payload, sourceMatrix);
|
|
557
|
+
} catch (error) {
|
|
558
|
+
this.handleError(error);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Seats the catalogue entries the payload carries with it, or refuses the run. The refusal is
|
|
563
|
+
* `registerExternalSkills`' own — a carried skill asked for as a plugin, which no marketplace
|
|
564
|
+
* serves — reported with this command's exit code for the same reason the decode's is.
|
|
565
|
+
*/
|
|
566
|
+
registerExternalSkillsOrFail(payload, sourceMatrix, projectDir) {
|
|
567
|
+
try {
|
|
568
|
+
return registerExternalSkills(payload, sourceMatrix, projectDir);
|
|
569
|
+
} catch (error) {
|
|
570
|
+
this.handleError(error);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
/** Writes the skills the configuration brought with it, and says which they were. */
|
|
574
|
+
async writeCarriedSkills(carried) {
|
|
575
|
+
if (carried.length === 0) return;
|
|
576
|
+
await writeExternalSkills(carried);
|
|
577
|
+
this.log(carriedSkillsWritten(carried.map((skill) => skill.id)));
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Shows what applying this configuration takes away, and stops the run unless a person says
|
|
581
|
+
* yes.
|
|
582
|
+
*
|
|
583
|
+
* The plan is built from the SAME `ConfigChanges` the apply below acts on, so what is approved
|
|
584
|
+
* and what is removed are one value read twice. Its kept half is the other side of the same
|
|
585
|
+
* honesty: nothing is refused over an entry this run cannot remove, and nothing is silent
|
|
586
|
+
* about one either.
|
|
587
|
+
*
|
|
588
|
+
* WHICH plan is built is decided here and only here, on the directory the run was started in.
|
|
589
|
+
* Inside the global installation the scope was chosen and is obvious, so the ordinary confirm
|
|
590
|
+
* is the whole of the gate; inside a project a global removal reaches projects nobody here is
|
|
591
|
+
* looking at, so it is shown apart and the reach is named.
|
|
592
|
+
*/
|
|
593
|
+
async confirmSharedConfigOrCancel(changes, kept, installed, cwd) {
|
|
594
|
+
const plan = isHomeDirectory(cwd) ? globalScopePlan(changes, kept) : projectScopePlan(changes, kept, installed, await this.otherRegisteredProjects(cwd));
|
|
595
|
+
const outcome = await promptConfirm(({ onConfirm, onCancel }) => /* @__PURE__ */ jsx(
|
|
596
|
+
RemovalPlanConfirm,
|
|
597
|
+
{
|
|
598
|
+
heading: plan.heading,
|
|
599
|
+
sections: plan.sections,
|
|
600
|
+
statements: plan.statements,
|
|
601
|
+
message: SHARED_CONFIG_APPLY.CONFIRM,
|
|
602
|
+
onConfirm,
|
|
603
|
+
onCancel
|
|
604
|
+
}
|
|
605
|
+
));
|
|
606
|
+
if (outcome === "confirmed") return;
|
|
607
|
+
this.log("\nEdit cancelled");
|
|
608
|
+
this.error("Cancelled", { exit: EXIT_CODES.CANCELLED });
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Every registered project but this one — the blast radius a global removal actually has.
|
|
612
|
+
*
|
|
613
|
+
* Read from the GLOBAL config rather than from `context.projectConfig`: `projects[]` is the
|
|
614
|
+
* registry the fan-out itself walks, and a project's own config never carries it, so taking
|
|
615
|
+
* the list from anywhere else would let the confirm name a set the propagation does not.
|
|
616
|
+
*
|
|
617
|
+
* Best-effort by nature. The list exists to be DISCLOSED, so a home directory that cannot be
|
|
618
|
+
* read leaves the disclosure counting nobody rather than failing an apply — and the statement
|
|
619
|
+
* it produces then is the one that says no other project is registered.
|
|
620
|
+
*/
|
|
621
|
+
async otherRegisteredProjects(cwd) {
|
|
622
|
+
try {
|
|
623
|
+
const global = await loadProjectConfigFromDir(os.homedir());
|
|
624
|
+
const here = normalizeProjectPath(cwd);
|
|
625
|
+
return (global?.config.projects ?? []).filter((projectDir) => projectDir !== here);
|
|
626
|
+
} catch (error) {
|
|
627
|
+
this.warn(`Could not tell which projects share this install: ${getErrorMessage(error)}`);
|
|
628
|
+
return [];
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* The outbound half of the editor round trip: this installation, minted as a configuration
|
|
633
|
+
* the editor opens, and handed to a browser.
|
|
634
|
+
*
|
|
635
|
+
* It is the same mint `share` performs — same reader, same mapping, same refusals, through
|
|
636
|
+
* `seedPayloadForInstallation` — because an id is the whole of what either command produces
|
|
637
|
+
* and two spellings of "the installation in this directory" would mint two different ids for
|
|
638
|
+
* one project. What differs is only the ending: `share` reports the id, this opens it.
|
|
639
|
+
*
|
|
640
|
+
* Nothing on disk is touched. A configuration is read, not rewritten, so a run that changed
|
|
641
|
+
* anything here would be editing the project on the way to offering to edit it.
|
|
642
|
+
*/
|
|
643
|
+
async openInEditor(projectDir) {
|
|
644
|
+
const prepared = await seedPayloadForInstallation(projectDir);
|
|
645
|
+
if (!prepared.ok) {
|
|
646
|
+
this.error(prepared.error, { exit: EXIT_CODES.ERROR });
|
|
647
|
+
}
|
|
648
|
+
this.log(`Opening ${prepared.skills} skill(s) across ${prepared.agents} sub-agent(s)...`);
|
|
649
|
+
const published = await publishSeedConfig(prepared.payload);
|
|
650
|
+
if (!published.ok) {
|
|
651
|
+
this.error(published.error, { exit: EXIT_CODES.ERROR });
|
|
652
|
+
}
|
|
653
|
+
await this.handToBrowser(published.id);
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* The link, printed first and opened second.
|
|
657
|
+
*
|
|
658
|
+
* Printed first because it is the only part of this that works everywhere: over a pipe, in CI
|
|
659
|
+
* and on a machine with no desktop session there is no browser to be anybody's, and a link
|
|
660
|
+
* nobody can copy is the whole loss. Opening one is the convenience on top, so a failure to
|
|
661
|
+
* open is a warning beside a link that still works rather than a failed command.
|
|
662
|
+
*
|
|
663
|
+
* `process.stdin.isTTY` is the same question `init`'s dashboard asks before it offers a
|
|
664
|
+
* prompt — is there a person here — because that is exactly what "whose browser is this"
|
|
665
|
+
* means.
|
|
666
|
+
*/
|
|
667
|
+
async handToBrowser(id) {
|
|
668
|
+
this.logSuccess(`Shared as ${id}`);
|
|
669
|
+
for (const destination of sharedConfigDestinations(id)) {
|
|
670
|
+
this.log(destination);
|
|
671
|
+
}
|
|
672
|
+
if (!process.stdin.isTTY) return;
|
|
673
|
+
const opened = await openUrl(editorConfigUrl(id));
|
|
674
|
+
if (!opened.ok) this.warn(opened.error);
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* The load below, behind a spinner that comes down whichever way the await ends.
|
|
678
|
+
*
|
|
679
|
+
* The cleanup is a `finally` because all three of `loadContext`'s refusals are raised
|
|
680
|
+
* while this spinner is mounted, and oclif would otherwise paint its error under an Ink
|
|
681
|
+
* tree still repainting over it. Never a `catch`: the throw reaches oclif untouched, or
|
|
682
|
+
* both the error rendering and the pinned exit codes change with it.
|
|
683
|
+
*/
|
|
684
|
+
async loadContextUnderSpinner() {
|
|
685
|
+
const { unmount, clear: clearSpinner } = render(
|
|
686
|
+
/* @__PURE__ */ jsx(Spinner, { label: STATUS_MESSAGES.LOADING_SKILLS })
|
|
687
|
+
);
|
|
688
|
+
try {
|
|
689
|
+
return await this.loadContext();
|
|
690
|
+
} finally {
|
|
691
|
+
clearSpinner();
|
|
692
|
+
unmount();
|
|
693
|
+
}
|
|
694
|
+
}
|
|
230
695
|
async loadContext() {
|
|
231
696
|
const detected = await detectProject();
|
|
232
697
|
if (!detected) {
|
|
@@ -317,11 +782,19 @@ var Edit = class _Edit extends BaseCommand {
|
|
|
317
782
|
* source contradict the filesystem and the plugin registry.
|
|
318
783
|
*
|
|
319
784
|
* So authority follows the work actually performed, and no further: only ids
|
|
320
|
-
* `executeMigration` acted on this run are rewritten, and only their `
|
|
785
|
+
* `executeMigration` acted on this run are rewritten, and only their `origin` field. Global
|
|
321
786
|
* entries this session merely displayed, re-scoped or deselected are untouched, as are
|
|
322
787
|
* `marketplace`, `stack`, `agents` and every other registered project's view of them.
|
|
323
|
-
*
|
|
324
|
-
* project directory is a supported flow
|
|
788
|
+
*
|
|
789
|
+
* Driving a global-scope migration from a project directory is NOT a supported flow, and this
|
|
790
|
+
* method is no longer the thing that permits it. The wizard now refuses it at source: the two
|
|
791
|
+
* bulk install-mode keys are withdrawn, and `setInstallMode` ignores a project-context call
|
|
792
|
+
* against a global slot the hydration snapshot owns — the same authority the Sources grid
|
|
793
|
+
* already enforced by rendering that row inert. What still reaches here is the residue that
|
|
794
|
+
* authority leaves legitimate: a mode change committed on the project half of a `[P][G]` pair
|
|
795
|
+
* and then carried to global scope by a P->G collapse (`s`) in the same session. The entry is
|
|
796
|
+
* the project's own to configure at the moment it is configured, and global at the moment it
|
|
797
|
+
* is written — so the migration is real, and the global config must record it.
|
|
325
798
|
*
|
|
326
799
|
* Runs BEFORE `writeConfigAndCompile`, so the global config written here is the one
|
|
327
800
|
* the wizard write reloads, keeps (existing wins in `mergeGlobalConfigs`) and inlines
|
|
@@ -329,14 +802,14 @@ var Edit = class _Edit extends BaseCommand {
|
|
|
329
802
|
* classifies as a no-op against what this one left on disk, so the fan-out below
|
|
330
803
|
* happens once.
|
|
331
804
|
*
|
|
332
|
-
* The migrated `
|
|
805
|
+
* The migrated `origin` decides the reference form a compiled agent emits, so every
|
|
333
806
|
* OTHER registered project's config and agents are stale until this write fans out —
|
|
334
807
|
* which is why it goes through the gate rather than straight to the file.
|
|
335
808
|
*/
|
|
336
809
|
async recordGlobalSourceMigrations(migratedSkillIds, newSkills, cwd, context) {
|
|
337
810
|
if (isHomeDirectory(cwd)) return;
|
|
338
811
|
const migratedSources = new Map(
|
|
339
|
-
newSkills.filter((s) => migratedSkillIds.has(s.id) && isActiveAt(s, "global")).map((s) => [s.id, s.
|
|
812
|
+
newSkills.filter((s) => migratedSkillIds.has(s.id) && isActiveAt(s, "global")).map((s) => [s.id, s.origin])
|
|
340
813
|
);
|
|
341
814
|
if (migratedSources.size === 0) return;
|
|
342
815
|
try {
|
|
@@ -348,12 +821,12 @@ var Edit = class _Edit extends BaseCommand {
|
|
|
348
821
|
// matrix in hand already.
|
|
349
822
|
// eslint-disable-next-line @typescript-eslint/require-await -- deps contract
|
|
350
823
|
loadMatrix: async () => context.sourceResult.matrix,
|
|
351
|
-
loadAgents: async () => (await loadAgentDefs(
|
|
824
|
+
loadAgents: async () => (await loadAgentDefs()).agents
|
|
352
825
|
}
|
|
353
826
|
);
|
|
354
827
|
this.reportPropagatedRecompile(report);
|
|
355
828
|
} catch (error) {
|
|
356
|
-
this.warn(`Could not record global
|
|
829
|
+
this.warn(`Could not record global origin change: ${getErrorMessage(error)}`);
|
|
357
830
|
}
|
|
358
831
|
}
|
|
359
832
|
logChangeSummary(changes, newSkills, oldSkills, removalReasons) {
|
|
@@ -430,11 +903,37 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
|
|
|
430
903
|
for (const warning of migrationResult.warnings) {
|
|
431
904
|
this.warn(warning);
|
|
432
905
|
}
|
|
906
|
+
if (migrationPlan.toEject.length > 0) {
|
|
907
|
+
this.reportEjectCopies(migrationResult.ejectCopies);
|
|
908
|
+
}
|
|
433
909
|
if (migrationPlan.toPlugin.length > 0) {
|
|
434
910
|
this.reportPluginInstalls(migrationResult.pluginInstalls);
|
|
435
911
|
}
|
|
436
912
|
return migratedSkillIds;
|
|
437
913
|
}
|
|
914
|
+
/**
|
|
915
|
+
* What the plugin→eject half copied, what it could not, and the refusal to continue past
|
|
916
|
+
* a failure.
|
|
917
|
+
*
|
|
918
|
+
* The shape of `BaseCommand.reportPluginInstalls`, deliberately: the two directions of one
|
|
919
|
+
* mode switch owe the user the same account, and the eject half having no structured
|
|
920
|
+
* failure at all is what let a config record `origin: "eject"` for a skill whose copy was
|
|
921
|
+
* refused. It stays private because `edit` is the only command that migrates a mode —
|
|
922
|
+
* `init` installs, and has no old state to move.
|
|
923
|
+
*
|
|
924
|
+
* The count line is the same one `copyNewLocalSkills` prints, and names no destination:
|
|
925
|
+
* the migration splits its copies between the project and $HOME by each skill's own scope,
|
|
926
|
+
* so one directory would misname the other half.
|
|
927
|
+
*/
|
|
928
|
+
reportEjectCopies(result) {
|
|
929
|
+
for (const item of result.failed) {
|
|
930
|
+
this.warn(`Failed to copy ${item.id} for eject: ${item.error}`);
|
|
931
|
+
}
|
|
932
|
+
if (result.failed.length > 0) {
|
|
933
|
+
this.error(ejectCopyFailureError(result.failed.length), { exit: EXIT_CODES.ERROR });
|
|
934
|
+
}
|
|
935
|
+
this.log(chalk.hex(CLI_COLORS.NEUTRAL)(localSkillsCopied(result.copied.length)));
|
|
936
|
+
}
|
|
438
937
|
/** Names what this run is switching, in the words `init` describes an install mode with. */
|
|
439
938
|
logModeSwitch(count, modeDescription) {
|
|
440
939
|
this.log(chalk.hex(CLI_COLORS.NEUTRAL)(`Switching ${count} skill(s) to ${modeDescription}`));
|
|
@@ -443,13 +942,13 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
|
|
|
443
942
|
const { scopeChanges } = changes;
|
|
444
943
|
for (const [skillId, change] of scopeChanges) {
|
|
445
944
|
const skillConfig = filteredResult.skills.find((s) => s.id === skillId);
|
|
446
|
-
if (skillConfig?.
|
|
945
|
+
if (skillConfig?.origin === EJECT_SOURCE) {
|
|
447
946
|
await migrateLocalSkillScope(skillId, change.from, cwd);
|
|
448
947
|
}
|
|
449
948
|
}
|
|
450
949
|
const hasPluginScopeChanges = [...scopeChanges.keys()].some((skillId) => {
|
|
451
950
|
const skillConfig = filteredResult.skills.find((s) => s.id === skillId);
|
|
452
|
-
return skillConfig && skillConfig.
|
|
951
|
+
return skillConfig && skillConfig.origin !== EJECT_SOURCE;
|
|
453
952
|
});
|
|
454
953
|
if (!hasPluginScopeChanges) return;
|
|
455
954
|
const marketplace = await this.requireMarketplaceOrExit(
|
|
@@ -482,10 +981,10 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
|
|
|
482
981
|
async applyPluginChanges(changes, filteredResult, activeOldSkills, context, cwd) {
|
|
483
982
|
const { addedSkills, removedSkills } = changes;
|
|
484
983
|
const addedPluginSkills = filteredResult.skills.filter(
|
|
485
|
-
(s) => addedSkills.includes(s.id) && s.
|
|
984
|
+
(s) => addedSkills.includes(s.id) && s.origin !== EJECT_SOURCE
|
|
486
985
|
);
|
|
487
986
|
const removedPluginSkills = removedSkills.filter(
|
|
488
|
-
(id) => activeOldSkills.find((s) => s.id === id)?.
|
|
987
|
+
(id) => activeOldSkills.find((s) => s.id === id)?.origin !== EJECT_SOURCE
|
|
489
988
|
);
|
|
490
989
|
if (addedPluginSkills.length === 0 && removedPluginSkills.length === 0) return;
|
|
491
990
|
const marketplace = await this.requireMarketplaceOrExit(
|
|
@@ -493,7 +992,12 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
|
|
|
493
992
|
"install or uninstall plugin skills"
|
|
494
993
|
);
|
|
495
994
|
if (addedPluginSkills.length > 0) {
|
|
496
|
-
await this.installPluginSkillsReported(
|
|
995
|
+
await this.installPluginSkillsReported(
|
|
996
|
+
addedPluginSkills,
|
|
997
|
+
marketplace,
|
|
998
|
+
cwd,
|
|
999
|
+
context.sourceResult.matrix
|
|
1000
|
+
);
|
|
497
1001
|
}
|
|
498
1002
|
if (removedPluginSkills.length > 0) {
|
|
499
1003
|
const uninstallResult = await uninstallPluginSkills(
|
|
@@ -515,26 +1019,26 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
|
|
|
515
1019
|
async copyNewLocalSkills(changes, filteredResult, context, cwd) {
|
|
516
1020
|
const { addedSkills } = changes;
|
|
517
1021
|
const addedLocalSkills = filteredResult.skills.filter(
|
|
518
|
-
(s) => addedSkills.includes(s.id) && s.
|
|
1022
|
+
(s) => addedSkills.includes(s.id) && s.origin === EJECT_SOURCE
|
|
519
1023
|
);
|
|
520
1024
|
if (addedLocalSkills.length > 0) {
|
|
521
1025
|
const copyResult = await copyLocalSkills(addedLocalSkills, cwd, context.sourceResult);
|
|
522
|
-
this.log(chalk.hex(CLI_COLORS.NEUTRAL)(
|
|
1026
|
+
this.log(chalk.hex(CLI_COLORS.NEUTRAL)(localSkillsCopied(copyResult.totalCopied)));
|
|
523
1027
|
}
|
|
524
1028
|
}
|
|
525
1029
|
async removeDeletedLocalSkills(changes, activeOldSkills, cwd) {
|
|
526
1030
|
const { removedSkills } = changes;
|
|
527
1031
|
for (const skillId of removedSkills) {
|
|
528
1032
|
const oldSkill = activeOldSkills.find((s) => s.id === skillId);
|
|
529
|
-
if (oldSkill?.
|
|
1033
|
+
if (oldSkill?.origin !== EJECT_SOURCE) continue;
|
|
530
1034
|
const deleteDir = installBaseDir(cwd, oldSkill.scope);
|
|
531
1035
|
await deleteLocalSkill(deleteDir, skillId);
|
|
532
1036
|
}
|
|
533
1037
|
}
|
|
534
|
-
async writeConfigAndCompile(result, context, cwd) {
|
|
1038
|
+
async writeConfigAndCompile(result, context, cwd, authority) {
|
|
535
1039
|
let agentDefsResult;
|
|
536
1040
|
try {
|
|
537
|
-
agentDefsResult = await loadAgentDefs(
|
|
1041
|
+
agentDefsResult = await loadAgentDefs();
|
|
538
1042
|
} catch (error) {
|
|
539
1043
|
this.handleError(error);
|
|
540
1044
|
}
|
|
@@ -546,14 +1050,17 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
|
|
|
546
1050
|
projectDir: cwd,
|
|
547
1051
|
agents: agentDefsResult.agents,
|
|
548
1052
|
// A full `cc edit` pass is authoritative over the roster it owns, so deselected entries
|
|
549
|
-
// are removed rather than union-preserved (D-233 Scenario C).
|
|
550
|
-
//
|
|
551
|
-
//
|
|
552
|
-
authoritativeScope:
|
|
1053
|
+
// are removed rather than union-preserved (D-233 Scenario C). `applyAuthority` decides
|
|
1054
|
+
// how much that is from the producer and the directory, and hands the same word to the
|
|
1055
|
+
// merger and to the global config the project branch of the gate commits.
|
|
1056
|
+
authoritativeScope: authority
|
|
553
1057
|
});
|
|
554
1058
|
} catch (error) {
|
|
555
|
-
this.
|
|
1059
|
+
this.error(`Could not update config: ${getErrorMessage(error)}`, {
|
|
1060
|
+
exit: EXIT_CODES.ERROR
|
|
1061
|
+
});
|
|
556
1062
|
}
|
|
1063
|
+
this.reportUnassignedSkills(configResult.config);
|
|
557
1064
|
try {
|
|
558
1065
|
const agentScopeMap = activeAgentScopeMap(result.agentConfigs);
|
|
559
1066
|
const { allSkills } = await discoverInstalledSkills(cwd);
|
|
@@ -585,31 +1092,14 @@ ${chalk.hex(CLI_COLORS.WHITE).bold("Changes:")}`);
|
|
|
585
1092
|
this.warn(`Agent recompilation failed: ${getErrorMessage(error)}`);
|
|
586
1093
|
this.log(`You can manually recompile with '${CLI_INVOKE_COMMAND} compile'.`);
|
|
587
1094
|
}
|
|
588
|
-
|
|
589
|
-
this.reportPropagatedRecompile(configResult.propagation);
|
|
590
|
-
}
|
|
1095
|
+
this.reportPropagatedRecompile(configResult.propagation);
|
|
591
1096
|
}
|
|
592
1097
|
async cleanupStaleAgentFiles(changes, oldAgents, cwd) {
|
|
593
|
-
const
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
`${agentName}.md`
|
|
599
|
-
);
|
|
600
|
-
try {
|
|
601
|
-
await remove(oldAgentPath);
|
|
602
|
-
} catch (error) {
|
|
603
|
-
this.warn(`Could not remove old agent file ${oldAgentPath}: ${getErrorMessage(error)}`);
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
for (const agentName of removedAgents) {
|
|
607
|
-
const oldScope = oldAgents.find((a) => a.name === agentName)?.scope ?? "project";
|
|
608
|
-
const agentPath = path.join(resolveInstallPaths(cwd, oldScope).agentsDir, `${agentName}.md`);
|
|
609
|
-
try {
|
|
610
|
-
await remove(agentPath);
|
|
611
|
-
} catch (error) {
|
|
612
|
-
this.warn(`Could not remove agent file ${agentPath}: ${getErrorMessage(error)}`);
|
|
1098
|
+
for (const removal of planStaleAgentRemovals(changes, oldAgents, cwd)) {
|
|
1099
|
+
const { failed } = await removeCompiledAgents(removal);
|
|
1100
|
+
for (const { name, error } of failed) {
|
|
1101
|
+
const agentPath = path.join(removal.agentsDir, `${name}.md`);
|
|
1102
|
+
this.warn(`Could not remove agent file ${agentPath}: ${error}`);
|
|
613
1103
|
}
|
|
614
1104
|
}
|
|
615
1105
|
}
|
|
@@ -647,7 +1137,7 @@ function detectConfigChanges(oldConfig, wizardResult, fullEntries) {
|
|
|
647
1137
|
wizardResult.skills,
|
|
648
1138
|
oldSkillsById,
|
|
649
1139
|
(s) => s.id,
|
|
650
|
-
(s) => s.
|
|
1140
|
+
(s) => s.origin
|
|
651
1141
|
),
|
|
652
1142
|
scopeChanges,
|
|
653
1143
|
agentScopeChanges,
|
|
@@ -688,6 +1178,24 @@ function detectDualScopeTransitions(scopeChanges, fullNew, fullOld, getKey) {
|
|
|
688
1178
|
}
|
|
689
1179
|
return result;
|
|
690
1180
|
}
|
|
1181
|
+
var STALE_AGENT_SCOPES = ["project", "global"];
|
|
1182
|
+
var UNRECORDED_AGENT_SCOPE = "project";
|
|
1183
|
+
function installedScope(name, oldAgents) {
|
|
1184
|
+
return oldAgents.find((agent) => agent.name === name)?.scope ?? UNRECORDED_AGENT_SCOPE;
|
|
1185
|
+
}
|
|
1186
|
+
function planStaleAgentRemovals(changes, oldAgents, cwd) {
|
|
1187
|
+
const supersededByGlobal = [...changes.agentScopeChanges].filter(([, change]) => change.from !== "global").map(([name]) => ({ name, scope: "project" }));
|
|
1188
|
+
const deselected = changes.removedAgents.map((name) => ({
|
|
1189
|
+
name,
|
|
1190
|
+
scope: installedScope(name, oldAgents)
|
|
1191
|
+
}));
|
|
1192
|
+
const stale = [...supersededByGlobal, ...deselected];
|
|
1193
|
+
const removalAtScope = (scope) => ({
|
|
1194
|
+
agentsDir: resolveInstallPaths(cwd, scope).agentsDir,
|
|
1195
|
+
agents: stale.filter((agent) => agent.scope === scope).map((agent) => agent.name)
|
|
1196
|
+
});
|
|
1197
|
+
return STALE_AGENT_SCOPES.map(removalAtScope).filter((removal) => removal.agents.length > 0);
|
|
1198
|
+
}
|
|
691
1199
|
function hasAnyChanges(changes) {
|
|
692
1200
|
return changes.addedSkills.length > 0 || changes.removedSkills.length > 0 || changes.addedAgents.length > 0 || changes.removedAgents.length > 0 || changes.sourceChanges.size > 0 || changes.scopeChanges.size > 0 || changes.agentScopeChanges.size > 0;
|
|
693
1201
|
}
|
|
@@ -696,7 +1204,7 @@ async function migratePluginSkillScopes(scopeChanges, skills, marketplace, proje
|
|
|
696
1204
|
const failed = [];
|
|
697
1205
|
for (const [skillId, change] of scopeChanges) {
|
|
698
1206
|
const skillConfig = skills.find((s) => s.id === skillId);
|
|
699
|
-
if (!skillConfig || skillConfig.
|
|
1207
|
+
if (!skillConfig || skillConfig.origin === EJECT_SOURCE) {
|
|
700
1208
|
continue;
|
|
701
1209
|
}
|
|
702
1210
|
const newPluginScope = toClaudePluginScope(change.to);
|