agents-inc 0.170.1 → 0.170.2
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 +9 -0
- package/dist/{chunk-BMRUNMPV.js → chunk-2YA4DDRM.js} +35 -35
- package/dist/chunk-2YA4DDRM.js.map +1 -0
- package/dist/{chunk-44TE3RKH.js → chunk-3ED3KHHD.js} +5 -4
- package/dist/chunk-3ED3KHHD.js.map +1 -0
- package/dist/{chunk-3G7X2WKI.js → chunk-5BNX73OU.js} +18 -38
- package/dist/chunk-5BNX73OU.js.map +1 -0
- package/dist/{chunk-7RDMTR64.js → chunk-66AEVERM.js} +785 -256
- package/dist/chunk-66AEVERM.js.map +1 -0
- package/dist/{chunk-PJWGTNOX.js → chunk-7C3PFRBU.js} +144 -186
- package/dist/chunk-7C3PFRBU.js.map +1 -0
- package/dist/{chunk-52HDHJ7I.js → chunk-AUNRHWH4.js} +32 -21
- package/dist/chunk-AUNRHWH4.js.map +1 -0
- package/dist/{chunk-KOLDW6SF.js → chunk-BBDGYJHX.js} +2 -2
- package/dist/chunk-BBDGYJHX.js.map +1 -0
- package/dist/{chunk-SZYQISA2.js → chunk-ELV5WDS3.js} +43 -29
- package/dist/chunk-ELV5WDS3.js.map +1 -0
- package/dist/{chunk-MQ6CGZNJ.js → chunk-GAKVZNTX.js} +1879 -2019
- package/dist/chunk-GAKVZNTX.js.map +1 -0
- package/dist/chunk-GEMW5RQ2.js +1169 -0
- package/dist/chunk-GEMW5RQ2.js.map +1 -0
- package/dist/{chunk-NQW25DCF.js → chunk-GHHJYNAN.js} +1 -7
- package/dist/chunk-GHHJYNAN.js.map +1 -0
- package/dist/{chunk-WTWMGH2C.js → chunk-HACRR422.js} +2 -2
- package/dist/chunk-HACRR422.js.map +1 -0
- package/dist/{chunk-F2BHT5C4.js → chunk-IWY5IR4F.js} +129 -151
- package/dist/chunk-IWY5IR4F.js.map +1 -0
- package/dist/{chunk-JFLVEFFP.js → chunk-KIK5EZYD.js} +1 -1
- package/dist/chunk-KIK5EZYD.js.map +1 -0
- package/dist/{chunk-USVBYQSQ.js → chunk-O4LN3HFI.js} +16 -6
- package/dist/chunk-O4LN3HFI.js.map +1 -0
- package/dist/{chunk-RIPSGNLU.js → chunk-OCAVW6N5.js} +3 -3
- package/dist/chunk-OCAVW6N5.js.map +1 -0
- package/dist/{chunk-4AAOOAIN.js → chunk-P6CYS4JK.js} +2 -2
- package/dist/chunk-P6CYS4JK.js.map +1 -0
- package/dist/chunk-PLFANHRZ.js +35 -0
- package/dist/chunk-PLFANHRZ.js.map +1 -0
- package/dist/{chunk-6ZRH5RHC.js → chunk-PMUZR4XO.js} +4 -4
- package/dist/chunk-PMUZR4XO.js.map +1 -0
- package/dist/{chunk-F5EBEATU.js → chunk-PSUTNOQ2.js} +34 -46
- package/dist/chunk-PSUTNOQ2.js.map +1 -0
- package/dist/chunk-RIK45Q4I.js +103 -0
- package/dist/chunk-RIK45Q4I.js.map +1 -0
- package/dist/{chunk-HED2DAXZ.js → chunk-THO7LO5B.js} +5 -5
- package/dist/chunk-THO7LO5B.js.map +1 -0
- package/dist/{chunk-OYJQUA3D.js → chunk-YGDWHDOY.js} +31 -13
- package/dist/chunk-YGDWHDOY.js.map +1 -0
- package/dist/{chunk-NCWDK6L7.js → chunk-YXKTY5WM.js} +254 -379
- package/dist/chunk-YXKTY5WM.js.map +1 -0
- package/dist/{chunk-NEZ4OAOL.js → chunk-ZEGM3MVR.js} +3 -5
- package/dist/chunk-ZEGM3MVR.js.map +1 -0
- package/dist/commands/build/marketplace.js +46 -46
- package/dist/commands/build/marketplace.js.map +1 -1
- package/dist/commands/build/plugins.js +25 -28
- package/dist/commands/build/plugins.js.map +1 -1
- package/dist/commands/compile.js +87 -178
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/doctor.js +510 -360
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +451 -357
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +144 -125
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/init.js +20 -27
- package/dist/commands/list.js +39 -55
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/new/marketplace.js +6 -11
- package/dist/commands/new/marketplace.js.map +1 -1
- package/dist/commands/search.js +35 -32
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/share.js +17 -77
- package/dist/commands/share.js.map +1 -1
- package/dist/commands/uninstall.js +159 -222
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +9 -32
- package/dist/commands/update.js.map +1 -1
- package/dist/components/common/prompt-confirm.js +2 -2
- package/dist/components/common/removal-plan-confirm.js +2 -2
- package/dist/components/common/scroll-affordance.js +2 -2
- package/dist/components/common/select-list.js +2 -2
- package/dist/components/common/skill-agent-summary.js +4 -4
- package/dist/components/common/spinner.js +2 -4
- package/dist/components/common/summary-panel.js +5 -5
- package/dist/components/common/summary-panel.js.map +1 -1
- package/dist/config-exports.js +7 -3
- package/dist/config-exports.js.map +1 -1
- package/dist/hooks/init.js +18 -19
- package/dist/hooks/init.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/load-agent-defs-6QUUMGHK.js +14 -0
- package/dist/recompile-project-agents-I33KQJFB.js +65 -0
- package/dist/recompile-project-agents-I33KQJFB.js.map +1 -0
- package/dist/{source-loader-C5SQXZXI.js → source-loader-TTJVW2ER.js} +5 -5
- package/dist/src/agents/developer/ai-developer/playbook.md +2 -5
- package/dist/src/agents/developer/api-developer/playbook.md +2 -5
- package/dist/src/agents/developer/cli-developer/playbook.md +2 -5
- package/dist/src/agents/developer/web-developer/playbook.md +2 -5
- package/dist/src/agents/meta/agent-summoner/output.md +2 -2
- package/dist/src/agents/meta/agent-summoner/playbook.md +1 -13
- package/dist/src/agents/meta/codex-keeper/critical-requirements.md +2 -5
- package/dist/src/agents/meta/convention-keeper/critical-requirements.md +2 -4
- package/dist/src/agents/tester/ai-tester/critical-requirements.md +1 -2
- package/dist/src/agents/tester/ai-tester/playbook.md +2 -0
- package/dist/src/agents/tester/api-tester/critical-requirements.md +1 -2
- package/dist/src/agents/tester/api-tester/playbook.md +2 -0
- package/dist/src/agents/tester/cli-tester/critical-requirements.md +1 -2
- package/dist/src/agents/tester/cli-tester/playbook.md +2 -0
- package/dist/src/agents/tester/web-tester/critical-requirements.md +1 -2
- package/dist/src/agents/tester/web-tester/playbook.md +2 -0
- package/package.json +9 -8
- package/src/agents/developer/ai-developer/playbook.md +2 -5
- package/src/agents/developer/api-developer/playbook.md +2 -5
- package/src/agents/developer/cli-developer/playbook.md +2 -5
- package/src/agents/developer/web-developer/playbook.md +2 -5
- package/src/agents/meta/agent-summoner/output.md +2 -2
- package/src/agents/meta/agent-summoner/playbook.md +1 -13
- package/src/agents/meta/codex-keeper/critical-requirements.md +2 -5
- package/src/agents/meta/convention-keeper/critical-requirements.md +2 -4
- package/src/agents/tester/ai-tester/critical-requirements.md +1 -2
- package/src/agents/tester/ai-tester/playbook.md +2 -0
- package/src/agents/tester/api-tester/critical-requirements.md +1 -2
- package/src/agents/tester/api-tester/playbook.md +2 -0
- package/src/agents/tester/cli-tester/critical-requirements.md +1 -2
- package/src/agents/tester/cli-tester/playbook.md +2 -0
- package/src/agents/tester/web-tester/critical-requirements.md +1 -2
- package/src/agents/tester/web-tester/playbook.md +2 -0
- package/src/schemas/project-config.schema.json +0 -3
- package/src/schemas/project-source-config.schema.json +0 -6
- package/dist/chunk-3G7X2WKI.js.map +0 -1
- package/dist/chunk-44TE3RKH.js.map +0 -1
- package/dist/chunk-4AAOOAIN.js.map +0 -1
- package/dist/chunk-52HDHJ7I.js.map +0 -1
- package/dist/chunk-6HNXYYVF.js +0 -373
- package/dist/chunk-6HNXYYVF.js.map +0 -1
- package/dist/chunk-6ZRH5RHC.js.map +0 -1
- package/dist/chunk-7RDMTR64.js.map +0 -1
- package/dist/chunk-BMRUNMPV.js.map +0 -1
- package/dist/chunk-CLPUWOSA.js +0 -46
- package/dist/chunk-CLPUWOSA.js.map +0 -1
- package/dist/chunk-F2BHT5C4.js.map +0 -1
- package/dist/chunk-F5EBEATU.js.map +0 -1
- package/dist/chunk-HED2DAXZ.js.map +0 -1
- package/dist/chunk-JFLVEFFP.js.map +0 -1
- package/dist/chunk-KOLDW6SF.js.map +0 -1
- package/dist/chunk-MQ6CGZNJ.js.map +0 -1
- package/dist/chunk-NCWDK6L7.js.map +0 -1
- package/dist/chunk-NEZ4OAOL.js.map +0 -1
- package/dist/chunk-NIHUOWE4.js +0 -106
- package/dist/chunk-NIHUOWE4.js.map +0 -1
- package/dist/chunk-NQW25DCF.js.map +0 -1
- package/dist/chunk-OYJQUA3D.js.map +0 -1
- package/dist/chunk-PJWGTNOX.js.map +0 -1
- package/dist/chunk-RIPSGNLU.js.map +0 -1
- package/dist/chunk-SZYQISA2.js.map +0 -1
- package/dist/chunk-USVBYQSQ.js.map +0 -1
- package/dist/chunk-V3KTSP3Q.js +0 -940
- package/dist/chunk-V3KTSP3Q.js.map +0 -1
- package/dist/chunk-WTWMGH2C.js.map +0 -1
- package/dist/load-agent-defs-YMDWBFDP.js +0 -14
- package/dist/recompile-project-agents-SZ76WNTW.js +0 -18
- package/dist/source-loader-C5SQXZXI.js.map +0 -1
- /package/dist/{load-agent-defs-YMDWBFDP.js.map → load-agent-defs-6QUUMGHK.js.map} +0 -0
- /package/dist/{recompile-project-agents-SZ76WNTW.js.map → source-loader-TTJVW2ER.js.map} +0 -0
package/dist/commands/compile.js
CHANGED
|
@@ -1,33 +1,32 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
unofferablePlacementsFound
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-HACRR422.js";
|
|
5
5
|
import {
|
|
6
6
|
hostCompileNotices
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-PSUTNOQ2.js";
|
|
8
8
|
import {
|
|
9
9
|
detectBothInstallations,
|
|
10
10
|
reconcileTypesFromDisk
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-66AEVERM.js";
|
|
12
12
|
import {
|
|
13
13
|
compileAgents,
|
|
14
14
|
discoverInstalledSkills
|
|
15
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-IWY5IR4F.js";
|
|
16
16
|
import {
|
|
17
17
|
loadAgentDefs
|
|
18
|
-
} from "../chunk-
|
|
19
|
-
import "../chunk-
|
|
20
|
-
import "../chunk-
|
|
18
|
+
} from "../chunk-THO7LO5B.js";
|
|
19
|
+
import "../chunk-5BNX73OU.js";
|
|
20
|
+
import "../chunk-2YA4DDRM.js";
|
|
21
21
|
import {
|
|
22
22
|
providerFlag,
|
|
23
23
|
providerNamedBy,
|
|
24
24
|
refuseAnAmbiguousInstallation
|
|
25
|
-
} from "../chunk-
|
|
25
|
+
} from "../chunk-OCAVW6N5.js";
|
|
26
26
|
import {
|
|
27
27
|
BaseCommand,
|
|
28
28
|
EXIT_CODES
|
|
29
|
-
} from "../chunk-
|
|
30
|
-
import "../chunk-CLPUWOSA.js";
|
|
29
|
+
} from "../chunk-GEMW5RQ2.js";
|
|
31
30
|
import {
|
|
32
31
|
ConfigLoadError,
|
|
33
32
|
ERROR_MESSAGES,
|
|
@@ -40,7 +39,6 @@ import {
|
|
|
40
39
|
loadInstalledConfig,
|
|
41
40
|
loadProjectConfig,
|
|
42
41
|
loadSkillsMatrixFromSource,
|
|
43
|
-
plural,
|
|
44
42
|
providerInUse,
|
|
45
43
|
recompileSummary,
|
|
46
44
|
registeredProjectUpdateFailed,
|
|
@@ -51,14 +49,16 @@ import {
|
|
|
51
49
|
skillMetadataUnusableDetail,
|
|
52
50
|
skillMetadataUnusableError,
|
|
53
51
|
verbose
|
|
54
|
-
} from "../chunk-
|
|
55
|
-
import
|
|
52
|
+
} from "../chunk-GAKVZNTX.js";
|
|
53
|
+
import {
|
|
54
|
+
plural
|
|
55
|
+
} from "../chunk-AUNRHWH4.js";
|
|
56
56
|
import {
|
|
57
57
|
STANDARD_FILES,
|
|
58
58
|
effectivelyExcludedSkillIds,
|
|
59
59
|
isActiveAt
|
|
60
|
-
} from "../chunk-
|
|
61
|
-
import "../chunk-
|
|
60
|
+
} from "../chunk-7C3PFRBU.js";
|
|
61
|
+
import "../chunk-GHHJYNAN.js";
|
|
62
62
|
|
|
63
63
|
// src/cli/commands/compile.ts
|
|
64
64
|
import { Flags } from "@oclif/core";
|
|
@@ -97,17 +97,7 @@ var Compile = class _Compile extends BaseCommand {
|
|
|
97
97
|
await this.runCompilePasses(installations, agentDefs, cwd);
|
|
98
98
|
await this.reportWhatThisHostCannotCarry(installations, cwd);
|
|
99
99
|
}
|
|
100
|
-
/**
|
|
101
|
-
* What this host could not carry, once per run and after the passes.
|
|
102
|
-
*
|
|
103
|
-
* AFTER, because the trust half of it is a question about the tree as it now stands: a project
|
|
104
|
-
* whose role files this run just wrote is exactly the one whose user has to trust it, and asking
|
|
105
|
-
* before the write would answer about the previous state.
|
|
106
|
-
*
|
|
107
|
-
* `init` prints the same lines in the same order — {@link hostCompileNotices} is the one place
|
|
108
|
-
* either of them gets them from, so the two commands cannot drift into saying different things
|
|
109
|
-
* about one tree.
|
|
110
|
-
*/
|
|
100
|
+
/** Runs after the passes, so the trust notice describes the tree this run wrote. */
|
|
111
101
|
async reportWhatThisHostCannotCarry(installations, cwd) {
|
|
112
102
|
const root = rootThisRunCompiled(installations, cwd);
|
|
113
103
|
for (const notice of await hostCompileNotices(providerInUse(root), cwd)) {
|
|
@@ -132,31 +122,14 @@ var Compile = class _Compile extends BaseCommand {
|
|
|
132
122
|
return installations;
|
|
133
123
|
}
|
|
134
124
|
/**
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
* **The install path's pre-flight cannot cover this, and nothing ties a folder's contents to
|
|
139
|
-
* its name.** `config.ts` carries no provider field — the ruling forbids one, so that a saved
|
|
140
|
-
* configuration installs onto either provider — which means a user who copies
|
|
141
|
-
* `.agents-inc/claude/` to `.agents-inc/codex/` has a Codex installation holding a
|
|
142
|
-
* configuration that never met `init --from --provider codex`'s refusal. This is the command
|
|
143
|
-
* that turns a configuration into files on disk, so it is the one that has to ask again.
|
|
144
|
-
*
|
|
145
|
-
* Both scopes, because a project inherits its global's rows and an unofferable row in either
|
|
146
|
-
* file is a row this run would act on. Each installation is asked about its OWN host: the two
|
|
147
|
-
* scopes can be on different providers, and asking one host about the other's configuration is
|
|
148
|
-
* how a refusal fires on a cell that is offered where the skill actually lives.
|
|
125
|
+
* Re-checked here because config.ts names no provider, so a copied installation folder can hold
|
|
126
|
+
* a configuration its host never vetted at install.
|
|
149
127
|
*/
|
|
150
128
|
async refuseUnofferablePlacements(cwd) {
|
|
151
129
|
const [finding] = await unofferablePlacementsFound(cwd);
|
|
152
130
|
if (finding !== void 0) this.error(finding, { exit: EXIT_CODES.ERROR });
|
|
153
131
|
}
|
|
154
|
-
/**
|
|
155
|
-
* Names where the marketplace came from — the project's own config first, then the global
|
|
156
|
-
* one, then the default. `compile` takes no `--marketplace`: it recompiles an installation
|
|
157
|
-
* that already recorded which marketplace its skill references answer to, and reading
|
|
158
|
-
* a different one would write agents against a catalogue config.ts does not name.
|
|
159
|
-
*/
|
|
132
|
+
/** No `--marketplace`: an installation recompiles against the marketplace config.ts recorded. */
|
|
160
133
|
async resolveAndLogSource(projectDir) {
|
|
161
134
|
this.log(STATUS_MESSAGES.RESOLVING_SOURCE);
|
|
162
135
|
try {
|
|
@@ -190,13 +163,7 @@ var Compile = class _Compile extends BaseCommand {
|
|
|
190
163
|
this.error(ERROR_MESSAGES.NO_SKILLS_TO_COMPILE, { exit: EXIT_CODES.ERROR });
|
|
191
164
|
}
|
|
192
165
|
}
|
|
193
|
-
/**
|
|
194
|
-
* Discovers what this pass compiles from, and refuses the run when any installed
|
|
195
|
-
* skill's metadata.yaml exists but describes no skill — before a count is printed,
|
|
196
|
-
* an agent is written or the type unions are regenerated. Skipping such a skill is
|
|
197
|
-
* what the config-types pass already does; loading it anyway is what this pass
|
|
198
|
-
* used to do, so a single run both loaded and skipped the same file.
|
|
199
|
-
*/
|
|
166
|
+
/** Refuses the run, before anything is written, when an installed skill's metadata is unusable. */
|
|
200
167
|
async discoverAllSkills(projectDir) {
|
|
201
168
|
this.log(STATUS_MESSAGES.DISCOVERING_SKILLS);
|
|
202
169
|
const result = await discoverInstalledSkills(projectDir);
|
|
@@ -207,23 +174,14 @@ var Compile = class _Compile extends BaseCommand {
|
|
|
207
174
|
this.log(formatDiscoveryMessage(result));
|
|
208
175
|
return result;
|
|
209
176
|
}
|
|
210
|
-
/**
|
|
211
|
-
* Names each offending file and its reason, then exits. The detail is LOGGED and
|
|
212
|
-
* only the refusal is raised: oclif hard-wraps error text at the terminal width,
|
|
213
|
-
* and a path broken across two lines is one nobody can copy.
|
|
214
|
-
*/
|
|
177
|
+
/** Detail is logged, not raised: oclif hard-wraps error text, which breaks copyable paths. */
|
|
215
178
|
refuseUnusableSkillMetadata(entries) {
|
|
216
179
|
for (const entry of entries) {
|
|
217
180
|
this.log(skillMetadataUnusableDetail(entry));
|
|
218
181
|
}
|
|
219
182
|
this.error(skillMetadataUnusableError(entries), { exit: EXIT_CODES.ERROR });
|
|
220
183
|
}
|
|
221
|
-
/**
|
|
222
|
-
* A stack skill that is not among the discovered skills is dropped from every
|
|
223
|
-
* agent that references it. The resolver only records that at verbose level, so
|
|
224
|
-
* the default output would claim a successful recompile of an agent that no
|
|
225
|
-
* longer matches config.ts. Name each dropped skill instead.
|
|
226
|
-
*/
|
|
184
|
+
/** The resolver drops a missing stack skill silently except at verbose level. */
|
|
227
185
|
async warnUnresolvedStackSkills(projectDir, allSkills) {
|
|
228
186
|
const loaded = await loadProjectConfig(projectDir);
|
|
229
187
|
if (!loaded?.config.stack) return;
|
|
@@ -238,15 +196,8 @@ var Compile = class _Compile extends BaseCommand {
|
|
|
238
196
|
}
|
|
239
197
|
}
|
|
240
198
|
/**
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
* compile-time filter in `buildCompileAgents` drops that reference on the way to the
|
|
244
|
-
* resolver and `compile` rewrites nothing in `config.ts`, so the row survives and is
|
|
245
|
-
* dropped again on every future run — while the recompile summary reports a clean pass
|
|
246
|
-
* over an agent that no longer carries what its own config says it does.
|
|
247
|
-
*
|
|
248
|
-
* The sibling of {@link warnUnresolvedStackSkills} one layer over: there the skill is
|
|
249
|
-
* missing from disk, here it is present and unreachable from that sub-agent.
|
|
199
|
+
* A hand-edited config.ts can give a global sub-agent a project-scoped skill, which the compile
|
|
200
|
+
* filter silently drops on every run.
|
|
250
201
|
*/
|
|
251
202
|
async warnScopeDroppedStackPairs(projectDir) {
|
|
252
203
|
const loaded = await loadProjectConfig(projectDir);
|
|
@@ -255,56 +206,20 @@ var Compile = class _Compile extends BaseCommand {
|
|
|
255
206
|
this.warn(scopeBlockedStackAssignment(agentNames, skillId));
|
|
256
207
|
}
|
|
257
208
|
}
|
|
258
|
-
/**
|
|
259
|
-
* The project pass compiled no agents, but the project config may still declare
|
|
260
|
-
* global-scope agents whose stack lives in the global config. Without a pointer
|
|
261
|
-
* the "No agents to recompile" line reads as a silent no-op after a global stack
|
|
262
|
-
* change, so name the global context and the count.
|
|
263
|
-
*/
|
|
209
|
+
/** Points at global-scope agents so "No agents to recompile" doesn't read as a silent no-op. */
|
|
264
210
|
async hintGlobalScopedAgents(projectDir) {
|
|
265
211
|
const loaded = await loadInstalledConfig(projectDir);
|
|
266
212
|
if (!loaded) return;
|
|
267
213
|
const globalAgentCount = loaded.config.agents.filter(
|
|
268
|
-
(agent) =>
|
|
214
|
+
(agent) => isActiveAt(agent, "global")
|
|
269
215
|
).length;
|
|
270
216
|
if (globalAgentCount === 0) return;
|
|
271
217
|
this.log(globalScopedAgentsHint(globalAgentCount));
|
|
272
218
|
}
|
|
273
219
|
/**
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
* `stacks-loader.ts`'s `statedUsageFor`/`liveCategoryOf` and those read the
|
|
278
|
-
* singleton directly rather than any value a caller threads through. Called
|
|
279
|
-
* first, before anything in the pass renders. Left unseated, the singleton stays
|
|
280
|
-
* at its process-start default (`BUILT_IN_MATRIX`, which never carries a local
|
|
281
|
-
* skill), so a locally-installed skill's stated `usageGuidance` silently falls
|
|
282
|
-
* back to the generic per-category placeholder — different bytes from what
|
|
283
|
-
* `install` last wrote, so a following `compile` rewrites every agent that
|
|
284
|
-
* carries one.
|
|
285
|
-
*
|
|
286
|
-
* Scoped to `pass.projectDir`, never the invoking `cwd`: a global pass must seat
|
|
287
|
-
* the global installation's own local skills, not the invoking directory's.
|
|
288
|
-
*
|
|
289
|
-
* `skipExtraSources: true` is NOT a divergence from a full multi-source
|
|
290
|
-
* load: extra-source loading only annotates each skill's
|
|
291
|
-
* `availableSources`/`activeSource` — it never adds skills
|
|
292
|
-
* or categories to the matrix, and neither the render path nor the config-types
|
|
293
|
-
* writer ever reads those annotations, so the emitted output is byte-identical
|
|
294
|
-
* either way (pinned by the skipExtraSources parity test in
|
|
295
|
-
* local-installer.test.ts). Skipping avoids fetching every registered extra
|
|
296
|
-
* source (network on a cold cache, plus unreachable-remote warnings) on this
|
|
297
|
-
* offline compile path. `matrixOnly` keeps the default-source path itself
|
|
298
|
-
* offline too.
|
|
299
|
-
*
|
|
300
|
-
* The seated matrix is RETURNED as well as seated, and `null` on a failure, so
|
|
301
|
-
* the two halves can take the postures they each need. The RENDER degrades: it
|
|
302
|
-
* reads the singleton whatever happens, and falls back to the same
|
|
303
|
-
* category-placeholder behavior compile had before this seat existed. The type
|
|
304
|
-
* refresh ABORTS on `null` — it derives every union from the catalogue, so with
|
|
305
|
-
* none loaded it would narrow them to whatever the built-in catalogue happens
|
|
306
|
-
* to carry, dropping every marketplace-only and local category and, at global
|
|
307
|
-
* scope, propagating that into every registered project.
|
|
220
|
+
* Seats the matrix singleton the render reads (else local skills lose their stated usage), and
|
|
221
|
+
* returns it, `null` on failure: the render degrades, the type refresh skips. Extra sources only
|
|
222
|
+
* annotate skills, so skipping them keeps output identical and the path offline.
|
|
308
223
|
*/
|
|
309
224
|
async seatMatrixForPass(projectDir) {
|
|
310
225
|
try {
|
|
@@ -320,24 +235,8 @@ var Compile = class _Compile extends BaseCommand {
|
|
|
320
235
|
}
|
|
321
236
|
}
|
|
322
237
|
/**
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
* pass that leaves them untouched strands stale unions after a hand-edit.
|
|
326
|
-
* Regenerates them from the scope's persisted config exactly as
|
|
327
|
-
* `writeConfigByScope` would: standalone narrowed unions at global scope, import-and-
|
|
328
|
-
* extend at project scope. A failed refresh downgrades to a warning — the
|
|
329
|
-
* compiled agents are already written and remain valid; only the type unions
|
|
330
|
-
* may still be stale.
|
|
331
|
-
*
|
|
332
|
-
* Takes the catalogue {@link seatMatrixForPass} returned rather than reading the
|
|
333
|
-
* singleton it seated, so this refresh cannot run against a seat that is not the
|
|
334
|
-
* one this pass asked for. `null` means the seat failed, and the refresh is
|
|
335
|
-
* skipped whole: every union here is DERIVED from the catalogue, so writing them
|
|
336
|
-
* without one is not a degraded answer but a wrong one — the unions narrow to
|
|
337
|
-
* the built-in catalogue's own categories, and `config.ts` beside them still
|
|
338
|
-
* keys its `stack` under the ones that just vanished, so the pair stops
|
|
339
|
-
* type-checking. Skipping falls under the same warning as any other failed
|
|
340
|
-
* refresh, for the same reason.
|
|
238
|
+
* Regenerates config-types.ts after a hand-edit; failure only warns, as the agents are written.
|
|
239
|
+
* Skipped without a catalogue, since unions derived from none would be wrong, not just stale.
|
|
341
240
|
*/
|
|
342
241
|
async refreshConfigTypes(pass, cwd, seatedMatrix) {
|
|
343
242
|
if (!seatedMatrix) {
|
|
@@ -368,11 +267,7 @@ var Compile = class _Compile extends BaseCommand {
|
|
|
368
267
|
}
|
|
369
268
|
this.reportPropagation(report);
|
|
370
269
|
}
|
|
371
|
-
/**
|
|
372
|
-
* Renders the fan-out the refresh above performed. Kept out of the refresh's
|
|
373
|
-
* catch on purpose: a project the fan-out could not reach is reported as that,
|
|
374
|
-
* not as a failure to refresh the type unions — which did succeed.
|
|
375
|
-
*/
|
|
270
|
+
/** Outside the refresh's catch: an unreachable project is not a failed refresh. */
|
|
376
271
|
reportPropagation(report) {
|
|
377
272
|
this.reportProjectsOutOfReach(report.propagated);
|
|
378
273
|
for (const projectPath of report.propagated.failed) {
|
|
@@ -380,66 +275,80 @@ var Compile = class _Compile extends BaseCommand {
|
|
|
380
275
|
}
|
|
381
276
|
this.reportFanOut(report);
|
|
382
277
|
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
278
|
+
async runCompilePass(pass, cwd) {
|
|
279
|
+
const { projectDir } = pass;
|
|
280
|
+
this.announcePass(pass);
|
|
281
|
+
const seatedMatrix = await this.seatMatrixForPass(projectDir);
|
|
282
|
+
const { allSkills, totalSkillCount } = await this.discoverAllSkills(projectDir);
|
|
283
|
+
const compiles = await this.announceWhetherPassCompiles(pass, totalSkillCount);
|
|
284
|
+
if (!compiles) return false;
|
|
285
|
+
await this.warnUnresolvedStackSkills(projectDir, allSkills);
|
|
286
|
+
await this.warnScopeDroppedStackPairs(projectDir);
|
|
287
|
+
await this.recompilePassAgents(pass, allSkills);
|
|
288
|
+
await this.refreshConfigTypes(pass, cwd, seatedMatrix);
|
|
289
|
+
this.log("");
|
|
290
|
+
this.logSuccess(`${pass.label} compile complete!`);
|
|
291
|
+
this.log("");
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
announcePass({ label, projectDir, installation }) {
|
|
386
295
|
this.log("");
|
|
387
296
|
this.log(`Compiling ${label.toLowerCase()} agents...`);
|
|
388
297
|
this.log("");
|
|
389
298
|
verbose(` Project: ${projectDir}`);
|
|
390
299
|
verbose(` Agents: ${installation.agentsDir}`);
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
if (
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
this.log(`No skills
|
|
398
|
-
return
|
|
300
|
+
}
|
|
301
|
+
/** A pass with no skills still compiles when its config declares base agents only. */
|
|
302
|
+
async announceWhetherPassCompiles(pass, totalSkillCount) {
|
|
303
|
+
if (totalSkillCount > 0) return true;
|
|
304
|
+
const passName = pass.label.toLowerCase();
|
|
305
|
+
if (await declaresOnlyBaseAgents(pass)) {
|
|
306
|
+
this.log(`No skills configured for ${passName} pass, compiling base agents`);
|
|
307
|
+
return true;
|
|
399
308
|
}
|
|
400
|
-
|
|
401
|
-
|
|
309
|
+
this.log(`No skills found for ${passName} pass, skipping`);
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
async recompilePassAgents(pass, skills) {
|
|
313
|
+
const { projectDir, installation, sourcePath, scopeFilter } = pass;
|
|
402
314
|
this.log(STATUS_MESSAGES.RECOMPILING_AGENTS);
|
|
403
315
|
try {
|
|
404
316
|
const recompileResult = await compileAgents({
|
|
405
317
|
projectDir,
|
|
406
318
|
sourcePath,
|
|
407
|
-
skills
|
|
319
|
+
skills,
|
|
408
320
|
pluginDir: projectDir,
|
|
409
321
|
outputDir: installation.agentsDir,
|
|
410
322
|
...scopeFilter !== void 0 && { scopeFilter }
|
|
411
323
|
});
|
|
412
|
-
|
|
413
|
-
const summary = recompileSummary(
|
|
414
|
-
rewritten.length,
|
|
415
|
-
compiled.length - rewritten.length,
|
|
416
|
-
`${label.toLowerCase()} agent`
|
|
417
|
-
);
|
|
418
|
-
if (failed.length > 0) {
|
|
419
|
-
this.log(`${summary} (${failed.length} failed)`);
|
|
420
|
-
for (const warning of warnings) {
|
|
421
|
-
this.warn(warning);
|
|
422
|
-
}
|
|
423
|
-
} else if (compiled.length > 0) {
|
|
424
|
-
this.log(summary);
|
|
425
|
-
} else {
|
|
426
|
-
this.log(INFO_MESSAGES.NO_AGENTS_TO_RECOMPILE);
|
|
427
|
-
if (label === "Project") {
|
|
428
|
-
await this.hintGlobalScopedAgents(projectDir);
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
if (compiled.length > 0) {
|
|
432
|
-
verbose(` Compiled: ${compiled.join(", ")}`);
|
|
433
|
-
}
|
|
324
|
+
await this.reportRecompile(recompileResult, pass);
|
|
434
325
|
} catch (error) {
|
|
435
326
|
this.log(ERROR_MESSAGES.FAILED_COMPILE_AGENTS);
|
|
436
327
|
this.handleError(error);
|
|
437
328
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
329
|
+
}
|
|
330
|
+
async reportRecompile({ compiled, rewritten, failed, warnings }, { label, projectDir }) {
|
|
331
|
+
const summary = recompileSummary(
|
|
332
|
+
rewritten.length,
|
|
333
|
+
compiled.length - rewritten.length,
|
|
334
|
+
`${label.toLowerCase()} agent`
|
|
335
|
+
);
|
|
336
|
+
if (failed.length > 0) {
|
|
337
|
+
this.log(`${summary} (${failed.length} failed)`);
|
|
338
|
+
for (const warning of warnings) {
|
|
339
|
+
this.warn(warning);
|
|
340
|
+
}
|
|
341
|
+
} else if (compiled.length > 0) {
|
|
342
|
+
this.log(summary);
|
|
343
|
+
} else {
|
|
344
|
+
this.log(INFO_MESSAGES.NO_AGENTS_TO_RECOMPILE);
|
|
345
|
+
if (label === "Project") {
|
|
346
|
+
await this.hintGlobalScopedAgents(projectDir);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
if (compiled.length > 0) {
|
|
350
|
+
verbose(` Compiled: ${compiled.join(", ")}`);
|
|
351
|
+
}
|
|
443
352
|
}
|
|
444
353
|
};
|
|
445
354
|
function buildCompilePasses(installations, cwd, agentDefs) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/commands/compile.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport os from \"os\";\nimport { unique } from \"remeda\";\nimport { BaseCommand } from \"../base-command\";\nimport { setVerbose, verbose } from \"../utils/logger\";\nimport {\n detectBothInstallations,\n type BothInstallations,\n loadAgentDefs,\n type AgentDefs,\n compileAgents,\n discoverInstalledSkills,\n type DiscoveredSkills,\n} from \"../lib/operations\";\nimport {\n ConfigLoadError,\n effectivelyExcludedSkillIds,\n isActiveAt,\n loadProjectConfig,\n loadInstalledConfig,\n resolveSource,\n} from \"../lib/configuration\";\nimport { getStackSkillIds, resolveAgentConfigToSkills } from \"../lib/stacks\";\nimport { loadSkillsMatrixFromSource, type UnusableSkillMetadata } from \"../lib/loading\";\nimport { STANDARD_FILES } from \"../consts\";\nimport { EXIT_CODES } from \"../lib/exit-codes\";\nimport { getErrorMessage } from \"../utils/errors\";\nimport { plural } from \"../utils/string\";\nimport {\n ERROR_MESSAGES,\n STATUS_MESSAGES,\n INFO_MESSAGES,\n configTypesRefreshFailed,\n globalScopedAgentsHint,\n recompileSummary,\n registeredProjectUpdateFailed,\n scopeBlockedStackAssignment,\n skillMetadataUnusableDetail,\n skillMetadataUnusableError,\n} from \"../utils/messages\";\nimport { reconcileTypesFromDisk, type GateReport } from \"../lib/config-gate/index.js\";\nimport { unofferablePlacementsFound } from \"../lib/hosts/configured-placements.js\";\nimport { providerInUse } from \"../lib/installation/install-layout.js\";\nimport {\n providerFlag,\n providerNamedBy,\n refuseAnAmbiguousInstallation,\n} from \"../lib/installation/provider-flag.js\";\nimport { hostCompileNotices } from \"../lib/hosts/host-compile-notices.js\";\nimport type { Installation } from \"../lib/installation\";\nimport type { SkillScope } from \"../types/config\";\nimport type {\n AgentDefinition,\n AgentName,\n MergedSkillsMatrix,\n ProjectConfig,\n SkillDefinitionMap,\n SkillId,\n StackAgentConfig,\n} from \"../types\";\n\nexport default class Compile extends BaseCommand {\n static summary = \"Compile agents using local skills and agent definitions\";\n\n static description =\n \"Compile agents with resolved skill references. Compiles to the Claude plugin directory.\";\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> --verbose\",\n ];\n\n static flags = {\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Enable verbose logging\",\n default: false,\n }),\n provider: providerFlag(),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Compile);\n setVerbose(flags.verbose);\n const cwd = process.cwd();\n\n // First, and before anything reads a folder: every path below resolves its provider through\n // `providerInUse`, which answers by ROSTER ORDER when a scope holds one installation of each —\n // so a compile with no flag rewrote the Claude one of a project that also has a Codex one, and\n // said nothing anywhere about which it had been about. `edit`, `uninstall`, `share` and\n // `eject` have refused this since C7b and `doctor` reports it as a finding; these two were the\n // hole, and they are the two that WRITE.\n await refuseAnAmbiguousInstallation(\n cwd,\n \"compile\",\n providerNamedBy(flags.provider),\n (message) => this.error(message, { exit: EXIT_CODES.INVALID_ARGS }),\n );\n await this.ensureConfigReadable(cwd);\n const installations = await this.detectInstallations(cwd);\n await this.refuseUnofferablePlacements(cwd);\n await this.resolveAndLogSource(cwd);\n const agentDefs = await this.loadAgentDefsOrFail();\n await this.runCompilePasses(installations, agentDefs, cwd);\n await this.reportWhatThisHostCannotCarry(installations, cwd);\n }\n\n /**\n * What this host could not carry, once per run and after the passes.\n *\n * AFTER, because the trust half of it is a question about the tree as it now stands: a project\n * whose role files this run just wrote is exactly the one whose user has to trust it, and asking\n * before the write would answer about the previous state.\n *\n * `init` prints the same lines in the same order — {@link hostCompileNotices} is the one place\n * either of them gets them from, so the two commands cannot drift into saying different things\n * about one tree.\n */\n private async reportWhatThisHostCannotCarry(\n installations: BothInstallations,\n cwd: string,\n ): Promise<void> {\n const root = rootThisRunCompiled(installations, cwd);\n\n for (const notice of await hostCompileNotices(providerInUse(root), cwd)) {\n this.log(notice);\n }\n }\n\n private async detectInstallations(cwd: string): Promise<BothInstallations> {\n let installations: BothInstallations;\n try {\n installations = await detectBothInstallations(cwd);\n } catch (error) {\n // A corrupt config (file present but unparseable) must not let compile run\n // config-less — that resurrects every deselected agent. Hard-error naming\n // the offending file before any compilation happens.\n if (error instanceof ConfigLoadError) {\n this.error(error.message, { exit: EXIT_CODES.ERROR });\n }\n throw error;\n }\n\n if (!installations.global && !installations.project) {\n this.error(ERROR_MESSAGES.NO_INSTALLATION, {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n return installations;\n }\n\n /**\n * Refuses a configuration asking for a mode/scope cell its own host does not offer, BEFORE\n * anything is discovered, compiled or written.\n *\n * **The install path's pre-flight cannot cover this, and nothing ties a folder's contents to\n * its name.** `config.ts` carries no provider field — the ruling forbids one, so that a saved\n * configuration installs onto either provider — which means a user who copies\n * `.agents-inc/claude/` to `.agents-inc/codex/` has a Codex installation holding a\n * configuration that never met `init --from --provider codex`'s refusal. This is the command\n * that turns a configuration into files on disk, so it is the one that has to ask again.\n *\n * Both scopes, because a project inherits its global's rows and an unofferable row in either\n * file is a row this run would act on. Each installation is asked about its OWN host: the two\n * scopes can be on different providers, and asking one host about the other's configuration is\n * how a refusal fires on a cell that is offered where the skill actually lives.\n */\n private async refuseUnofferablePlacements(cwd: string): Promise<void> {\n const [finding] = await unofferablePlacementsFound(cwd);\n if (finding !== undefined) this.error(finding, { exit: EXIT_CODES.ERROR });\n }\n\n /**\n * Names where the marketplace came from — the project's own config first, then the global\n * one, then the default. `compile` takes no `--marketplace`: it recompiles an installation\n * that already recorded which marketplace its skill references answer to, and reading\n * a different one would write agents against a catalogue config.ts does not name.\n */\n private async resolveAndLogSource(projectDir: string): Promise<void> {\n this.log(STATUS_MESSAGES.RESOLVING_SOURCE);\n try {\n // ABORT on an unreadable config, and unreachable with one: `detectInstallation` reads the\n // same file first and already hard-errors, at both scopes — verified by hand at both.\n // The posture is recorded anyway, because what makes it unreachable is a guard in another\n // command's private helper rather than anything visible from here.\n const sourceConfig = await resolveSource({ caller: \"stored\", projectDir });\n this.log(`Marketplace: ${sourceConfig.sourceOrigin}`);\n } catch (error) {\n this.log(ERROR_MESSAGES.FAILED_RESOLVE_SOURCE);\n this.handleError(error);\n }\n }\n\n private async loadAgentDefsOrFail(): Promise<AgentDefs> {\n this.log(STATUS_MESSAGES.LOADING_AGENT_PARTIALS);\n try {\n const defs = await loadAgentDefs();\n this.log(\"Agent partials loaded\");\n verbose(` Agents: ${defs.agentSourcePaths.agentsDir}`);\n return defs;\n } catch (error) {\n this.log(ERROR_MESSAGES.FAILED_LOAD_AGENT_PARTIALS);\n this.handleError(error);\n }\n }\n\n private async runCompilePasses(\n installations: BothInstallations,\n agentDefs: AgentDefs,\n cwd: string,\n ): Promise<void> {\n const passes = buildCompilePasses(installations, cwd, agentDefs);\n\n let passesCompiled = 0;\n for (const pass of passes) {\n const compiled = await this.runCompilePass(pass, cwd);\n if (compiled) passesCompiled++;\n }\n\n if (passesCompiled === 0) {\n this.error(ERROR_MESSAGES.NO_SKILLS_TO_COMPILE, { exit: EXIT_CODES.ERROR });\n }\n }\n\n /**\n * Discovers what this pass compiles from, and refuses the run when any installed\n * skill's metadata.yaml exists but describes no skill — before a count is printed,\n * an agent is written or the type unions are regenerated. Skipping such a skill is\n * what the config-types pass already does; loading it anyway is what this pass\n * used to do, so a single run both loaded and skipped the same file.\n */\n private async discoverAllSkills(projectDir: string): Promise<DiscoveredSkills> {\n this.log(STATUS_MESSAGES.DISCOVERING_SKILLS);\n const result = await discoverInstalledSkills(projectDir);\n if (result.unusableMetadata.length > 0) {\n this.refuseUnusableSkillMetadata(result.unusableMetadata);\n }\n if (result.totalSkillCount === 0) return result;\n this.log(formatDiscoveryMessage(result));\n return result;\n }\n\n /**\n * Names each offending file and its reason, then exits. The detail is LOGGED and\n * only the refusal is raised: oclif hard-wraps error text at the terminal width,\n * and a path broken across two lines is one nobody can copy.\n */\n private refuseUnusableSkillMetadata(entries: UnusableSkillMetadata[]): never {\n for (const entry of entries) {\n this.log(skillMetadataUnusableDetail(entry));\n }\n this.error(skillMetadataUnusableError(entries), { exit: EXIT_CODES.ERROR });\n }\n\n /**\n * A stack skill that is not among the discovered skills is dropped from every\n * agent that references it. The resolver only records that at verbose level, so\n * the default output would claim a successful recompile of an agent that no\n * longer matches config.ts. Name each dropped skill instead.\n */\n private async warnUnresolvedStackSkills(\n projectDir: string,\n allSkills: SkillDefinitionMap,\n ): Promise<void> {\n const loaded = await loadProjectConfig(projectDir);\n if (!loaded?.config.stack) return;\n\n const excludedIds = effectivelyExcludedSkillIds(loaded.config.skills);\n const unresolved = getStackSkillIds(loaded.config.stack).filter(\n (id) => !excludedIds.has(id) && !(id in allSkills),\n );\n\n for (const id of unresolved) {\n this.warn(\n `Skill '${id}' is configured but was not found — agents will be compiled without it.`,\n );\n }\n }\n\n /**\n * `config.ts` is the hand-editable half of the pair, so it can declare a pair the scope\n * rule forbids: a GLOBAL sub-agent whose stack carries a PROJECT-scoped skill. The\n * compile-time filter in `buildCompileAgents` drops that reference on the way to the\n * resolver and `compile` rewrites nothing in `config.ts`, so the row survives and is\n * dropped again on every future run — while the recompile summary reports a clean pass\n * over an agent that no longer carries what its own config says it does.\n *\n * The sibling of {@link warnUnresolvedStackSkills} one layer over: there the skill is\n * missing from disk, here it is present and unreachable from that sub-agent.\n */\n private async warnScopeDroppedStackPairs(projectDir: string): Promise<void> {\n const loaded = await loadProjectConfig(projectDir);\n if (!loaded?.config.stack) return;\n\n for (const [skillId, agentNames] of findScopeDroppedStackPairs(loaded.config)) {\n this.warn(scopeBlockedStackAssignment(agentNames, skillId));\n }\n }\n\n /**\n * The project pass compiled no agents, but the project config may still declare\n * global-scope agents whose stack lives in the global config. Without a pointer\n * the \"No agents to recompile\" line reads as a silent no-op after a global stack\n * change, so name the global context and the count.\n */\n private async hintGlobalScopedAgents(projectDir: string): Promise<void> {\n const loaded = await loadInstalledConfig(projectDir);\n if (!loaded) return;\n\n const globalAgentCount = loaded.config.agents.filter(\n (agent) => !agent.excluded && agent.scope === \"global\",\n ).length;\n if (globalAgentCount === 0) return;\n\n this.log(globalScopedAgentsHint(globalAgentCount));\n }\n\n /**\n * Loads this pass's skills catalogue and returns it, seating the module-level\n * singleton (`matrix` in `matrix-provider.ts`) on the way — which is what the\n * RENDER needs, because `compileAgents` reaches the catalogue through\n * `stacks-loader.ts`'s `statedUsageFor`/`liveCategoryOf` and those read the\n * singleton directly rather than any value a caller threads through. Called\n * first, before anything in the pass renders. Left unseated, the singleton stays\n * at its process-start default (`BUILT_IN_MATRIX`, which never carries a local\n * skill), so a locally-installed skill's stated `usageGuidance` silently falls\n * back to the generic per-category placeholder — different bytes from what\n * `install` last wrote, so a following `compile` rewrites every agent that\n * carries one.\n *\n * Scoped to `pass.projectDir`, never the invoking `cwd`: a global pass must seat\n * the global installation's own local skills, not the invoking directory's.\n *\n * `skipExtraSources: true` is NOT a divergence from a full multi-source\n * load: extra-source loading only annotates each skill's\n * `availableSources`/`activeSource` — it never adds skills\n * or categories to the matrix, and neither the render path nor the config-types\n * writer ever reads those annotations, so the emitted output is byte-identical\n * either way (pinned by the skipExtraSources parity test in\n * local-installer.test.ts). Skipping avoids fetching every registered extra\n * source (network on a cold cache, plus unreachable-remote warnings) on this\n * offline compile path. `matrixOnly` keeps the default-source path itself\n * offline too.\n *\n * The seated matrix is RETURNED as well as seated, and `null` on a failure, so\n * the two halves can take the postures they each need. The RENDER degrades: it\n * reads the singleton whatever happens, and falls back to the same\n * category-placeholder behavior compile had before this seat existed. The type\n * refresh ABORTS on `null` — it derives every union from the catalogue, so with\n * none loaded it would narrow them to whatever the built-in catalogue happens\n * to carry, dropping every marketplace-only and local category and, at global\n * scope, propagating that into every registered project.\n */\n private async seatMatrixForPass(projectDir: string): Promise<MergedSkillsMatrix | null> {\n try {\n const { matrix: seated } = await loadSkillsMatrixFromSource({\n projectDir,\n skipExtraSources: true,\n matrixOnly: true,\n });\n return seated;\n } catch (error) {\n this.warn(`Failed to load skills matrix for ${projectDir}: ${getErrorMessage(error)}`);\n return null;\n }\n }\n\n /**\n * The documented hand-edit workflow is \"edit config.ts, then run compile\", and\n * the type unions in config-types.ts are derived from config.ts — so a compile\n * pass that leaves them untouched strands stale unions after a hand-edit.\n * Regenerates them from the scope's persisted config exactly as\n * `writeConfigByScope` would: standalone narrowed unions at global scope, import-and-\n * extend at project scope. A failed refresh downgrades to a warning — the\n * compiled agents are already written and remain valid; only the type unions\n * may still be stale.\n *\n * Takes the catalogue {@link seatMatrixForPass} returned rather than reading the\n * singleton it seated, so this refresh cannot run against a seat that is not the\n * one this pass asked for. `null` means the seat failed, and the refresh is\n * skipped whole: every union here is DERIVED from the catalogue, so writing them\n * without one is not a degraded answer but a wrong one — the unions narrow to\n * the built-in catalogue's own categories, and `config.ts` beside them still\n * keys its `stack` under the ones that just vanished, so the pair stops\n * type-checking. Skipping falls under the same warning as any other failed\n * refresh, for the same reason.\n */\n private async refreshConfigTypes(\n pass: CompilePass,\n cwd: string,\n seatedMatrix: MergedSkillsMatrix | null,\n ): Promise<void> {\n if (!seatedMatrix) {\n this.warn(\n configTypesRefreshFailed(`no skills catalogue could be loaded for ${pass.projectDir}`),\n );\n return;\n }\n\n let report: GateReport;\n try {\n const loaded = await loadInstalledConfig(pass.projectDir);\n if (!loaded) {\n verbose(\n `No config found at ${pass.projectDir} — skipping ${STANDARD_FILES.CONFIG_TYPES_TS} refresh`,\n );\n return;\n }\n\n // `cwd` is excluded from the fan-out, which only a global pass can perform:\n // whatever this invocation was run from is this command's own subject, so a\n // fan-out must never reach back into it.\n report = await reconcileTypesFromDisk(\n pass.projectDir,\n loaded.config,\n { matrix: seatedMatrix, agents: pass.agents },\n { currentProjectDir: cwd },\n );\n this.log(INFO_MESSAGES.CONFIG_TYPES_REFRESHED);\n } catch (error) {\n this.warn(configTypesRefreshFailed(getErrorMessage(error)));\n return;\n }\n\n this.reportPropagation(report);\n }\n\n /**\n * Renders the fan-out the refresh above performed. Kept out of the refresh's\n * catch on purpose: a project the fan-out could not reach is reported as that,\n * not as a failure to refresh the type unions — which did succeed.\n */\n private reportPropagation(report: GateReport): void {\n this.reportProjectsOutOfReach(report.propagated);\n for (const projectPath of report.propagated.failed) {\n this.warn(registeredProjectUpdateFailed(projectPath));\n }\n this.reportFanOut(report);\n }\n\n /** Runs one pass, and answers whether it compiled rather than skipping for want of anything to. */\n private async runCompilePass(params: CompilePass, cwd: string): Promise<boolean> {\n const { label, projectDir, installation, sourcePath, scopeFilter } = params;\n\n this.log(\"\");\n this.log(`Compiling ${label.toLowerCase()} agents...`);\n this.log(\"\");\n\n verbose(` Project: ${projectDir}`);\n verbose(` Agents: ${installation.agentsDir}`);\n\n // Before anything below reads the matrix.\n const seatedMatrix = await this.seatMatrixForPass(projectDir);\n\n const { allSkills, totalSkillCount } = await this.discoverAllSkills(projectDir);\n const compilesBaseAgents = totalSkillCount === 0 && (await declaresOnlyBaseAgents(params));\n\n if (compilesBaseAgents) {\n this.log(`No skills configured for ${label.toLowerCase()} pass, compiling base agents`);\n } else if (totalSkillCount === 0) {\n // A run is one pass, so a skipped pass is a refused run — and a refused run writes nothing,\n // config-types.ts included (owner ruling).\n this.log(`No skills found for ${label.toLowerCase()} pass, skipping`);\n return false;\n }\n\n await this.warnUnresolvedStackSkills(projectDir, allSkills);\n await this.warnScopeDroppedStackPairs(projectDir);\n\n this.log(STATUS_MESSAGES.RECOMPILING_AGENTS);\n try {\n const recompileResult = await compileAgents({\n projectDir,\n sourcePath,\n skills: allSkills,\n pluginDir: projectDir,\n outputDir: installation.agentsDir,\n ...(scopeFilter !== undefined && { scopeFilter }),\n });\n\n const { compiled, rewritten, failed, warnings } = recompileResult;\n const summary = recompileSummary(\n rewritten.length,\n compiled.length - rewritten.length,\n `${label.toLowerCase()} agent`,\n );\n\n if (failed.length > 0) {\n this.log(`${summary} (${failed.length} failed)`);\n for (const warning of warnings) {\n this.warn(warning);\n }\n } else if (compiled.length > 0) {\n this.log(summary);\n } else {\n this.log(INFO_MESSAGES.NO_AGENTS_TO_RECOMPILE);\n if (label === \"Project\") {\n await this.hintGlobalScopedAgents(projectDir);\n }\n }\n\n if (compiled.length > 0) {\n verbose(` Compiled: ${compiled.join(\", \")}`);\n }\n } catch (error) {\n this.log(ERROR_MESSAGES.FAILED_COMPILE_AGENTS);\n this.handleError(error);\n }\n\n await this.refreshConfigTypes(params, cwd, seatedMatrix);\n\n this.log(\"\");\n this.logSuccess(`${label} compile complete!`);\n this.log(\"\");\n\n return true;\n }\n}\n\ntype CompilePass = {\n label: \"Global\" | \"Project\";\n projectDir: string;\n installation: Installation;\n sourcePath: string;\n agents: Partial<Record<AgentName, AgentDefinition>>;\n scopeFilter?: SkillScope;\n};\n\n/**\n * The single pass this invocation owns.\n *\n * A compile run inside a project is a PROJECT-scope operation and writes nothing\n * outside that project: it compiles the project's own agents and refreshes the\n * project's own type unions, and never the global install's or another\n * registered project's. Propagation is a global operation's consequence — the\n * global config is what every project's config inlines — and a project compile\n * is not one.\n *\n * The global pass is therefore reached only where no project installation is in\n * play: at the home directory (where `detectBothInstallations` returns no\n * project by construction), or in a directory that has no config of its own, so\n * the global install is the only thing there is to compile.\n *\n * `scopeFilter` still narrows the project pass whenever both installations\n * exist: the project's config inlines the global entries, so an unfiltered pass\n * would compile global-scoped agents into the project's own agents directory.\n */\nfunction buildCompilePasses(\n installations: BothInstallations,\n cwd: string,\n agentDefs: AgentDefs,\n): CompilePass[] {\n const { sourcePath, agents } = agentDefs;\n\n if (installations.project) {\n return [\n {\n label: \"Project\",\n projectDir: cwd,\n installation: installations.project,\n sourcePath,\n agents,\n ...(installations.hasBoth && { scopeFilter: \"project\" as const }),\n },\n ];\n }\n\n if (installations.global) {\n return [\n {\n label: \"Global\",\n projectDir: os.homedir(),\n installation: installations.global,\n sourcePath,\n agents,\n },\n ];\n }\n\n return [];\n}\n\n/**\n * The install root this run compiled, which the reports after the passes read the provider off.\n *\n * The root {@link buildCompilePasses} picks, read the same way it picks it: a project installation\n * is this run's subject and the global one is what a directory with none is about. Asking `cwd`\n * alone would answer Claude for a project that has no installation of its own under a Codex\n * global.\n */\nfunction rootThisRunCompiled(installations: BothInstallations, cwd: string): string {\n return installations.project ? cwd : os.homedir();\n}\n\n/**\n * Whether a pass that discovered no skill still has something to compile: sub-agents its config\n * pins on with no skill at all, which the editor produces (\"no skills — base agent\") and `init`\n * compiles like any other roster — `compileAgentsAllScopes` asks nothing about skills. The roster\n * is read the way `compileAgents` reads it: active rows, narrowed to the pass's scope when it has\n * one.\n *\n * A config that DECLARES a skill, none of which is on disk, is not this. It is an installation\n * whose skills were lost, and compiling it would rewrite every sub-agent without them — so that\n * pass is still skipped and, with no other pass compiling, still refused.\n */\nasync function declaresOnlyBaseAgents(pass: CompilePass): Promise<boolean> {\n const loaded = await loadInstalledConfig(pass.projectDir);\n if (!loaded) return false;\n\n const { skills, agents } = loaded.config;\n const declaresASkill = skills.some((skill) => !skill.excluded);\n const compilesAnAgent = agents.some((agent) =>\n pass.scopeFilter === undefined ? !agent.excluded : isActiveAt(agent, pass.scopeFilter),\n );\n return !declaresASkill && compilesAnAgent;\n}\n\n/**\n * Every project-scoped skill that a GLOBAL sub-agent's stack assigns to itself, with the\n * sub-agents that assign it — exactly the pairs `buildCompileAgents`' scope filter drops on\n * the way to the resolver.\n *\n * Grouped by skill rather than emitted per pair, so one sentence accounts for every\n * sub-agent one skill was kept away from.\n */\nfunction findScopeDroppedStackPairs(config: ProjectConfig): [SkillId, AgentName[]][] {\n const stack = config.stack ?? {};\n const globalAgentNames = config.agents\n .filter((agent) => isActiveAt(agent, \"global\"))\n .map((agent) => agent.name);\n const projectScopedIds = unique(\n config.skills.filter((skill) => isActiveAt(skill, \"project\")).map((skill) => skill.id),\n );\n\n return projectScopedIds\n .map((skillId): [SkillId, AgentName[]] => [\n skillId,\n globalAgentNames.filter((agentName) => stackAssignsSkill(stack[agentName], skillId)),\n ])\n .filter(([, agentNames]) => agentNames.length > 0);\n}\n\n/** True when this sub-agent's stack names the skill, in any of its categories. */\nfunction stackAssignsSkill(agentStack: StackAgentConfig | undefined, skillId: SkillId): boolean {\n if (!agentStack) return false;\n return resolveAgentConfigToSkills(agentStack).some((ref) => ref.id === skillId);\n}\n\nfunction formatDiscoveryMessage(result: DiscoveredSkills): string {\n const { totalSkillCount, pluginSkillCount } = result;\n const localCount = totalSkillCount - pluginSkillCount;\n\n if (pluginSkillCount > 0 && localCount > 0) {\n return `Discovered ${plural(totalSkillCount, \"skill\")} (${pluginSkillCount} from plugins, ${localCount} local)`;\n }\n\n return pluginSkillCount > 0\n ? `Discovered ${plural(pluginSkillCount, \"skill\")} from plugins`\n : `Discovered ${plural(totalSkillCount, \"local skill\")}`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,aAAa;AACtB,OAAO,QAAQ;AACf,SAAS,cAAc;AA2DvB,IAAqB,UAArB,MAAqB,iBAAgB,YAAY;AAAA,EAC/C,OAAO,UAAU;AAAA,EAEjB,OAAO,cACL;AAAA,EAEF,OAAO,WAAW;AAAA,IAChB;AAAA,IACA;AAAA,EACF;AAAA,EAEA,OAAO,QAAQ;AAAA,IACb,SAAS,MAAM,QAAQ;AAAA,MACrB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,UAAU,aAAa;AAAA,EACzB;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,QAAO;AAC1C,eAAW,MAAM,OAAO;AACxB,UAAM,MAAM,QAAQ,IAAI;AAQxB,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA,gBAAgB,MAAM,QAAQ;AAAA,MAC9B,CAAC,YAAY,KAAK,MAAM,SAAS,EAAE,MAAM,WAAW,aAAa,CAAC;AAAA,IACpE;AACA,UAAM,KAAK,qBAAqB,GAAG;AACnC,UAAM,gBAAgB,MAAM,KAAK,oBAAoB,GAAG;AACxD,UAAM,KAAK,4BAA4B,GAAG;AAC1C,UAAM,KAAK,oBAAoB,GAAG;AAClC,UAAM,YAAY,MAAM,KAAK,oBAAoB;AACjD,UAAM,KAAK,iBAAiB,eAAe,WAAW,GAAG;AACzD,UAAM,KAAK,8BAA8B,eAAe,GAAG;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAc,8BACZ,eACA,KACe;AACf,UAAM,OAAO,oBAAoB,eAAe,GAAG;AAEnD,eAAW,UAAU,MAAM,mBAAmB,cAAc,IAAI,GAAG,GAAG,GAAG;AACvE,WAAK,IAAI,MAAM;AAAA,IACjB;AAAA,EACF;AAAA,EAEA,MAAc,oBAAoB,KAAyC;AACzE,QAAI;AACJ,QAAI;AACF,sBAAgB,MAAM,wBAAwB,GAAG;AAAA,IACnD,SAAS,OAAO;AAId,UAAI,iBAAiB,iBAAiB;AACpC,aAAK,MAAM,MAAM,SAAS,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,MACtD;AACA,YAAM;AAAA,IACR;AAEA,QAAI,CAAC,cAAc,UAAU,CAAC,cAAc,SAAS;AACnD,WAAK,MAAM,eAAe,iBAAiB;AAAA,QACzC,MAAM,WAAW;AAAA,MACnB,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAc,4BAA4B,KAA4B;AACpE,UAAM,CAAC,OAAO,IAAI,MAAM,2BAA2B,GAAG;AACtD,QAAI,YAAY,OAAW,MAAK,MAAM,SAAS,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,EAC3E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,oBAAoB,YAAmC;AACnE,SAAK,IAAI,gBAAgB,gBAAgB;AACzC,QAAI;AAKF,YAAM,eAAe,MAAM,cAAc,EAAE,QAAQ,UAAU,WAAW,CAAC;AACzE,WAAK,IAAI,gBAAgB,aAAa,YAAY,EAAE;AAAA,IACtD,SAAS,OAAO;AACd,WAAK,IAAI,eAAe,qBAAqB;AAC7C,WAAK,YAAY,KAAK;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,MAAc,sBAA0C;AACtD,SAAK,IAAI,gBAAgB,sBAAsB;AAC/C,QAAI;AACF,YAAM,OAAO,MAAM,cAAc;AACjC,WAAK,IAAI,uBAAuB;AAChC,cAAQ,aAAa,KAAK,iBAAiB,SAAS,EAAE;AACtD,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,IAAI,eAAe,0BAA0B;AAClD,WAAK,YAAY,KAAK;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,MAAc,iBACZ,eACA,WACA,KACe;AACf,UAAM,SAAS,mBAAmB,eAAe,KAAK,SAAS;AAE/D,QAAI,iBAAiB;AACrB,eAAW,QAAQ,QAAQ;AACzB,YAAM,WAAW,MAAM,KAAK,eAAe,MAAM,GAAG;AACpD,UAAI,SAAU;AAAA,IAChB;AAEA,QAAI,mBAAmB,GAAG;AACxB,WAAK,MAAM,eAAe,sBAAsB,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IAC5E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,kBAAkB,YAA+C;AAC7E,SAAK,IAAI,gBAAgB,kBAAkB;AAC3C,UAAM,SAAS,MAAM,wBAAwB,UAAU;AACvD,QAAI,OAAO,iBAAiB,SAAS,GAAG;AACtC,WAAK,4BAA4B,OAAO,gBAAgB;AAAA,IAC1D;AACA,QAAI,OAAO,oBAAoB,EAAG,QAAO;AACzC,SAAK,IAAI,uBAAuB,MAAM,CAAC;AACvC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,4BAA4B,SAAyC;AAC3E,eAAW,SAAS,SAAS;AAC3B,WAAK,IAAI,4BAA4B,KAAK,CAAC;AAAA,IAC7C;AACA,SAAK,MAAM,2BAA2B,OAAO,GAAG,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,0BACZ,YACA,WACe;AACf,UAAM,SAAS,MAAM,kBAAkB,UAAU;AACjD,QAAI,CAAC,QAAQ,OAAO,MAAO;AAE3B,UAAM,cAAc,4BAA4B,OAAO,OAAO,MAAM;AACpE,UAAM,aAAa,iBAAiB,OAAO,OAAO,KAAK,EAAE;AAAA,MACvD,CAAC,OAAO,CAAC,YAAY,IAAI,EAAE,KAAK,EAAE,MAAM;AAAA,IAC1C;AAEA,eAAW,MAAM,YAAY;AAC3B,WAAK;AAAA,QACH,UAAU,EAAE;AAAA,MACd;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAc,2BAA2B,YAAmC;AAC1E,UAAM,SAAS,MAAM,kBAAkB,UAAU;AACjD,QAAI,CAAC,QAAQ,OAAO,MAAO;AAE3B,eAAW,CAAC,SAAS,UAAU,KAAK,2BAA2B,OAAO,MAAM,GAAG;AAC7E,WAAK,KAAK,4BAA4B,YAAY,OAAO,CAAC;AAAA,IAC5D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,uBAAuB,YAAmC;AACtE,UAAM,SAAS,MAAM,oBAAoB,UAAU;AACnD,QAAI,CAAC,OAAQ;AAEb,UAAM,mBAAmB,OAAO,OAAO,OAAO;AAAA,MAC5C,CAAC,UAAU,CAAC,MAAM,YAAY,MAAM,UAAU;AAAA,IAChD,EAAE;AACF,QAAI,qBAAqB,EAAG;AAE5B,SAAK,IAAI,uBAAuB,gBAAgB,CAAC;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsCA,MAAc,kBAAkB,YAAwD;AACtF,QAAI;AACF,YAAM,EAAE,QAAQ,OAAO,IAAI,MAAM,2BAA2B;AAAA,QAC1D;AAAA,QACA,kBAAkB;AAAA,QAClB,YAAY;AAAA,MACd,CAAC;AACD,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,KAAK,oCAAoC,UAAU,KAAK,gBAAgB,KAAK,CAAC,EAAE;AACrF,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MAAc,mBACZ,MACA,KACA,cACe;AACf,QAAI,CAAC,cAAc;AACjB,WAAK;AAAA,QACH,yBAAyB,2CAA2C,KAAK,UAAU,EAAE;AAAA,MACvF;AACA;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AACF,YAAM,SAAS,MAAM,oBAAoB,KAAK,UAAU;AACxD,UAAI,CAAC,QAAQ;AACX;AAAA,UACE,sBAAsB,KAAK,UAAU,oBAAe,eAAe,eAAe;AAAA,QACpF;AACA;AAAA,MACF;AAKA,eAAS,MAAM;AAAA,QACb,KAAK;AAAA,QACL,OAAO;AAAA,QACP,EAAE,QAAQ,cAAc,QAAQ,KAAK,OAAO;AAAA,QAC5C,EAAE,mBAAmB,IAAI;AAAA,MAC3B;AACA,WAAK,IAAI,cAAc,sBAAsB;AAAA,IAC/C,SAAS,OAAO;AACd,WAAK,KAAK,yBAAyB,gBAAgB,KAAK,CAAC,CAAC;AAC1D;AAAA,IACF;AAEA,SAAK,kBAAkB,MAAM;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,kBAAkB,QAA0B;AAClD,SAAK,yBAAyB,OAAO,UAAU;AAC/C,eAAW,eAAe,OAAO,WAAW,QAAQ;AAClD,WAAK,KAAK,8BAA8B,WAAW,CAAC;AAAA,IACtD;AACA,SAAK,aAAa,MAAM;AAAA,EAC1B;AAAA;AAAA,EAGA,MAAc,eAAe,QAAqB,KAA+B;AAC/E,UAAM,EAAE,OAAO,YAAY,cAAc,YAAY,YAAY,IAAI;AAErE,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,aAAa,MAAM,YAAY,CAAC,YAAY;AACrD,SAAK,IAAI,EAAE;AAEX,YAAQ,cAAc,UAAU,EAAE;AAClC,YAAQ,aAAa,aAAa,SAAS,EAAE;AAG7C,UAAM,eAAe,MAAM,KAAK,kBAAkB,UAAU;AAE5D,UAAM,EAAE,WAAW,gBAAgB,IAAI,MAAM,KAAK,kBAAkB,UAAU;AAC9E,UAAM,qBAAqB,oBAAoB,KAAM,MAAM,uBAAuB,MAAM;AAExF,QAAI,oBAAoB;AACtB,WAAK,IAAI,4BAA4B,MAAM,YAAY,CAAC,8BAA8B;AAAA,IACxF,WAAW,oBAAoB,GAAG;AAGhC,WAAK,IAAI,uBAAuB,MAAM,YAAY,CAAC,iBAAiB;AACpE,aAAO;AAAA,IACT;AAEA,UAAM,KAAK,0BAA0B,YAAY,SAAS;AAC1D,UAAM,KAAK,2BAA2B,UAAU;AAEhD,SAAK,IAAI,gBAAgB,kBAAkB;AAC3C,QAAI;AACF,YAAM,kBAAkB,MAAM,cAAc;AAAA,QAC1C;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,WAAW,aAAa;AAAA,QACxB,GAAI,gBAAgB,UAAa,EAAE,YAAY;AAAA,MACjD,CAAC;AAED,YAAM,EAAE,UAAU,WAAW,QAAQ,SAAS,IAAI;AAClD,YAAM,UAAU;AAAA,QACd,UAAU;AAAA,QACV,SAAS,SAAS,UAAU;AAAA,QAC5B,GAAG,MAAM,YAAY,CAAC;AAAA,MACxB;AAEA,UAAI,OAAO,SAAS,GAAG;AACrB,aAAK,IAAI,GAAG,OAAO,KAAK,OAAO,MAAM,UAAU;AAC/C,mBAAW,WAAW,UAAU;AAC9B,eAAK,KAAK,OAAO;AAAA,QACnB;AAAA,MACF,WAAW,SAAS,SAAS,GAAG;AAC9B,aAAK,IAAI,OAAO;AAAA,MAClB,OAAO;AACL,aAAK,IAAI,cAAc,sBAAsB;AAC7C,YAAI,UAAU,WAAW;AACvB,gBAAM,KAAK,uBAAuB,UAAU;AAAA,QAC9C;AAAA,MACF;AAEA,UAAI,SAAS,SAAS,GAAG;AACvB,gBAAQ,eAAe,SAAS,KAAK,IAAI,CAAC,EAAE;AAAA,MAC9C;AAAA,IACF,SAAS,OAAO;AACd,WAAK,IAAI,eAAe,qBAAqB;AAC7C,WAAK,YAAY,KAAK;AAAA,IACxB;AAEA,UAAM,KAAK,mBAAmB,QAAQ,KAAK,YAAY;AAEvD,SAAK,IAAI,EAAE;AACX,SAAK,WAAW,GAAG,KAAK,oBAAoB;AAC5C,SAAK,IAAI,EAAE;AAEX,WAAO;AAAA,EACT;AACF;AA8BA,SAAS,mBACP,eACA,KACA,WACe;AACf,QAAM,EAAE,YAAY,OAAO,IAAI;AAE/B,MAAI,cAAc,SAAS;AACzB,WAAO;AAAA,MACL;AAAA,QACE,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,cAAc,cAAc;AAAA,QAC5B;AAAA,QACA;AAAA,QACA,GAAI,cAAc,WAAW,EAAE,aAAa,UAAmB;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAEA,MAAI,cAAc,QAAQ;AACxB,WAAO;AAAA,MACL;AAAA,QACE,OAAO;AAAA,QACP,YAAY,GAAG,QAAQ;AAAA,QACvB,cAAc,cAAc;AAAA,QAC5B;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,CAAC;AACV;AAUA,SAAS,oBAAoB,eAAkC,KAAqB;AAClF,SAAO,cAAc,UAAU,MAAM,GAAG,QAAQ;AAClD;AAaA,eAAe,uBAAuB,MAAqC;AACzE,QAAM,SAAS,MAAM,oBAAoB,KAAK,UAAU;AACxD,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,EAAE,QAAQ,OAAO,IAAI,OAAO;AAClC,QAAM,iBAAiB,OAAO,KAAK,CAAC,UAAU,CAAC,MAAM,QAAQ;AAC7D,QAAM,kBAAkB,OAAO;AAAA,IAAK,CAAC,UACnC,KAAK,gBAAgB,SAAY,CAAC,MAAM,WAAW,WAAW,OAAO,KAAK,WAAW;AAAA,EACvF;AACA,SAAO,CAAC,kBAAkB;AAC5B;AAUA,SAAS,2BAA2B,QAAiD;AACnF,QAAM,QAAQ,OAAO,SAAS,CAAC;AAC/B,QAAM,mBAAmB,OAAO,OAC7B,OAAO,CAAC,UAAU,WAAW,OAAO,QAAQ,CAAC,EAC7C,IAAI,CAAC,UAAU,MAAM,IAAI;AAC5B,QAAM,mBAAmB;AAAA,IACvB,OAAO,OAAO,OAAO,CAAC,UAAU,WAAW,OAAO,SAAS,CAAC,EAAE,IAAI,CAAC,UAAU,MAAM,EAAE;AAAA,EACvF;AAEA,SAAO,iBACJ,IAAI,CAAC,YAAoC;AAAA,IACxC;AAAA,IACA,iBAAiB,OAAO,CAAC,cAAc,kBAAkB,MAAM,SAAS,GAAG,OAAO,CAAC;AAAA,EACrF,CAAC,EACA,OAAO,CAAC,CAAC,EAAE,UAAU,MAAM,WAAW,SAAS,CAAC;AACrD;AAGA,SAAS,kBAAkB,YAA0C,SAA2B;AAC9F,MAAI,CAAC,WAAY,QAAO;AACxB,SAAO,2BAA2B,UAAU,EAAE,KAAK,CAAC,QAAQ,IAAI,OAAO,OAAO;AAChF;AAEA,SAAS,uBAAuB,QAAkC;AAChE,QAAM,EAAE,iBAAiB,iBAAiB,IAAI;AAC9C,QAAM,aAAa,kBAAkB;AAErC,MAAI,mBAAmB,KAAK,aAAa,GAAG;AAC1C,WAAO,cAAc,OAAO,iBAAiB,OAAO,CAAC,KAAK,gBAAgB,kBAAkB,UAAU;AAAA,EACxG;AAEA,SAAO,mBAAmB,IACtB,cAAc,OAAO,kBAAkB,OAAO,CAAC,kBAC/C,cAAc,OAAO,iBAAiB,aAAa,CAAC;AAC1D;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/compile.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport os from \"os\";\nimport { unique } from \"remeda\";\nimport { BaseCommand } from \"../base-command\";\nimport { setVerbose, verbose } from \"../utils/logger\";\nimport {\n detectBothInstallations,\n type BothInstallations,\n loadAgentDefs,\n type AgentDefs,\n compileAgents,\n type CompilationResult,\n discoverInstalledSkills,\n type DiscoveredSkills,\n} from \"../lib/operations\";\nimport {\n ConfigLoadError,\n effectivelyExcludedSkillIds,\n isActiveAt,\n loadProjectConfig,\n loadInstalledConfig,\n resolveSource,\n} from \"../lib/configuration\";\nimport { getStackSkillIds, resolveAgentConfigToSkills } from \"../lib/stacks\";\nimport { loadSkillsMatrixFromSource, type UnusableSkillMetadata } from \"../lib/loading\";\nimport { STANDARD_FILES } from \"../consts\";\nimport { EXIT_CODES } from \"../lib/exit-codes\";\nimport { getErrorMessage } from \"../utils/errors\";\nimport { plural } from \"../utils/string\";\nimport {\n ERROR_MESSAGES,\n STATUS_MESSAGES,\n INFO_MESSAGES,\n configTypesRefreshFailed,\n globalScopedAgentsHint,\n recompileSummary,\n registeredProjectUpdateFailed,\n scopeBlockedStackAssignment,\n skillMetadataUnusableDetail,\n skillMetadataUnusableError,\n} from \"../utils/messages\";\nimport { reconcileTypesFromDisk, type GateReport } from \"../lib/config-gate/index.js\";\nimport { unofferablePlacementsFound } from \"../lib/hosts/configured-placements.js\";\nimport { providerInUse } from \"../lib/installation/install-layout.js\";\nimport {\n providerFlag,\n providerNamedBy,\n refuseAnAmbiguousInstallation,\n} from \"../lib/installation/provider-flag.js\";\nimport { hostCompileNotices } from \"../lib/hosts/host-compile-notices.js\";\nimport type { Installation } from \"../lib/installation\";\nimport type { SkillScope } from \"../types/config\";\nimport type {\n AgentDefinition,\n AgentName,\n MergedSkillsMatrix,\n ProjectConfig,\n SkillDefinitionMap,\n SkillId,\n StackAgentConfig,\n} from \"../types\";\n\nexport default class Compile extends BaseCommand {\n static summary = \"Compile agents using local skills and agent definitions\";\n\n static description =\n \"Compile agents with resolved skill references. Compiles to the Claude plugin directory.\";\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> --verbose\",\n ];\n\n static flags = {\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Enable verbose logging\",\n default: false,\n }),\n provider: providerFlag(),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Compile);\n setVerbose(flags.verbose);\n const cwd = process.cwd();\n\n // First: `providerInUse` below picks by roster order when a scope holds both providers.\n await refuseAnAmbiguousInstallation(\n cwd,\n \"compile\",\n providerNamedBy(flags.provider),\n (message) => this.error(message, { exit: EXIT_CODES.INVALID_ARGS }),\n );\n await this.ensureConfigReadable(cwd);\n const installations = await this.detectInstallations(cwd);\n await this.refuseUnofferablePlacements(cwd);\n await this.resolveAndLogSource(cwd);\n const agentDefs = await this.loadAgentDefsOrFail();\n await this.runCompilePasses(installations, agentDefs, cwd);\n await this.reportWhatThisHostCannotCarry(installations, cwd);\n }\n\n /** Runs after the passes, so the trust notice describes the tree this run wrote. */\n private async reportWhatThisHostCannotCarry(\n installations: BothInstallations,\n cwd: string,\n ): Promise<void> {\n const root = rootThisRunCompiled(installations, cwd);\n\n for (const notice of await hostCompileNotices(providerInUse(root), cwd)) {\n this.log(notice);\n }\n }\n\n private async detectInstallations(cwd: string): Promise<BothInstallations> {\n let installations: BothInstallations;\n try {\n installations = await detectBothInstallations(cwd);\n } catch (error) {\n // Compiling config-less would resurrect every deselected agent.\n if (error instanceof ConfigLoadError) {\n this.error(error.message, { exit: EXIT_CODES.ERROR });\n }\n throw error;\n }\n\n if (!installations.global && !installations.project) {\n this.error(ERROR_MESSAGES.NO_INSTALLATION, {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n return installations;\n }\n\n /**\n * Re-checked here because config.ts names no provider, so a copied installation folder can hold\n * a configuration its host never vetted at install.\n */\n private async refuseUnofferablePlacements(cwd: string): Promise<void> {\n const [finding] = await unofferablePlacementsFound(cwd);\n if (finding !== undefined) this.error(finding, { exit: EXIT_CODES.ERROR });\n }\n\n /** No `--marketplace`: an installation recompiles against the marketplace config.ts recorded. */\n private async resolveAndLogSource(projectDir: string): Promise<void> {\n this.log(STATUS_MESSAGES.RESOLVING_SOURCE);\n try {\n // ABORT on an unreadable config (already refused earlier by `detectInstallations`).\n const sourceConfig = await resolveSource({ caller: \"stored\", projectDir });\n this.log(`Marketplace: ${sourceConfig.sourceOrigin}`);\n } catch (error) {\n this.log(ERROR_MESSAGES.FAILED_RESOLVE_SOURCE);\n this.handleError(error);\n }\n }\n\n private async loadAgentDefsOrFail(): Promise<AgentDefs> {\n this.log(STATUS_MESSAGES.LOADING_AGENT_PARTIALS);\n try {\n const defs = await loadAgentDefs();\n this.log(\"Agent partials loaded\");\n verbose(` Agents: ${defs.agentSourcePaths.agentsDir}`);\n return defs;\n } catch (error) {\n this.log(ERROR_MESSAGES.FAILED_LOAD_AGENT_PARTIALS);\n this.handleError(error);\n }\n }\n\n private async runCompilePasses(\n installations: BothInstallations,\n agentDefs: AgentDefs,\n cwd: string,\n ): Promise<void> {\n const passes = buildCompilePasses(installations, cwd, agentDefs);\n\n let passesCompiled = 0;\n for (const pass of passes) {\n const compiled = await this.runCompilePass(pass, cwd);\n if (compiled) passesCompiled++;\n }\n\n if (passesCompiled === 0) {\n this.error(ERROR_MESSAGES.NO_SKILLS_TO_COMPILE, { exit: EXIT_CODES.ERROR });\n }\n }\n\n /** Refuses the run, before anything is written, when an installed skill's metadata is unusable. */\n private async discoverAllSkills(projectDir: string): Promise<DiscoveredSkills> {\n this.log(STATUS_MESSAGES.DISCOVERING_SKILLS);\n const result = await discoverInstalledSkills(projectDir);\n if (result.unusableMetadata.length > 0) {\n this.refuseUnusableSkillMetadata(result.unusableMetadata);\n }\n if (result.totalSkillCount === 0) return result;\n this.log(formatDiscoveryMessage(result));\n return result;\n }\n\n /** Detail is logged, not raised: oclif hard-wraps error text, which breaks copyable paths. */\n private refuseUnusableSkillMetadata(entries: UnusableSkillMetadata[]): never {\n for (const entry of entries) {\n this.log(skillMetadataUnusableDetail(entry));\n }\n this.error(skillMetadataUnusableError(entries), { exit: EXIT_CODES.ERROR });\n }\n\n /** The resolver drops a missing stack skill silently except at verbose level. */\n private async warnUnresolvedStackSkills(\n projectDir: string,\n allSkills: SkillDefinitionMap,\n ): Promise<void> {\n const loaded = await loadProjectConfig(projectDir);\n if (!loaded?.config.stack) return;\n\n const excludedIds = effectivelyExcludedSkillIds(loaded.config.skills);\n const unresolved = getStackSkillIds(loaded.config.stack).filter(\n (id) => !excludedIds.has(id) && !(id in allSkills),\n );\n\n for (const id of unresolved) {\n this.warn(\n `Skill '${id}' is configured but was not found — agents will be compiled without it.`,\n );\n }\n }\n\n /**\n * A hand-edited config.ts can give a global sub-agent a project-scoped skill, which the compile\n * filter silently drops on every run.\n */\n private async warnScopeDroppedStackPairs(projectDir: string): Promise<void> {\n const loaded = await loadProjectConfig(projectDir);\n if (!loaded?.config.stack) return;\n\n for (const [skillId, agentNames] of findScopeDroppedStackPairs(loaded.config)) {\n this.warn(scopeBlockedStackAssignment(agentNames, skillId));\n }\n }\n\n /** Points at global-scope agents so \"No agents to recompile\" doesn't read as a silent no-op. */\n private async hintGlobalScopedAgents(projectDir: string): Promise<void> {\n const loaded = await loadInstalledConfig(projectDir);\n if (!loaded) return;\n\n const globalAgentCount = loaded.config.agents.filter((agent) =>\n isActiveAt(agent, \"global\"),\n ).length;\n if (globalAgentCount === 0) return;\n\n this.log(globalScopedAgentsHint(globalAgentCount));\n }\n\n /**\n * Seats the matrix singleton the render reads (else local skills lose their stated usage), and\n * returns it, `null` on failure: the render degrades, the type refresh skips. Extra sources only\n * annotate skills, so skipping them keeps output identical and the path offline.\n */\n private async seatMatrixForPass(projectDir: string): Promise<MergedSkillsMatrix | null> {\n try {\n const { matrix: seated } = await loadSkillsMatrixFromSource({\n projectDir,\n skipExtraSources: true,\n matrixOnly: true,\n });\n return seated;\n } catch (error) {\n this.warn(`Failed to load skills matrix for ${projectDir}: ${getErrorMessage(error)}`);\n return null;\n }\n }\n\n /**\n * Regenerates config-types.ts after a hand-edit; failure only warns, as the agents are written.\n * Skipped without a catalogue, since unions derived from none would be wrong, not just stale.\n */\n private async refreshConfigTypes(\n pass: CompilePass,\n cwd: string,\n seatedMatrix: MergedSkillsMatrix | null,\n ): Promise<void> {\n if (!seatedMatrix) {\n this.warn(\n configTypesRefreshFailed(`no skills catalogue could be loaded for ${pass.projectDir}`),\n );\n return;\n }\n\n let report: GateReport;\n try {\n const loaded = await loadInstalledConfig(pass.projectDir);\n if (!loaded) {\n verbose(\n `No config found at ${pass.projectDir} — skipping ${STANDARD_FILES.CONFIG_TYPES_TS} refresh`,\n );\n return;\n }\n\n // A global pass's fan-out must not reach back into the invoking directory.\n report = await reconcileTypesFromDisk(\n pass.projectDir,\n loaded.config,\n { matrix: seatedMatrix, agents: pass.agents },\n { currentProjectDir: cwd },\n );\n this.log(INFO_MESSAGES.CONFIG_TYPES_REFRESHED);\n } catch (error) {\n this.warn(configTypesRefreshFailed(getErrorMessage(error)));\n return;\n }\n\n this.reportPropagation(report);\n }\n\n /** Outside the refresh's catch: an unreachable project is not a failed refresh. */\n private reportPropagation(report: GateReport): void {\n this.reportProjectsOutOfReach(report.propagated);\n for (const projectPath of report.propagated.failed) {\n this.warn(registeredProjectUpdateFailed(projectPath));\n }\n this.reportFanOut(report);\n }\n\n private async runCompilePass(pass: CompilePass, cwd: string): Promise<boolean> {\n const { projectDir } = pass;\n this.announcePass(pass);\n\n const seatedMatrix = await this.seatMatrixForPass(projectDir);\n const { allSkills, totalSkillCount } = await this.discoverAllSkills(projectDir);\n const compiles = await this.announceWhetherPassCompiles(pass, totalSkillCount);\n // A skipped pass is a refused run, which writes nothing, config-types.ts included.\n if (!compiles) return false;\n\n await this.warnUnresolvedStackSkills(projectDir, allSkills);\n await this.warnScopeDroppedStackPairs(projectDir);\n await this.recompilePassAgents(pass, allSkills);\n await this.refreshConfigTypes(pass, cwd, seatedMatrix);\n\n this.log(\"\");\n this.logSuccess(`${pass.label} compile complete!`);\n this.log(\"\");\n return true;\n }\n\n private announcePass({ label, projectDir, installation }: CompilePass): void {\n this.log(\"\");\n this.log(`Compiling ${label.toLowerCase()} agents...`);\n this.log(\"\");\n\n verbose(` Project: ${projectDir}`);\n verbose(` Agents: ${installation.agentsDir}`);\n }\n\n /** A pass with no skills still compiles when its config declares base agents only. */\n private async announceWhetherPassCompiles(\n pass: CompilePass,\n totalSkillCount: number,\n ): Promise<boolean> {\n if (totalSkillCount > 0) return true;\n\n const passName = pass.label.toLowerCase();\n if (await declaresOnlyBaseAgents(pass)) {\n this.log(`No skills configured for ${passName} pass, compiling base agents`);\n return true;\n }\n\n this.log(`No skills found for ${passName} pass, skipping`);\n return false;\n }\n\n private async recompilePassAgents(pass: CompilePass, skills: SkillDefinitionMap): Promise<void> {\n const { projectDir, installation, sourcePath, scopeFilter } = pass;\n\n this.log(STATUS_MESSAGES.RECOMPILING_AGENTS);\n try {\n const recompileResult = await compileAgents({\n projectDir,\n sourcePath,\n skills,\n pluginDir: projectDir,\n outputDir: installation.agentsDir,\n ...(scopeFilter !== undefined && { scopeFilter }),\n });\n await this.reportRecompile(recompileResult, pass);\n } catch (error) {\n this.log(ERROR_MESSAGES.FAILED_COMPILE_AGENTS);\n this.handleError(error);\n }\n }\n\n private async reportRecompile(\n { compiled, rewritten, failed, warnings }: CompilationResult,\n { label, projectDir }: CompilePass,\n ): Promise<void> {\n const summary = recompileSummary(\n rewritten.length,\n compiled.length - rewritten.length,\n `${label.toLowerCase()} agent`,\n );\n\n if (failed.length > 0) {\n this.log(`${summary} (${failed.length} failed)`);\n for (const warning of warnings) {\n this.warn(warning);\n }\n } else if (compiled.length > 0) {\n this.log(summary);\n } else {\n this.log(INFO_MESSAGES.NO_AGENTS_TO_RECOMPILE);\n if (label === \"Project\") {\n await this.hintGlobalScopedAgents(projectDir);\n }\n }\n\n if (compiled.length > 0) {\n verbose(` Compiled: ${compiled.join(\", \")}`);\n }\n }\n}\n\ntype CompilePass = {\n label: \"Global\" | \"Project\";\n projectDir: string;\n installation: Installation;\n sourcePath: string;\n agents: Partial<Record<AgentName, AgentDefinition>>;\n scopeFilter?: SkillScope;\n};\n\n/**\n * One pass: the project's when there is one (writing nothing outside it), else the global's.\n * `scopeFilter` keeps inlined global agents out of the project's agents directory.\n */\nfunction buildCompilePasses(\n installations: BothInstallations,\n cwd: string,\n agentDefs: AgentDefs,\n): CompilePass[] {\n const { sourcePath, agents } = agentDefs;\n\n if (installations.project) {\n return [\n {\n label: \"Project\",\n projectDir: cwd,\n installation: installations.project,\n sourcePath,\n agents,\n ...(installations.hasBoth && { scopeFilter: \"project\" as const }),\n },\n ];\n }\n\n if (installations.global) {\n return [\n {\n label: \"Global\",\n projectDir: os.homedir(),\n installation: installations.global,\n sourcePath,\n agents,\n },\n ];\n }\n\n return [];\n}\n\n/** Mirrors the root {@link buildCompilePasses} picks. */\nfunction rootThisRunCompiled(installations: BothInstallations, cwd: string): string {\n return installations.project ? cwd : os.homedir();\n}\n\n/**\n * A skill-less pass still compiles a config of base agents only. One that declares skills none of\n * which are on disk lost them, and is skipped rather than recompiled without them.\n */\nasync function declaresOnlyBaseAgents(pass: CompilePass): Promise<boolean> {\n const loaded = await loadInstalledConfig(pass.projectDir);\n if (!loaded) return false;\n\n const { skills, agents } = loaded.config;\n const declaresASkill = skills.some((skill) => !skill.excluded);\n const compilesAnAgent = agents.some((agent) =>\n pass.scopeFilter === undefined ? !agent.excluded : isActiveAt(agent, pass.scopeFilter),\n );\n return !declaresASkill && compilesAnAgent;\n}\n\n/** Project-scoped skills a global sub-agent's stack names, grouped by skill. */\nfunction findScopeDroppedStackPairs(config: ProjectConfig): [SkillId, AgentName[]][] {\n const stack = config.stack ?? {};\n const globalAgentNames = config.agents\n .filter((agent) => isActiveAt(agent, \"global\"))\n .map((agent) => agent.name);\n const projectScopedIds = unique(\n config.skills.filter((skill) => isActiveAt(skill, \"project\")).map((skill) => skill.id),\n );\n\n return projectScopedIds\n .map((skillId): [SkillId, AgentName[]] => [\n skillId,\n globalAgentNames.filter((agentName) => stackAssignsSkill(stack[agentName], skillId)),\n ])\n .filter(([, agentNames]) => agentNames.length > 0);\n}\n\nfunction stackAssignsSkill(agentStack: StackAgentConfig | undefined, skillId: SkillId): boolean {\n if (!agentStack) return false;\n return resolveAgentConfigToSkills(agentStack).some((ref) => ref.id === skillId);\n}\n\nfunction formatDiscoveryMessage(result: DiscoveredSkills): string {\n const { totalSkillCount, pluginSkillCount } = result;\n const localCount = totalSkillCount - pluginSkillCount;\n\n if (pluginSkillCount > 0 && localCount > 0) {\n return `Discovered ${plural(totalSkillCount, \"skill\")} (${pluginSkillCount} from plugins, ${localCount} local)`;\n }\n\n return pluginSkillCount > 0\n ? `Discovered ${plural(pluginSkillCount, \"skill\")} from plugins`\n : `Discovered ${plural(totalSkillCount, \"local skill\")}`;\n}\n"],"mappings":"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","names":[]}
|