neon 8.13.1 → 8.13.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/README.md +2 -0
- package/dist/_chunks/{plugins-DqD7BDO1.js → plugins-Dj0H6lDA.js} +1 -1
- package/dist/analytics.js +1 -1
- package/dist/commands/index.js +1 -1
- package/dist/commands/plugins.js +1 -1
- package/dist/init/copy.js +12 -1
- package/dist/init/funnel.js +62 -14
- package/dist/init/run.js +147 -92
- package/dist/init/tooling.js +3 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -891,6 +891,8 @@ Unauthenticated `-y` skips linking and prints the next step: sign up at https://
|
|
|
891
891
|
|
|
892
892
|
When init picks MCP auth (no `--mcp-auth`) and the CLI credential is an organization or project-scoped API key, which cannot mint the MCP server's key, init configures MCP with OAuth instead and continues. With `--mcp-auth api-key`, init skips MCP, finishes linking and `neon.ts`, then reports `Neon setup failed.` with the `neon mcp` commands to retry and exits 1.
|
|
893
893
|
|
|
894
|
+
When the Neon plugin, skills, or MCP setup fails for an agent, init runs the remaining agent steps, links (or writes `.neon` offline), and writes `neon.ts` as it would have, then reports `Neon setup failed.` with the error and the `neon plugins`, `neon skills`, or `neon mcp` command to retry, and exits 1.
|
|
895
|
+
|
|
894
896
|
Custom asks how to add Neon to coding agents (plugin, skills and MCP separately, or skip), then how to get a project (sign in and link, or a claimable project when you are not signed in), then which services `neon.ts` should declare. Skills and MCP use separate agent pickers, and either can be skipped. Postgres is listed first as always included. The package manager is inferred from the directory; Custom asks only when none is detected. `--skill` selects skills (not the plugin) and skips that picker. MCP flags (`--mcp-config-location`, `--mcp-auth`, `--mcp-project-scoped`) select skills and MCP. `--mcp-config-location` is where the config is written: `global` maps to `neon mcp`, and `project` maps to `neon mcp --project`. With `-y`, the location defaults to `global`; interactive Custom asks. If some selected agents cannot write that location, init warns and skips MCP for those agents while continuing with the supported agents. It fails when none of the selected agents support the location. `--mcp-project-scoped` limits MCP tools to the linked Neon project by passing its ID to `neon mcp --project-id`. Omitted is false, including in Custom; there is no prompt. `--no-agent-setup` skips agent setup.
|
|
895
897
|
|
|
896
898
|
Empty directories are set up in place. `neon init` does not scaffold starter files.
|
|
@@ -132,7 +132,7 @@ const pluginsInstallError = (outcome) => {
|
|
|
132
132
|
global: scope === "global"
|
|
133
133
|
});
|
|
134
134
|
if (first.message.includes("needs npx (Node.js)")) return new Error(first.message);
|
|
135
|
-
const detail = failed.map((row) => row.message).join("\n");
|
|
135
|
+
const detail = [...new Set(failed.map((row) => row.message))].join("\n");
|
|
136
136
|
if (failed.length === rows.length) return /* @__PURE__ */ new Error(`${detail}\nRetry with: ${retry}`);
|
|
137
137
|
return /* @__PURE__ */ new Error(`Failed to install the Neon plugin for: ${failed.flatMap((row) => row.agents).join(", ")}.\n${detail}\nRetry with: ${retry}`);
|
|
138
138
|
};
|
package/dist/analytics.js
CHANGED
|
@@ -356,4 +356,4 @@ const getAnalyticsEventProperties = (args) => ({
|
|
|
356
356
|
githubEnvVars: getGithubEnvVars(process.env)
|
|
357
357
|
});
|
|
358
358
|
//#endregion
|
|
359
|
-
export { analyticsIdentity, analyticsMiddleware, closeAnalytics, commandSuccessProperties, getAnalyticsEventProperties, getErrorAnalyticsEventProperties, initAnalyticsClientMiddleware, isAnalyticsActive, recordCommandSuccessExtras, recordScaffoldedTemplate, sendError, storedCredentialAttribution, takeCommandSuccessExtras, telemetryCredential, trackCommandSuccess, trackEvent, useAnalyticsClientForTests };
|
|
359
|
+
export { analyticsIdentity, analyticsMiddleware, closeAnalytics, commandSuccessProperties, getAnalyticsEventProperties, getErrorAnalyticsEventProperties, initAnalyticsClientMiddleware, isAnalyticsActive, recordCommandSuccessExtras, recordScaffoldedTemplate, redactCredentialTokenIds, sendError, storedCredentialAttribution, takeCommandSuccessExtras, telemetryCredential, trackCommandSuccess, trackEvent, useAnalyticsClientForTests };
|
package/dist/commands/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { c as config_exports } from "../_chunks/config-BH_qRHiG.js";
|
|
|
7
7
|
import { u as projects_exports } from "../_chunks/projects-BwI2Uo0z.js";
|
|
8
8
|
import { a as link_exports } from "../_chunks/link-BgtkOBws.js";
|
|
9
9
|
import { o as mcp_exports } from "../_chunks/mcp-Bo-7TKc7.js";
|
|
10
|
-
import { c as plugins_exports } from "../_chunks/plugins-
|
|
10
|
+
import { c as plugins_exports } from "../_chunks/plugins-Dj0H6lDA.js";
|
|
11
11
|
import { l as skills_exports } from "../_chunks/skills-BP6pIm7O.js";
|
|
12
12
|
import { t as bootstrap_exports } from "../_chunks/bootstrap-wPZWa1sT.js";
|
|
13
13
|
import { r as branches_exports } from "../_chunks/branches-BNa1xX1L.js";
|
package/dist/commands/plugins.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as aliases, n as builder, r as command, i as describe, a as handler, o as installPlugins, s as pluginsInstallError, l as reportPluginsInstall } from "../_chunks/plugins-
|
|
1
|
+
export { t as aliases, n as builder, r as command, i as describe, a as handler, o as installPlugins, s as pluginsInstallError, l as reportPluginsInstall } from "../_chunks/plugins-Dj0H6lDA.js";
|
package/dist/init/copy.js
CHANGED
|
@@ -158,6 +158,17 @@ const mcpKeyFailedNext = (reason, mcp) => [
|
|
|
158
158
|
"Or with OAuth:",
|
|
159
159
|
`${mcp} --oauth`
|
|
160
160
|
];
|
|
161
|
+
const AGENTS_NOT_INSTALLED = "not installed";
|
|
162
|
+
const TOOLING_FAILED = {
|
|
163
|
+
plugins: "The Neon plugin was not installed. Retry with:",
|
|
164
|
+
skills: "Neon skills were not installed. Retry with:",
|
|
165
|
+
mcp: "The Neon MCP server was not configured. Retry with:"
|
|
166
|
+
};
|
|
167
|
+
const toolingFailedNext = (failures) => failures.flatMap((failure, index) => [
|
|
168
|
+
...index > 0 ? [""] : [],
|
|
169
|
+
TOOLING_FAILED[failure.kind],
|
|
170
|
+
failure.command
|
|
171
|
+
]);
|
|
161
172
|
const mcpAfterLinkNext = (mcp) => ["Then configure the Neon MCP server for that project:", mcp];
|
|
162
173
|
const envPullFailedNext = () => ({
|
|
163
174
|
heading: HEADING_FAILED,
|
|
@@ -174,4 +185,4 @@ const headingForOutcome = (outcome) => {
|
|
|
174
185
|
}
|
|
175
186
|
};
|
|
176
187
|
//#endregion
|
|
177
|
-
export { AGENT_DETECTED_DESCRIPTION, AGENT_MCP_PICKER_MESSAGE, AGENT_MCP_SKIP_MESSAGE, AGENT_OTHER_DESCRIPTION, AGENT_PICKER_MESSAGE, AGENT_PLUGIN_SKIP_MESSAGE, AGENT_SETUP_MESSAGE, AGENT_SETUP_PLUGIN_DESCRIPTION, AGENT_SETUP_PLUGIN_TITLE, AGENT_SETUP_SKILLS_DESCRIPTION, AGENT_SETUP_SKILLS_TITLE, AGENT_SETUP_SKIP_DESCRIPTION, AGENT_SETUP_SKIP_TITLE, AGENT_SKILLS_PICKER_MESSAGE, AGENT_SKILLS_SKIP_MESSAGE, CANCELLED_BODY, CLAIMABLE_ACCOUNT_FLAGS, CLAIMABLE_ALREADY_LINKED, CLAIMABLE_MCP_API_KEY, CLAIMABLE_NO_LINK, CONFIG_CONFIRM_HINT, CONFIG_CONFIRM_MESSAGE, HEADING_CANCELLED, HEADING_COMPLETE, HEADING_FAILED, HEADING_PENDING, INIT_NEEDS_YES, INIT_SUBTITLE, MCP_API_KEY_NEEDS_AUTH, MCP_AUTH_API_KEY_DESCRIPTION, MCP_AUTH_API_KEY_TITLE, MCP_AUTH_MESSAGE, MCP_AUTH_OAUTH_DESCRIPTION, MCP_AUTH_OAUTH_TITLE, MCP_OAUTH_FALLBACK, MCP_SCOPED_NEEDS_PROJECT, MCP_SCOPE_GLOBAL_DESCRIPTION, MCP_SCOPE_GLOBAL_TITLE, MCP_SCOPE_MESSAGE, MCP_SCOPE_PROJECT_DESCRIPTION, MCP_SCOPE_PROJECT_TITLE, MODE_CUSTOM_DESCRIPTION, MODE_CUSTOM_TITLE, MODE_MESSAGE, MODE_RECOMMENDED_DESCRIPTION, MODE_RECOMMENDED_TITLE, NON_TTY_AGENT_SETUP, NON_TTY_LINK_NEEDS_AUTH, NO_AGENTS_FALLBACK_STATUS, NO_AGENT_SETUP_CONFLICT, PACKAGE_MANAGER_MESSAGE, PROGRESS, PROJECT_PINNED_OFFLINE, PROJECT_SETUP_CLAIMABLE_DESCRIPTION, PROJECT_SETUP_CLAIMABLE_TITLE, PROJECT_SETUP_LINK_DESCRIPTION, PROJECT_SETUP_LINK_TITLE, PROJECT_SETUP_MESSAGE, SERVICES_HINT, SERVICES_MESSAGE, SKILLS_PICKER_MESSAGE, agentMissingCommandDescription, claimableNext, claimableThenServicesNext, configInitNext, envPullFailedNext, existingConfigNext, headingForOutcome, installFailedNext, mcpAfterLinkNext, mcpConfigLocationSkipped, mcpConfigLocationUnavailable, mcpKeyFailedNext, namedAgentsUnavailable, newConfigNext, offlinePinNext, skippedLinkNext, unattendedUnauthedNext };
|
|
188
|
+
export { AGENTS_NOT_INSTALLED, AGENT_DETECTED_DESCRIPTION, AGENT_MCP_PICKER_MESSAGE, AGENT_MCP_SKIP_MESSAGE, AGENT_OTHER_DESCRIPTION, AGENT_PICKER_MESSAGE, AGENT_PLUGIN_SKIP_MESSAGE, AGENT_SETUP_MESSAGE, AGENT_SETUP_PLUGIN_DESCRIPTION, AGENT_SETUP_PLUGIN_TITLE, AGENT_SETUP_SKILLS_DESCRIPTION, AGENT_SETUP_SKILLS_TITLE, AGENT_SETUP_SKIP_DESCRIPTION, AGENT_SETUP_SKIP_TITLE, AGENT_SKILLS_PICKER_MESSAGE, AGENT_SKILLS_SKIP_MESSAGE, CANCELLED_BODY, CLAIMABLE_ACCOUNT_FLAGS, CLAIMABLE_ALREADY_LINKED, CLAIMABLE_MCP_API_KEY, CLAIMABLE_NO_LINK, CONFIG_CONFIRM_HINT, CONFIG_CONFIRM_MESSAGE, HEADING_CANCELLED, HEADING_COMPLETE, HEADING_FAILED, HEADING_PENDING, INIT_NEEDS_YES, INIT_SUBTITLE, MCP_API_KEY_NEEDS_AUTH, MCP_AUTH_API_KEY_DESCRIPTION, MCP_AUTH_API_KEY_TITLE, MCP_AUTH_MESSAGE, MCP_AUTH_OAUTH_DESCRIPTION, MCP_AUTH_OAUTH_TITLE, MCP_OAUTH_FALLBACK, MCP_SCOPED_NEEDS_PROJECT, MCP_SCOPE_GLOBAL_DESCRIPTION, MCP_SCOPE_GLOBAL_TITLE, MCP_SCOPE_MESSAGE, MCP_SCOPE_PROJECT_DESCRIPTION, MCP_SCOPE_PROJECT_TITLE, MODE_CUSTOM_DESCRIPTION, MODE_CUSTOM_TITLE, MODE_MESSAGE, MODE_RECOMMENDED_DESCRIPTION, MODE_RECOMMENDED_TITLE, NON_TTY_AGENT_SETUP, NON_TTY_LINK_NEEDS_AUTH, NO_AGENTS_FALLBACK_STATUS, NO_AGENT_SETUP_CONFLICT, PACKAGE_MANAGER_MESSAGE, PROGRESS, PROJECT_PINNED_OFFLINE, PROJECT_SETUP_CLAIMABLE_DESCRIPTION, PROJECT_SETUP_CLAIMABLE_TITLE, PROJECT_SETUP_LINK_DESCRIPTION, PROJECT_SETUP_LINK_TITLE, PROJECT_SETUP_MESSAGE, SERVICES_HINT, SERVICES_MESSAGE, SKILLS_PICKER_MESSAGE, agentMissingCommandDescription, claimableNext, claimableThenServicesNext, configInitNext, envPullFailedNext, existingConfigNext, headingForOutcome, installFailedNext, mcpAfterLinkNext, mcpConfigLocationSkipped, mcpConfigLocationUnavailable, mcpKeyFailedNext, namedAgentsUnavailable, newConfigNext, offlinePinNext, skippedLinkNext, toolingFailedNext, unattendedUnauthedNext };
|
package/dist/init/funnel.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import pkg_default from "../pkg.js";
|
|
2
|
-
import {
|
|
2
|
+
import { codeFromBody, isNeonApiError } from "../api.js";
|
|
3
|
+
import { isNetworkError, matchErrorCode } from "../errors.js";
|
|
4
|
+
import { redactCredentialTokenIds, trackEvent } from "../analytics.js";
|
|
5
|
+
import { AuthRefreshError } from "../auth.js";
|
|
3
6
|
import { randomUUID } from "node:crypto";
|
|
7
|
+
import { stripVTControlCharacters } from "node:util";
|
|
4
8
|
//#region src/init/funnel.ts
|
|
5
9
|
const CLI_INIT_START = "cli_init_start";
|
|
6
10
|
const CLI_INIT_END = "cli_init_end";
|
|
@@ -70,17 +74,45 @@ const initStartProperties = (input) => ({
|
|
|
70
74
|
detected_agents: input.detection.detectedAgents,
|
|
71
75
|
ci: input.detection.ci
|
|
72
76
|
});
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
77
|
+
/** Longer messages are cut so one plugin CLI dump cannot dominate the event. */
|
|
78
|
+
const ERROR_MESSAGE_LIMIT = 2e3;
|
|
79
|
+
/**
|
|
80
|
+
* The `errCode` the top-level failure handler (`index.ts`) sends on `CLI Error` for the same
|
|
81
|
+
* error, so a run's `error_code` and its `CLI Error` event agree.
|
|
82
|
+
*/
|
|
83
|
+
const initErrorCode = (error) => {
|
|
84
|
+
if (error instanceof AuthRefreshError) return "AUTH_FAILED";
|
|
85
|
+
if (isNetworkError(error)) return "NETWORK_ERROR";
|
|
86
|
+
if (isNeonApiError(error)) {
|
|
87
|
+
if (error.code === "ECONNABORTED") return "REQUEST_TIMEOUT";
|
|
88
|
+
const bodyCode = codeFromBody(error.data);
|
|
89
|
+
if (error.status === 401 || bodyCode === "SSO_AUTHORIZATION_REQUIRED" || bodyCode === "SSO_ORG_CREDS_ONLY") return "AUTH_FAILED";
|
|
90
|
+
return "API_ERROR";
|
|
91
|
+
}
|
|
92
|
+
return matchErrorCode(error instanceof Error ? error.message : void 0);
|
|
93
|
+
};
|
|
94
|
+
const initErrorMessage = (error) => {
|
|
95
|
+
const raw = error instanceof Error ? error.message : String(error);
|
|
96
|
+
return redactCredentialTokenIds(stripVTControlCharacters(raw)).slice(0, ERROR_MESSAGE_LIMIT);
|
|
97
|
+
};
|
|
98
|
+
const initEndProperties = (input) => {
|
|
99
|
+
const reported = input.errors.find((entry) => entry.error === input.exitError) ?? input.errors[0];
|
|
100
|
+
return {
|
|
101
|
+
init_run_id: input.initRunId,
|
|
102
|
+
cli_version: pkg_default.version,
|
|
103
|
+
mode: input.mode,
|
|
104
|
+
agent_setup: input.agentSetup,
|
|
105
|
+
agents_installed: input.agentsInstalled,
|
|
106
|
+
link: input.link,
|
|
107
|
+
config: input.config,
|
|
108
|
+
services: input.services,
|
|
109
|
+
outcome: input.outcome,
|
|
110
|
+
error_step: reported?.step ?? null,
|
|
111
|
+
error_code: reported === void 0 ? null : initErrorCode(reported.error),
|
|
112
|
+
error_message: reported === void 0 ? null : initErrorMessage(reported.error),
|
|
113
|
+
error_steps: [...new Set(input.errors.map((entry) => entry.step))]
|
|
114
|
+
};
|
|
115
|
+
};
|
|
84
116
|
const emitInitStart = (properties) => {
|
|
85
117
|
trackEvent(CLI_INIT_START, properties);
|
|
86
118
|
};
|
|
@@ -95,8 +127,22 @@ const createInitFunnel = (initRunId = createInitRunId()) => ({
|
|
|
95
127
|
link: null,
|
|
96
128
|
config: null,
|
|
97
129
|
services: null,
|
|
130
|
+
errors: [],
|
|
131
|
+
exitError: void 0,
|
|
98
132
|
ended: false
|
|
99
133
|
});
|
|
134
|
+
/** Records a failure once: a deferred error rethrown at the end keeps the step it failed in. */
|
|
135
|
+
const recordInitError = (state, step, error) => {
|
|
136
|
+
if (state.errors.some((entry) => entry.error === error)) return;
|
|
137
|
+
state.errors.push({
|
|
138
|
+
step,
|
|
139
|
+
error
|
|
140
|
+
});
|
|
141
|
+
};
|
|
142
|
+
const recordInitExit = (state, step, error) => {
|
|
143
|
+
recordInitError(state, step, error);
|
|
144
|
+
state.exitError = error;
|
|
145
|
+
};
|
|
100
146
|
const finishInitFunnel = (state, outcome, analytics) => {
|
|
101
147
|
if (state.ended || !analytics) return;
|
|
102
148
|
state.ended = true;
|
|
@@ -108,8 +154,10 @@ const finishInitFunnel = (state, outcome, analytics) => {
|
|
|
108
154
|
link: state.link,
|
|
109
155
|
config: state.config,
|
|
110
156
|
services: state.services,
|
|
111
|
-
outcome
|
|
157
|
+
outcome,
|
|
158
|
+
errors: state.errors,
|
|
159
|
+
exitError: state.exitError
|
|
112
160
|
}));
|
|
113
161
|
};
|
|
114
162
|
//#endregion
|
|
115
|
-
export { CLI_INIT_END, CLI_INIT_START, createInitFunnel, createInitRunId, emitInitEnd, emitInitStart, finishInitFunnel, initEndProperties, initFlagsFromArgv, initStartProperties };
|
|
163
|
+
export { CLI_INIT_END, CLI_INIT_START, createInitFunnel, createInitRunId, emitInitEnd, emitInitStart, finishInitFunnel, initEndProperties, initErrorCode, initErrorMessage, initFlagsFromArgv, initStartProperties, recordInitError, recordInitExit };
|
package/dist/init/run.js
CHANGED
|
@@ -15,7 +15,7 @@ import { missingPluginsCommands, pluginsInstallableAgents } from "../plugins/tar
|
|
|
15
15
|
import { skillsInstallableAgents } from "../skills/targets.js";
|
|
16
16
|
import { FALLBACK_SKILLS_AGENTS, assertNamedAgentTooling, funnelAgentSetup, planInitToolingSteps, recommendedTooling, resolveNamedAgents, splitInitTooling } from "./plan.js";
|
|
17
17
|
import { inferPackageManager, resolvePackageManager } from "../utils/package_manager.js";
|
|
18
|
-
import { CANCELLED_BODY, CLAIMABLE_ACCOUNT_FLAGS, CLAIMABLE_ALREADY_LINKED, CLAIMABLE_MCP_API_KEY, CLAIMABLE_NO_LINK, MCP_API_KEY_NEEDS_AUTH, MCP_SCOPED_NEEDS_PROJECT, NON_TTY_LINK_NEEDS_AUTH, NO_AGENTS_FALLBACK_STATUS, PROGRESS, PROJECT_PINNED_OFFLINE, claimableNext, claimableThenServicesNext, configInitNext, envPullFailedNext, existingConfigNext, installFailedNext, mcpAfterLinkNext, mcpConfigLocationSkipped, mcpConfigLocationUnavailable, mcpKeyFailedNext, namedAgentsUnavailable, newConfigNext, offlinePinNext, skippedLinkNext, unattendedUnauthedNext } from "./copy.js";
|
|
18
|
+
import { AGENTS_NOT_INSTALLED, CANCELLED_BODY, CLAIMABLE_ACCOUNT_FLAGS, CLAIMABLE_ALREADY_LINKED, CLAIMABLE_MCP_API_KEY, CLAIMABLE_NO_LINK, MCP_API_KEY_NEEDS_AUTH, MCP_SCOPED_NEEDS_PROJECT, NON_TTY_LINK_NEEDS_AUTH, NO_AGENTS_FALLBACK_STATUS, PROGRESS, PROJECT_PINNED_OFFLINE, claimableNext, claimableThenServicesNext, configInitNext, envPullFailedNext, existingConfigNext, installFailedNext, mcpAfterLinkNext, mcpConfigLocationSkipped, mcpConfigLocationUnavailable, mcpKeyFailedNext, namedAgentsUnavailable, newConfigNext, offlinePinNext, skippedLinkNext, toolingFailedNext, unattendedUnauthedNext } from "./copy.js";
|
|
19
19
|
import { agentsRowValue, configRowValue, formatInitDone, headingForKind, printInitBanner, printInitDone, printInitProgress, projectRowValue, shouldPrintInitBanner } from "./chrome.js";
|
|
20
20
|
import { h as initCmd, t as ConfigInstallFailed } from "../_chunks/config-BH_qRHiG.js";
|
|
21
21
|
import { o as quoteFlagValue, s as runLink } from "../_chunks/link-BgtkOBws.js";
|
|
@@ -24,11 +24,11 @@ import { CannotMintApiKeyError } from "../mcp/mint.js";
|
|
|
24
24
|
import { pullInitEnv } from "./auth.js";
|
|
25
25
|
import { InitCancelled, raceSigint, restoreCursor } from "./cancelled.js";
|
|
26
26
|
import { pickAgentSetupInteractively, pickInitAgentsInteractively, pickInitConfigInteractively, pickInitMcpAuthInteractively, pickInitMcpConfigLocationInteractively, pickInitModeInteractively, pickInitPackageManagerInteractively, pickInitProjectSetupInteractively, pickInitServicesInteractively, pickInitSkillsInteractively } from "./wizard.js";
|
|
27
|
-
import { runToolingSteps } from "./tooling.js";
|
|
27
|
+
import { runToolingSteps, toolingStepCommandText } from "./tooling.js";
|
|
28
28
|
import { l as create } from "../_chunks/claim-DqAvAvDm.js";
|
|
29
29
|
import { INIT_CONFIG_SERVICES_CONFLICT, configPlanFromResolution, initEnvPullAfterConfig, resolveInitConfigChoice } from "./choices.js";
|
|
30
30
|
import { detectInitEnvironment } from "./detect.js";
|
|
31
|
-
import { createInitFunnel, emitInitStart, finishInitFunnel, initStartProperties } from "./funnel.js";
|
|
31
|
+
import { createInitFunnel, emitInitStart, finishInitFunnel, initStartProperties, recordInitError, recordInitExit } from "./funnel.js";
|
|
32
32
|
import { assertAgentSetupFlags, hasInitMcpFlags, inferInitAgentSetup, resolveInitMode } from "./mode.js";
|
|
33
33
|
import { resolve } from "node:path";
|
|
34
34
|
//#region src/init/run.ts
|
|
@@ -197,6 +197,8 @@ const runInit = async (props) => {
|
|
|
197
197
|
const funnel = createInitFunnel();
|
|
198
198
|
let outcome = "error";
|
|
199
199
|
let printed = false;
|
|
200
|
+
let step = "setup";
|
|
201
|
+
let deferredFailureNext = () => [];
|
|
200
202
|
try {
|
|
201
203
|
const detectOpts = {
|
|
202
204
|
cwd,
|
|
@@ -332,7 +334,23 @@ const runInit = async (props) => {
|
|
|
332
334
|
const mcpOauth = mcpAuth === "oauth";
|
|
333
335
|
const earlyTooling = delayMcp ? withoutMcp(tooling) : tooling;
|
|
334
336
|
const mcpState = {};
|
|
335
|
-
const
|
|
337
|
+
const toolingFailures = [];
|
|
338
|
+
const reportedTooling = () => {
|
|
339
|
+
const dropped = new Set(toolingFailures.map((failure) => failure.kind));
|
|
340
|
+
if (mcpState.error !== void 0 || mcpState.deferredPin !== void 0) dropped.add("mcp");
|
|
341
|
+
return withoutKinds(tooling, dropped);
|
|
342
|
+
};
|
|
343
|
+
const agentsRow = () => {
|
|
344
|
+
const reported = reportedTooling();
|
|
345
|
+
return toolingFailures.length > 0 && reported.setup === "skip" ? AGENTS_NOT_INSTALLED : agentsRowValue({
|
|
346
|
+
tooling: reported,
|
|
347
|
+
installed: funnel.agentsInstalled
|
|
348
|
+
});
|
|
349
|
+
};
|
|
350
|
+
const toolingFailedNextLines = () => toolingFailedNext(toolingFailures.map((failure) => ({
|
|
351
|
+
kind: failure.kind,
|
|
352
|
+
command: failure.command
|
|
353
|
+
})));
|
|
336
354
|
const mcpCommand = (projectIdArg) => [
|
|
337
355
|
`${getCliName()} mcp -y`,
|
|
338
356
|
...mcpConfigLocation === "project" ? ["--project"] : [],
|
|
@@ -340,25 +358,35 @@ const runInit = async (props) => {
|
|
|
340
358
|
...("mcpAgents" in tooling ? tooling.mcpAgents : []).map((agent) => `--agent ${agent}`)
|
|
341
359
|
].join(" ");
|
|
342
360
|
const mcpFailedNext = () => mcpState.error === void 0 ? [] : mcpKeyFailedNext(mcpState.reason ?? "cannot-mint", mcpCommand(mcpState.pinId !== void 0 ? quoteFlagValue(mcpState.pinId) : void 0));
|
|
361
|
+
deferredFailureNext = () => joinNext(toolingFailedNextLines(), mcpFailedNext());
|
|
343
362
|
const mcpDeferredNext = () => mcpState.deferredPin === void 0 ? [] : mcpAfterLinkNext(`${mcpCommand(mcpState.deferredPin)}${mcpOauth ? " --oauth" : ""}`);
|
|
344
363
|
const runTooling = async (steps, plan) => {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
364
|
+
for (const toolingStep of steps) {
|
|
365
|
+
let completed;
|
|
366
|
+
try {
|
|
367
|
+
completed = await runToolingSteps([toolingStep], {
|
|
368
|
+
cwd,
|
|
369
|
+
output: props.output,
|
|
370
|
+
auth,
|
|
371
|
+
operations: props.operations,
|
|
372
|
+
narrate: "human",
|
|
373
|
+
mcpOauthFallback: !mcpAuthChosen
|
|
374
|
+
});
|
|
375
|
+
} catch (error) {
|
|
376
|
+
if (error instanceof InitCancelled) throw error;
|
|
377
|
+
if (error instanceof CannotMintApiKeyError) {
|
|
378
|
+
mcpState.error = error;
|
|
379
|
+
mcpState.reason = "cannot-mint";
|
|
380
|
+
} else toolingFailures.push({
|
|
381
|
+
kind: toolingStep.kind,
|
|
382
|
+
command: `${getCliName()} ${toolingStepCommandText(toolingStep)}`,
|
|
383
|
+
error
|
|
384
|
+
});
|
|
385
|
+
recordInitError(funnel, toolingStep.kind, error);
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
if (completed.includes(toolingStep.kind)) funnel.agentsInstalled = uniqueAgents([...funnel.agentsInstalled, ...agentsForStep(plan, toolingStep.kind)]);
|
|
360
389
|
}
|
|
361
|
-
funnel.agentsInstalled = uniqueAgents([...funnel.agentsInstalled, ...agentsFromTooling(ran)]);
|
|
362
390
|
};
|
|
363
391
|
const toolingSteps = planInitToolingSteps({
|
|
364
392
|
tooling: earlyTooling,
|
|
@@ -370,6 +398,7 @@ const runInit = async (props) => {
|
|
|
370
398
|
...selectedSkills !== void 0 ? { skills: selectedSkills } : {}
|
|
371
399
|
});
|
|
372
400
|
if (toolingSteps.length > 0) await runTooling(toolingSteps, earlyTooling);
|
|
401
|
+
step = "link";
|
|
373
402
|
let projectSetup = "skip";
|
|
374
403
|
let claimExpiresAt;
|
|
375
404
|
const noLink = props.link === false;
|
|
@@ -419,6 +448,7 @@ const runInit = async (props) => {
|
|
|
419
448
|
};
|
|
420
449
|
if (usesMcp && mcpAuth === "api-key" && (projectSetup === "claimable" || props.claimable === true)) throw new Error(CLAIMABLE_MCP_API_KEY);
|
|
421
450
|
if (projectSetup === "claimable") {
|
|
451
|
+
step = "claimable";
|
|
422
452
|
printInitProgress(PROGRESS.claim);
|
|
423
453
|
await (props.createClaimable ?? defaultCreateClaimable)({
|
|
424
454
|
cwd,
|
|
@@ -432,12 +462,14 @@ const runInit = async (props) => {
|
|
|
432
462
|
funnel.link = "claimable";
|
|
433
463
|
claimExpiresAt = readLinkedClaimableCredentials(configDir, readContextFile(contextFile))?.expiresAt;
|
|
434
464
|
} else if (projectSetup === "link") {
|
|
465
|
+
step = "link";
|
|
435
466
|
printInitProgress(detection.authenticated ? PROGRESS.link : PROGRESS.auth);
|
|
436
467
|
await (props.linkProject ?? runAuthenticatedLink)(linkProps);
|
|
437
468
|
funnel.link = "linked";
|
|
438
469
|
}
|
|
439
470
|
const pinnedOffline = funnel.link === "skipped" && !noLink && linkInputs.orgId !== void 0 && linkInputs.projectId !== void 0 && linkInputs.branch !== void 0 && linkInputs.projectName === void 0 && linkInputs.regionId === void 0;
|
|
440
471
|
if (pinnedOffline) {
|
|
472
|
+
step = "link";
|
|
441
473
|
await runLink({
|
|
442
474
|
...linkProps,
|
|
443
475
|
checks: false,
|
|
@@ -449,9 +481,11 @@ const runInit = async (props) => {
|
|
|
449
481
|
else if (delayMcp && tooling.setup !== "skip" && mcpAuth === "api-key" && yes && !detection.authenticated) {
|
|
450
482
|
mcpState.error = new Error(MCP_API_KEY_NEEDS_AUTH);
|
|
451
483
|
mcpState.reason = "signed-out";
|
|
484
|
+
recordInitError(funnel, "mcp", mcpState.error);
|
|
452
485
|
const linkedId = readContextFile(contextFile).projectId;
|
|
453
486
|
if (props.mcpProjectScoped === true && typeof linkedId === "string") mcpState.pinId = linkedId;
|
|
454
487
|
} else if (delayMcp && tooling.setup !== "skip") {
|
|
488
|
+
step = "mcp";
|
|
455
489
|
const linkedId = readContextFile(contextFile).projectId;
|
|
456
490
|
let pinId;
|
|
457
491
|
if (props.mcpProjectScoped === true) {
|
|
@@ -479,6 +513,7 @@ const runInit = async (props) => {
|
|
|
479
513
|
mcpState.pinId = pinId;
|
|
480
514
|
if (mcpSteps.length > 0) await runTooling(mcpSteps, mcpOnly);
|
|
481
515
|
}
|
|
516
|
+
step = "config";
|
|
482
517
|
const canAskConfig = props.pickConfig !== void 0 || detection.interactive;
|
|
483
518
|
const configResolution = resolveInitConfigChoice({
|
|
484
519
|
flag: recommended ? props.config ?? true : props.config,
|
|
@@ -536,7 +571,7 @@ const runInit = async (props) => {
|
|
|
536
571
|
heading: failed.heading,
|
|
537
572
|
body: failed.body,
|
|
538
573
|
rows: [],
|
|
539
|
-
next: joinNext(failed.next, mcpFailedNext())
|
|
574
|
+
next: joinNext(failed.next, joinNext(toolingFailedNextLines(), mcpFailedNext()))
|
|
540
575
|
}));
|
|
541
576
|
printed = true;
|
|
542
577
|
outcome = "error";
|
|
@@ -557,48 +592,48 @@ const runInit = async (props) => {
|
|
|
557
592
|
...typeof context.projectId === "string" ? { projectId: context.projectId } : {},
|
|
558
593
|
...branch !== void 0 ? { branch } : {}
|
|
559
594
|
});
|
|
560
|
-
if (envPullPlan.kind !== "skip")
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
595
|
+
if (envPullPlan.kind !== "skip") {
|
|
596
|
+
step = "env_pull";
|
|
597
|
+
try {
|
|
598
|
+
if (typeof context.projectId !== "string" || typeof branch !== "string") throw new Error("Env pull requires a linked project and branch.");
|
|
599
|
+
printInitProgress(PROGRESS.env);
|
|
600
|
+
await raceSigint((props.envPull ?? pullInitEnv)({
|
|
601
|
+
...auth,
|
|
602
|
+
output: props.output,
|
|
603
|
+
cwd,
|
|
604
|
+
projectId: context.projectId,
|
|
605
|
+
branch,
|
|
606
|
+
...envPullPlan.kind === "services" ? {
|
|
607
|
+
services: envPullPlan.services,
|
|
608
|
+
envKeys: envPullPlan.envKeys
|
|
609
|
+
} : {}
|
|
610
|
+
}));
|
|
611
|
+
} catch (error) {
|
|
612
|
+
if (error instanceof InitCancelled) throw error;
|
|
613
|
+
const failed = envPullFailedNext();
|
|
614
|
+
printInitDone(formatInitDone({
|
|
615
|
+
heading: failed.heading,
|
|
616
|
+
body: failed.body,
|
|
617
|
+
rows: [
|
|
618
|
+
{
|
|
619
|
+
label: "Agents",
|
|
620
|
+
value: agentsRow()
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
label: "Project",
|
|
624
|
+
value: projectRowValue(funnel.link)
|
|
625
|
+
},
|
|
626
|
+
{
|
|
627
|
+
label: "Config",
|
|
628
|
+
value: configRowValue(funnel.config, existingFilename)
|
|
629
|
+
}
|
|
630
|
+
],
|
|
631
|
+
next: joinNext(failed.next, joinNext(toolingFailedNextLines(), mcpFailedNext()))
|
|
632
|
+
}));
|
|
633
|
+
printed = true;
|
|
634
|
+
outcome = "error";
|
|
635
|
+
throw error;
|
|
636
|
+
}
|
|
602
637
|
}
|
|
603
638
|
const pendingUnauthed = funnel.link === "skipped" && !noLink;
|
|
604
639
|
const pendingServices = extraServices && linked;
|
|
@@ -640,16 +675,14 @@ const runInit = async (props) => {
|
|
|
640
675
|
outcome = pending && !pendingUnauthed && noLink ? "success" : pending ? "pending" : "success";
|
|
641
676
|
if (pendingUnauthed) outcome = "pending";
|
|
642
677
|
if (noLink && !pendingUnauthed && !pendingServices && !pendingExisting) outcome = "success";
|
|
643
|
-
|
|
678
|
+
const deferredError = toolingFailures[0]?.error ?? mcpState.error;
|
|
679
|
+
if (deferredError !== void 0) outcome = "error";
|
|
644
680
|
printInitDone(formatInitDone({
|
|
645
681
|
heading: headingForKind(outcome),
|
|
646
682
|
rows: [
|
|
647
683
|
{
|
|
648
684
|
label: "Agents",
|
|
649
|
-
value:
|
|
650
|
-
tooling: reportedTooling(),
|
|
651
|
-
installed: funnel.agentsInstalled
|
|
652
|
-
})
|
|
685
|
+
value: agentsRow()
|
|
653
686
|
},
|
|
654
687
|
{
|
|
655
688
|
label: "Project",
|
|
@@ -660,10 +693,10 @@ const runInit = async (props) => {
|
|
|
660
693
|
value: configRowValue(funnel.config, existingFilename)
|
|
661
694
|
}
|
|
662
695
|
],
|
|
663
|
-
next: joinNext(mcpFailedNext(), next)
|
|
696
|
+
next: joinNext(joinNext(toolingFailedNextLines(), mcpFailedNext()), next)
|
|
664
697
|
}));
|
|
665
698
|
printed = true;
|
|
666
|
-
if (
|
|
699
|
+
if (deferredError !== void 0) throw deferredError;
|
|
667
700
|
takeCommandSuccessExtras();
|
|
668
701
|
recordCommandSuccessExtras({
|
|
669
702
|
init_kind: detection.emptyDirectory ? "empty-skip" : "existing",
|
|
@@ -682,6 +715,13 @@ const runInit = async (props) => {
|
|
|
682
715
|
throw error;
|
|
683
716
|
}
|
|
684
717
|
outcome = "error";
|
|
718
|
+
recordInitExit(funnel, step, error);
|
|
719
|
+
const deferred = deferredFailureNext();
|
|
720
|
+
if (!printed && deferred.length > 0) printInitDone(formatInitDone({
|
|
721
|
+
heading: headingForKind("error"),
|
|
722
|
+
rows: [],
|
|
723
|
+
next: deferred
|
|
724
|
+
}));
|
|
685
725
|
throw error;
|
|
686
726
|
} finally {
|
|
687
727
|
finishInitFunnel(funnel, outcome, analytics);
|
|
@@ -702,31 +742,46 @@ const joinNext = (first, second) => first.length === 0 || second.length === 0 ?
|
|
|
702
742
|
"",
|
|
703
743
|
...second
|
|
704
744
|
];
|
|
705
|
-
const
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
745
|
+
const withoutKinds = (tooling, kinds) => {
|
|
746
|
+
switch (tooling.setup) {
|
|
747
|
+
case "skip": return tooling;
|
|
748
|
+
case "plugin": return kinds.has("plugins") ? { setup: "skip" } : tooling;
|
|
749
|
+
case "skills": return kinds.has("skills") ? { setup: "skip" } : tooling;
|
|
750
|
+
case "skills-mcp": {
|
|
751
|
+
const skillsAgents = kinds.has("skills") ? [] : tooling.skillsAgents;
|
|
752
|
+
const mcpAgents = kinds.has("mcp") ? [] : tooling.mcpAgents;
|
|
753
|
+
return skillsAgents.length === 0 && mcpAgents.length === 0 ? { setup: "skip" } : {
|
|
754
|
+
...tooling,
|
|
755
|
+
skillsAgents,
|
|
756
|
+
mcpAgents
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
case "mixed": {
|
|
760
|
+
const skillsAgents = kinds.has("skills") ? [] : tooling.skillsAgents;
|
|
761
|
+
const mcpAgents = kinds.has("mcp") ? [] : tooling.mcpAgents;
|
|
762
|
+
if (!kinds.has("plugins")) return {
|
|
763
|
+
...tooling,
|
|
764
|
+
skillsAgents,
|
|
765
|
+
mcpAgents
|
|
766
|
+
};
|
|
767
|
+
return skillsAgents.length === 0 && mcpAgents.length === 0 ? { setup: "skip" } : {
|
|
768
|
+
setup: "skills-mcp",
|
|
769
|
+
skillsAgents,
|
|
770
|
+
mcpAgents
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
default: return tooling;
|
|
774
|
+
}
|
|
715
775
|
};
|
|
776
|
+
const withoutMcp = (tooling) => withoutKinds(tooling, /* @__PURE__ */ new Set(["mcp"]));
|
|
716
777
|
/** The Neon plugin bundles the skills. */
|
|
717
778
|
const installsSkills = (tooling) => tooling.setup === "skills-mcp" ? tooling.skillsAgents.length > 0 : tooling.setup !== "skip";
|
|
718
|
-
const
|
|
719
|
-
switch (
|
|
720
|
-
case "
|
|
721
|
-
case "
|
|
722
|
-
case "
|
|
723
|
-
|
|
724
|
-
case "mixed": return uniqueAgents([
|
|
725
|
-
...tooling.pluginAgents,
|
|
726
|
-
...tooling.skillsAgents,
|
|
727
|
-
...tooling.mcpAgents
|
|
728
|
-
]);
|
|
729
|
-
default: return tooling;
|
|
779
|
+
const agentsForStep = (tooling, kind) => {
|
|
780
|
+
switch (kind) {
|
|
781
|
+
case "plugins": return tooling.setup === "plugin" ? [...tooling.agents] : tooling.setup === "mixed" ? [...tooling.pluginAgents] : [];
|
|
782
|
+
case "skills": return tooling.setup === "skills" ? [...tooling.agents] : tooling.setup === "skills-mcp" || tooling.setup === "mixed" ? [...tooling.skillsAgents] : [];
|
|
783
|
+
case "mcp": return tooling.setup === "skills-mcp" || tooling.setup === "mixed" ? [...tooling.mcpAgents] : [];
|
|
784
|
+
default: return kind;
|
|
730
785
|
}
|
|
731
786
|
};
|
|
732
787
|
//#endregion
|
package/dist/init/tooling.js
CHANGED
|
@@ -6,7 +6,7 @@ import { CannotMintApiKeyError } from "../mcp/mint.js";
|
|
|
6
6
|
import { detectAgent } from "./detect_host.js";
|
|
7
7
|
import { AgentSelectionSkipped, canPickAgentsInteractively } from "../utils/agent_picker.js";
|
|
8
8
|
import { a as mcpInstallError, s as reportMcpInstall } from "../_chunks/mcp-Bo-7TKc7.js";
|
|
9
|
-
import { l as reportPluginsInstall, o as installPlugins, s as pluginsInstallError } from "../_chunks/plugins-
|
|
9
|
+
import { l as reportPluginsInstall, o as installPlugins, s as pluginsInstallError } from "../_chunks/plugins-Dj0H6lDA.js";
|
|
10
10
|
import { c as skillsInstallError, o as installSkills, s as reportSkillsInstall } from "../_chunks/skills-BP6pIm7O.js";
|
|
11
11
|
import { runAuthenticatedMcp } from "./auth.js";
|
|
12
12
|
import { raceSigint } from "./cancelled.js";
|
|
@@ -19,7 +19,7 @@ const TOOLING_STEP_LABELS = {
|
|
|
19
19
|
skills: PROGRESS.skills,
|
|
20
20
|
mcp: PROGRESS.mcp
|
|
21
21
|
};
|
|
22
|
-
/**
|
|
22
|
+
/** The `<command> <flags>` a user can run to repeat this step on its own. Never executed here. */
|
|
23
23
|
const toolingStepCommandText = (step) => {
|
|
24
24
|
const flags = [];
|
|
25
25
|
switch (step.kind) {
|
|
@@ -185,4 +185,4 @@ const runAgentTooling = async (options) => {
|
|
|
185
185
|
}));
|
|
186
186
|
};
|
|
187
187
|
//#endregion
|
|
188
|
-
export { runAgentTooling, runToolingSteps };
|
|
188
|
+
export { runAgentTooling, runToolingSteps, toolingStepCommandText };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neon",
|
|
3
|
-
"version": "8.13.
|
|
3
|
+
"version": "8.13.2",
|
|
4
4
|
"description": "CLI tool for Neon, the cloud backend primitives built around Lakebase Postgres",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"neon",
|
|
@@ -113,8 +113,8 @@
|
|
|
113
113
|
"vitest": "^3.0.9",
|
|
114
114
|
"@neon-internals/cli-core": "0.0.0",
|
|
115
115
|
"@neon-internals/env-core": "0.0.36",
|
|
116
|
-
"@neon/env": "1.6.6",
|
|
117
116
|
"@neon/e2e-harness": "0.0.0",
|
|
117
|
+
"@neon/env": "1.6.6",
|
|
118
118
|
"@neon/functions": "0.11.0"
|
|
119
119
|
},
|
|
120
120
|
"publishConfig": {
|