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/list.js
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
SkillAgentSummary
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-PMUZR4XO.js";
|
|
5
|
+
import "../chunk-RIK45Q4I.js";
|
|
6
6
|
import {
|
|
7
7
|
render
|
|
8
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-KIK5EZYD.js";
|
|
9
9
|
import {
|
|
10
10
|
otherInstallationsInThisScope,
|
|
11
11
|
providerFlag,
|
|
12
12
|
providerNamedBy
|
|
13
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-OCAVW6N5.js";
|
|
14
14
|
import {
|
|
15
15
|
BaseCommand
|
|
16
|
-
} from "../chunk-
|
|
17
|
-
import "../chunk-CLPUWOSA.js";
|
|
16
|
+
} from "../chunk-GEMW5RQ2.js";
|
|
18
17
|
import {
|
|
19
18
|
INSTALL_MODE_LABELS,
|
|
20
19
|
chooseProviderForThisRun,
|
|
@@ -23,14 +22,14 @@ import {
|
|
|
23
22
|
getInstallationInfo,
|
|
24
23
|
loadProjectConfig,
|
|
25
24
|
providerInUse
|
|
26
|
-
} from "../chunk-
|
|
27
|
-
import "../chunk-
|
|
25
|
+
} from "../chunk-GAKVZNTX.js";
|
|
26
|
+
import "../chunk-AUNRHWH4.js";
|
|
28
27
|
import {
|
|
29
28
|
CLI_COLORS,
|
|
30
29
|
CLI_INVOKE_COMMAND,
|
|
31
30
|
DEFAULT_BRANDING
|
|
32
|
-
} from "../chunk-
|
|
33
|
-
import "../chunk-
|
|
31
|
+
} from "../chunk-7C3PFRBU.js";
|
|
32
|
+
import "../chunk-GHHJYNAN.js";
|
|
34
33
|
|
|
35
34
|
// src/cli/commands/list.tsx
|
|
36
35
|
import { useEffect } from "react";
|
|
@@ -76,20 +75,7 @@ var List = class _List extends BaseCommand {
|
|
|
76
75
|
command: "<%= config.bin %> <%= command.id %>"
|
|
77
76
|
}
|
|
78
77
|
];
|
|
79
|
-
/**
|
|
80
|
-
* Which of the scope's installations this report is about, said out loud where there are two.
|
|
81
|
-
*
|
|
82
|
-
* **`list` reported one of two and nothing anywhere said so.** Everything below resolves the
|
|
83
|
-
* provider through `providerInUse`, which answers by ROSTER ORDER for a scope holding one
|
|
84
|
-
* installation of each — so the report named one installation, its mode, its counts and its
|
|
85
|
-
* config path, all correct, about the half of the directory the user was not asking after. Every
|
|
86
|
-
* command that WRITES refuses this state by name and `doctor` reports it as a finding; the one
|
|
87
|
-
* command whose whole job is to say what is installed was silent about it.
|
|
88
|
-
*
|
|
89
|
-
* It reports rather than refusing, for the reason `doctor` does: a read-only command that
|
|
90
|
-
* refused would leave a user whose scope holds two installations unable to look at either,
|
|
91
|
-
* which is the one state they most need to see.
|
|
92
|
-
*/
|
|
78
|
+
/** Names the other installation in this scope; reports rather than refuses, like `doctor`. */
|
|
93
79
|
async sayWhichInstallationThisIs(providerFlagValue) {
|
|
94
80
|
const named = providerNamedBy(providerFlagValue);
|
|
95
81
|
if (named !== void 0) {
|
|
@@ -105,40 +91,38 @@ var List = class _List extends BaseCommand {
|
|
|
105
91
|
await this.sayWhichInstallationThisIs(flags.provider);
|
|
106
92
|
await this.ensureConfigReadable(process.cwd());
|
|
107
93
|
const installation = await detectInstallation();
|
|
108
|
-
if (!installation)
|
|
109
|
-
this.log("No installation found.");
|
|
110
|
-
this.log(`Run '${CLI_INVOKE_COMMAND} init' to create one.`);
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
94
|
+
if (!installation) return this.reportNoInstallation();
|
|
113
95
|
const loaded = await loadProjectConfig(installation.projectDir);
|
|
114
|
-
if (!loaded?.config || !process.stdin.isTTY)
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const { waitUntilExit, clear } = render(
|
|
128
|
-
/* @__PURE__ */ jsx(
|
|
129
|
-
ListView,
|
|
130
|
-
{
|
|
131
|
-
mode: modeLabel,
|
|
132
|
-
source: config.marketplace,
|
|
133
|
-
skillConfigs: activeSkills,
|
|
134
|
-
agentConfigs: activeAgents
|
|
135
|
-
}
|
|
136
|
-
)
|
|
137
|
-
);
|
|
138
|
-
await waitUntilExit();
|
|
139
|
-
clear();
|
|
96
|
+
if (!loaded?.config || !process.stdin.isTTY) return this.printInstallationInfo();
|
|
97
|
+
await showListView(installation, loaded.config);
|
|
98
|
+
}
|
|
99
|
+
reportNoInstallation() {
|
|
100
|
+
this.log("No installation found.");
|
|
101
|
+
this.log(`Run '${CLI_INVOKE_COMMAND} init' to create one.`);
|
|
102
|
+
}
|
|
103
|
+
async printInstallationInfo() {
|
|
104
|
+
const info = await getInstallationInfo();
|
|
105
|
+
if (!info) return;
|
|
106
|
+
this.log("");
|
|
107
|
+
this.log(formatInstallationDisplay(info));
|
|
108
|
+
this.log("");
|
|
140
109
|
}
|
|
141
110
|
};
|
|
111
|
+
async function showListView(installation, config) {
|
|
112
|
+
const { waitUntilExit, clear } = render(
|
|
113
|
+
/* @__PURE__ */ jsx(
|
|
114
|
+
ListView,
|
|
115
|
+
{
|
|
116
|
+
mode: INSTALL_MODE_LABELS[installation.mode],
|
|
117
|
+
source: config.marketplace,
|
|
118
|
+
skillConfigs: config.skills.filter((skill) => !skill.excluded),
|
|
119
|
+
agentConfigs: config.agents.filter((agent) => !agent.excluded)
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
);
|
|
123
|
+
await waitUntilExit();
|
|
124
|
+
clear();
|
|
125
|
+
}
|
|
142
126
|
export {
|
|
143
127
|
List as default
|
|
144
128
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/commands/list.tsx"],"sourcesContent":["import React, { useEffect } from \"react\";\n\nimport { Box, Text, useApp } from \"ink\";\nimport { render } from \"../components/render.js\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { CLI_INVOKE_COMMAND, CLI_COLORS, DEFAULT_BRANDING } from \"../consts.js\";\nimport { chooseProviderForThisRun, providerInUse } from \"../lib/installation/install-layout.js\";\nimport {\n otherInstallationsInThisScope,\n providerFlag,\n providerNamedBy,\n} from \"../lib/installation/provider-flag.js\";\nimport { getInstallationInfo, formatInstallationDisplay } from \"../lib/plugins/index.js\";\nimport {
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/list.tsx"],"sourcesContent":["import React, { useEffect } from \"react\";\n\nimport { Box, Text, useApp } from \"ink\";\nimport { render } from \"../components/render.js\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { CLI_INVOKE_COMMAND, CLI_COLORS, DEFAULT_BRANDING } from \"../consts.js\";\nimport { chooseProviderForThisRun, providerInUse } from \"../lib/installation/install-layout.js\";\nimport {\n otherInstallationsInThisScope,\n providerFlag,\n providerNamedBy,\n} from \"../lib/installation/provider-flag.js\";\nimport { getInstallationInfo, formatInstallationDisplay } from \"../lib/plugins/index.js\";\nimport {\n detectInstallation,\n INSTALL_MODE_LABELS,\n type Installation,\n} from \"../lib/installation/installation.js\";\nimport { loadProjectConfig } from \"../lib/configuration/project-config.js\";\nimport { SkillAgentSummary } from \"../components/common/skill-agent-summary.js\";\nimport type { AgentScopeConfig, ProjectConfig, SkillConfig } from \"../types/config.js\";\n\ntype ListViewProps = {\n mode: string;\n source?: string | undefined;\n skillConfigs: SkillConfig[];\n agentConfigs: AgentScopeConfig[];\n};\n\nconst ListView: React.FC<ListViewProps> = ({ mode, source, skillConfigs, agentConfigs }) => {\n const { exit } = useApp();\n\n useEffect(() => {\n const timer = setTimeout(() => exit(), 0);\n return () => clearTimeout(timer);\n }, [exit]);\n\n return (\n <Box flexDirection=\"column\" paddingX={1} paddingY={1}>\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box flexDirection=\"row\" columnGap={1}>\n <Text color={CLI_COLORS.WARNING} bold>\n Mode\n </Text>\n <Text color={CLI_COLORS.NEUTRAL}>{mode}</Text>\n </Box>\n {source && (\n <Box flexDirection=\"row\" columnGap={1}>\n <Text color={CLI_COLORS.WARNING} bold>\n Marketplace\n </Text>\n <Text color={CLI_COLORS.NEUTRAL}>{source}</Text>\n </Box>\n )}\n </Box>\n\n {/* Installed and current are one configuration, so every row reads unchanged. */}\n <SkillAgentSummary\n skillConfigs={skillConfigs}\n agentConfigs={agentConfigs}\n installedSkillConfigs={skillConfigs}\n installedAgentConfigs={agentConfigs}\n isInitMode={false}\n />\n </Box>\n );\n};\n\nexport default class List extends BaseCommand {\n static summary = \"Show installation information\";\n static description = `Display details about the ${DEFAULT_BRANDING.NAME} installation (local or plugin mode)`;\n static aliases = [\"ls\"];\n\n static flags = { provider: providerFlag() };\n\n static examples = [\n {\n description: \"Show current installation details\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n ];\n\n /** Names the other installation in this scope; reports rather than refuses, like `doctor`. */\n private async sayWhichInstallationThisIs(providerFlagValue: string | undefined): Promise<void> {\n const named = providerNamedBy(providerFlagValue);\n if (named !== undefined) {\n chooseProviderForThisRun(named);\n return;\n }\n\n const cwd = process.cwd();\n const line = await otherInstallationsInThisScope(cwd, providerInUse(cwd));\n if (line !== null) this.log(line);\n }\n\n async run(): Promise<void> {\n const { flags } = await this.parse(List);\n await this.sayWhichInstallationThisIs(flags.provider);\n await this.ensureConfigReadable(process.cwd());\n\n const installation = await detectInstallation();\n if (!installation) return this.reportNoInstallation();\n\n const loaded = await loadProjectConfig(installation.projectDir);\n if (!loaded?.config || !process.stdin.isTTY) return this.printInstallationInfo();\n\n await showListView(installation, loaded.config);\n }\n\n private reportNoInstallation(): void {\n this.log(\"No installation found.\");\n this.log(`Run '${CLI_INVOKE_COMMAND} init' to create one.`);\n }\n\n private async printInstallationInfo(): Promise<void> {\n const info = await getInstallationInfo();\n if (!info) return;\n\n this.log(\"\");\n this.log(formatInstallationDisplay(info));\n this.log(\"\");\n }\n}\n\nasync function showListView(installation: Installation, config: ProjectConfig): Promise<void> {\n const { waitUntilExit, clear } = render(\n <ListView\n mode={INSTALL_MODE_LABELS[installation.mode]}\n source={config.marketplace}\n skillConfigs={config.skills.filter((skill) => !skill.excluded)}\n agentConfigs={config.agents.filter((agent) => !agent.excluded)}\n />,\n );\n\n await waitUntilExit();\n clear();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAgB,iBAAiB;AAEjC,SAAS,KAAK,MAAM,cAAc;AAuC1B,SACE,KADF;AAXR,IAAM,WAAoC,CAAC,EAAE,MAAM,QAAQ,cAAc,aAAa,MAAM;AAC1F,QAAM,EAAE,KAAK,IAAI,OAAO;AAExB,YAAU,MAAM;AACd,UAAM,QAAQ,WAAW,MAAM,KAAK,GAAG,CAAC;AACxC,WAAO,MAAM,aAAa,KAAK;AAAA,EACjC,GAAG,CAAC,IAAI,CAAC;AAET,SACE,qBAAC,OAAI,eAAc,UAAS,UAAU,GAAG,UAAU,GACjD;AAAA,yBAAC,OAAI,eAAc,UAAS,cAAc,GACxC;AAAA,2BAAC,OAAI,eAAc,OAAM,WAAW,GAClC;AAAA,4BAAC,QAAK,OAAO,WAAW,SAAS,MAAI,MAAC,kBAEtC;AAAA,QACA,oBAAC,QAAK,OAAO,WAAW,SAAU,gBAAK;AAAA,SACzC;AAAA,MACC,UACC,qBAAC,OAAI,eAAc,OAAM,WAAW,GAClC;AAAA,4BAAC,QAAK,OAAO,WAAW,SAAS,MAAI,MAAC,yBAEtC;AAAA,QACA,oBAAC,QAAK,OAAO,WAAW,SAAU,kBAAO;AAAA,SAC3C;AAAA,OAEJ;AAAA,IAGA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,uBAAuB;AAAA,QACvB,uBAAuB;AAAA,QACvB,YAAY;AAAA;AAAA,IACd;AAAA,KACF;AAEJ;AAEA,IAAqB,OAArB,MAAqB,cAAa,YAAY;AAAA,EAC5C,OAAO,UAAU;AAAA,EACjB,OAAO,cAAc,6BAA6B,iBAAiB,IAAI;AAAA,EACvE,OAAO,UAAU,CAAC,IAAI;AAAA,EAEtB,OAAO,QAAQ,EAAE,UAAU,aAAa,EAAE;AAAA,EAE1C,OAAO,WAAW;AAAA,IAChB;AAAA,MACE,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,EACF;AAAA;AAAA,EAGA,MAAc,2BAA2B,mBAAsD;AAC7F,UAAM,QAAQ,gBAAgB,iBAAiB;AAC/C,QAAI,UAAU,QAAW;AACvB,+BAAyB,KAAK;AAC9B;AAAA,IACF;AAEA,UAAM,MAAM,QAAQ,IAAI;AACxB,UAAM,OAAO,MAAM,8BAA8B,KAAK,cAAc,GAAG,CAAC;AACxE,QAAI,SAAS,KAAM,MAAK,IAAI,IAAI;AAAA,EAClC;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,KAAI;AACvC,UAAM,KAAK,2BAA2B,MAAM,QAAQ;AACpD,UAAM,KAAK,qBAAqB,QAAQ,IAAI,CAAC;AAE7C,UAAM,eAAe,MAAM,mBAAmB;AAC9C,QAAI,CAAC,aAAc,QAAO,KAAK,qBAAqB;AAEpD,UAAM,SAAS,MAAM,kBAAkB,aAAa,UAAU;AAC9D,QAAI,CAAC,QAAQ,UAAU,CAAC,QAAQ,MAAM,MAAO,QAAO,KAAK,sBAAsB;AAE/E,UAAM,aAAa,cAAc,OAAO,MAAM;AAAA,EAChD;AAAA,EAEQ,uBAA6B;AACnC,SAAK,IAAI,wBAAwB;AACjC,SAAK,IAAI,QAAQ,kBAAkB,uBAAuB;AAAA,EAC5D;AAAA,EAEA,MAAc,wBAAuC;AACnD,UAAM,OAAO,MAAM,oBAAoB;AACvC,QAAI,CAAC,KAAM;AAEX,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,0BAA0B,IAAI,CAAC;AACxC,SAAK,IAAI,EAAE;AAAA,EACb;AACF;AAEA,eAAe,aAAa,cAA4B,QAAsC;AAC5F,QAAM,EAAE,eAAe,MAAM,IAAI;AAAA,IAC/B;AAAA,MAAC;AAAA;AAAA,QACC,MAAM,oBAAoB,aAAa,IAAI;AAAA,QAC3C,QAAQ,OAAO;AAAA,QACf,cAAc,OAAO,OAAO,OAAO,CAAC,UAAU,CAAC,MAAM,QAAQ;AAAA,QAC7D,cAAc,OAAO,OAAO,OAAO,CAAC,UAAU,CAAC,MAAM,QAAQ;AAAA;AAAA,IAC/D;AAAA,EACF;AAEA,QAAM,cAAc;AACpB,QAAM;AACR;","names":[]}
|
|
@@ -2,15 +2,14 @@
|
|
|
2
2
|
import {
|
|
3
3
|
BaseCommand,
|
|
4
4
|
EXIT_CODES
|
|
5
|
-
} from "../../chunk-
|
|
6
|
-
import "../../chunk-CLPUWOSA.js";
|
|
5
|
+
} from "../../chunk-GEMW5RQ2.js";
|
|
7
6
|
import {
|
|
8
7
|
isDirectoryEmpty,
|
|
9
8
|
validateKebabCaseName,
|
|
10
9
|
validateMarketplaceName,
|
|
11
10
|
writeFile
|
|
12
|
-
} from "../../chunk-
|
|
13
|
-
import "../../chunk-
|
|
11
|
+
} from "../../chunk-GAKVZNTX.js";
|
|
12
|
+
import "../../chunk-AUNRHWH4.js";
|
|
14
13
|
import {
|
|
15
14
|
CLI_INVOKE_COMMAND,
|
|
16
15
|
DEFAULT_VERSION,
|
|
@@ -20,8 +19,8 @@ import {
|
|
|
20
19
|
SKILL_RULES_PATH,
|
|
21
20
|
STACKS_FILE_PATH,
|
|
22
21
|
STANDARD_FILES
|
|
23
|
-
} from "../../chunk-
|
|
24
|
-
import "../../chunk-
|
|
22
|
+
} from "../../chunk-7C3PFRBU.js";
|
|
23
|
+
import "../../chunk-GHHJYNAN.js";
|
|
25
24
|
|
|
26
25
|
// src/cli/commands/new/marketplace.ts
|
|
27
26
|
import { Args } from "@oclif/core";
|
|
@@ -187,11 +186,7 @@ var NewMarketplace = class _NewMarketplace extends BaseCommand {
|
|
|
187
186
|
this.handleError(error);
|
|
188
187
|
}
|
|
189
188
|
}
|
|
190
|
-
/**
|
|
191
|
-
* Both name rules `build marketplace` enforces, enforced here instead — failing
|
|
192
|
-
* at creation beats failing at publish, when the name is already the directory,
|
|
193
|
-
* the package name and the prefix on every id.
|
|
194
|
-
*/
|
|
189
|
+
/** `build marketplace`'s name rules, enforced at creation rather than at publish. */
|
|
195
190
|
refuseUnusableName(marketplaceName) {
|
|
196
191
|
const kebabError = validateKebabCaseName(marketplaceName, "Marketplace");
|
|
197
192
|
if (kebabError) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/cli/commands/new/marketplace.ts","../../../src/cli/lib/marketplace-scaffold.ts"],"sourcesContent":["import { Args } from \"@oclif/core\";\nimport path from \"path\";\n\nimport { BaseCommand } from \"../../base-command.js\";\nimport { CLI_INVOKE_COMMAND, EDITOR_URL, SKILLS_DIR_PATH } from \"../../consts.js\";\nimport { EXIT_CODES } from \"../../lib/exit-codes.js\";\nimport { validateMarketplaceName } from \"../../lib/marketplace-generator.js\";\nimport { exampleSkillId, writeMarketplaceScaffold } from \"../../lib/marketplace-scaffold.js\";\nimport { validateKebabCaseName } from \"../../lib/validate-kebab-name.js\";\nimport { isDirectoryEmpty } from \"../../utils/fs.js\";\n\n/**\n * How a reserved name is replaced here. The name is this command's argument, and nothing it could\n * be read from exists yet — no package.json, and no `--name` — so another argument is the way out.\n */\nconst RESERVED_NAME_WAY_OUT = `run '${CLI_INVOKE_COMMAND} new marketplace <other-name>'`;\n\n/**\n * The refusal over a target directory that already holds something.\n *\n * A scaffold writes a whole marketplace, so writing into an occupied directory\n * would mean merging with — or overwriting — work this command did not author.\n * Both ways out are one step, which is why there is no `--force`: a flag that\n * overwrites an author's own files is the destructive half of a silent fallback.\n */\nfunction occupiedDirectoryError(marketplaceDir: string): string {\n return (\n `${marketplaceDir} already holds files. A scaffold writes a whole marketplace, ` +\n `so it will not write into a directory that already has contents. Choose another ` +\n `name, or empty that directory first.`\n );\n}\n\nexport default class NewMarketplace extends BaseCommand {\n static summary = \"Scaffold a marketplace of your own\";\n\n static description =\n \"Create a directory holding everything the CLI needs to read a marketplace: a package.json \" +\n \"carrying its identity, the three config files, and one example skill already named in the \" +\n \"marketplace's own namespace. It scaffolds only — run 'build plugins' and 'build marketplace' \" +\n \"to publish what you have written.\";\n\n static examples = [\n {\n description: \"Scaffold a marketplace named acme into ./acme\",\n command: \"<%= config.bin %> <%= command.id %> acme\",\n },\n ];\n\n static args = {\n name: Args.string({\n description:\n \"Name of the marketplace (kebab-case). Becomes the directory, the package.json name, \" +\n \"and the prefix every skill id must carry.\",\n required: true,\n }),\n };\n\n async run(): Promise<void> {\n const { args } = await this.parse(NewMarketplace);\n const marketplaceName = args.name;\n const marketplaceDir = path.join(process.cwd(), marketplaceName);\n\n this.refuseUnusableName(marketplaceName);\n await this.refuseOccupiedDirectory(marketplaceDir);\n\n try {\n const written = await writeMarketplaceScaffold(marketplaceDir, marketplaceName);\n this.reportCreated(marketplaceName, marketplaceDir, written);\n this.reportNextSteps(marketplaceName, marketplaceDir);\n } catch (error) {\n this.handleError(error);\n }\n }\n\n /**\n * Both name rules `build marketplace` enforces, enforced here instead — failing\n * at creation beats failing at publish, when the name is already the directory,\n * the package name and the prefix on every id.\n */\n private refuseUnusableName(marketplaceName: string): void {\n const kebabError = validateKebabCaseName(marketplaceName, \"Marketplace\");\n if (kebabError) {\n this.error(kebabError, { exit: EXIT_CODES.INVALID_ARGS });\n }\n\n // The package.json this command is about to write names the marketplace after\n // itself, so the marketplace name IS the package name. That is what keeps the\n // public catalogue's exemption out of reach: it belongs to one npm package, and\n // nobody scaffolds that package from here.\n const reservedError = validateMarketplaceName(\n marketplaceName,\n marketplaceName,\n RESERVED_NAME_WAY_OUT,\n );\n if (reservedError) {\n this.error(reservedError, { exit: EXIT_CODES.ERROR });\n }\n }\n\n private async refuseOccupiedDirectory(marketplaceDir: string): Promise<void> {\n if (await isDirectoryEmpty(marketplaceDir)) return;\n\n this.error(occupiedDirectoryError(marketplaceDir), { exit: EXIT_CODES.ERROR });\n }\n\n private reportCreated(\n marketplaceName: string,\n marketplaceDir: string,\n written: readonly string[],\n ): void {\n this.log(\"\");\n this.logSuccess(`Created marketplace '${marketplaceName}' at ${marketplaceDir}`);\n for (const relPath of written) {\n this.log(` ${relPath}`);\n }\n }\n\n private reportNextSteps(marketplaceName: string, marketplaceDir: string): void {\n const skillDir = path.join(SKILLS_DIR_PATH, exampleSkillId(marketplaceName));\n const steps = [\n `cd ${marketplaceName}`,\n \"Replace the placeholder 'author' in package.json with your own handle — it is what 'build marketplace' records as this marketplace's owner\",\n `Replace ${skillDir}/ with a skill of your own. Every skill id must begin with '${marketplaceName}-'`,\n `${CLI_INVOKE_COMMAND} build plugins`,\n `${CLI_INVOKE_COMMAND} build marketplace`,\n `Push it to GitHub, then add it from the Marketplace button at ${EDITOR_URL}`,\n `${CLI_INVOKE_COMMAND} init --from <id> --marketplace ${marketplaceDir} (from a project — tests your local changes against a configuration built there)`,\n ];\n\n this.log(\"\");\n this.log(\"Next steps:\");\n for (const [index, step] of steps.entries()) {\n this.log(` ${index + 1}. ${step}`);\n }\n this.log(\"\");\n }\n}\n","import path from \"path\";\n\nimport {\n DEFAULT_VERSION,\n SKILL_CATEGORIES_PATH,\n SKILL_RULES_PATH,\n SKILLS_DIR_PATH,\n STACKS_FILE_PATH,\n STANDARD_FILES,\n} from \"../consts.js\";\nimport { writeFile } from \"../utils/fs.js\";\n\n/** One file of a scaffolded marketplace: where it goes, and what it holds. */\ntype ScaffoldFile = {\n /** Path relative to the marketplace root. */\n relPath: string;\n contents: string;\n};\n\n/**\n * The bare id of the one skill a scaffold ships. The marketplace's own name is\n * prefixed onto it by {@link exampleSkillId} — this half is the same for every\n * marketplace, and on its own it belongs to none of them.\n */\nconst EXAMPLE_SKILL_SUFFIX = \"example-skill\";\n\n/**\n * The domain the scaffolded category sits under.\n *\n * `web` rather than a placeholder of its own: a domain is a member of a generated\n * union, and one invented for the scaffold reaches no sub-agent.\n */\nconst EXAMPLE_DOMAIN = \"web\";\n\n/**\n * The category the scaffold declares and places its example skill in, named by the\n * `<domain>-<name>` convention every category in the public catalogue follows. No\n * built-in category holds this key, so declaring it adds one rather than redefining\n * somebody else's.\n */\nconst EXAMPLE_CATEGORY = `${EXAMPLE_DOMAIN}-example`;\n\n/**\n * The slug the example skill answers to.\n *\n * Deliberately NOT namespaced: the marketplace-namespace rule governs skill ids,\n * not slugs.\n */\nconst EXAMPLE_SLUG = \"example-skill\";\n\n/** Where the scaffolded category sorts among the categories a marketplace grows later. */\nconst EXAMPLE_CATEGORY_ORDER = 1;\n\n/** The version a marketplace starts at — pre-release, because nothing is published yet. */\nconst INITIAL_PACKAGE_VERSION = \"0.1.0\";\n\n/** The sub-agent the scaffolded stack hands its skill to. */\nconst EXAMPLE_STACK_AGENT = \"web-developer\";\n\n/**\n * Composes the id of a scaffolded marketplace's example skill.\n *\n * Every skill id a marketplace publishes begins with that marketplace's name, so an\n * author who edits the scaffold rather than starting from a blank directory falls\n * into the namespace instead of having to remember it — `build marketplace` refuses\n * an id that lacks the prefix.\n */\nexport function exampleSkillId(marketplaceName: string): string {\n return `${marketplaceName}-${EXAMPLE_SKILL_SUFFIX}`;\n}\n\n/**\n * Writes a complete marketplace into `marketplaceDir` and returns every path it\n * wrote, relative to that directory.\n *\n * What it writes is exactly what\n * `apps/www/src/content/docs/docs/guides/creating-a-marketplace.md` promises a\n * marketplace holds — no more. It deliberately writes no config pair: a\n * marketplace is a repository of skills, and a config manifest there would make\n * `doctor` diagnose an installation that does not exist.\n */\nexport async function writeMarketplaceScaffold(\n marketplaceDir: string,\n marketplaceName: string,\n): Promise<string[]> {\n const files = scaffoldFiles(marketplaceName);\n\n await Promise.all(\n files.map((file) => writeFile(path.join(marketplaceDir, file.relPath), file.contents)),\n );\n\n return files.map((file) => file.relPath);\n}\n\nfunction scaffoldFiles(marketplaceName: string): ScaffoldFile[] {\n const skillId = exampleSkillId(marketplaceName);\n const skillDir = path.join(SKILLS_DIR_PATH, skillId);\n\n return [\n { relPath: STANDARD_FILES.PACKAGE_JSON, contents: packageJson(marketplaceName) },\n { relPath: SKILL_CATEGORIES_PATH, contents: skillCategoriesModule() },\n { relPath: SKILL_RULES_PATH, contents: skillRulesModule() },\n { relPath: STACKS_FILE_PATH, contents: stacksModule(marketplaceName, skillId) },\n { relPath: path.join(skillDir, STANDARD_FILES.SKILL_MD), contents: skillMd(skillId) },\n {\n relPath: path.join(skillDir, STANDARD_FILES.METADATA_YAML),\n contents: metadataYaml(marketplaceName),\n },\n ];\n}\n\n/**\n * A `config/*.ts` module the CLI's loader can read.\n *\n * The loader reads only a DEFAULT export, so the export form here is load-bearing\n * rather than stylistic.\n */\nfunction configModule(comment: string, data: unknown): string {\n return `${comment}\\nexport default ${JSON.stringify(data, null, 2)};\\n`;\n}\n\n/**\n * `build marketplace` reads a marketplace's whole identity out of package.json and\n * refuses a file missing any of name, version, description or author.\n *\n * `author` is the field this command cannot know, so it is written as the\n * marketplace's own handle — the least-wrong default: it is derived from what the\n * author typed rather than invented, and the next steps say to replace it.\n */\nfunction packageJson(marketplaceName: string): string {\n return `${JSON.stringify(\n {\n name: marketplaceName,\n version: INITIAL_PACKAGE_VERSION,\n description: `Skills curated for ${marketplaceName}'s conventions`,\n author: { name: authorHandle(marketplaceName) },\n },\n null,\n 2,\n )}\\n`;\n}\n\n/** The placeholder handle the marketplace publishes itself and its example skill under. */\nfunction authorHandle(marketplaceName: string): string {\n return `@${marketplaceName}`;\n}\n\nfunction skillCategoriesModule(): string {\n return configModule(\"// The categories this marketplace's skills fall into.\", {\n version: DEFAULT_VERSION,\n categories: {\n [EXAMPLE_CATEGORY]: {\n id: EXAMPLE_CATEGORY,\n displayName: \"Example\",\n description: \"Replace this with a category of your own\",\n domain: EXAMPLE_DOMAIN,\n exclusive: false,\n order: EXAMPLE_CATEGORY_ORDER,\n },\n },\n });\n}\n\n/**\n * A rules file with a version and nothing else.\n *\n * Relationship rules name skills by slug, and that slug reference is the CLI's own\n * generated union — so a marketplace cannot yet name its OWN skills in a rule, and\n * one that tries fails to load. A marketplace works fully without them; what it\n * loses is the incompatibility hints between its own skills.\n */\nfunction skillRulesModule(): string {\n return configModule(\n [\n \"// Relationships between skills — conflicts, requires, alternatives.\",\n \"//\",\n \"// Rules may only name skills the public catalogue carries; this marketplace's own\",\n \"// skills cannot be named here yet, and a rule that names one will not load.\",\n ].join(\"\\n\"),\n { version: DEFAULT_VERSION },\n );\n}\n\nfunction stacksModule(marketplaceName: string, skillId: string): string {\n return configModule(\"// The stacks this marketplace offers.\", {\n stacks: [\n {\n id: `${marketplaceName}-starter`,\n name: `${marketplaceName} starter`,\n description: `Every skill ${marketplaceName} ships`,\n agents: {\n [EXAMPLE_STACK_AGENT]: {\n [EXAMPLE_CATEGORY]: [{ id: skillId }],\n },\n },\n },\n ],\n });\n}\n\n/**\n * The skill's content, headed by the frontmatter the loader reads its machine id\n * out of. That id is also the directory name — `doctor` compares the two — so both\n * come from {@link exampleSkillId} rather than being spelled twice.\n */\nfunction skillMd(skillId: string): string {\n return `---\nname: ${skillId}\ndescription: A placeholder skill — replace it with one of your own\n---\n\n# Example Skill\n\nThis is where a skill's content goes: the conventions, patterns and rules you want\nevery sub-agent carrying it to follow.\n\nReplace this file and the \\`${STANDARD_FILES.METADATA_YAML}\\` beside it, and rename the\ndirectory to the id your skill should publish under.\n`;\n}\n\nfunction metadataYaml(marketplaceName: string): string {\n return [\n \"custom: true\",\n `domain: ${EXAMPLE_DOMAIN}`,\n `author: \"${authorHandle(marketplaceName)}\"`,\n \"displayName: Example Skill\",\n `category: ${EXAMPLE_CATEGORY}`,\n `slug: ${EXAMPLE_SLUG}`,\n 'cliDescription: \"A placeholder skill to replace with your own\"',\n 'usageGuidance: \"Use when you need a worked example of this marketplace\\'s skill shape\"',\n \"\",\n ].join(\"\\n\");\n}\n"],"mappings":"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","names":["path","path"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/cli/commands/new/marketplace.ts","../../../src/cli/lib/marketplace-scaffold.ts"],"sourcesContent":["import { Args } from \"@oclif/core\";\nimport path from \"path\";\n\nimport { BaseCommand } from \"../../base-command.js\";\nimport { CLI_INVOKE_COMMAND, EDITOR_URL, SKILLS_DIR_PATH } from \"../../consts.js\";\nimport { EXIT_CODES } from \"../../lib/exit-codes.js\";\nimport { validateMarketplaceName } from \"../../lib/marketplace-generator.js\";\nimport { exampleSkillId, writeMarketplaceScaffold } from \"../../lib/marketplace-scaffold.js\";\nimport { validateKebabCaseName } from \"../../lib/validate-kebab-name.js\";\nimport { isDirectoryEmpty } from \"../../utils/fs.js\";\n\nconst RESERVED_NAME_WAY_OUT = `run '${CLI_INVOKE_COMMAND} new marketplace <other-name>'`;\n\n/** No `--force` on purpose: it would overwrite work this command did not author. */\nfunction occupiedDirectoryError(marketplaceDir: string): string {\n return (\n `${marketplaceDir} already holds files. A scaffold writes a whole marketplace, ` +\n `so it will not write into a directory that already has contents. Choose another ` +\n `name, or empty that directory first.`\n );\n}\n\nexport default class NewMarketplace extends BaseCommand {\n static summary = \"Scaffold a marketplace of your own\";\n\n static description =\n \"Create a directory holding everything the CLI needs to read a marketplace: a package.json \" +\n \"carrying its identity, the three config files, and one example skill already named in the \" +\n \"marketplace's own namespace. It scaffolds only — run 'build plugins' and 'build marketplace' \" +\n \"to publish what you have written.\";\n\n static examples = [\n {\n description: \"Scaffold a marketplace named acme into ./acme\",\n command: \"<%= config.bin %> <%= command.id %> acme\",\n },\n ];\n\n static args = {\n name: Args.string({\n description:\n \"Name of the marketplace (kebab-case). Becomes the directory, the package.json name, \" +\n \"and the prefix every skill id must carry.\",\n required: true,\n }),\n };\n\n async run(): Promise<void> {\n const { args } = await this.parse(NewMarketplace);\n const marketplaceName = args.name;\n const marketplaceDir = path.join(process.cwd(), marketplaceName);\n\n this.refuseUnusableName(marketplaceName);\n await this.refuseOccupiedDirectory(marketplaceDir);\n\n try {\n const written = await writeMarketplaceScaffold(marketplaceDir, marketplaceName);\n this.reportCreated(marketplaceName, marketplaceDir, written);\n this.reportNextSteps(marketplaceName, marketplaceDir);\n } catch (error) {\n this.handleError(error);\n }\n }\n\n /** `build marketplace`'s name rules, enforced at creation rather than at publish. */\n private refuseUnusableName(marketplaceName: string): void {\n const kebabError = validateKebabCaseName(marketplaceName, \"Marketplace\");\n if (kebabError) {\n this.error(kebabError, { exit: EXIT_CODES.INVALID_ARGS });\n }\n\n // The scaffolded package.json uses this name, so it is also the package name.\n const reservedError = validateMarketplaceName(\n marketplaceName,\n marketplaceName,\n RESERVED_NAME_WAY_OUT,\n );\n if (reservedError) {\n this.error(reservedError, { exit: EXIT_CODES.ERROR });\n }\n }\n\n private async refuseOccupiedDirectory(marketplaceDir: string): Promise<void> {\n if (await isDirectoryEmpty(marketplaceDir)) return;\n\n this.error(occupiedDirectoryError(marketplaceDir), { exit: EXIT_CODES.ERROR });\n }\n\n private reportCreated(\n marketplaceName: string,\n marketplaceDir: string,\n written: readonly string[],\n ): void {\n this.log(\"\");\n this.logSuccess(`Created marketplace '${marketplaceName}' at ${marketplaceDir}`);\n for (const relPath of written) {\n this.log(` ${relPath}`);\n }\n }\n\n private reportNextSteps(marketplaceName: string, marketplaceDir: string): void {\n const skillDir = path.join(SKILLS_DIR_PATH, exampleSkillId(marketplaceName));\n const steps = [\n `cd ${marketplaceName}`,\n \"Replace the placeholder 'author' in package.json with your own handle — it is what 'build marketplace' records as this marketplace's owner\",\n `Replace ${skillDir}/ with a skill of your own. Every skill id must begin with '${marketplaceName}-'`,\n `${CLI_INVOKE_COMMAND} build plugins`,\n `${CLI_INVOKE_COMMAND} build marketplace`,\n `Push it to GitHub, then add it from the Marketplace button at ${EDITOR_URL}`,\n `${CLI_INVOKE_COMMAND} init --from <id> --marketplace ${marketplaceDir} (from a project — tests your local changes against a configuration built there)`,\n ];\n\n this.log(\"\");\n this.log(\"Next steps:\");\n for (const [index, step] of steps.entries()) {\n this.log(` ${index + 1}. ${step}`);\n }\n this.log(\"\");\n }\n}\n","import path from \"path\";\n\nimport {\n DEFAULT_VERSION,\n SKILL_CATEGORIES_PATH,\n SKILL_RULES_PATH,\n SKILLS_DIR_PATH,\n STACKS_FILE_PATH,\n STANDARD_FILES,\n} from \"../consts.js\";\nimport { writeFile } from \"../utils/fs.js\";\n\ntype ScaffoldFile = {\n /** Path relative to the marketplace root. */\n relPath: string;\n contents: string;\n};\n\nconst EXAMPLE_SKILL_SUFFIX = \"example-skill\";\n\n/** `web` rather than an invented domain, which would reach no sub-agent. */\nconst EXAMPLE_DOMAIN = \"web\";\n\n/** No built-in category holds this key, so declaring it adds one rather than redefining another. */\nconst EXAMPLE_CATEGORY = `${EXAMPLE_DOMAIN}-example`;\n\n/** Not namespaced: the namespace rule governs ids, not slugs. */\nconst EXAMPLE_SLUG = \"example-skill\";\n\n/** Where the scaffolded category sorts among the categories a marketplace grows later. */\nconst EXAMPLE_CATEGORY_ORDER = 1;\n\nconst INITIAL_PACKAGE_VERSION = \"0.1.0\";\n\nconst EXAMPLE_STACK_AGENT = \"web-developer\";\n\n/** Prefixed with the marketplace name, which `build marketplace` requires of every id. */\nexport function exampleSkillId(marketplaceName: string): string {\n return `${marketplaceName}-${EXAMPLE_SKILL_SUFFIX}`;\n}\n\n/** Writes exactly what the marketplace guide promises; a config pair would look installed. */\nexport async function writeMarketplaceScaffold(\n marketplaceDir: string,\n marketplaceName: string,\n): Promise<string[]> {\n const files = scaffoldFiles(marketplaceName);\n\n await Promise.all(\n files.map((file) => writeFile(path.join(marketplaceDir, file.relPath), file.contents)),\n );\n\n return files.map((file) => file.relPath);\n}\n\nfunction scaffoldFiles(marketplaceName: string): ScaffoldFile[] {\n const skillId = exampleSkillId(marketplaceName);\n const skillDir = path.join(SKILLS_DIR_PATH, skillId);\n\n return [\n { relPath: STANDARD_FILES.PACKAGE_JSON, contents: packageJson(marketplaceName) },\n { relPath: SKILL_CATEGORIES_PATH, contents: skillCategoriesModule() },\n { relPath: SKILL_RULES_PATH, contents: skillRulesModule() },\n { relPath: STACKS_FILE_PATH, contents: stacksModule(marketplaceName, skillId) },\n { relPath: path.join(skillDir, STANDARD_FILES.SKILL_MD), contents: skillMd(skillId) },\n {\n relPath: path.join(skillDir, STANDARD_FILES.METADATA_YAML),\n contents: metadataYaml(marketplaceName),\n },\n ];\n}\n\n/** The loader reads only a default export, so the export form is load-bearing. */\nfunction configModule(comment: string, data: unknown): string {\n return `${comment}\\nexport default ${JSON.stringify(data, null, 2)};\\n`;\n}\n\n/** `author` is the marketplace's own handle, a placeholder the next steps say to replace. */\nfunction packageJson(marketplaceName: string): string {\n return `${JSON.stringify(\n {\n name: marketplaceName,\n version: INITIAL_PACKAGE_VERSION,\n description: `Skills curated for ${marketplaceName}'s conventions`,\n author: { name: authorHandle(marketplaceName) },\n },\n null,\n 2,\n )}\\n`;\n}\n\nfunction authorHandle(marketplaceName: string): string {\n return `@${marketplaceName}`;\n}\n\nfunction skillCategoriesModule(): string {\n return configModule(\"// The categories this marketplace's skills fall into.\", {\n version: DEFAULT_VERSION,\n categories: {\n [EXAMPLE_CATEGORY]: {\n id: EXAMPLE_CATEGORY,\n displayName: \"Example\",\n description: \"Replace this with a category of your own\",\n domain: EXAMPLE_DOMAIN,\n exclusive: false,\n order: EXAMPLE_CATEGORY_ORDER,\n },\n },\n });\n}\n\n/** Version only: rules name skills by the CLI's slug union, which a marketplace's own lack. */\nfunction skillRulesModule(): string {\n return configModule(\n [\n \"// Relationships between skills — conflicts, requires, alternatives.\",\n \"//\",\n \"// Rules may only name skills the public catalogue carries; this marketplace's own\",\n \"// skills cannot be named here yet, and a rule that names one will not load.\",\n ].join(\"\\n\"),\n { version: DEFAULT_VERSION },\n );\n}\n\nfunction stacksModule(marketplaceName: string, skillId: string): string {\n return configModule(\"// The stacks this marketplace offers.\", {\n stacks: [\n {\n id: `${marketplaceName}-starter`,\n name: `${marketplaceName} starter`,\n description: `Every skill ${marketplaceName} ships`,\n agents: {\n [EXAMPLE_STACK_AGENT]: {\n [EXAMPLE_CATEGORY]: [{ id: skillId }],\n },\n },\n },\n ],\n });\n}\n\n/** The frontmatter id is also the directory name (`doctor` compares them). */\nfunction skillMd(skillId: string): string {\n return `---\nname: ${skillId}\ndescription: A placeholder skill — replace it with one of your own\n---\n\n# Example Skill\n\nThis is where a skill's content goes: the conventions, patterns and rules you want\nevery sub-agent carrying it to follow.\n\nReplace this file and the \\`${STANDARD_FILES.METADATA_YAML}\\` beside it, and rename the\ndirectory to the id your skill should publish under.\n`;\n}\n\nfunction metadataYaml(marketplaceName: string): string {\n return [\n \"custom: true\",\n `domain: ${EXAMPLE_DOMAIN}`,\n `author: \"${authorHandle(marketplaceName)}\"`,\n \"displayName: Example Skill\",\n `category: ${EXAMPLE_CATEGORY}`,\n `slug: ${EXAMPLE_SLUG}`,\n 'cliDescription: \"A placeholder skill to replace with your own\"',\n 'usageGuidance: \"Use when you need a worked example of this marketplace\\'s skill shape\"',\n \"\",\n ].join(\"\\n\");\n}\n"],"mappings":"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","names":["path","path"]}
|
package/dist/commands/search.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
loadSource
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-
|
|
8
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-66AEVERM.js";
|
|
5
|
+
import "../chunk-IWY5IR4F.js";
|
|
6
|
+
import "../chunk-THO7LO5B.js";
|
|
7
|
+
import "../chunk-5BNX73OU.js";
|
|
8
|
+
import "../chunk-2YA4DDRM.js";
|
|
9
9
|
import {
|
|
10
10
|
BaseCommand
|
|
11
|
-
} from "../chunk-
|
|
12
|
-
import "../chunk-CLPUWOSA.js";
|
|
11
|
+
} from "../chunk-GEMW5RQ2.js";
|
|
13
12
|
import {
|
|
14
13
|
STATUS_MESSAGES,
|
|
14
|
+
typedValues
|
|
15
|
+
} from "../chunk-GAKVZNTX.js";
|
|
16
|
+
import {
|
|
17
|
+
plural,
|
|
15
18
|
stripTerminalControls,
|
|
16
19
|
truncateText
|
|
17
|
-
} from "../chunk-
|
|
18
|
-
import
|
|
19
|
-
|
|
20
|
-
} from "../chunk-52HDHJ7I.js";
|
|
21
|
-
import "../chunk-PJWGTNOX.js";
|
|
22
|
-
import "../chunk-NQW25DCF.js";
|
|
20
|
+
} from "../chunk-AUNRHWH4.js";
|
|
21
|
+
import "../chunk-7C3PFRBU.js";
|
|
22
|
+
import "../chunk-GHHJYNAN.js";
|
|
23
23
|
|
|
24
24
|
// src/cli/commands/search.ts
|
|
25
25
|
import { Args } from "@oclif/core";
|
|
@@ -54,31 +54,15 @@ var Search = class _Search extends BaseCommand {
|
|
|
54
54
|
async runSearch(query) {
|
|
55
55
|
try {
|
|
56
56
|
this.log(STATUS_MESSAGES.LOADING_SKILLS);
|
|
57
|
-
const
|
|
58
|
-
const results = sortBy(
|
|
59
|
-
allSkills.filter((skill) => matchesQuery(skill, query)),
|
|
60
|
-
(r) => r.displayName.toLowerCase()
|
|
61
|
-
);
|
|
57
|
+
const results = skillsMatching(await loadSearchableSkills(), query);
|
|
62
58
|
this.log("");
|
|
63
59
|
if (results.length === 0) {
|
|
64
60
|
this.warn(`No skills found matching "${query}"`);
|
|
65
61
|
return;
|
|
66
62
|
}
|
|
67
|
-
this.
|
|
68
|
-
`Found ${results.length} skill${results.length === 1 ? "" : "s"} matching "${query}"`
|
|
69
|
-
);
|
|
63
|
+
this.log(`Found ${plural(results.length, "skill")} matching "${query}"`);
|
|
70
64
|
this.log("");
|
|
71
|
-
|
|
72
|
-
data: results.map(toResultRow),
|
|
73
|
-
columns: [
|
|
74
|
-
{ key: "id", name: "ID" },
|
|
75
|
-
{ key: "name", name: "Name" },
|
|
76
|
-
{ key: "source", name: "Origin" },
|
|
77
|
-
{ key: "category", name: "Category" },
|
|
78
|
-
{ key: "description", name: "Description" }
|
|
79
|
-
],
|
|
80
|
-
headerOptions: { bold: true }
|
|
81
|
-
});
|
|
65
|
+
printResultsTable(results);
|
|
82
66
|
this.log("");
|
|
83
67
|
} catch (error) {
|
|
84
68
|
this.handleError(error);
|
|
@@ -89,6 +73,25 @@ async function loadSearchableSkills() {
|
|
|
89
73
|
const { sourceResult } = await loadSource({ projectDir: process.cwd() });
|
|
90
74
|
return typedValues(sourceResult.matrix.skills);
|
|
91
75
|
}
|
|
76
|
+
function skillsMatching(skills, query) {
|
|
77
|
+
return sortBy(
|
|
78
|
+
skills.filter((skill) => matchesQuery(skill, query)),
|
|
79
|
+
(skill) => skill.displayName.toLowerCase()
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
function printResultsTable(results) {
|
|
83
|
+
printTable({
|
|
84
|
+
data: results.map(toResultRow),
|
|
85
|
+
columns: [
|
|
86
|
+
{ key: "id", name: "ID" },
|
|
87
|
+
{ key: "name", name: "Name" },
|
|
88
|
+
{ key: "source", name: "Origin" },
|
|
89
|
+
{ key: "category", name: "Category" },
|
|
90
|
+
{ key: "description", name: "Description" }
|
|
91
|
+
],
|
|
92
|
+
headerOptions: { bold: true }
|
|
93
|
+
});
|
|
94
|
+
}
|
|
92
95
|
function toResultRow(skill) {
|
|
93
96
|
return {
|
|
94
97
|
id: stripTerminalControls(skill.id),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/commands/search.ts"],"sourcesContent":["import { Args } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport { sortBy } from \"remeda\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { loadSource } from \"../lib/operations/index.js\";\nimport type { ResolvedSkill } from \"../types/index.js\";\nimport { STATUS_MESSAGES } from \"../utils/messages.js\";\nimport { stripTerminalControls, truncateText } from \"../utils/string.js\";\nimport { typedValues } from \"../utils/typed-object.js\";\n\nconst MAX_DESCRIPTION_WIDTH = 50;\n\n
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/search.ts"],"sourcesContent":["import { Args } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport { sortBy } from \"remeda\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { loadSource } from \"../lib/operations/index.js\";\nimport type { ResolvedSkill } from \"../types/index.js\";\nimport { STATUS_MESSAGES } from \"../utils/messages.js\";\nimport { plural, stripTerminalControls, truncateText } from \"../utils/string.js\";\nimport { typedValues } from \"../utils/typed-object.js\";\n\nconst MAX_DESCRIPTION_WIDTH = 50;\n\n/** Plain strings: sanitised values are no longer known to be in their unions. */\ntype ResultRow = {\n id: string;\n name: string;\n source: string;\n category: string;\n description: string;\n};\n\nexport default class Search extends BaseCommand {\n static summary = \"Search the catalog of available skills\";\n static description =\n \"Read-only catalog browse. Searches the marketplace this installation reads from, \" +\n \"plus the local skills already on disk, by id, displayName, slug, description, or \" +\n \"category. To install one, add it in agentsinc.sh/editor.\";\n\n static examples = [\n {\n description: \"Search for React skills\",\n command: \"<%= config.bin %> search react\",\n },\n {\n description: \"Search by any keyword (matches id, name, description, category)\",\n command: \"<%= config.bin %> search state\",\n },\n ];\n\n static args = {\n query: Args.string({\n description: \"Search query (matches id, displayName, slug, description, category)\",\n required: true,\n }),\n };\n\n static flags = {};\n\n async run(): Promise<void> {\n const { args } = await this.parse(Search);\n // The configs name the marketplace searched, so an unreadable one is not read past.\n await this.ensureConfigReadable(process.cwd());\n await this.runSearch(args.query);\n }\n\n private async runSearch(query: string): Promise<void> {\n try {\n this.log(STATUS_MESSAGES.LOADING_SKILLS);\n const results = skillsMatching(await loadSearchableSkills(), query);\n\n this.log(\"\");\n if (results.length === 0) {\n this.warn(`No skills found matching \"${query}\"`);\n return;\n }\n\n this.log(`Found ${plural(results.length, \"skill\")} matching \"${query}\"`);\n this.log(\"\");\n printResultsTable(results);\n this.log(\"\");\n } catch (error) {\n this.handleError(error);\n }\n }\n}\n\n/** The marketplace matrix, with on-disk local skills already merged in by `loadSource`. */\nasync function loadSearchableSkills(): Promise<ResolvedSkill[]> {\n const { sourceResult } = await loadSource({ projectDir: process.cwd() });\n\n return typedValues(sourceResult.matrix.skills);\n}\n\n/** In display-name order, case aside. */\nfunction skillsMatching(skills: ResolvedSkill[], query: string): ResolvedSkill[] {\n return sortBy(\n skills.filter((skill) => matchesQuery(skill, query)),\n (skill) => skill.displayName.toLowerCase(),\n );\n}\n\nfunction printResultsTable(results: ResolvedSkill[]): void {\n printTable({\n data: results.map(toResultRow),\n columns: [\n { key: \"id\", name: \"ID\" },\n { key: \"name\", name: \"Name\" },\n { key: \"source\", name: \"Origin\" },\n { key: \"category\", name: \"Category\" },\n { key: \"description\", name: \"Description\" },\n ],\n headerOptions: { bold: true },\n });\n}\n\n/** Strips terminal controls: a third-party marketplace's text could otherwise repaint the table. */\nfunction toResultRow(skill: ResolvedSkill): ResultRow {\n return {\n id: stripTerminalControls(skill.id),\n name: stripTerminalControls(skill.displayName),\n source: stripTerminalControls(activeSourceName(skill)),\n category: stripTerminalControls(skill.category),\n description: truncateText(skill.description, MAX_DESCRIPTION_WIDTH),\n };\n}\n\n/** `loadSource` always tags an origin, so an untagged skill is a bug, not a fallback case. */\nfunction activeSourceName(skill: ResolvedSkill): string {\n const { activeSource } = skill;\n if (!activeSource) {\n throw new Error(\n `Skill \"${skill.id}\" was loaded with no origin, so where it comes from is unknown`,\n );\n }\n return activeSource.name;\n}\n\nfunction matchesQuery(skill: ResolvedSkill, query: string): boolean {\n const lowerQuery = query.toLowerCase();\n return [skill.id, skill.displayName, skill.slug, skill.description, skill.category].some(\n (field) => field.toLowerCase().includes(lowerQuery),\n );\n}\n"],"mappings":"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","names":[]}
|
package/dist/commands/share.js
CHANGED
|
@@ -2,22 +2,21 @@
|
|
|
2
2
|
import {
|
|
3
3
|
publishSeedConfig,
|
|
4
4
|
seedPayloadForInstallation
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-ELV5WDS3.js";
|
|
6
6
|
import {
|
|
7
7
|
unofferablePlacementsFound
|
|
8
|
-
} from "../chunk-
|
|
9
|
-
import "../chunk-
|
|
10
|
-
import "../chunk-
|
|
8
|
+
} from "../chunk-HACRR422.js";
|
|
9
|
+
import "../chunk-YGDWHDOY.js";
|
|
10
|
+
import "../chunk-2YA4DDRM.js";
|
|
11
11
|
import {
|
|
12
12
|
providerFlag,
|
|
13
13
|
providerNamedBy,
|
|
14
14
|
refuseAnAmbiguousInstallation
|
|
15
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-OCAVW6N5.js";
|
|
16
16
|
import {
|
|
17
17
|
BaseCommand,
|
|
18
18
|
EXIT_CODES
|
|
19
|
-
} from "../chunk-
|
|
20
|
-
import "../chunk-CLPUWOSA.js";
|
|
19
|
+
} from "../chunk-GEMW5RQ2.js";
|
|
21
20
|
import {
|
|
22
21
|
formatZodErrors,
|
|
23
22
|
getErrorMessage,
|
|
@@ -26,17 +25,17 @@ import {
|
|
|
26
25
|
sharedConfigDestinations,
|
|
27
26
|
sharedIdNamesAFolder,
|
|
28
27
|
sharedSkillsLeftBehind,
|
|
29
|
-
|
|
30
|
-
truncateText,
|
|
28
|
+
typedEntries,
|
|
31
29
|
warn
|
|
32
|
-
} from "../chunk-
|
|
30
|
+
} from "../chunk-GAKVZNTX.js";
|
|
33
31
|
import {
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
stripTerminalControls,
|
|
33
|
+
truncateText
|
|
34
|
+
} from "../chunk-AUNRHWH4.js";
|
|
36
35
|
import {
|
|
37
36
|
installableSeedPayloadSchema
|
|
38
|
-
} from "../chunk-
|
|
39
|
-
import "../chunk-
|
|
37
|
+
} from "../chunk-7C3PFRBU.js";
|
|
38
|
+
import "../chunk-GHHJYNAN.js";
|
|
40
39
|
|
|
41
40
|
// src/cli/commands/share.ts
|
|
42
41
|
import { Flags } from "@oclif/core";
|
|
@@ -114,18 +113,7 @@ var Share = class _Share extends BaseCommand {
|
|
|
114
113
|
"<%= config.bin %> <%= command.id %>",
|
|
115
114
|
"cat proposal.json | <%= config.bin %> <%= command.id %> --stdin"
|
|
116
115
|
];
|
|
117
|
-
/**
|
|
118
|
-
* Read, map, refuse, publish, then say what the id will not do everywhere.
|
|
119
|
-
*
|
|
120
|
-
* Everything that can fail locally fails before the POST. The store's free tier allows a
|
|
121
|
-
* thousand writes a day and reads a hundred times that, so a write is the scarce half — and one
|
|
122
|
-
* spent on a configuration that cannot be installed buys a dead link.
|
|
123
|
-
*
|
|
124
|
-
* The first three steps are `seedPayloadForInstallation`, shared with `edit --ui`: the two
|
|
125
|
-
* commands mint the same id from the same directory and differ only in what they do with it.
|
|
126
|
-
* The one refusal `edit --ui` does not share is of ejected skills — a share carries plugins
|
|
127
|
-
* only, and the editor is where a user goes to turn ejected skills into plugins.
|
|
128
|
-
*/
|
|
116
|
+
/** Everything that can fail locally fails before the POST: store writes are the scarce quota. */
|
|
129
117
|
async run() {
|
|
130
118
|
const { flags } = await this.parse(_Share);
|
|
131
119
|
if (!flags.stdin) {
|
|
@@ -146,31 +134,11 @@ var Share = class _Share extends BaseCommand {
|
|
|
146
134
|
this.reportShared(published.id);
|
|
147
135
|
for (const caveat of caveats) warn(caveat);
|
|
148
136
|
}
|
|
149
|
-
/**
|
|
150
|
-
* Refuses a configuration asking for a mode/scope cell its own host does not offer, before the
|
|
151
|
-
* payload is built and long before the POST.
|
|
152
|
-
*
|
|
153
|
-
* **`share` is a read path, and the roster that names them missed it.** The list this refusal
|
|
154
|
-
* was built against reads "`compile`, `edit`, `update` and `doctor`" and claims to be every
|
|
155
|
-
* command that acts on a configuration it did not just write — while `share` sits beside them
|
|
156
|
-
* reading the same file through `seedPayloadForInstallation`. What it publishes is described as
|
|
157
|
-
* "the skills, sub-agents and per-agent curation installed HERE", and a row the host could not
|
|
158
|
-
* place was never installed here at all, so the id would describe an installation that does not
|
|
159
|
-
* exist. `refuseAnAmbiguousInstallation` above is this finding's sibling and was already asked;
|
|
160
|
-
* the two are the pair `doctor`'s Placements row reports together.
|
|
161
|
-
*
|
|
162
|
-
* A refusal rather than a row, like the other three writers, and for a reason of its own: the
|
|
163
|
-
* store's write is the scarce half, and one spent on an installation nothing on this machine
|
|
164
|
-
* will act on buys a link to a misdescription.
|
|
165
|
-
*
|
|
166
|
-
* `uninstall` reads the same file and is deliberately NOT on this roster: a refusal there would
|
|
167
|
-
* make an unofferable installation unremovable, which is a guard that has swallowed its domain.
|
|
168
|
-
*/
|
|
137
|
+
/** A placement the host cannot fill was never installed here, so the id would misdescribe it. */
|
|
169
138
|
async refuseUnofferablePlacements(cwd) {
|
|
170
139
|
const [finding] = await unofferablePlacementsFound(cwd);
|
|
171
140
|
if (finding !== void 0) this.error(finding, { exit: EXIT_CODES.ERROR });
|
|
172
141
|
}
|
|
173
|
-
/** The installation in this directory: mapped, refused if it holds ejected skills, announced. */
|
|
174
142
|
async payloadFromInstallation() {
|
|
175
143
|
const prepared = await seedPayloadForInstallation(process.cwd());
|
|
176
144
|
if (!prepared.ok) {
|
|
@@ -183,36 +151,14 @@ var Share = class _Share extends BaseCommand {
|
|
|
183
151
|
caveats: caveatsAbout(prepared.payload, prepared.leftBehind)
|
|
184
152
|
};
|
|
185
153
|
}
|
|
186
|
-
/**
|
|
187
|
-
* Refuses a share while anything it would send is an ejected (Local) skill.
|
|
188
|
-
*
|
|
189
|
-
* An ejected skill is a copy on this machine, which the user may have edited and an
|
|
190
|
-
* editor-added skill always is, so a share carries plugins only — from a project, that covers
|
|
191
|
-
* the ejected skills it inherits from the global installation as well as its own. A skill the
|
|
192
|
-
* user wrote by hand is never in the payload, so it neither travels nor refuses.
|
|
193
|
-
*/
|
|
154
|
+
/** A share carries plugins only: an ejected skill is a local copy the user may have edited. */
|
|
194
155
|
refuseEjectedSkills(payload) {
|
|
195
156
|
const ejected = ejectedSkillsIn(payload);
|
|
196
157
|
if (ejected.length > 0) {
|
|
197
158
|
this.error(shareRefusesEjectedSkills(ejected), { exit: EXIT_CODES.ERROR });
|
|
198
159
|
}
|
|
199
160
|
}
|
|
200
|
-
/**
|
|
201
|
-
* A configuration the CALLER holds, which is why nothing here reads an installation.
|
|
202
|
-
*
|
|
203
|
-
* That is the whole distinction the flag draws, and it is not cosmetic: a bare `share` resolves
|
|
204
|
-
* an installation the way every other command does — this project, then the global one — so
|
|
205
|
-
* without this branch, sharing a piped payload from a directory with nothing in it would
|
|
206
|
-
* publish whatever the machine happens to have installed globally.
|
|
207
|
-
*
|
|
208
|
-
* The producer this exists for is not this CLI. `meta-config-stack-detect` walks a repository
|
|
209
|
-
* and emits a `SeedPayload` it is forbidden to write or apply, and an id is the only door into
|
|
210
|
-
* the editor, which reads `?fromId=` and nothing else. Publishing from here rather than from
|
|
211
|
-
* the producer keeps `SEED_VERSION`, the `AGENTS_INC_API_URL` override and the caller's
|
|
212
|
-
* user-agent in the one place that owns them.
|
|
213
|
-
*
|
|
214
|
-
* It owes no caveats: those describe an installation, and none was read.
|
|
215
|
-
*/
|
|
161
|
+
/** The caller's configuration; no installation is read, so it owes no caveats. */
|
|
216
162
|
async payloadFromPipe() {
|
|
217
163
|
if (process.stdin.isTTY) {
|
|
218
164
|
this.error(STDIN_IS_A_TERMINAL, { exit: EXIT_CODES.ERROR });
|
|
@@ -223,12 +169,6 @@ var Share = class _Share extends BaseCommand {
|
|
|
223
169
|
}
|
|
224
170
|
return { payload: read.payload, caveats: [] };
|
|
225
171
|
}
|
|
226
|
-
/**
|
|
227
|
-
* Both destinations, because an id nobody can act on is not a share and there are exactly two
|
|
228
|
-
* things that read one: this CLI, and the editor the configuration can be reopened in. The
|
|
229
|
-
* lines themselves are `sharedConfigDestinations`, shared with `edit --ui` for the same reason
|
|
230
|
-
* the mint above is.
|
|
231
|
-
*/
|
|
232
172
|
reportShared(id) {
|
|
233
173
|
this.logSuccess(`Shared as ${id}`);
|
|
234
174
|
for (const destination of sharedConfigDestinations(id)) {
|