neon 4.15.0 → 4.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -5
- package/dist/analytics.js +11 -9
- package/dist/api.js +79 -0
- package/dist/commands/bootstrap.js +38 -34
- package/dist/commands/credentials.js +146 -0
- package/dist/commands/index.js +4 -0
- package/dist/commands/init.js +233 -23
- package/dist/commands/link.js +27 -16
- package/dist/commands/triggers.js +182 -0
- package/dist/context.js +1 -0
- package/dist/init/child.js +2 -1
- package/dist/init/choices.js +46 -0
- package/dist/init/chrome.js +25 -2
- package/dist/init/plan.js +42 -7
- package/dist/init/template_title.js +15 -0
- package/dist/init/tooling.js +5 -1
- package/dist/init/wizard.js +58 -6
- package/package.json +1 -1
package/dist/init/chrome.js
CHANGED
|
@@ -13,7 +13,7 @@ const INIT_BANNER_LINES = [
|
|
|
13
13
|
const formatInitBanner = () => INIT_BANNER_LINES.join("\n");
|
|
14
14
|
const shouldPrintInitBanner = (yes) => !yes && !isCi() && Boolean(process.stdout.isTTY);
|
|
15
15
|
const printInitBanner = () => {
|
|
16
|
-
process.stdout.write(`\n${chalk.hex(NEON_GREEN)(formatInitBanner())}\n\n${chalk.dim("
|
|
16
|
+
process.stdout.write(`\n${chalk.hex(NEON_GREEN)(formatInitBanner())}\n\n${chalk.dim("Set up this directory for Neon.")}\n\n`);
|
|
17
17
|
};
|
|
18
18
|
const formatInitDone = (input) => {
|
|
19
19
|
const labelWidth = Math.max(0, ...input.rows.map((row) => row.label.length));
|
|
@@ -40,5 +40,28 @@ const agentSetupDoneLabel = (input) => {
|
|
|
40
40
|
if (!input.ran && input.setup !== "skip") return "not run";
|
|
41
41
|
return agentSetupLabel(input.setup);
|
|
42
42
|
};
|
|
43
|
+
const configSummaryLabel = (summary) => {
|
|
44
|
+
switch (summary) {
|
|
45
|
+
case "created": return "neon.ts created";
|
|
46
|
+
case "skipped": return "skipped";
|
|
47
|
+
case "existing": return "existing Neon config";
|
|
48
|
+
case "template": return "provided by template";
|
|
49
|
+
default: return summary;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const INIT_STEP_LABELS = {
|
|
53
|
+
bootstrap: "Creating the app from the selected template…",
|
|
54
|
+
plugins: "Installing the Neon plugin…",
|
|
55
|
+
skills: "Installing Neon agent skills…",
|
|
56
|
+
mcp: "Setting up the Neon MCP server…",
|
|
57
|
+
link: "Linking a Neon project…",
|
|
58
|
+
config: "Setting up neon.ts…",
|
|
59
|
+
env: "Refreshing Neon env vars…"
|
|
60
|
+
};
|
|
61
|
+
const initStepLabel = (step) => {
|
|
62
|
+
const command = step[0];
|
|
63
|
+
if (command === void 0) return;
|
|
64
|
+
return INIT_STEP_LABELS[command];
|
|
65
|
+
};
|
|
43
66
|
//#endregion
|
|
44
|
-
export { INIT_BANNER_LINES, NEON_GREEN, agentSetupDoneLabel, agentSetupLabel, formatInitBanner, formatInitDone, printInitBanner, printInitDone, shouldPrintInitBanner };
|
|
67
|
+
export { INIT_BANNER_LINES, INIT_STEP_LABELS, NEON_GREEN, agentSetupDoneLabel, agentSetupLabel, configSummaryLabel, formatInitBanner, formatInitDone, initStepLabel, printInitBanner, printInitDone, shouldPrintInitBanner };
|
package/dist/init/plan.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getCliName } from "../utils/cli_name.js";
|
|
2
|
+
import { NO_SERVICES } from "../neon_services.js";
|
|
2
3
|
import { tryResolveAddMcpAgentId, uniqueAgentIds } from "../mcp/agents.js";
|
|
3
4
|
import { mcpInstallableAgents } from "../mcp/targets.js";
|
|
4
5
|
import { supportsSkills } from "./agents.js";
|
|
@@ -93,6 +94,9 @@ const BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
93
94
|
"--no-env-pull",
|
|
94
95
|
"--no-agent-setup",
|
|
95
96
|
"--no-link",
|
|
97
|
+
"--no-config",
|
|
98
|
+
"--skip-template",
|
|
99
|
+
"--config",
|
|
96
100
|
"--list",
|
|
97
101
|
"--list-templates",
|
|
98
102
|
"--force-auth",
|
|
@@ -218,15 +222,46 @@ const resolveNamedAgents = (raw) => {
|
|
|
218
222
|
}
|
|
219
223
|
return uniqueAgentIds(resolved);
|
|
220
224
|
};
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
+
const planLinkStep = (input) => [
|
|
226
|
+
"link",
|
|
227
|
+
...input.yes ? ["--yes"] : [],
|
|
228
|
+
"--no-config",
|
|
229
|
+
...input.extra ?? []
|
|
230
|
+
];
|
|
231
|
+
const planConfigInitStep = (input) => {
|
|
232
|
+
if (input.services !== void 0) return [
|
|
233
|
+
"config",
|
|
234
|
+
"init",
|
|
235
|
+
"--services",
|
|
236
|
+
input.services.length === 0 ? NO_SERVICES : input.services.join(",")
|
|
237
|
+
];
|
|
238
|
+
if (input.yes) return [
|
|
225
239
|
"config",
|
|
226
240
|
"init",
|
|
227
241
|
"--services",
|
|
228
|
-
|
|
229
|
-
]
|
|
242
|
+
NO_SERVICES
|
|
243
|
+
];
|
|
244
|
+
return ["config", "init"];
|
|
245
|
+
};
|
|
246
|
+
const linkInputArgv = (input) => {
|
|
247
|
+
const args = [];
|
|
248
|
+
if (input.orgId) args.push("--org-id", input.orgId);
|
|
249
|
+
if (input.projectId) args.push("--project-id", input.projectId);
|
|
250
|
+
if (input.projectName) args.push("--project-name", input.projectName);
|
|
251
|
+
if (input.regionId) args.push("--region-id", input.regionId);
|
|
252
|
+
if (input.branch) args.push("--branch", input.branch);
|
|
253
|
+
return args;
|
|
254
|
+
};
|
|
255
|
+
const planExistingInit = (input) => {
|
|
256
|
+
const steps = [...planAgentSteps(input)];
|
|
257
|
+
if (!input.linked) steps.push(planLinkStep({
|
|
258
|
+
yes: input.yes,
|
|
259
|
+
extra: input.linkExtra
|
|
260
|
+
}));
|
|
261
|
+
if (input.config.kind === "write") steps.push(planConfigInitStep({
|
|
262
|
+
yes: input.yes,
|
|
263
|
+
services: input.config.services
|
|
264
|
+
}));
|
|
230
265
|
return steps;
|
|
231
266
|
};
|
|
232
267
|
const resolveInitAgentSetup = async (input) => {
|
|
@@ -243,4 +278,4 @@ const childArgv = (step, forward) => {
|
|
|
243
278
|
return args;
|
|
244
279
|
};
|
|
245
280
|
//#endregion
|
|
246
|
-
export { INIT_NEEDS_YES_OR_TERMINAL, NAMED_AGENTS_MIXED, NAMED_AGENTS_UNSUPPORTED, assertNamedAgentTooling, bootstrapInitStep, childArgv, chooseYesAgentTooling, collectYesAgents, directoryIsEmpty, initPluginAgents, initSkillsMcpAgents, initYesSupportedAgents, namedAgentsMixedMessage, namedAgentsNeedSplit, noDetectedAgentsMessage, planAgentSteps, planExistingInit, planToolingSteps, planYesAgentSteps, postScaffoldActions, projectContextFile, resolveInitAgentSetup, resolveNamedAgents, resolveYesAgentList, rewriteUnknownAgentArg };
|
|
281
|
+
export { INIT_NEEDS_YES_OR_TERMINAL, NAMED_AGENTS_MIXED, NAMED_AGENTS_UNSUPPORTED, assertNamedAgentTooling, bootstrapInitStep, childArgv, chooseYesAgentTooling, collectYesAgents, directoryIsEmpty, initPluginAgents, initSkillsMcpAgents, initYesSupportedAgents, linkInputArgv, namedAgentsMixedMessage, namedAgentsNeedSplit, noDetectedAgentsMessage, planAgentSteps, planConfigInitStep, planExistingInit, planLinkStep, planToolingSteps, planYesAgentSteps, postScaffoldActions, projectContextFile, resolveInitAgentSetup, resolveNamedAgents, resolveYesAgentList, rewriteUnknownAgentArg };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
//#region src/init/template_title.ts
|
|
3
|
+
const SKIP_TEMPLATE_VALUE = "skip";
|
|
4
|
+
/**
|
|
5
|
+
* The picker label for a template: the title first, then the Neon services it
|
|
6
|
+
* uses as a dim, italic suffix. The suffix is styled with chalk.dim (and italic)
|
|
7
|
+
* only — never a foreground color — so it survives the cyan/underline `prompts`
|
|
8
|
+
* paints over the focused row.
|
|
9
|
+
*/
|
|
10
|
+
const formatTemplateTitle = (template) => {
|
|
11
|
+
if (!template.services || template.services.length === 0) return template.title;
|
|
12
|
+
return `${template.title} ${chalk.dim.italic(template.services.join(" · "))}`;
|
|
13
|
+
};
|
|
14
|
+
//#endregion
|
|
15
|
+
export { SKIP_TEMPLATE_VALUE, formatTemplateTitle };
|
package/dist/init/tooling.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { log } from "../log.js";
|
|
2
2
|
import { getCliName } from "../utils/cli_name.js";
|
|
3
3
|
import { AUTH_CHILD } from "./child.js";
|
|
4
|
+
import { initStepLabel } from "./chrome.js";
|
|
4
5
|
import { assertNamedAgentTooling, childArgv, chooseYesAgentTooling, collectYesAgents, initYesSupportedAgents, noDetectedAgentsMessage, planAgentSteps, planToolingSteps, planYesAgentSteps, resolveInitAgentSetup } from "./plan.js";
|
|
5
6
|
import { canPickAgentsInteractively } from "../utils/agent_picker.js";
|
|
6
7
|
import { detectAgent } from "./detect_host.js";
|
|
@@ -10,7 +11,10 @@ import { detectProjectAgents } from "add-mcp";
|
|
|
10
11
|
const defaultProjectAgents = (cwd) => detectProjectAgents(cwd);
|
|
11
12
|
const runInitSteps = async (steps, options) => {
|
|
12
13
|
for (const step of steps) {
|
|
13
|
-
|
|
14
|
+
const label = options.narrate === "human" ? initStepLabel(step) : void 0;
|
|
15
|
+
if (label !== void 0) log.info(label);
|
|
16
|
+
else log.info("Running `%s %s`", getCliName(), step.join(" "));
|
|
17
|
+
log.debug("Running `%s %s`", getCliName(), step.join(" "));
|
|
14
18
|
const argv = childArgv(step, options.forward);
|
|
15
19
|
const command = step[0];
|
|
16
20
|
if (!await options.run(argv, options.cwd, command !== void 0 && AUTH_CHILD.has(command) ? options.authEnv : void 0)) throw new Error(`\`${getCliName()} ${step.join(" ")}\` failed.`);
|
package/dist/init/wizard.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { INIT_NEEDS_YES_OR_TERMINAL } from "./plan.js";
|
|
2
|
+
import { SKIP_TEMPLATE_VALUE, formatTemplateTitle } from "./template_title.js";
|
|
2
3
|
import { canPickAgentsInteractively } from "../utils/agent_picker.js";
|
|
3
4
|
import { NEON_PLUGIN_NAME } from "../plugins/run.js";
|
|
5
|
+
import chalk from "chalk";
|
|
4
6
|
import prompts from "prompts";
|
|
5
7
|
//#region src/init/wizard.ts
|
|
6
8
|
const restoreCursorOnAbort = (state) => {
|
|
@@ -10,19 +12,22 @@ const restoreCursorOnAbort = (state) => {
|
|
|
10
12
|
process.exit(1);
|
|
11
13
|
}
|
|
12
14
|
};
|
|
13
|
-
const
|
|
15
|
+
const requireInteractive = () => {
|
|
14
16
|
if (!canPickAgentsInteractively()) throw new Error(INIT_NEEDS_YES_OR_TERMINAL);
|
|
17
|
+
};
|
|
18
|
+
const pickAgentSetupInteractively = async () => {
|
|
19
|
+
requireInteractive();
|
|
15
20
|
const { setup } = await prompts({
|
|
16
21
|
onState: restoreCursorOnAbort,
|
|
17
22
|
type: "select",
|
|
18
23
|
name: "setup",
|
|
19
|
-
message: "How
|
|
24
|
+
message: "How would you like to set up your coding agents?",
|
|
20
25
|
initial: 0,
|
|
21
26
|
choices: [
|
|
22
27
|
{
|
|
23
|
-
title: "
|
|
28
|
+
title: "Neon plugin (recommended)",
|
|
24
29
|
value: "plugin",
|
|
25
|
-
description: `Install ${NEON_PLUGIN_NAME} (skills and MCP
|
|
30
|
+
description: `Install ${NEON_PLUGIN_NAME} (skills and MCP together)`
|
|
26
31
|
},
|
|
27
32
|
{
|
|
28
33
|
title: "Skills and MCP separately",
|
|
@@ -32,12 +37,59 @@ const pickAgentSetupInteractively = async () => {
|
|
|
32
37
|
{
|
|
33
38
|
title: "Skip agent setup",
|
|
34
39
|
value: "skip",
|
|
35
|
-
description: "Continue
|
|
40
|
+
description: "Continue to project setup"
|
|
36
41
|
}
|
|
37
42
|
]
|
|
38
43
|
});
|
|
39
44
|
if (setup !== "plugin" && setup !== "skills-mcp" && setup !== "skip") throw new Error("Aborted.");
|
|
40
45
|
return setup;
|
|
41
46
|
};
|
|
47
|
+
/** First catalog template; skip is index 0 so it stays on the first screen. */
|
|
48
|
+
const INIT_TEMPLATE_PICKER_INITIAL = 1;
|
|
49
|
+
const initTemplatePickerChoices = (templates) => {
|
|
50
|
+
if (templates.length === 0) throw new Error("No templates available to scaffold from.");
|
|
51
|
+
return [{
|
|
52
|
+
title: "Skip the template",
|
|
53
|
+
value: SKIP_TEMPLATE_VALUE,
|
|
54
|
+
description: "Set up agents and link a Neon project without copying template files."
|
|
55
|
+
}, ...templates.map((template) => ({
|
|
56
|
+
title: formatTemplateTitle(template),
|
|
57
|
+
value: template.id,
|
|
58
|
+
description: template.description ?? ""
|
|
59
|
+
}))];
|
|
60
|
+
};
|
|
61
|
+
const pickInitTemplateInteractively = async (templates) => {
|
|
62
|
+
requireInteractive();
|
|
63
|
+
const choices = initTemplatePickerChoices(templates);
|
|
64
|
+
const { id } = await prompts({
|
|
65
|
+
onState: restoreCursorOnAbort,
|
|
66
|
+
type: "select",
|
|
67
|
+
name: "id",
|
|
68
|
+
message: "How would you like to set up this directory?",
|
|
69
|
+
initial: 1,
|
|
70
|
+
choices
|
|
71
|
+
});
|
|
72
|
+
if (id === "skip") return { kind: "skip" };
|
|
73
|
+
if (typeof id !== "string" || id.length === 0) throw new Error("Aborted.");
|
|
74
|
+
const selected = templates.find((template) => template.id === id);
|
|
75
|
+
if (selected === void 0) throw new Error("Aborted.");
|
|
76
|
+
return {
|
|
77
|
+
kind: "template",
|
|
78
|
+
template: selected
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
const pickInitConfigInteractively = async () => {
|
|
82
|
+
requireInteractive();
|
|
83
|
+
process.stdout.write(`${chalk.dim("Choose services, then edit neon.ts and apply changes with neon config apply.")}\n`);
|
|
84
|
+
const { value } = await prompts({
|
|
85
|
+
onState: restoreCursorOnAbort,
|
|
86
|
+
type: "confirm",
|
|
87
|
+
name: "value",
|
|
88
|
+
message: "Create neon.ts to manage this project's Neon setup as code?",
|
|
89
|
+
initial: true
|
|
90
|
+
});
|
|
91
|
+
if (value === void 0) throw new Error("Aborted.");
|
|
92
|
+
return value === true;
|
|
93
|
+
};
|
|
42
94
|
//#endregion
|
|
43
|
-
export { pickAgentSetupInteractively };
|
|
95
|
+
export { INIT_TEMPLATE_PICKER_INITIAL, initTemplatePickerChoices, pickAgentSetupInteractively, pickInitConfigInteractively, pickInitTemplateInteractively };
|