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
|
@@ -1,27 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
SelectList
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3ED3KHHD.js";
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
notInstalledGlobally,
|
|
9
|
-
openUrl,
|
|
10
|
-
readInstalledGlobal
|
|
11
|
-
} from "./chunk-6HNXYYVF.js";
|
|
6
|
+
openUrl
|
|
7
|
+
} from "./chunk-PLFANHRZ.js";
|
|
12
8
|
import {
|
|
13
9
|
fetchSeedConfig
|
|
14
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-YGDWHDOY.js";
|
|
15
11
|
import {
|
|
16
12
|
promptConfirm,
|
|
17
13
|
promptValue
|
|
18
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-P6CYS4JK.js";
|
|
19
15
|
import {
|
|
20
16
|
Confirm
|
|
21
17
|
} from "./chunk-OZXAJNLA.js";
|
|
22
18
|
import {
|
|
23
19
|
hostCompileNotices
|
|
24
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-PSUTNOQ2.js";
|
|
25
21
|
import {
|
|
26
22
|
compileAgentsAllScopes,
|
|
27
23
|
compileProjectScope,
|
|
@@ -29,30 +25,36 @@ import {
|
|
|
29
25
|
movedGlobalAgentInputs,
|
|
30
26
|
sayCapturedWarnings,
|
|
31
27
|
writeProjectConfig
|
|
32
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-66AEVERM.js";
|
|
33
29
|
import {
|
|
34
30
|
copyLocalSkills,
|
|
35
31
|
discoverInstalledSkills
|
|
36
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-IWY5IR4F.js";
|
|
37
33
|
import {
|
|
38
34
|
loadAgentDefs
|
|
39
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-THO7LO5B.js";
|
|
40
36
|
import {
|
|
41
37
|
render
|
|
42
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-KIK5EZYD.js";
|
|
43
39
|
import {
|
|
44
40
|
providerFlag,
|
|
45
41
|
providerNamedBy,
|
|
46
42
|
providerNeedsAConfigurationToInstall
|
|
47
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-OCAVW6N5.js";
|
|
48
44
|
import {
|
|
49
45
|
BaseCommand,
|
|
50
46
|
EXIT_CODES,
|
|
51
47
|
clearTerminalScreen,
|
|
48
|
+
holdInstalledGlobal,
|
|
49
|
+
installPlanLines,
|
|
50
|
+
installsAtHome,
|
|
51
|
+
notInstalledGlobally,
|
|
52
|
+
readInstalledGlobal,
|
|
52
53
|
registerExternalSkills,
|
|
53
54
|
writeExternalSkills
|
|
54
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-GEMW5RQ2.js";
|
|
55
56
|
import {
|
|
57
|
+
ERROR_MESSAGES,
|
|
56
58
|
INCOMPLETE_WORK_RECOVERY,
|
|
57
59
|
INSTALL_MODE_DESCRIPTIONS,
|
|
58
60
|
INSTALL_MODE_LABELS,
|
|
@@ -63,6 +65,7 @@ import {
|
|
|
63
65
|
agentCodec,
|
|
64
66
|
agentsNotCompiled,
|
|
65
67
|
applySharedConfigHere,
|
|
68
|
+
assertNamedSourceUsable,
|
|
66
69
|
buildAgentScopeMap,
|
|
67
70
|
carriedSkillsWritten,
|
|
68
71
|
chooseProviderForThisRun,
|
|
@@ -71,7 +74,7 @@ import {
|
|
|
71
74
|
detectProjectInstallation,
|
|
72
75
|
fileExists,
|
|
73
76
|
getErrorMessage,
|
|
74
|
-
|
|
77
|
+
getInstallationsByProvider,
|
|
75
78
|
globalScopedAgentsHint,
|
|
76
79
|
holdsItsOwnInstallation,
|
|
77
80
|
hostAt,
|
|
@@ -80,10 +83,9 @@ import {
|
|
|
80
83
|
isHomeDirectory,
|
|
81
84
|
isLocalSource,
|
|
82
85
|
keptAsInstalledGlobally,
|
|
83
|
-
loadProjectConfig,
|
|
84
86
|
permissionFiles,
|
|
85
|
-
plural,
|
|
86
87
|
providerInUse,
|
|
88
|
+
providerToNameAt,
|
|
87
89
|
readFileSafe,
|
|
88
90
|
relativeConfigPath,
|
|
89
91
|
resolveBranding,
|
|
@@ -91,10 +93,11 @@ import {
|
|
|
91
93
|
seedToInstallSelection,
|
|
92
94
|
settingsFileSchema,
|
|
93
95
|
sharedConfigExistingInstall,
|
|
94
|
-
skippedUnknownAgents,
|
|
95
|
-
skippedUnknownSkills,
|
|
96
96
|
warn
|
|
97
|
-
} from "./chunk-
|
|
97
|
+
} from "./chunk-GAKVZNTX.js";
|
|
98
|
+
import {
|
|
99
|
+
plural
|
|
100
|
+
} from "./chunk-AUNRHWH4.js";
|
|
98
101
|
import {
|
|
99
102
|
ASCII_LOGO,
|
|
100
103
|
CLI_COLORS,
|
|
@@ -104,30 +107,31 @@ import {
|
|
|
104
107
|
EJECT_SOURCE,
|
|
105
108
|
MAX_CONFIG_FILE_SIZE,
|
|
106
109
|
editorConfigUrl
|
|
107
|
-
} from "./chunk-
|
|
110
|
+
} from "./chunk-7C3PFRBU.js";
|
|
108
111
|
|
|
109
112
|
// src/cli/commands/init.tsx
|
|
110
113
|
import "react";
|
|
111
114
|
import { Flags } from "@oclif/core";
|
|
112
115
|
import { Box as Box2, Text as Text2, useApp } from "ink";
|
|
116
|
+
import { partition } from "remeda";
|
|
113
117
|
|
|
114
118
|
// src/cli/components/hooks/use-terminal-dimensions.ts
|
|
115
119
|
import { useState, useEffect } from "react";
|
|
116
120
|
import { useStdout } from "ink";
|
|
117
121
|
var DEFAULT_COLUMNS = 80;
|
|
118
122
|
var DEFAULT_ROWS = 24;
|
|
119
|
-
function
|
|
120
|
-
|
|
121
|
-
const [dimensions, setDimensions] = useState(() => ({
|
|
123
|
+
function dimensionsOf(stdout) {
|
|
124
|
+
return {
|
|
122
125
|
columns: stdout.columns || DEFAULT_COLUMNS,
|
|
123
126
|
rows: stdout.rows || DEFAULT_ROWS
|
|
124
|
-
}
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function useTerminalDimensions() {
|
|
130
|
+
const { stdout } = useStdout();
|
|
131
|
+
const [dimensions, setDimensions] = useState(() => dimensionsOf(stdout));
|
|
125
132
|
useEffect(() => {
|
|
126
133
|
const handleResize = () => {
|
|
127
|
-
setDimensions(
|
|
128
|
-
columns: stdout.columns || DEFAULT_COLUMNS,
|
|
129
|
-
rows: stdout.rows || DEFAULT_ROWS
|
|
130
|
-
});
|
|
134
|
+
setDimensions(dimensionsOf(stdout));
|
|
131
135
|
};
|
|
132
136
|
stdout.on("resize", handleResize);
|
|
133
137
|
return () => {
|
|
@@ -248,16 +252,24 @@ var Dashboard = ({ data, onSelect, onCancel }) => {
|
|
|
248
252
|
)
|
|
249
253
|
] });
|
|
250
254
|
};
|
|
251
|
-
function dashboardCountLines(
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
`
|
|
255
|
-
|
|
255
|
+
function dashboardCountLines({ installations }) {
|
|
256
|
+
const named = installations.length > 1;
|
|
257
|
+
const blocks = installations.map((installation) => [
|
|
258
|
+
...named ? [` Provider: ${installation.provider}`] : [],
|
|
259
|
+
...installationCountLines(installation)
|
|
260
|
+
]);
|
|
261
|
+
return blankLineBetween(blocks);
|
|
262
|
+
}
|
|
263
|
+
function blankLineBetween(blocks) {
|
|
264
|
+
return blocks.flatMap((block, index) => index === 0 ? block : ["", ...block]);
|
|
265
|
+
}
|
|
266
|
+
function installationCountLines(installation) {
|
|
267
|
+
return [
|
|
268
|
+
` Skills: ${installation.skillCount} installed`,
|
|
269
|
+
` Agents: ${installation.agentCount} compiled`,
|
|
270
|
+
` Mode: ${INSTALL_MODE_LABELS[installation.mode]}`,
|
|
271
|
+
...installation.marketplace ? [` Marketplace: ${installation.marketplace}`] : []
|
|
256
272
|
];
|
|
257
|
-
if (data.source) {
|
|
258
|
-
lines.push(` Marketplace: ${data.source}`);
|
|
259
|
-
}
|
|
260
|
-
return lines;
|
|
261
273
|
}
|
|
262
274
|
function formatDashboardText(data) {
|
|
263
275
|
return [data.name, "", ...dashboardCountLines(data), "", DASHBOARD_OPTIONS_LINE].join("\n");
|
|
@@ -301,12 +313,7 @@ function sharedConfigSourceFlags(flags, payload) {
|
|
|
301
313
|
return { marketplace: flags.marketplace ?? payload.marketplace };
|
|
302
314
|
}
|
|
303
315
|
var Init = class _Init extends BaseCommand {
|
|
304
|
-
/**
|
|
305
|
-
* The name this run prints itself under, resolved once on {@link install}'s spine because the
|
|
306
|
-
* closing line is printed several calls below it. Same shape and same reason as `uninstall`'s
|
|
307
|
-
* field: a plain `string` holding the shipped default rather than an optional every reader
|
|
308
|
-
* would have to answer for.
|
|
309
|
-
*/
|
|
316
|
+
/** Resolved once in {@link install}; the closing line is printed several calls below. */
|
|
310
317
|
brandingName = DEFAULT_BRANDING.NAME;
|
|
311
318
|
static summary = `Initialize ${DEFAULT_BRANDING.NAME} in this project`;
|
|
312
319
|
static description = "Build a configuration in agentsinc.sh/editor, or install one by id with --from. Over an existing installation, shows its dashboard.";
|
|
@@ -340,95 +347,57 @@ var Init = class _Init extends BaseCommand {
|
|
|
340
347
|
}),
|
|
341
348
|
provider: providerFlag()
|
|
342
349
|
};
|
|
343
|
-
/**
|
|
344
|
-
* The command in two statements: do the work, then answer for it.
|
|
345
|
-
*
|
|
346
|
-
* {@link install} owns every path through the setup and returns however it likes; the exit
|
|
347
|
-
* code is decided once, here, after the last of them. Deciding it inside would mean deciding
|
|
348
|
-
* it at each of that method's endings, and an ending added later would inherit the exit-0
|
|
349
|
-
* default silently — which is the defect this pair exists to close. `edit` is two statements
|
|
350
|
-
* for the same reason.
|
|
351
|
-
*/
|
|
350
|
+
/** The exit code is decided once, after every path through {@link install} has ended. */
|
|
352
351
|
async run() {
|
|
353
352
|
await this.install();
|
|
354
353
|
this.exitIfWorkIncomplete();
|
|
355
354
|
}
|
|
356
|
-
/**
|
|
357
|
-
|
|
358
|
-
*
|
|
359
|
-
* **One rule, both commands (owner ruling 2026-08-24): `--ui` opens the command's SUBJECT, and
|
|
360
|
-
* `--from` is what supplies one.** `edit --ui` alone opens this installation because that is
|
|
361
|
-
* `edit`'s subject; `init --ui` alone opens the catalogue because a fresh directory has none.
|
|
362
|
-
* Given an id, either opens that id — which is what makes a shared configuration something a
|
|
363
|
-
* recipient can look at rather than only apply blind.
|
|
364
|
-
*
|
|
365
|
-
* No publish happens here and none is needed. `edit --ui` mints an id because an installation
|
|
366
|
-
* is not a configuration the store holds yet; an id already IS one, so this is
|
|
367
|
-
* `editorConfigUrl` and nothing else — no network, no marketplace, no catalogue load.
|
|
368
|
-
*
|
|
369
|
-
* The link is PRINTED first and opened second. Over a pipe, in CI, and on a machine with no
|
|
370
|
-
* desktop session there is no browser to be anybody's — a link nobody can copy is the whole
|
|
371
|
-
* loss, so opening one is the convenience on top and a failure to open is a warning beside a
|
|
372
|
-
* link that still works.
|
|
373
|
-
*
|
|
374
|
-
* A marketplace named here cannot ride along: the address carries an id and nothing else, so
|
|
375
|
-
* the line under the link says how to add it in the editor.
|
|
376
|
-
*/
|
|
377
|
-
async openEditor(projectDir, id, marketplace) {
|
|
355
|
+
/** The link is printed before it is opened, so it still works where no browser can open. */
|
|
356
|
+
async openEditor(projectDir, provider, id, marketplace) {
|
|
378
357
|
const url = id === void 0 ? EDITOR_URL : editorConfigUrl(id);
|
|
379
358
|
const marketplaceLine = marketplace === void 0 ? void 0 : this.addMarketplaceLineOrFail(marketplace);
|
|
380
359
|
this.log(id === void 0 ? `Build it at ${url}` : `Open it at ${url}`);
|
|
381
360
|
if (marketplaceLine !== void 0) this.log(marketplaceLine);
|
|
382
|
-
this.log(applySharedConfigHere(id, await holdsItsOwnInstallation(projectDir)));
|
|
361
|
+
this.log(applySharedConfigHere(id, await holdsItsOwnInstallation(projectDir), provider));
|
|
383
362
|
if (!process.stdin.isTTY) return;
|
|
384
363
|
const opened = await openUrl(url);
|
|
385
364
|
if (!opened.ok) this.warn(opened.error);
|
|
386
365
|
}
|
|
387
|
-
/**
|
|
388
|
-
* Every route `init` has, in the order they are tried: the editor for `--ui` and for a
|
|
389
|
-
* marketplace named without `--from`; for a bare run, the installation's dashboard — or the
|
|
390
|
-
* editor where nothing is installed; and the install of the configuration `--from` names.
|
|
391
|
-
*/
|
|
392
366
|
async install() {
|
|
393
367
|
const { flags } = await this.parse(_Init);
|
|
394
368
|
const projectDir = process.cwd();
|
|
395
369
|
this.settleTheProviderForThisRun(flags);
|
|
396
|
-
if (opensTheEditor(flags))
|
|
370
|
+
if (opensTheEditor(flags)) {
|
|
371
|
+
return this.openEditor(
|
|
372
|
+
projectDir,
|
|
373
|
+
providerNamedBy(flags.provider),
|
|
374
|
+
flags.from,
|
|
375
|
+
flags.marketplace
|
|
376
|
+
);
|
|
377
|
+
}
|
|
397
378
|
await this.ensureConfigReadable(projectDir);
|
|
398
379
|
if (flags.from === void 0) return this.showDashboardOrOpenEditor(projectDir);
|
|
399
380
|
this.brandingName = await this.resolveBrandingName(projectDir);
|
|
400
381
|
const selection = await this.selectionFromSharedConfig(flags.from, flags, projectDir);
|
|
401
382
|
if (!selection) this.exit(EXIT_CODES.CANCELLED);
|
|
402
383
|
this.reportValidationErrors(selection.result.validation);
|
|
403
|
-
await this.handleInstallation(selection);
|
|
384
|
+
await this.handleInstallation(selection, projectDir);
|
|
404
385
|
}
|
|
405
|
-
/** A bare `init`: the installation's dashboard, or the editor where nothing is installed. */
|
|
406
386
|
async showDashboardOrOpenEditor(projectDir) {
|
|
407
387
|
const dashboard = await runDashboardFlow(projectDir, this.config, (msg) => this.log(msg));
|
|
408
388
|
if (dashboard === "cancelled") this.error("Cancelled", { exit: EXIT_CODES.CANCELLED });
|
|
409
|
-
if (dashboard === "not-installed") await this.openEditor(projectDir);
|
|
389
|
+
if (dashboard === "not-installed") await this.openEditor(projectDir, void 0);
|
|
410
390
|
}
|
|
411
|
-
/**
|
|
391
|
+
/** Refused as the install route refuses it, since the line echoes the ref it was given. */
|
|
412
392
|
addMarketplaceLineOrFail(ref) {
|
|
413
393
|
try {
|
|
394
|
+
assertNamedSourceUsable(ref);
|
|
414
395
|
return addMarketplaceInTheEditor(ref, isLocalSource(ref));
|
|
415
396
|
} catch (error) {
|
|
416
397
|
this.handleError(error);
|
|
417
398
|
}
|
|
418
399
|
}
|
|
419
|
-
/**
|
|
420
|
-
* Commits this run to the provider `--provider` named, or refuses a flag with nothing to name.
|
|
421
|
-
*
|
|
422
|
-
* **`--provider` is a LOCATION parameter, not a feature switch**, and the control that proves it
|
|
423
|
-
* is `--provider claude`: naming the default out loud installs byte-for-byte what no flag
|
|
424
|
-
* installs, because all the flag decides is which folder this run creates. Without that half
|
|
425
|
-
* "the flag selects an installation" would be indistinguishable from "the flag means Codex".
|
|
426
|
-
*
|
|
427
|
-
* **And it is meaningless without `--from` (D15).** The provider is chosen in the web app, so
|
|
428
|
-
* the only run that can be told one is the run that installs what the app produced. It also
|
|
429
|
-
* gives the placement refusal something to refuse BEFORE anything is written: with `--from`
|
|
430
|
-
* required, a provider always arrives beside a payload the pre-flight can read.
|
|
431
|
-
*/
|
|
400
|
+
/** `--provider` only picks which folder an install creates, so it needs `--from`. */
|
|
432
401
|
settleTheProviderForThisRun(flags) {
|
|
433
402
|
const named = providerNamedBy(flags.provider);
|
|
434
403
|
if (named === void 0) return;
|
|
@@ -437,46 +406,21 @@ var Init = class _Init extends BaseCommand {
|
|
|
437
406
|
}
|
|
438
407
|
chooseProviderForThisRun(named);
|
|
439
408
|
}
|
|
440
|
-
/**
|
|
441
|
-
* The `--from <id>` producer: fetch and map — and, at a terminal, one question.
|
|
442
|
-
*
|
|
443
|
-
* It installs into a clean directory, which is what the first refusal is: a shared
|
|
444
|
-
* configuration is installed whole, so a directory already holding one has it applied with
|
|
445
|
-
* `edit --from` instead, or is uninstalled first. The second is about the LOCATION rather than what is already in it — a global
|
|
446
|
-
* installation holds only global-scoped content. Both fire before anything is written.
|
|
447
|
-
*
|
|
448
|
-
* A global installation ABOVE a project is not in the way. It is not this project's, so the run
|
|
449
|
-
* adds to it what it lacks and states every entry it already holds as installed (see
|
|
450
|
-
* `holdInstalledGlobal`).
|
|
451
|
-
*
|
|
452
|
-
* Before writing anything the run lists what goes into the project and what into the global
|
|
453
|
-
* install. At a terminal it then asks, and a no writes nothing. With no terminal — a CI job or a
|
|
454
|
-
* script — it prints the same lists and carries on: running headless is most of why the flag
|
|
455
|
-
* exists.
|
|
456
|
-
*/
|
|
409
|
+
/** Every refusal fires before anything is written. */
|
|
457
410
|
async selectionFromSharedConfig(id, flags, projectDir) {
|
|
458
411
|
await this.refuseInstalledProject(projectDir, id);
|
|
459
|
-
this.
|
|
460
|
-
const
|
|
461
|
-
|
|
462
|
-
this.error(fetched.error, { exit: EXIT_CODES.ERROR });
|
|
463
|
-
}
|
|
464
|
-
const sourceFlags = sharedConfigSourceFlags(flags, fetched.payload);
|
|
465
|
-
const { sourceResult, startupMessages } = await this.loadSourceOrFail(sourceFlags);
|
|
412
|
+
const payload = await this.fetchSharedConfigOrFail(id);
|
|
413
|
+
const sourceFlags = sharedConfigSourceFlags(flags, payload);
|
|
414
|
+
const { sourceResult, startupMessages } = await this.loadSourceOrFail(sourceFlags, projectDir);
|
|
466
415
|
const carriedSkills = this.registerExternalSkillsOrFail(
|
|
467
|
-
|
|
416
|
+
payload,
|
|
468
417
|
sourceResult.matrix,
|
|
469
418
|
projectDir
|
|
470
419
|
);
|
|
471
|
-
const
|
|
472
|
-
|
|
473
|
-
sourceResult.matrix
|
|
474
|
-
);
|
|
420
|
+
const mapping = this.decodeSeedOrFail(payload, sourceResult.matrix);
|
|
421
|
+
const { result } = mapping;
|
|
475
422
|
this.refuseProjectScopedContentAtHome(result, projectDir);
|
|
476
|
-
const held = holdInstalledGlobal(
|
|
477
|
-
result,
|
|
478
|
-
isHomeDirectory(projectDir) ? null : await readInstalledGlobal(projectDir)
|
|
479
|
-
);
|
|
423
|
+
const held = holdInstalledGlobal(result, await installedGlobalToHold(projectDir));
|
|
480
424
|
const arrivingCarried = notInstalledGlobally(carriedSkills, held);
|
|
481
425
|
await this.refuseSharedConfigBeforeAsking(
|
|
482
426
|
held.result,
|
|
@@ -485,26 +429,15 @@ var Init = class _Init extends BaseCommand {
|
|
|
485
429
|
sourceResult
|
|
486
430
|
);
|
|
487
431
|
sayCapturedWarnings(startupMessages);
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
this.error(`Configuration '${id}' contains no skills this catalog can install.`, {
|
|
492
|
-
exit: EXIT_CODES.ERROR
|
|
493
|
-
});
|
|
494
|
-
}
|
|
495
|
-
this.logWhatGoesWhere(held);
|
|
432
|
+
this.warnOfSkippedEntries(mapping, held.result.selectedAgents);
|
|
433
|
+
this.refuseAnEmptySelection(held.result, id);
|
|
434
|
+
this.logWhatGoesWhere(held, installsAtHome(result) ? id : void 0);
|
|
496
435
|
if (process.stdin.isTTY && !await this.confirmInstall()) {
|
|
497
436
|
this.log("Setup cancelled");
|
|
498
437
|
return null;
|
|
499
438
|
}
|
|
500
439
|
await this.writeCarriedSkills(arrivingCarried);
|
|
501
|
-
|
|
502
|
-
if (arriving.length > 0) {
|
|
503
|
-
this.log(
|
|
504
|
-
`Installing ${arriving.length} skill(s) across ${result.selectedAgents.length} sub-agent(s)
|
|
505
|
-
`
|
|
506
|
-
);
|
|
507
|
-
}
|
|
440
|
+
this.announceArrivingSkills(held, result.selectedAgents.length);
|
|
508
441
|
return {
|
|
509
442
|
result: held.result,
|
|
510
443
|
sourceResult,
|
|
@@ -512,22 +445,29 @@ var Init = class _Init extends BaseCommand {
|
|
|
512
445
|
installedAlready: new Set(held.installed.skillIds)
|
|
513
446
|
};
|
|
514
447
|
}
|
|
515
|
-
/**
|
|
516
|
-
|
|
517
|
-
* global skills skipped as already installed, the held sub-agents a new skill joins, and the
|
|
518
|
-
* global entries the configuration states otherwise than they are installed, which stay.
|
|
519
|
-
*/
|
|
520
|
-
logWhatGoesWhere(held) {
|
|
448
|
+
/** `idAppliedAtHome` is the id only where a run from home would take the configuration. */
|
|
449
|
+
logWhatGoesWhere(held, idAppliedAtHome) {
|
|
521
450
|
for (const line of installPlanLines(held)) {
|
|
522
451
|
this.log(line);
|
|
523
452
|
}
|
|
524
453
|
const { skillIds, agentNames } = held.keptAsInstalled;
|
|
525
454
|
if (skillIds.length > 0 || agentNames.length > 0) {
|
|
526
|
-
this.log(keptAsInstalledGlobally(skillIds, agentNames));
|
|
455
|
+
this.log(keptAsInstalledGlobally(skillIds, agentNames, idAppliedAtHome));
|
|
527
456
|
}
|
|
528
457
|
this.log("");
|
|
529
458
|
}
|
|
530
|
-
|
|
459
|
+
refuseAnEmptySelection(result, id) {
|
|
460
|
+
if (!selectsNothing(result)) return;
|
|
461
|
+
this.error(`Configuration '${id}' contains no skills this catalog can install.`, {
|
|
462
|
+
exit: EXIT_CODES.ERROR
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
announceArrivingSkills(held, agentCount) {
|
|
466
|
+
const arriving = notInstalledGlobally(held.result.skills, held);
|
|
467
|
+
if (arriving.length === 0) return;
|
|
468
|
+
this.log(`Installing ${arriving.length} skill(s) across ${agentCount} sub-agent(s)
|
|
469
|
+
`);
|
|
470
|
+
}
|
|
531
471
|
async confirmInstall() {
|
|
532
472
|
const outcome = await promptConfirm(({ onConfirm, onCancel }) => /* @__PURE__ */ jsx2(
|
|
533
473
|
Confirm,
|
|
@@ -539,28 +479,23 @@ var Init = class _Init extends BaseCommand {
|
|
|
539
479
|
));
|
|
540
480
|
return outcome === "confirmed";
|
|
541
481
|
}
|
|
542
|
-
/**
|
|
543
|
-
* Refuses to install a shared configuration into a directory that already has one.
|
|
544
|
-
*
|
|
545
|
-
* Project-scoped detection rather than `detectInstallation`, whose global fallback would refuse
|
|
546
|
-
* every clean project on a machine with a global install. A global install above the project is
|
|
547
|
-
* added to rather than refused over — see {@link selectionFromSharedConfig}.
|
|
548
|
-
*
|
|
549
|
-
* This runs before the fetch: there is nothing to learn from the network about a directory that
|
|
550
|
-
* is already spoken for.
|
|
551
|
-
*/
|
|
482
|
+
/** Project-scoped: `detectInstallation`'s global fallback would refuse every clean project. */
|
|
552
483
|
async refuseInstalledProject(projectDir, id) {
|
|
553
484
|
const installation = await detectProjectInstallation(projectDir);
|
|
554
485
|
if (!installation) return;
|
|
555
|
-
|
|
486
|
+
const provider = providerToNameAt(projectDir, providerInUse(projectDir));
|
|
487
|
+
this.error(sharedConfigExistingInstall(installation.configPath, id, provider), {
|
|
556
488
|
exit: EXIT_CODES.ERROR
|
|
557
489
|
});
|
|
558
490
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
491
|
+
async fetchSharedConfigOrFail(id) {
|
|
492
|
+
this.log(`Fetching configuration ${id}...`);
|
|
493
|
+
const fetched = await fetchSeedConfig(id);
|
|
494
|
+
if (!fetched.ok) {
|
|
495
|
+
this.error(fetched.error, { exit: EXIT_CODES.ERROR });
|
|
496
|
+
}
|
|
497
|
+
return fetched.payload;
|
|
498
|
+
}
|
|
564
499
|
decodeSeedOrFail(payload, matrix) {
|
|
565
500
|
try {
|
|
566
501
|
return seedToInstallSelection(payload, matrix);
|
|
@@ -568,14 +503,6 @@ var Init = class _Init extends BaseCommand {
|
|
|
568
503
|
this.handleError(error);
|
|
569
504
|
}
|
|
570
505
|
}
|
|
571
|
-
/**
|
|
572
|
-
* Seats the catalogue entries the payload carries with it, or refuses the run.
|
|
573
|
-
*
|
|
574
|
-
* The refusals are `registerExternalSkills`' own — a carried skill asked for as a plugin, which
|
|
575
|
-
* no marketplace serves, and a carried skill claiming an id the loaded catalogue already owns,
|
|
576
|
-
* whose bytes would be written over that catalogue's own copy — and are reported with this
|
|
577
|
-
* command's exit code for the same reason the decode's is.
|
|
578
|
-
*/
|
|
579
506
|
registerExternalSkillsOrFail(payload, matrix, projectDir) {
|
|
580
507
|
try {
|
|
581
508
|
return registerExternalSkills(payload, matrix, projectDir);
|
|
@@ -583,19 +510,18 @@ var Init = class _Init extends BaseCommand {
|
|
|
583
510
|
this.handleError(error);
|
|
584
511
|
}
|
|
585
512
|
}
|
|
586
|
-
/** Writes the skills the payload brought with it, and says which they were. */
|
|
587
513
|
async writeCarriedSkills(carried) {
|
|
588
514
|
if (carried.length === 0) return;
|
|
589
515
|
await writeExternalSkills(carried);
|
|
590
516
|
this.log(carriedSkillsWritten(carried.map((skill) => skill.id)));
|
|
591
517
|
}
|
|
592
|
-
async loadSourceOrFail(flags) {
|
|
518
|
+
async loadSourceOrFail(flags, projectDir) {
|
|
593
519
|
try {
|
|
594
520
|
const loaded = await loadSource({
|
|
595
|
-
// The one load that may
|
|
521
|
+
// The one load that may choose a marketplace rather than read the stored one.
|
|
596
522
|
caller: "init",
|
|
597
523
|
...flags.marketplace !== void 0 && { sourceFlag: flags.marketplace },
|
|
598
|
-
projectDir
|
|
524
|
+
projectDir,
|
|
599
525
|
captureStartupMessages: true
|
|
600
526
|
});
|
|
601
527
|
return { sourceResult: loaded.sourceResult, startupMessages: loaded.startupMessages };
|
|
@@ -605,88 +531,83 @@ var Init = class _Init extends BaseCommand {
|
|
|
605
531
|
});
|
|
606
532
|
}
|
|
607
533
|
}
|
|
608
|
-
async handleInstallation({
|
|
609
|
-
result,
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
}) {
|
|
614
|
-
const projectDir = process.cwd();
|
|
615
|
-
const activeSkills = result.skills.filter((s) => !s.excluded);
|
|
616
|
-
const toInstall = activeSkills.filter((s) => !installedAlready.has(s.id));
|
|
617
|
-
const installMode = deriveInstallMode(toInstall);
|
|
618
|
-
const ejectedSkills = toInstall.filter((s) => s.origin === EJECT_SOURCE);
|
|
619
|
-
const pluginSkills = toInstall.filter((s) => s.origin !== EJECT_SOURCE);
|
|
620
|
-
this.logInstallPlan(installMode, ejectedSkills, pluginSkills);
|
|
621
|
-
const resolvedMarketplace = pluginSkills.length > 0 ? await this.requireMarketplaceOrExit(
|
|
534
|
+
async handleInstallation({ result, sourceResult, sourceFlags, installedAlready }, projectDir) {
|
|
535
|
+
const plan = planInstall(result, installedAlready);
|
|
536
|
+
this.logInstallPlan(plan);
|
|
537
|
+
const resolvedMarketplace = await this.marketplaceForPluginSkills(
|
|
538
|
+
plan.pluginSkills,
|
|
622
539
|
sourceResult,
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
) : null;
|
|
627
|
-
const copyResult = ejectedSkills.length > 0 ? await this.copyEjectSkillsStep(ejectedSkills, projectDir, sourceResult, installMode) : null;
|
|
540
|
+
projectDir
|
|
541
|
+
);
|
|
542
|
+
const copyResult = await this.copyEjectedSkills(plan, projectDir, sourceResult);
|
|
628
543
|
if (resolvedMarketplace !== null) {
|
|
629
544
|
await this.installPluginSkillsReported(
|
|
630
|
-
pluginSkills,
|
|
545
|
+
plan.pluginSkills,
|
|
631
546
|
resolvedMarketplace,
|
|
632
547
|
projectDir,
|
|
633
548
|
sourceResult.matrix
|
|
634
549
|
);
|
|
635
550
|
}
|
|
636
|
-
const pluginModeSucceeded = resolvedMarketplace !== null;
|
|
637
551
|
try {
|
|
638
|
-
const
|
|
552
|
+
const written = await this.writeConfigAndCompile(
|
|
639
553
|
result,
|
|
640
554
|
sourceResult,
|
|
641
|
-
sourceFlags
|
|
642
|
-
|
|
643
|
-
this.reportSuccess(
|
|
644
|
-
configResult,
|
|
645
|
-
compileResult,
|
|
646
|
-
agentScopeMap,
|
|
647
|
-
installMode,
|
|
648
|
-
pluginModeSucceeded,
|
|
649
|
-
copyResult
|
|
555
|
+
sourceFlags,
|
|
556
|
+
projectDir
|
|
650
557
|
);
|
|
558
|
+
this.reportSuccess(written, copyResult, projectDir);
|
|
651
559
|
await this.showPermissionNotice(projectDir);
|
|
652
560
|
} catch (error) {
|
|
653
561
|
this.handleError(error);
|
|
654
562
|
}
|
|
655
563
|
}
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
564
|
+
async marketplaceForPluginSkills(pluginSkills, sourceResult, projectDir) {
|
|
565
|
+
if (pluginSkills.length === 0) return null;
|
|
566
|
+
return this.requireMarketplaceOrExit(
|
|
567
|
+
sourceResult,
|
|
568
|
+
"install plugin skills",
|
|
569
|
+
hostAt(projectDir),
|
|
570
|
+
(marketplace) => this.log(`Registering marketplace "${marketplace}"...`)
|
|
571
|
+
);
|
|
572
|
+
}
|
|
573
|
+
/** One frame, then unmount: the notice has no exit of its own and `--from` must run headless. */
|
|
661
574
|
async showPermissionNotice(projectDir) {
|
|
662
575
|
const permissionWarning = await checkPermissions(projectDir);
|
|
663
576
|
if (!permissionWarning) return;
|
|
664
577
|
const { unmount } = render(permissionWarning);
|
|
665
578
|
unmount();
|
|
666
579
|
}
|
|
667
|
-
logInstallPlan(
|
|
580
|
+
logInstallPlan(plan) {
|
|
668
581
|
this.log("\n");
|
|
669
|
-
this.log(`Selected ${plural(ejectedSkills.length + pluginSkills.length, "skill")}`);
|
|
670
|
-
this.log(
|
|
671
|
-
`Install mode: ${installMode === "mixed" ? `${INSTALL_MODE_LABELS.mixed} (${ejectedSkills.length} eject, ${pluginSkills.length} plugin)` : INSTALL_MODE_DESCRIPTIONS[installMode]}`
|
|
672
|
-
);
|
|
582
|
+
this.log(`Selected ${plural(plan.ejectedSkills.length + plan.pluginSkills.length, "skill")}`);
|
|
583
|
+
this.log(`Install mode: ${installModeDescription(plan)}`);
|
|
673
584
|
}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
* {@link skillsCopiedLine} chooses.
|
|
677
|
-
*/
|
|
678
|
-
async copyEjectSkillsStep(localSkills, projectDir, sourceResult, installMode) {
|
|
585
|
+
async copyEjectedSkills({ ejectedSkills, installMode }, projectDir, sourceResult) {
|
|
586
|
+
if (ejectedSkills.length === 0) return null;
|
|
679
587
|
this.log("Copying skills to local directory...");
|
|
680
|
-
const copyResult = await copyLocalSkills(
|
|
588
|
+
const copyResult = await copyLocalSkills(ejectedSkills, projectDir, sourceResult);
|
|
681
589
|
this.log(skillsCopiedLine(copyResult, installMode, projectDir));
|
|
682
590
|
return copyResult;
|
|
683
591
|
}
|
|
684
|
-
async writeConfigAndCompile(result, sourceResult, flags) {
|
|
592
|
+
async writeConfigAndCompile(result, sourceResult, flags, projectDir) {
|
|
593
|
+
const configResult = await this.writeConfigReported(result, sourceResult, flags, projectDir);
|
|
594
|
+
const agentScopeMap = buildAgentScopeMap(configResult.config);
|
|
595
|
+
const compileResult = await this.compileInstalledAgents(
|
|
596
|
+
configResult.propagation,
|
|
597
|
+
agentScopeMap,
|
|
598
|
+
projectDir
|
|
599
|
+
);
|
|
600
|
+
this.reportCompilation(compileResult);
|
|
601
|
+
await this.reportWhatThisHostCannotCarry(projectDir);
|
|
602
|
+
this.reportFanOut(configResult.propagation);
|
|
603
|
+
return { configResult, compileResult, agentScopeMap };
|
|
604
|
+
}
|
|
605
|
+
async writeConfigReported(result, sourceResult, flags, projectDir) {
|
|
685
606
|
this.log("Generating configuration...");
|
|
686
607
|
const configResult = await writeProjectConfig({
|
|
687
608
|
selection: result,
|
|
688
609
|
sourceResult,
|
|
689
|
-
projectDir
|
|
610
|
+
projectDir,
|
|
690
611
|
...flags.marketplace !== void 0 && { sourceFlag: flags.marketplace }
|
|
691
612
|
});
|
|
692
613
|
if (configResult.wasMerged) {
|
|
@@ -695,51 +616,28 @@ var Init = class _Init extends BaseCommand {
|
|
|
695
616
|
this.log(`Configuration saved (${plural(configResult.config.agents.length, "agent")})
|
|
696
617
|
`);
|
|
697
618
|
this.reportUnassignedSkills(configResult.config, result.skills);
|
|
619
|
+
return configResult;
|
|
620
|
+
}
|
|
621
|
+
async compileInstalledAgents(written, agentScopeMap, projectDir) {
|
|
698
622
|
this.log(STATUS_MESSAGES.COMPILING_AGENTS);
|
|
699
|
-
const cwd = process.cwd();
|
|
700
623
|
const agentDefs = await loadAgentDefs();
|
|
701
|
-
const { allSkills } = await discoverInstalledSkills(
|
|
702
|
-
const
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
projectDir: cwd,
|
|
624
|
+
const { allSkills } = await discoverInstalledSkills(projectDir);
|
|
625
|
+
const compile = compilesGlobalScope(projectDir, written) ? compileAgentsAllScopes : compileProjectScope;
|
|
626
|
+
return compile({
|
|
627
|
+
projectDir,
|
|
706
628
|
sourcePath: agentDefs.sourcePath,
|
|
707
629
|
skills: allSkills,
|
|
708
630
|
agentScopeMap
|
|
709
631
|
});
|
|
710
|
-
this.reportCompilation(compileResult);
|
|
711
|
-
await this.reportWhatThisHostCannotCarry(cwd);
|
|
712
|
-
this.reportFanOut(configResult.propagation);
|
|
713
|
-
return { configResult, compileResult, agentScopeMap };
|
|
714
632
|
}
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
*
|
|
718
|
-
* `init --from` is the door a configuration somebody ELSE wrote arrives through, so it is
|
|
719
|
-
* precisely the run that must not be silent about the parts of it that did not survive the
|
|
720
|
-
* translation. `compile` prints the same lines in the same order — see
|
|
721
|
-
* {@link hostCompileNotices}, which is the one place either of them gets them from.
|
|
722
|
-
*
|
|
723
|
-
* A Claude install expresses every setting and carries every sub-agent, so it gets one line at
|
|
724
|
-
* most: the trust dialog, while its project sub-agents' completion gate cannot run in this
|
|
725
|
-
* folder.
|
|
726
|
-
*/
|
|
727
|
-
async reportWhatThisHostCannotCarry(cwd) {
|
|
728
|
-
for (const notice of await hostCompileNotices(providerInUse(cwd), cwd)) {
|
|
633
|
+
async reportWhatThisHostCannotCarry(projectDir) {
|
|
634
|
+
for (const notice of await hostCompileNotices(providerInUse(projectDir), projectDir)) {
|
|
729
635
|
this.log(notice);
|
|
730
636
|
}
|
|
731
637
|
}
|
|
732
638
|
/**
|
|
733
|
-
*
|
|
734
|
-
*
|
|
735
|
-
* It read `compiled` and nothing else, so a pass that lost a sub-agent printed a number that
|
|
736
|
-
* looked perfectly right — `compiled` counts successes, so it is correct either way — and the
|
|
737
|
-
* failures reached no surface at all: no count, no reason, no exit code. A user's FIRST
|
|
738
|
-
* install could silently land a roster missing a sub-agent.
|
|
739
|
-
*
|
|
740
|
-
* The compile is the last thing `init` does, so a failure here cannot be answered by aborting:
|
|
741
|
-
* the skills are on disk and `config.ts` and `config-types.ts` describe them. What is owed is
|
|
742
|
-
* the account, which {@link BaseCommand.exitIfWorkIncomplete} prints and answers for.
|
|
639
|
+
* Failures are recorded rather than aborted on: the skills and config are already written, and
|
|
640
|
+
* {@link BaseCommand.exitIfWorkIncomplete} answers for them.
|
|
743
641
|
*/
|
|
744
642
|
reportCompilation(compileResult) {
|
|
745
643
|
const { compiled, failed, warnings } = compileResult;
|
|
@@ -756,104 +654,41 @@ var Init = class _Init extends BaseCommand {
|
|
|
756
654
|
}
|
|
757
655
|
this.recordIncompleteWork(agentsNotCompiled(failed), INCOMPLETE_WORK_RECOVERY.RECOMPILE);
|
|
758
656
|
}
|
|
759
|
-
reportSuccess(configResult, compileResult, agentScopeMap
|
|
657
|
+
reportSuccess({ configResult, compileResult, agentScopeMap }, copyResult, projectDir) {
|
|
760
658
|
if (!this.hasIncompleteWork) this.log(`${initSucceeded(this.brandingName)}
|
|
761
659
|
`);
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
this.reportSkillsCopied(copyResult);
|
|
660
|
+
if (copyResult !== null && copyResult.totalCopied > 0) {
|
|
661
|
+
this.logDirectoryBlocks("Skills copied to:", skillsCopiedBlocks(projectDir, copyResult));
|
|
765
662
|
}
|
|
766
|
-
this.
|
|
767
|
-
|
|
663
|
+
this.logDirectoryBlocks(
|
|
664
|
+
"Agents compiled to:",
|
|
665
|
+
agentsCompiledBlocks(projectDir, compileResult.compiled, agentScopeMap)
|
|
666
|
+
);
|
|
667
|
+
this.reportConfiguration(configResult, agentScopeMap, projectDir);
|
|
768
668
|
}
|
|
769
|
-
|
|
770
|
-
* Names the config that actually holds this install's assignments, and where a
|
|
771
|
-
* recompile of them has to be run from.
|
|
772
|
-
*
|
|
773
|
-
* Split by the same `agentScopeMap` the two reporters above split on, because the
|
|
774
|
-
* same scope decides both. A project config's `stack` is filtered down to
|
|
775
|
-
* project-scoped agents on the way out, so a wholly GLOBAL install leaves it
|
|
776
|
-
* carrying no assignment at all — naming it sends the user to a file with nothing
|
|
777
|
-
* in it — and `compile` in this cwd runs the PROJECT pass, which recompiles no
|
|
778
|
-
* global agent. At the home root both scopes resolve to one file and one pass, so
|
|
779
|
-
* there is nothing to split and the project wording stands.
|
|
780
|
-
*/
|
|
781
|
-
reportConfiguration(projectConfigPath, agentScopeMap) {
|
|
782
|
-
const cwd = process.cwd();
|
|
669
|
+
reportConfiguration({ configPath, propagation }, agentScopeMap, projectDir) {
|
|
783
670
|
const paths = {
|
|
784
|
-
global: resolveInstallPaths(
|
|
785
|
-
project:
|
|
671
|
+
global: resolveInstallPaths(projectDir, "global").configPath,
|
|
672
|
+
project: configPath
|
|
786
673
|
};
|
|
787
|
-
const split = splitAgentScopes(
|
|
674
|
+
const split = splitAgentScopes(projectDir, agentScopeMap);
|
|
788
675
|
this.log("Configuration:");
|
|
789
|
-
for (const
|
|
790
|
-
this.log(` ${
|
|
676
|
+
for (const written of configsWritten(projectDir, paths, propagation.globalWritten)) {
|
|
677
|
+
this.log(` ${written}`);
|
|
791
678
|
}
|
|
792
679
|
this.log("");
|
|
793
680
|
this.log("To customize agent-skill assignments:");
|
|
794
|
-
for (const [index, step] of customizationSteps(split, paths.global,
|
|
681
|
+
for (const [index, step] of customizationSteps(split, paths.global, projectDir).entries()) {
|
|
795
682
|
this.log(` ${index + 1}. ${step}`);
|
|
796
683
|
}
|
|
797
684
|
this.log("");
|
|
798
685
|
}
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
* This block is a filesystem listing, so the entries are the on-disk directory
|
|
806
|
-
* names — skill ids, not display names. `copySkillsToLocalFlattened` names each
|
|
807
|
-
* destination directory after `skill.id`, so a user can copy any line and `cd`
|
|
808
|
-
* into it.
|
|
809
|
-
*/
|
|
810
|
-
reportSkillsCopied(copyResult) {
|
|
811
|
-
const cwd = process.cwd();
|
|
812
|
-
const groups = isHomeDirectory(cwd) ? [
|
|
813
|
-
{
|
|
814
|
-
dir: resolveInstallPaths(cwd, "project").skillsDir,
|
|
815
|
-
copied: [...copyResult.globalCopied, ...copyResult.projectCopied]
|
|
816
|
-
}
|
|
817
|
-
] : [
|
|
818
|
-
{ dir: resolveInstallPaths(cwd, "global").skillsDir, copied: copyResult.globalCopied },
|
|
819
|
-
{ dir: resolveInstallPaths(cwd, "project").skillsDir, copied: copyResult.projectCopied }
|
|
820
|
-
].filter((group) => group.copied.length > 0);
|
|
821
|
-
for (const group of groups) {
|
|
822
|
-
this.log("Skills copied to:");
|
|
823
|
-
this.log(` ${group.dir}`);
|
|
824
|
-
for (const copied of group.copied) {
|
|
825
|
-
this.log(` ${copied.skillId}/`);
|
|
826
|
-
}
|
|
827
|
-
this.log("");
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
/**
|
|
831
|
-
* Reports where the agents actually landed, mirroring the scope split
|
|
832
|
-
* `compileAgentsAllScopes` performs: one pass at the home root, otherwise a
|
|
833
|
-
* global pass under HOME and a project pass under the project directory.
|
|
834
|
-
*
|
|
835
|
-
* **The EXTENSION is the host's, per scope, and was Claude's literal `.md` until C5.** This
|
|
836
|
-
* block describes the filesystem, so every line under a path header has to be a name a user can
|
|
837
|
-
* copy out and open — and a Codex install printed `web-developer.md` above a directory holding
|
|
838
|
-
* `web-developer.toml`. The two scopes are read separately because they can be on two hosts.
|
|
839
|
-
*/
|
|
840
|
-
reportAgentsCompiled(compiled, agentScopeMap) {
|
|
841
|
-
const cwd = process.cwd();
|
|
842
|
-
const groups = isHomeDirectory(cwd) ? [{ ...compiledInto(cwd, "project"), agents: compiled }] : [
|
|
843
|
-
{
|
|
844
|
-
...compiledInto(cwd, "global"),
|
|
845
|
-
agents: compiled.filter((name) => agentScopeMap.get(name) === "global")
|
|
846
|
-
},
|
|
847
|
-
{
|
|
848
|
-
...compiledInto(cwd, "project"),
|
|
849
|
-
agents: compiled.filter((name) => agentScopeMap.get(name) !== "global")
|
|
850
|
-
}
|
|
851
|
-
].filter((group) => group.agents.length > 0);
|
|
852
|
-
for (const group of groups) {
|
|
853
|
-
this.log("Agents compiled to:");
|
|
854
|
-
this.log(` ${group.dir}`);
|
|
855
|
-
for (const agentName of group.agents) {
|
|
856
|
-
this.log(` ${agentName}${group.extension}`);
|
|
686
|
+
logDirectoryBlocks(heading, blocks) {
|
|
687
|
+
for (const { dir, entries } of blocks) {
|
|
688
|
+
this.log(heading);
|
|
689
|
+
this.log(` ${dir}`);
|
|
690
|
+
for (const entry of entries) {
|
|
691
|
+
this.log(` ${entry}`);
|
|
857
692
|
}
|
|
858
693
|
this.log("");
|
|
859
694
|
}
|
|
@@ -865,6 +700,24 @@ function opensTheEditor(flags) {
|
|
|
865
700
|
function selectsNothing(result) {
|
|
866
701
|
return result.skills.length === 0 && result.selectedAgents.length === 0;
|
|
867
702
|
}
|
|
703
|
+
async function installedGlobalToHold(projectDir) {
|
|
704
|
+
if (isHomeDirectory(projectDir)) return null;
|
|
705
|
+
return await readInstalledGlobal(projectDir);
|
|
706
|
+
}
|
|
707
|
+
function planInstall(result, installedAlready) {
|
|
708
|
+
const toInstall = result.skills.filter(
|
|
709
|
+
(skill) => !skill.excluded && !installedAlready.has(skill.id)
|
|
710
|
+
);
|
|
711
|
+
const [ejectedSkills, pluginSkills] = partition(
|
|
712
|
+
toInstall,
|
|
713
|
+
(skill) => skill.origin === EJECT_SOURCE
|
|
714
|
+
);
|
|
715
|
+
return { installMode: deriveInstallMode(toInstall), ejectedSkills, pluginSkills };
|
|
716
|
+
}
|
|
717
|
+
function installModeDescription({ installMode, ejectedSkills, pluginSkills }) {
|
|
718
|
+
if (installMode !== "mixed") return INSTALL_MODE_DESCRIPTIONS[installMode];
|
|
719
|
+
return `${INSTALL_MODE_LABELS.mixed} (${ejectedSkills.length} eject, ${pluginSkills.length} plugin)`;
|
|
720
|
+
}
|
|
868
721
|
function compilesGlobalScope(cwd, written) {
|
|
869
722
|
return isHomeDirectory(cwd) || movedGlobalAgentInputs(written);
|
|
870
723
|
}
|
|
@@ -881,10 +734,47 @@ function skillsCopiedLine(copyResult, installMode, projectDir) {
|
|
|
881
734
|
const landedAt = globalCount > 0 ? "global" : "project";
|
|
882
735
|
return `Copied ${copied} to ${resolveInstallPaths(projectDir, landedAt).skillsDir}/${lineEnd}`;
|
|
883
736
|
}
|
|
884
|
-
function
|
|
737
|
+
function hasEntries(block) {
|
|
738
|
+
return block.entries.length > 0;
|
|
739
|
+
}
|
|
740
|
+
function oneBlockPerDir(blocks) {
|
|
741
|
+
const dirs = [...new Set(blocks.map((block) => block.dir))];
|
|
742
|
+
return dirs.map((dir) => ({
|
|
743
|
+
dir,
|
|
744
|
+
entries: blocks.filter((block) => block.dir === dir).flatMap((block) => block.entries)
|
|
745
|
+
}));
|
|
746
|
+
}
|
|
747
|
+
function skillsCopiedBlocks(projectDir, copyResult) {
|
|
748
|
+
return oneBlockPerDir(
|
|
749
|
+
[
|
|
750
|
+
copiedSkillsBlock(projectDir, "global", copyResult.globalCopied),
|
|
751
|
+
copiedSkillsBlock(projectDir, "project", copyResult.projectCopied)
|
|
752
|
+
].filter(hasEntries)
|
|
753
|
+
);
|
|
754
|
+
}
|
|
755
|
+
function copiedSkillsBlock(projectDir, scope, copied) {
|
|
885
756
|
return {
|
|
886
|
-
dir: resolveInstallPaths(
|
|
887
|
-
|
|
757
|
+
dir: resolveInstallPaths(projectDir, scope).skillsDir,
|
|
758
|
+
entries: copied.map(({ skillId }) => `${skillId}/`)
|
|
759
|
+
};
|
|
760
|
+
}
|
|
761
|
+
function agentsCompiledBlocks(projectDir, compiled, agentScopeMap) {
|
|
762
|
+
const [globalAgents, projectAgents] = partition(
|
|
763
|
+
compiled,
|
|
764
|
+
(name) => agentScopeMap.get(name) === "global"
|
|
765
|
+
);
|
|
766
|
+
return oneBlockPerDir(
|
|
767
|
+
[
|
|
768
|
+
compiledAgentsBlock(projectDir, "global", globalAgents),
|
|
769
|
+
compiledAgentsBlock(projectDir, "project", projectAgents)
|
|
770
|
+
].filter(hasEntries)
|
|
771
|
+
);
|
|
772
|
+
}
|
|
773
|
+
function compiledAgentsBlock(projectDir, scope, agents) {
|
|
774
|
+
const { extension } = agentCodec(providerInUse(installBaseDir(projectDir, scope)));
|
|
775
|
+
return {
|
|
776
|
+
dir: resolveInstallPaths(projectDir, scope).agentsDir,
|
|
777
|
+
entries: agents.map((name) => `${name}${extension}`)
|
|
888
778
|
};
|
|
889
779
|
}
|
|
890
780
|
function splitAgentScopes(cwd, agentScopeMap) {
|
|
@@ -896,10 +786,9 @@ function splitAgentScopes(cwd, agentScopeMap) {
|
|
|
896
786
|
isGlobalOnly: globalAgentCount > 0 && globalAgentCount === scopes.length
|
|
897
787
|
};
|
|
898
788
|
}
|
|
899
|
-
function
|
|
900
|
-
if (
|
|
901
|
-
|
|
902
|
-
return [paths.project];
|
|
789
|
+
function configsWritten(projectDir, paths, globalWritten) {
|
|
790
|
+
if (isHomeDirectory(projectDir)) return [paths.project];
|
|
791
|
+
return globalWritten ? [paths.global, paths.project] : [paths.project];
|
|
903
792
|
}
|
|
904
793
|
function customizationSteps(split, globalConfigPath, projectDir) {
|
|
905
794
|
if (split.isGlobalOnly) {
|
|
@@ -912,32 +801,18 @@ function customizationSteps(split, globalConfigPath, projectDir) {
|
|
|
912
801
|
];
|
|
913
802
|
}
|
|
914
803
|
async function getDashboardData(projectDir) {
|
|
915
|
-
const [
|
|
916
|
-
|
|
917
|
-
loadProjectConfig(projectDir),
|
|
804
|
+
const [installations, branding] = await Promise.all([
|
|
805
|
+
getInstallationsByProvider(projectDir),
|
|
918
806
|
resolveBranding(projectDir)
|
|
919
807
|
]);
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
const agentCount = info?.agentCount ?? 0;
|
|
923
|
-
const mode = info?.mode ?? (activeSkills ? deriveInstallMode(activeSkills) : "eject");
|
|
924
|
-
const source = loaded?.config.marketplace;
|
|
925
|
-
return {
|
|
926
|
-
name: branding.name,
|
|
927
|
-
skillCount,
|
|
928
|
-
agentCount,
|
|
929
|
-
mode,
|
|
930
|
-
...source !== void 0 && { source }
|
|
931
|
-
};
|
|
808
|
+
if (installations.length === 0) throw new Error(ERROR_MESSAGES.NO_INSTALLATION);
|
|
809
|
+
return { name: branding.name, installations };
|
|
932
810
|
}
|
|
933
811
|
|
|
934
812
|
export {
|
|
935
813
|
Dashboard,
|
|
936
|
-
dashboardCountLines,
|
|
937
814
|
formatDashboardText,
|
|
938
|
-
showDashboard,
|
|
939
815
|
runDashboardFlow,
|
|
940
|
-
Init
|
|
941
|
-
getDashboardData
|
|
816
|
+
Init
|
|
942
817
|
};
|
|
943
|
-
//# sourceMappingURL=chunk-
|
|
818
|
+
//# sourceMappingURL=chunk-YXKTY5WM.js.map
|