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
package/dist/chunk-JIERYE6B.js
DELETED
|
@@ -1,480 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
installPluginSkills,
|
|
4
|
-
pluginInstallFailureError,
|
|
5
|
-
unbackedPluginInstallError,
|
|
6
|
-
unbackedPluginSkillIds
|
|
7
|
-
} from "./chunk-NKGYKOB7.js";
|
|
8
|
-
import {
|
|
9
|
-
clearTerminalScreen,
|
|
10
|
-
formatTerminalTooSmallMessage,
|
|
11
|
-
isTerminalLargeEnough
|
|
12
|
-
} from "./chunk-PHCPUQVR.js";
|
|
13
|
-
import {
|
|
14
|
-
STATUS_MESSAGES,
|
|
15
|
-
claudePluginMarketplaceAdd,
|
|
16
|
-
claudePluginMarketplaceExists,
|
|
17
|
-
claudePluginMarketplaceUpdate,
|
|
18
|
-
completedWithFailures,
|
|
19
|
-
configUnreadableError,
|
|
20
|
-
fetchMarketplace,
|
|
21
|
-
findConfigLoadFailures,
|
|
22
|
-
findUnusableSavedSkillMetadata,
|
|
23
|
-
getErrorMessage,
|
|
24
|
-
getStackSkillIds,
|
|
25
|
-
isHomeDirectory,
|
|
26
|
-
pluginsInstalled,
|
|
27
|
-
propagatedRecompileSummary,
|
|
28
|
-
resolveBranding,
|
|
29
|
-
savedSkillMetadataUnusableError,
|
|
30
|
-
scopeBlockedStackAssignment,
|
|
31
|
-
sharedConfigProjectScopeAtHome,
|
|
32
|
-
skillAssignedToNoAgent,
|
|
33
|
-
skillMetadataUnusableDetail,
|
|
34
|
-
verbose,
|
|
35
|
-
warn
|
|
36
|
-
} from "./chunk-XPDVAJDH.js";
|
|
37
|
-
import {
|
|
38
|
-
CLI_COLORS,
|
|
39
|
-
DEFAULT_BRANDING,
|
|
40
|
-
MIN_TERMINAL_SIZE,
|
|
41
|
-
isActiveAt
|
|
42
|
-
} from "./chunk-UITEKY2R.js";
|
|
43
|
-
|
|
44
|
-
// src/cli/lib/exit-codes.ts
|
|
45
|
-
var EXIT_CODES = {
|
|
46
|
-
SUCCESS: 0,
|
|
47
|
-
ERROR: 1,
|
|
48
|
-
INVALID_ARGS: 2,
|
|
49
|
-
NETWORK_ERROR: 3,
|
|
50
|
-
CANCELLED: 4,
|
|
51
|
-
/**
|
|
52
|
-
* The command ran to the end and part of what it set out to do did not happen.
|
|
53
|
-
*
|
|
54
|
-
* Distinct from {@link EXIT_CODES.ERROR} because the two ask opposite things of whoever reads
|
|
55
|
-
* them: an `ERROR` aborted, so nothing landed and the run can be repeated; this one landed and
|
|
56
|
-
* the repeat is the wrong move — what is owed is the remedy the output names, per failure.
|
|
57
|
-
* Collapsing it into `ERROR` would re-make the defect it exists to close one value along, and
|
|
58
|
-
* a spec asserting `not.toBe(0)` cannot tell a refusal from a partial apply either.
|
|
59
|
-
*
|
|
60
|
-
* It is raised at the END of a command, never mid-flight: the work completes first, which is
|
|
61
|
-
* the whole difference between this and `this.error`.
|
|
62
|
-
*/
|
|
63
|
-
COMPLETED_WITH_FAILURES: 5
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
// src/cli/base-command.ts
|
|
67
|
-
import { Command } from "@oclif/core";
|
|
68
|
-
import chalk from "chalk";
|
|
69
|
-
import { unique } from "remeda";
|
|
70
|
-
|
|
71
|
-
// src/cli/lib/operations/source/ensure-marketplace.ts
|
|
72
|
-
async function ensureMarketplace(sourceResult) {
|
|
73
|
-
const source = sourceResult.sourceConfig.source;
|
|
74
|
-
if (!sourceResult.marketplace) {
|
|
75
|
-
try {
|
|
76
|
-
const marketplaceResult = await fetchMarketplace(source);
|
|
77
|
-
sourceResult.marketplace = marketplaceResult.marketplace.name;
|
|
78
|
-
} catch (error) {
|
|
79
|
-
warn(`Could not resolve a marketplace from '${source}': ${getErrorMessage(error)}`);
|
|
80
|
-
return { marketplace: null, registered: false };
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
const marketplace = sourceResult.marketplace;
|
|
84
|
-
const exists = await claudePluginMarketplaceExists(marketplace);
|
|
85
|
-
if (!exists) {
|
|
86
|
-
const marketplaceSource = source.replace(/^github:/, "");
|
|
87
|
-
await claudePluginMarketplaceAdd(marketplaceSource);
|
|
88
|
-
return { marketplace, registered: true };
|
|
89
|
-
}
|
|
90
|
-
try {
|
|
91
|
-
await claudePluginMarketplaceUpdate(marketplace);
|
|
92
|
-
} catch {
|
|
93
|
-
warn("Could not update marketplace \u2014 continuing with cached version");
|
|
94
|
-
}
|
|
95
|
-
return { marketplace, registered: false };
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// src/cli/lib/operations/source/require-marketplace.ts
|
|
99
|
-
async function requireMarketplace(sourceResult, purpose) {
|
|
100
|
-
const mpResult = await ensureMarketplace(sourceResult);
|
|
101
|
-
if (!mpResult.marketplace) {
|
|
102
|
-
return {
|
|
103
|
-
ok: false,
|
|
104
|
-
error: `Cannot ${purpose}: marketplace could not be resolved from '${sourceResult.sourceConfig.source}'. Plugin install mode requires a marketplace \u2014 fix the marketplace or switch the affected skills to eject mode.`
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
return { ok: true, marketplace: mpResult.marketplace, registered: mpResult.registered };
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// src/cli/base-command.ts
|
|
111
|
-
var TERMINAL_RESIZE_POLL_MS = 500;
|
|
112
|
-
var terminalColumns = () => process.stdout.columns ?? MIN_TERMINAL_SIZE.COLS;
|
|
113
|
-
var terminalRows = () => process.stdout.rows ?? MIN_TERMINAL_SIZE.ROWS;
|
|
114
|
-
function isTerminalBigEnough() {
|
|
115
|
-
return isTerminalLargeEnough(terminalColumns(), terminalRows());
|
|
116
|
-
}
|
|
117
|
-
function waitForTerminal(isSatisfied) {
|
|
118
|
-
return new Promise((resolve) => {
|
|
119
|
-
const check = () => {
|
|
120
|
-
if (!isSatisfied()) return;
|
|
121
|
-
clearInterval(interval);
|
|
122
|
-
process.stdout.off("resize", check);
|
|
123
|
-
resolve();
|
|
124
|
-
};
|
|
125
|
-
const interval = setInterval(check, TERMINAL_RESIZE_POLL_MS);
|
|
126
|
-
process.stdout.on("resize", check);
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
function findUnassignedSkills(config) {
|
|
130
|
-
const assignedIds = new Set(config.stack ? getStackSkillIds(config.stack) : []);
|
|
131
|
-
const globalAgentNames = config.agents.filter((agent) => isActiveAt(agent, "global")).map((agent) => agent.name);
|
|
132
|
-
const unassignedIds = unique(
|
|
133
|
-
config.skills.filter((skill) => !skill.excluded).map((skill) => skill.id).filter((skillId) => !assignedIds.has(skillId))
|
|
134
|
-
);
|
|
135
|
-
return unassignedIds.map((skillId) => ({
|
|
136
|
-
skillId,
|
|
137
|
-
blockedBy: hasActiveProjectEntry(config.skills, skillId) ? globalAgentNames : []
|
|
138
|
-
}));
|
|
139
|
-
}
|
|
140
|
-
function hasActiveProjectEntry(skills, skillId) {
|
|
141
|
-
return skills.some((skill) => skill.id === skillId && isActiveAt(skill, "project"));
|
|
142
|
-
}
|
|
143
|
-
function projectScopedContent(result) {
|
|
144
|
-
return {
|
|
145
|
-
skillIds: result.skills.filter((skill) => isActiveAt(skill, "project")).map((skill) => skill.id),
|
|
146
|
-
agentNames: result.agentConfigs.filter((agent) => isActiveAt(agent, "project")).map((agent) => agent.name)
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
var BaseCommand = class extends Command {
|
|
150
|
-
/**
|
|
151
|
-
* Everything this run set out to do and did not, in the order it hit them.
|
|
152
|
-
*
|
|
153
|
-
* Non-empty is the whole of the exit-code decision — see {@link exitIfWorkIncomplete}. It is
|
|
154
|
-
* deliberately not a boolean: a non-zero exit whose output does not say what failed and what
|
|
155
|
-
* finishes it is worse than the silent success it replaces.
|
|
156
|
-
*
|
|
157
|
-
* Private, with {@link hasIncompleteWork} the only reading a subclass gets. A command records
|
|
158
|
-
* through the two methods below and asks whether anything is owed; the list itself is this
|
|
159
|
-
* class's, because it is this class that answers for it.
|
|
160
|
-
*/
|
|
161
|
-
incompleteWork = [];
|
|
162
|
-
async init() {
|
|
163
|
-
await super.init();
|
|
164
|
-
await this.ensureTerminalSize();
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Blocks the command from launching in a terminal below
|
|
168
|
-
* {@link MIN_TERMINAL_SIZE}. This runs once, before Ink mounts; the terminal
|
|
169
|
-
* shrinking mid-session is caught by the matching guard in `WizardLayout`.
|
|
170
|
-
*/
|
|
171
|
-
async ensureTerminalSize() {
|
|
172
|
-
if (isTerminalBigEnough()) return;
|
|
173
|
-
this.clearTerminal();
|
|
174
|
-
this.log(chalk.hex(CLI_COLORS.WARNING)(formatTerminalTooSmallMessage(terminalColumns())));
|
|
175
|
-
await waitForTerminal(isTerminalBigEnough);
|
|
176
|
-
}
|
|
177
|
-
handleError(error) {
|
|
178
|
-
const message = getErrorMessage(error);
|
|
179
|
-
this.error(message, { exit: EXIT_CODES.ERROR });
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* The name this run prints itself under: `branding.name` where a config supplies one, and
|
|
183
|
-
* {@link DEFAULT_BRANDING.NAME} everywhere else.
|
|
184
|
-
*
|
|
185
|
-
* **DEGRADE is the posture, and it is chosen here for every command that prints a name.**
|
|
186
|
-
* `loadSourceConfig` raises for a config that exists and cannot be evaluated, and three of the
|
|
187
|
-
* four callers must survive precisely that state: `doctor`'s whole job is naming it,
|
|
188
|
-
* `uninstall` is the only way out of it, and `eject` already catches the same fault one method
|
|
189
|
-
* down so an ejection that landed is never reported as a run that did nothing. A heading is
|
|
190
|
-
* decoration — nothing about a display name is worth refusing a command over, and refusing
|
|
191
|
-
* here would turn the branding wiring into a new way for an unreadable config to abort three
|
|
192
|
-
* commands that survive it today. `init` is the fourth caller and cannot reach the catch at
|
|
193
|
-
* all: {@link ensureConfigReadable} has already refused every config this would read.
|
|
194
|
-
*
|
|
195
|
-
* The cause is not swallowed: it goes to `verbose`, and the command's own config reader reports
|
|
196
|
-
* it in full where the user needs to act on it. Reporting it twice would put a warning about
|
|
197
|
-
* the configuration above a heading, which is the one line that has to be the first thing on
|
|
198
|
-
* screen.
|
|
199
|
-
*/
|
|
200
|
-
async resolveBrandingName(projectDir) {
|
|
201
|
-
try {
|
|
202
|
-
const branding = await resolveBranding(projectDir);
|
|
203
|
-
return branding.name;
|
|
204
|
-
} catch (error) {
|
|
205
|
-
verbose(`Could not read branding from the config: ${getErrorMessage(error)}`);
|
|
206
|
-
return DEFAULT_BRANDING.NAME;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
logSuccess(message) {
|
|
210
|
-
this.log(`\u2713 ${message}`);
|
|
211
|
-
}
|
|
212
|
-
logWarning(message) {
|
|
213
|
-
this.warn(message);
|
|
214
|
-
}
|
|
215
|
-
logInfo(message) {
|
|
216
|
-
this.log(message);
|
|
217
|
-
}
|
|
218
|
-
clearTerminal() {
|
|
219
|
-
clearTerminalScreen();
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
* Resolves the marketplace required for a plugin operation, or hard-exits with
|
|
223
|
-
* an actionable error when it cannot be resolved. `onRegistered` is invoked
|
|
224
|
-
* (when provided) if the marketplace had to be registered — init uses it to log.
|
|
225
|
-
*/
|
|
226
|
-
async requireMarketplaceOrExit(sourceResult, purpose, onRegistered) {
|
|
227
|
-
const required = await requireMarketplace(sourceResult, purpose);
|
|
228
|
-
if (!required.ok) {
|
|
229
|
-
this.error(required.error, { exit: EXIT_CODES.ERROR });
|
|
230
|
-
}
|
|
231
|
-
if (required.registered) {
|
|
232
|
-
onRegistered?.(required.marketplace);
|
|
233
|
-
}
|
|
234
|
-
return required.marketplace;
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Reports every constraint a completed selection breaks — a conflicting pair, an unmet
|
|
238
|
-
* requirement, an exclusive category with two picks.
|
|
239
|
-
*
|
|
240
|
-
* Shared by `init` and `edit` so one selection cannot be reported two ways. Both commands ask
|
|
241
|
-
* the same question of the same matrix, so a roster that draws a warning through one must draw
|
|
242
|
-
* the same warning through the other; `init` used to compute the answer and drop it, which is
|
|
243
|
-
* the whole reason this lives here rather than on either command.
|
|
244
|
-
*
|
|
245
|
-
* These are advisory (`ValidationError` in types/matrix.ts): the selection is installed either
|
|
246
|
-
* way and neither command's exit code turns on them, so they are warnings and not errors. The
|
|
247
|
-
* loop is its own guard — an accepted selection carries no errors and says nothing.
|
|
248
|
-
*/
|
|
249
|
-
reportValidationErrors(validation) {
|
|
250
|
-
for (const error of validation.errors) {
|
|
251
|
-
this.warn(error.message);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* Installs skill plugins and narrates the operation.
|
|
256
|
-
*
|
|
257
|
-
* Shared by `init` and `edit` for the same reason as {@link reportValidationErrors}:
|
|
258
|
-
* both run the SAME install against the same marketplace, so a line one prints about
|
|
259
|
-
* it the other owes. `edit` used to run it in silence — a real `claude plugin install`
|
|
260
|
-
* was indistinguishable in the output from nothing having happened.
|
|
261
|
-
*
|
|
262
|
-
* The skills nothing carries are refused FIRST, by name: an install no marketplace
|
|
263
|
-
* could serve is knowable before the Claude CLI is asked, and the generic
|
|
264
|
-
* install-failure advice is unfollowable for a skill the user wrote themselves.
|
|
265
|
-
*/
|
|
266
|
-
async installPluginSkillsReported(skills, marketplace, projectDir, matrix) {
|
|
267
|
-
const unbacked = unbackedPluginSkillIds(skills, matrix);
|
|
268
|
-
if (unbacked.length > 0) {
|
|
269
|
-
this.error(unbackedPluginInstallError(unbacked), { exit: EXIT_CODES.ERROR });
|
|
270
|
-
}
|
|
271
|
-
this.announcePluginInstall();
|
|
272
|
-
const result = await installPluginSkills(skills, marketplace, projectDir);
|
|
273
|
-
this.reportPluginInstalls(result);
|
|
274
|
-
return result;
|
|
275
|
-
}
|
|
276
|
-
/**
|
|
277
|
-
* The opening half of the narration above, exposed for the one caller that cannot
|
|
278
|
-
* use the whole of it: an eject→plugin migration installs each plugin and deletes
|
|
279
|
-
* that skill's working copy in the same step (see `executeMigration`), so the
|
|
280
|
-
* install it performs is not this command's to run.
|
|
281
|
-
*/
|
|
282
|
-
announcePluginInstall() {
|
|
283
|
-
this.log(STATUS_MESSAGES.INSTALLING_PLUGINS);
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* The closing half: what was installed, what was not, and the refusal to continue
|
|
287
|
-
* past a failure.
|
|
288
|
-
*
|
|
289
|
-
* The hard-error is part of the report rather than each caller's own postscript
|
|
290
|
-
* because it is the same rule everywhere — plugin install intent is inviolable, so
|
|
291
|
-
* a run that could not honor it must stop BEFORE any config records a marketplace
|
|
292
|
-
* `origin` for a skill with no plugin registration.
|
|
293
|
-
*/
|
|
294
|
-
reportPluginInstalls(result) {
|
|
295
|
-
for (const item of result.installed) {
|
|
296
|
-
this.log(` Installed ${item.ref}`);
|
|
297
|
-
}
|
|
298
|
-
for (const item of result.failed) {
|
|
299
|
-
this.warn(`Failed to install plugin ${item.id}: ${item.error}`);
|
|
300
|
-
}
|
|
301
|
-
if (result.failed.length > 0) {
|
|
302
|
-
this.error(pluginInstallFailureError(result.failed.length), { exit: EXIT_CODES.ERROR });
|
|
303
|
-
}
|
|
304
|
-
this.log(`${pluginsInstalled(result.installed.length)}
|
|
305
|
-
`);
|
|
306
|
-
}
|
|
307
|
-
/**
|
|
308
|
-
* Renders the recompile a gated write already performed on every OTHER registered
|
|
309
|
-
* project this run's global change was propagated into.
|
|
310
|
-
*
|
|
311
|
-
* Shared by all four commands that fan out — the count and its wording are one
|
|
312
|
-
* statement about one operation, and four copies of it had already drifted into two
|
|
313
|
-
* spellings of the same sentence.
|
|
314
|
-
*/
|
|
315
|
-
reportPropagatedRecompile(report) {
|
|
316
|
-
if (report.propagated.updated.length === 0) return;
|
|
317
|
-
const { rewrittenCount, unchangedCount, failedCount, warnings } = report.recompile;
|
|
318
|
-
for (const warning of warnings) {
|
|
319
|
-
this.warn(warning);
|
|
320
|
-
}
|
|
321
|
-
this.log(propagatedRecompileSummary(rewrittenCount, unchangedCount, failedCount));
|
|
322
|
-
}
|
|
323
|
-
/**
|
|
324
|
-
* Names every selected skill this save left in no sub-agent's stack, and — where the
|
|
325
|
-
* scope rule is why — every sub-agent it was kept away from.
|
|
326
|
-
*
|
|
327
|
-
* Shared by `init` and `edit` for the reason {@link reportValidationErrors} is: both
|
|
328
|
-
* build the stack from the same rules over the same selection, so a skill that reaches
|
|
329
|
-
* nothing through one reaches nothing through the other. The rule being reported is
|
|
330
|
-
* CORRECT and nothing here changes it — a project-scoped skill installs, is written to
|
|
331
|
-
* `config.ts`, and is loaded by nobody, which every other surface reports as a clean
|
|
332
|
-
* install.
|
|
333
|
-
*
|
|
334
|
-
* `compile` says the same thing about the same shape one layer over, for a config
|
|
335
|
-
* hand-edited into it — see `Compile.warnScopeDroppedStackPairs`.
|
|
336
|
-
*/
|
|
337
|
-
reportUnassignedSkills(config) {
|
|
338
|
-
for (const { skillId, blockedBy } of findUnassignedSkills(config)) {
|
|
339
|
-
this.warn(skillAssignedToNoAgent(skillId));
|
|
340
|
-
if (blockedBy.length > 0) {
|
|
341
|
-
this.warn(scopeBlockedStackAssignment(blockedBy, skillId));
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
/**
|
|
346
|
-
* Refuses to run when a config file exists but cannot be loaded.
|
|
347
|
-
*
|
|
348
|
-
* Both configs this run would read are checked, because both are read on the way through: a
|
|
349
|
-
* project's own `config.ts` and the global one every project write inlines. Checking up
|
|
350
|
-
* front is the whole point — an unreadable GLOBAL config otherwise surfaced only at the
|
|
351
|
-
* config write, after the wizard had copied skills and installed plugins, as a warning that
|
|
352
|
-
* the write never happened.
|
|
353
|
-
*
|
|
354
|
-
* A MISSING config is not a corrupt one and passes here untouched: it is the legitimate
|
|
355
|
-
* state `init` exists for, and the state `edit` reports as "no installation".
|
|
356
|
-
*/
|
|
357
|
-
async ensureConfigReadable(projectDir) {
|
|
358
|
-
const [failure] = await findConfigLoadFailures(projectDir);
|
|
359
|
-
if (failure) {
|
|
360
|
-
this.error(configUnreadableError(failure.message), { exit: EXIT_CODES.ERROR });
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
/**
|
|
364
|
-
* Refuses to run when a saved skill entry names a local skill that IS installed and whose
|
|
365
|
-
* metadata.yaml describes no skill.
|
|
366
|
-
*
|
|
367
|
-
* One layer below {@link ensureConfigReadable} and for the same reason: the config parses,
|
|
368
|
-
* and a file it points at does not. Both wizards resolve their saved roster against the
|
|
369
|
-
* loaded catalogue, and an id nothing can be loaded for reaches no screen — so without this
|
|
370
|
-
* the entry is dropped and reported as a skill the marketplace no longer carries, which is a
|
|
371
|
-
* removal the user never asked for and a sentence blaming the wrong thing.
|
|
372
|
-
*
|
|
373
|
-
* Only entries the catalogue does not carry are looked at, so a healthy install pays a
|
|
374
|
-
* filesystem read for nothing. An entry whose files are simply GONE is not refused — there
|
|
375
|
-
* is no file to repair, so it is removed with a reason that says so
|
|
376
|
-
* (`unresolvedSkillRemovalReasons`).
|
|
377
|
-
*
|
|
378
|
-
* Runs before the wizard mounts, which is the whole point: past that, a refusal costs the
|
|
379
|
-
* user the session they had already spent, and everything this protects has been rewritten.
|
|
380
|
-
*/
|
|
381
|
-
async ensureSavedSkillsReadable(savedSkills, matrix, projectDir) {
|
|
382
|
-
const unresolved = savedSkills.filter((saved) => !saved.excluded && !matrix.skills[saved.id]).map((saved) => saved.id);
|
|
383
|
-
if (unresolved.length === 0) return;
|
|
384
|
-
const unusable = await findUnusableSavedSkillMetadata(unresolved, savedSkills, projectDir);
|
|
385
|
-
if (unusable.length === 0) return;
|
|
386
|
-
for (const entry of unusable) {
|
|
387
|
-
this.log(skillMetadataUnusableDetail(entry));
|
|
388
|
-
}
|
|
389
|
-
this.error(savedSkillMetadataUnusableError(unusable), { exit: EXIT_CODES.ERROR });
|
|
390
|
-
}
|
|
391
|
-
/**
|
|
392
|
-
* Refuses a shared configuration carrying project-scoped content at the home directory.
|
|
393
|
-
*
|
|
394
|
-
* The home directory IS the global scope, and a global installation holds only global-scoped
|
|
395
|
-
* content. Both scopes resolve to the same files there — one config, one skills directory, one
|
|
396
|
-
* agents directory — so a project-scoped entry does not land somewhere else; it lands in the
|
|
397
|
-
* global config wearing a label that contradicts the file it is in, and `toClaudePluginScope`
|
|
398
|
-
* maps that declared scope onward, registering the skill against `$HOME` as a project. Nothing
|
|
399
|
-
* below this point reads the scope again, so whatever the boundary lets through becomes the
|
|
400
|
-
* truth.
|
|
401
|
-
*
|
|
402
|
-
* Shared by `init --from` and `edit --from` for the reason {@link reportValidationErrors} is
|
|
403
|
-
* shared: it is a fact about the payload and the directory, identical whichever command asked,
|
|
404
|
-
* and an invariant enforced on one producer and not the other is enforced nowhere. It matters
|
|
405
|
-
* more on the destructive one — `edit --from` reaches the same contradiction through the other
|
|
406
|
-
* door and can remove global entries on the way.
|
|
407
|
-
*
|
|
408
|
-
* The interactive producer has always answered this for itself — `isHomeDirectory(projectDir)`
|
|
409
|
-
* reaches the wizard session as `isGlobalRoot` and the scope toggles are inert under it — so
|
|
410
|
-
* this puts both `--from` paths on the rule the wizard already follows.
|
|
411
|
-
*
|
|
412
|
-
* It takes the DECODED selection, so it must run after the decode and can run no earlier: an
|
|
413
|
-
* all-global configuration is exactly what a global installation is for, and only the decode
|
|
414
|
-
* says which entries survived this catalogue and what scope each rests at. Every caller runs it
|
|
415
|
-
* before it reports a skip and before it writes anything, so a run about to be refused neither
|
|
416
|
-
* narrates nor mutates.
|
|
417
|
-
*/
|
|
418
|
-
refuseProjectScopedContentAtHome(result, projectDir) {
|
|
419
|
-
if (!isHomeDirectory(projectDir)) return;
|
|
420
|
-
const { skillIds, agentNames } = projectScopedContent(result);
|
|
421
|
-
if (skillIds.length === 0 && agentNames.length === 0) return;
|
|
422
|
-
this.error(sharedConfigProjectScopeAtHome(skillIds, agentNames), { exit: EXIT_CODES.ERROR });
|
|
423
|
-
}
|
|
424
|
-
/** Whether this run owes an account — the one thing a command may ask about the list. */
|
|
425
|
-
get hasIncompleteWork() {
|
|
426
|
-
return this.incompleteWork.length > 0;
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* Warns about work this run attempted and did not complete, and records it for the ending.
|
|
430
|
-
*
|
|
431
|
-
* Both halves, always. The warning stays at the point of failure because that is where it is
|
|
432
|
-
* explicable and where the surrounding output says what was being attempted; the record is
|
|
433
|
-
* what decides the exit code, and a failure the user is told about while the process reports
|
|
434
|
-
* success is exactly the state this closes.
|
|
435
|
-
*
|
|
436
|
-
* What it must never do is abort. Every caller sits past the point where the mutation it is
|
|
437
|
-
* reporting on has already happened, so stopping would relabel a state already committed to
|
|
438
|
-
* disk rather than prevent it — and would abandon the steps after it that can still land.
|
|
439
|
-
*
|
|
440
|
-
* The `recovery` sentences live in `INCOMPLETE_WORK_RECOVERY` in `utils/messages.ts`. One
|
|
441
|
-
* spelling per remedy is what matters; three spellings of "run compile" read as three
|
|
442
|
-
* different instructions.
|
|
443
|
-
*/
|
|
444
|
-
reportIncompleteWork(what, recovery) {
|
|
445
|
-
this.warn(what);
|
|
446
|
-
this.recordIncompleteWork(what, recovery);
|
|
447
|
-
}
|
|
448
|
-
/**
|
|
449
|
-
* The recording half alone, for a caller that has already said its piece: a recompile warns
|
|
450
|
-
* once per failed sub-agent with the compiler's own reason, so the ending names the roster
|
|
451
|
-
* those reasons belong to instead of repeating any of them.
|
|
452
|
-
*/
|
|
453
|
-
recordIncompleteWork(what, recovery) {
|
|
454
|
-
this.incompleteWork.push({ what, recovery });
|
|
455
|
-
}
|
|
456
|
-
/**
|
|
457
|
-
* The command's last word: what did not happen, what finishes it, and a non-zero exit.
|
|
458
|
-
*
|
|
459
|
-
* `this.exit` raises oclif's `ExitError`, which the framework carries to the process exit
|
|
460
|
-
* code and prints nothing for — so the account printed here is the whole of the output, with
|
|
461
|
-
* none of the `Error:` framing `this.error` would add to a command that in fact completed.
|
|
462
|
-
*
|
|
463
|
-
* A command that records must call this, or it files failures into a list nothing reads —
|
|
464
|
-
* which is the original silence wearing the mechanism built to close it, and is what
|
|
465
|
-
* `failure-reporting-classification.test.ts` holds every command in `src/cli/commands/` to.
|
|
466
|
-
*/
|
|
467
|
-
exitIfWorkIncomplete() {
|
|
468
|
-
if (!this.hasIncompleteWork) return;
|
|
469
|
-
this.log(`
|
|
470
|
-
${chalk.hex(CLI_COLORS.WARNING)(completedWithFailures(this.incompleteWork))}
|
|
471
|
-
`);
|
|
472
|
-
this.exit(EXIT_CODES.COMPLETED_WITH_FAILURES);
|
|
473
|
-
}
|
|
474
|
-
};
|
|
475
|
-
|
|
476
|
-
export {
|
|
477
|
-
EXIT_CODES,
|
|
478
|
-
BaseCommand
|
|
479
|
-
};
|
|
480
|
-
//# sourceMappingURL=chunk-JIERYE6B.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/lib/exit-codes.ts","../src/cli/base-command.ts","../src/cli/lib/operations/source/ensure-marketplace.ts","../src/cli/lib/operations/source/require-marketplace.ts"],"sourcesContent":["export const EXIT_CODES = {\n SUCCESS: 0,\n ERROR: 1,\n INVALID_ARGS: 2,\n NETWORK_ERROR: 3,\n CANCELLED: 4,\n /**\n * The command ran to the end and part of what it set out to do did not happen.\n *\n * Distinct from {@link EXIT_CODES.ERROR} because the two ask opposite things of whoever reads\n * them: an `ERROR` aborted, so nothing landed and the run can be repeated; this one landed and\n * the repeat is the wrong move — what is owed is the remedy the output names, per failure.\n * Collapsing it into `ERROR` would re-make the defect it exists to close one value along, and\n * a spec asserting `not.toBe(0)` cannot tell a refusal from a partial apply either.\n *\n * It is raised at the END of a command, never mid-flight: the work completes first, which is\n * the whole difference between this and `this.error`.\n */\n COMPLETED_WITH_FAILURES: 5,\n} as const;\n","import { Command } from \"@oclif/core\";\n\nimport chalk from \"chalk\";\nimport { unique } from \"remeda\";\n\nimport { CLI_COLORS, DEFAULT_BRANDING, MIN_TERMINAL_SIZE } from \"./consts.js\";\nimport { getErrorMessage } from \"./utils/errors.js\";\nimport { verbose } from \"./utils/logger.js\";\nimport {\n completedWithFailures,\n configUnreadableError,\n type IncompleteWork,\n pluginsInstalled,\n propagatedRecompileSummary,\n savedSkillMetadataUnusableError,\n scopeBlockedStackAssignment,\n sharedConfigProjectScopeAtHome,\n skillAssignedToNoAgent,\n skillMetadataUnusableDetail,\n STATUS_MESSAGES,\n} from \"./utils/messages.js\";\nimport {\n clearTerminalScreen,\n formatTerminalTooSmallMessage,\n isTerminalLargeEnough,\n} from \"./utils/terminal.js\";\nimport { EXIT_CODES } from \"./lib/exit-codes.js\";\nimport { isActiveAt } from \"./lib/configuration/scope-predicates.js\";\nimport { resolveBranding } from \"./lib/configuration/config.js\";\nimport { isHomeDirectory } from \"./lib/installation/index.js\";\nimport type { WizardResultV2 } from \"./components/wizard/wizard.js\";\nimport { getStackSkillIds } from \"./lib/stacks/index.js\";\nimport type {\n AgentName,\n MergedSkillsMatrix,\n ProjectConfig,\n SelectionValidation,\n SkillConfig,\n SkillId,\n} from \"./types/index.js\";\nimport { findConfigLoadFailures } from \"./lib/configuration/project-config.js\";\nimport { findUnusableSavedSkillMetadata } from \"./lib/skills/index.js\";\nimport { requireMarketplace } from \"./lib/operations/source/require-marketplace.js\";\nimport {\n installPluginSkills,\n pluginInstallFailureError,\n unbackedPluginInstallError,\n unbackedPluginSkillIds,\n type PluginInstallResult,\n} from \"./lib/operations/skills/install-plugin-skills.js\";\nimport type { GateReport } from \"./lib/config-gate/index.js\";\nimport type { SourceLoadResult } from \"./lib/loading/source-loader.js\";\n\n/**\n * How often the size gate re-reads the terminal while it is blocked. `resize` is what normally\n * ends the wait; the poll is the belt for the terminals and multiplexers that resize without\n * ever emitting one, and it is the only reason a blocked command is not a hung one there.\n */\nconst TERMINAL_RESIZE_POLL_MS = 500;\n\n// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- @types/node declares this as `number`; it is undefined whenever stdout is not a TTY\nconst terminalColumns = (): number => process.stdout.columns ?? MIN_TERMINAL_SIZE.COLS;\n\n// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- @types/node declares this as `number`; it is undefined whenever stdout is not a TTY\nconst terminalRows = (): number => process.stdout.rows ?? MIN_TERMINAL_SIZE.ROWS;\n\nfunction isTerminalBigEnough(): boolean {\n return isTerminalLargeEnough(terminalColumns(), terminalRows());\n}\n\n/**\n * Resolves the moment the terminal satisfies `isSatisfied` — on the resize event where there is\n * one, on the poll where there is not. Both listeners are torn down before resolving, so a\n * command that got past the gate leaves nothing behind holding the process open.\n */\nfunction waitForTerminal(isSatisfied: () => boolean): Promise<void> {\n return new Promise<void>((resolve) => {\n const check = () => {\n if (!isSatisfied()) return;\n clearInterval(interval);\n process.stdout.off(\"resize\", check);\n resolve();\n };\n const interval = setInterval(check, TERMINAL_RESIZE_POLL_MS);\n process.stdout.on(\"resize\", check);\n });\n}\n\n/** A selected skill no sub-agent's stack carries, and the sub-agents the scope rule blocked. */\ntype UnassignedSkill = { skillId: SkillId; blockedBy: AgentName[] };\n\n/**\n * Every active skill of a saved config that no agent's stack references, paired with the\n * global-scoped sub-agents that could not have carried it.\n *\n * `blockedBy` is empty for a global-scoped skill: the scope rule had no say there, and the\n * skill reached nothing for a different reason (no selected sub-agent the resolver\n * considers it relevant to). Naming sub-agents there would blame the wrong rule.\n */\nfunction findUnassignedSkills(config: ProjectConfig): UnassignedSkill[] {\n const assignedIds = new Set(config.stack ? getStackSkillIds(config.stack) : []);\n const globalAgentNames = config.agents\n .filter((agent) => isActiveAt(agent, \"global\"))\n .map((agent) => agent.name);\n\n const unassignedIds = unique(\n config.skills\n .filter((skill) => !skill.excluded)\n .map((skill) => skill.id)\n .filter((skillId) => !assignedIds.has(skillId)),\n );\n\n return unassignedIds.map((skillId) => ({\n skillId,\n blockedBy: hasActiveProjectEntry(config.skills, skillId) ? globalAgentNames : [],\n }));\n}\n\n/** True when an ACTIVE entry for this id sits at project scope — the only case the rule explains. */\nfunction hasActiveProjectEntry(skills: readonly SkillConfig[], skillId: SkillId): boolean {\n return skills.some((skill) => skill.id === skillId && isActiveAt(skill, \"project\"));\n}\n\n/**\n * What a decoded selection would file at PROJECT scope, split by kind because a skill's scope\n * and a sub-agent's are independent decisions in a payload — a refusal naming only one kind\n * would send the sharer to change the wrong entry.\n */\nfunction projectScopedContent(result: WizardResultV2): {\n skillIds: SkillId[];\n agentNames: AgentName[];\n} {\n return {\n skillIds: result.skills\n .filter((skill) => isActiveAt(skill, \"project\"))\n .map((skill) => skill.id),\n agentNames: result.agentConfigs\n .filter((agent) => isActiveAt(agent, \"project\"))\n .map((agent) => agent.name),\n };\n}\n\n/**\n * Nothing is inherited by every command, so this class declares no `baseFlags`.\n *\n * There was one — the marketplace flag — until naming a marketplace became `init`'s\n * decision alone (owner ruling 2026-08-09). Six commands were already opting out of it\n * through an exported empty-object cast; a flag one command wants is that command's flag,\n * so it is declared in `init` as `--marketplace` and the six opt-outs went with it.\n */\nexport abstract class BaseCommand extends Command {\n /**\n * Everything this run set out to do and did not, in the order it hit them.\n *\n * Non-empty is the whole of the exit-code decision — see {@link exitIfWorkIncomplete}. It is\n * deliberately not a boolean: a non-zero exit whose output does not say what failed and what\n * finishes it is worse than the silent success it replaces.\n *\n * Private, with {@link hasIncompleteWork} the only reading a subclass gets. A command records\n * through the two methods below and asks whether anything is owed; the list itself is this\n * class's, because it is this class that answers for it.\n */\n private readonly incompleteWork: IncompleteWork[] = [];\n\n async init(): Promise<void> {\n await super.init();\n await this.ensureTerminalSize();\n }\n\n /**\n * Blocks the command from launching in a terminal below\n * {@link MIN_TERMINAL_SIZE}. This runs once, before Ink mounts; the terminal\n * shrinking mid-session is caught by the matching guard in `WizardLayout`.\n */\n protected async ensureTerminalSize(): Promise<void> {\n if (isTerminalBigEnough()) return;\n\n this.clearTerminal();\n this.log(chalk.hex(CLI_COLORS.WARNING)(formatTerminalTooSmallMessage(terminalColumns())));\n\n await waitForTerminal(isTerminalBigEnough);\n }\n\n protected handleError(error: unknown): never {\n const message = getErrorMessage(error);\n this.error(message, { exit: EXIT_CODES.ERROR });\n }\n\n /**\n * The name this run prints itself under: `branding.name` where a config supplies one, and\n * {@link DEFAULT_BRANDING.NAME} everywhere else.\n *\n * **DEGRADE is the posture, and it is chosen here for every command that prints a name.**\n * `loadSourceConfig` raises for a config that exists and cannot be evaluated, and three of the\n * four callers must survive precisely that state: `doctor`'s whole job is naming it,\n * `uninstall` is the only way out of it, and `eject` already catches the same fault one method\n * down so an ejection that landed is never reported as a run that did nothing. A heading is\n * decoration — nothing about a display name is worth refusing a command over, and refusing\n * here would turn the branding wiring into a new way for an unreadable config to abort three\n * commands that survive it today. `init` is the fourth caller and cannot reach the catch at\n * all: {@link ensureConfigReadable} has already refused every config this would read.\n *\n * The cause is not swallowed: it goes to `verbose`, and the command's own config reader reports\n * it in full where the user needs to act on it. Reporting it twice would put a warning about\n * the configuration above a heading, which is the one line that has to be the first thing on\n * screen.\n */\n protected async resolveBrandingName(projectDir: string): Promise<string> {\n try {\n const branding = await resolveBranding(projectDir);\n return branding.name;\n } catch (error) {\n verbose(`Could not read branding from the config: ${getErrorMessage(error)}`);\n return DEFAULT_BRANDING.NAME;\n }\n }\n\n protected logSuccess(message: string): void {\n this.log(`✓ ${message}`);\n }\n\n protected logWarning(message: string): void {\n this.warn(message);\n }\n\n protected logInfo(message: string): void {\n this.log(message);\n }\n\n protected clearTerminal(): void {\n clearTerminalScreen();\n }\n\n /**\n * Resolves the marketplace required for a plugin operation, or hard-exits with\n * an actionable error when it cannot be resolved. `onRegistered` is invoked\n * (when provided) if the marketplace had to be registered — init uses it to log.\n */\n protected async requireMarketplaceOrExit(\n sourceResult: SourceLoadResult,\n purpose: string,\n onRegistered?: (marketplace: string) => void,\n ): Promise<string> {\n const required = await requireMarketplace(sourceResult, purpose);\n if (!required.ok) {\n this.error(required.error, { exit: EXIT_CODES.ERROR });\n }\n if (required.registered) {\n onRegistered?.(required.marketplace);\n }\n return required.marketplace;\n }\n\n /**\n * Reports every constraint a completed selection breaks — a conflicting pair, an unmet\n * requirement, an exclusive category with two picks.\n *\n * Shared by `init` and `edit` so one selection cannot be reported two ways. Both commands ask\n * the same question of the same matrix, so a roster that draws a warning through one must draw\n * the same warning through the other; `init` used to compute the answer and drop it, which is\n * the whole reason this lives here rather than on either command.\n *\n * These are advisory (`ValidationError` in types/matrix.ts): the selection is installed either\n * way and neither command's exit code turns on them, so they are warnings and not errors. The\n * loop is its own guard — an accepted selection carries no errors and says nothing.\n */\n protected reportValidationErrors(validation: SelectionValidation): void {\n for (const error of validation.errors) {\n this.warn(error.message);\n }\n }\n\n /**\n * Installs skill plugins and narrates the operation.\n *\n * Shared by `init` and `edit` for the same reason as {@link reportValidationErrors}:\n * both run the SAME install against the same marketplace, so a line one prints about\n * it the other owes. `edit` used to run it in silence — a real `claude plugin install`\n * was indistinguishable in the output from nothing having happened.\n *\n * The skills nothing carries are refused FIRST, by name: an install no marketplace\n * could serve is knowable before the Claude CLI is asked, and the generic\n * install-failure advice is unfollowable for a skill the user wrote themselves.\n */\n protected async installPluginSkillsReported(\n skills: SkillConfig[],\n marketplace: string,\n projectDir: string,\n matrix: MergedSkillsMatrix,\n ): Promise<PluginInstallResult> {\n const unbacked = unbackedPluginSkillIds(skills, matrix);\n if (unbacked.length > 0) {\n this.error(unbackedPluginInstallError(unbacked), { exit: EXIT_CODES.ERROR });\n }\n\n this.announcePluginInstall();\n const result = await installPluginSkills(skills, marketplace, projectDir);\n this.reportPluginInstalls(result);\n return result;\n }\n\n /**\n * The opening half of the narration above, exposed for the one caller that cannot\n * use the whole of it: an eject→plugin migration installs each plugin and deletes\n * that skill's working copy in the same step (see `executeMigration`), so the\n * install it performs is not this command's to run.\n */\n protected announcePluginInstall(): void {\n this.log(STATUS_MESSAGES.INSTALLING_PLUGINS);\n }\n\n /**\n * The closing half: what was installed, what was not, and the refusal to continue\n * past a failure.\n *\n * The hard-error is part of the report rather than each caller's own postscript\n * because it is the same rule everywhere — plugin install intent is inviolable, so\n * a run that could not honor it must stop BEFORE any config records a marketplace\n * `origin` for a skill with no plugin registration.\n */\n protected reportPluginInstalls(result: PluginInstallResult): void {\n for (const item of result.installed) {\n this.log(` Installed ${item.ref}`);\n }\n for (const item of result.failed) {\n this.warn(`Failed to install plugin ${item.id}: ${item.error}`);\n }\n if (result.failed.length > 0) {\n this.error(pluginInstallFailureError(result.failed.length), { exit: EXIT_CODES.ERROR });\n }\n this.log(`${pluginsInstalled(result.installed.length)}\\n`);\n }\n\n /**\n * Renders the recompile a gated write already performed on every OTHER registered\n * project this run's global change was propagated into.\n *\n * Shared by all four commands that fan out — the count and its wording are one\n * statement about one operation, and four copies of it had already drifted into two\n * spellings of the same sentence.\n */\n protected reportPropagatedRecompile(report: GateReport): void {\n if (report.propagated.updated.length === 0) return;\n\n const { rewrittenCount, unchangedCount, failedCount, warnings } = report.recompile;\n for (const warning of warnings) {\n this.warn(warning);\n }\n this.log(propagatedRecompileSummary(rewrittenCount, unchangedCount, failedCount));\n }\n\n /**\n * Names every selected skill this save left in no sub-agent's stack, and — where the\n * scope rule is why — every sub-agent it was kept away from.\n *\n * Shared by `init` and `edit` for the reason {@link reportValidationErrors} is: both\n * build the stack from the same rules over the same selection, so a skill that reaches\n * nothing through one reaches nothing through the other. The rule being reported is\n * CORRECT and nothing here changes it — a project-scoped skill installs, is written to\n * `config.ts`, and is loaded by nobody, which every other surface reports as a clean\n * install.\n *\n * `compile` says the same thing about the same shape one layer over, for a config\n * hand-edited into it — see `Compile.warnScopeDroppedStackPairs`.\n */\n protected reportUnassignedSkills(config: ProjectConfig): void {\n for (const { skillId, blockedBy } of findUnassignedSkills(config)) {\n this.warn(skillAssignedToNoAgent(skillId));\n if (blockedBy.length > 0) {\n this.warn(scopeBlockedStackAssignment(blockedBy, skillId));\n }\n }\n }\n\n /**\n * Refuses to run when a config file exists but cannot be loaded.\n *\n * Both configs this run would read are checked, because both are read on the way through: a\n * project's own `config.ts` and the global one every project write inlines. Checking up\n * front is the whole point — an unreadable GLOBAL config otherwise surfaced only at the\n * config write, after the wizard had copied skills and installed plugins, as a warning that\n * the write never happened.\n *\n * A MISSING config is not a corrupt one and passes here untouched: it is the legitimate\n * state `init` exists for, and the state `edit` reports as \"no installation\".\n */\n protected async ensureConfigReadable(projectDir: string): Promise<void> {\n const [failure] = await findConfigLoadFailures(projectDir);\n if (failure) {\n this.error(configUnreadableError(failure.message), { exit: EXIT_CODES.ERROR });\n }\n }\n\n /**\n * Refuses to run when a saved skill entry names a local skill that IS installed and whose\n * metadata.yaml describes no skill.\n *\n * One layer below {@link ensureConfigReadable} and for the same reason: the config parses,\n * and a file it points at does not. Both wizards resolve their saved roster against the\n * loaded catalogue, and an id nothing can be loaded for reaches no screen — so without this\n * the entry is dropped and reported as a skill the marketplace no longer carries, which is a\n * removal the user never asked for and a sentence blaming the wrong thing.\n *\n * Only entries the catalogue does not carry are looked at, so a healthy install pays a\n * filesystem read for nothing. An entry whose files are simply GONE is not refused — there\n * is no file to repair, so it is removed with a reason that says so\n * (`unresolvedSkillRemovalReasons`).\n *\n * Runs before the wizard mounts, which is the whole point: past that, a refusal costs the\n * user the session they had already spent, and everything this protects has been rewritten.\n */\n protected async ensureSavedSkillsReadable(\n savedSkills: readonly SkillConfig[],\n matrix: MergedSkillsMatrix,\n projectDir: string,\n ): Promise<void> {\n const unresolved = savedSkills\n .filter((saved) => !saved.excluded && !matrix.skills[saved.id])\n .map((saved) => saved.id);\n if (unresolved.length === 0) return;\n\n const unusable = await findUnusableSavedSkillMetadata(unresolved, savedSkills, projectDir);\n if (unusable.length === 0) return;\n\n // The detail is LOGGED and only the refusal is raised — oclif hard-wraps error text at the\n // terminal width, and a path broken across two lines is one nobody can copy. Same split\n // `compile` makes over the same verdict.\n for (const entry of unusable) {\n this.log(skillMetadataUnusableDetail(entry));\n }\n this.error(savedSkillMetadataUnusableError(unusable), { exit: EXIT_CODES.ERROR });\n }\n\n /**\n * Refuses a shared configuration carrying project-scoped content at the home directory.\n *\n * The home directory IS the global scope, and a global installation holds only global-scoped\n * content. Both scopes resolve to the same files there — one config, one skills directory, one\n * agents directory — so a project-scoped entry does not land somewhere else; it lands in the\n * global config wearing a label that contradicts the file it is in, and `toClaudePluginScope`\n * maps that declared scope onward, registering the skill against `$HOME` as a project. Nothing\n * below this point reads the scope again, so whatever the boundary lets through becomes the\n * truth.\n *\n * Shared by `init --from` and `edit --from` for the reason {@link reportValidationErrors} is\n * shared: it is a fact about the payload and the directory, identical whichever command asked,\n * and an invariant enforced on one producer and not the other is enforced nowhere. It matters\n * more on the destructive one — `edit --from` reaches the same contradiction through the other\n * door and can remove global entries on the way.\n *\n * The interactive producer has always answered this for itself — `isHomeDirectory(projectDir)`\n * reaches the wizard session as `isGlobalRoot` and the scope toggles are inert under it — so\n * this puts both `--from` paths on the rule the wizard already follows.\n *\n * It takes the DECODED selection, so it must run after the decode and can run no earlier: an\n * all-global configuration is exactly what a global installation is for, and only the decode\n * says which entries survived this catalogue and what scope each rests at. Every caller runs it\n * before it reports a skip and before it writes anything, so a run about to be refused neither\n * narrates nor mutates.\n */\n protected refuseProjectScopedContentAtHome(result: WizardResultV2, projectDir: string): void {\n if (!isHomeDirectory(projectDir)) return;\n\n const { skillIds, agentNames } = projectScopedContent(result);\n if (skillIds.length === 0 && agentNames.length === 0) return;\n\n this.error(sharedConfigProjectScopeAtHome(skillIds, agentNames), { exit: EXIT_CODES.ERROR });\n }\n\n /** Whether this run owes an account — the one thing a command may ask about the list. */\n protected get hasIncompleteWork(): boolean {\n return this.incompleteWork.length > 0;\n }\n\n /**\n * Warns about work this run attempted and did not complete, and records it for the ending.\n *\n * Both halves, always. The warning stays at the point of failure because that is where it is\n * explicable and where the surrounding output says what was being attempted; the record is\n * what decides the exit code, and a failure the user is told about while the process reports\n * success is exactly the state this closes.\n *\n * What it must never do is abort. Every caller sits past the point where the mutation it is\n * reporting on has already happened, so stopping would relabel a state already committed to\n * disk rather than prevent it — and would abandon the steps after it that can still land.\n *\n * The `recovery` sentences live in `INCOMPLETE_WORK_RECOVERY` in `utils/messages.ts`. One\n * spelling per remedy is what matters; three spellings of \"run compile\" read as three\n * different instructions.\n */\n protected reportIncompleteWork(what: string, recovery: string): void {\n this.warn(what);\n this.recordIncompleteWork(what, recovery);\n }\n\n /**\n * The recording half alone, for a caller that has already said its piece: a recompile warns\n * once per failed sub-agent with the compiler's own reason, so the ending names the roster\n * those reasons belong to instead of repeating any of them.\n */\n protected recordIncompleteWork(what: string, recovery: string): void {\n this.incompleteWork.push({ what, recovery });\n }\n\n /**\n * The command's last word: what did not happen, what finishes it, and a non-zero exit.\n *\n * `this.exit` raises oclif's `ExitError`, which the framework carries to the process exit\n * code and prints nothing for — so the account printed here is the whole of the output, with\n * none of the `Error:` framing `this.error` would add to a command that in fact completed.\n *\n * A command that records must call this, or it files failures into a list nothing reads —\n * which is the original silence wearing the mechanism built to close it, and is what\n * `failure-reporting-classification.test.ts` holds every command in `src/cli/commands/` to.\n */\n protected exitIfWorkIncomplete(): void {\n if (!this.hasIncompleteWork) return;\n\n this.log(`\\n${chalk.hex(CLI_COLORS.WARNING)(completedWithFailures(this.incompleteWork))}\\n`);\n this.exit(EXIT_CODES.COMPLETED_WITH_FAILURES);\n }\n}\n","import {\n claudePluginMarketplaceExists,\n claudePluginMarketplaceAdd,\n claudePluginMarketplaceUpdate,\n} from \"../../../utils/exec.js\";\nimport { fetchMarketplace } from \"../../loading/index.js\";\nimport { warn } from \"../../../utils/logger.js\";\nimport { getErrorMessage } from \"../../../utils/errors.js\";\nimport type { SourceLoadResult } from \"../../loading/source-loader.js\";\n\nexport type MarketplaceResult = {\n /** The resolved marketplace name, or null if no marketplace is configured. */\n marketplace: string | null;\n /** Whether a new marketplace was registered (vs. updated or already existed). */\n registered: boolean;\n};\n\n/**\n * Ensures the marketplace is registered with the Claude CLI.\n *\n * If the marketplace does not exist, registers it. If it exists, updates it.\n * Handles lazy marketplace name resolution when sourceResult.marketplace is undefined.\n *\n * Reports nothing on success — commands decide what to log based on the `registered`\n * flag — but never swallows a failure: `requireMarketplace` turns a null marketplace\n * into a hard error whose text cannot tell a transient fetch failure apart from a\n * source that genuinely ships no marketplace, so the cause is warned here or nowhere.\n */\nexport async function ensureMarketplace(\n sourceResult: SourceLoadResult,\n): Promise<MarketplaceResult> {\n const source = sourceResult.sourceConfig.source;\n\n if (!sourceResult.marketplace) {\n try {\n const marketplaceResult = await fetchMarketplace(source);\n sourceResult.marketplace = marketplaceResult.marketplace.name;\n } catch (error) {\n warn(`Could not resolve a marketplace from '${source}': ${getErrorMessage(error)}`);\n return { marketplace: null, registered: false };\n }\n }\n\n const marketplace = sourceResult.marketplace;\n const exists = await claudePluginMarketplaceExists(marketplace);\n\n if (!exists) {\n const marketplaceSource = source.replace(/^github:/, \"\");\n await claudePluginMarketplaceAdd(marketplaceSource);\n return { marketplace, registered: true };\n }\n\n try {\n await claudePluginMarketplaceUpdate(marketplace);\n } catch {\n warn(\"Could not update marketplace — continuing with cached version\");\n }\n\n return { marketplace, registered: false };\n}\n","import { ensureMarketplace } from \"./ensure-marketplace.js\";\nimport type { SourceLoadResult } from \"../../loading/source-loader.js\";\n\nexport type MarketplaceRequirement =\n { ok: true; marketplace: string; registered: boolean } | { ok: false; error: string };\n\n/**\n * Resolves the marketplace required for plugin operations. Plugin install\n * intent is inviolable — callers must hard-error on `ok: false` rather than\n * silently falling back to eject or skipping, and must do so BEFORE any\n * filesystem mutation so a failure leaves no partial state on disk.\n */\nexport async function requireMarketplace(\n sourceResult: SourceLoadResult,\n purpose: string,\n): Promise<MarketplaceRequirement> {\n const mpResult = await ensureMarketplace(sourceResult);\n if (!mpResult.marketplace) {\n return {\n ok: false,\n error:\n `Cannot ${purpose}: marketplace could not be resolved from '${sourceResult.sourceConfig.source}'. ` +\n `Plugin install mode requires a marketplace — fix the marketplace or switch the affected skills to eject mode.`,\n };\n }\n return { ok: true, marketplace: mpResult.marketplace, registered: mpResult.registered };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAO,IAAM,aAAa;AAAA,EACxB,SAAS;AAAA,EACT,OAAO;AAAA,EACP,cAAc;AAAA,EACd,eAAe;AAAA,EACf,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaX,yBAAyB;AAC3B;;;ACnBA,SAAS,eAAe;AAExB,OAAO,WAAW;AAClB,SAAS,cAAc;;;ACyBvB,eAAsB,kBACpB,cAC4B;AAC5B,QAAM,SAAS,aAAa,aAAa;AAEzC,MAAI,CAAC,aAAa,aAAa;AAC7B,QAAI;AACF,YAAM,oBAAoB,MAAM,iBAAiB,MAAM;AACvD,mBAAa,cAAc,kBAAkB,YAAY;AAAA,IAC3D,SAAS,OAAO;AACd,WAAK,yCAAyC,MAAM,MAAM,gBAAgB,KAAK,CAAC,EAAE;AAClF,aAAO,EAAE,aAAa,MAAM,YAAY,MAAM;AAAA,IAChD;AAAA,EACF;AAEA,QAAM,cAAc,aAAa;AACjC,QAAM,SAAS,MAAM,8BAA8B,WAAW;AAE9D,MAAI,CAAC,QAAQ;AACX,UAAM,oBAAoB,OAAO,QAAQ,YAAY,EAAE;AACvD,UAAM,2BAA2B,iBAAiB;AAClD,WAAO,EAAE,aAAa,YAAY,KAAK;AAAA,EACzC;AAEA,MAAI;AACF,UAAM,8BAA8B,WAAW;AAAA,EACjD,QAAQ;AACN,SAAK,oEAA+D;AAAA,EACtE;AAEA,SAAO,EAAE,aAAa,YAAY,MAAM;AAC1C;;;AC/CA,eAAsB,mBACpB,cACA,SACiC;AACjC,QAAM,WAAW,MAAM,kBAAkB,YAAY;AACrD,MAAI,CAAC,SAAS,aAAa;AACzB,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OACE,UAAU,OAAO,6CAA6C,aAAa,aAAa,MAAM;AAAA,IAElG;AAAA,EACF;AACA,SAAO,EAAE,IAAI,MAAM,aAAa,SAAS,aAAa,YAAY,SAAS,WAAW;AACxF;;;AFgCA,IAAM,0BAA0B;AAGhC,IAAM,kBAAkB,MAAc,QAAQ,OAAO,WAAW,kBAAkB;AAGlF,IAAM,eAAe,MAAc,QAAQ,OAAO,QAAQ,kBAAkB;AAE5E,SAAS,sBAA+B;AACtC,SAAO,sBAAsB,gBAAgB,GAAG,aAAa,CAAC;AAChE;AAOA,SAAS,gBAAgB,aAA2C;AAClE,SAAO,IAAI,QAAc,CAAC,YAAY;AACpC,UAAM,QAAQ,MAAM;AAClB,UAAI,CAAC,YAAY,EAAG;AACpB,oBAAc,QAAQ;AACtB,cAAQ,OAAO,IAAI,UAAU,KAAK;AAClC,cAAQ;AAAA,IACV;AACA,UAAM,WAAW,YAAY,OAAO,uBAAuB;AAC3D,YAAQ,OAAO,GAAG,UAAU,KAAK;AAAA,EACnC,CAAC;AACH;AAaA,SAAS,qBAAqB,QAA0C;AACtE,QAAM,cAAc,IAAI,IAAI,OAAO,QAAQ,iBAAiB,OAAO,KAAK,IAAI,CAAC,CAAC;AAC9E,QAAM,mBAAmB,OAAO,OAC7B,OAAO,CAAC,UAAU,WAAW,OAAO,QAAQ,CAAC,EAC7C,IAAI,CAAC,UAAU,MAAM,IAAI;AAE5B,QAAM,gBAAgB;AAAA,IACpB,OAAO,OACJ,OAAO,CAAC,UAAU,CAAC,MAAM,QAAQ,EACjC,IAAI,CAAC,UAAU,MAAM,EAAE,EACvB,OAAO,CAAC,YAAY,CAAC,YAAY,IAAI,OAAO,CAAC;AAAA,EAClD;AAEA,SAAO,cAAc,IAAI,CAAC,aAAa;AAAA,IACrC;AAAA,IACA,WAAW,sBAAsB,OAAO,QAAQ,OAAO,IAAI,mBAAmB,CAAC;AAAA,EACjF,EAAE;AACJ;AAGA,SAAS,sBAAsB,QAAgC,SAA2B;AACxF,SAAO,OAAO,KAAK,CAAC,UAAU,MAAM,OAAO,WAAW,WAAW,OAAO,SAAS,CAAC;AACpF;AAOA,SAAS,qBAAqB,QAG5B;AACA,SAAO;AAAA,IACL,UAAU,OAAO,OACd,OAAO,CAAC,UAAU,WAAW,OAAO,SAAS,CAAC,EAC9C,IAAI,CAAC,UAAU,MAAM,EAAE;AAAA,IAC1B,YAAY,OAAO,aAChB,OAAO,CAAC,UAAU,WAAW,OAAO,SAAS,CAAC,EAC9C,IAAI,CAAC,UAAU,MAAM,IAAI;AAAA,EAC9B;AACF;AAUO,IAAe,cAAf,cAAmC,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAY/B,iBAAmC,CAAC;AAAA,EAErD,MAAM,OAAsB;AAC1B,UAAM,MAAM,KAAK;AACjB,UAAM,KAAK,mBAAmB;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAgB,qBAAoC;AAClD,QAAI,oBAAoB,EAAG;AAE3B,SAAK,cAAc;AACnB,SAAK,IAAI,MAAM,IAAI,WAAW,OAAO,EAAE,8BAA8B,gBAAgB,CAAC,CAAC,CAAC;AAExF,UAAM,gBAAgB,mBAAmB;AAAA,EAC3C;AAAA,EAEU,YAAY,OAAuB;AAC3C,UAAM,UAAU,gBAAgB,KAAK;AACrC,SAAK,MAAM,SAAS,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBA,MAAgB,oBAAoB,YAAqC;AACvE,QAAI;AACF,YAAM,WAAW,MAAM,gBAAgB,UAAU;AACjD,aAAO,SAAS;AAAA,IAClB,SAAS,OAAO;AACd,cAAQ,4CAA4C,gBAAgB,KAAK,CAAC,EAAE;AAC5E,aAAO,iBAAiB;AAAA,IAC1B;AAAA,EACF;AAAA,EAEU,WAAW,SAAuB;AAC1C,SAAK,IAAI,UAAK,OAAO,EAAE;AAAA,EACzB;AAAA,EAEU,WAAW,SAAuB;AAC1C,SAAK,KAAK,OAAO;AAAA,EACnB;AAAA,EAEU,QAAQ,SAAuB;AACvC,SAAK,IAAI,OAAO;AAAA,EAClB;AAAA,EAEU,gBAAsB;AAC9B,wBAAoB;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAgB,yBACd,cACA,SACA,cACiB;AACjB,UAAM,WAAW,MAAM,mBAAmB,cAAc,OAAO;AAC/D,QAAI,CAAC,SAAS,IAAI;AAChB,WAAK,MAAM,SAAS,OAAO,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IACvD;AACA,QAAI,SAAS,YAAY;AACvB,qBAAe,SAAS,WAAW;AAAA,IACrC;AACA,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeU,uBAAuB,YAAuC;AACtE,eAAW,SAAS,WAAW,QAAQ;AACrC,WAAK,KAAK,MAAM,OAAO;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAgB,4BACd,QACA,aACA,YACA,QAC8B;AAC9B,UAAM,WAAW,uBAAuB,QAAQ,MAAM;AACtD,QAAI,SAAS,SAAS,GAAG;AACvB,WAAK,MAAM,2BAA2B,QAAQ,GAAG,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IAC7E;AAEA,SAAK,sBAAsB;AAC3B,UAAM,SAAS,MAAM,oBAAoB,QAAQ,aAAa,UAAU;AACxE,SAAK,qBAAqB,MAAM;AAChC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQU,wBAA8B;AACtC,SAAK,IAAI,gBAAgB,kBAAkB;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWU,qBAAqB,QAAmC;AAChE,eAAW,QAAQ,OAAO,WAAW;AACnC,WAAK,IAAI,eAAe,KAAK,GAAG,EAAE;AAAA,IACpC;AACA,eAAW,QAAQ,OAAO,QAAQ;AAChC,WAAK,KAAK,4BAA4B,KAAK,EAAE,KAAK,KAAK,KAAK,EAAE;AAAA,IAChE;AACA,QAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,WAAK,MAAM,0BAA0B,OAAO,OAAO,MAAM,GAAG,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IACxF;AACA,SAAK,IAAI,GAAG,iBAAiB,OAAO,UAAU,MAAM,CAAC;AAAA,CAAI;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUU,0BAA0B,QAA0B;AAC5D,QAAI,OAAO,WAAW,QAAQ,WAAW,EAAG;AAE5C,UAAM,EAAE,gBAAgB,gBAAgB,aAAa,SAAS,IAAI,OAAO;AACzE,eAAW,WAAW,UAAU;AAC9B,WAAK,KAAK,OAAO;AAAA,IACnB;AACA,SAAK,IAAI,2BAA2B,gBAAgB,gBAAgB,WAAW,CAAC;AAAA,EAClF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBU,uBAAuB,QAA6B;AAC5D,eAAW,EAAE,SAAS,UAAU,KAAK,qBAAqB,MAAM,GAAG;AACjE,WAAK,KAAK,uBAAuB,OAAO,CAAC;AACzC,UAAI,UAAU,SAAS,GAAG;AACxB,aAAK,KAAK,4BAA4B,WAAW,OAAO,CAAC;AAAA,MAC3D;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAgB,qBAAqB,YAAmC;AACtE,UAAM,CAAC,OAAO,IAAI,MAAM,uBAAuB,UAAU;AACzD,QAAI,SAAS;AACX,WAAK,MAAM,sBAAsB,QAAQ,OAAO,GAAG,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IAC/E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,MAAgB,0BACd,aACA,QACA,YACe;AACf,UAAM,aAAa,YAChB,OAAO,CAAC,UAAU,CAAC,MAAM,YAAY,CAAC,OAAO,OAAO,MAAM,EAAE,CAAC,EAC7D,IAAI,CAAC,UAAU,MAAM,EAAE;AAC1B,QAAI,WAAW,WAAW,EAAG;AAE7B,UAAM,WAAW,MAAM,+BAA+B,YAAY,aAAa,UAAU;AACzF,QAAI,SAAS,WAAW,EAAG;AAK3B,eAAW,SAAS,UAAU;AAC5B,WAAK,IAAI,4BAA4B,KAAK,CAAC;AAAA,IAC7C;AACA,SAAK,MAAM,gCAAgC,QAAQ,GAAG,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,EAClF;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,EA6BU,iCAAiC,QAAwB,YAA0B;AAC3F,QAAI,CAAC,gBAAgB,UAAU,EAAG;AAElC,UAAM,EAAE,UAAU,WAAW,IAAI,qBAAqB,MAAM;AAC5D,QAAI,SAAS,WAAW,KAAK,WAAW,WAAW,EAAG;AAEtD,SAAK,MAAM,+BAA+B,UAAU,UAAU,GAAG,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,EAC7F;AAAA;AAAA,EAGA,IAAc,oBAA6B;AACzC,WAAO,KAAK,eAAe,SAAS;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBU,qBAAqB,MAAc,UAAwB;AACnE,SAAK,KAAK,IAAI;AACd,SAAK,qBAAqB,MAAM,QAAQ;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOU,qBAAqB,MAAc,UAAwB;AACnE,SAAK,eAAe,KAAK,EAAE,MAAM,SAAS,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaU,uBAA6B;AACrC,QAAI,CAAC,KAAK,kBAAmB;AAE7B,SAAK,IAAI;AAAA,EAAK,MAAM,IAAI,WAAW,OAAO,EAAE,sBAAsB,KAAK,cAAc,CAAC,CAAC;AAAA,CAAI;AAC3F,SAAK,KAAK,WAAW,uBAAuB;AAAA,EAC9C;AACF;","names":[]}
|