agents-inc 0.161.1 → 0.163.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 +42 -0
- package/dist/{chunk-DOQUAWL4.js → chunk-3CSK5CQN.js} +17 -16
- package/dist/chunk-3CSK5CQN.js.map +1 -0
- package/dist/{chunk-VFZF7LVY.js → chunk-3WVH2CTK.js} +3 -3
- package/dist/{chunk-SBL4AYSB.js → chunk-4VL3CEOS.js} +3 -3
- package/dist/{chunk-QM3ZNOWJ.js → chunk-6MV4JOCL.js} +2 -2
- package/dist/{chunk-ADSIYZGS.js → chunk-7ANJQLPJ.js} +2 -2
- package/dist/{chunk-3JDVBHWO.js → chunk-7REKOTKG.js} +2 -2
- package/dist/{chunk-MI7LKLD7.js → chunk-ABAZMMG4.js} +2 -2
- package/dist/{chunk-2P3MKX5Q.js → chunk-AOTCIUGX.js} +2 -2
- package/dist/{chunk-GUFRQJAE.js → chunk-ARYNOWKF.js} +8 -8
- package/dist/{chunk-3QBOVV6A.js → chunk-AVK2HEKB.js} +5 -5
- package/dist/{chunk-3QBOVV6A.js.map → chunk-AVK2HEKB.js.map} +1 -1
- package/dist/{chunk-Z56AUTER.js → chunk-B3Y3QMWI.js} +4 -4
- package/dist/{chunk-WDN4HAN7.js → chunk-DSL66I4N.js} +6 -6
- package/dist/{chunk-SXYFATQN.js → chunk-ECURHW3T.js} +12 -12
- package/dist/{chunk-TPRRWOHZ.js → chunk-FLW25ORT.js} +3 -3
- package/dist/{chunk-YC4CLTQE.js → chunk-IAVEMTN4.js} +35 -14
- package/dist/chunk-IAVEMTN4.js.map +1 -0
- package/dist/{chunk-F5JTW3HZ.js → chunk-JIERYE6B.js} +5 -5
- package/dist/{chunk-UE3MLDL2.js → chunk-K5ITEA3I.js} +4 -4
- package/dist/{chunk-Q4KCUR2T.js → chunk-LT5GXEB2.js} +6 -6
- package/dist/{chunk-C2K7Q7HO.js → chunk-NKGYKOB7.js} +3 -3
- package/dist/{chunk-X6KXPRKI.js → chunk-NQXO4LR3.js} +4 -4
- package/dist/{chunk-7ZFEZN4Y.js → chunk-NTF4UXGK.js} +71 -9
- package/dist/{chunk-7ZFEZN4Y.js.map → chunk-NTF4UXGK.js.map} +1 -1
- package/dist/{chunk-IAN7QDBR.js → chunk-O664ITBD.js} +108 -25
- package/dist/chunk-O664ITBD.js.map +1 -0
- package/dist/{chunk-77YZFVQD.js → chunk-PHCPUQVR.js} +2 -2
- package/dist/{chunk-U5O4BWKI.js → chunk-PM3374E7.js} +43 -41
- package/dist/chunk-PM3374E7.js.map +1 -0
- package/dist/{chunk-ESI3JYOQ.js → chunk-Q4IRRVXK.js} +3 -3
- package/dist/{chunk-EN5MEPAS.js → chunk-QGUP3QJF.js} +5 -5
- package/dist/{chunk-MSUTHS2V.js → chunk-QZX7SYKU.js} +2 -2
- package/dist/{chunk-ZPFM2VHZ.js → chunk-RGYDFBCT.js} +4 -4
- package/dist/{chunk-4NAWM4OQ.js → chunk-S63LXWMC.js} +2 -2
- package/dist/{chunk-QTLYSVYE.js → chunk-SMSB6YZW.js} +3 -3
- package/dist/{chunk-IV42Z63R.js → chunk-UITEKY2R.js} +19 -9
- package/dist/chunk-UITEKY2R.js.map +1 -0
- package/dist/{chunk-SWYV7QXX.js → chunk-URXIQE7I.js} +2 -2
- package/dist/{chunk-ZYXQUU2P.js → chunk-V5GLL2JB.js} +7 -7
- package/dist/{chunk-JEJJHRZA.js → chunk-X4SSJZLY.js} +77 -8
- package/dist/chunk-X4SSJZLY.js.map +1 -0
- package/dist/{chunk-QG4NRKZD.js → chunk-XATLUKXK.js} +5 -5
- package/dist/{chunk-RLSZWDTB.js → chunk-XHPWTL4I.js} +3 -3
- package/dist/{chunk-7WKNPDN2.js → chunk-XPDVAJDH.js} +112 -32
- package/dist/chunk-XPDVAJDH.js.map +1 -0
- package/dist/{chunk-FL2CJ5T5.js → chunk-YRS3QZP2.js} +3 -3
- package/dist/{chunk-FXL63LDL.js → chunk-ZVXGW2IC.js} +2 -2
- package/dist/commands/build/marketplace.js +7 -7
- package/dist/commands/build/plugins.js +7 -7
- package/dist/commands/compile.js +82 -30
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/doctor.js +10 -10
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +40 -38
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +10 -10
- package/dist/commands/init.js +36 -36
- package/dist/commands/list.js +8 -8
- package/dist/commands/new/marketplace.js +7 -7
- package/dist/commands/search.js +15 -14
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/share.js +22 -16
- package/dist/commands/share.js.map +1 -1
- package/dist/commands/uninstall.js +11 -11
- package/dist/commands/update.js +6 -6
- package/dist/components/common/removal-plan-confirm.js +2 -2
- package/dist/components/common/select-list.js +2 -2
- package/dist/components/wizard/category-grid.js +4 -4
- package/dist/components/wizard/checkbox-grid.js +4 -4
- package/dist/components/wizard/domain-selection.js +9 -9
- package/dist/components/wizard/run-wizard-session.js +26 -26
- package/dist/components/wizard/scroll-affordance.js +2 -2
- package/dist/components/wizard/skill-agent-summary.js +5 -5
- package/dist/components/wizard/source-grid.js +5 -5
- package/dist/components/wizard/stack-selection.js +7 -7
- package/dist/components/wizard/step-agents.js +8 -8
- package/dist/components/wizard/step-build.js +7 -7
- package/dist/components/wizard/step-confirm.js +9 -9
- package/dist/components/wizard/step-sources.js +8 -8
- package/dist/components/wizard/step-stack.js +8 -8
- package/dist/components/wizard/summary-panel.js +8 -8
- package/dist/components/wizard/toast.js +2 -2
- package/dist/components/wizard/wizard-layout.js +12 -12
- package/dist/components/wizard/wizard-tabs.js +2 -2
- package/dist/components/wizard/wizard.js +25 -25
- package/dist/hooks/init.js +36 -36
- package/dist/load-agent-defs-5J2MZLAA.js +13 -0
- package/dist/recompile-project-agents-FCJLHAE3.js +17 -0
- package/dist/{source-loader-7T754EZC.js → source-loader-GRBVNRAW.js} +4 -4
- package/dist/src/agents/_templates/agent.liquid +30 -122
- package/dist/src/agents/_templates/methodologies/operating-principles.liquid +27 -0
- package/dist/src/agents/developer/ai-developer/critical-reminders.md +9 -48
- package/dist/src/agents/developer/ai-developer/critical-requirements.md +29 -47
- package/dist/src/agents/developer/ai-developer/identity.md +31 -40
- package/dist/src/agents/developer/ai-developer/output.md +92 -245
- package/dist/src/agents/developer/ai-developer/playbook.md +116 -270
- package/dist/src/agents/developer/api-developer/critical-reminders.md +9 -40
- package/dist/src/agents/developer/api-developer/critical-requirements.md +19 -34
- package/dist/src/agents/developer/api-developer/identity.md +18 -33
- package/dist/src/agents/developer/api-developer/output.md +118 -255
- package/dist/src/agents/developer/api-developer/playbook.md +103 -284
- package/dist/src/agents/developer/cli-developer/critical-reminders.md +9 -45
- package/dist/src/agents/developer/cli-developer/critical-requirements.md +21 -39
- package/dist/src/agents/developer/cli-developer/identity.md +22 -36
- package/dist/src/agents/developer/cli-developer/output.md +72 -185
- package/dist/src/agents/developer/cli-developer/playbook.md +107 -307
- package/dist/src/agents/developer/web-developer/critical-reminders.md +9 -34
- package/dist/src/agents/developer/web-developer/critical-requirements.md +11 -30
- package/dist/src/agents/developer/web-developer/identity.md +15 -15
- package/dist/src/agents/developer/web-developer/output.md +67 -220
- package/dist/src/agents/developer/web-developer/playbook.md +93 -283
- package/dist/src/agents/meta/agent-summoner/critical-reminders.md +6 -39
- package/dist/src/agents/meta/agent-summoner/critical-requirements.md +6 -44
- package/dist/src/agents/meta/agent-summoner/identity.md +20 -23
- package/dist/src/agents/meta/agent-summoner/metadata.yaml +1 -1
- package/dist/src/agents/meta/agent-summoner/output.md +85 -261
- package/dist/src/agents/meta/agent-summoner/playbook.md +220 -1398
- package/dist/src/agents/meta/codex-keeper/critical-reminders.md +11 -32
- package/dist/src/agents/meta/codex-keeper/critical-requirements.md +32 -22
- package/dist/src/agents/meta/codex-keeper/identity.md +31 -32
- package/dist/src/agents/meta/codex-keeper/output.md +49 -335
- package/dist/src/agents/meta/codex-keeper/playbook.md +151 -1112
- package/dist/src/agents/meta/convention-keeper/critical-reminders.md +11 -26
- package/dist/src/agents/meta/convention-keeper/critical-requirements.md +36 -25
- package/dist/src/agents/meta/convention-keeper/identity.md +35 -21
- package/dist/src/agents/meta/convention-keeper/metadata.yaml +1 -1
- package/dist/src/agents/meta/convention-keeper/output.md +33 -123
- package/dist/src/agents/meta/convention-keeper/playbook.md +64 -144
- package/dist/src/agents/meta/skill-summoner/critical-reminders.md +8 -71
- package/dist/src/agents/meta/skill-summoner/critical-requirements.md +9 -73
- package/dist/src/agents/meta/skill-summoner/identity.md +18 -22
- package/dist/src/agents/meta/skill-summoner/metadata.yaml +1 -1
- package/dist/src/agents/meta/skill-summoner/output.md +164 -270
- package/dist/src/agents/meta/skill-summoner/playbook.md +150 -1398
- package/dist/src/agents/planning/pm/critical-requirements.md +23 -25
- package/dist/src/agents/planning/pm/identity.md +24 -23
- package/dist/src/agents/planning/pm/output.md +5 -9
- package/dist/src/agents/planning/pm/playbook.md +50 -140
- package/dist/src/agents/researcher/ai-researcher/critical-reminders.md +8 -53
- package/dist/src/agents/researcher/ai-researcher/critical-requirements.md +31 -26
- package/dist/src/agents/researcher/ai-researcher/identity.md +36 -77
- package/dist/src/agents/researcher/ai-researcher/output.md +44 -151
- package/dist/src/agents/researcher/ai-researcher/playbook.md +130 -394
- package/dist/src/agents/researcher/api-researcher/critical-reminders.md +6 -38
- package/dist/src/agents/researcher/api-researcher/critical-requirements.md +15 -17
- package/dist/src/agents/researcher/api-researcher/identity.md +29 -63
- package/dist/src/agents/researcher/api-researcher/output.md +61 -153
- package/dist/src/agents/researcher/api-researcher/playbook.md +63 -140
- package/dist/src/agents/researcher/cli-researcher/critical-reminders.md +8 -45
- package/dist/src/agents/researcher/cli-researcher/critical-requirements.md +29 -24
- package/dist/src/agents/researcher/cli-researcher/identity.md +36 -78
- package/dist/src/agents/researcher/cli-researcher/output.md +22 -128
- package/dist/src/agents/researcher/cli-researcher/playbook.md +108 -263
- package/dist/src/agents/researcher/web-researcher/critical-reminders.md +5 -34
- package/dist/src/agents/researcher/web-researcher/critical-requirements.md +11 -16
- package/dist/src/agents/researcher/web-researcher/identity.md +28 -60
- package/dist/src/agents/researcher/web-researcher/output.md +41 -134
- package/dist/src/agents/researcher/web-researcher/playbook.md +48 -162
- package/dist/src/agents/reviewer/reviewer/critical-reminders.md +9 -22
- package/dist/src/agents/reviewer/reviewer/critical-requirements.md +24 -19
- package/dist/src/agents/reviewer/reviewer/identity.md +23 -20
- package/dist/src/agents/reviewer/reviewer/metadata.yaml +7 -2
- package/dist/src/agents/reviewer/reviewer/output.md +8 -26
- package/dist/src/agents/reviewer/reviewer/playbook.md +50 -91
- package/dist/src/agents/tester/ai-tester/critical-reminders.md +7 -40
- package/dist/src/agents/tester/ai-tester/critical-requirements.md +39 -31
- package/dist/src/agents/tester/ai-tester/identity.md +25 -40
- package/dist/src/agents/tester/ai-tester/output.md +8 -144
- package/dist/src/agents/tester/ai-tester/playbook.md +28 -40
- package/dist/src/agents/tester/api-tester/critical-reminders.md +8 -35
- package/dist/src/agents/tester/api-tester/critical-requirements.md +36 -25
- package/dist/src/agents/tester/api-tester/identity.md +18 -29
- package/dist/src/agents/tester/api-tester/metadata.yaml +1 -1
- package/dist/src/agents/tester/api-tester/output.md +3 -86
- package/dist/src/agents/tester/api-tester/playbook.md +10 -2
- package/dist/src/agents/tester/cli-tester/critical-reminders.md +7 -30
- package/dist/src/agents/tester/cli-tester/critical-requirements.md +29 -21
- package/dist/src/agents/tester/cli-tester/identity.md +25 -33
- package/dist/src/agents/tester/cli-tester/output.md +13 -105
- package/dist/src/agents/tester/cli-tester/playbook.md +8 -5
- package/dist/src/agents/tester/web-tester/critical-reminders.md +7 -25
- package/dist/src/agents/tester/web-tester/critical-requirements.md +25 -16
- package/dist/src/agents/tester/web-tester/identity.md +24 -30
- package/dist/src/agents/tester/web-tester/output.md +11 -116
- package/dist/src/agents/tester/web-tester/playbook.md +58 -221
- package/dist/stores/wizard-store.js +4 -4
- package/package.json +2 -2
- package/src/agents/_templates/agent.liquid +30 -122
- package/src/agents/_templates/methodologies/operating-principles.liquid +27 -0
- package/src/agents/developer/ai-developer/critical-reminders.md +9 -48
- package/src/agents/developer/ai-developer/critical-requirements.md +29 -47
- package/src/agents/developer/ai-developer/identity.md +31 -40
- package/src/agents/developer/ai-developer/output.md +92 -245
- package/src/agents/developer/ai-developer/playbook.md +116 -270
- package/src/agents/developer/api-developer/critical-reminders.md +9 -40
- package/src/agents/developer/api-developer/critical-requirements.md +19 -34
- package/src/agents/developer/api-developer/identity.md +18 -33
- package/src/agents/developer/api-developer/output.md +118 -255
- package/src/agents/developer/api-developer/playbook.md +103 -284
- package/src/agents/developer/cli-developer/critical-reminders.md +9 -45
- package/src/agents/developer/cli-developer/critical-requirements.md +21 -39
- package/src/agents/developer/cli-developer/identity.md +22 -36
- package/src/agents/developer/cli-developer/output.md +72 -185
- package/src/agents/developer/cli-developer/playbook.md +107 -307
- package/src/agents/developer/web-developer/critical-reminders.md +9 -34
- package/src/agents/developer/web-developer/critical-requirements.md +11 -30
- package/src/agents/developer/web-developer/identity.md +15 -15
- package/src/agents/developer/web-developer/output.md +67 -220
- package/src/agents/developer/web-developer/playbook.md +93 -283
- package/src/agents/meta/agent-summoner/critical-reminders.md +6 -39
- package/src/agents/meta/agent-summoner/critical-requirements.md +6 -44
- package/src/agents/meta/agent-summoner/identity.md +20 -23
- package/src/agents/meta/agent-summoner/metadata.yaml +1 -1
- package/src/agents/meta/agent-summoner/output.md +85 -261
- package/src/agents/meta/agent-summoner/playbook.md +220 -1398
- package/src/agents/meta/codex-keeper/critical-reminders.md +11 -32
- package/src/agents/meta/codex-keeper/critical-requirements.md +32 -22
- package/src/agents/meta/codex-keeper/identity.md +31 -32
- package/src/agents/meta/codex-keeper/output.md +49 -335
- package/src/agents/meta/codex-keeper/playbook.md +151 -1112
- package/src/agents/meta/convention-keeper/critical-reminders.md +11 -26
- package/src/agents/meta/convention-keeper/critical-requirements.md +36 -25
- package/src/agents/meta/convention-keeper/identity.md +35 -21
- package/src/agents/meta/convention-keeper/metadata.yaml +1 -1
- package/src/agents/meta/convention-keeper/output.md +33 -123
- package/src/agents/meta/convention-keeper/playbook.md +64 -144
- package/src/agents/meta/skill-summoner/critical-reminders.md +8 -71
- package/src/agents/meta/skill-summoner/critical-requirements.md +9 -73
- package/src/agents/meta/skill-summoner/identity.md +18 -22
- package/src/agents/meta/skill-summoner/metadata.yaml +1 -1
- package/src/agents/meta/skill-summoner/output.md +164 -270
- package/src/agents/meta/skill-summoner/playbook.md +150 -1398
- package/src/agents/planning/pm/critical-requirements.md +23 -25
- package/src/agents/planning/pm/identity.md +24 -23
- package/src/agents/planning/pm/output.md +5 -9
- package/src/agents/planning/pm/playbook.md +50 -140
- package/src/agents/researcher/ai-researcher/critical-reminders.md +8 -53
- package/src/agents/researcher/ai-researcher/critical-requirements.md +31 -26
- package/src/agents/researcher/ai-researcher/identity.md +36 -77
- package/src/agents/researcher/ai-researcher/output.md +44 -151
- package/src/agents/researcher/ai-researcher/playbook.md +130 -394
- package/src/agents/researcher/api-researcher/critical-reminders.md +6 -38
- package/src/agents/researcher/api-researcher/critical-requirements.md +15 -17
- package/src/agents/researcher/api-researcher/identity.md +29 -63
- package/src/agents/researcher/api-researcher/output.md +61 -153
- package/src/agents/researcher/api-researcher/playbook.md +63 -140
- package/src/agents/researcher/cli-researcher/critical-reminders.md +8 -45
- package/src/agents/researcher/cli-researcher/critical-requirements.md +29 -24
- package/src/agents/researcher/cli-researcher/identity.md +36 -78
- package/src/agents/researcher/cli-researcher/output.md +22 -128
- package/src/agents/researcher/cli-researcher/playbook.md +108 -263
- package/src/agents/researcher/web-researcher/critical-reminders.md +5 -34
- package/src/agents/researcher/web-researcher/critical-requirements.md +11 -16
- package/src/agents/researcher/web-researcher/identity.md +28 -60
- package/src/agents/researcher/web-researcher/output.md +41 -134
- package/src/agents/researcher/web-researcher/playbook.md +48 -162
- package/src/agents/reviewer/reviewer/critical-reminders.md +9 -22
- package/src/agents/reviewer/reviewer/critical-requirements.md +24 -19
- package/src/agents/reviewer/reviewer/identity.md +23 -20
- package/src/agents/reviewer/reviewer/metadata.yaml +7 -2
- package/src/agents/reviewer/reviewer/output.md +8 -26
- package/src/agents/reviewer/reviewer/playbook.md +50 -91
- package/src/agents/tester/ai-tester/critical-reminders.md +7 -40
- package/src/agents/tester/ai-tester/critical-requirements.md +39 -31
- package/src/agents/tester/ai-tester/identity.md +25 -40
- package/src/agents/tester/ai-tester/output.md +8 -144
- package/src/agents/tester/ai-tester/playbook.md +28 -40
- package/src/agents/tester/api-tester/critical-reminders.md +8 -35
- package/src/agents/tester/api-tester/critical-requirements.md +36 -25
- package/src/agents/tester/api-tester/identity.md +18 -29
- package/src/agents/tester/api-tester/metadata.yaml +1 -1
- package/src/agents/tester/api-tester/output.md +3 -86
- package/src/agents/tester/api-tester/playbook.md +10 -2
- package/src/agents/tester/cli-tester/critical-reminders.md +7 -30
- package/src/agents/tester/cli-tester/critical-requirements.md +29 -21
- package/src/agents/tester/cli-tester/identity.md +25 -33
- package/src/agents/tester/cli-tester/output.md +13 -105
- package/src/agents/tester/cli-tester/playbook.md +8 -5
- package/src/agents/tester/web-tester/critical-reminders.md +7 -25
- package/src/agents/tester/web-tester/critical-requirements.md +25 -16
- package/src/agents/tester/web-tester/identity.md +24 -30
- package/src/agents/tester/web-tester/output.md +11 -116
- package/src/agents/tester/web-tester/playbook.md +58 -221
- package/src/schemas/agent-frontmatter.schema.json +14 -0
- package/src/schemas/agent.schema.json +14 -0
- package/dist/chunk-7WKNPDN2.js.map +0 -1
- package/dist/chunk-DOQUAWL4.js.map +0 -1
- package/dist/chunk-IAN7QDBR.js.map +0 -1
- package/dist/chunk-IV42Z63R.js.map +0 -1
- package/dist/chunk-JEJJHRZA.js.map +0 -1
- package/dist/chunk-U5O4BWKI.js.map +0 -1
- package/dist/chunk-YC4CLTQE.js.map +0 -1
- package/dist/load-agent-defs-TWDFYM5S.js +0 -13
- package/dist/recompile-project-agents-YIGIVMCQ.js +0 -17
- package/dist/src/agents/_templates/methodologies/anti-over-engineering.liquid +0 -135
- package/dist/src/agents/_templates/methodologies/context-management.liquid +0 -15
- package/dist/src/agents/_templates/methodologies/improvement-protocol.liquid +0 -150
- package/dist/src/agents/_templates/methodologies/investigation-requirements.liquid +0 -61
- package/dist/src/agents/_templates/methodologies/success-criteria.liquid +0 -121
- package/dist/src/agents/_templates/methodologies/write-verification.liquid +0 -43
- package/dist/src/agents/planning/pm/critical-reminders.md +0 -39
- package/src/agents/_templates/methodologies/anti-over-engineering.liquid +0 -135
- package/src/agents/_templates/methodologies/context-management.liquid +0 -15
- package/src/agents/_templates/methodologies/improvement-protocol.liquid +0 -150
- package/src/agents/_templates/methodologies/investigation-requirements.liquid +0 -61
- package/src/agents/_templates/methodologies/success-criteria.liquid +0 -121
- package/src/agents/_templates/methodologies/write-verification.liquid +0 -43
- package/src/agents/planning/pm/critical-reminders.md +0 -39
- /package/dist/{chunk-VFZF7LVY.js.map → chunk-3WVH2CTK.js.map} +0 -0
- /package/dist/{chunk-SBL4AYSB.js.map → chunk-4VL3CEOS.js.map} +0 -0
- /package/dist/{chunk-QM3ZNOWJ.js.map → chunk-6MV4JOCL.js.map} +0 -0
- /package/dist/{chunk-ADSIYZGS.js.map → chunk-7ANJQLPJ.js.map} +0 -0
- /package/dist/{chunk-3JDVBHWO.js.map → chunk-7REKOTKG.js.map} +0 -0
- /package/dist/{chunk-MI7LKLD7.js.map → chunk-ABAZMMG4.js.map} +0 -0
- /package/dist/{chunk-2P3MKX5Q.js.map → chunk-AOTCIUGX.js.map} +0 -0
- /package/dist/{chunk-GUFRQJAE.js.map → chunk-ARYNOWKF.js.map} +0 -0
- /package/dist/{chunk-Z56AUTER.js.map → chunk-B3Y3QMWI.js.map} +0 -0
- /package/dist/{chunk-WDN4HAN7.js.map → chunk-DSL66I4N.js.map} +0 -0
- /package/dist/{chunk-SXYFATQN.js.map → chunk-ECURHW3T.js.map} +0 -0
- /package/dist/{chunk-TPRRWOHZ.js.map → chunk-FLW25ORT.js.map} +0 -0
- /package/dist/{chunk-F5JTW3HZ.js.map → chunk-JIERYE6B.js.map} +0 -0
- /package/dist/{chunk-UE3MLDL2.js.map → chunk-K5ITEA3I.js.map} +0 -0
- /package/dist/{chunk-Q4KCUR2T.js.map → chunk-LT5GXEB2.js.map} +0 -0
- /package/dist/{chunk-C2K7Q7HO.js.map → chunk-NKGYKOB7.js.map} +0 -0
- /package/dist/{chunk-X6KXPRKI.js.map → chunk-NQXO4LR3.js.map} +0 -0
- /package/dist/{chunk-77YZFVQD.js.map → chunk-PHCPUQVR.js.map} +0 -0
- /package/dist/{chunk-ESI3JYOQ.js.map → chunk-Q4IRRVXK.js.map} +0 -0
- /package/dist/{chunk-EN5MEPAS.js.map → chunk-QGUP3QJF.js.map} +0 -0
- /package/dist/{chunk-MSUTHS2V.js.map → chunk-QZX7SYKU.js.map} +0 -0
- /package/dist/{chunk-ZPFM2VHZ.js.map → chunk-RGYDFBCT.js.map} +0 -0
- /package/dist/{chunk-4NAWM4OQ.js.map → chunk-S63LXWMC.js.map} +0 -0
- /package/dist/{chunk-QTLYSVYE.js.map → chunk-SMSB6YZW.js.map} +0 -0
- /package/dist/{chunk-SWYV7QXX.js.map → chunk-URXIQE7I.js.map} +0 -0
- /package/dist/{chunk-ZYXQUU2P.js.map → chunk-V5GLL2JB.js.map} +0 -0
- /package/dist/{chunk-QG4NRKZD.js.map → chunk-XATLUKXK.js.map} +0 -0
- /package/dist/{chunk-RLSZWDTB.js.map → chunk-XHPWTL4I.js.map} +0 -0
- /package/dist/{chunk-FL2CJ5T5.js.map → chunk-YRS3QZP2.js.map} +0 -0
- /package/dist/{chunk-FXL63LDL.js.map → chunk-ZVXGW2IC.js.map} +0 -0
- /package/dist/{load-agent-defs-TWDFYM5S.js.map → load-agent-defs-5J2MZLAA.js.map} +0 -0
- /package/dist/{recompile-project-agents-YIGIVMCQ.js.map → recompile-project-agents-FCJLHAE3.js.map} +0 -0
- /package/dist/{source-loader-7T754EZC.js.map → source-loader-GRBVNRAW.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/lib/seed/installation-payload.ts","../src/cli/lib/seed/config-to-seed.ts","../src/cli/lib/seed/publish-seed.ts"],"sourcesContent":["import path from \"path\";\n\nimport { configToSeedPayload, isInstalled } from \"./config-to-seed.js\";\nimport { readCarriedSkills } from \"./external-skills.js\";\nimport { EJECT_SOURCE } from \"../../consts.js\";\nimport { loadProjectConfig } from \"../configuration/project-config.js\";\nimport { resolveInstallPaths } from \"../installation/install-base-dir.js\";\nimport { readForkedFromMetadata } from \"../skills/skill-metadata.js\";\nimport { getErrorMessage } from \"../../utils/errors.js\";\nimport { directoryExists } from \"../../utils/fs.js\";\nimport { ERROR_MESSAGES } from \"../../utils/messages.js\";\n\nimport type { ContentReading, OwnedSkillDir } from \"./external-skills.js\";\nimport type { ProjectConfig, SkillConfig, SkillId } from \"../../types/index.js\";\nimport type { SeedPayload } from \"@workspace/matrix/seed\";\n\n/**\n * A payload ready to post, and what it will install — counted the way the sharer's own screens\n * count it, off the payload rather than off the config, so what a caller announces and what it\n * posts cannot disagree.\n */\nexport type InstallationPayload =\n { ok: true; payload: SeedPayload; skills: number; agents: number } | { ok: false; error: string };\n\n/** The config to map, or the sentence explaining why there is none to map. */\ntype InstalledConfig = { ok: true; config: ProjectConfig } | { ok: false; error: string };\n\n/** The mapped payload, or every line naming something the contract cannot carry. */\ntype MappedPayload = { ok: true; payload: SeedPayload } | { ok: false; error: string };\n\n/** The installation as the round trip sees it: what it owns, and what it has to carry with it. */\ntype RoundTrip = { config: ProjectConfig; content: ContentReading };\n\n/**\n * What the round trip makes of one installed entry: whether it travels at all, and whether its\n * bytes travel with it.\n */\ntype SkillJudgement = { skill: SkillConfig; owned: boolean; carried: OwnedSkillDir | null };\n\n/**\n * Read, map, refuse — everything that can fail locally, failing before anybody spends a write.\n *\n * Shared by the two commands that mint an id for what is installed here: `share`, which reports\n * the id, and `edit --ui`, which opens it. They are one operation with two endings, and this is\n * the half that has to be identical — two spellings of \"the installation in this directory\"\n * would mint two different ids for one project, and only one of them would be true.\n *\n * Every failure is a message rather than a throw, because nothing has been written by the time\n * it runs: the caller's only job is to explain, and both callers explain the same way.\n */\nexport async function seedPayloadForInstallation(projectDir: string): Promise<InstallationPayload> {\n const installed = await readInstalledConfig(projectDir);\n if (!installed.ok) return installed;\n\n const mapped = mapOrRefuse(await readRoundTrip(installed.config, projectDir));\n if (!mapped.ok) return mapped;\n\n const { payload } = mapped;\n const skills = Object.keys(payload.skills).length;\n const agents = Object.keys(payload.agents).length;\n\n // The same guard `init --from` applies on arrival, applied here before the write instead of\n // there after it. A sub-agent is installable on its own — it has front-matter, a prompt and a\n // compiled file without owning a single skill — so only a configuration with neither skills\n // nor sub-agents is nothing to carry.\n if (skills === 0 && agents === 0) return { ok: false, error: ERROR_MESSAGES.NO_INSTALLATION };\n\n return { ok: true, payload, skills, agents };\n}\n\n/**\n * The installation this directory has: its own configuration, or the global one it inherits.\n *\n * That is the config every other command reads here, and it carries the entries of BOTH scopes\n * with each entry's own scope on it — which is exactly what the wire keys by. So a payload minted\n * from a project describes the whole of what is installed for it rather than half of it, and the\n * receiver puts each entry back where this one had it.\n *\n * A config file that exists but cannot be loaded is a fault, not an absence, so its own message\n * is reported rather than read as \"not installed\".\n */\nasync function readInstalledConfig(projectDir: string): Promise<InstalledConfig> {\n try {\n const loaded = await loadProjectConfig(projectDir);\n if (!loaded) return { ok: false, error: ERROR_MESSAGES.NO_INSTALLATION };\n return { ok: true, config: loaded.config };\n } catch (error) {\n return { ok: false, error: getErrorMessage(error) };\n }\n}\n\n/**\n * The installation minus what the round trip does not own, plus the content it has to take along.\n *\n * `forkedFrom` decides ownership, and the round trip leaves what it does not own alone. The CLI\n * stamps that key into every skill directory it writes — an ejected catalogue skill, and a skill\n * a payload carried inline — while a skill the user wrote by hand into `.claude/skills/` carries\n * none. So absence of the key is not the whole answer and provenance is: what the CLI put there\n * says so on disk, and what a person put there says nothing because nothing forked it.\n *\n * A user-authored skill is therefore neither carried nor refused — it is simply outside the\n * round trip, and nothing about leaving it home is lossy because it was never in scope. Dropping\n * it here rather than in a command is what keeps `share` and `edit --ui`, which mint an id from\n * the same directory, from disagreeing about a single project.\n *\n * The stack rows naming a dropped skill go with it: `configToSeedPayload` keys assignments by\n * the skills it carries, so a row whose skill is gone is gone too.\n *\n * One walk answers both questions, because they are asked of the same file: whether the CLI put\n * this directory here, and — for the one kind of skill no catalogue can resolve — where its bytes\n * came from, so they can travel a second time.\n */\nasync function readRoundTrip(config: ProjectConfig, projectDir: string): Promise<RoundTrip> {\n const owned = (await judgeSkills(config, projectDir)).filter((entry) => entry.owned);\n\n return {\n config: { ...config, skills: owned.map((entry) => entry.skill) },\n content: await readCarriedSkills(owned.flatMap((entry) => entry.carried ?? [])),\n };\n}\n\n/** Every installed entry, judged. One walk of the disk, whichever half of the trip is asking. */\nfunction judgeSkills(config: ProjectConfig, projectDir: string): Promise<SkillJudgement[]> {\n return Promise.all(config.skills.map((skill) => judgeSkill(skill, projectDir)));\n}\n\n/**\n * The installed skills the round trip does NOT own — the user's own work, sitting in\n * `.claude/skills/` with no `forkedFrom` to say the CLI put it there.\n *\n * The producer already drops these on the way out, so no payload minted here ever named one.\n * This is the same judgement read by the other half: `edit --from` applies a payload\n * destructively, and a payload that made no statement about a skill cannot be read as an\n * instruction to delete it. Both halves ask {@link judgeSkill}, so \"outside the round trip\" has\n * one definition and cannot come to mean two things on one machine.\n */\nexport async function skillsAuthoredHere(\n config: ProjectConfig,\n projectDir: string,\n): Promise<Set<SkillId>> {\n const judged = await judgeSkills(config, projectDir);\n return new Set(judged.filter((entry) => !entry.owned).map((entry) => entry.skill.id));\n}\n\n/** The entry travels and no directory is read for it: a row naming an id is the whole of it. */\nfunction travelsAsAnId(skill: SkillConfig): SkillJudgement {\n return { skill, owned: true, carried: null };\n}\n\n/**\n * How one installed entry answers to the round trip — asked of the disk, offline, exactly as\n * `uninstall` asks it before removing anything.\n *\n * Only a directory that EXISTS and carries no provenance is somebody's own work, and that is the\n * one thing this excludes; each guard below says why the case above it never gets that far.\n */\nasync function judgeSkill(skill: SkillConfig, projectDir: string): Promise<SkillJudgement> {\n // A marketplace skill has no local directory to hold provenance and needs none: the marketplace\n // is what installs it again.\n if (skill.origin !== EJECT_SOURCE) return travelsAsAnId(skill);\n // A tombstone is a statement about something that is NOT installed here, so there are no bytes\n // of it to carry — and a refusal raised over them would refuse a share for a skill it is not\n // sharing.\n if (!isInstalled(skill)) return travelsAsAnId(skill);\n\n const skillsDir = resolveInstallPaths(projectDir, skill.scope).skillsDir;\n const skillDir = path.join(skillsDir, skill.id);\n // A configuration recording an install that is not there is evidence of nothing rather than\n // evidence of authorship, so it travels as the configuration records it.\n if (!(await directoryExists(skillDir))) return travelsAsAnId(skill);\n\n const provenance = await readForkedFromMetadata(skillDir);\n if (provenance === null) return { skill, owned: false, carried: null };\n\n return { skill, owned: true, carried: { id: skill.id, skillDir, provenance } };\n}\n\n/**\n * The mapping, with its refusals turned into this module's own currency.\n *\n * `configToSeedPayload` throws, and what it throws is a list: every line names something this\n * installation has that a shared configuration cannot say. That is a message for the user, not a\n * fault to propagate — the alternative is worse than a failed command, because a payload quietly\n * missing what it could not say still mints an id, and that id installs a configuration nobody\n * chose.\n */\nfunction mapOrRefuse({ config, content }: RoundTrip): MappedPayload {\n try {\n return { ok: true, payload: configToSeedPayload(config, content) };\n } catch (error) {\n return { ok: false, error: getErrorMessage(error) };\n }\n}\n","import { MATRIX_VERSION } from \"@workspace/matrix\";\nimport {\n SEED_VERSION,\n installableSeedPayloadSchema,\n seedModelSchema,\n} from \"@workspace/matrix/seed\";\n\nimport { DEFAULT_PUBLIC_SOURCE_NAME, EJECT_SOURCE } from \"../../consts.js\";\nimport { isScopePairCompatible } from \"../configuration/config-generator.js\";\nimport { typedEntries, typedValues } from \"../../utils/typed-object.js\";\n\nimport type { ContentReading } from \"./external-skills.js\";\nimport type {\n AgentScopeConfig,\n ProjectConfig,\n SkillConfig,\n SkillScope,\n} from \"../../types/config.js\";\nimport type { ModelName } from \"../../types/matrix.js\";\nimport type { SkillId } from \"../../types/skills.js\";\nimport type {\n SeedAgent,\n SeedLoadState,\n SeedModel,\n SeedPayload,\n SeedSkill,\n} from \"@workspace/matrix/seed\";\n\n/** Sub-agent name -> load state for one skill: the shape the wire keys by skill. */\ntype SeedAssignments = Record<string, SeedLoadState>;\n\n/** What one walk of `config.stack` yields: the wire's assignments, and the rows that cannot be one. */\ntype StackReading = {\n assignments: Map<SkillId, SeedAssignments>;\n /** Pairs the config model has nowhere to write, worded for the refusal. */\n unwritable: string[];\n};\n\n/**\n * An installed entry. An excluded one is a tombstone — a statement about something that is NOT\n * installed here — and presence is selection on the wire, so it has nothing to say. Nothing is\n * lost by leaving it home either: `init --from` installs into a clean setup, where there is no\n * global install for a tombstone to mask.\n *\n * Exported because the reader that gathers what an installation CARRIES has to agree with the\n * mapper about what it installs: content read for an entry this payload will not name is content\n * paid for by nobody, and a refusal raised over it would refuse a share for a skill it is not\n * sharing.\n */\nexport function isInstalled(entry: { excluded?: boolean }): boolean {\n return !entry.excluded;\n}\n\n/**\n * Whether a skill from this origin obliges the payload to name a marketplace.\n *\n * Two do not. An ejected copy travels with the project, and the default public catalogue is what\n * an absent ref already means — so neither puts a ref on the wire, and two identical selections\n * cannot mint two different ids over one.\n */\nfunction needsMarketplaceNamed(origin: string): boolean {\n return origin !== EJECT_SOURCE && origin !== DEFAULT_PUBLIC_SOURCE_NAME;\n}\n\n/**\n * Asked of the contract's own enum rather than spelled out here, so widening `MODEL_NAMES`\n * without widening the wire cannot slip past as a silently dropped pin.\n */\nfunction isSeedModel(model: ModelName): model is SeedModel {\n return seedModelSchema.safeParse(model).success;\n}\n\n/** The wire spells as an enum what a stack entry spells as a boolean, and an absent flag is lazy. */\nfunction seedLoadState(preloaded: boolean | undefined): SeedLoadState {\n return preloaded === true ? \"preloaded\" : \"lazy\";\n}\n\nfunction unnameableOriginMessage(skill: SkillConfig): string {\n return `${skill.id} comes from the marketplace '${skill.origin}', and this installation does not record where that marketplace is fetched from`;\n}\n\nfunction unnameableModelMessage(agent: AgentScopeConfig[\"name\"], model: ModelName): string {\n return `${agent} pins model '${model}', which this contract has no word for — leaving it out would say \"keep the sub-agent's own metadata\", which is a different instruction`;\n}\n\nfunction unwritablePairMessage(skillId: SkillId, agent: string): string {\n return `${skillId} -> ${agent}: a project-scoped skill never reaches a sub-agent that rests at global scope`;\n}\n\n/**\n * Names everything the contract cannot carry at once, not one thing at a time: a sharer who fixes\n * one only to be refused for the next learns nothing the first message could not have told them.\n *\n * The refusal exists because the alternative is worse than a failed command. A payload quietly\n * missing what it could not say still mints an id, and that id installs a configuration nobody\n * chose — with nothing on either side saying so.\n */\nfunction unshareableConfigError(unshareable: string[]): string {\n return [\n \"This installation cannot be shared as it stands — a shared configuration has no way to carry:\",\n ...unshareable.map((line) => ` ${line}`),\n \"Sharing it anyway would mint an id that installs something else.\",\n ].join(\"\\n\");\n}\n\n/** The ref a payload has to carry, and the skills no ref this config holds can account for. */\ntype MarketplaceReading = {\n /** Absent when nothing installed here came from a marketplace. */\n ref: string | undefined;\n unnameable: string[];\n};\n\n/**\n * Whether the marketplace this installation reads is the one `skill` came from.\n *\n * A skill's `origin` is a marketplace's NAME, `config.marketplace` is the ref it was fetched from,\n * and `marketplaceName` is what joins them — the name the install read out of that repository's\n * own manifest. Without both halves agreeing, the ref would send the receiver to a repository that\n * never served this skill, which is the same silent swap under a different spelling.\n */\nfunction isRecordedMarketplace(config: ProjectConfig, skill: SkillConfig): boolean {\n return config.marketplace !== undefined && skill.origin === config.marketplaceName;\n}\n\n/** Which marketplace the payload names, decided by the skills that oblige it to name one. */\nfunction readMarketplace(config: ProjectConfig, skills: SkillConfig[]): MarketplaceReading {\n const served = skills.filter((skill) => needsMarketplaceNamed(skill.origin));\n if (served.length === 0) return { ref: undefined, unnameable: [] };\n\n const unaccounted = served.filter((skill) => !isRecordedMarketplace(config, skill));\n if (unaccounted.length > 0) {\n return { ref: undefined, unnameable: unaccounted.map(unnameableOriginMessage) };\n }\n\n return { ref: config.marketplace, unnameable: [] };\n}\n\nfunction unnameableModels(agents: AgentScopeConfig[]): string[] {\n return agents.flatMap((agent) =>\n agent.model !== undefined && !isSeedModel(agent.model)\n ? [unnameableModelMessage(agent.name, agent.model)]\n : [],\n );\n}\n\n/**\n * Turns `config.stack` inside out: it is keyed by sub-agent and this contract is keyed by skill.\n *\n * Rows naming a sub-agent or a skill this configuration does not install are dropped rather than\n * refused, because they are already no part of what is installed — `compile` warns about exactly\n * those and leaves them out of the agents it writes, so carrying them would share more than this\n * project has.\n *\n * A row the config model cannot write is the opposite case and is collected for the refusal: the\n * decoder turns the same pair away on the way back in, so minting it would produce an id that\n * cannot be installed.\n */\nfunction readStack(\n stack: ProjectConfig[\"stack\"],\n skillScopes: Map<SkillId, SkillScope>,\n agentScopes: Map<string, SkillScope>,\n): StackReading {\n const assignments = new Map<SkillId, SeedAssignments>();\n const unwritable: string[] = [];\n\n for (const [agent, agentStack] of typedEntries(stack ?? {})) {\n const agentScope = agentScopes.get(agent);\n if (agentScope === undefined) continue;\n\n for (const categoryAssignments of typedValues(agentStack)) {\n for (const { id, preloaded } of categoryAssignments) {\n const skillScope = skillScopes.get(id);\n if (skillScope === undefined) continue;\n\n if (!isScopePairCompatible(skillScope, agentScope)) {\n unwritable.push(unwritablePairMessage(id, agent));\n continue;\n }\n\n const forSkill = assignments.get(id) ?? {};\n forSkill[agent] = seedLoadState(preloaded);\n assignments.set(id, forSkill);\n }\n }\n }\n\n return { assignments, unwritable };\n}\n\nfunction toSeedSkill(skill: SkillConfig, assignments: SeedAssignments | undefined): SeedSkill {\n return {\n // \"eject\" is the project's own copy; anything else is a plugin the marketplace serves, and\n // which marketplace that is has already had to be one the envelope's ref accounts for.\n install: skill.origin === EJECT_SOURCE ? \"eject\" : \"plugin\",\n scope: skill.scope,\n assignments: assignments ?? {},\n };\n}\n\n/**\n * A sub-agent's own row, and it always says `on`.\n *\n * The web app pins `on` only where a person did, because there an agent switched on by its rows is\n * already implied by them. An installed config is not an inference — every sub-agent it names was\n * chosen and has a compiled file on disk — so saying so outright is what carries the one that owns\n * no skill, which is the only thing the agents map can do that assignments cannot.\n */\nfunction toSeedAgent(agent: AgentScopeConfig): SeedAgent {\n return {\n on: true,\n scope: agent.scope,\n ...(agent.model !== undefined && isSeedModel(agent.model) && { model: agent.model }),\n ...(agent.effort !== undefined && { effort: agent.effort }),\n };\n}\n\n/**\n * Turns the installation this directory records into the payload the config store holds, so the\n * CLI can mint an id rather than only consume one.\n *\n * The inverse of `seedToWizardResult` in `seed-to-wizard.ts`, and held to it: a\n * payload minted here and decoded there has to describe the same install. That is why the scope\n * of every skill and sub-agent travels per entry rather than being implied, why the whole stack\n * is carried as per-`(skill, sub-agent)` assignments, and why nothing here leans on a wire default\n * the decoder would have to guess back.\n *\n * What it will not do is share a thinner configuration than the one installed. Anything the\n * contract cannot state is refused by name — see {@link unshareableConfigError} — because the\n * failure mode of the alternative is an id that silently installs something else.\n *\n * `stackId` is always null. A saved config records a stack's expansion and never the id it came\n * from, and the assignments above carry that expansion in full; naming an id this module invented\n * would make the receiver overlay a stack's own preload flags over the curation being shared.\n *\n * `description` is what a resolvable id would have supplied that the assignments do not, so it is\n * carried directly instead. That is the whole of the trade: the sentence travels, the roster the id\n * would have dragged behind it does not.\n *\n * `marketplace` is the one field carried for the payload rather than for an entry, because the\n * receiver loads one catalogue before it reads a single skill row — see {@link readMarketplace}.\n *\n * `carried` arrives as an argument because it is read off disk and this mapping touches none:\n * every id above is resolved by the receiver against a catalogue it already has, and the entries\n * in `carried` are the ones that answer to no catalogue in either direction. Stated rather than\n * defaulted, because a producer that forgot the content is exactly the defect this closed.\n */\nexport function configToSeedPayload(config: ProjectConfig, carried: ContentReading): SeedPayload {\n const skills = config.skills.filter(isInstalled);\n const agents = config.agents.filter(isInstalled);\n const skillScopes = new Map(skills.map((skill) => [skill.id, skill.scope]));\n const agentScopes = new Map<string, SkillScope>(agents.map((agent) => [agent.name, agent.scope]));\n\n const { assignments, unwritable } = readStack(config.stack, skillScopes, agentScopes);\n const marketplace = readMarketplace(config, skills);\n\n const unshareable = [\n ...marketplace.unnameable,\n ...unnameableModels(agents),\n ...unwritable,\n ...carried.uncarryable,\n ];\n if (unshareable.length > 0) throw new Error(unshareableConfigError(unshareable));\n\n // Parsed rather than merely assembled, exactly as the web app's encoder is: it makes \"the JSON\n // the store will hold\" literal, and it is the one gate that catches a field whose values have\n // drifted out of the wire's enums since this module last named them.\n //\n // The INSTALLABLE half of the contract, which is the schema the store's POST route declares —\n // the lenient one exists for READING links already out in the world, and this module only ever\n // mints. It refuses nothing the refusal above permits, and that is the point: it is the belt\n // over those braces, so the day this module's own rule and the wire's disagree, the mint fails\n // loudly here instead of minting an id that cannot be installed.\n return installableSeedPayloadSchema.parse({\n v: SEED_VERSION,\n matrixVersion: MATRIX_VERSION,\n stackId: null,\n // Absent rather than empty, for the reason the marketplace ref is: an id is the hash of its\n // body, so a key meaning what its absence already means would remint every ordinary payload.\n ...(config.description !== undefined && { description: config.description }),\n ...(marketplace.ref !== undefined && { marketplace: marketplace.ref }),\n skills: Object.fromEntries(\n skills.map((skill) => [skill.id, toSeedSkill(skill, assignments.get(skill.id))]),\n ),\n // Absent rather than empty, for the reason the marketplace ref is: an id is the hash of its\n // body, so a key meaning what its absence already means would remint every ordinary payload.\n ...(Object.keys(carried.external).length > 0 && { external: carried.external }),\n agents: Object.fromEntries(agents.map((agent) => [agent.name, toSeedAgent(agent)])),\n });\n}\n","import { z } from \"zod\";\n\nimport { SEED_API_URL, SEED_USER_AGENT } from \"./fetch-seed.js\";\n\nimport type { SeedPayload } from \"@workspace/matrix/seed\";\n\n/**\n * The store answers a stored configuration with its content-addressed id and nothing else.\n * Revalidated rather than read off the response type, because that type describes the worker this\n * CLI was built against and what answers is whatever is deployed.\n */\nconst mintedSchema = z.object({ id: z.string().min(1) });\n\nexport type PublishSeedResult = { ok: true; id: string } | { ok: false; error: string };\n\n/**\n * Stores a configuration and returns the id it was given.\n *\n * The outbound half of the boundary `fetchSeedConfig` in `fetch-seed.ts` owns the inbound half\n * of, and it keeps the same posture: every failure is a message rather than a throw.\n * Nothing local has been written by the time this runs, so there is nothing to roll back and the\n * caller's only job is to explain.\n *\n * The id is the payload's own hash, so re-sharing an unchanged configuration returns the id it\n * had — the store spends no write, and a caller can share as often as it likes.\n */\nexport async function publishSeedConfig(payload: SeedPayload): Promise<PublishSeedResult> {\n const url = `${SEED_API_URL}/configs`;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"POST\",\n headers: {\n accept: \"application/json\",\n \"content-type\": \"application/json\",\n // The same signal the fetch half sends: it is the only thing that tells the store a\n // configuration came from the CLI rather than from a browser.\n \"user-agent\": SEED_USER_AGENT,\n },\n body: JSON.stringify(payload),\n });\n } catch {\n return { ok: false, error: `Could not reach ${SEED_API_URL} — check your connection.` };\n }\n\n if (!response.ok) {\n return { ok: false, error: `Sharing this configuration failed (HTTP ${response.status}).` };\n }\n\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n return { ok: false, error: \"The configuration store returned something that is not JSON.\" };\n }\n\n const minted = mintedSchema.safeParse(body);\n if (!minted.success) {\n // Reporting success here would print an id nobody can install and tell the user to use it.\n return { ok: false, error: \"The configuration store did not return an id for this share.\" };\n }\n\n return { ok: true, id: minted.data.id };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/cli/lib/seed/installation-payload.ts","../src/cli/lib/seed/config-to-seed.ts","../src/cli/lib/seed/publish-seed.ts"],"sourcesContent":["import path from \"path\";\n\nimport { configToSeedPayload, isInstalled } from \"./config-to-seed.js\";\nimport { readCarriedSkills } from \"./external-skills.js\";\nimport { EJECT_SOURCE } from \"../../consts.js\";\nimport { loadProjectConfig } from \"../configuration/project-config.js\";\nimport { resolveInstallPaths } from \"../installation/install-base-dir.js\";\nimport { readForkedFromMetadata } from \"../skills/skill-metadata.js\";\nimport { getErrorMessage } from \"../../utils/errors.js\";\nimport { directoryExists } from \"../../utils/fs.js\";\nimport { ERROR_MESSAGES } from \"../../utils/messages.js\";\n\nimport type { ContentReading, OwnedSkillDir } from \"./external-skills.js\";\nimport type { ProjectConfig, SkillConfig, SkillId } from \"../../types/index.js\";\nimport type { SeedPayload } from \"@workspace/matrix/seed\";\n\n/**\n * A payload ready to post, and what it will install — counted the way the sharer's own screens\n * count it, off the payload rather than off the config, so what a caller announces and what it\n * posts cannot disagree.\n */\nexport type InstallationPayload =\n { ok: true; payload: SeedPayload; skills: number; agents: number } | { ok: false; error: string };\n\n/** The config to map, or the sentence explaining why there is none to map. */\ntype InstalledConfig = { ok: true; config: ProjectConfig } | { ok: false; error: string };\n\n/** The mapped payload, or every line naming something the contract cannot carry. */\ntype MappedPayload = { ok: true; payload: SeedPayload } | { ok: false; error: string };\n\n/** The installation as the round trip sees it: what it owns, and what it has to carry with it. */\ntype RoundTrip = { config: ProjectConfig; content: ContentReading };\n\n/**\n * What the round trip makes of one installed entry: whether it travels at all, and whether its\n * bytes travel with it.\n */\ntype SkillJudgement = { skill: SkillConfig; owned: boolean; carried: OwnedSkillDir | null };\n\n/**\n * Read, map, refuse — everything that can fail locally, failing before anybody spends a write.\n *\n * Shared by the two commands that mint an id for what is installed here: `share`, which reports\n * the id, and `edit --ui`, which opens it. They are one operation with two endings, and this is\n * the half that has to be identical — two spellings of \"the installation in this directory\"\n * would mint two different ids for one project, and only one of them would be true.\n *\n * Every failure is a message rather than a throw, because nothing has been written by the time\n * it runs: the caller's only job is to explain, and both callers explain the same way.\n */\nexport async function seedPayloadForInstallation(projectDir: string): Promise<InstallationPayload> {\n const installed = await readInstalledConfig(projectDir);\n if (!installed.ok) return installed;\n\n const mapped = mapOrRefuse(await readRoundTrip(installed.config, projectDir));\n if (!mapped.ok) return mapped;\n\n const { payload } = mapped;\n const skills = Object.keys(payload.skills).length;\n const agents = Object.keys(payload.agents).length;\n\n // The same guard `init --from` applies on arrival, applied here before the write instead of\n // there after it. A sub-agent is installable on its own — it has front-matter, a prompt and a\n // compiled file without owning a single skill — so only a configuration with neither skills\n // nor sub-agents is nothing to carry.\n if (skills === 0 && agents === 0) return { ok: false, error: ERROR_MESSAGES.NO_INSTALLATION };\n\n return { ok: true, payload, skills, agents };\n}\n\n/**\n * The installation this directory has: its own configuration, or the global one it inherits.\n *\n * That is the config every other command reads here, and it carries the entries of BOTH scopes\n * with each entry's own scope on it — which is exactly what the wire keys by. So a payload minted\n * from a project describes the whole of what is installed for it rather than half of it, and the\n * receiver puts each entry back where this one had it.\n *\n * A config file that exists but cannot be loaded is a fault, not an absence, so its own message\n * is reported rather than read as \"not installed\".\n */\nasync function readInstalledConfig(projectDir: string): Promise<InstalledConfig> {\n try {\n const loaded = await loadProjectConfig(projectDir);\n if (!loaded) return { ok: false, error: ERROR_MESSAGES.NO_INSTALLATION };\n return { ok: true, config: loaded.config };\n } catch (error) {\n return { ok: false, error: getErrorMessage(error) };\n }\n}\n\n/**\n * The installation minus what the round trip does not own, plus the content it has to take along.\n *\n * `forkedFrom` decides ownership, and the round trip leaves what it does not own alone. The CLI\n * stamps that key into every skill directory it writes — an ejected catalogue skill, and a skill\n * a payload carried inline — while a skill the user wrote by hand into `.claude/skills/` carries\n * none. So absence of the key is not the whole answer and provenance is: what the CLI put there\n * says so on disk, and what a person put there says nothing because nothing forked it.\n *\n * A user-authored skill is therefore neither carried nor refused — it is simply outside the\n * round trip, and nothing about leaving it home is lossy because it was never in scope. Dropping\n * it here rather than in a command is what keeps `share` and `edit --ui`, which mint an id from\n * the same directory, from disagreeing about a single project.\n *\n * The stack rows naming a dropped skill go with it: `configToSeedPayload` keys assignments by\n * the skills it carries, so a row whose skill is gone is gone too.\n *\n * One walk answers both questions, because they are asked of the same file: whether the CLI put\n * this directory here, and — for the one kind of skill no catalogue can resolve — where its bytes\n * came from, so they can travel a second time.\n */\nasync function readRoundTrip(config: ProjectConfig, projectDir: string): Promise<RoundTrip> {\n const owned = (await judgeSkills(config, projectDir)).filter((entry) => entry.owned);\n\n return {\n config: { ...config, skills: owned.map((entry) => entry.skill) },\n content: await readCarriedSkills(owned.flatMap((entry) => entry.carried ?? [])),\n };\n}\n\n/** Every installed entry, judged. One walk of the disk, whichever half of the trip is asking. */\nfunction judgeSkills(config: ProjectConfig, projectDir: string): Promise<SkillJudgement[]> {\n return Promise.all(config.skills.map((skill) => judgeSkill(skill, projectDir)));\n}\n\n/**\n * The installed skills the round trip does NOT own — the user's own work, sitting in\n * `.claude/skills/` with no `forkedFrom` to say the CLI put it there.\n *\n * The producer already drops these on the way out, so no payload minted here ever named one.\n * This is the same judgement read by the other half: `edit --from` applies a payload\n * destructively, and a payload that made no statement about a skill cannot be read as an\n * instruction to delete it. Both halves ask {@link judgeSkill}, so \"outside the round trip\" has\n * one definition and cannot come to mean two things on one machine.\n */\nexport async function skillsAuthoredHere(\n config: ProjectConfig,\n projectDir: string,\n): Promise<Set<SkillId>> {\n const judged = await judgeSkills(config, projectDir);\n return new Set(judged.filter((entry) => !entry.owned).map((entry) => entry.skill.id));\n}\n\n/** The entry travels and no directory is read for it: a row naming an id is the whole of it. */\nfunction travelsAsAnId(skill: SkillConfig): SkillJudgement {\n return { skill, owned: true, carried: null };\n}\n\n/**\n * How one installed entry answers to the round trip — asked of the disk, offline, exactly as\n * `uninstall` asks it before removing anything.\n *\n * Only a directory that EXISTS and carries no provenance is somebody's own work, and that is the\n * one thing this excludes; each guard below says why the case above it never gets that far.\n */\nasync function judgeSkill(skill: SkillConfig, projectDir: string): Promise<SkillJudgement> {\n // A marketplace skill has no local directory to hold provenance and needs none: the marketplace\n // is what installs it again.\n if (skill.origin !== EJECT_SOURCE) return travelsAsAnId(skill);\n // A tombstone is a statement about something that is NOT installed here, so there are no bytes\n // of it to carry — and a refusal raised over them would refuse a share for a skill it is not\n // sharing.\n if (!isInstalled(skill)) return travelsAsAnId(skill);\n\n const skillsDir = resolveInstallPaths(projectDir, skill.scope).skillsDir;\n const skillDir = path.join(skillsDir, skill.id);\n // A configuration recording an install that is not there is evidence of nothing rather than\n // evidence of authorship, so it travels as the configuration records it.\n if (!(await directoryExists(skillDir))) return travelsAsAnId(skill);\n\n const provenance = await readForkedFromMetadata(skillDir);\n if (provenance === null) return { skill, owned: false, carried: null };\n\n return { skill, owned: true, carried: { id: skill.id, skillDir, provenance } };\n}\n\n/**\n * The mapping, with its refusals turned into this module's own currency.\n *\n * `configToSeedPayload` throws, and what it throws is a list: every line names something this\n * installation has that a shared configuration cannot say. That is a message for the user, not a\n * fault to propagate — the alternative is worse than a failed command, because a payload quietly\n * missing what it could not say still mints an id, and that id installs a configuration nobody\n * chose.\n */\nfunction mapOrRefuse({ config, content }: RoundTrip): MappedPayload {\n try {\n return { ok: true, payload: configToSeedPayload(config, content) };\n } catch (error) {\n return { ok: false, error: getErrorMessage(error) };\n }\n}\n","import { MATRIX_VERSION } from \"@workspace/matrix\";\nimport {\n SEED_VERSION,\n installableSeedPayloadSchema,\n seedModelSchema,\n} from \"@workspace/matrix/seed\";\n\nimport { DEFAULT_PUBLIC_SOURCE_NAME, EJECT_SOURCE } from \"../../consts.js\";\nimport { isScopePairCompatible } from \"../configuration/config-generator.js\";\nimport { typedEntries, typedValues } from \"../../utils/typed-object.js\";\n\nimport type { ContentReading } from \"./external-skills.js\";\nimport type {\n AgentScopeConfig,\n ProjectConfig,\n SkillConfig,\n SkillScope,\n} from \"../../types/config.js\";\nimport type { ModelName } from \"../../types/matrix.js\";\nimport type { SkillId } from \"../../types/skills.js\";\nimport type {\n SeedAgent,\n SeedLoadState,\n SeedModel,\n SeedPayload,\n SeedSkill,\n} from \"@workspace/matrix/seed\";\n\n/** Sub-agent name -> load state for one skill: the shape the wire keys by skill. */\ntype SeedAssignments = Record<string, SeedLoadState>;\n\n/** What one walk of `config.stack` yields: the wire's assignments, and the rows that cannot be one. */\ntype StackReading = {\n assignments: Map<SkillId, SeedAssignments>;\n /** Pairs the config model has nowhere to write, worded for the refusal. */\n unwritable: string[];\n};\n\n/**\n * An installed entry. An excluded one is a tombstone — a statement about something that is NOT\n * installed here — and presence is selection on the wire, so it has nothing to say. Nothing is\n * lost by leaving it home either: `init --from` installs into a clean setup, where there is no\n * global install for a tombstone to mask.\n *\n * Exported because the reader that gathers what an installation CARRIES has to agree with the\n * mapper about what it installs: content read for an entry this payload will not name is content\n * paid for by nobody, and a refusal raised over it would refuse a share for a skill it is not\n * sharing.\n */\nexport function isInstalled(entry: { excluded?: boolean }): boolean {\n return !entry.excluded;\n}\n\n/**\n * Whether a skill from this origin obliges the payload to name a marketplace.\n *\n * Two do not. An ejected copy travels with the project, and the default public catalogue is what\n * an absent ref already means — so neither puts a ref on the wire, and two identical selections\n * cannot mint two different ids over one.\n */\nfunction needsMarketplaceNamed(origin: string): boolean {\n return origin !== EJECT_SOURCE && origin !== DEFAULT_PUBLIC_SOURCE_NAME;\n}\n\n/**\n * Asked of the contract's own enum rather than spelled out here, so widening `MODEL_NAMES`\n * without widening the wire cannot slip past as a silently dropped pin.\n */\nfunction isSeedModel(model: ModelName): model is SeedModel {\n return seedModelSchema.safeParse(model).success;\n}\n\n/** The wire spells as an enum what a stack entry spells as a boolean, and an absent flag is lazy. */\nfunction seedLoadState(preloaded: boolean | undefined): SeedLoadState {\n return preloaded === true ? \"preloaded\" : \"lazy\";\n}\n\nfunction unnameableOriginMessage(skill: SkillConfig): string {\n return `${skill.id} comes from the marketplace '${skill.origin}', and this installation does not record where that marketplace is fetched from`;\n}\n\nfunction unnameableModelMessage(agent: AgentScopeConfig[\"name\"], model: ModelName): string {\n return `${agent} pins model '${model}', which this contract has no word for — leaving it out would say \"keep the sub-agent's own metadata\", which is a different instruction`;\n}\n\nfunction unwritablePairMessage(skillId: SkillId, agent: string): string {\n return `${skillId} -> ${agent}: a project-scoped skill never reaches a sub-agent that rests at global scope`;\n}\n\n/**\n * Names everything the contract cannot carry at once, not one thing at a time: a sharer who fixes\n * one only to be refused for the next learns nothing the first message could not have told them.\n *\n * The refusal exists because the alternative is worse than a failed command. A payload quietly\n * missing what it could not say still mints an id, and that id installs a configuration nobody\n * chose — with nothing on either side saying so.\n */\nfunction unshareableConfigError(unshareable: string[]): string {\n return [\n \"This installation cannot be shared as it stands — a shared configuration has no way to carry:\",\n ...unshareable.map((line) => ` ${line}`),\n \"Sharing it anyway would mint an id that installs something else.\",\n ].join(\"\\n\");\n}\n\n/** The ref a payload has to carry, and the skills no ref this config holds can account for. */\ntype MarketplaceReading = {\n /** Absent when nothing installed here came from a marketplace. */\n ref: string | undefined;\n unnameable: string[];\n};\n\n/**\n * Whether the marketplace this installation reads is the one `skill` came from.\n *\n * A skill's `origin` is a marketplace's NAME, `config.marketplace` is the ref it was fetched from,\n * and `marketplaceName` is what joins them — the name the install read out of that repository's\n * own manifest. Without both halves agreeing, the ref would send the receiver to a repository that\n * never served this skill, which is the same silent swap under a different spelling.\n */\nfunction isRecordedMarketplace(config: ProjectConfig, skill: SkillConfig): boolean {\n return config.marketplace !== undefined && skill.origin === config.marketplaceName;\n}\n\n/** Which marketplace the payload names, decided by the skills that oblige it to name one. */\nfunction readMarketplace(config: ProjectConfig, skills: SkillConfig[]): MarketplaceReading {\n const served = skills.filter((skill) => needsMarketplaceNamed(skill.origin));\n if (served.length === 0) return { ref: undefined, unnameable: [] };\n\n const unaccounted = served.filter((skill) => !isRecordedMarketplace(config, skill));\n if (unaccounted.length > 0) {\n return { ref: undefined, unnameable: unaccounted.map(unnameableOriginMessage) };\n }\n\n return { ref: config.marketplace, unnameable: [] };\n}\n\nfunction unnameableModels(agents: AgentScopeConfig[]): string[] {\n return agents.flatMap((agent) =>\n agent.model !== undefined && !isSeedModel(agent.model)\n ? [unnameableModelMessage(agent.name, agent.model)]\n : [],\n );\n}\n\n/**\n * Turns `config.stack` inside out: it is keyed by sub-agent and this contract is keyed by skill.\n *\n * Rows naming a sub-agent or a skill this configuration does not install are dropped rather than\n * refused, because they are already no part of what is installed — `compile` warns about exactly\n * those and leaves them out of the agents it writes, so carrying them would share more than this\n * project has.\n *\n * A row the config model cannot write is the opposite case and is collected for the refusal: the\n * decoder turns the same pair away on the way back in, so minting it would produce an id that\n * cannot be installed.\n */\nfunction readStack(\n stack: ProjectConfig[\"stack\"],\n skillScopes: Map<SkillId, SkillScope>,\n agentScopes: Map<string, SkillScope>,\n): StackReading {\n const assignments = new Map<SkillId, SeedAssignments>();\n const unwritable: string[] = [];\n\n for (const [agent, agentStack] of typedEntries(stack ?? {})) {\n const agentScope = agentScopes.get(agent);\n if (agentScope === undefined) continue;\n\n for (const categoryAssignments of typedValues(agentStack)) {\n for (const { id, preloaded } of categoryAssignments) {\n const skillScope = skillScopes.get(id);\n if (skillScope === undefined) continue;\n\n if (!isScopePairCompatible(skillScope, agentScope)) {\n unwritable.push(unwritablePairMessage(id, agent));\n continue;\n }\n\n const forSkill = assignments.get(id) ?? {};\n forSkill[agent] = seedLoadState(preloaded);\n assignments.set(id, forSkill);\n }\n }\n }\n\n return { assignments, unwritable };\n}\n\nfunction toSeedSkill(skill: SkillConfig, assignments: SeedAssignments | undefined): SeedSkill {\n return {\n // \"eject\" is the project's own copy; anything else is a plugin the marketplace serves, and\n // which marketplace that is has already had to be one the envelope's ref accounts for.\n install: skill.origin === EJECT_SOURCE ? \"eject\" : \"plugin\",\n scope: skill.scope,\n assignments: assignments ?? {},\n };\n}\n\n/**\n * A sub-agent's own row, and it always says `on`.\n *\n * The web app pins `on` only where a person did, because there an agent switched on by its rows is\n * already implied by them. An installed config is not an inference — every sub-agent it names was\n * chosen and has a compiled file on disk — so saying so outright is what carries the one that owns\n * no skill, which is the only thing the agents map can do that assignments cannot.\n */\nfunction toSeedAgent(agent: AgentScopeConfig): SeedAgent {\n return {\n on: true,\n scope: agent.scope,\n ...(agent.model !== undefined && isSeedModel(agent.model) && { model: agent.model }),\n ...(agent.effort !== undefined && { effort: agent.effort }),\n };\n}\n\n/**\n * Turns the installation this directory records into the payload the config store holds, so the\n * CLI can mint an id rather than only consume one.\n *\n * The inverse of `seedToWizardResult` in `seed-to-wizard.ts`, and held to it: a\n * payload minted here and decoded there has to describe the same install. That is why the scope\n * of every skill and sub-agent travels per entry rather than being implied, why the whole stack\n * is carried as per-`(skill, sub-agent)` assignments, and why nothing here leans on a wire default\n * the decoder would have to guess back.\n *\n * What it will not do is share a thinner configuration than the one installed. Anything the\n * contract cannot state is refused by name — see {@link unshareableConfigError} — because the\n * failure mode of the alternative is an id that silently installs something else.\n *\n * `stackId` is always null. A saved config records a stack's expansion and never the id it came\n * from, and the assignments above carry that expansion in full; naming an id this module invented\n * would make the receiver overlay a stack's own preload flags over the curation being shared.\n *\n * `description` is what a resolvable id would have supplied that the assignments do not, so it is\n * carried directly instead. That is the whole of the trade: the sentence travels, the roster the id\n * would have dragged behind it does not.\n *\n * `marketplace` is the one field carried for the payload rather than for an entry, because the\n * receiver loads one catalogue before it reads a single skill row — see {@link readMarketplace}.\n *\n * `carried` arrives as an argument because it is read off disk and this mapping touches none:\n * every id above is resolved by the receiver against a catalogue it already has, and the entries\n * in `carried` are the ones that answer to no catalogue in either direction. Stated rather than\n * defaulted, because a producer that forgot the content is exactly the defect this closed.\n */\nexport function configToSeedPayload(config: ProjectConfig, carried: ContentReading): SeedPayload {\n const skills = config.skills.filter(isInstalled);\n const agents = config.agents.filter(isInstalled);\n const skillScopes = new Map(skills.map((skill) => [skill.id, skill.scope]));\n const agentScopes = new Map<string, SkillScope>(agents.map((agent) => [agent.name, agent.scope]));\n\n const { assignments, unwritable } = readStack(config.stack, skillScopes, agentScopes);\n const marketplace = readMarketplace(config, skills);\n\n const unshareable = [\n ...marketplace.unnameable,\n ...unnameableModels(agents),\n ...unwritable,\n ...carried.uncarryable,\n ];\n if (unshareable.length > 0) throw new Error(unshareableConfigError(unshareable));\n\n // Parsed rather than merely assembled, exactly as the web app's encoder is: it makes \"the JSON\n // the store will hold\" literal, and it is the one gate that catches a field whose values have\n // drifted out of the wire's enums since this module last named them.\n //\n // The INSTALLABLE half of the contract, which is the schema the store's POST route declares —\n // the lenient one exists for READING links already out in the world, and this module only ever\n // mints. It refuses nothing the refusal above permits, and that is the point: it is the belt\n // over those braces, so the day this module's own rule and the wire's disagree, the mint fails\n // loudly here instead of minting an id that cannot be installed.\n return installableSeedPayloadSchema.parse({\n v: SEED_VERSION,\n matrixVersion: MATRIX_VERSION,\n stackId: null,\n // Absent rather than empty, for the reason the marketplace ref is: an id is the hash of its\n // body, so a key meaning what its absence already means would remint every ordinary payload.\n ...(config.description !== undefined && { description: config.description }),\n ...(marketplace.ref !== undefined && { marketplace: marketplace.ref }),\n skills: Object.fromEntries(\n skills.map((skill) => [skill.id, toSeedSkill(skill, assignments.get(skill.id))]),\n ),\n // Absent rather than empty, for the reason the marketplace ref is: an id is the hash of its\n // body, so a key meaning what its absence already means would remint every ordinary payload.\n ...(Object.keys(carried.external).length > 0 && { external: carried.external }),\n agents: Object.fromEntries(agents.map((agent) => [agent.name, toSeedAgent(agent)])),\n });\n}\n","import { STATUS_CODES } from \"node:http\";\n\nimport { z } from \"zod\";\n\nimport { SEED_API_URL, SEED_USER_AGENT } from \"./fetch-seed.js\";\nimport { CLI_INVOKE_COMMAND } from \"../../consts.js\";\nimport { truncateText } from \"../../utils/string.js\";\n\nimport type { SeedPayload } from \"@workspace/matrix/seed\";\n\n/**\n * The store answers a stored configuration with its content-addressed id and nothing else.\n * Revalidated rather than read off the response type, because that type describes the worker this\n * CLI was built against and what answers is whatever is deployed.\n */\nconst mintedSchema = z.object({ id: z.string().min(1) });\n\n/**\n * The envelope a refused POST arrives in.\n *\n * `apps/server` registers no `defaultHook` and its own hook narrows only the seed-version case,\n * so every other refused body falls through to `@hono/zod-validator`, which answers\n * `c.json(result, 400)` — the whole `safeParse` result. A `ZodError` has no own enumerable fields\n * beyond `name` and `message`, so `{ success: false, error: { name, message } }` is what crosses\n * the wire. Only that string is read here; everything else is shape to match against.\n */\nconst refusalSchema = z.object({ error: z.object({ message: z.string() }) });\n\n/**\n * What that string really is, which is the part worth knowing: Zod renders its ISSUES into\n * `message` as a JSON document, so the field named `message` is not something to show a person.\n * The sentences the store's own schema wrote are one level further in, and reading them back out\n * is the whole difference between a bare `HTTP 400` and a refusal that names what is wrong.\n */\nconst refusedIssuesSchema = z\n .array(\n z.object({\n path: z.array(z.union([z.string(), z.number()])),\n message: z.string().min(1),\n }),\n )\n .min(1);\n\n/**\n * How much of the store's account of a refusal to quote back.\n *\n * The refusal it really writes is one sentence naming a skill and a sub-agent — around 150\n * characters — so this holds that whole, and a second beside it. Past that a body has stopped\n * being an explanation, and a store replaced by a proxy, a captive portal or something worse must\n * not get to paint the terminal. The same reasoning as `EXCERPT` in `read-piped-payload.ts`, at\n * the length this quote needs: that one bounds unreadable bytes shown so a user recognises them,\n * where this one bounds prose the user has to be able to finish reading.\n *\n * ONE budget for both shapes this route answers in, rather than one apiece, because a budget is a\n * measurement of a ROUTE and both are `POST /configs`. The plain-text refusals it writes are far\n * shorter than a list of schema issues — the longest is `Could not store this config` — so the\n * number sized on the longer shape holds the shorter one with room to spare. `fetch-seed.ts` sets\n * 120 for its own route and neither number travels between them; see the 2026-09-01 finding on\n * quoting a refusal's body.\n */\nconst EXPLANATION_BUDGET = 300;\n\n/** The content type the store's own sentences arrive as — the only one worth reading as prose. */\nconst QUOTABLE_TYPE = \"text/plain\";\n\n/** The status the store spends on a payload naming a version of the contract it does not serve. */\nconst CONTRACT_MISMATCH = 409;\n\n/**\n * What a 409 means from a terminal, said in the CLI's own words rather than the store's.\n *\n * This is the one refusal whose entire purpose is naming a remedy, and the store's body names one\n * a terminal cannot carry out: `refuseAnotherSeedVersion` in `apps/server/src/index.ts` answers\n * `Reload the page: ...`, written for the caller that refusal was designed around — a browser tab\n * minting from a bundle older than the last deploy, for which one reload really is the whole fix.\n * There is no page here. Quoting it would be worse than the bare status it replaced, because the\n * bare status at least does not send the reader somewhere that does not exist.\n *\n * The fact underneath is the same one, and from a terminal it is actionable: `SEED_VERSION` is a\n * `z.literal` imported from `@workspace/matrix/seed` and bundled into this binary, so the version\n * written here travels INSIDE the CLI. Nothing about the configuration, the directory it was read\n * from or the pipe it arrived on can change it, and a newer CLI is the only thing that can.\n *\n * It cannot be the payload's fault by either door: `read-piped-payload.ts` validates a piped\n * configuration against `installableSeedPayloadSchema` before this runs, and `config-to-seed.ts`\n * writes `SEED_VERSION` into one it builds — so a `v` this CLI does not itself name never reaches\n * the wire, and a 409 can only be the two ends disagreeing.\n *\n * It names no sub-command, which is deliberate twice over. `publishSeedConfig` is called by both\n * `share` and `edit --ui`, so there is no one command to re-run; and an invocation written after\n * `@latest` is invisible to `handed-out-invocations.ts`, whose reader matches\n * `${CLI_INVOKE_COMMAND}` followed by a SPACE — so naming one here would hand out a command the\n * gate that runs every handed-out command could not see.\n */\nconst OUT_OF_DATE_AGAINST_STORE =\n `This CLI is out of date against the configuration store: it writes a version of the sharing ` +\n `contract the store does not serve, and that version travels inside the CLI rather than with ` +\n `the configuration. Re-run this command through '${CLI_INVOKE_COMMAND}@latest'.`;\n\nexport type PublishSeedResult = { ok: true; id: string } | { ok: false; error: string };\n\n/**\n * Stores a configuration and returns the id it was given.\n *\n * The outbound half of the boundary `fetchSeedConfig` in `fetch-seed.ts` owns the inbound half\n * of, and it keeps the same posture: every failure is a message rather than a throw.\n * Nothing local has been written by the time this runs, so there is nothing to roll back and the\n * caller's only job is to explain.\n *\n * The id is the payload's own hash, so re-sharing an unchanged configuration returns the id it\n * had — the store spends no write, and a caller can share as often as it likes.\n */\nexport async function publishSeedConfig(payload: SeedPayload): Promise<PublishSeedResult> {\n const url = `${SEED_API_URL}/configs`;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"POST\",\n headers: {\n accept: \"application/json\",\n \"content-type\": \"application/json\",\n // The same signal the fetch half sends: it is the only thing that tells the store a\n // configuration came from the CLI rather than from a browser.\n \"user-agent\": SEED_USER_AGENT,\n },\n body: JSON.stringify(payload),\n });\n } catch {\n return { ok: false, error: `Could not reach ${SEED_API_URL} — check your connection.` };\n }\n\n if (!response.ok) return { ok: false, error: await refusalMessage(response) };\n\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n return { ok: false, error: \"The configuration store returned something that is not JSON.\" };\n }\n\n const minted = mintedSchema.safeParse(body);\n if (!minted.success) {\n // Reporting success here would print an id nobody can install and tell the user to use it.\n return { ok: false, error: \"The configuration store did not return an id for this share.\" };\n }\n\n return { ok: true, id: minted.data.id };\n}\n\n/**\n * A refusal, carrying the store's own account of it wherever there is one to have.\n *\n * The status is never given up, because it is the only thing that separates a bad payload (400)\n * from a stale contract (409), a body over the cap (413), a rate limit (429) and a store that\n * refused the write (503). What it cannot do is say WHY a payload was bad, and the store already\n * knows: a refused POST answers with the issues its own schema raised, in plain English, naming\n * the skill and the sub-agent. Discarding that cost a real user a debugging session for a fault\n * the store had already described.\n *\n * Read for every status rather than for 400 alone — except the one status whose body is answering\n * somebody else. Which statuses carry which shape is the deployed worker's business, so both\n * shapes are tried against every body, and one that is neither degrades to the status anyway.\n */\nasync function refusalMessage(response: Response): Promise<string> {\n const refused = `Sharing this configuration failed (HTTP ${response.status}).`;\n\n // Branched on the status rather than on the body, because the status is the whole of the fact:\n // what a 409 says is that the two ends name different contract versions, and no body the store\n // could send makes that any more actionable from a terminal than the sentence above does.\n if (response.status === CONTRACT_MISMATCH) return `${refused} ${OUT_OF_DATE_AGAINST_STORE}`;\n\n const explanation = explanationOf(response, await refusalBody(response));\n\n return explanation === undefined ? refused : `${refused} The store said: ${explanation}`;\n}\n\n/**\n * Whatever the store sent, as text and unjudged.\n *\n * Deliberately NOT gated on the content type the way the function of this name in `fetch-seed.ts`\n * is, and the difference is the routes rather than a disagreement: that one answers every refusal\n * with `c.text`, where this one answers in two shapes under two types — the validator's envelope\n * as `application/json`, the worker's own sentences as `text/plain`. A gate here would throw one\n * of them away. It belongs on the prose arm alone, which is where {@link arrivedAsText} is.\n *\n * Nothing below this line is worth failing over: the message being assembled is already a\n * failure, and a body that cannot be read is one more thing the status will have to cover on its\n * own. Draining the stream can throw in its own right — a connection dropped mid-body — which is\n * why this is a `try` around the read.\n */\nasync function refusalBody(response: Response): Promise<string | undefined> {\n try {\n return await response.text();\n } catch {\n return undefined;\n }\n}\n\n/** `JSON.parse` as a value rather than a throw, since a body that is not JSON is expected here. */\nfunction jsonOf(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\n\n/**\n * The store's account of a refusal, in whichever of the two shapes this route answers in.\n *\n * The envelope is read first because it is the more specific of the two, and the order costs\n * nothing either way: an envelope arrives as JSON and could never satisfy the prose arm's\n * content-type gate, and prose has no shape for `refusalSchema` to match.\n *\n * The budget is spent here rather than inside either arm, so that whatever leaves this module is\n * bounded once, by one number belonging to one route.\n *\n * The body travels beside the response it came from rather than being taken off it, because by\n * the time this runs the stream has been drained and a second read would answer nothing.\n */\nfunction explanationOf(response: Response, body: string | undefined): string | undefined {\n if (body === undefined) return undefined;\n\n const said = schemaIssuesIn(body) ?? quotableProseIn(response, body);\n\n return said === undefined ? undefined : truncateText(said, EXPLANATION_BUDGET);\n}\n\n/** The sentences the store's own schema wrote, read back out of the validator's envelope. */\nfunction schemaIssuesIn(body: string): string | undefined {\n const refusal = refusalSchema.safeParse(jsonOf(body));\n if (!refusal.success) return undefined;\n\n const issues = refusedIssuesSchema.safeParse(jsonOf(refusal.data.error.message));\n if (!issues.success) return undefined;\n\n return issues.data.map(sentenceOf).join(\"; \");\n}\n\n/**\n * The store's own words, where the wire says the store wrote them and they say something.\n *\n * The three refusals this route writes with `c.text` — 413, 429 and 503 — reach a terminal by no\n * other arm, and before this they reached it by none at all. Two of the three are then discarded\n * again by {@link restatesItsOwnStatus}, which is the whole shape of the rule: what earns a quote\n * is not a body, it is a body that adds something to the status printed beside it.\n */\nfunction quotableProseIn(response: Response, body: string): string | undefined {\n if (!arrivedAsText(response)) return undefined;\n\n const said = body.trim();\n if (said === \"\") return undefined;\n if (restatesItsOwnStatus(said, response.status)) return undefined;\n\n return said;\n}\n\n/**\n * Whether what arrived is the store speaking, as far as the wire says it is.\n *\n * `c.text(...)` is how this route writes every refusal that is not the validator's, so `text/plain`\n * is the shape the store's own words take. What arrives as anything else did not come from it: a\n * proxy, a WAF, a captive portal or a gateway answering in its place — and their answer is markup\n * rather than prose, which quoted into a terminal is a screenful of tags that explains nothing and\n * buries the status that does.\n *\n * A sentence has no shape to validate, so the wire's own statement of what it sent is the only\n * discriminator prose has — where the envelope beside it has `refusalSchema`, a shape a foreign\n * body fails to be. It is not proof, since a hostile answer may claim any type it likes, which is\n * what {@link EXPLANATION_BUDGET} is for and why what survives both is attributed to the store\n * rather than spoken in the CLI's own voice.\n */\nfunction arrivedAsText(response: Response): boolean {\n return (response.headers.get(\"content-type\") ?? \"\").startsWith(QUOTABLE_TYPE);\n}\n\n/**\n * Whether the body says only what the status line printed beside it has already said.\n *\n * `node:http`'s `STATUS_CODES` is the registry of reason phrases a status line carries, so holding\n * a body against it is a rule about the whole class rather than a list of the statuses it happens\n * to catch today. It catches two: `Too many requests` is 429's `Too Many Requests` re-cased and\n * `Payload too large` is 413's, so neither is named here and a fourth refusal written the same way\n * is suppressed the day it ships. `Could not store this config` is not `Service Unavailable`, which\n * is why the one refusal on this route that names a cause is the one that survives.\n *\n * Compared case-insensitively, and against the trimmed body, because the worker writes sentence\n * case where the registry writes title case and that is not a difference in meaning.\n */\nfunction restatesItsOwnStatus(said: string, status: number): boolean {\n const reason = STATUS_CODES[status];\n\n return reason !== undefined && said.toLowerCase() === reason.toLowerCase();\n}\n\n/** One issue as it arrives, read off the schema above so the two cannot drift apart. */\ntype RefusedIssue = z.infer<typeof refusedIssuesSchema>[number];\n\n/**\n * One issue, path first — the same rendering `formatZodIssue` in `lib/schema-validator.ts` gives\n * a local one, and deliberately the same sentence a user sees from `share --stdin`.\n *\n * It cannot call that function: this issue was read off a wire and is a plain object, where\n * `formatZodIssue` takes a `z.ZodIssue`, a discriminated union nothing arriving over HTTP can be\n * narrowed to without a cast. The path is what the sentence itself cannot carry — the store's\n * message names the sub-agent and the path names the skill.\n */\nfunction sentenceOf(issue: RefusedIssue): string {\n const path = issue.path.join(\".\");\n return path === \"\" ? issue.message : `${path}: ${issue.message}`;\n}\n"],"mappings":"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","names":["path"]}
|
|
@@ -33,12 +33,12 @@ import {
|
|
|
33
33
|
writeContentHash,
|
|
34
34
|
writeFile,
|
|
35
35
|
writePluginManifest
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-XPDVAJDH.js";
|
|
37
37
|
import {
|
|
38
38
|
typedEntries,
|
|
39
39
|
typedFromEntries,
|
|
40
40
|
typedKeys
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-AVK2HEKB.js";
|
|
42
42
|
import {
|
|
43
43
|
CLAUDE_DIR,
|
|
44
44
|
CLAUDE_SRC_DIR,
|
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
STANDARD_FILES,
|
|
51
51
|
diagnostics,
|
|
52
52
|
effectivelyExcludedSkillIds
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-UITEKY2R.js";
|
|
54
54
|
|
|
55
55
|
// src/cli/lib/agents/list-compiled-agents.ts
|
|
56
56
|
import path2 from "path";
|
|
@@ -74,6 +74,45 @@ function sanitizeLiquidSyntax(value, fieldName) {
|
|
|
74
74
|
function sanitizeStringArray(values, fieldName) {
|
|
75
75
|
return values.map((v) => sanitizeLiquidSyntax(v, fieldName));
|
|
76
76
|
}
|
|
77
|
+
function sanitizeHooks(hooks) {
|
|
78
|
+
return Object.fromEntries(
|
|
79
|
+
Object.entries(hooks).map(([event, definitions]) => [
|
|
80
|
+
sanitizeLiquidSyntax(event, "hook.event"),
|
|
81
|
+
definitions.map((definition) => ({
|
|
82
|
+
...definition,
|
|
83
|
+
...definition.matcher !== void 0 && {
|
|
84
|
+
matcher: sanitizeLiquidSyntax(definition.matcher, "hook.matcher")
|
|
85
|
+
},
|
|
86
|
+
...definition.hooks !== void 0 && {
|
|
87
|
+
hooks: definition.hooks.map((action) => ({
|
|
88
|
+
...action,
|
|
89
|
+
type: sanitizeLiquidSyntax(action.type, "hook.type"),
|
|
90
|
+
...action.command !== void 0 && {
|
|
91
|
+
command: sanitizeLiquidSyntax(action.command, "hook.command")
|
|
92
|
+
},
|
|
93
|
+
...action.script !== void 0 && {
|
|
94
|
+
script: sanitizeLiquidSyntax(action.script, "hook.script")
|
|
95
|
+
},
|
|
96
|
+
...action.prompt !== void 0 && {
|
|
97
|
+
prompt: sanitizeLiquidSyntax(action.prompt, "hook.prompt")
|
|
98
|
+
}
|
|
99
|
+
}))
|
|
100
|
+
}
|
|
101
|
+
}))
|
|
102
|
+
])
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
function sanitizeExperimental(experimental) {
|
|
106
|
+
return {
|
|
107
|
+
...experimental,
|
|
108
|
+
...experimental.cacheTtl !== void 0 && {
|
|
109
|
+
cacheTtl: sanitizeLiquidSyntax(
|
|
110
|
+
experimental.cacheTtl,
|
|
111
|
+
"agent.experimental.cacheTtl"
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
77
116
|
function sanitizeSkills(skills) {
|
|
78
117
|
return skills.map((s) => ({
|
|
79
118
|
...s,
|
|
@@ -112,6 +151,15 @@ function sanitizeCompiledAgentData(data) {
|
|
|
112
151
|
data.agent.permissionMode,
|
|
113
152
|
"agent.permissionMode"
|
|
114
153
|
)
|
|
154
|
+
},
|
|
155
|
+
...data.agent.isolation !== void 0 && {
|
|
156
|
+
isolation: sanitizeLiquidSyntax(data.agent.isolation, "agent.isolation")
|
|
157
|
+
},
|
|
158
|
+
...data.agent.experimental !== void 0 && {
|
|
159
|
+
experimental: sanitizeExperimental(data.agent.experimental)
|
|
160
|
+
},
|
|
161
|
+
...data.agent.hooks !== void 0 && {
|
|
162
|
+
hooks: sanitizeHooks(data.agent.hooks)
|
|
115
163
|
}
|
|
116
164
|
};
|
|
117
165
|
const sanitizedSkills = sanitizeSkills(data.skills);
|
|
@@ -133,6 +181,11 @@ function sanitizeCompiledAgentData(data) {
|
|
|
133
181
|
preloadedSkillIds: sanitizedPreloadedIds
|
|
134
182
|
};
|
|
135
183
|
}
|
|
184
|
+
var SKILL_TOOL = "Skill";
|
|
185
|
+
function withSkillTool(agent) {
|
|
186
|
+
if (agent.tools.includes(SKILL_TOOL)) return agent;
|
|
187
|
+
return { ...agent, tools: [...agent.tools, SKILL_TOOL] };
|
|
188
|
+
}
|
|
136
189
|
function buildAgentTemplateContext(name, agent, files, mapSkill = (skill) => skill) {
|
|
137
190
|
const skills = agent.skills.map(mapSkill);
|
|
138
191
|
const preloadedSkills = skills.filter((s) => s.preloaded);
|
|
@@ -142,7 +195,7 @@ function buildAgentTemplateContext(name, agent, files, mapSkill = (skill) => ski
|
|
|
142
195
|
`Skills for ${name}: ${preloadedSkills.length} preloaded, ${dynamicSkills.length} dynamic`
|
|
143
196
|
);
|
|
144
197
|
return {
|
|
145
|
-
agent,
|
|
198
|
+
agent: withSkillTool(agent),
|
|
146
199
|
...files,
|
|
147
200
|
skills,
|
|
148
201
|
preloadedSkills,
|
|
@@ -154,12 +207,12 @@ function pluginRefFor(skill) {
|
|
|
154
207
|
if (skill.source === void 0 || skill.source === EJECT_SOURCE) return {};
|
|
155
208
|
return { pluginRef: `${skill.id}:${skill.id}` };
|
|
156
209
|
}
|
|
157
|
-
var MARKER_OPEN = `<!-- Generated by ${DEFAULT_PLUGIN_NAME}
|
|
210
|
+
var MARKER_OPEN = `<!-- Generated by ${DEFAULT_PLUGIN_NAME}`;
|
|
158
211
|
var MARKER_NOTICE = " \u2014 do not edit; compile rewrites this file";
|
|
159
212
|
var MARKER_CLOSE = " -->";
|
|
160
213
|
var FRONTMATTER_FENCE = "---";
|
|
161
|
-
function provenanceMarker(
|
|
162
|
-
return `${MARKER_OPEN}${
|
|
214
|
+
function provenanceMarker() {
|
|
215
|
+
return `${MARKER_OPEN}${MARKER_NOTICE}${MARKER_CLOSE}`;
|
|
163
216
|
}
|
|
164
217
|
function isProvenanceMarker(line) {
|
|
165
218
|
return line.startsWith(MARKER_OPEN) && line.endsWith(MARKER_CLOSE);
|
|
@@ -175,23 +228,50 @@ function hasProvenanceMarker(content) {
|
|
|
175
228
|
const firstBodyLine = lines[bodyStartIndex(lines)];
|
|
176
229
|
return firstBodyLine !== void 0 && isProvenanceMarker(firstBodyLine);
|
|
177
230
|
}
|
|
178
|
-
function stampProvenanceMarker(content
|
|
231
|
+
function stampProvenanceMarker(content) {
|
|
179
232
|
const lines = content.split("\n");
|
|
180
233
|
const bodyStart = bodyStartIndex(lines);
|
|
181
234
|
const replacedLines = hasProvenanceMarker(content) ? 1 : 0;
|
|
182
235
|
return [
|
|
183
236
|
...lines.slice(0, bodyStart),
|
|
184
|
-
provenanceMarker(
|
|
237
|
+
provenanceMarker(),
|
|
185
238
|
...lines.slice(bodyStart + replacedLines)
|
|
186
239
|
].join("\n");
|
|
187
240
|
}
|
|
188
241
|
var AGENT_TEMPLATE = "agent";
|
|
242
|
+
var COMPLETION_GATE_COMMAND = `command -v npm >/dev/null 2>&1 && [ -f package.json ] || exit 0; out=$(npm run --if-present --silent typecheck 2>&1) || { printf '%s\\n' "$out" >&2; exit 2; }`;
|
|
243
|
+
var WRITING_TOOLS = ["Write", "Edit"];
|
|
244
|
+
var GATE_EVENT = "Stop";
|
|
245
|
+
var CONVERTED_GATE_EVENT = "SubagentStop";
|
|
246
|
+
function completionGateHooks() {
|
|
247
|
+
return {
|
|
248
|
+
[GATE_EVENT]: [
|
|
249
|
+
{ hooks: [{ type: "command", command: COMPLETION_GATE_COMMAND }] }
|
|
250
|
+
]
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function declaresOwnGate(hooks) {
|
|
254
|
+
if (hooks === void 0) return false;
|
|
255
|
+
const stated = [GATE_EVENT, CONVERTED_GATE_EVENT];
|
|
256
|
+
return stated.some((event) => (hooks[event]?.length ?? 0) > 0);
|
|
257
|
+
}
|
|
258
|
+
function withCompletionGate(agent) {
|
|
259
|
+
const writes = WRITING_TOOLS.some((tool) => agent.tools.includes(tool));
|
|
260
|
+
if (!writes || declaresOwnGate(agent.hooks)) return agent;
|
|
261
|
+
return { ...agent, hooks: { ...agent.hooks, ...completionGateHooks() } };
|
|
262
|
+
}
|
|
263
|
+
function prepareForRender(data) {
|
|
264
|
+
return sanitizeCompiledAgentData({
|
|
265
|
+
...data,
|
|
266
|
+
agent: withCompletionGate(data.agent)
|
|
267
|
+
});
|
|
268
|
+
}
|
|
189
269
|
async function renderAgent(engine, data, version) {
|
|
190
|
-
const rendered = await engine.renderFile(
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
);
|
|
194
|
-
return stampProvenanceMarker(rendered
|
|
270
|
+
const rendered = await engine.renderFile(AGENT_TEMPLATE, {
|
|
271
|
+
...prepareForRender(data),
|
|
272
|
+
generatorVersion: sanitizeLiquidSyntax(version, "generatorVersion")
|
|
273
|
+
});
|
|
274
|
+
return stampProvenanceMarker(rendered);
|
|
195
275
|
}
|
|
196
276
|
|
|
197
277
|
// src/cli/lib/agents/agent-provenance.ts
|
|
@@ -497,29 +577,32 @@ async function recompileAgents(options) {
|
|
|
497
577
|
|
|
498
578
|
// src/cli/lib/agents/agent-plugin-compiler.ts
|
|
499
579
|
import path7 from "path";
|
|
500
|
-
|
|
580
|
+
var NO_FRONTMATTER_REASON = "no YAML frontmatter block";
|
|
581
|
+
function parseAgentFrontmatter(content) {
|
|
501
582
|
const raw = extractFrontmatter(content);
|
|
502
583
|
if (!raw) {
|
|
503
|
-
return
|
|
584
|
+
return { ok: false, reason: NO_FRONTMATTER_REASON };
|
|
504
585
|
}
|
|
505
586
|
const result = agentFrontmatterValidationSchema.safeParse(raw);
|
|
506
587
|
if (!result.success) {
|
|
507
|
-
|
|
508
|
-
return null;
|
|
588
|
+
return { ok: false, reason: formatZodIssues(result.error.issues) };
|
|
509
589
|
}
|
|
510
|
-
return {
|
|
590
|
+
return {
|
|
591
|
+
ok: true,
|
|
592
|
+
frontmatter: { name: result.data.name, description: result.data.description }
|
|
593
|
+
};
|
|
511
594
|
}
|
|
512
595
|
async function compileAgentPlugin(options) {
|
|
513
596
|
const { agentPath, outputDir } = options;
|
|
514
597
|
const fileName = path7.basename(agentPath);
|
|
515
598
|
const content = await readFile(agentPath);
|
|
516
|
-
const
|
|
517
|
-
if (!
|
|
599
|
+
const parsed = parseAgentFrontmatter(content);
|
|
600
|
+
if (!parsed.ok) {
|
|
518
601
|
throw new Error(
|
|
519
|
-
`Agent '${fileName}' has invalid or missing YAML frontmatter
|
|
602
|
+
`Agent '${fileName}' has invalid or missing YAML frontmatter: ${parsed.reason}. File: ${agentPath}`
|
|
520
603
|
);
|
|
521
604
|
}
|
|
522
|
-
const agentName2 = frontmatter.name;
|
|
605
|
+
const agentName2 = parsed.frontmatter.name;
|
|
523
606
|
verbose(`Compiling agent plugin: ${agentName2} from ${agentPath}`);
|
|
524
607
|
const pluginDir = path7.join(outputDir, `agent-${agentName2}`);
|
|
525
608
|
const agentsDir = path7.join(pluginDir, "agents");
|
|
@@ -533,7 +616,7 @@ async function compileAgentPlugin(options) {
|
|
|
533
616
|
);
|
|
534
617
|
const manifest = generateAgentPluginManifest({
|
|
535
618
|
agentName: agentName2,
|
|
536
|
-
description: frontmatter.description,
|
|
619
|
+
description: parsed.frontmatter.description,
|
|
537
620
|
version
|
|
538
621
|
});
|
|
539
622
|
await writePluginManifest(pluginDir, manifest);
|
|
@@ -584,4 +667,4 @@ export {
|
|
|
584
667
|
compileAllAgentPlugins,
|
|
585
668
|
printAgentCompilationSummary
|
|
586
669
|
};
|
|
587
|
-
//# sourceMappingURL=chunk-
|
|
670
|
+
//# sourceMappingURL=chunk-O664ITBD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/lib/agents/list-compiled-agents.ts","../src/cli/lib/agents/agent-provenance.ts","../../compile/src/agent-source.ts","../src/cli/lib/agents/agent-fetcher.ts","../src/cli/lib/agents/agent-recompiler.ts","../src/cli/lib/agents/write-compiled-agents.ts","../src/cli/lib/compiler.ts","../src/cli/lib/agents/agent-plugin-compiler.ts"],"sourcesContent":["import path from \"path\";\nimport { partition } from \"remeda\";\nimport { glob, readFileOptional, remove } from \"../../utils/fs\";\nimport { isAgentName } from \"../../utils/type-guards\";\nimport { hasProvenanceMarker } from \"./agent-provenance\";\nimport type { AgentName } from \"../../types\";\n\n/** Compiled-agent basenames in a directory, split by whether this CLI compiled them. */\nexport type AgentProvenanceSplit = {\n /** Files carrying the provenance marker — provably written by this CLI. */\n marked: string[];\n /** Everything else in the directory, the user's own agents among them. */\n unmarked: string[];\n};\n\n/** Lists compiled-agent markdown filenames (e.g. \"web-developer.md\") in a directory. */\nexport async function listAgentMdFiles(agentsDir: string): Promise<string[]> {\n return glob(\"*.md\", agentsDir);\n}\n\n/**\n * Splits the agent files in a directory by the provenance marker each compiled agent carries.\n *\n * This is the only thing that identifies this CLI's own output once the configuration naming\n * it is gone, so the split errs one way by construction: a file that cannot be read yields no\n * marker and lands in `unmarked`, because \"cannot prove it is ours\" and \"is not ours\" call for\n * the same answer — leave it alone.\n */\nexport async function splitAgentsByProvenance(agentsDir: string): Promise<AgentProvenanceSplit> {\n const files = await listAgentMdFiles(agentsDir);\n const classified = await Promise.all(files.map((file) => readAgentProvenance(agentsDir, file)));\n const [marked, unmarked] = partition(classified, (agent) => agent.compiledHere);\n\n return { marked: marked.map(agentName), unmarked: unmarked.map(agentName) };\n}\n\ntype ClassifiedAgent = { name: string; compiledHere: boolean };\n\nasync function readAgentProvenance(agentsDir: string, file: string): Promise<ClassifiedAgent> {\n const content = await readFileOptional(path.join(agentsDir, file));\n return { name: path.basename(file, \".md\"), compiledHere: hasProvenanceMarker(content) };\n}\n\nfunction agentName(agent: ClassifiedAgent): string {\n return agent.name;\n}\n\n/** Lists compiled-agent names (filenames without the `.md` extension) in a directory. */\nexport async function listCompiledAgentNames(agentsDir: string): Promise<AgentName[]> {\n const files = await listAgentMdFiles(agentsDir);\n // Boundary cast: compiled .md filenames are agent names by convention; custom\n // agents from marketplace stacks may not be members of the AgentName union.\n return files.map((f) => path.basename(f, \".md\") as AgentName);\n}\n\n/**\n * Removes stale CLI-compiled agent files from `agentsDir`: deletes any `.md`\n * whose basename is a built-in CLI agent name (`isAgentName`) that is NOT in\n * `keep`. The built-in-name check protects hand-authored agents (whose basename\n * is not a built-in name) — it is never the removal criterion. Only call this\n * when `keep` is the COMPLETE set of agents that should live in `agentsDir`.\n */\nexport async function pruneStaleCompiledAgents(\n agentsDir: string,\n keep: ReadonlySet<AgentName>,\n): Promise<void> {\n // A non-built-in basename is a hand-authored agent — always preserved.\n const isStaleCompiledAgent = (file: string): boolean => {\n const name = path.basename(file, \".md\");\n return isAgentName(name) && !keep.has(name);\n };\n\n const files = await listAgentMdFiles(agentsDir);\n await Promise.all(\n files.filter(isStaleCompiledAgent).map((file) => remove(path.join(agentsDir, file))),\n );\n}\n","import path from \"path\";\nimport { z } from \"zod\";\n\nimport { PROJECT_ROOT, STANDARD_FILES } from \"../../consts\";\nimport { readFile } from \"../../utils/fs\";\n\n/** The one field the marker needs from this CLI's own manifest. */\nconst ownPackageJsonSchema = z.object({ version: z.string().min(1) });\n\n/**\n * The provenance marker every compiled agent carries lives in `@workspace/compile/agent-source`,\n * beside the renderer that stamps it — the editor's output preview draws the same first body line\n * and must not compute it a second way. What stays here is the half that reads this CLI's own\n * manifest, which a browser has no equivalent of.\n */\nexport {\n hasProvenanceMarker,\n provenanceMarker,\n stampProvenanceMarker,\n} from \"@workspace/compile/agent-source\";\n\nlet ownVersion: Promise<string> | undefined;\n\n/**\n * This CLI's own published version, read once per process from the package manifest beside\n * the code — the same `PROJECT_ROOT` the bundled agent partials and templates resolve from.\n *\n * It reaches a compiled agent as the `version` argument of `renderAgent`, which hands it to the\n * template as `generatorVersion`; `agent.liquid` renders it in the trailing `<system-reminder>`\n * block. Deliberately not the provenance marker above it — that line's bytes are constant across\n * releases, so a version bump no longer rewrites the first cacheable byte of every compiled agent.\n */\nexport function cliVersion(): Promise<string> {\n ownVersion ??= readOwnVersion();\n return ownVersion;\n}\n\nasync function readOwnVersion(): Promise<string> {\n const manifestPath = path.join(PROJECT_ROOT, STANDARD_FILES.PACKAGE_JSON);\n const raw: unknown = JSON.parse(await readFile(manifestPath));\n\n const parsed = ownPackageJsonSchema.safeParse(raw);\n if (!parsed.success) {\n throw new Error(`Could not read this CLI's own version from ${manifestPath}`);\n }\n return parsed.data.version;\n}\n","import type { Liquid } from \"liquidjs\"\n\nimport { diagnostics } from \"./diagnostics.js\"\nimport { DEFAULT_PLUGIN_NAME, EJECT_SOURCE } from \"./paths.js\"\nimport type {\n AgentConfig,\n CompiledAgentData,\n PluginSkillRef,\n Skill,\n} from \"./types.js\"\n\n/**\n * Everything that turns a resolved sub-agent into the markdown an install writes,\n * with two things left behind in the CLI because they read the machine: the five\n * `readFile`s that fetch an agent's partials off disk, and `cliVersion()`, which\n * reads the CLI's own manifest. Both arrive here as data — {@link AgentFiles} and\n * the `version` argument of {@link renderAgent} — which is what lets a browser\n * render the same bytes from the vendored corpus.\n */\n\n/** Pattern matching Liquid template delimiters that could enable template injection */\nconst LIQUID_SYNTAX_PATTERN = /\\{\\{|\\}\\}|\\{%|%\\}/g\n\n/**\n * Strips Liquid template syntax (`{{`, `}}`, `{%`, `%}`) from a string value.\n * Prevents template injection when user-controlled data is passed to the Liquid engine.\n *\n * @param value - Input string that may contain Liquid syntax\n * @param fieldName - Name of the field (for warning messages)\n * @returns Sanitized string with Liquid delimiters removed\n */\nexport function sanitizeLiquidSyntax<T extends string>(\n value: T,\n fieldName: string\n): T {\n if (!LIQUID_SYNTAX_PATTERN.test(value)) return value\n LIQUID_SYNTAX_PATTERN.lastIndex = 0\n const sanitized = value.replace(LIQUID_SYNTAX_PATTERN, \"\")\n diagnostics().warn(\n `Stripped Liquid template syntax from '${fieldName}' — possible template injection attempt`\n )\n // Boundary cast: .replace() widens the branded string T; stripping characters keeps it in T's domain\n return sanitized as T\n}\n\nfunction sanitizeStringArray(values: string[], fieldName: string): string[] {\n return values.map((v) => sanitizeLiquidSyntax(v, fieldName))\n}\n\n/**\n * Hook definitions with every author-supplied string stripped of Liquid syntax.\n *\n * These are the only fields on an agent that render as an EXECUTABLE: a `SubagentStop` hook's\n * `command` is a shell line Claude Code runs when the sub-agent finishes. An agent definition\n * can arrive from a marketplace, so the strings here are as author-controlled as `agent.name`\n * beside them — and they were the one part of the definition the sanitiser did not cover,\n * because until this release nothing rendered them.\n *\n * Sanitising is not a substitute for trusting the source: a marketplace whose agents you compile\n * can name any command it likes, and that is a property of installing an agent rather than of\n * this function. What this closes is the narrower hole of a hook string carrying template syntax\n * into a render.\n */\nfunction sanitizeHooks(\n hooks: NonNullable<AgentConfig[\"hooks\"]>\n): NonNullable<AgentConfig[\"hooks\"]> {\n return Object.fromEntries(\n Object.entries(hooks).map(([event, definitions]) => [\n sanitizeLiquidSyntax(event, \"hook.event\"),\n definitions.map((definition) => ({\n ...definition,\n ...(definition.matcher !== undefined && {\n matcher: sanitizeLiquidSyntax(definition.matcher, \"hook.matcher\"),\n }),\n ...(definition.hooks !== undefined && {\n hooks: definition.hooks.map((action) => ({\n ...action,\n type: sanitizeLiquidSyntax(action.type, \"hook.type\"),\n ...(action.command !== undefined && {\n command: sanitizeLiquidSyntax(action.command, \"hook.command\"),\n }),\n ...(action.script !== undefined && {\n script: sanitizeLiquidSyntax(action.script, \"hook.script\"),\n }),\n ...(action.prompt !== undefined && {\n prompt: sanitizeLiquidSyntax(action.prompt, \"hook.prompt\"),\n }),\n })),\n }),\n })),\n ])\n )\n}\n\n/**\n * Experimental frontmatter options with their author-supplied value stripped of\n * Liquid syntax.\n *\n * Here for the same reason {@link sanitizeHooks} is: the template renders the\n * field, and being rendered is what puts a field in this enumeration. That\n * `cacheTtl` is a closed vocabulary does not exempt it — `model`, `effort`,\n * `permissionMode` and `isolation` are closed vocabularies too and are all\n * sanitised, because a type says nothing about what reached the renderer.\n * {@link renderAgent} is also the editor's preview path, which arrives from a\n * browser without the CLI's Zod loader having parsed anything.\n */\nfunction sanitizeExperimental(\n experimental: NonNullable<AgentConfig[\"experimental\"]>\n): NonNullable<AgentConfig[\"experimental\"]> {\n return {\n ...experimental,\n ...(experimental.cacheTtl !== undefined && {\n cacheTtl: sanitizeLiquidSyntax(\n experimental.cacheTtl,\n \"agent.experimental.cacheTtl\"\n ),\n }),\n }\n}\n\nfunction sanitizeSkills(skills: Skill[]): Skill[] {\n return skills.map((s) => ({\n ...s,\n id: sanitizeLiquidSyntax(s.id, \"skill.id\"),\n description: sanitizeLiquidSyntax(s.description, \"skill.description\"),\n usage: sanitizeLiquidSyntax(s.usage, \"skill.usage\"),\n ...(s.pluginRef !== undefined && {\n pluginRef: sanitizeLiquidSyntax(s.pluginRef, \"skill.pluginRef\"),\n }),\n }))\n}\n\n/**\n * Sanitizes user-controlled metadata fields in compiled agent data to prevent\n * Liquid template injection. Strips `{{`, `}}`, `{%`, `%}` from agent\n * metadata and skill metadata before template rendering.\n *\n * Content fields (identity, playbook, output, criticalRequirementsTop,\n * criticalReminders) are passed through unchanged — LiquidJS does not\n * re-evaluate template syntax inside variable values, so double-curlies\n * in content (e.g. GitHub Actions `${{ secrets.X }}`) are safe.\n */\nexport function sanitizeCompiledAgentData(\n data: CompiledAgentData\n): CompiledAgentData {\n const sanitizedAgent: AgentConfig = {\n ...data.agent,\n name: sanitizeLiquidSyntax(data.agent.name, \"agent.name\"),\n title: sanitizeLiquidSyntax(data.agent.title, \"agent.title\"),\n description: sanitizeLiquidSyntax(\n data.agent.description,\n \"agent.description\"\n ),\n tools: sanitizeStringArray(data.agent.tools, \"agent.tools\"),\n ...(data.agent.disallowedTools !== undefined && {\n disallowedTools: sanitizeStringArray(\n data.agent.disallowedTools,\n \"agent.disallowedTools\"\n ),\n }),\n ...(data.agent.model !== undefined && {\n model: sanitizeLiquidSyntax(data.agent.model, \"agent.model\"),\n }),\n ...(data.agent.effort !== undefined && {\n effort: sanitizeLiquidSyntax(data.agent.effort, \"agent.effort\"),\n }),\n ...(data.agent.permissionMode !== undefined && {\n permissionMode: sanitizeLiquidSyntax(\n data.agent.permissionMode,\n \"agent.permissionMode\"\n ),\n }),\n ...(data.agent.isolation !== undefined && {\n isolation: sanitizeLiquidSyntax(data.agent.isolation, \"agent.isolation\"),\n }),\n ...(data.agent.experimental !== undefined && {\n experimental: sanitizeExperimental(data.agent.experimental),\n }),\n ...(data.agent.hooks !== undefined && {\n hooks: sanitizeHooks(data.agent.hooks),\n }),\n }\n\n const sanitizedSkills = sanitizeSkills(data.skills)\n const sanitizedPreloaded = sanitizeSkills(data.preloadedSkills)\n const sanitizedDynamic = sanitizeSkills(data.dynamicSkills)\n const sanitizedPreloadedIds = data.preloadedSkillIds.map((id) =>\n sanitizeLiquidSyntax(id, \"preloadedSkillId\")\n )\n\n return {\n agent: sanitizedAgent,\n identity: data.identity,\n playbook: data.playbook,\n output: data.output,\n criticalRequirementsTop: data.criticalRequirementsTop,\n criticalReminders: data.criticalReminders,\n skills: sanitizedSkills,\n preloadedSkills: sanitizedPreloaded,\n dynamicSkills: sanitizedDynamic,\n preloadedSkillIds: sanitizedPreloadedIds,\n }\n}\n\n/**\n * The tool that loads a skill.\n *\n * A sub-agent's `tools:` frontmatter is an ALLOWLIST: an agent that declares one\n * gets exactly what it names, where an agent that omits the key inherits every\n * tool the session has. Every agent compiled here declares one, and no\n * `metadata.yaml` names this — so every agent this product had ever written was\n * unable to invoke a skill, while being instructed in the strongest terms the\n * template can manage to do exactly that.\n *\n * The `skills:` key does not close that gap, which is the non-obvious half and\n * the reason the defect survived: it preloads skill content into the agent's\n * startup context and grants no tool, so a compiled agent can list skills, carry\n * the activation protocol, and still have no way to load one.\n *\n * Granted to every agent rather than only to those with dynamic skills. Skills\n * are this product's atom: an agent has to be able to reach one a user adds\n * after it was compiled, and one its own playbook names in prose. It is a\n * read-only capability — it loads instructions and grants no write access — so\n * the deliberately read-only researchers take it on the same terms.\n */\nconst SKILL_TOOL = \"Skill\"\n\n/**\n * The same definition with {@link SKILL_TOOL} among its tools exactly once.\n *\n * Idempotent and order-stable: a definition already naming it is returned\n * unchanged, by identity, and everything else keeps its declared order with the\n * grant appended. Both halves are about the next compile — a second entry, or a\n * reordered list, would diff the frontmatter of every agent on disk.\n */\nfunction withSkillTool(agent: AgentConfig): AgentConfig {\n if (agent.tools.includes(SKILL_TOOL)) return agent\n return { ...agent, tools: [...agent.tools, SKILL_TOOL] }\n}\n\n/** The five markdown partials a sub-agent is assembled from, however they were fetched. */\nexport type AgentFiles = Pick<\n CompiledAgentData,\n | \"identity\"\n | \"playbook\"\n | \"output\"\n | \"criticalRequirementsTop\"\n | \"criticalReminders\"\n>\n\n/**\n * The template context for one sub-agent.\n *\n * The single assembly point for both front doors — the CLI's write path and the\n * editor's output preview — which is why {@link withSkillTool} is applied here\n * rather than in the eighteen `metadata.yaml` files: a user-authored agent gets\n * the grant on the same terms as a shipped one.\n *\n * The preloaded/dynamic split PRESERVES the order `agent.skills` arrives in, and\n * that order is `config.ts`'s stack key order — so the emitted rows of the\n * sub-agent's skill-activation table are decided by the config writer's\n * canonicalisation rather than by anything here.\n */\nexport function buildAgentTemplateContext(\n name: string,\n agent: AgentConfig,\n files: AgentFiles,\n mapSkill: (skill: Skill) => Skill = (skill) => skill\n): CompiledAgentData {\n const skills = agent.skills.map(mapSkill)\n const preloadedSkills = skills.filter((s) => s.preloaded)\n const dynamicSkills = skills.filter((s) => !s.preloaded)\n const preloadedSkillIds = preloadedSkills.map((s) => s.pluginRef ?? s.id)\n\n diagnostics().verbose(\n `Skills for ${name}: ${preloadedSkills.length} preloaded, ${dynamicSkills.length} dynamic`\n )\n\n return {\n agent: withSkillTool(agent),\n ...files,\n skills,\n preloadedSkills,\n dynamicSkills,\n preloadedSkillIds,\n }\n}\n\n/**\n * The per-skill pluginRef decision. A skill renders as `${id}:${id}` only\n * when it has an explicit non-eject source on its SkillReference — i.e. it was\n * installed from a marketplace. `undefined` source (user-authored local skills\n * with no SkillConfig entry) and `\"eject\"` both fall through to bare id.\n */\nexport function pluginRefFor(skill: Skill): { pluginRef?: PluginSkillRef } {\n if (skill.source === undefined || skill.source === EJECT_SOURCE) return {}\n return { pluginRef: `${skill.id}:${skill.id}` as const }\n}\n\n/**\n * The provenance marker every compiled agent carries: an HTML comment on the first line\n * after the frontmatter, naming the generator and the fact that the file is rewritten\n * rather than edited.\n *\n * **A body comment, deliberately not a frontmatter field.** Claude Code documents its\n * supported frontmatter keys and says nothing about how it treats an unknown one, so a\n * stricter release could reject every agent this CLI has ever written. The body is free-form\n * by contract, which makes a marker there safe, greppable, and the do-not-edit notice at the\n * same time.\n *\n * **Its bytes are constant across releases, and that is the point.** A compiled agent IS a\n * sub-agent's system prompt, so this line is the first cacheable byte of every invocation of\n * it — and while it carried the CLI's version it moved on every release, invalidating the\n * whole prompt prefix of all eighteen agents for a string nothing reads back. The version\n * still travels, in the trailing volatile block where a change to it costs nothing.\n *\n * {@link hasProvenanceMarker} matched on SHAPE while the text varied and still does, so an\n * agent compiled by any release — before this change or after it — is recognised by any other.\n */\nconst MARKER_OPEN = `<!-- Generated by ${DEFAULT_PLUGIN_NAME}`\nconst MARKER_NOTICE = \" — do not edit; compile rewrites this file\"\nconst MARKER_CLOSE = \" -->\"\n\nconst FRONTMATTER_FENCE = \"---\"\n\nexport function provenanceMarker(): string {\n return `${MARKER_OPEN}${MARKER_NOTICE}${MARKER_CLOSE}`\n}\n\n/** Whether a line is a marker this CLI wrote, at any version and under any wording. */\nfunction isProvenanceMarker(line: string): boolean {\n return line.startsWith(MARKER_OPEN) && line.endsWith(MARKER_CLOSE)\n}\n\n/**\n * The index of the first body line: past the closing frontmatter fence when there is one,\n * and the top of the file when there is not — a template override may render no frontmatter,\n * and the marker still needs a defined home.\n */\nfunction bodyStartIndex(lines: readonly string[]): number {\n if (lines[0] !== FRONTMATTER_FENCE) return 0\n const closingFence = lines.indexOf(FRONTMATTER_FENCE, 1)\n if (closingFence === -1) return 0\n return closingFence + 1\n}\n\n/**\n * Whether this CLI compiled the agent file this content came from.\n *\n * The marker's POSITION is part of the claim: an agent that merely quotes the line further\n * down (a prompt about this very feature, say) is the user's, and a sweep reading that as\n * provenance would delete a file nothing here wrote.\n */\nexport function hasProvenanceMarker(content: string): boolean {\n const lines = content.split(\"\\n\")\n const firstBodyLine = lines[bodyStartIndex(lines)]\n return firstBodyLine !== undefined && isProvenanceMarker(firstBodyLine)\n}\n\n/**\n * The same content carrying exactly one provenance marker, on the first line after the\n * frontmatter.\n *\n * Idempotent by replacement rather than by insertion: content that already carries a marker\n * has that line rewritten rather than a second one stacked beside it. Since the marker's text\n * became constant that replacement is a no-op on anything this release wrote — but it is what\n * upgrades an agent stamped by a release that still spelled the version into the line.\n */\nexport function stampProvenanceMarker(content: string): string {\n const lines = content.split(\"\\n\")\n const bodyStart = bodyStartIndex(lines)\n const replacedLines = hasProvenanceMarker(content) ? 1 : 0\n\n return [\n ...lines.slice(0, bodyStart),\n provenanceMarker(),\n ...lines.slice(bodyStart + replacedLines),\n ].join(\"\\n\")\n}\n\n/** The template every compiled sub-agent is rendered from, by name rather than by path. */\nconst AGENT_TEMPLATE = \"agent\"\n\n/**\n * The deterministic completion gate every writing sub-agent stops against.\n *\n * A `SubagentStop` hook rather than a sentence in the prompt, because the two are different\n * kinds of claim: \"check your work before stopping\" is advice a model may decline to take, and\n * this is a process that runs whether it does or not. Exit 2 is the documented way to BLOCK the\n * stop, and the command's captured output goes to stderr, which is what Claude Code returns to\n * the sub-agent — so a failing typecheck comes back as the compiler's own output and the\n * agent iterates rather than reporting done.\n *\n * **Inert where it cannot be right.** A compiled agent is installed into someone else's\n * repository, and a gate that hard-blocks in a project with no npm — or no `typecheck` script —\n * would make every sub-agent unstoppable. So the first clause exits 0 unless there is both an\n * npm and a `package.json`, and `--if-present` exits 0 for a script the project does not\n * define. What is left is exactly the case the gate is for: a project that declares these\n * checks, failing one of them.\n *\n * **Typecheck only.** The gate runs the project's typecheck script; lint and test are\n * deliberately not in it. A type error means the work does not compile, which is the one\n * failure a stopping agent must not report as done. A lint finding or a failing test is the\n * project's own judgement to gate on, and a project that wants either declares its own `Stop`\n * hook — see {@link declaresOwnGate} — which replaces this one entirely rather than running\n * beside it.\n *\n * Composed for agents holding `Write` or `Edit` by {@link withCompletionGate}, which merges it\n * with whatever the agent declared rather than losing to it.\n */\nconst COMPLETION_GATE_COMMAND =\n \"command -v npm >/dev/null 2>&1 && [ -f package.json ] || exit 0; \" +\n \"out=$(npm run --if-present --silent typecheck 2>&1) \" +\n \"|| { printf '%s\\\\n' \\\"$out\\\" >&2; exit 2; }\"\n\n/** The tools whose presence makes an agent one the gate is for. */\nconst WRITING_TOOLS = [\"Write\", \"Edit\"]\n\n/**\n * The frontmatter spelling of the completion event, which is not the spelling that fires.\n *\n * Claude Code registers a sub-agent's frontmatter hooks through a function that walks its\n * event vocabulary and rewrites exactly one key — `Stop` becomes `SubagentStop`, logged as\n * \"Converting Stop hook to SubagentStop for agent X (subagents trigger SubagentStop)\". The\n * vocabulary contains `SubagentStop` verbatim, so EITHER spelling works when the agent is\n * invoked as a sub-agent.\n *\n * They diverge on the other path. An agent run as the main session through `--agent` has its\n * frontmatter hooks stored raw, with no such rewrite, and every dispatch looks the record up\n * by the event's own name — so a `SubagentStop` key is consulted only for an event a main\n * session never fires, while `Stop` fires natively. `Stop` is therefore correct in both modes\n * and `SubagentStop` in one, which is why this emits `Stop`.\n *\n * Read from the shipped binary at version 2.1.259 on 2026-09-03 rather than from published\n * documentation. Compiled agents written before that release carry `SubagentStop`; both are\n * live, and a reader seeing `Stop:` in frontmatter and `SubagentStop` in a log is seeing the\n * conversion rather than a mismatch.\n */\nconst GATE_EVENT = \"Stop\"\n\n/** The runtime spelling of {@link GATE_EVENT} — what a sub-agent's registration is rewritten to. */\nconst CONVERTED_GATE_EVENT = \"SubagentStop\"\n\n/**\n * The gate as its own hooks record — a fresh one per call.\n *\n * A factory rather than a const because the record is spread into an agent's own\n * hooks and the arrays inside it would otherwise be shared, by identity, with every\n * agent ever compiled in the process; `validResult()` in the CLI's\n * `lib/validation-result.ts` is the same shape for the same reason.\n */\nfunction completionGateHooks(): NonNullable<AgentConfig[\"hooks\"]> {\n return {\n [GATE_EVENT]: [\n { hooks: [{ type: \"command\", command: COMPLETION_GATE_COMMAND }] },\n ],\n }\n}\n\n/**\n * Whether the definition states a completion gate of its own, under either spelling.\n *\n * Both count, because the two ARE one event on the path a compiled agent is normally\n * invoked on — see {@link GATE_EVENT}. Keying only on `Stop` would emit this gate beside a\n * project's `SubagentStop`, and a sub-agent would then run both, which is the opposite of\n * the rule that a project's completion gate is its own to state. `SubagentStop` is also the\n * spelling every agent compiled before 2026-09-03 carries, so it is what a project that\n * copied its gate out of a compiled agent will have written.\n */\nfunction declaresOwnGate(hooks: AgentConfig[\"hooks\"]): boolean {\n if (hooks === undefined) return false\n const stated = [GATE_EVENT, CONVERTED_GATE_EVENT]\n return stated.some((event) => (hooks[event]?.length ?? 0) > 0)\n}\n\n/**\n * The same definition carrying the completion gate alongside whatever it declared.\n *\n * **Composition, not exclusion.** The template used to decide this with an\n * `{% if agent.hooks %}` / `{% elsif tools contains Write %}` pair, so an agent\n * declaring any hook at all — a `PostToolUse` formatter, say — silently lost the\n * completion gate, with nothing reporting it.\n *\n * Merged per EVENT: a declared completion gate replaces this one, because a project stating\n * its own is the rule this product has always documented; every other event is added beside\n * it. An agent holding neither `Write` nor `Edit` is returned unchanged, so the gate is still\n * emitted only where it can mean something.\n *\n * The gate is spread LAST rather than first, which matters only for the degenerate declaration\n * `Stop: []`. {@link declaresOwnGate} reads that as stating no gate, correctly — and spreading\n * the declared record over the gate would then let an empty array clobber it, emitting\n * `hooks: {\"Stop\":[]}` and losing the gate to a key that says nothing. Gate-last cannot lose to\n * a declaration this function has already established is not one.\n *\n * **Composed before the sanitiser, for a narrower reason than that ordering used to claim.** The\n * only value whose sanitisation depends on it is {@link COMPLETION_GATE_COMMAND}, a constant this\n * product authors. An author's own hooks are stripped under either order, because\n * {@link sanitizeCompiledAgentData} walks `agent.hooks` whether or not the gate has been composed\n * into them — measured by rendering a writing agent whose declared hook was poisoned in every\n * field, under both orders: one line of the two renders differed, and the marker in it was the\n * gate's own.\n *\n * Which is a rule nothing can hold, since no fixture can reach that constant. So it is structural\n * instead of remembered: this function is private, {@link prepareForRender} is the one expression\n * that composes with the sanitiser, and {@link renderAgent} has no order left to state.\n */\nfunction withCompletionGate(agent: AgentConfig): AgentConfig {\n const writes = WRITING_TOOLS.some((tool) => agent.tools.includes(tool))\n if (!writes || declaresOwnGate(agent.hooks)) return agent\n return { ...agent, hooks: { ...agent.hooks, ...completionGateHooks() } }\n}\n\n/**\n * The whole of what a render is handed: the completion gate composed into the\n * definition's own hooks, and every author-supplied string stripped of Liquid\n * syntax.\n *\n * The two steps have an order and this is the only expression allowed to state\n * it — written as one nested call rather than two statements, so getting it\n * wrong takes rewriting the expression rather than moving a line. That is worth\n * the indirection because the ordering is unfalsifiable: {@link withCompletionGate}\n * is the reason, and it explains which single value the order decides.\n */\nfunction prepareForRender(data: CompiledAgentData): CompiledAgentData {\n return sanitizeCompiledAgentData({\n ...data,\n agent: withCompletionGate(data.agent),\n })\n}\n\n/**\n * Renders the agent template and stamps the result with the provenance marker.\n *\n * Every compile entry point renders through here, so there is no path that writes a compiled\n * agent this CLI cannot later recognise as its own — which is what `uninstall` reads back\n * when the configuration naming the agents is gone. The stamp replaces rather than inserts,\n * so a template that emits the marker itself still produces exactly one.\n *\n * `version` is an argument because the CLI reads it from its own `package.json` and a browser\n * has no manifest to read; the editor passes `CORPUS_CLI_VERSION`, the release the corpus was\n * vendored at. It reaches the template as `generatorVersion` and renders inside the trailing\n * volatile block rather than into the provenance marker, so a release bump no longer rewrites\n * the first cacheable byte of every compiled agent.\n *\n * The completion gate is composed into the agent's own hooks before the render rather than\n * branched on in the template — see {@link prepareForRender} — so the template holds one\n * unconditional `hooks:` emission and the gate reaches `sanitizeHooks` like any other hook.\n */\nexport async function renderAgent(\n engine: Liquid,\n data: CompiledAgentData,\n version: string\n): Promise<string> {\n // Boundary cast: liquidjs types renderFile as `Promise<any>` because a template\n // can render to any value. The agent template renders a markdown file, and both\n // callers have declared `Promise<string>` since they were written.\n const rendered = (await engine.renderFile(AGENT_TEMPLATE, {\n ...prepareForRender(data),\n generatorVersion: sanitizeLiquidSyntax(version, \"generatorVersion\"),\n })) as string\n return stampProvenanceMarker(rendered)\n}\n","import path from \"path\";\nimport { directoryExists } from \"../../utils/fs\";\nimport { verbose } from \"../../utils/logger\";\nimport { PROJECT_ROOT, DIRS } from \"../../consts\";\nimport { fetchFromSource, type FetchOptions } from \"../loading\";\nimport { loadProjectSourceConfig } from \"../configuration\";\nimport type { AgentSourcePaths } from \"../../types\";\n\nexport async function getAgentDefinitions(remoteSource?: string): Promise<AgentSourcePaths> {\n if (remoteSource) {\n return fetchAgentDefinitionsFromRemote(remoteSource);\n }\n return getLocalAgentDefinitions();\n}\n\nexport async function getLocalAgentDefinitions(): Promise<AgentSourcePaths> {\n const agentsDir = path.join(PROJECT_ROOT, DIRS.agents);\n\n if (!(await directoryExists(agentsDir))) {\n throw new Error(\n `Agent partials not found at '${agentsDir}'. Ensure the CLI is properly installed.`,\n );\n }\n\n verbose(`Agent partials loaded from CLI: ${agentsDir}`);\n\n return {\n agentsDir,\n sourcePath: PROJECT_ROOT,\n };\n}\n\nexport async function fetchAgentDefinitionsFromRemote(\n source: string,\n options: FetchOptions & { agentsDir?: string } = {},\n): Promise<AgentSourcePaths> {\n verbose(`Fetching agent partials from remote: ${source}`);\n\n const result = await fetchFromSource(source, { subdir: \"\" });\n\n // ABORT on an unreadable config. It names the directory the fetched repository keeps its agent\n // partials in; defaulting past it compiles agents from whatever happens to sit at `DIRS.agents`,\n // or reports partials missing from a repository that has them.\n const sourceProjectConfig = options.agentsDir\n ? undefined\n : await loadProjectSourceConfig(result.path);\n if (sourceProjectConfig?.agentsDir) {\n verbose(`Using agentsDir from source config: ${sourceProjectConfig.agentsDir}`);\n }\n const agentsDirRelPath = options.agentsDir ?? sourceProjectConfig?.agentsDir ?? DIRS.agents;\n\n const agentsDir = path.join(result.path, agentsDirRelPath);\n\n if (!(await directoryExists(agentsDir))) {\n throw new Error(`Agent partials not found at '${agentsDir}'`);\n }\n\n verbose(`Agent partials fetched from: ${result.path}`);\n\n return {\n agentsDir,\n sourcePath: result.path,\n };\n}\n","import { partition } from \"remeda\";\nimport { writeCompiledAgentsByScope, type AgentWriteOutcome } from \"./write-compiled-agents\";\nimport { listCompiledAgentNames } from \"./list-compiled-agents\";\nimport path from \"path\";\n\nimport { getErrorMessage } from \"../../utils/errors\";\nimport type {\n AgentDefinition,\n AgentName,\n CompileAgentConfig,\n CompileConfig,\n ProjectConfig,\n SkillDefinitionMap,\n SkillScope,\n} from \"../../types\";\n\nimport { buildCompileAgents } from \"../installation/local-installer\";\nimport { ensureDir } from \"../../utils/fs\";\nimport { verbose } from \"../../utils/logger\";\nimport { typedEntries, typedFromEntries, typedKeys } from \"../../utils/typed-object\";\nimport { createLiquidEngine } from \"../compiler\";\nimport { loadProjectConfig, effectivelyExcludedSkillIds } from \"../configuration\";\nimport { loadAllAgents, loadProjectAgents } from \"../loading\";\nimport { getPluginAgentsDir } from \"../plugins\";\nimport { discoverAllPluginSkills } from \"../plugins/plugin-discovery\";\nimport { resolveAgents } from \"../resolver\";\n\nexport type RecompileAgentsOptions = {\n pluginDir: string;\n sourcePath: string;\n agents?: AgentName[];\n skills?: SkillDefinitionMap;\n projectDir?: string;\n outputDir?: string;\n /** When provided, routes agents by scope: global agents to ~/.claude/agents/, project agents to outputDir */\n agentScopeMap?: Map<AgentName, SkillScope>;\n};\n\nexport type RecompileAgentsResult = {\n compiled: AgentName[];\n /**\n * The subset of `compiled` whose file this pass actually wrote. `compiled` is\n * every agent that came through the pass with a correct file at the end of it;\n * `rewritten` is the ones whose content moved, so `compiled minus rewritten` is\n * the count a summary reports as unchanged.\n */\n rewritten: AgentName[];\n failed: AgentName[];\n warnings: string[];\n};\n\nasync function getExistingAgentNames(pluginDir: string): Promise<AgentName[]> {\n return listCompiledAgentNames(getPluginAgentsDir(pluginDir));\n}\n\ntype ResolveAgentNamesParams = {\n specifiedAgents?: AgentName[];\n projectConfig: ProjectConfig | null;\n allAgents: Partial<Record<AgentName, AgentDefinition>>;\n outputDir?: string;\n pluginDir: string;\n};\n\nasync function resolveAgentNames(params: ResolveAgentNamesParams): Promise<AgentName[]> {\n const { specifiedAgents, projectConfig, allAgents, outputDir, pluginDir } = params;\n\n if (specifiedAgents) {\n return specifiedAgents;\n }\n\n // A present config is authoritative over its agent roster — even when empty.\n // `agents: []` means \"no agents\", so it must NOT fall through to the\n // all-agents branch below; that branch exists only for the config-LESS case.\n if (projectConfig) {\n const agentNames = projectConfig.agents.map((a) => a.name);\n verbose(`Using agents from config: ${agentNames.join(\", \")}`);\n return agentNames;\n }\n\n if (outputDir) {\n const names = typedKeys<AgentName>(allAgents);\n verbose(`Using all available agents from source: ${names.join(\", \")}`);\n return names;\n }\n\n return getExistingAgentNames(pluginDir);\n}\n\n/** Splits write outcomes into the recompile result; logs each success at verbose level. */\nfunction buildRecompileResult(\n outcomes: AgentWriteOutcome[],\n priorWarnings: string[],\n): RecompileAgentsResult {\n const [succeeded, failedOutcomes] = partition(\n outcomes,\n (outcome): outcome is Extract<AgentWriteOutcome, { ok: true }> => outcome.ok,\n );\n succeeded.forEach((outcome) =>\n verbose(\n ` ${outcome.rewritten ? \"Rewrote\" : \"Unchanged\"}: ${outcome.name} (${outcome.scope} -> ${outcome.targetDir})`,\n ),\n );\n return {\n compiled: succeeded.map((outcome) => outcome.name),\n rewritten: succeeded.filter((outcome) => outcome.rewritten).map((outcome) => outcome.name),\n failed: failedOutcomes.map((outcome) => outcome.name),\n warnings: [\n ...priorWarnings,\n ...failedOutcomes.map(\n (outcome) => `Failed to compile ${outcome.name}: ${getErrorMessage(outcome.error)}`,\n ),\n ],\n };\n}\n\nexport function filterExcludedEntries(config: ProjectConfig): ProjectConfig {\n const excludedIds = effectivelyExcludedSkillIds(config.skills);\n const activeSkills = config.skills.filter((s) => !s.excluded);\n const activeAgents = config.agents.filter((a) => !a.excluded);\n\n // Also remove excluded skill refs from stack assignments. A config with no stack keeps\n // none — the key stays absent rather than becoming an explicit `undefined`.\n const filteredStack =\n config.stack === undefined\n ? {}\n : {\n stack: Object.fromEntries(\n typedEntries(config.stack).map(([agentName, agentStack]) => [\n agentName,\n Object.fromEntries(\n typedEntries(agentStack).map(([category, assignments]) => [\n category,\n assignments.filter((a) => !excludedIds.has(a.id)),\n ]),\n ),\n ]),\n ),\n };\n\n return { ...config, skills: activeSkills, agents: activeAgents, ...filteredStack };\n}\n\nexport async function recompileAgents(\n options: RecompileAgentsOptions,\n): Promise<RecompileAgentsResult> {\n const { pluginDir, sourcePath, skills: providedSkills, projectDir, outputDir } = options;\n\n const configDir = projectDir ?? pluginDir;\n const loadedConfig = await loadProjectConfig(configDir);\n const projectConfig = loadedConfig?.config ?? null;\n\n // Filter excluded entries once at the entry point — callees receive clean data\n const filteredConfig = projectConfig ? filterExcludedEntries(projectConfig) : null;\n\n const builtinAgents = await loadAllAgents(sourcePath);\n const projectAgents = projectDir ? await loadProjectAgents(projectDir) : {};\n\n // Priority: project agents > built-in agents\n const allAgents: Partial<Record<AgentName, AgentDefinition>> = {\n ...builtinAgents,\n ...projectAgents,\n };\n\n const agentNames = await resolveAgentNames({\n ...(options.agents !== undefined && { specifiedAgents: options.agents }),\n projectConfig: filteredConfig,\n allAgents,\n ...(outputDir !== undefined && { outputDir }),\n pluginDir,\n });\n\n if (agentNames.length === 0) {\n return { compiled: [], rewritten: [], failed: [], warnings: [\"No agents found to recompile\"] };\n }\n\n verbose(`Recompiling ${agentNames.length} agents in ${outputDir ?? pluginDir}`);\n\n // When skills are not provided, discover from all plugin directories.\n const pluginSkills: SkillDefinitionMap =\n providedSkills ?? (await discoverAllPluginSkills(projectDir ?? pluginDir));\n\n const allConfigAgents = filteredConfig ? buildCompileAgents(filteredConfig, allAgents) : {};\n\n // Restrict to only the agents we're compiling (agentNames).\n // buildCompileAgents returns entries for ALL agents in the config, but when\n // scopeFilter is active, we only want the agents matching that scope.\n // Without this filter, a project pass would compile global agents without\n // their stack (since the project config omits global agent stack entries)\n // and overwrite correctly compiled global agent files.\n const [knownAgents, missingAgents] = partition(agentNames, (name) =>\n Boolean(allConfigAgents[name] || allAgents[name]),\n );\n const missingWarnings = missingAgents.map(\n (name) => `Agent \"${name}\" not found in source definitions`,\n );\n const configAgents = typedFromEntries<AgentName, CompileAgentConfig>(\n knownAgents.map((name) => [name, allConfigAgents[name] ?? {}]),\n );\n\n const compileConfig: CompileConfig = {\n name: filteredConfig?.name || path.basename(pluginDir),\n description: filteredConfig?.description || \"Recompiled plugin\",\n agents: configAgents,\n };\n\n const engine = await createLiquidEngine(projectDir);\n const resolvedAgents = await resolveAgents(allAgents, pluginSkills, compileConfig, sourcePath);\n\n const agentsDir = outputDir ?? getPluginAgentsDir(pluginDir);\n await ensureDir(agentsDir);\n\n const outcomes = await writeCompiledAgentsByScope({\n resolvedAgents,\n sourcePath,\n engine,\n projectAgentsDir: agentsDir,\n ...(options.agentScopeMap !== undefined && { agentScopeMap: options.agentScopeMap }),\n });\n return buildRecompileResult(outcomes, missingWarnings);\n}\n","import os from \"os\";\nimport path from \"path\";\nimport type { Liquid } from \"liquidjs\";\nimport { compileAgentForPlugin } from \"../compiler.js\";\nimport { resolveInstallPaths } from \"../installation/install-base-dir.js\";\nimport { writeFile, fileExists, readFile } from \"../../utils/fs.js\";\nimport { typedEntries } from \"../../utils/typed-object.js\";\nimport type { AgentConfig, AgentName, SkillScope } from \"../../types/index.js\";\n\nexport type AgentWriteOutcome =\n | {\n name: AgentName;\n ok: true;\n scope: SkillScope;\n targetDir: string;\n /**\n * Whether this pass actually wrote the file. False means the compiled output\n * matched what was already on disk, so nothing was written — which is what\n * lets a recompile summary tell a real one from a no-op instead of counting\n * the roster it walked.\n */\n rewritten: boolean;\n }\n | { name: AgentName; ok: false; error: unknown };\n\n/**\n * Whether the target already holds exactly this content, making a write a no-op.\n *\n * Skipping that write is what gives \"unchanged\" a meaning a caller can check: an\n * agent reported unchanged keeps its mtime, and an mtime is the only trace a\n * rewrite-with-identical-bytes leaves anywhere.\n */\nasync function holdsExactly(filePath: string, content: string): Promise<boolean> {\n return (await fileExists(filePath)) && (await readFile(filePath)) === content;\n}\n\n/**\n * Where an agent goes when `agentScopeMap` has nothing to say about it — either because the caller\n * passed no map at all (`agents-inc update` recompiles that way) or because this agent is not in\n * the one it passed (a hand-authored agent under `.claude/agents/` has no config row).\n *\n * This is a ROUTING answer, not a selection default: `\"project\"` here means \"the directory the\n * caller named in `projectAgentsDir`\", which for an unrouted write is the only defensible target.\n * It is deliberately NOT `DEFAULT_SELECTION_OPTIONS.scope` from `@workspace/matrix` — that constant\n * says what an untouched *pick* installs as, and adopting it here would relocate the agents of every\n * caller that never asked for global routing into the user's `~/.claude/agents`.\n */\nconst UNROUTED_AGENT_SCOPE: SkillScope = \"project\";\n\n/**\n * Compiles each resolved agent and writes it to its scope's agents directory:\n * global agents to `~/.claude/agents/`, project agents to `projectAgentsDir`.\n * Per-agent failures are collected as outcomes — callers own the policy\n * (recompile reports and continues; install hard-errors).\n *\n * Neither directory is created up front. `writeFile` makes a target's parent on\n * the way past, so a directory appears exactly when an agent routes into it —\n * which is what keeps a wholly project-scoped pass from leaving an empty\n * `~/.claude/agents/` behind in a home that has no global install.\n */\nexport async function writeCompiledAgentsByScope(params: {\n resolvedAgents: Partial<Record<AgentName, AgentConfig>>;\n sourcePath: string;\n engine: Liquid;\n projectAgentsDir: string;\n agentScopeMap?: Map<AgentName, SkillScope>;\n}): Promise<AgentWriteOutcome[]> {\n const globalAgentsDir = resolveInstallPaths(os.homedir(), \"global\").agentsDir;\n\n const outcomes: AgentWriteOutcome[] = [];\n for (const [name, agent] of typedEntries<AgentName, AgentConfig>(params.resolvedAgents)) {\n try {\n const output = await compileAgentForPlugin(name, agent, params.sourcePath, params.engine);\n const scope = params.agentScopeMap?.get(name) ?? UNROUTED_AGENT_SCOPE;\n const targetDir = scope === \"global\" ? globalAgentsDir : params.projectAgentsDir;\n const targetPath = path.join(targetDir, `${name}.md`);\n const rewritten = !(await holdsExactly(targetPath, output));\n if (rewritten) await writeFile(targetPath, output);\n outcomes.push({ name, ok: true, scope, targetDir, rewritten });\n } catch (error) {\n outcomes.push({ name, ok: false, error });\n }\n }\n return outcomes;\n}\n","import { Liquid } from \"liquidjs\";\nimport path from \"path\";\nimport {\n buildAgentTemplateContext,\n pluginRefFor,\n renderAgent,\n type AgentFiles,\n} from \"@workspace/compile/agent-source\";\nimport { readFile, readFileOptional, directoryExists } from \"../utils/fs\";\nimport { verbose } from \"../utils/logger\";\nimport {\n CLAUDE_DIR,\n CLAUDE_SRC_DIR,\n DIRS,\n PROJECT_ROOT,\n STANDARD_FILES,\n STANDARD_DIRS,\n} from \"../consts\";\nimport { cliVersion } from \"./agents/agent-provenance\";\nimport \"./compile-seat.js\";\nimport type { AgentConfig, AgentName } from \"../types\";\n\n/**\n * What survives here is the half of a compile that reads the machine: the five `readFile`s that\n * fetch an agent's partials off disk, and the layered template roots a project can override. The\n * rendering itself — the template context, the injection sanitiser and the provenance stamp — is\n * `@workspace/compile/agent-source`, so the editor's output preview draws the bytes this writes\n * rather than a second implementation of them.\n */\nexport {\n buildAgentTemplateContext,\n sanitizeCompiledAgentData,\n sanitizeLiquidSyntax,\n} from \"@workspace/compile/agent-source\";\n\nasync function readAgentFiles(\n name: AgentName,\n agent: AgentConfig,\n projectRoot: string,\n): Promise<AgentFiles> {\n const agentSourceRoot = agent.sourceRoot || projectRoot;\n const agentBaseDir = agent.agentBaseDir || DIRS.agents;\n const agentDir = path.join(agentSourceRoot, agentBaseDir, agent.path || name);\n\n const identity = await readFile(path.join(agentDir, STANDARD_FILES.IDENTITY_MD));\n const playbook = await readFile(path.join(agentDir, STANDARD_FILES.PLAYBOOK_MD));\n const criticalRequirementsTop = await readFileOptional(\n path.join(agentDir, STANDARD_FILES.CRITICAL_REQUIREMENTS_MD),\n \"\",\n );\n const criticalReminders = await readFileOptional(\n path.join(agentDir, STANDARD_FILES.CRITICAL_REMINDERS_MD),\n \"\",\n );\n\n const agentPath = agent.path || name;\n const parts = agentPath.split(\"/\");\n const category = parts[0] || name;\n const categoryDir = path.join(agentSourceRoot, agentBaseDir, category);\n\n let output = await readFileOptional(path.join(agentDir, STANDARD_FILES.OUTPUT_MD), \"\");\n if (!output) {\n output = await readFileOptional(path.join(categoryDir, STANDARD_FILES.OUTPUT_MD), \"\");\n }\n\n return { identity, playbook, output, criticalRequirementsTop, criticalReminders };\n}\n\n/**\n * Creates a Liquid template engine with a layered template root hierarchy.\n *\n * Template resolution order (first match wins):\n * 1. Project-local templates: `{projectDir}/.claude-src/agents/_templates/`\n * 2. Legacy templates: `{projectDir}/.claude/templates/`\n * 3. Built-in templates: `{PROJECT_ROOT}/src/agents/_templates/`\n *\n * The browser-side twin is `createEngineFromTemplates` in `@workspace/compile/engine`, which\n * builds the same engine over the vendored corpus instead of over directories. Every option\n * below is duplicated there, because a render that resolved filters or variables differently\n * would produce a different file from the same data.\n *\n * @param projectDir - Optional project directory for local template overrides\n * @returns Configured Liquid engine with `.liquid` extension and strict filters\n */\nexport async function createLiquidEngine(projectDir?: string): Promise<Liquid> {\n const roots: string[] = [];\n\n if (projectDir) {\n const srcTemplatesDir = path.join(\n projectDir,\n CLAUDE_SRC_DIR,\n STANDARD_DIRS.AGENTS,\n path.basename(DIRS.templates),\n );\n if (await directoryExists(srcTemplatesDir)) {\n roots.push(srcTemplatesDir);\n verbose(`Using local templates from: ${srcTemplatesDir}`);\n }\n\n const legacyTemplatesDir = path.join(projectDir, CLAUDE_DIR, STANDARD_DIRS.TEMPLATES);\n if (await directoryExists(legacyTemplatesDir)) {\n roots.push(legacyTemplatesDir);\n verbose(`Using legacy templates from: ${legacyTemplatesDir}`);\n }\n }\n\n roots.push(path.join(PROJECT_ROOT, DIRS.templates));\n\n return new Liquid({\n root: roots,\n extname: \".liquid\",\n strictVariables: false,\n strictFilters: true,\n });\n}\n\nexport async function compileAgentForPlugin(\n name: AgentName,\n agent: AgentConfig,\n fallbackRoot: string,\n engine: Liquid,\n): Promise<string> {\n verbose(`Compiling agent: ${name}`);\n\n const files = await readAgentFiles(name, agent, fallbackRoot);\n\n // Per-skill pluginRef attachment. Each skill's own `source` decides\n // whether it renders as `${id}:${id}` (plugin-installed) or bare id (ejected).\n // This correctly handles mixed-mode agents where some skills are plugin and\n // others are ejected. Missing `source` (user-authored local skills with no\n // SkillConfig entry) falls through to bare id — the expected case, not a\n // silent fallback.\n const data = buildAgentTemplateContext(name, agent, files, (skill) => ({\n ...skill,\n ...pluginRefFor(skill),\n }));\n\n return renderAgent(engine, data, await cliVersion());\n}\n","import path from \"path\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { readFile, ensureDir, copy } from \"../../utils/fs\";\nimport { log, verbose, warn } from \"../../utils/logger\";\nimport {\n generateAgentPluginManifest,\n writePluginManifest,\n getPluginManifestPath,\n} from \"../plugins\";\nimport { listAgentMdFiles } from \"./list-compiled-agents\";\nimport { computeStringHash, determinePluginVersion, writeContentHash } from \"../versioning\";\nimport { extractFrontmatter } from \"../../utils/frontmatter\";\nimport type { AgentFrontmatter, PluginManifest } from \"../../types\";\nimport { agentFrontmatterValidationSchema, formatZodIssues } from \"../schemas\";\n\nexport type AgentPluginOptions = {\n agentPath: string;\n outputDir: string;\n};\n\nexport type CompiledAgentPlugin = {\n pluginPath: string;\n manifest: PluginManifest;\n agentName: string;\n};\n\n/**\n * The frontmatter a plugin build needs, or the reason it could not be had.\n *\n * The reason is carried out rather than discarded because the throw in\n * {@link compileAgentPlugin} is the only thing a `build` run surfaces for a failed agent, and it\n * used to name `name` and `description` whatever had actually gone wrong — so an agent rejected\n * for an unknown key or a bad enum value was reported as missing two fields it declared correctly.\n *\n * Nothing is warned here, deliberately. This function is private and has one caller, which throws\n * on every failure, and {@link compileAllAgentPlugins} catches that throw and warns the message —\n * so a warning here would print the same cause twice. The shared `parseFrontmatter` on the skill\n * side keeps its own warn for the opposite reason: most of its callers skip rather than throw.\n */\ntype AgentFrontmatterParse =\n | { ok: true; frontmatter: Pick<AgentFrontmatter, \"name\" | \"description\"> }\n | { ok: false; reason: string };\n\n/** The reason when there is no frontmatter block at all, as opposed to one the schema refused. */\nconst NO_FRONTMATTER_REASON = \"no YAML frontmatter block\";\n\nfunction parseAgentFrontmatter(content: string): AgentFrontmatterParse {\n const raw = extractFrontmatter(content);\n if (!raw) {\n return { ok: false, reason: NO_FRONTMATTER_REASON };\n }\n\n const result = agentFrontmatterValidationSchema.safeParse(raw);\n if (!result.success) {\n return { ok: false, reason: formatZodIssues(result.error.issues) };\n }\n\n return {\n ok: true,\n frontmatter: { name: result.data.name, description: result.data.description },\n };\n}\n\nexport async function compileAgentPlugin(\n options: AgentPluginOptions,\n): Promise<CompiledAgentPlugin> {\n const { agentPath, outputDir } = options;\n const fileName = path.basename(agentPath);\n\n const content = await readFile(agentPath);\n const parsed = parseAgentFrontmatter(content);\n\n if (!parsed.ok) {\n throw new Error(\n `Agent '${fileName}' has invalid or missing YAML frontmatter: ${parsed.reason}. ` +\n `File: ${agentPath}`,\n );\n }\n\n const agentName = parsed.frontmatter.name;\n\n verbose(`Compiling agent plugin: ${agentName} from ${agentPath}`);\n\n const pluginDir = path.join(outputDir, `agent-${agentName}`);\n const agentsDir = path.join(pluginDir, \"agents\");\n\n await ensureDir(pluginDir);\n await ensureDir(agentsDir);\n\n const newHash = computeStringHash(content);\n const { version, contentHash } = await determinePluginVersion(\n newHash,\n pluginDir,\n getPluginManifestPath,\n );\n\n const manifest = generateAgentPluginManifest({\n agentName,\n description: parsed.frontmatter.description,\n version,\n });\n\n await writePluginManifest(pluginDir, manifest);\n\n await writeContentHash(pluginDir, contentHash, getPluginManifestPath);\n\n verbose(` Wrote plugin.json for ${agentName} (v${version})`);\n\n await copy(agentPath, path.join(agentsDir, `${agentName}.md`));\n verbose(` Copied agent ${fileName} -> agents/${agentName}.md`);\n\n return {\n pluginPath: pluginDir,\n manifest,\n agentName,\n };\n}\n\nexport async function compileAllAgentPlugins(\n agentsDir: string,\n outputDir: string,\n): Promise<CompiledAgentPlugin[]> {\n const results: CompiledAgentPlugin[] = [];\n\n const agentMdFiles = await listAgentMdFiles(agentsDir);\n\n for (const agentFile of agentMdFiles) {\n const agentPath = path.join(agentsDir, agentFile);\n\n try {\n const result = await compileAgentPlugin({\n agentPath,\n outputDir,\n });\n results.push(result);\n log(` [OK] agent-${result.agentName}`);\n } catch (error) {\n const errorMessage = getErrorMessage(error);\n warn(`Failed to compile agent from '${agentFile}': ${errorMessage}`);\n }\n }\n\n return results;\n}\n\nexport function printAgentCompilationSummary(results: CompiledAgentPlugin[]): void {\n log(`\\nCompiled ${results.length} agent plugins:`);\n for (const result of results) {\n log(` - agent-${result.agentName} (v${result.manifest.version})`);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAOA,WAAU;AACjB,SAAS,iBAAiB;;;ACD1B,OAAO,UAAU;AACjB,SAAS,SAAS;;;ACoBlB,IAAM,wBAAwB;AAUvB,SAAS,qBACd,OACA,WACG;AACH,MAAI,CAAC,sBAAsB,KAAK,KAAK,EAAG,QAAO;AAC/C,wBAAsB,YAAY;AAClC,QAAM,YAAY,MAAM,QAAQ,uBAAuB,EAAE;AACzD,cAAY,EAAE;AAAA,IACZ,yCAAyC,SAAS;AAAA,EACpD;AAEA,SAAO;AACT;AAEA,SAAS,oBAAoB,QAAkB,WAA6B;AAC1E,SAAO,OAAO,IAAI,CAAC,MAAM,qBAAqB,GAAG,SAAS,CAAC;AAC7D;AAgBA,SAAS,cACP,OACmC;AACnC,SAAO,OAAO;AAAA,IACZ,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,OAAO,WAAW,MAAM;AAAA,MAClD,qBAAqB,OAAO,YAAY;AAAA,MACxC,YAAY,IAAI,CAAC,gBAAgB;AAAA,QAC/B,GAAG;AAAA,QACH,GAAI,WAAW,YAAY,UAAa;AAAA,UACtC,SAAS,qBAAqB,WAAW,SAAS,cAAc;AAAA,QAClE;AAAA,QACA,GAAI,WAAW,UAAU,UAAa;AAAA,UACpC,OAAO,WAAW,MAAM,IAAI,CAAC,YAAY;AAAA,YACvC,GAAG;AAAA,YACH,MAAM,qBAAqB,OAAO,MAAM,WAAW;AAAA,YACnD,GAAI,OAAO,YAAY,UAAa;AAAA,cAClC,SAAS,qBAAqB,OAAO,SAAS,cAAc;AAAA,YAC9D;AAAA,YACA,GAAI,OAAO,WAAW,UAAa;AAAA,cACjC,QAAQ,qBAAqB,OAAO,QAAQ,aAAa;AAAA,YAC3D;AAAA,YACA,GAAI,OAAO,WAAW,UAAa;AAAA,cACjC,QAAQ,qBAAqB,OAAO,QAAQ,aAAa;AAAA,YAC3D;AAAA,UACF,EAAE;AAAA,QACJ;AAAA,MACF,EAAE;AAAA,IACJ,CAAC;AAAA,EACH;AACF;AAcA,SAAS,qBACP,cAC0C;AAC1C,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAI,aAAa,aAAa,UAAa;AAAA,MACzC,UAAU;AAAA,QACR,aAAa;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,eAAe,QAA0B;AAChD,SAAO,OAAO,IAAI,CAAC,OAAO;AAAA,IACxB,GAAG;AAAA,IACH,IAAI,qBAAqB,EAAE,IAAI,UAAU;AAAA,IACzC,aAAa,qBAAqB,EAAE,aAAa,mBAAmB;AAAA,IACpE,OAAO,qBAAqB,EAAE,OAAO,aAAa;AAAA,IAClD,GAAI,EAAE,cAAc,UAAa;AAAA,MAC/B,WAAW,qBAAqB,EAAE,WAAW,iBAAiB;AAAA,IAChE;AAAA,EACF,EAAE;AACJ;AAYO,SAAS,0BACd,MACmB;AACnB,QAAM,iBAA8B;AAAA,IAClC,GAAG,KAAK;AAAA,IACR,MAAM,qBAAqB,KAAK,MAAM,MAAM,YAAY;AAAA,IACxD,OAAO,qBAAqB,KAAK,MAAM,OAAO,aAAa;AAAA,IAC3D,aAAa;AAAA,MACX,KAAK,MAAM;AAAA,MACX;AAAA,IACF;AAAA,IACA,OAAO,oBAAoB,KAAK,MAAM,OAAO,aAAa;AAAA,IAC1D,GAAI,KAAK,MAAM,oBAAoB,UAAa;AAAA,MAC9C,iBAAiB;AAAA,QACf,KAAK,MAAM;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAAA,IACA,GAAI,KAAK,MAAM,UAAU,UAAa;AAAA,MACpC,OAAO,qBAAqB,KAAK,MAAM,OAAO,aAAa;AAAA,IAC7D;AAAA,IACA,GAAI,KAAK,MAAM,WAAW,UAAa;AAAA,MACrC,QAAQ,qBAAqB,KAAK,MAAM,QAAQ,cAAc;AAAA,IAChE;AAAA,IACA,GAAI,KAAK,MAAM,mBAAmB,UAAa;AAAA,MAC7C,gBAAgB;AAAA,QACd,KAAK,MAAM;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAAA,IACA,GAAI,KAAK,MAAM,cAAc,UAAa;AAAA,MACxC,WAAW,qBAAqB,KAAK,MAAM,WAAW,iBAAiB;AAAA,IACzE;AAAA,IACA,GAAI,KAAK,MAAM,iBAAiB,UAAa;AAAA,MAC3C,cAAc,qBAAqB,KAAK,MAAM,YAAY;AAAA,IAC5D;AAAA,IACA,GAAI,KAAK,MAAM,UAAU,UAAa;AAAA,MACpC,OAAO,cAAc,KAAK,MAAM,KAAK;AAAA,IACvC;AAAA,EACF;AAEA,QAAM,kBAAkB,eAAe,KAAK,MAAM;AAClD,QAAM,qBAAqB,eAAe,KAAK,eAAe;AAC9D,QAAM,mBAAmB,eAAe,KAAK,aAAa;AAC1D,QAAM,wBAAwB,KAAK,kBAAkB;AAAA,IAAI,CAAC,OACxD,qBAAqB,IAAI,kBAAkB;AAAA,EAC7C;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,UAAU,KAAK;AAAA,IACf,UAAU,KAAK;AAAA,IACf,QAAQ,KAAK;AAAA,IACb,yBAAyB,KAAK;AAAA,IAC9B,mBAAmB,KAAK;AAAA,IACxB,QAAQ;AAAA,IACR,iBAAiB;AAAA,IACjB,eAAe;AAAA,IACf,mBAAmB;AAAA,EACrB;AACF;AAuBA,IAAM,aAAa;AAUnB,SAAS,cAAc,OAAiC;AACtD,MAAI,MAAM,MAAM,SAAS,UAAU,EAAG,QAAO;AAC7C,SAAO,EAAE,GAAG,OAAO,OAAO,CAAC,GAAG,MAAM,OAAO,UAAU,EAAE;AACzD;AAyBO,SAAS,0BACd,MACA,OACA,OACA,WAAoC,CAAC,UAAU,OAC5B;AACnB,QAAM,SAAS,MAAM,OAAO,IAAI,QAAQ;AACxC,QAAM,kBAAkB,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS;AACxD,QAAM,gBAAgB,OAAO,OAAO,CAAC,MAAM,CAAC,EAAE,SAAS;AACvD,QAAM,oBAAoB,gBAAgB,IAAI,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE;AAExE,cAAY,EAAE;AAAA,IACZ,cAAc,IAAI,KAAK,gBAAgB,MAAM,eAAe,cAAc,MAAM;AAAA,EAClF;AAEA,SAAO;AAAA,IACL,OAAO,cAAc,KAAK;AAAA,IAC1B,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAQO,SAAS,aAAa,OAA8C;AACzE,MAAI,MAAM,WAAW,UAAa,MAAM,WAAW,aAAc,QAAO,CAAC;AACzE,SAAO,EAAE,WAAW,GAAG,MAAM,EAAE,IAAI,MAAM,EAAE,GAAY;AACzD;AAsBA,IAAM,cAAc,qBAAqB,mBAAmB;AAC5D,IAAM,gBAAgB;AACtB,IAAM,eAAe;AAErB,IAAM,oBAAoB;AAEnB,SAAS,mBAA2B;AACzC,SAAO,GAAG,WAAW,GAAG,aAAa,GAAG,YAAY;AACtD;AAGA,SAAS,mBAAmB,MAAuB;AACjD,SAAO,KAAK,WAAW,WAAW,KAAK,KAAK,SAAS,YAAY;AACnE;AAOA,SAAS,eAAe,OAAkC;AACxD,MAAI,MAAM,CAAC,MAAM,kBAAmB,QAAO;AAC3C,QAAM,eAAe,MAAM,QAAQ,mBAAmB,CAAC;AACvD,MAAI,iBAAiB,GAAI,QAAO;AAChC,SAAO,eAAe;AACxB;AASO,SAAS,oBAAoB,SAA0B;AAC5D,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,QAAM,gBAAgB,MAAM,eAAe,KAAK,CAAC;AACjD,SAAO,kBAAkB,UAAa,mBAAmB,aAAa;AACxE;AAWO,SAAS,sBAAsB,SAAyB;AAC7D,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,QAAM,YAAY,eAAe,KAAK;AACtC,QAAM,gBAAgB,oBAAoB,OAAO,IAAI,IAAI;AAEzD,SAAO;AAAA,IACL,GAAG,MAAM,MAAM,GAAG,SAAS;AAAA,IAC3B,iBAAiB;AAAA,IACjB,GAAG,MAAM,MAAM,YAAY,aAAa;AAAA,EAC1C,EAAE,KAAK,IAAI;AACb;AAGA,IAAM,iBAAiB;AA6BvB,IAAM,0BACJ;AAKF,IAAM,gBAAgB,CAAC,SAAS,MAAM;AAsBtC,IAAM,aAAa;AAGnB,IAAM,uBAAuB;AAU7B,SAAS,sBAAyD;AAChE,SAAO;AAAA,IACL,CAAC,UAAU,GAAG;AAAA,MACZ,EAAE,OAAO,CAAC,EAAE,MAAM,WAAW,SAAS,wBAAwB,CAAC,EAAE;AAAA,IACnE;AAAA,EACF;AACF;AAYA,SAAS,gBAAgB,OAAsC;AAC7D,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,SAAS,CAAC,YAAY,oBAAoB;AAChD,SAAO,OAAO,KAAK,CAAC,WAAW,MAAM,KAAK,GAAG,UAAU,KAAK,CAAC;AAC/D;AAiCA,SAAS,mBAAmB,OAAiC;AAC3D,QAAM,SAAS,cAAc,KAAK,CAAC,SAAS,MAAM,MAAM,SAAS,IAAI,CAAC;AACtE,MAAI,CAAC,UAAU,gBAAgB,MAAM,KAAK,EAAG,QAAO;AACpD,SAAO,EAAE,GAAG,OAAO,OAAO,EAAE,GAAG,MAAM,OAAO,GAAG,oBAAoB,EAAE,EAAE;AACzE;AAaA,SAAS,iBAAiB,MAA4C;AACpE,SAAO,0BAA0B;AAAA,IAC/B,GAAG;AAAA,IACH,OAAO,mBAAmB,KAAK,KAAK;AAAA,EACtC,CAAC;AACH;AAoBA,eAAsB,YACpB,QACA,MACA,SACiB;AAIjB,QAAM,WAAY,MAAM,OAAO,WAAW,gBAAgB;AAAA,IACxD,GAAG,iBAAiB,IAAI;AAAA,IACxB,kBAAkB,qBAAqB,SAAS,kBAAkB;AAAA,EACpE,CAAC;AACD,SAAO,sBAAsB,QAAQ;AACvC;;;AD1iBA,IAAM,uBAAuB,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;AAcpE,IAAI;AAWG,SAAS,aAA8B;AAC5C,iBAAe,eAAe;AAC9B,SAAO;AACT;AAEA,eAAe,iBAAkC;AAC/C,QAAM,eAAe,KAAK,KAAK,cAAc,eAAe,YAAY;AACxE,QAAM,MAAe,KAAK,MAAM,MAAM,SAAS,YAAY,CAAC;AAE5D,QAAM,SAAS,qBAAqB,UAAU,GAAG;AACjD,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,IAAI,MAAM,8CAA8C,YAAY,EAAE;AAAA,EAC9E;AACA,SAAO,OAAO,KAAK;AACrB;;;AD9BA,eAAsB,iBAAiB,WAAsC;AAC3E,SAAO,KAAK,QAAQ,SAAS;AAC/B;AAUA,eAAsB,wBAAwB,WAAkD;AAC9F,QAAM,QAAQ,MAAM,iBAAiB,SAAS;AAC9C,QAAM,aAAa,MAAM,QAAQ,IAAI,MAAM,IAAI,CAAC,SAAS,oBAAoB,WAAW,IAAI,CAAC,CAAC;AAC9F,QAAM,CAAC,QAAQ,QAAQ,IAAI,UAAU,YAAY,CAAC,UAAU,MAAM,YAAY;AAE9E,SAAO,EAAE,QAAQ,OAAO,IAAI,SAAS,GAAG,UAAU,SAAS,IAAI,SAAS,EAAE;AAC5E;AAIA,eAAe,oBAAoB,WAAmB,MAAwC;AAC5F,QAAM,UAAU,MAAM,iBAAiBC,MAAK,KAAK,WAAW,IAAI,CAAC;AACjE,SAAO,EAAE,MAAMA,MAAK,SAAS,MAAM,KAAK,GAAG,cAAc,oBAAoB,OAAO,EAAE;AACxF;AAEA,SAAS,UAAU,OAAgC;AACjD,SAAO,MAAM;AACf;AAGA,eAAsB,uBAAuB,WAAyC;AACpF,QAAM,QAAQ,MAAM,iBAAiB,SAAS;AAG9C,SAAO,MAAM,IAAI,CAAC,MAAMA,MAAK,SAAS,GAAG,KAAK,CAAc;AAC9D;AASA,eAAsB,yBACpB,WACA,MACe;AAEf,QAAM,uBAAuB,CAAC,SAA0B;AACtD,UAAM,OAAOA,MAAK,SAAS,MAAM,KAAK;AACtC,WAAO,YAAY,IAAI,KAAK,CAAC,KAAK,IAAI,IAAI;AAAA,EAC5C;AAEA,QAAM,QAAQ,MAAM,iBAAiB,SAAS;AAC9C,QAAM,QAAQ;AAAA,IACZ,MAAM,OAAO,oBAAoB,EAAE,IAAI,CAAC,SAAS,OAAOA,MAAK,KAAK,WAAW,IAAI,CAAC,CAAC;AAAA,EACrF;AACF;;;AG5EA,OAAOC,WAAU;AAQjB,eAAsB,oBAAoB,cAAkD;AAC1F,MAAI,cAAc;AAChB,WAAO,gCAAgC,YAAY;AAAA,EACrD;AACA,SAAO,yBAAyB;AAClC;AAEA,eAAsB,2BAAsD;AAC1E,QAAM,YAAYC,MAAK,KAAK,cAAc,KAAK,MAAM;AAErD,MAAI,CAAE,MAAM,gBAAgB,SAAS,GAAI;AACvC,UAAM,IAAI;AAAA,MACR,gCAAgC,SAAS;AAAA,IAC3C;AAAA,EACF;AAEA,UAAQ,mCAAmC,SAAS,EAAE;AAEtD,SAAO;AAAA,IACL;AAAA,IACA,YAAY;AAAA,EACd;AACF;AAEA,eAAsB,gCACpB,QACA,UAAiD,CAAC,GACvB;AAC3B,UAAQ,wCAAwC,MAAM,EAAE;AAExD,QAAM,SAAS,MAAM,gBAAgB,QAAQ,EAAE,QAAQ,GAAG,CAAC;AAK3D,QAAM,sBAAsB,QAAQ,YAChC,SACA,MAAM,wBAAwB,OAAO,IAAI;AAC7C,MAAI,qBAAqB,WAAW;AAClC,YAAQ,uCAAuC,oBAAoB,SAAS,EAAE;AAAA,EAChF;AACA,QAAM,mBAAmB,QAAQ,aAAa,qBAAqB,aAAa,KAAK;AAErF,QAAM,YAAYA,MAAK,KAAK,OAAO,MAAM,gBAAgB;AAEzD,MAAI,CAAE,MAAM,gBAAgB,SAAS,GAAI;AACvC,UAAM,IAAI,MAAM,gCAAgC,SAAS,GAAG;AAAA,EAC9D;AAEA,UAAQ,gCAAgC,OAAO,IAAI,EAAE;AAErD,SAAO;AAAA,IACL;AAAA,IACA,YAAY,OAAO;AAAA,EACrB;AACF;;;AC/DA,SAAS,aAAAC,kBAAiB;;;ACA1B,OAAO,QAAQ;AACf,OAAOC,WAAU;;;ACDjB,SAAS,cAAc;AACvB,OAAOC,WAAU;AAkCjB,eAAe,eACb,MACA,OACA,aACqB;AACrB,QAAM,kBAAkB,MAAM,cAAc;AAC5C,QAAM,eAAe,MAAM,gBAAgB,KAAK;AAChD,QAAM,WAAWC,MAAK,KAAK,iBAAiB,cAAc,MAAM,QAAQ,IAAI;AAE5E,QAAM,WAAW,MAAM,SAASA,MAAK,KAAK,UAAU,eAAe,WAAW,CAAC;AAC/E,QAAM,WAAW,MAAM,SAASA,MAAK,KAAK,UAAU,eAAe,WAAW,CAAC;AAC/E,QAAM,0BAA0B,MAAM;AAAA,IACpCA,MAAK,KAAK,UAAU,eAAe,wBAAwB;AAAA,IAC3D;AAAA,EACF;AACA,QAAM,oBAAoB,MAAM;AAAA,IAC9BA,MAAK,KAAK,UAAU,eAAe,qBAAqB;AAAA,IACxD;AAAA,EACF;AAEA,QAAM,YAAY,MAAM,QAAQ;AAChC,QAAM,QAAQ,UAAU,MAAM,GAAG;AACjC,QAAM,WAAW,MAAM,CAAC,KAAK;AAC7B,QAAM,cAAcA,MAAK,KAAK,iBAAiB,cAAc,QAAQ;AAErE,MAAI,SAAS,MAAM,iBAAiBA,MAAK,KAAK,UAAU,eAAe,SAAS,GAAG,EAAE;AACrF,MAAI,CAAC,QAAQ;AACX,aAAS,MAAM,iBAAiBA,MAAK,KAAK,aAAa,eAAe,SAAS,GAAG,EAAE;AAAA,EACtF;AAEA,SAAO,EAAE,UAAU,UAAU,QAAQ,yBAAyB,kBAAkB;AAClF;AAkBA,eAAsB,mBAAmB,YAAsC;AAC7E,QAAM,QAAkB,CAAC;AAEzB,MAAI,YAAY;AACd,UAAM,kBAAkBA,MAAK;AAAA,MAC3B;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACdA,MAAK,SAAS,KAAK,SAAS;AAAA,IAC9B;AACA,QAAI,MAAM,gBAAgB,eAAe,GAAG;AAC1C,YAAM,KAAK,eAAe;AAC1B,cAAQ,+BAA+B,eAAe,EAAE;AAAA,IAC1D;AAEA,UAAM,qBAAqBA,MAAK,KAAK,YAAY,YAAY,cAAc,SAAS;AACpF,QAAI,MAAM,gBAAgB,kBAAkB,GAAG;AAC7C,YAAM,KAAK,kBAAkB;AAC7B,cAAQ,gCAAgC,kBAAkB,EAAE;AAAA,IAC9D;AAAA,EACF;AAEA,QAAM,KAAKA,MAAK,KAAK,cAAc,KAAK,SAAS,CAAC;AAElD,SAAO,IAAI,OAAO;AAAA,IAChB,MAAM;AAAA,IACN,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,eAAe;AAAA,EACjB,CAAC;AACH;AAEA,eAAsB,sBACpB,MACA,OACA,cACA,QACiB;AACjB,UAAQ,oBAAoB,IAAI,EAAE;AAElC,QAAM,QAAQ,MAAM,eAAe,MAAM,OAAO,YAAY;AAQ5D,QAAM,OAAO,0BAA0B,MAAM,OAAO,OAAO,CAAC,WAAW;AAAA,IACrE,GAAG;AAAA,IACH,GAAG,aAAa,KAAK;AAAA,EACvB,EAAE;AAEF,SAAO,YAAY,QAAQ,MAAM,MAAM,WAAW,CAAC;AACrD;;;AD1GA,eAAe,aAAa,UAAkB,SAAmC;AAC/E,SAAQ,MAAM,WAAW,QAAQ,KAAO,MAAM,SAAS,QAAQ,MAAO;AACxE;AAaA,IAAM,uBAAmC;AAazC,eAAsB,2BAA2B,QAMhB;AAC/B,QAAM,kBAAkB,oBAAoB,GAAG,QAAQ,GAAG,QAAQ,EAAE;AAEpE,QAAM,WAAgC,CAAC;AACvC,aAAW,CAAC,MAAM,KAAK,KAAK,aAAqC,OAAO,cAAc,GAAG;AACvF,QAAI;AACF,YAAM,SAAS,MAAM,sBAAsB,MAAM,OAAO,OAAO,YAAY,OAAO,MAAM;AACxF,YAAM,QAAQ,OAAO,eAAe,IAAI,IAAI,KAAK;AACjD,YAAM,YAAY,UAAU,WAAW,kBAAkB,OAAO;AAChE,YAAM,aAAaC,MAAK,KAAK,WAAW,GAAG,IAAI,KAAK;AACpD,YAAM,YAAY,CAAE,MAAM,aAAa,YAAY,MAAM;AACzD,UAAI,UAAW,OAAM,UAAU,YAAY,MAAM;AACjD,eAAS,KAAK,EAAE,MAAM,IAAI,MAAM,OAAO,WAAW,UAAU,CAAC;AAAA,IAC/D,SAAS,OAAO;AACd,eAAS,KAAK,EAAE,MAAM,IAAI,OAAO,MAAM,CAAC;AAAA,IAC1C;AAAA,EACF;AACA,SAAO;AACT;;;ADjFA,OAAOC,WAAU;AAgDjB,eAAe,sBAAsB,WAAyC;AAC5E,SAAO,uBAAuB,mBAAmB,SAAS,CAAC;AAC7D;AAUA,eAAe,kBAAkB,QAAuD;AACtF,QAAM,EAAE,iBAAiB,eAAe,WAAW,WAAW,UAAU,IAAI;AAE5E,MAAI,iBAAiB;AACnB,WAAO;AAAA,EACT;AAKA,MAAI,eAAe;AACjB,UAAM,aAAa,cAAc,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI;AACzD,YAAQ,6BAA6B,WAAW,KAAK,IAAI,CAAC,EAAE;AAC5D,WAAO;AAAA,EACT;AAEA,MAAI,WAAW;AACb,UAAM,QAAQ,UAAqB,SAAS;AAC5C,YAAQ,2CAA2C,MAAM,KAAK,IAAI,CAAC,EAAE;AACrE,WAAO;AAAA,EACT;AAEA,SAAO,sBAAsB,SAAS;AACxC;AAGA,SAAS,qBACP,UACA,eACuB;AACvB,QAAM,CAAC,WAAW,cAAc,IAAIC;AAAA,IAClC;AAAA,IACA,CAAC,YAAiE,QAAQ;AAAA,EAC5E;AACA,YAAU;AAAA,IAAQ,CAAC,YACjB;AAAA,MACE,KAAK,QAAQ,YAAY,YAAY,WAAW,KAAK,QAAQ,IAAI,KAAK,QAAQ,KAAK,OAAO,QAAQ,SAAS;AAAA,IAC7G;AAAA,EACF;AACA,SAAO;AAAA,IACL,UAAU,UAAU,IAAI,CAAC,YAAY,QAAQ,IAAI;AAAA,IACjD,WAAW,UAAU,OAAO,CAAC,YAAY,QAAQ,SAAS,EAAE,IAAI,CAAC,YAAY,QAAQ,IAAI;AAAA,IACzF,QAAQ,eAAe,IAAI,CAAC,YAAY,QAAQ,IAAI;AAAA,IACpD,UAAU;AAAA,MACR,GAAG;AAAA,MACH,GAAG,eAAe;AAAA,QAChB,CAAC,YAAY,qBAAqB,QAAQ,IAAI,KAAK,gBAAgB,QAAQ,KAAK,CAAC;AAAA,MACnF;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,sBAAsB,QAAsC;AAC1E,QAAM,cAAc,4BAA4B,OAAO,MAAM;AAC7D,QAAM,eAAe,OAAO,OAAO,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ;AAC5D,QAAM,eAAe,OAAO,OAAO,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ;AAI5D,QAAM,gBACJ,OAAO,UAAU,SACb,CAAC,IACD;AAAA,IACE,OAAO,OAAO;AAAA,MACZ,aAAa,OAAO,KAAK,EAAE,IAAI,CAAC,CAACC,YAAW,UAAU,MAAM;AAAA,QAC1DA;AAAA,QACA,OAAO;AAAA,UACL,aAAa,UAAU,EAAE,IAAI,CAAC,CAAC,UAAU,WAAW,MAAM;AAAA,YACxD;AAAA,YACA,YAAY,OAAO,CAAC,MAAM,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC;AAAA,UAClD,CAAC;AAAA,QACH;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEN,SAAO,EAAE,GAAG,QAAQ,QAAQ,cAAc,QAAQ,cAAc,GAAG,cAAc;AACnF;AAEA,eAAsB,gBACpB,SACgC;AAChC,QAAM,EAAE,WAAW,YAAY,QAAQ,gBAAgB,YAAY,UAAU,IAAI;AAEjF,QAAM,YAAY,cAAc;AAChC,QAAM,eAAe,MAAM,kBAAkB,SAAS;AACtD,QAAM,gBAAgB,cAAc,UAAU;AAG9C,QAAM,iBAAiB,gBAAgB,sBAAsB,aAAa,IAAI;AAE9E,QAAM,gBAAgB,MAAM,cAAc,UAAU;AACpD,QAAM,gBAAgB,aAAa,MAAM,kBAAkB,UAAU,IAAI,CAAC;AAG1E,QAAM,YAAyD;AAAA,IAC7D,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AAEA,QAAM,aAAa,MAAM,kBAAkB;AAAA,IACzC,GAAI,QAAQ,WAAW,UAAa,EAAE,iBAAiB,QAAQ,OAAO;AAAA,IACtE,eAAe;AAAA,IACf;AAAA,IACA,GAAI,cAAc,UAAa,EAAE,UAAU;AAAA,IAC3C;AAAA,EACF,CAAC;AAED,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO,EAAE,UAAU,CAAC,GAAG,WAAW,CAAC,GAAG,QAAQ,CAAC,GAAG,UAAU,CAAC,8BAA8B,EAAE;AAAA,EAC/F;AAEA,UAAQ,eAAe,WAAW,MAAM,cAAc,aAAa,SAAS,EAAE;AAG9E,QAAM,eACJ,kBAAmB,MAAM,wBAAwB,cAAc,SAAS;AAE1E,QAAM,kBAAkB,iBAAiB,mBAAmB,gBAAgB,SAAS,IAAI,CAAC;AAQ1F,QAAM,CAAC,aAAa,aAAa,IAAID;AAAA,IAAU;AAAA,IAAY,CAAC,SAC1D,QAAQ,gBAAgB,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,EAClD;AACA,QAAM,kBAAkB,cAAc;AAAA,IACpC,CAAC,SAAS,UAAU,IAAI;AAAA,EAC1B;AACA,QAAM,eAAe;AAAA,IACnB,YAAY,IAAI,CAAC,SAAS,CAAC,MAAM,gBAAgB,IAAI,KAAK,CAAC,CAAC,CAAC;AAAA,EAC/D;AAEA,QAAM,gBAA+B;AAAA,IACnC,MAAM,gBAAgB,QAAQE,MAAK,SAAS,SAAS;AAAA,IACrD,aAAa,gBAAgB,eAAe;AAAA,IAC5C,QAAQ;AAAA,EACV;AAEA,QAAM,SAAS,MAAM,mBAAmB,UAAU;AAClD,QAAM,iBAAiB,MAAM,cAAc,WAAW,cAAc,eAAe,UAAU;AAE7F,QAAM,YAAY,aAAa,mBAAmB,SAAS;AAC3D,QAAM,UAAU,SAAS;AAEzB,QAAM,WAAW,MAAM,2BAA2B;AAAA,IAChD;AAAA,IACA;AAAA,IACA;AAAA,IACA,kBAAkB;AAAA,IAClB,GAAI,QAAQ,kBAAkB,UAAa,EAAE,eAAe,QAAQ,cAAc;AAAA,EACpF,CAAC;AACD,SAAO,qBAAqB,UAAU,eAAe;AACvD;;;AG3NA,OAAOC,WAAU;AA4CjB,IAAM,wBAAwB;AAE9B,SAAS,sBAAsB,SAAwC;AACrE,QAAM,MAAM,mBAAmB,OAAO;AACtC,MAAI,CAAC,KAAK;AACR,WAAO,EAAE,IAAI,OAAO,QAAQ,sBAAsB;AAAA,EACpD;AAEA,QAAM,SAAS,iCAAiC,UAAU,GAAG;AAC7D,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,EAAE,IAAI,OAAO,QAAQ,gBAAgB,OAAO,MAAM,MAAM,EAAE;AAAA,EACnE;AAEA,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,aAAa,EAAE,MAAM,OAAO,KAAK,MAAM,aAAa,OAAO,KAAK,YAAY;AAAA,EAC9E;AACF;AAEA,eAAsB,mBACpB,SAC8B;AAC9B,QAAM,EAAE,WAAW,UAAU,IAAI;AACjC,QAAM,WAAWC,MAAK,SAAS,SAAS;AAExC,QAAM,UAAU,MAAM,SAAS,SAAS;AACxC,QAAM,SAAS,sBAAsB,OAAO;AAE5C,MAAI,CAAC,OAAO,IAAI;AACd,UAAM,IAAI;AAAA,MACR,UAAU,QAAQ,8CAA8C,OAAO,MAAM,WAClE,SAAS;AAAA,IACtB;AAAA,EACF;AAEA,QAAMC,aAAY,OAAO,YAAY;AAErC,UAAQ,2BAA2BA,UAAS,SAAS,SAAS,EAAE;AAEhE,QAAM,YAAYD,MAAK,KAAK,WAAW,SAASC,UAAS,EAAE;AAC3D,QAAM,YAAYD,MAAK,KAAK,WAAW,QAAQ;AAE/C,QAAM,UAAU,SAAS;AACzB,QAAM,UAAU,SAAS;AAEzB,QAAM,UAAU,kBAAkB,OAAO;AACzC,QAAM,EAAE,SAAS,YAAY,IAAI,MAAM;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,WAAW,4BAA4B;AAAA,IAC3C,WAAAC;AAAA,IACA,aAAa,OAAO,YAAY;AAAA,IAChC;AAAA,EACF,CAAC;AAED,QAAM,oBAAoB,WAAW,QAAQ;AAE7C,QAAM,iBAAiB,WAAW,aAAa,qBAAqB;AAEpE,UAAQ,2BAA2BA,UAAS,MAAM,OAAO,GAAG;AAE5D,QAAM,KAAK,WAAWD,MAAK,KAAK,WAAW,GAAGC,UAAS,KAAK,CAAC;AAC7D,UAAQ,kBAAkB,QAAQ,cAAcA,UAAS,KAAK;AAE9D,SAAO;AAAA,IACL,YAAY;AAAA,IACZ;AAAA,IACA,WAAAA;AAAA,EACF;AACF;AAEA,eAAsB,uBACpB,WACA,WACgC;AAChC,QAAM,UAAiC,CAAC;AAExC,QAAM,eAAe,MAAM,iBAAiB,SAAS;AAErD,aAAW,aAAa,cAAc;AACpC,UAAM,YAAYD,MAAK,KAAK,WAAW,SAAS;AAEhD,QAAI;AACF,YAAM,SAAS,MAAM,mBAAmB;AAAA,QACtC;AAAA,QACA;AAAA,MACF,CAAC;AACD,cAAQ,KAAK,MAAM;AACnB,UAAI,gBAAgB,OAAO,SAAS,EAAE;AAAA,IACxC,SAAS,OAAO;AACd,YAAM,eAAe,gBAAgB,KAAK;AAC1C,WAAK,iCAAiC,SAAS,MAAM,YAAY,EAAE;AAAA,IACrE;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,6BAA6B,SAAsC;AACjF,MAAI;AAAA,WAAc,QAAQ,MAAM,iBAAiB;AACjD,aAAW,UAAU,SAAS;AAC5B,QAAI,aAAa,OAAO,SAAS,MAAM,OAAO,SAAS,OAAO,GAAG;AAAA,EACnE;AACF;","names":["path","path","path","path","partition","path","path","path","path","path","partition","agentName","path","path","path","agentName"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
MIN_TERMINAL_SIZE
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-UITEKY2R.js";
|
|
5
5
|
|
|
6
6
|
// src/cli/utils/terminal.ts
|
|
7
7
|
function clearTerminalScreen() {
|
|
@@ -20,4 +20,4 @@ export {
|
|
|
20
20
|
isTerminalLargeEnough,
|
|
21
21
|
formatTerminalTooSmallMessage
|
|
22
22
|
};
|
|
23
|
-
//# sourceMappingURL=chunk-
|
|
23
|
+
//# sourceMappingURL=chunk-PHCPUQVR.js.map
|