agents-inc 0.164.0 → 0.166.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 +63 -0
- package/README.md +8 -9
- package/dist/{chunk-X4SSJZLY.js → chunk-25MPBIK3.js} +12 -261
- package/dist/chunk-25MPBIK3.js.map +1 -0
- package/dist/{chunk-LT5GXEB2.js → chunk-2VUYFTUB.js} +8 -7
- package/dist/chunk-2VUYFTUB.js.map +1 -0
- package/dist/chunk-4AAOOAIN.js +49 -0
- package/dist/chunk-4AAOOAIN.js.map +1 -0
- package/dist/{chunk-ARYNOWKF.js → chunk-4NDBUJHK.js} +8 -8
- package/dist/{chunk-S63LXWMC.js → chunk-6L75SQZU.js} +2 -2
- package/dist/{chunk-7REKOTKG.js → chunk-6LF4CQBY.js} +3 -3
- package/dist/{chunk-K5ITEA3I.js → chunk-7JNJ52CD.js} +34 -17
- package/dist/chunk-7JNJ52CD.js.map +1 -0
- package/dist/{chunk-XPDVAJDH.js → chunk-A4KDXNOT.js} +3519 -1568
- package/dist/chunk-A4KDXNOT.js.map +1 -0
- package/dist/{chunk-XHPWTL4I.js → chunk-DAIEQJIF.js} +3 -3
- package/dist/{chunk-UITEKY2R.js → chunk-ENGYJCTF.js} +28 -4
- package/dist/chunk-ENGYJCTF.js.map +1 -0
- package/dist/{chunk-G2JJ5BO5.js → chunk-G4JK7WVO.js} +336 -140
- package/dist/chunk-G4JK7WVO.js.map +1 -0
- package/dist/{chunk-X37UYIE3.js → chunk-G6UREQ4V.js} +436 -739
- package/dist/chunk-G6UREQ4V.js.map +1 -0
- package/dist/chunk-GE3WKJ6Q.js +375 -0
- package/dist/chunk-GE3WKJ6Q.js.map +1 -0
- package/dist/{chunk-RGYDFBCT.js → chunk-HHIYT3PI.js} +5 -5
- package/dist/{chunk-2CQNPLVF.js → chunk-HWEKHVLE.js} +63 -42
- package/dist/chunk-HWEKHVLE.js.map +1 -0
- package/dist/{chunk-XVAQG2CV.js → chunk-JOEA52NR.js} +10 -8
- package/dist/chunk-JOEA52NR.js.map +1 -0
- package/dist/{chunk-3WVH2CTK.js → chunk-JQRJQ4SS.js} +15 -8
- package/dist/chunk-JQRJQ4SS.js.map +1 -0
- package/dist/{chunk-DSL66I4N.js → chunk-LFWLEDUG.js} +6 -6
- package/dist/{chunk-B3Y3QMWI.js → chunk-MAWNVT2C.js} +4 -4
- package/dist/{chunk-Q4IRRVXK.js → chunk-MPTNC32T.js} +3 -3
- package/dist/chunk-NBXXFIIW.js +73 -0
- package/dist/chunk-NBXXFIIW.js.map +1 -0
- package/dist/{chunk-B6FSLXYN.js → chunk-PMJWD27C.js} +3 -3
- package/dist/{chunk-XATLUKXK.js → chunk-PNB3524H.js} +6 -6
- package/dist/chunk-PXWG7KFO.js +39 -0
- package/dist/chunk-PXWG7KFO.js.map +1 -0
- package/dist/{chunk-4VL3CEOS.js → chunk-QHDPLLK6.js} +3 -3
- package/dist/{chunk-AOTCIUGX.js → chunk-RAHSOJQ2.js} +2 -2
- package/dist/{chunk-PHCPUQVR.js → chunk-RZDXDMT6.js} +2 -2
- package/dist/{chunk-6MV4JOCL.js → chunk-SAYZWCH6.js} +2 -2
- package/dist/{chunk-URXIQE7I.js → chunk-SCOQ34YM.js} +2 -2
- package/dist/{chunk-NQXO4LR3.js → chunk-SXVHSOTH.js} +16 -11
- package/dist/chunk-SXVHSOTH.js.map +1 -0
- package/dist/{chunk-QZX7SYKU.js → chunk-T6UWJAB3.js} +2 -2
- package/dist/{chunk-ZVXGW2IC.js → chunk-TODCQFRB.js} +4 -6
- package/dist/chunk-TODCQFRB.js.map +1 -0
- package/dist/{chunk-YRS3QZP2.js → chunk-TTY6DPJN.js} +3 -3
- package/dist/{chunk-QGUP3QJF.js → chunk-TZ2YJJKK.js} +22 -18
- package/dist/{chunk-QGUP3QJF.js.map → chunk-TZ2YJJKK.js.map} +1 -1
- package/dist/chunk-V3I7VQ7N.js +356 -0
- package/dist/chunk-V3I7VQ7N.js.map +1 -0
- package/dist/{chunk-AVK2HEKB.js → chunk-V5WXIM2F.js} +2 -6
- package/dist/{chunk-AVK2HEKB.js.map → chunk-V5WXIM2F.js.map} +1 -1
- package/dist/{chunk-NKGYKOB7.js → chunk-VAPTVR3J.js} +7 -8
- package/dist/chunk-VAPTVR3J.js.map +1 -0
- package/dist/chunk-VRXX4D6K.js +31 -0
- package/dist/chunk-VRXX4D6K.js.map +1 -0
- package/dist/{chunk-ABAZMMG4.js → chunk-WVUDLKIO.js} +2 -2
- package/dist/{chunk-ECURHW3T.js → chunk-WWIFNPJG.js} +13 -12
- package/dist/chunk-WWIFNPJG.js.map +1 -0
- package/dist/{chunk-J27W6TXS.js → chunk-XQHZPINL.js} +8 -4
- package/dist/chunk-XQHZPINL.js.map +1 -0
- package/dist/{chunk-V5GLL2JB.js → chunk-XZEVWPX6.js} +7 -7
- package/dist/chunk-Y3VIRVVE.js +932 -0
- package/dist/chunk-Y3VIRVVE.js.map +1 -0
- package/dist/{chunk-NTF4UXGK.js → chunk-Y47EV74W.js} +73 -30
- package/dist/chunk-Y47EV74W.js.map +1 -0
- package/dist/chunk-ZR4YPKXQ.js +159 -0
- package/dist/chunk-ZR4YPKXQ.js.map +1 -0
- package/dist/chunk-ZXKBERQU.js +250 -0
- package/dist/chunk-ZXKBERQU.js.map +1 -0
- package/dist/commands/build/marketplace.js +17 -17
- package/dist/commands/build/marketplace.js.map +1 -1
- package/dist/commands/build/plugins.js +11 -9
- package/dist/commands/build/plugins.js.map +1 -1
- package/dist/commands/compile.js +105 -27
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/doctor.js +309 -171
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +503 -314
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +40 -23
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/init.js +44 -40
- package/dist/commands/list.js +44 -10
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/new/marketplace.js +13 -10
- package/dist/commands/new/marketplace.js.map +1 -1
- package/dist/commands/search.js +12 -10
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/share.js +102 -15
- package/dist/commands/share.js.map +1 -1
- package/dist/commands/uninstall.js +231 -103
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +49 -20
- package/dist/commands/update.js.map +1 -1
- package/dist/components/common/prompt-confirm.js +1 -1
- package/dist/components/common/removal-plan-confirm.js +2 -2
- package/dist/components/common/select-list.js +3 -3
- package/dist/components/common/spinner.js +6 -3
- package/dist/components/wizard/category-grid.js +5 -5
- 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 +29 -29
- 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 +6 -6
- package/dist/components/wizard/stack-selection.js +8 -8
- package/dist/components/wizard/step-agents.js +8 -8
- package/dist/components/wizard/step-build.js +8 -8
- package/dist/components/wizard/step-confirm.js +9 -9
- package/dist/components/wizard/step-sources.js +9 -9
- package/dist/components/wizard/step-stack.js +9 -9
- 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 +27 -27
- package/dist/hooks/init.js +69 -43
- package/dist/hooks/init.js.map +1 -1
- package/dist/load-agent-defs-3C27ENC7.js +14 -0
- package/dist/recompile-project-agents-DGNBCU3N.js +18 -0
- package/dist/{source-loader-GRBVNRAW.js → source-loader-7KZ3MD5O.js} +6 -4
- package/dist/src/agents/_templates/agent-body.liquid +55 -0
- package/dist/src/agents/_templates/agent.liquid +1 -55
- package/dist/src/agents/meta/agent-summoner/output.md +1 -1
- package/dist/src/agents/meta/agent-summoner/playbook.md +15 -7
- package/dist/stores/wizard-store.js +4 -4
- package/package.json +10 -9
- package/src/agents/_templates/agent-body.liquid +55 -0
- package/src/agents/_templates/agent.liquid +1 -55
- package/src/agents/meta/agent-summoner/output.md +1 -1
- package/src/agents/meta/agent-summoner/playbook.md +15 -7
- package/src/schemas/project-config.schema.json +1 -1
- package/src/schemas/project-source-config.schema.json +1 -1
- package/dist/chunk-2CQNPLVF.js.map +0 -1
- package/dist/chunk-3WVH2CTK.js.map +0 -1
- package/dist/chunk-7ANJQLPJ.js +0 -35
- package/dist/chunk-7ANJQLPJ.js.map +0 -1
- package/dist/chunk-ECURHW3T.js.map +0 -1
- package/dist/chunk-FLW25ORT.js +0 -130
- package/dist/chunk-FLW25ORT.js.map +0 -1
- package/dist/chunk-G2JJ5BO5.js.map +0 -1
- package/dist/chunk-J27W6TXS.js.map +0 -1
- package/dist/chunk-JCPANDNR.js +0 -35
- package/dist/chunk-JCPANDNR.js.map +0 -1
- package/dist/chunk-JIERYE6B.js +0 -480
- package/dist/chunk-JIERYE6B.js.map +0 -1
- package/dist/chunk-JU4ZGJ7A.js +0 -668
- package/dist/chunk-JU4ZGJ7A.js.map +0 -1
- package/dist/chunk-K5ITEA3I.js.map +0 -1
- package/dist/chunk-LT5GXEB2.js.map +0 -1
- package/dist/chunk-NKGYKOB7.js.map +0 -1
- package/dist/chunk-NQXO4LR3.js.map +0 -1
- package/dist/chunk-NTF4UXGK.js.map +0 -1
- package/dist/chunk-UITEKY2R.js.map +0 -1
- package/dist/chunk-X37UYIE3.js.map +0 -1
- package/dist/chunk-X4SSJZLY.js.map +0 -1
- package/dist/chunk-XPDVAJDH.js.map +0 -1
- package/dist/chunk-XVAQG2CV.js.map +0 -1
- package/dist/chunk-ZBPEFQ4G.js +0 -12
- package/dist/chunk-ZBPEFQ4G.js.map +0 -1
- package/dist/chunk-ZVXGW2IC.js.map +0 -1
- package/dist/load-agent-defs-7IM3GBEQ.js +0 -13
- package/dist/recompile-project-agents-VR4NLGOU.js +0 -17
- /package/dist/{chunk-ARYNOWKF.js.map → chunk-4NDBUJHK.js.map} +0 -0
- /package/dist/{chunk-S63LXWMC.js.map → chunk-6L75SQZU.js.map} +0 -0
- /package/dist/{chunk-7REKOTKG.js.map → chunk-6LF4CQBY.js.map} +0 -0
- /package/dist/{chunk-XHPWTL4I.js.map → chunk-DAIEQJIF.js.map} +0 -0
- /package/dist/{chunk-RGYDFBCT.js.map → chunk-HHIYT3PI.js.map} +0 -0
- /package/dist/{chunk-DSL66I4N.js.map → chunk-LFWLEDUG.js.map} +0 -0
- /package/dist/{chunk-B3Y3QMWI.js.map → chunk-MAWNVT2C.js.map} +0 -0
- /package/dist/{chunk-Q4IRRVXK.js.map → chunk-MPTNC32T.js.map} +0 -0
- /package/dist/{chunk-B6FSLXYN.js.map → chunk-PMJWD27C.js.map} +0 -0
- /package/dist/{chunk-XATLUKXK.js.map → chunk-PNB3524H.js.map} +0 -0
- /package/dist/{chunk-4VL3CEOS.js.map → chunk-QHDPLLK6.js.map} +0 -0
- /package/dist/{chunk-AOTCIUGX.js.map → chunk-RAHSOJQ2.js.map} +0 -0
- /package/dist/{chunk-PHCPUQVR.js.map → chunk-RZDXDMT6.js.map} +0 -0
- /package/dist/{chunk-6MV4JOCL.js.map → chunk-SAYZWCH6.js.map} +0 -0
- /package/dist/{chunk-URXIQE7I.js.map → chunk-SCOQ34YM.js.map} +0 -0
- /package/dist/{chunk-QZX7SYKU.js.map → chunk-T6UWJAB3.js.map} +0 -0
- /package/dist/{chunk-YRS3QZP2.js.map → chunk-TTY6DPJN.js.map} +0 -0
- /package/dist/{chunk-ABAZMMG4.js.map → chunk-WVUDLKIO.js.map} +0 -0
- /package/dist/{chunk-V5GLL2JB.js.map → chunk-XZEVWPX6.js.map} +0 -0
- /package/dist/{load-agent-defs-7IM3GBEQ.js.map → load-agent-defs-3C27ENC7.js.map} +0 -0
- /package/dist/{recompile-project-agents-VR4NLGOU.js.map → recompile-project-agents-DGNBCU3N.js.map} +0 -0
- /package/dist/{source-loader-GRBVNRAW.js.map → source-loader-7KZ3MD5O.js.map} +0 -0
|
@@ -12,58 +12,4 @@ tools: {{ agent.tools | join: ", " }}
|
|
|
12
12
|
{% endif %}{% if preloadedSkillIds.size > 0 %}skills:
|
|
13
13
|
{% for skillId in preloadedSkillIds %} - {{ skillId }}
|
|
14
14
|
{% endfor %}{% endif %}---
|
|
15
|
-
|
|
16
|
-
# {{ agent.title }}
|
|
17
|
-
|
|
18
|
-
<role>
|
|
19
|
-
{{ identity }}
|
|
20
|
-
</role>
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
{% render "methodologies/operating-principles" %}
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
{% if criticalRequirementsTop != "" %}<critical_requirements>
|
|
29
|
-
{{ criticalRequirementsTop }}
|
|
30
|
-
</critical_requirements>
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
{% endif %}{{ playbook }}
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
{% if criticalReminders != "" %}<critical_reminders>
|
|
39
|
-
{{ criticalReminders }}
|
|
40
|
-
</critical_reminders>
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
{% endif %}{% if output != "" %}{{ output }}
|
|
45
|
-
|
|
46
|
-
---
|
|
47
|
-
|
|
48
|
-
{% endif %}<system-reminder>
|
|
49
|
-
Compiled by {{ generatorVersion }}.
|
|
50
|
-
|
|
51
|
-
{% if dynamicSkills.size > 0 %}<skill_activation_protocol>
|
|
52
|
-
The skills below are available through the Skill tool. Open a task by naming which of them it
|
|
53
|
-
touches and loading those first — a skill carries the conventions this project expects for its
|
|
54
|
-
area, and its content reaches you only once you invoke it.
|
|
55
|
-
|
|
56
|
-
{% for skill in dynamicSkills %}### {{ skill.id }}
|
|
57
|
-
- Description: {{ skill.description }}
|
|
58
|
-
- Invoke: `skill: "{{ skill.pluginRef | default: skill.id }}"`
|
|
59
|
-
- {{ skill.usage }}
|
|
60
|
-
|
|
61
|
-
{% endfor %}</skill_activation_protocol>
|
|
62
|
-
{% elsif preloadedSkillIds.size > 0 %}<skills_note>
|
|
63
|
-
This agent's skills are preloaded through its frontmatter, so their content is already in context.
|
|
64
|
-
</skills_note>
|
|
65
|
-
{% else %}<skills_note>
|
|
66
|
-
No skills are configured for this agent. The Skill tool is available, so a skill this project adds
|
|
67
|
-
later can be loaded by name.
|
|
68
|
-
</skills_note>
|
|
69
|
-
{% endif %}</system-reminder>
|
|
15
|
+
{% include "agent-body" -%}
|
|
@@ -39,7 +39,7 @@ hooks:
|
|
|
39
39
|
command: <shell command>
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
**Config entry.**
|
|
42
|
+
**Config entry.** `@@SOURCE_FOLDER@@/config.ts` is a TypeScript module, and an agent with source files
|
|
43
43
|
and no entry there compiles into nothing.
|
|
44
44
|
|
|
45
45
|
```ts
|
|
@@ -65,7 +65,7 @@ lands.
|
|
|
65
65
|
|
|
66
66
|
An agent is a directory of at most six files — three every agent owes and three it writes only where
|
|
67
67
|
the role has something for them — and which tree it goes in follows from who it is for. An agent
|
|
68
|
-
authored for a consuming project goes to that project's
|
|
68
|
+
authored for a consuming project goes to that project's `@@SOURCE_FOLDER@@/agents/{category}/{agent-name}/`,
|
|
69
69
|
where `loadProjectAgents` reads it at runtime. An agent authored for this product goes to
|
|
70
70
|
`packages/cli/src/agents/{category}/{agent-name}/`, the bundled tree every agent this CLI ships
|
|
71
71
|
lives in, and then takes the generate step the create workflow names.
|
|
@@ -87,6 +87,14 @@ agent has none of its own.
|
|
|
87
87
|
Where that column names a wrapper, the source file leaves it out; writing it there produces a
|
|
88
88
|
doubled tag in the compiled output.
|
|
89
89
|
|
|
90
|
+
**A partial is prose and nothing evaluates it.** What you write reaches the compiled agent byte for
|
|
91
|
+
byte, so `{{ … }}`, `{% … %}` and the `${{ … }}` of a GitHub Actions example are text rather than
|
|
92
|
+
template syntax. The one exception is `\@@SOURCE_FOLDER@@`, which the compile step replaces with the
|
|
93
|
+
source folder the install being compiled for actually uses — write it wherever an instruction has to
|
|
94
|
+
name that folder, and nowhere else. **A backslash in front of it names the token instead of asking
|
|
95
|
+
for the folder**, which is how the sentence you are reading spells it: write `\\@@SOURCE_FOLDER@@`
|
|
96
|
+
wherever a partial teaches the token rather than uses it.
|
|
97
|
+
|
|
90
98
|
Four tags the source files write themselves have a fixed home, which every agent in the tree
|
|
91
99
|
follows: `<domain_scope>` in `identity.md`, `<self_correction_triggers>` in
|
|
92
100
|
`critical-requirements.md`, `<post_action_reflection>` in `critical-reminders.md`, and
|
|
@@ -139,15 +147,15 @@ provenance marker an HTML comment the compile step stamps
|
|
|
139
147
|
to fill a slot fills with padding, and padding is what the reader pays for on every invocation.
|
|
140
148
|
Keep each file to its own job: the playbook is the process, `output.md` is the shape, and
|
|
141
149
|
neither repeats the other.
|
|
142
|
-
5. **Register the agent in the config** — `
|
|
143
|
-
working tree,
|
|
144
|
-
which is where its skills come from.
|
|
150
|
+
5. **Register the agent in the config** — `config.ts` in `packages/cli`'s own source folder in the
|
|
151
|
+
`agents-inc` working tree, whichever layout that checkout is on; `@@SOURCE_FOLDER@@/config.ts`
|
|
152
|
+
in a project that installed the CLI — and give it a stack, which is where its skills come from.
|
|
145
153
|
6. **Where the agent went into this CLI's own `packages/cli/src/agents/` tree, run
|
|
146
154
|
`bun run generate` from `packages/cli`.** The
|
|
147
155
|
`AgentName` union is generated from `packages/cli/src/agents/*/*/metadata.yaml` by
|
|
148
156
|
`packages/cli/scripts/generate-source-types.ts`, and the vendored catalogue is generated beside it — so until
|
|
149
157
|
that runs, the new name is not a member of the union the config is typed against and the compile
|
|
150
|
-
has nothing to resolve. An agent authored into a project's own
|
|
158
|
+
has nothing to resolve. An agent authored into a project's own `@@SOURCE_FOLDER@@/agents/` skips this
|
|
151
159
|
step: those are read at runtime rather than generated into a union.
|
|
152
160
|
7. **Compile and read the result.** Run `npx agents-inc compile`, open the compiled file, and check
|
|
153
161
|
the frontmatter, the section order, and that nothing in the body repeats what the template
|
|
@@ -201,7 +209,7 @@ fixer, and a reviewer that repairs what it finds leaves a diff where a finding s
|
|
|
201
209
|
|
|
202
210
|
**Model and effort follow the work's difficulty rather than its importance.** A mechanical role — a
|
|
203
211
|
sweep, a listing, a file-shaped report — runs well on a smaller model and a lower effort. Both
|
|
204
|
-
fields can be overridden per project in
|
|
212
|
+
fields can be overridden per project in `@@SOURCE_FOLDER@@/config.ts`, so the value in `metadata.yaml` is
|
|
205
213
|
the default rather than the last word.
|
|
206
214
|
|
|
207
215
|
**`experimental.cacheTtl` decides how long this agent's prompt cache lives.** A compiled agent's
|
|
@@ -239,7 +247,7 @@ completion checks declares `Stop` specifically. It has to declare an actual hook
|
|
|
239
247
|
## Skills
|
|
240
248
|
|
|
241
249
|
**An agent's skills come from the project's stack, not from its own metadata.**
|
|
242
|
-
|
|
250
|
+
`@@SOURCE_FOLDER@@/config.ts` maps each agent to skill ids by category, and the compile step splits them
|
|
243
251
|
in two: a skill marked `preloaded: true` is listed in the compiled frontmatter and its content is in
|
|
244
252
|
context from the first token, while every other skill is named in the trailing `<system-reminder>`
|
|
245
253
|
for the agent to load through the `Skill` tool when a task calls for it.
|
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
hydrateWizardStore,
|
|
8
8
|
showWarningsAsToast,
|
|
9
9
|
useWizardStore
|
|
10
|
-
} from "../chunk-
|
|
11
|
-
import "../chunk-
|
|
12
|
-
import "../chunk-
|
|
13
|
-
import "../chunk-
|
|
10
|
+
} from "../chunk-7JNJ52CD.js";
|
|
11
|
+
import "../chunk-A4KDXNOT.js";
|
|
12
|
+
import "../chunk-V5WXIM2F.js";
|
|
13
|
+
import "../chunk-ENGYJCTF.js";
|
|
14
14
|
import "../chunk-OI2H6M5I.js";
|
|
15
15
|
export {
|
|
16
16
|
DOMAIN_AGENTS,
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agents-inc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.166.0",
|
|
4
4
|
"description": "CLI for managing Agents Inc. skills, stacks, and agents for Claude Code",
|
|
5
|
-
"//generate": "The write path for all
|
|
5
|
+
"//generate": "The write path for all four generators, in dependency order: generate:types reads the skills marketplace and writes src/cli/types/generated/, then generate:schemas copies SKILL_SLUGS and CATEGORIES out of it into metadata.schema.json's enums, then generate:matrix vendors the same directory into packages/matrix, then generate:compile vendors this package's own src/agents/ partials and templates into packages/compile. A marketplace change drifts the first three, and .github/workflows/regenerate-catalog.yml runs those three step by step; generate:compile is not on that chain, because an agent-partial edit drifts it and a marketplace change does not. It replaces the write path only: the :check variants stay separate because CI deliberately runs different subsets of them in different jobs.",
|
|
6
6
|
"//no-shared-vitest-config": "A three-project suite — unit, integration and commands, each with its own include and the retry that separates them — behind one root config that also carries vitest.setup.ts, disableConsoleIntercept for @oclif/test and ink-testing-library, and its own timeouts. @workspace/vitest-config is a single-project node config that turns globals off, which this suite needs on, so merging it in would contradict as much as it contributed. e2e/vitest.config.ts stands under the same decision. Read by scripts/check-shared-vitest-config.ts in packages/cli.",
|
|
7
|
-
"//test:smoke": "The second half of e2e/vitest.config.ts, which is now two named projects over one tree: `test:e2e` runs `*.e2e.test.ts` and this runs `*.smoke.test.ts`. Before this pair existed no command ran the smoke files at all — the old single `include` excluded them, vitest has no `--include` flag, and reaching them took a hand-written config nobody had.
|
|
7
|
+
"//test:smoke": "The second half of e2e/vitest.config.ts, which is now two named projects over one tree: `test:e2e` runs `*.e2e.test.ts` and this runs `*.smoke.test.ts`. Before this pair existed no command ran the smoke files at all — the old single `include` excluded them, vitest has no `--include` flag, and reaching them took a hand-written config nobody had. They sat outside every gate for months and rotted exactly as you would expect: a marketplace fixture the Claude CLI has always rejected sat under a spec named 'should add a marketplace from a local directory source' that had never once added one. It DOES run in CI, and deliberately, and what it proves there now has TWO halves that must not be conflated. The Claude probes are `describe.skipIf(!claudeAvailable)` and the runner has no `claude`, so nothing they assert is coverage of the Claude CLI and must not be reported as such — for that, run them on a machine that has the binary. What a skipped run still proves is that the files collect, import and resolve their helpers, which is the whole of what rotted. The Codex probe does NOT skip: `e2e/smoke/codex-lane.smoke.test.ts` runs the pinned @openai/codex devDependency for real on every runner, so its assertions are coverage. `grep -L 'describe.skipIf' e2e/smoke/*.smoke.test.ts` is which files are which — a bare `skipIf` does not separate them, because codex-lane's docblock says in prose that it carries none.",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"main": "dist/index.js",
|
|
10
10
|
"exports": {
|
|
@@ -132,18 +132,19 @@
|
|
|
132
132
|
"//devDependencies": "@workspace/matrix, @workspace/compile and @workspace/api are private and never installed by a consumer, so all three are devDependencies and tsup bundles them (see `noExternal`). matrix is the one home of the seed wire contract, which src/cli/lib/seed/ used to hand-vendor; compile is the one home of the config-pair and compiled-agent renderers, which the editor's output preview draws with; api is the one home of the typed client both front doors reach the worker through, which src/cli/lib/seed/fetch-seed.ts used to hand-write a fetch for. api pulls `hono/client` in with it, and `hono` is deliberately NOT a dependency here: tsup externalises exactly what `dependencies` names, so leaving it out is what inlines it into the bundle rather than adding a runtime install to a CLI that makes one GET. The cost of that was measured before it was accepted — `find dist -name '*.js' -not -name '*.map' | xargs du -cb | tail -1` is the number. @workspace/api-mocks and msw are a different case and are named in neither `noExternal` nor this rule: nothing under src/cli/ imports them, so they reach no bundle at all — they are the one description of the worker this suite's network mocks are resolved from, and the editor's suites read the same one.",
|
|
133
133
|
"devDependencies": {
|
|
134
134
|
"@eslint/js": "^10",
|
|
135
|
-
"@workspace/eslint-config": "workspace:*",
|
|
136
|
-
"@workspace/api": "workspace:*",
|
|
137
|
-
"@workspace/api-mocks": "workspace:*",
|
|
138
|
-
"@workspace/compile": "workspace:*",
|
|
139
|
-
"@workspace/matrix": "workspace:*",
|
|
140
|
-
"@workspace/typescript-config": "workspace:*",
|
|
141
135
|
"@lydell/node-pty": "^1.2.0-beta.3",
|
|
142
136
|
"@oclif/test": "^4.0.0",
|
|
137
|
+
"@openai/codex": "0.155.1",
|
|
143
138
|
"@types/fs-extra": "^11.0.0",
|
|
144
139
|
"@types/node": "^24",
|
|
145
140
|
"@types/react": "^19",
|
|
146
141
|
"@vitest/coverage-v8": "^4.0.18",
|
|
142
|
+
"@workspace/api": "workspace:*",
|
|
143
|
+
"@workspace/api-mocks": "workspace:*",
|
|
144
|
+
"@workspace/compile": "workspace:*",
|
|
145
|
+
"@workspace/eslint-config": "workspace:*",
|
|
146
|
+
"@workspace/matrix": "workspace:*",
|
|
147
|
+
"@workspace/typescript-config": "workspace:*",
|
|
147
148
|
"@xterm/headless": "^6.0.0",
|
|
148
149
|
"eslint": "^10",
|
|
149
150
|
"eslint-config-prettier": "^10",
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
|
|
2
|
+
# {{ agent.title }}
|
|
3
|
+
|
|
4
|
+
<role>
|
|
5
|
+
{{ identity }}
|
|
6
|
+
</role>
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
{% render "methodologies/operating-principles" %}
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
{% if criticalRequirementsTop != "" %}<critical_requirements>
|
|
15
|
+
{{ criticalRequirementsTop }}
|
|
16
|
+
</critical_requirements>
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
{% endif %}{{ playbook }}
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
{% if criticalReminders != "" %}<critical_reminders>
|
|
25
|
+
{{ criticalReminders }}
|
|
26
|
+
</critical_reminders>
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
{% endif %}{% if output != "" %}{{ output }}
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
{% endif %}<system-reminder>
|
|
35
|
+
Compiled by {{ generatorVersion }}.
|
|
36
|
+
|
|
37
|
+
{% if dynamicSkills.size > 0 %}<skill_activation_protocol>
|
|
38
|
+
The skills below are available through the Skill tool. Open a task by naming which of them it
|
|
39
|
+
touches and loading those first — a skill carries the conventions this project expects for its
|
|
40
|
+
area, and its content reaches you only once you invoke it.
|
|
41
|
+
|
|
42
|
+
{% for skill in dynamicSkills %}### {{ skill.id }}
|
|
43
|
+
- Description: {{ skill.description }}
|
|
44
|
+
- Invoke: `skill: "{{ skill.pluginRef | default: skill.id }}"`
|
|
45
|
+
- {{ skill.usage }}
|
|
46
|
+
|
|
47
|
+
{% endfor %}</skill_activation_protocol>
|
|
48
|
+
{% elsif preloadedSkillIds.size > 0 %}<skills_note>
|
|
49
|
+
This agent's skills are preloaded through its frontmatter, so their content is already in context.
|
|
50
|
+
</skills_note>
|
|
51
|
+
{% else %}<skills_note>
|
|
52
|
+
No skills are configured for this agent. The Skill tool is available, so a skill this project adds
|
|
53
|
+
later can be loaded by name.
|
|
54
|
+
</skills_note>
|
|
55
|
+
{% endif %}</system-reminder>
|
|
@@ -12,58 +12,4 @@ tools: {{ agent.tools | join: ", " }}
|
|
|
12
12
|
{% endif %}{% if preloadedSkillIds.size > 0 %}skills:
|
|
13
13
|
{% for skillId in preloadedSkillIds %} - {{ skillId }}
|
|
14
14
|
{% endfor %}{% endif %}---
|
|
15
|
-
|
|
16
|
-
# {{ agent.title }}
|
|
17
|
-
|
|
18
|
-
<role>
|
|
19
|
-
{{ identity }}
|
|
20
|
-
</role>
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
{% render "methodologies/operating-principles" %}
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
{% if criticalRequirementsTop != "" %}<critical_requirements>
|
|
29
|
-
{{ criticalRequirementsTop }}
|
|
30
|
-
</critical_requirements>
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
{% endif %}{{ playbook }}
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
{% if criticalReminders != "" %}<critical_reminders>
|
|
39
|
-
{{ criticalReminders }}
|
|
40
|
-
</critical_reminders>
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
{% endif %}{% if output != "" %}{{ output }}
|
|
45
|
-
|
|
46
|
-
---
|
|
47
|
-
|
|
48
|
-
{% endif %}<system-reminder>
|
|
49
|
-
Compiled by {{ generatorVersion }}.
|
|
50
|
-
|
|
51
|
-
{% if dynamicSkills.size > 0 %}<skill_activation_protocol>
|
|
52
|
-
The skills below are available through the Skill tool. Open a task by naming which of them it
|
|
53
|
-
touches and loading those first — a skill carries the conventions this project expects for its
|
|
54
|
-
area, and its content reaches you only once you invoke it.
|
|
55
|
-
|
|
56
|
-
{% for skill in dynamicSkills %}### {{ skill.id }}
|
|
57
|
-
- Description: {{ skill.description }}
|
|
58
|
-
- Invoke: `skill: "{{ skill.pluginRef | default: skill.id }}"`
|
|
59
|
-
- {{ skill.usage }}
|
|
60
|
-
|
|
61
|
-
{% endfor %}</skill_activation_protocol>
|
|
62
|
-
{% elsif preloadedSkillIds.size > 0 %}<skills_note>
|
|
63
|
-
This agent's skills are preloaded through its frontmatter, so their content is already in context.
|
|
64
|
-
</skills_note>
|
|
65
|
-
{% else %}<skills_note>
|
|
66
|
-
No skills are configured for this agent. The Skill tool is available, so a skill this project adds
|
|
67
|
-
later can be loaded by name.
|
|
68
|
-
</skills_note>
|
|
69
|
-
{% endif %}</system-reminder>
|
|
15
|
+
{% include "agent-body" -%}
|
|
@@ -39,7 +39,7 @@ hooks:
|
|
|
39
39
|
command: <shell command>
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
**Config entry.**
|
|
42
|
+
**Config entry.** `@@SOURCE_FOLDER@@/config.ts` is a TypeScript module, and an agent with source files
|
|
43
43
|
and no entry there compiles into nothing.
|
|
44
44
|
|
|
45
45
|
```ts
|
|
@@ -65,7 +65,7 @@ lands.
|
|
|
65
65
|
|
|
66
66
|
An agent is a directory of at most six files — three every agent owes and three it writes only where
|
|
67
67
|
the role has something for them — and which tree it goes in follows from who it is for. An agent
|
|
68
|
-
authored for a consuming project goes to that project's
|
|
68
|
+
authored for a consuming project goes to that project's `@@SOURCE_FOLDER@@/agents/{category}/{agent-name}/`,
|
|
69
69
|
where `loadProjectAgents` reads it at runtime. An agent authored for this product goes to
|
|
70
70
|
`packages/cli/src/agents/{category}/{agent-name}/`, the bundled tree every agent this CLI ships
|
|
71
71
|
lives in, and then takes the generate step the create workflow names.
|
|
@@ -87,6 +87,14 @@ agent has none of its own.
|
|
|
87
87
|
Where that column names a wrapper, the source file leaves it out; writing it there produces a
|
|
88
88
|
doubled tag in the compiled output.
|
|
89
89
|
|
|
90
|
+
**A partial is prose and nothing evaluates it.** What you write reaches the compiled agent byte for
|
|
91
|
+
byte, so `{{ … }}`, `{% … %}` and the `${{ … }}` of a GitHub Actions example are text rather than
|
|
92
|
+
template syntax. The one exception is `\@@SOURCE_FOLDER@@`, which the compile step replaces with the
|
|
93
|
+
source folder the install being compiled for actually uses — write it wherever an instruction has to
|
|
94
|
+
name that folder, and nowhere else. **A backslash in front of it names the token instead of asking
|
|
95
|
+
for the folder**, which is how the sentence you are reading spells it: write `\\@@SOURCE_FOLDER@@`
|
|
96
|
+
wherever a partial teaches the token rather than uses it.
|
|
97
|
+
|
|
90
98
|
Four tags the source files write themselves have a fixed home, which every agent in the tree
|
|
91
99
|
follows: `<domain_scope>` in `identity.md`, `<self_correction_triggers>` in
|
|
92
100
|
`critical-requirements.md`, `<post_action_reflection>` in `critical-reminders.md`, and
|
|
@@ -139,15 +147,15 @@ provenance marker an HTML comment the compile step stamps
|
|
|
139
147
|
to fill a slot fills with padding, and padding is what the reader pays for on every invocation.
|
|
140
148
|
Keep each file to its own job: the playbook is the process, `output.md` is the shape, and
|
|
141
149
|
neither repeats the other.
|
|
142
|
-
5. **Register the agent in the config** — `
|
|
143
|
-
working tree,
|
|
144
|
-
which is where its skills come from.
|
|
150
|
+
5. **Register the agent in the config** — `config.ts` in `packages/cli`'s own source folder in the
|
|
151
|
+
`agents-inc` working tree, whichever layout that checkout is on; `@@SOURCE_FOLDER@@/config.ts`
|
|
152
|
+
in a project that installed the CLI — and give it a stack, which is where its skills come from.
|
|
145
153
|
6. **Where the agent went into this CLI's own `packages/cli/src/agents/` tree, run
|
|
146
154
|
`bun run generate` from `packages/cli`.** The
|
|
147
155
|
`AgentName` union is generated from `packages/cli/src/agents/*/*/metadata.yaml` by
|
|
148
156
|
`packages/cli/scripts/generate-source-types.ts`, and the vendored catalogue is generated beside it — so until
|
|
149
157
|
that runs, the new name is not a member of the union the config is typed against and the compile
|
|
150
|
-
has nothing to resolve. An agent authored into a project's own
|
|
158
|
+
has nothing to resolve. An agent authored into a project's own `@@SOURCE_FOLDER@@/agents/` skips this
|
|
151
159
|
step: those are read at runtime rather than generated into a union.
|
|
152
160
|
7. **Compile and read the result.** Run `npx agents-inc compile`, open the compiled file, and check
|
|
153
161
|
the frontmatter, the section order, and that nothing in the body repeats what the template
|
|
@@ -201,7 +209,7 @@ fixer, and a reviewer that repairs what it finds leaves a diff where a finding s
|
|
|
201
209
|
|
|
202
210
|
**Model and effort follow the work's difficulty rather than its importance.** A mechanical role — a
|
|
203
211
|
sweep, a listing, a file-shaped report — runs well on a smaller model and a lower effort. Both
|
|
204
|
-
fields can be overridden per project in
|
|
212
|
+
fields can be overridden per project in `@@SOURCE_FOLDER@@/config.ts`, so the value in `metadata.yaml` is
|
|
205
213
|
the default rather than the last word.
|
|
206
214
|
|
|
207
215
|
**`experimental.cacheTtl` decides how long this agent's prompt cache lives.** A compiled agent's
|
|
@@ -239,7 +247,7 @@ completion checks declares `Stop` specifically. It has to declare an actual hook
|
|
|
239
247
|
## Skills
|
|
240
248
|
|
|
241
249
|
**An agent's skills come from the project's stack, not from its own metadata.**
|
|
242
|
-
|
|
250
|
+
`@@SOURCE_FOLDER@@/config.ts` maps each agent to skill ids by category, and the compile step splits them
|
|
243
251
|
in two: a skill marked `preloaded: true` is listed in the compiled frontmatter and its content is in
|
|
244
252
|
context from the first token, while every other skill is named in the trailing `<system-reminder>`
|
|
245
253
|
for the agent to load through the `Skill` tool when a task calls for it.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
3
|
"$id": "schemas/project-config.schema.json",
|
|
4
4
|
"title": "Project Configuration",
|
|
5
|
-
"description": "Schema for .
|
|
5
|
+
"description": "Schema for .agents-inc/<provider>/config.ts consumer project files (name, agents, stack, skills).",
|
|
6
6
|
"$comment": "HAND-MAINTAINED. scripts/generate-json-schemas.ts does NOT emit this file (nor project-source-config.schema.json) — its SCHEMA_ENTRIES list has no entry for either, so `generate:schemas` neither emits nor judges them and writes nothing here. Edit this file by hand and keep it prettier-clean — .ai-docs/reference/features/code-generation.md names the gate that enforces that. Three vocabularies below are copied out of src/cli/types/generated/source-types.ts and drift silently, because no generator and no check re-derives any of them: the stack category enum is the CATEGORIES tuple, verbatim and in that tuple's order; the selectedDomains enum is the DOMAINS tuple; and the skill-id pattern's leading alternation is that same DOMAINS tuple, since a skill id is `<domain>-<category>-<name>`. Re-derive all three whenever a category or domain is added, renamed or removed — a missing domain silently rejects every skill id under it.",
|
|
7
7
|
"type": "object",
|
|
8
8
|
"properties": {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
3
|
"$id": "schemas/project-source-config.schema.json",
|
|
4
4
|
"title": "Project Source Configuration",
|
|
5
|
-
"description": "Schema for .
|
|
5
|
+
"description": "Schema for .agents-inc/config.ts marketplace source configuration files. Provider-neutral, with no <provider> segment: the fields describe the repository's own layout.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"properties": {
|
|
8
8
|
"marketplace": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/lib/operations/project/remove-compiled-agents.ts","../src/cli/lib/operations/project/compile-agents.ts","../src/cli/lib/operations/skills/discover-skills.ts","../src/cli/lib/operations/skills/copy-local-skills.ts","../src/cli/lib/operations/skills/uninstall-plugin-skills.ts","../src/cli/lib/loading/catalogue-seat.ts","../src/cli/lib/operations/project/recompile-project-agents.ts"],"sourcesContent":["import path from \"path\";\nimport { pruneStaleCompiledAgents } from \"../../agents/list-compiled-agents.js\";\nimport { getErrorMessage } from \"../../../utils/errors.js\";\nimport { remove, removeDirIfEmpty } from \"../../../utils/fs.js\";\nimport type { AgentName } from \"../../../types/index.js\";\n\nconst AGENT_FILE_EXTENSION = \".md\";\n\nexport type RemoveCompiledAgentsOptions = {\n /** The scope's `.claude/agents/` directory holding the compiled files. */\n agentsDir: string;\n agents: readonly AgentName[];\n};\n\nexport type PruneCompiledAgentsOptions = {\n agentsDir: string;\n /**\n * The COMPLETE set of agents that belong in `agentsDir` — every other\n * CLI-compiled agent there is stale. Only an authoritative pass can say this.\n */\n keep: ReadonlySet<AgentName>;\n};\n\nexport type RemoveCompiledAgentsResult = {\n /** Agents whose compiled file this call disposed of; an absent file counts. */\n removed: AgentName[];\n /** Agents whose file survived an error, for the caller to report. */\n failed: Array<{ name: AgentName; error: string }>;\n};\n\ntype RemovalOutcome = { name: AgentName; ok: true } | { name: AgentName; ok: false; error: string };\n\n/**\n * Deletes the named agents' compiled `.md` files from `agentsDir`, then takes the\n * directory itself when nothing at all is left in it — the shape `deleteLocalSkill`\n * models for skills.\n *\n * A scope's `.claude/agents/` is an artefact of what it holds, so the removal that\n * empties it owns the tidy and no caller has to remember. An agent with no file on\n * disk is nothing to do rather than an error.\n */\nexport async function removeCompiledAgents(\n options: RemoveCompiledAgentsOptions,\n): Promise<RemoveCompiledAgentsResult> {\n const outcomes = await Promise.all(\n options.agents.map((name) => removeCompiledAgentFile(options.agentsDir, name)),\n );\n await tidyEmptiedAgentsDir(options.agentsDir);\n\n return {\n removed: outcomes.flatMap((outcome) => (outcome.ok ? [outcome.name] : [])),\n failed: outcomes.flatMap((outcome) =>\n outcome.ok ? [] : [{ name: outcome.name, error: outcome.error }],\n ),\n };\n}\n\n/**\n * Deletes every CLI-compiled agent in `agentsDir` outside `keep`, then takes the\n * directory on the same terms as `removeCompiledAgents`.\n *\n * Hand-authored agents are preserved by `pruneStaleCompiledAgents`'s `isAgentName`\n * predicate, so a directory this leaves empty is one nothing at all remains in.\n */\nexport async function pruneCompiledAgents(options: PruneCompiledAgentsOptions): Promise<void> {\n await pruneStaleCompiledAgents(options.agentsDir, options.keep);\n await tidyEmptiedAgentsDir(options.agentsDir);\n}\n\nasync function removeCompiledAgentFile(\n agentsDir: string,\n name: AgentName,\n): Promise<RemovalOutcome> {\n try {\n await remove(path.join(agentsDir, `${name}${AGENT_FILE_EXTENSION}`));\n return { name, ok: true };\n } catch (error) {\n return { name, ok: false, error: getErrorMessage(error) };\n }\n}\n\n/**\n * Emptiness is FILESYSTEM emptiness, never roster emptiness: a hand-authored agent\n * or any user-owned file keeps the directory alive whatever a config says. The\n * agents directory only — `.claude/` above it is uninstall's decision, not a\n * removal path's.\n */\nasync function tidyEmptiedAgentsDir(agentsDir: string): Promise<void> {\n await removeDirIfEmpty(agentsDir);\n}\n","import { pruneCompiledAgents } from \"./remove-compiled-agents.js\";\nimport { recompileAgents } from \"../../agents/index.js\";\nimport { loadProjectConfigFromDir } from \"../../configuration/index.js\";\nimport { buildAgentScopeMap } from \"../../installation/index.js\";\nimport type { AgentName, SkillDefinitionMap, SkillScope } from \"../../../types/index.js\";\n\nexport type CompileAgentsOptions = {\n projectDir: string;\n sourcePath: string;\n pluginDir?: string;\n skills?: SkillDefinitionMap;\n agentScopeMap?: Map<AgentName, SkillScope>;\n agents?: AgentName[];\n /** When set, loads config and filters agents to only those matching this scope. */\n scopeFilter?: SkillScope;\n outputDir?: string;\n};\n\nexport type CompilationResult = {\n compiled: AgentName[];\n /**\n * The subset of `compiled` whose file this pass actually wrote. A pass whose\n * `rewritten` is empty changed nothing on disk, which is exactly what the\n * recompile summary reports and what the count it replaced could not say.\n */\n rewritten: AgentName[];\n failed: AgentName[];\n warnings: string[];\n};\n\n/**\n * Compiles agent markdown files from templates + skill content.\n *\n * Thin wrapper around recompileAgents() that standardizes options.\n * The caller invokes this once (edit, update) or twice with scopeFilter (compile).\n */\nexport async function compileAgents(options: CompileAgentsOptions): Promise<CompilationResult> {\n let resolvedAgents = options.agents;\n let resolvedAgentScopeMap = options.agentScopeMap;\n\n if (options.scopeFilter) {\n const loadedConfig = await loadProjectConfigFromDir(options.projectDir);\n\n // Auto-build agentScopeMap from config if not provided\n if (!resolvedAgentScopeMap && loadedConfig?.config) {\n resolvedAgentScopeMap = buildAgentScopeMap(loadedConfig.config);\n }\n\n const filteredAgents = loadedConfig?.config.agents\n .filter((a) => !a.excluded && a.scope === options.scopeFilter)\n .map((a) => a.name);\n\n if (resolvedAgents && filteredAgents) {\n const filterSet = new Set(filteredAgents);\n resolvedAgents = resolvedAgents.filter((a) => filterSet.has(a));\n } else if (filteredAgents) {\n resolvedAgents = filteredAgents;\n }\n }\n\n const recompileResult = await recompileAgents({\n pluginDir: options.pluginDir ?? options.projectDir,\n sourcePath: options.sourcePath,\n ...(resolvedAgents !== undefined && { agents: resolvedAgents }),\n ...(options.skills !== undefined && { skills: options.skills }),\n projectDir: options.projectDir,\n ...(options.outputDir !== undefined && { outputDir: options.outputDir }),\n ...(resolvedAgentScopeMap !== undefined && { agentScopeMap: resolvedAgentScopeMap }),\n });\n\n await pruneStaleAgentsForPass(options, recompileResult);\n\n return {\n compiled: recompileResult.compiled,\n rewritten: recompileResult.rewritten,\n failed: recompileResult.failed,\n warnings: recompileResult.warnings,\n };\n}\n\n/**\n * Compiled-agent writes are additive, so a deselected or stale agent's `.md`\n * lingers after recompile. An authoritative, scope-UNfiltered pass owns its\n * entire `outputDir` (its resolved roster is the full set for that directory),\n * so it prunes built-in agents no longer compiled there. A scope-FILTERED pass\n * (the hasBoth two-pass compile, or the registered-project recompile)\n * sees only one scope's agents and must never delete another scope's files, so\n * it skips pruning. Removing the stale files and tidying the directory they\n * emptied is one operation's job, not this pass's.\n */\nasync function pruneStaleAgentsForPass(\n options: CompileAgentsOptions,\n recompileResult: CompilationResult,\n): Promise<void> {\n if (options.scopeFilter || !options.outputDir) return;\n\n const compiledForDir = new Set<AgentName>([\n ...recompileResult.compiled,\n ...recompileResult.failed,\n ]);\n await pruneCompiledAgents({ agentsDir: options.outputDir, keep: compiledForDir });\n}\n","import path from \"path\";\nimport { discoverAllPluginSkills } from \"../../plugins/index.js\";\nimport { isHomeDirectory } from \"../../installation/is-home-directory.js\";\n// loadSkillsFromDir lives in loading/ (a leaf) so both this module and\n// plugins/plugin-discovery can share it without an operations↔plugins cycle.\nimport { loadSkillsFromDir, type LoadedSkills } from \"../../loading/index.js\";\nimport { verbose } from \"../../../utils/logger.js\";\nimport { globalInstallRoot, LOCAL_SKILLS_PATH } from \"../../../consts.js\";\nimport { typedEntries, typedKeys } from \"../../../utils/typed-object.js\";\nimport type { UnusableSkillMetadata } from \"../../loading/index.js\";\nimport type { SkillDefinition, SkillDefinitionMap, SkillId } from \"../../../types/index.js\";\n\nexport type DiscoveredSkills = {\n allSkills: SkillDefinitionMap;\n totalSkillCount: number;\n pluginSkillCount: number;\n localSkillCount: number;\n globalPluginSkillCount: number;\n globalLocalSkillCount: number;\n /**\n * Installed skills whose metadata.yaml exists but describes no skill, from either\n * scope. Nothing was loaded for them; `compile` refuses the run over any entry\n * here rather than compile agents around a skill its metadata does not describe.\n */\n unusableMetadata: UnusableSkillMetadata[];\n};\n\n/** The result of a local-skill scan that was not performed. */\nconst NO_LOCAL_SKILLS: LoadedSkills = { skills: {}, unusableMetadata: [] };\n\n/**\n * Discovers local (non-plugin) skills from `<rootDir>/.claude/skills/`. Used for\n * both the project root and the global install root.\n */\nexport async function discoverLocalProjectSkills(rootDir: string): Promise<LoadedSkills> {\n const localSkillsDir = path.join(rootDir, LOCAL_SKILLS_PATH);\n return loadSkillsFromDir(localSkillsDir, {\n pathPrefix: LOCAL_SKILLS_PATH,\n requireMetadata: true,\n });\n}\n\n/** Merges skill maps — later sources take precedence over earlier ones. */\nexport function mergeSkills(...skillSources: SkillDefinitionMap[]): SkillDefinitionMap {\n const merged: SkillDefinitionMap = {};\n\n for (const source of skillSources) {\n for (const [id, skill] of typedEntries<SkillId, SkillDefinition | undefined>(source)) {\n if (skill) {\n merged[id] = skill;\n }\n }\n }\n\n return merged;\n}\n\n/**\n * Discovers all installed skills for a project directory using 4-way merge:\n * 1. Global plugins (from ~/.claude/plugins/)\n * 2. Global local (from ~/.claude/skills/)\n * 3. Project plugins (from <projectDir>/.claude/plugins/)\n * 4. Project local (from <projectDir>/.claude/skills/)\n *\n * Pure function — no user-facing logging. Callers add their own log messages.\n * Uses verbose() for diagnostic output only.\n */\nexport async function discoverInstalledSkills(projectDir: string): Promise<DiscoveredSkills> {\n const isGlobalProject = isHomeDirectory(projectDir);\n\n // 1. Global plugins\n const globalPluginSkills = isGlobalProject\n ? {}\n : await discoverAllPluginSkills(globalInstallRoot());\n const globalPluginSkillCount = typedKeys<SkillId>(globalPluginSkills).length;\n if (globalPluginSkillCount > 0) {\n verbose(` Found ${globalPluginSkillCount} skills from global plugins`);\n }\n\n // 2. Global local skills\n const globalLocal = isGlobalProject\n ? NO_LOCAL_SKILLS\n : await discoverLocalProjectSkills(globalInstallRoot());\n const globalLocalSkillCount = typedKeys<SkillId>(globalLocal.skills).length;\n if (globalLocalSkillCount > 0) {\n verbose(` Found ${globalLocalSkillCount} global local skills from ~/.claude/skills/`);\n }\n\n // 3. Project plugins\n const pluginSkills = await discoverAllPluginSkills(projectDir);\n const pluginSkillCount = typedKeys<SkillId>(pluginSkills).length;\n verbose(` Found ${pluginSkillCount} skills from installed plugins`);\n\n // 4. Project local skills\n const local = await discoverLocalProjectSkills(projectDir);\n const localSkillCount = typedKeys<SkillId>(local.skills).length;\n verbose(` Found ${localSkillCount} local skills from .claude/skills/`);\n\n // Merge: global first, project second — project wins on conflict\n const allSkills = mergeSkills(globalPluginSkills, globalLocal.skills, pluginSkills, local.skills);\n const totalSkillCount = typedKeys<SkillId>(allSkills).length;\n\n return {\n allSkills,\n totalSkillCount,\n pluginSkillCount: globalPluginSkillCount + pluginSkillCount,\n localSkillCount: globalLocalSkillCount + localSkillCount,\n globalPluginSkillCount,\n globalLocalSkillCount,\n unusableMetadata: [...globalLocal.unusableMetadata, ...local.unusableMetadata],\n };\n}\n","import { resolveInstallPaths } from \"../../installation/index.js\";\nimport { copySkillsToLocalFlattened, type CopiedSkill } from \"../../skills/index.js\";\nimport { ensureDir } from \"../../../utils/fs.js\";\nimport type { SkillConfig } from \"../../../types/config.js\";\nimport type { SourceLoadResult } from \"../../loading/source-loader.js\";\n\nexport type SkillCopyResult = {\n projectCopied: CopiedSkill[];\n globalCopied: CopiedSkill[];\n totalCopied: number;\n};\n\n/** Copies one scope's local skills into its skills directory. */\nasync function copyScopedLocalSkills(\n scopeSkills: SkillConfig[],\n skillsDir: string,\n sourceResult: SourceLoadResult,\n): Promise<CopiedSkill[]> {\n if (scopeSkills.length === 0) return [];\n\n await ensureDir(skillsDir);\n\n return copySkillsToLocalFlattened(\n scopeSkills.map((s) => s.id),\n skillsDir,\n sourceResult,\n );\n}\n\n/**\n * Copies local-source skills to their scope-appropriate directories.\n *\n * Splits skills by scope (project vs global), resolves install paths,\n * ensures directories exist, and copies from source.\n */\nexport async function copyLocalSkills(\n skills: SkillConfig[],\n projectDir: string,\n sourceResult: SourceLoadResult,\n): Promise<SkillCopyResult> {\n const projectLocalSkills = skills.filter((s) => s.scope !== \"global\");\n const globalLocalSkills = skills.filter((s) => s.scope === \"global\");\n\n const projectPaths = resolveInstallPaths(projectDir, \"project\");\n const globalPaths = resolveInstallPaths(projectDir, \"global\");\n\n const projectCopied = await copyScopedLocalSkills(\n projectLocalSkills,\n projectPaths.skillsDir,\n sourceResult,\n );\n const globalCopied = await copyScopedLocalSkills(\n globalLocalSkills,\n globalPaths.skillsDir,\n sourceResult,\n );\n\n return {\n projectCopied,\n globalCopied,\n totalCopied: projectCopied.length + globalCopied.length,\n };\n}\n","import { claudePluginUninstall } from \"../../../utils/exec.js\";\nimport { buildMarketplacePluginRef, toClaudePluginScope } from \"../../plugins/index.js\";\nimport { getErrorMessage } from \"../../../utils/errors.js\";\nimport type { SkillId } from \"../../../types/index.js\";\nimport type { SkillConfig } from \"../../../types/config.js\";\n\nexport type PluginUninstallResult = {\n uninstalled: SkillId[];\n failed: Array<{ id: SkillId; error: string }>;\n};\n\n/**\n * Uninstalls skill plugins via the Claude CLI, using scope from old config.\n *\n * Each plugin reference is qualified as `{skillId}@{marketplace}` to match\n * the form used at install time — bare skill IDs will not match the registry.\n */\nexport async function uninstallPluginSkills(\n skillIds: SkillId[],\n oldSkills: SkillConfig[],\n marketplace: string,\n projectDir: string,\n): Promise<PluginUninstallResult> {\n const uninstalled: SkillId[] = [];\n const failed: PluginUninstallResult[\"failed\"] = [];\n\n for (const skillId of skillIds) {\n const oldSkill = oldSkills.find((s) => s.id === skillId);\n const pluginScope = toClaudePluginScope(oldSkill?.scope);\n const pluginRef = buildMarketplacePluginRef(skillId, marketplace);\n try {\n await claudePluginUninstall(pluginRef, pluginScope, projectDir);\n uninstalled.push(skillId);\n } catch (error) {\n failed.push({ id: skillId, error: getErrorMessage(error) });\n }\n }\n\n return { uninstalled, failed };\n}\n","import type { MergedSkillsMatrix } from \"../../types\";\nimport { initializeMatrix, matrix } from \"../matrix/matrix-provider.js\";\nimport { loadSkillsMatrixFromSource } from \"./source-loader.js\";\n\n/**\n * Runs `body` with the skills catalogue seated for `projectDir`, hands it the catalogue\n * that was seated, and puts the caller's own seat back afterwards.\n *\n * A registered project's own local skills, and the skills of the marketplace ITS config\n * names, are in that project's catalogue and in nobody else's. Two things a fan-out does to\n * such a project read a catalogue, and both used to read the TRIGGERING command's:\n *\n * - The RENDER of a compiled agent, which reaches the catalogue through the module-level\n * singleton (`matrix` in `matrix-provider.ts`) that `statedUsageFor` and `liveCategoryOf`\n * in `stacks/stacks-loader.ts` read directly, so no argument reaches it. Rendered against\n * somebody else's seat, each of the project's own skills loses the `usageGuidance` it\n * states and falls back to the per-category placeholder.\n * - The DERIVATION of that project's `config-types.ts` unions, which looks each configured\n * skill's category up in the catalogue (`deriveCategories` / `deriveDomains`). Against\n * somebody else's, a skill only this project's catalogue carries resolves to nothing and\n * its category and domain leave the project's `Category` and `Domain` unions.\n *\n * Both have the same ending: the project's own next `compile` writes the value back from its\n * own catalogue, so the two commands undo each other for as long as they are both run.\n *\n * The catalogue is PASSED to the body as well as seated, so a derivation that can take one as\n * an argument does — a body reading the singleton it just asked to be seated cannot say which\n * seat it got, which is the distinction the whole helper exists to keep. `compile.ts`'s\n * `seatMatrixForPass` returns its catalogue for the same reason.\n *\n * The seat is restored rather than left standing because this is a side trip: the caller has\n * its own pass to finish — `init` and `edit` compile their own agents after the gate returns —\n * and would otherwise render them against the last registered project's catalogue.\n *\n * The load sits outside the `try` deliberately. It seats nothing when it throws, so there is\n * no seat to restore, and a project whose catalogue cannot be loaded is left to the caller's\n * own failure handling rather than silently processed against somebody else's — which is the\n * whole defect this exists to stop. Both callers count such a project as one they could not\n * reach and carry on with the rest.\n */\nexport async function withCatalogueSeatedFor<T>(\n projectDir: string,\n body: (catalogue: MergedSkillsMatrix) => Promise<T>,\n): Promise<T> {\n const callersCatalogue = matrix;\n const { matrix: seated } = await loadSkillsMatrixFromSource({\n projectDir,\n skipExtraSources: true,\n matrixOnly: true,\n });\n try {\n return await body(seated);\n } finally {\n initializeMatrix(callersCatalogue);\n }\n}\n","import { compileAgents, type CompilationResult } from \"./compile-agents.js\";\nimport { loadAgentDefs } from \"./load-agent-defs.js\";\nimport { discoverInstalledSkills } from \"../skills/index.js\";\nimport { resolveInstallPaths } from \"../../installation/index.js\";\nimport { withCatalogueSeatedFor } from \"../../loading/catalogue-seat.js\";\nimport { getErrorMessage } from \"../../../utils/errors.js\";\n\n/**\n * Recompiles the PROJECT-scoped agents of a registered project after a global\n * config change was propagated into that project's `config.ts`.\n *\n * Propagation (`propagateGlobalChangesToProjects`) rewrites a registered\n * project's `config.ts` / `config-types.ts` but never touches its compiled\n * `.claude/agents/*.md`, so the compiled agents keep emitting whatever skill\n * reference form the OLD global data dictated. Run this per propagated project,\n * after propagation, to bring the compiled artifacts back in step.\n *\n * Scope: project only. The global agents were already recompiled by the\n * triggering operation's own pass; repeating a global pass per project would\n * rewrite `~/.claude/agents` once per registered project for no gain.\n *\n * Both inputs a compiled agent's bytes depend on are resolved from THIS\n * project's directory, and neither is inherited from the command that triggered\n * the fan-out: `skills` is passed explicitly, because without it\n * `recompileAgents` falls back to `discoverAllPluginSkills`, which sees plugin\n * skills only and would silently strip every global-local and project-local\n * skill; and the catalogue is seated by {@link withCatalogueSeatedFor}, because\n * the render reads it from a module-level singleton no argument reaches.\n *\n * Agent partials always come from the CLI itself (`getLocalAgentDefinitions`\n * returns `sourcePath: PROJECT_ROOT`), so no per-project marketplace source\n * resolution is needed.\n */\nexport async function recompileRegisteredProjectAgents(\n projectDir: string,\n): Promise<CompilationResult> {\n return withCatalogueSeatedFor(projectDir, async () => {\n const { allSkills } = await discoverInstalledSkills(projectDir);\n const { sourcePath } = await loadAgentDefs();\n\n return compileAgents({\n projectDir,\n sourcePath,\n skills: allSkills,\n scopeFilter: \"project\",\n outputDir: resolveInstallPaths(projectDir, \"project\").agentsDir,\n });\n });\n}\n\nexport type PropagatedRecompileSummary = {\n /** Projects where at least one compiled agent's content actually moved. */\n rewrittenCount: number;\n /**\n * Projects the fan-out reached whose agents all came back byte-identical. They\n * were visited and left alone, which is a different fact from being recompiled\n * and the one the old single count could not tell apart.\n */\n unchangedCount: number;\n failedCount: number;\n /** Per-project warnings in processing order — the caller surfaces them via warn(). */\n warnings: string[];\n};\n\n/**\n * Runs {@link recompileRegisteredProjectAgents} over every propagated project,\n * isolating per-project failures: one project's unreadable config or broken\n * template must not abort the loop or leave the remaining projects stale.\n * Projects are processed sequentially so the collected warnings keep a\n * deterministic per-project order.\n */\nexport async function recompilePropagatedProjectAgents(\n projectDirs: string[],\n): Promise<PropagatedRecompileSummary> {\n let rewrittenCount = 0;\n let unchangedCount = 0;\n let failedCount = 0;\n const warnings: string[] = [];\n\n for (const dir of projectDirs) {\n try {\n const result = await recompileRegisteredProjectAgents(dir);\n if (result.failed.length > 0) {\n failedCount++;\n warnings.push(...result.warnings);\n continue;\n }\n if (result.rewritten.length > 0) rewrittenCount++;\n else unchangedCount++;\n } catch (error) {\n failedCount++;\n warnings.push(`Could not recompile agents in ${dir}: ${getErrorMessage(error)}`);\n }\n }\n\n return { rewrittenCount, unchangedCount, failedCount, warnings };\n}\n"],"mappings":"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","names":["path","path"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/components/wizard/checkbox-grid.tsx"],"sourcesContent":["import { Box, Text, useInput } from \"ink\";\nimport React, { useState } from \"react\";\nimport { CLI_COLORS, UI_SYMBOLS } from \"../../consts.js\";\nimport { useRowScroll } from \"../hooks/use-row-scroll.js\";\nimport { KEY_SPACE } from \"./hotkeys.js\";\n\nexport type CheckboxItem<T extends string = string> = {\n id: T;\n label: string;\n description: string;\n};\n\nexport type CheckboxGridProps<T extends string = string> = {\n subtitle?: string;\n items: CheckboxItem<T>[];\n selectedIds: T[];\n /** Available height in terminal lines for the scrollable viewport. 0 = no constraint. */\n availableHeight?: number;\n onToggle: (id: T) => void;\n onContinue: () => void;\n onBack: () => void;\n /** Message shown when nothing is selected */\n emptyMessage?: string;\n};\n\nexport const CheckboxGrid = <T extends string = string>({\n subtitle,\n items,\n selectedIds,\n availableHeight = 0,\n onToggle,\n onContinue,\n onBack,\n emptyMessage = \"Please select at least one item\",\n}: CheckboxGridProps<T>): React.ReactElement => {\n // Items + continue option at the end\n const totalItems = items.length + 1;\n const [focusedIndex, setFocusedIndex] = useState(0);\n\n useInput((input, key) => {\n if (key.escape) {\n onBack();\n return;\n }\n\n if (key.upArrow || input === \"k\") {\n setFocusedIndex((prev) => (prev <= 0 ? totalItems - 1 : prev - 1));\n return;\n }\n\n if (key.downArrow || input === \"j\") {\n setFocusedIndex((prev) => (prev >= totalItems - 1 ? 0 : prev + 1));\n return;\n }\n\n if (key.return) {\n onContinue();\n return;\n }\n\n if (input === KEY_SPACE) {\n const item = items[focusedIndex];\n if (item) {\n onToggle(item.id);\n }\n }\n });\n\n // The Domains grid clips silently: `useRowScroll` exposes no hidden-line\n // counts and this view renders no `ScrollAffordance`, by owner decision — see\n // the hook's doc comment.\n // When focus is on continue (past items), scroll to show last items\n const effectiveRow = focusedIndex >= items.length ? items.length - 1 : focusedIndex;\n const { scrollEnabled, scrollTop } = useRowScroll({\n focusedIndex: effectiveRow,\n itemCount: items.length,\n availableHeight,\n });\n\n const itemElements = items.map((item, index) => {\n const isFocused = index === focusedIndex;\n const isSelected = selectedIds.includes(item.id);\n const checkbox = isSelected ? \"[\\u2713]\" : \"[ ]\";\n const pointer = isFocused ? UI_SYMBOLS.CHEVRON : UI_SYMBOLS.CHEVRON_SPACER;\n\n return (\n <Text key={item.id}>\n <Text {...(isFocused && { color: CLI_COLORS.PRIMARY })}>{pointer}</Text>\n <Text {...((isSelected || isFocused) && { color: CLI_COLORS.PRIMARY })} bold={isFocused}>\n {\" \"}\n {checkbox} {item.label}\n </Text>\n {item.description && (\n <Text dimColor>\n {\" \"}\n {item.description}\n </Text>\n )}\n </Text>\n );\n });\n\n const footerElement =\n selectedIds.length > 0 ? (\n <Text>\n {\"\\n\"}Selected: <Text color={CLI_COLORS.WARNING}>{selectedIds.join(\", \")}</Text>\n </Text>\n ) : emptyMessage ? (\n <Text dimColor>\n {\"\\n\"}\n {emptyMessage}\n </Text>\n ) : null;\n\n return (\n <Box flexDirection=\"column\">\n {subtitle && <Text dimColor>{subtitle}</Text>}\n <Box\n flexDirection=\"column\"\n {...(scrollEnabled && { height: availableHeight, overflow: \"hidden\" as const })}\n >\n <Box\n flexDirection=\"column\"\n marginTop={scrollTop > 0 ? -scrollTop : 0}\n {...(scrollEnabled && { flexShrink: 0 })}\n >\n {itemElements}\n </Box>\n </Box>\n {footerElement}\n </Box>\n );\n};\n"],"mappings":";;;;;;;;;;;;;AAAA,SAAS,KAAK,MAAM,gBAAgB;AACpC,SAAgB,gBAAgB;AAsFxB,cACA,YADA;AA9DD,IAAM,eAAe,CAA4B;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAkB;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AACjB,MAAgD;AAE9C,QAAM,aAAa,MAAM,SAAS;AAClC,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,CAAC;AAElD,WAAS,CAAC,OAAO,QAAQ;AACvB,QAAI,IAAI,QAAQ;AACd,aAAO;AACP;AAAA,IACF;AAEA,QAAI,IAAI,WAAW,UAAU,KAAK;AAChC,sBAAgB,CAAC,SAAU,QAAQ,IAAI,aAAa,IAAI,OAAO,CAAE;AACjE;AAAA,IACF;AAEA,QAAI,IAAI,aAAa,UAAU,KAAK;AAClC,sBAAgB,CAAC,SAAU,QAAQ,aAAa,IAAI,IAAI,OAAO,CAAE;AACjE;AAAA,IACF;AAEA,QAAI,IAAI,QAAQ;AACd,iBAAW;AACX;AAAA,IACF;AAEA,QAAI,UAAU,WAAW;AACvB,YAAM,OAAO,MAAM,YAAY;AAC/B,UAAI,MAAM;AACR,iBAAS,KAAK,EAAE;AAAA,MAClB;AAAA,IACF;AAAA,EACF,CAAC;AAMD,QAAM,eAAe,gBAAgB,MAAM,SAAS,MAAM,SAAS,IAAI;AACvE,QAAM,EAAE,eAAe,UAAU,IAAI,aAAa;AAAA,IAChD,cAAc;AAAA,IACd,WAAW,MAAM;AAAA,IACjB;AAAA,EACF,CAAC;AAED,QAAM,eAAe,MAAM,IAAI,CAAC,MAAM,UAAU;AAC9C,UAAM,YAAY,UAAU;AAC5B,UAAM,aAAa,YAAY,SAAS,KAAK,EAAE;AAC/C,UAAM,WAAW,aAAa,aAAa;AAC3C,UAAM,UAAU,YAAY,WAAW,UAAU,WAAW;AAE5D,WACE,qBAAC,QACC;AAAA,0BAAC,QAAM,GAAI,aAAa,EAAE,OAAO,WAAW,QAAQ,GAAK,mBAAQ;AAAA,MACjE,qBAAC,QAAM,IAAK,cAAc,cAAc,EAAE,OAAO,WAAW,QAAQ,GAAI,MAAM,WAC3E;AAAA;AAAA,QACA;AAAA,QAAS;AAAA,QAAE,KAAK;AAAA,SACnB;AAAA,MACC,KAAK,eACJ,qBAAC,QAAK,UAAQ,MACX;AAAA;AAAA,QACA,KAAK;AAAA,SACR;AAAA,SAVO,KAAK,EAYhB;AAAA,EAEJ,CAAC;AAED,QAAM,gBACJ,YAAY,SAAS,IACnB,qBAAC,QACE;AAAA;AAAA,IAAK;AAAA,IAAU,oBAAC,QAAK,OAAO,WAAW,SAAU,sBAAY,KAAK,IAAI,GAAE;AAAA,KAC3E,IACE,eACF,qBAAC,QAAK,UAAQ,MACX;AAAA;AAAA,IACA;AAAA,KACH,IACE;AAEN,SACE,qBAAC,OAAI,eAAc,UAChB;AAAA,gBAAY,oBAAC,QAAK,UAAQ,MAAE,oBAAS;AAAA,IACtC;AAAA,MAAC;AAAA;AAAA,QACC,eAAc;AAAA,QACb,GAAI,iBAAiB,EAAE,QAAQ,iBAAiB,UAAU,SAAkB;AAAA,QAE7E;AAAA,UAAC;AAAA;AAAA,YACC,eAAc;AAAA,YACd,WAAW,YAAY,IAAI,CAAC,YAAY;AAAA,YACvC,GAAI,iBAAiB,EAAE,YAAY,EAAE;AAAA,YAErC;AAAA;AAAA,QACH;AAAA;AAAA,IACF;AAAA,IACC;AAAA,KACH;AAEJ;","names":[]}
|
package/dist/chunk-7ANJQLPJ.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
execCommand,
|
|
4
|
-
getErrorMessage
|
|
5
|
-
} from "./chunk-XPDVAJDH.js";
|
|
6
|
-
|
|
7
|
-
// src/cli/utils/open-url.ts
|
|
8
|
-
function browserOpenerCommand(platform, url) {
|
|
9
|
-
if (platform === "darwin") return { command: "open", args: [url] };
|
|
10
|
-
if (platform === "win32") return { command: "cmd", args: ["/c", "start", "", url] };
|
|
11
|
-
return { command: "xdg-open", args: [url] };
|
|
12
|
-
}
|
|
13
|
-
function openerRefusedMessage(command, exitCode) {
|
|
14
|
-
return `Could not open your browser \u2014 '${command}' exited ${exitCode}.`;
|
|
15
|
-
}
|
|
16
|
-
function openerUnavailableMessage(command, reason) {
|
|
17
|
-
return `Could not open your browser \u2014 '${command}' could not be run: ${reason}`;
|
|
18
|
-
}
|
|
19
|
-
async function openUrl(url) {
|
|
20
|
-
const { command, args } = browserOpenerCommand(process.platform, url);
|
|
21
|
-
try {
|
|
22
|
-
const result = await execCommand(command, args);
|
|
23
|
-
if (result.exitCode !== 0) {
|
|
24
|
-
return { ok: false, error: openerRefusedMessage(command, result.exitCode) };
|
|
25
|
-
}
|
|
26
|
-
return { ok: true };
|
|
27
|
-
} catch (error) {
|
|
28
|
-
return { ok: false, error: openerUnavailableMessage(command, getErrorMessage(error)) };
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export {
|
|
33
|
-
openUrl
|
|
34
|
-
};
|
|
35
|
-
//# sourceMappingURL=chunk-7ANJQLPJ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/utils/open-url.ts"],"sourcesContent":["import { execCommand } from \"./exec.js\";\nimport { getErrorMessage } from \"./errors.js\";\n\n/** The shell-out one platform answers \"open this with whatever handles it\" with. */\nexport type OpenerCommand = { command: string; args: string[] };\n\n/**\n * Never a throw. A machine with no browser, no desktop session or no opener at all is a\n * legitimate place to run this CLI, so failing to open a link is something to say rather than\n * something to fail on — the same posture the seed boundaries take, and for the same reason:\n * the link is already printed by the time this runs, so nothing is lost by it not working.\n */\nexport type OpenUrlResult = { ok: true } | { ok: false; error: string };\n\n/**\n * The command a platform opens a link with.\n *\n * There is no dependency for this. All three are one-line shell-outs to something the operating\n * system already ships, and a package for it would be a fourth thing to keep current for no\n * behaviour this does not have.\n *\n * Windows goes through `cmd` because `start` is a shell builtin rather than a program, and the\n * empty string after it is its TITLE argument: without one, `start` reads the first quoted\n * argument it is given as the window title and opens nothing.\n */\nexport function browserOpenerCommand(platform: NodeJS.Platform, url: string): OpenerCommand {\n if (platform === \"darwin\") return { command: \"open\", args: [url] };\n if (platform === \"win32\") return { command: \"cmd\", args: [\"/c\", \"start\", \"\", url] };\n return { command: \"xdg-open\", args: [url] };\n}\n\nfunction openerRefusedMessage(command: string, exitCode: number): string {\n return `Could not open your browser — '${command}' exited ${exitCode}.`;\n}\n\nfunction openerUnavailableMessage(command: string, reason: string): string {\n return `Could not open your browser — '${command}' could not be run: ${reason}`;\n}\n\n/**\n * Hands a link to whatever this platform opens links with.\n *\n * The URL travels as its own argument rather than inside a command line: `execCommand` spawns\n * without a shell, so the argument vector is the whole of the injection guard — there is no\n * string for a link to break out of.\n */\nexport async function openUrl(url: string): Promise<OpenUrlResult> {\n const { command, args } = browserOpenerCommand(process.platform, url);\n\n try {\n const result = await execCommand(command, args);\n if (result.exitCode !== 0) {\n return { ok: false, error: openerRefusedMessage(command, result.exitCode) };\n }\n return { ok: true };\n } catch (error) {\n return { ok: false, error: openerUnavailableMessage(command, getErrorMessage(error)) };\n }\n}\n"],"mappings":";;;;;;;AAyBO,SAAS,qBAAqB,UAA2B,KAA4B;AAC1F,MAAI,aAAa,SAAU,QAAO,EAAE,SAAS,QAAQ,MAAM,CAAC,GAAG,EAAE;AACjE,MAAI,aAAa,QAAS,QAAO,EAAE,SAAS,OAAO,MAAM,CAAC,MAAM,SAAS,IAAI,GAAG,EAAE;AAClF,SAAO,EAAE,SAAS,YAAY,MAAM,CAAC,GAAG,EAAE;AAC5C;AAEA,SAAS,qBAAqB,SAAiB,UAA0B;AACvE,SAAO,uCAAkC,OAAO,YAAY,QAAQ;AACtE;AAEA,SAAS,yBAAyB,SAAiB,QAAwB;AACzE,SAAO,uCAAkC,OAAO,uBAAuB,MAAM;AAC/E;AASA,eAAsB,QAAQ,KAAqC;AACjE,QAAM,EAAE,SAAS,KAAK,IAAI,qBAAqB,QAAQ,UAAU,GAAG;AAEpE,MAAI;AACF,UAAM,SAAS,MAAM,YAAY,SAAS,IAAI;AAC9C,QAAI,OAAO,aAAa,GAAG;AACzB,aAAO,EAAE,IAAI,OAAO,OAAO,qBAAqB,SAAS,OAAO,QAAQ,EAAE;AAAA,IAC5E;AACA,WAAO,EAAE,IAAI,KAAK;AAAA,EACpB,SAAS,OAAO;AACd,WAAO,EAAE,IAAI,OAAO,OAAO,yBAAyB,SAAS,gBAAgB,KAAK,CAAC,EAAE;AAAA,EACvF;AACF;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/components/wizard/wizard.tsx","../src/cli/components/themes/default.ts","../src/cli/components/hooks/use-build-step-props.ts"],"sourcesContent":["import React, { useCallback, useEffect } from \"react\";\nimport { EJECT_SOURCE } from \"../../consts.js\";\nimport { useApp, useInput } from \"ink\";\nimport { ThemeProvider } from \"@inkjs/ui\";\nimport { useWizardStore, type WizardState } from \"../../stores/wizard-store.js\";\nimport { cliTheme } from \"../themes/default.js\";\nimport { WizardLayout } from \"./wizard-layout.js\";\nimport { StepStack } from \"./step-stack.js\";\nimport { StepBuild } from \"./step-build.js\";\nimport { StepConfirm } from \"./step-confirm.js\";\nimport { StepSources } from \"./step-sources.js\";\nimport { StepAgents } from \"./step-agents.js\";\nimport { DomainSelection } from \"./domain-selection.js\";\nimport { validateSelection } from \"../../lib/matrix/index.js\";\nimport { getSkillById } from \"../../lib/matrix/matrix-provider.js\";\nimport { findStack } from \"../../lib/matrix/matrix-provider.js\";\nimport {\n HOTKEY_ACCEPT_DEFAULTS,\n HOTKEY_INFO,\n HOTKEY_SCOPE,\n isHotkey,\n isInfoPanelAvailable,\n} from \"./hotkeys.js\";\nimport type {\n AgentName,\n Domain,\n DomainSelections,\n SelectionValidation,\n SkillId,\n StackAgentConfig,\n} from \"../../types/index.js\";\nimport type { AgentScopeConfig, SkillConfig } from \"../../types/config.js\";\nimport type { StartupMessage } from \"../../utils/logger.js\";\nimport { useBuildStepProps } from \"../hooks/use-build-step-props.js\";\n\nconst TOAST_DURATION_MS = 2000;\n\nexport type WizardResultV2 = {\n skills: SkillConfig[];\n selectedAgents: AgentName[];\n agentConfigs: AgentScopeConfig[];\n /**\n * What each sub-agent holds and what preloads, when the producer knows per `(skill, sub-agent)`.\n * A shared configuration installed with `init --from` does: it assigns each skill to named\n * sub-agents at a named load state, and that curation is the whole of what was shared.\n *\n * The wizard has no per-agent granularity — a skill is selected for the project, not for one\n * sub-agent — so it leaves this undefined and the install pipeline's ownership rules build the\n * stack as they always have.\n */\n assignedStack?: Partial<Record<AgentName, StackAgentConfig>>;\n selectedStackId: string | null;\n /**\n * What the written config should record about itself, when the producer already knows.\n *\n * A shared configuration installed with `init --from` does: its payload carries the sharer's own\n * description, because it names no stack for the install to resolve one out of. The wizard leaves\n * this undefined and the install pipeline takes the applied stack's description instead — there\n * IS a loaded stack on that path, and it is the authority on its own sentence.\n */\n description?: string;\n domainSelections: DomainSelections;\n selectedDomains: Domain[];\n /**\n * Skill ids from the saved config that could not be resolved against the loaded source matrix\n * this session. The wizard could not represent them, so they are absent from `skills` and the\n * merge removes their config entries. Carried out of the wizard so the command can NAME each\n * removal and say why it happened — a removal the user never asked for must never be silent.\n */\n unresolvableSkillIds: SkillId[];\n cancelled: boolean;\n validation: SelectionValidation;\n};\n\nexport type WizardProps = {\n onComplete: (result: WizardResultV2) => void;\n onCancel: () => void;\n version: string;\n logo?: string | undefined;\n startupMessages?: StartupMessage[] | undefined;\n initialAgents?: AgentName[] | undefined;\n installedSkillIds?: SkillId[] | undefined;\n};\n\n/** S-key scope toggle: blocked (with a toast) in global context; no-op without a focused row. */\nfunction toggleFocusedScope<Id>(\n isEditingFromGlobalScope: boolean,\n focusedId: Id | null,\n actions: { toggle: (id: Id) => void; setToastMessage: (message: string) => void },\n): void {\n if (isEditingFromGlobalScope) {\n actions.setToastMessage(\"Scope toggle unavailable in global context\");\n return;\n }\n if (focusedId) {\n actions.toggle(focusedId);\n }\n}\n\n/** Selected skill ids: the chosen stack's full list under stack-defaults, else the wizard selections. */\nexport function resolveSelectedSkillIds(store: WizardState): SkillId[] {\n if (store.selectedStackId && store.stackAction === \"defaults\") {\n const stack = findStack(store.selectedStackId);\n if (!stack) {\n throw new Error(`Stack not found: ${store.selectedStackId}`);\n }\n return [...stack.allSkillIds];\n }\n return store.getAllSelectedTechnologies().map((tech) => getSkillById(tech).id);\n}\n\nexport const Wizard: React.FC<WizardProps> = ({\n onComplete,\n onCancel,\n version,\n logo,\n startupMessages,\n initialAgents,\n installedSkillIds,\n}) => {\n const store = useWizardStore();\n const { exit } = useApp();\n\n const toastMessage = useWizardStore((s) => s.toastMessage);\n\n useEffect(() => {\n if (!toastMessage) return;\n const timer = setTimeout(() => {\n useWizardStore.getState().setToastMessage(null);\n }, TOAST_DURATION_MS);\n return () => clearTimeout(timer);\n }, [toastMessage]);\n\n const buildStepProps = useBuildStepProps({\n store,\n ...(installedSkillIds !== undefined && { installedSkillIds }),\n });\n\n useInput((input, key) => {\n // Closing is never gated on the step: the panel is only ever open on a step\n // that allows it, and gating the close would strand the overlay.\n if (store.showInfo) {\n if (key.escape || isHotkey(input, HOTKEY_INFO)) {\n store.toggleInfo();\n }\n return;\n }\n\n if (isInfoPanelAvailable(store.step) && isHotkey(input, HOTKEY_INFO)) {\n store.toggleInfo();\n return;\n }\n\n if (key.escape) {\n // Steps with their own ESC handling (via useInput in child components):\n // - \"stack\": StackSelection handles ESC via onCancel prop\n // - \"domains\": DomainSelection handles ESC via CheckboxGrid onBack\n // - \"build\": StepBuild handles ESC via its own useInput\n // - \"sources\": StepSources handles ESC via onBack prop\n // - \"confirm\": StepConfirm handles ESC via onBack prop\n // - \"agents\": StepAgents handles ESC via its own useInput\n // All steps handle their own ESC, so this is a no-op.\n return;\n }\n\n if (\n isHotkey(input, HOTKEY_ACCEPT_DEFAULTS) &&\n store.step === \"build\" &&\n store.selectedStackId\n ) {\n store.setStackAction(\"defaults\");\n store.setStep(\"confirm\");\n return;\n }\n\n if (isHotkey(input, HOTKEY_SCOPE) && store.step === \"build\") {\n toggleFocusedScope(store.isEditingFromGlobalScope, store.focusedSkillId, {\n toggle: store.toggleSkillScope,\n setToastMessage: store.setToastMessage,\n });\n return;\n }\n\n if (isHotkey(input, HOTKEY_SCOPE) && store.step === \"agents\") {\n toggleFocusedScope(store.isEditingFromGlobalScope, store.focusedAgentId, {\n toggle: store.toggleAgentScope,\n setToastMessage: store.setToastMessage,\n });\n return;\n }\n });\n\n const handleComplete = useCallback(() => {\n const allSkills = resolveSelectedSkillIds(store);\n\n const skillConfigs: SkillConfig[] = allSkills.map((id) => {\n const existing = store.skillConfigs.find((sc) => sc.id === id && !sc.excluded);\n return existing ?? { id, scope: \"global\" as const, origin: EJECT_SOURCE };\n });\n\n // Append excluded entries so they flow through to config generation\n const excludedConfigs = store.skillConfigs.filter((sc) => sc.excluded);\n const allSkillConfigs = [...skillConfigs, ...excludedConfigs];\n\n const validation = validateSelection(allSkills);\n\n const result: WizardResultV2 = {\n skills: allSkillConfigs,\n selectedAgents: store.selectedAgents,\n agentConfigs: store.agentConfigs,\n selectedStackId: store.selectedStackId,\n domainSelections: store.domainSelections,\n selectedDomains: store.selectedDomains,\n unresolvableSkillIds: store.unresolvableSkillIds,\n cancelled: false,\n validation,\n };\n\n onComplete(result);\n exit();\n }, [store, onComplete, exit]);\n\n const handleCancel = useCallback(() => {\n onCancel();\n exit();\n }, [onCancel, exit]);\n\n const renderStep = () => {\n switch (store.step) {\n case \"stack\":\n return <StepStack onCancel={handleCancel} />;\n\n case \"domains\":\n return <DomainSelection />;\n\n case \"build\":\n return <StepBuild {...buildStepProps} />;\n\n case \"sources\": {\n return (\n <StepSources\n onContinue={() => {\n if (!initialAgents?.length) {\n store.preselectAgentsFromDomains();\n }\n store.setStep(\"agents\");\n }}\n onBack={store.goBack}\n />\n );\n }\n\n case \"agents\":\n return <StepAgents />;\n\n case \"confirm\": {\n return <StepConfirm onComplete={handleComplete} onBack={store.goBack} />;\n }\n\n default: {\n const _exhaustive: never = store.step;\n return _exhaustive;\n }\n }\n };\n\n return (\n <ThemeProvider theme={cliTheme}>\n <WizardLayout version={version} logo={logo} startupMessages={startupMessages}>\n {renderStep()}\n </WizardLayout>\n </ThemeProvider>\n );\n};\n","import { extendTheme, defaultTheme } from \"@inkjs/ui\";\nimport { CLI_COLORS } from \"../../consts.js\";\n\n/** Variant → color mapping shared by StatusMessage, Alert, and Badge; unknown variants fall back per-site. */\nconst VARIANT_COLORS: Partial<Record<string, string>> = {\n error: CLI_COLORS.ERROR,\n warning: CLI_COLORS.WARNING,\n success: CLI_COLORS.SUCCESS,\n info: CLI_COLORS.INFO,\n};\n\n/**\n * @inkjs/ui types the props it hands a style function as `any`, so reading\n * `variant` off them is an unchecked access at four call sites. Taking it as\n * `unknown` here is the boundary: the value is only ever a lookup key, and a\n * variant the map does not name falls back to what the call site passes.\n */\nconst variantColor = (variant: unknown, fallback: string): string =>\n VARIANT_COLORS[String(variant)] ?? fallback;\n\n/**\n * CLI theme matching existing picocolors styling\n *\n * Color scheme:\n * - Cyan: Focus/primary (headings, prompts, selected items)\n * - Green: Success states\n * - Red: Errors\n * - Yellow: Warnings\n * - Blue: Info messages\n */\nexport const cliTheme = extendTheme(defaultTheme, {\n components: {\n Spinner: {\n styles: {\n frame: () => ({ color: CLI_COLORS.PRIMARY }),\n label: () => ({ color: CLI_COLORS.NEUTRAL }),\n },\n },\n Select: {\n styles: {\n focusIndicator: () => ({ color: CLI_COLORS.FOCUS }),\n label: ({ isFocused }) => ({\n color: isFocused ? CLI_COLORS.FOCUS : undefined,\n }),\n },\n },\n MultiSelect: {\n styles: {\n focusIndicator: () => ({ color: CLI_COLORS.FOCUS }),\n label: ({ isFocused, isSelected }) => ({\n color: isFocused ? CLI_COLORS.FOCUS : isSelected ? CLI_COLORS.SUCCESS : undefined,\n }),\n checkboxChecked: () => ({ color: CLI_COLORS.SUCCESS }),\n },\n },\n StatusMessage: {\n styles: {\n container: ({ variant }) => ({\n borderStyle: \"round\",\n borderColor: variantColor(variant, CLI_COLORS.INFO),\n }),\n },\n },\n Alert: {\n styles: {\n container: ({ variant }) => ({\n borderColor: variantColor(variant, CLI_COLORS.INFO),\n }),\n icon: ({ variant }) => ({\n color: variantColor(variant, CLI_COLORS.INFO),\n }),\n },\n },\n TextInput: {\n styles: {\n container: ({ isFocused }) => ({\n borderColor: isFocused ? CLI_COLORS.FOCUS : CLI_COLORS.NEUTRAL,\n }),\n cursor: () => ({ color: CLI_COLORS.PRIMARY }),\n },\n },\n ConfirmInput: {\n styles: {\n highlightedChoice: () => ({ color: CLI_COLORS.PRIMARY }),\n },\n },\n Badge: {\n styles: {\n container: ({ variant }) => ({\n color: variantColor(variant, CLI_COLORS.PRIMARY),\n }),\n },\n },\n },\n});\n","import { useCallback } from \"react\";\nimport { FALLBACK_DOMAIN } from \"../../consts.js\";\nimport type { Domain, SkillId } from \"../../types/index.js\";\nimport type { WizardState } from \"../../stores/wizard-store.js\";\nimport { matrix } from \"../../lib/matrix/matrix-provider.js\";\nimport type { StepBuildProps } from \"../wizard/step-build.js\";\n\ntype UseBuildStepPropsOptions = {\n store: WizardState;\n installedSkillIds?: SkillId[];\n};\n\nexport function useBuildStepProps({\n store,\n installedSkillIds,\n}: UseBuildStepPropsOptions): StepBuildProps {\n const currentDomain = store.getCurrentDomain();\n const defaultDomains: Domain[] = [FALLBACK_DOMAIN];\n const effectiveDomains =\n store.selectedDomains.length > 0 ? store.selectedDomains : defaultDomains;\n\n const allSelections = store.getAllSelectedTechnologies();\n\n const activeDomain: Domain = currentDomain || effectiveDomains[0] || FALLBACK_DOMAIN;\n\n const onToggle = useCallback(\n (categoryId: Parameters<StepBuildProps[\"onToggle\"]>[0], techId: SkillId) => {\n const domain: Domain = store.getCurrentDomain() || FALLBACK_DOMAIN;\n const cat = matrix.categories[categoryId];\n const exclusive = cat?.exclusive ?? true;\n store.toggleTechnology(domain, categoryId, techId, exclusive);\n },\n [store],\n );\n\n const onContinue = useCallback(() => {\n if (!store.nextDomain()) {\n store.setStep(\"sources\");\n }\n }, [store]);\n\n const onBack = useCallback(() => {\n if (!store.prevDomain()) {\n store.goBack();\n }\n }, [store]);\n\n return {\n domain: activeDomain,\n selectedDomains: effectiveDomains,\n allSelections,\n showLabels: store.showLabels,\n installedSkillIds,\n onToggle,\n onToggleLabels: store.toggleShowLabels,\n onContinue,\n onBack,\n };\n}\n"],"mappings":"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","names":["useCallback","useCallback"]}
|