neon 3.0.0 → 3.1.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 +54 -0
- package/dist/_shared/auth_selection.js +76 -79
- package/dist/_shared/credentials.js +166 -187
- package/dist/_shared/env-core/env.js +354 -517
- package/dist/_shared/env-core/reuse-secrets.js +159 -203
- package/dist/_shared/paths.js +129 -126
- package/dist/_shared/profiles.js +192 -242
- package/dist/_shared/secure_file.js +36 -38
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/analytics.js +163 -207
- package/dist/api.js +815 -758
- package/dist/auth.js +121 -141
- package/dist/auth_context.js +39 -53
- package/dist/cli.js +4 -7
- package/dist/commands/api.js +220 -250
- package/dist/commands/api_keys.js +251 -314
- package/dist/commands/auth.js +283 -328
- package/dist/commands/bootstrap.js +372 -437
- package/dist/commands/branches.js +304 -455
- package/dist/commands/bucket.js +374 -514
- package/dist/commands/checkout.js +213 -298
- package/dist/commands/config.js +573 -690
- package/dist/commands/connection_string.js +137 -165
- package/dist/commands/data_api.js +238 -260
- package/dist/commands/databases.js +67 -76
- package/dist/commands/deploy.js +31 -25
- package/dist/commands/dev.js +639 -719
- package/dist/commands/diff.js +156 -200
- package/dist/commands/env.js +243 -303
- package/dist/commands/functions.js +275 -355
- package/dist/commands/index.js +70 -65
- package/dist/commands/init.js +84 -119
- package/dist/commands/inspect.js +55 -55
- package/dist/commands/ip_allow.js +88 -120
- package/dist/commands/link.js +874 -1019
- package/dist/commands/logs.js +291 -0
- package/dist/commands/neon_auth.js +725 -933
- package/dist/commands/operations.js +34 -25
- package/dist/commands/orgs.js +28 -18
- package/dist/commands/profile.js +614 -845
- package/dist/commands/projects.js +313 -373
- package/dist/commands/psql.js +60 -58
- package/dist/commands/roles.js +55 -58
- package/dist/commands/schema_diff.js +87 -131
- package/dist/commands/set_context.js +34 -26
- package/dist/commands/snapshots.js +288 -413
- package/dist/commands/status.js +41 -37
- package/dist/commands/user.js +21 -10
- package/dist/commands/vpc_endpoints.js +85 -113
- package/dist/config.js +7 -6
- package/dist/config_format.js +50 -66
- package/dist/config_template.js +128 -157
- package/dist/context.js +183 -235
- package/dist/current_branch_fast_path.js +40 -49
- package/dist/dev/env.js +313 -394
- package/dist/dev/functions.js +54 -68
- package/dist/dev/inputs.js +46 -58
- package/dist/dev/runtime.js +135 -164
- package/dist/dev/websocket.js +766 -959
- package/dist/env.js +27 -33
- package/dist/env_file.js +118 -132
- package/dist/env_services.js +36 -38
- package/dist/errors.js +57 -68
- package/dist/functions_api.js +45 -43
- package/dist/help.js +189 -140
- package/dist/index.js +182 -257
- package/dist/init/agents.js +137 -118
- package/dist/init/auth.js +58 -68
- package/dist/init/bootstrap.js +325 -396
- package/dist/init/build_config.js +4 -2
- package/dist/init/detect_agent.js +56 -101
- package/dist/init/editors.js +35 -52
- package/dist/init/enrich_output.js +51 -66
- package/dist/init/extension.js +134 -171
- package/dist/init/inspect.js +179 -266
- package/dist/init/interactive.js +510 -622
- package/dist/init/neonctl.js +117 -168
- package/dist/init/orchestrate.js +157 -173
- package/dist/init/phases/auth.js +188 -202
- package/dist/init/phases/cleanup.js +23 -23
- package/dist/init/phases/db.js +251 -277
- package/dist/init/phases/getting_started.js +213 -223
- package/dist/init/phases/mcp.js +174 -224
- package/dist/init/phases/migrations.js +247 -248
- package/dist/init/phases/neon_auth.js +114 -133
- package/dist/init/phases/setup.js +546 -703
- package/dist/init/phases/skills.js +75 -86
- package/dist/init/phases/status.js +72 -67
- package/dist/init/resolve_context.js +102 -99
- package/dist/init/route_command.js +91 -98
- package/dist/init/skills.js +174 -218
- package/dist/init/vsix.js +77 -99
- package/dist/log.js +17 -16
- package/dist/neon_services.js +104 -129
- package/dist/parameters.gen.js +481 -471
- package/dist/pkg.js +17 -19
- package/dist/profile_keys.js +44 -47
- package/dist/psql/cli.js +44 -47
- package/dist/psql/command/cmd_cond.js +231 -406
- package/dist/psql/command/cmd_connect.js +557 -764
- package/dist/psql/command/cmd_copy.js +727 -983
- package/dist/psql/command/cmd_describe.js +1499 -1688
- package/dist/psql/command/cmd_format.js +733 -905
- package/dist/psql/command/cmd_io.js +1293 -2082
- package/dist/psql/command/cmd_lo.js +297 -359
- package/dist/psql/command/cmd_meta.js +727 -878
- package/dist/psql/command/cmd_misc.js +138 -172
- package/dist/psql/command/cmd_pipeline.js +547 -1099
- package/dist/psql/command/cmd_restrict.js +119 -155
- package/dist/psql/command/cmd_show.js +529 -688
- package/dist/psql/command/dispatch.js +261 -325
- package/dist/psql/command/inputQueue.js +35 -33
- package/dist/psql/command/shared.js +49 -63
- package/dist/psql/complete/filenames.js +90 -133
- package/dist/psql/complete/index.js +59 -97
- package/dist/psql/complete/matcher.js +236 -300
- package/dist/psql/complete/psqlVars.js +218 -223
- package/dist/psql/complete/queries.js +159 -177
- package/dist/psql/complete/rules.js +1493 -2299
- package/dist/psql/core/common.js +762 -1180
- package/dist/psql/core/help.js +456 -546
- package/dist/psql/core/mainloop.js +692 -1302
- package/dist/psql/core/prompt.js +391 -408
- package/dist/psql/core/settings.js +429 -644
- package/dist/psql/core/sqlHelp.js +480 -554
- package/dist/psql/core/startup.js +626 -815
- package/dist/psql/core/syncVars.js +67 -110
- package/dist/psql/core/variables.js +156 -278
- package/dist/psql/describe/formatters.js +884 -1285
- package/dist/psql/describe/processNamePattern.js +173 -260
- package/dist/psql/describe/queries.js +1368 -2403
- package/dist/psql/describe/versionGate.js +32 -41
- package/dist/psql/index.js +1414 -1927
- package/dist/psql/io/history.js +232 -271
- package/dist/psql/io/input.js +103 -108
- package/dist/psql/io/lineEditor/buffer.js +238 -319
- package/dist/psql/io/lineEditor/complete.js +135 -213
- package/dist/psql/io/lineEditor/filename.js +139 -148
- package/dist/psql/io/lineEditor/index.js +653 -870
- package/dist/psql/io/lineEditor/keymap.js +544 -702
- package/dist/psql/io/lineEditor/vt100.js +294 -341
- package/dist/psql/io/pgpass.js +158 -187
- package/dist/psql/io/pgservice.js +146 -183
- package/dist/psql/io/psqlrc.js +328 -403
- package/dist/psql/print/aligned.js +1020 -1683
- package/dist/psql/print/asciidoc.js +180 -214
- package/dist/psql/print/crosstab.js +281 -442
- package/dist/psql/print/csv.js +48 -70
- package/dist/psql/print/html.js +195 -226
- package/dist/psql/print/json.js +75 -88
- package/dist/psql/print/latex.js +291 -364
- package/dist/psql/print/pager.js +171 -242
- package/dist/psql/print/troff.js +194 -226
- package/dist/psql/print/unaligned.js +69 -95
- package/dist/psql/print/units.js +167 -169
- package/dist/psql/scanner/slash.js +428 -483
- package/dist/psql/scanner/sql.js +445 -889
- package/dist/psql/scanner/stringutils.js +309 -379
- package/dist/psql/types/index.js +2 -7
- package/dist/psql/types/scanner.js +25 -22
- package/dist/psql/wire/connection.js +2042 -2803
- package/dist/psql/wire/copy.js +84 -100
- package/dist/psql/wire/notify.js +39 -59
- package/dist/psql/wire/pipeline.js +305 -518
- package/dist/psql/wire/protocol.js +349 -417
- package/dist/psql/wire/sasl.js +180 -265
- package/dist/psql/wire/tls.js +400 -561
- package/dist/storage_api.js +115 -129
- package/dist/test_utils/fixtures.js +94 -113
- package/dist/test_utils/oauth_server.js +10 -7
- package/dist/test_utils/project_dir.js +33 -0
- package/dist/utils/ai_gateway_notice.js +131 -162
- package/dist/utils/api_enums.js +21 -28
- package/dist/utils/auth.js +10 -4
- package/dist/utils/branch_notice.js +20 -19
- package/dist/utils/branch_picker.js +83 -89
- package/dist/utils/cli_name.js +15 -12
- package/dist/utils/compute_units.js +20 -27
- package/dist/utils/config_diff.js +127 -158
- package/dist/utils/enrichers.js +95 -148
- package/dist/utils/esbuild.js +130 -189
- package/dist/utils/flags.js +35 -47
- package/dist/utils/formats.js +8 -15
- package/dist/utils/git_diff.js +69 -80
- package/dist/utils/inspect_db.js +101 -143
- package/dist/utils/inspect_queries.js +179 -142
- package/dist/utils/middlewares.js +37 -44
- package/dist/utils/openapi.js +87 -99
- package/dist/utils/package_manager.js +312 -110
- package/dist/utils/point_in_time.js +49 -53
- package/dist/utils/psql.js +89 -106
- package/dist/utils/service_picker.js +55 -58
- package/dist/utils/string.js +5 -5
- package/dist/utils/ui.js +38 -55
- package/dist/utils/write_sync.js +26 -35
- package/dist/utils/zip.js +4 -3
- package/dist/writer.js +67 -87
- package/package.json +7 -5
|
@@ -1,100 +1,93 @@
|
|
|
1
|
+
//#region src/init/route_command.ts
|
|
1
2
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const { handleStatusPhase } = await import("./phases/status.js");
|
|
91
|
-
return handleStatusPhase({ agent: resolvedAgent });
|
|
92
|
-
}
|
|
93
|
-
case "finalize": {
|
|
94
|
-
const { handleCleanup } = await import("./phases/cleanup.js");
|
|
95
|
-
return handleCleanup();
|
|
96
|
-
}
|
|
97
|
-
default:
|
|
98
|
-
throw new Error(`Unknown step: "${step}". Valid steps: auth, db, setup, getting-started, mcp, skills, migrations, neon-auth, status, finalize`);
|
|
99
|
-
}
|
|
3
|
+
* Routes a `--data` payload to a phase handler by its `step` field, without
|
|
4
|
+
* shelling out. This is the whole agent-facing surface of `neon init`:
|
|
5
|
+
*
|
|
6
|
+
* neon init --agent --data '{"step":"auth"}'
|
|
7
|
+
* neon init --agent --data '{"step":"db","projectId":"xyz"}'
|
|
8
|
+
*/
|
|
9
|
+
async function routeDataStep(data, agent) {
|
|
10
|
+
const { step, agentId, ...rest } = data;
|
|
11
|
+
const resolvedAgent = typeof agentId === "string" ? agentId : agent;
|
|
12
|
+
if (rest.data !== void 0 && Object.keys(rest).length === 1) {
|
|
13
|
+
let nested = rest.data;
|
|
14
|
+
if (typeof nested === "string") try {
|
|
15
|
+
nested = JSON.parse(nested);
|
|
16
|
+
} catch {}
|
|
17
|
+
if (typeof nested === "object" && nested !== null) {
|
|
18
|
+
Object.assign(rest, nested);
|
|
19
|
+
delete rest.data;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
switch (step) {
|
|
23
|
+
case "auth": {
|
|
24
|
+
const { handleAuthPhase } = await import("./phases/auth.js");
|
|
25
|
+
return handleAuthPhase({
|
|
26
|
+
agent: resolvedAgent,
|
|
27
|
+
...rest
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
case "db": {
|
|
31
|
+
const { handleDbPhase } = await import("./phases/db.js");
|
|
32
|
+
return handleDbPhase({
|
|
33
|
+
agent: resolvedAgent,
|
|
34
|
+
...rest
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
case "setup": {
|
|
38
|
+
const { handleSetupPhase } = await import("./phases/setup.js");
|
|
39
|
+
return handleSetupPhase({
|
|
40
|
+
agent: resolvedAgent,
|
|
41
|
+
...rest
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
case "getting-started": {
|
|
45
|
+
const { handleGettingStartedPhase } = await import("./phases/getting_started.js");
|
|
46
|
+
return handleGettingStartedPhase({
|
|
47
|
+
agent: resolvedAgent,
|
|
48
|
+
...rest,
|
|
49
|
+
cwd: process.cwd()
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
case "mcp": {
|
|
53
|
+
const { handleMcpPhase } = await import("./phases/mcp.js");
|
|
54
|
+
return handleMcpPhase({
|
|
55
|
+
agent: resolvedAgent,
|
|
56
|
+
...rest
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
case "skills": {
|
|
60
|
+
const { handleSkillsPhase } = await import("./phases/skills.js");
|
|
61
|
+
return handleSkillsPhase({
|
|
62
|
+
agent: resolvedAgent,
|
|
63
|
+
...rest
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
case "migrations": {
|
|
67
|
+
const { handleMigrationsPhase } = await import("./phases/migrations.js");
|
|
68
|
+
return handleMigrationsPhase({
|
|
69
|
+
agent: resolvedAgent,
|
|
70
|
+
...rest,
|
|
71
|
+
cwd: process.cwd()
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
case "neon-auth": {
|
|
75
|
+
const { handleNeonAuthPhase } = await import("./phases/neon_auth.js");
|
|
76
|
+
return handleNeonAuthPhase({
|
|
77
|
+
agent: resolvedAgent,
|
|
78
|
+
...rest
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
case "status": {
|
|
82
|
+
const { handleStatusPhase } = await import("./phases/status.js");
|
|
83
|
+
return handleStatusPhase({ agent: resolvedAgent });
|
|
84
|
+
}
|
|
85
|
+
case "finalize": {
|
|
86
|
+
const { handleCleanup } = await import("./phases/cleanup.js");
|
|
87
|
+
return handleCleanup();
|
|
88
|
+
}
|
|
89
|
+
default: throw new Error(`Unknown step: "${step}". Valid steps: auth, db, setup, getting-started, mcp, skills, migrations, neon-auth, status, finalize`);
|
|
90
|
+
}
|
|
100
91
|
}
|
|
92
|
+
//#endregion
|
|
93
|
+
export { routeDataStep };
|
package/dist/init/skills.js
CHANGED
|
@@ -1,248 +1,204 @@
|
|
|
1
|
+
import { globalInstallCommand, resolveInvokingPackageManager } from "../utils/package_manager.js";
|
|
2
|
+
import { getSkillsAgentName } from "./agents.js";
|
|
1
3
|
import { existsSync, statSync } from "node:fs";
|
|
2
4
|
import { resolve } from "node:path";
|
|
3
5
|
import { log, spinner } from "@clack/prompts";
|
|
4
6
|
import { execa } from "execa";
|
|
5
7
|
import { dim } from "yoctocolors";
|
|
6
|
-
|
|
8
|
+
//#region src/init/skills.ts
|
|
7
9
|
/**
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
* Ensures the `skills` CLI is globally installed so npx doesn't need
|
|
11
|
+
* to download it (which can fail behind corporate proxies / sandboxes).
|
|
12
|
+
*/
|
|
11
13
|
async function ensureSkillsCli() {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
14
|
+
try {
|
|
15
|
+
await execa("skills", ["--version"], {
|
|
16
|
+
stdio: "pipe",
|
|
17
|
+
timeout: 5e3
|
|
18
|
+
});
|
|
19
|
+
} catch {
|
|
20
|
+
const install = globalInstallCommand(resolveInvokingPackageManager(), "skills");
|
|
21
|
+
if (!install) return;
|
|
22
|
+
try {
|
|
23
|
+
await execa(install.command, install.args, {
|
|
24
|
+
stdio: "pipe",
|
|
25
|
+
timeout: 6e4
|
|
26
|
+
});
|
|
27
|
+
} catch {}
|
|
28
|
+
}
|
|
27
29
|
}
|
|
28
30
|
/** Base skills installed for all invocations */
|
|
29
31
|
const BASE_SKILLS = ["neon", "neon-postgres"];
|
|
30
32
|
/** Additional skills installed for preview (non-bootstrap) invocations */
|
|
31
33
|
const PREVIEW_SKILLS = [
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
"neon-object-storage",
|
|
35
|
+
"neon-functions",
|
|
36
|
+
"neon-ai-gateway"
|
|
35
37
|
];
|
|
36
38
|
/** Returns the skill list based on whether preview mode is active */
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
function getSkillList(preview) {
|
|
40
|
+
return preview ? [...BASE_SKILLS, ...PREVIEW_SKILLS] : BASE_SKILLS;
|
|
39
41
|
}
|
|
40
42
|
const SKILL_BASE_URL = "https://neon.com/docs/ai/skills/neon-postgres/references";
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
const SKILL_REFERENCE_URLS = {
|
|
44
|
+
gettingStarted: `${SKILL_BASE_URL}/getting-started.md`,
|
|
45
|
+
connectionMethods: `${SKILL_BASE_URL}/connection-methods.md`,
|
|
46
|
+
neonAuth: `${SKILL_BASE_URL}/neon-auth.md`,
|
|
47
|
+
serverlessDriver: `${SKILL_BASE_URL}/neon-serverless.md`,
|
|
48
|
+
neonCli: `${SKILL_BASE_URL}/neon-cli.md`,
|
|
49
|
+
devtools: `${SKILL_BASE_URL}/devtools.md`,
|
|
50
|
+
branching: `${SKILL_BASE_URL}/branching.md`,
|
|
51
|
+
neonJs: `${SKILL_BASE_URL}/neon-js.md`
|
|
50
52
|
};
|
|
51
53
|
/**
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
* Maps Editor display names to the skills CLI agent name.
|
|
55
|
+
*/
|
|
54
56
|
function editorToSkillsAgent(editor) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
case "Gemini CLI":
|
|
73
|
-
return "gemini-cli";
|
|
74
|
-
case "Goose":
|
|
75
|
-
return "goose";
|
|
76
|
-
case "Claude Desktop":
|
|
77
|
-
return "claude-code";
|
|
78
|
-
case "MCPorter":
|
|
79
|
-
return "mcporter";
|
|
80
|
-
case "Zed":
|
|
81
|
-
return "zed";
|
|
82
|
-
default:
|
|
83
|
-
return "";
|
|
84
|
-
}
|
|
57
|
+
switch (editor) {
|
|
58
|
+
case "Cursor": return "cursor";
|
|
59
|
+
case "VS Code":
|
|
60
|
+
case "GitHub Copilot CLI": return "github-copilot";
|
|
61
|
+
case "Claude CLI": return "claude-code";
|
|
62
|
+
case "Codex": return "codex";
|
|
63
|
+
case "OpenCode": return "opencode";
|
|
64
|
+
case "Antigravity": return "antigravity";
|
|
65
|
+
case "Cline":
|
|
66
|
+
case "Cline CLI": return "cline";
|
|
67
|
+
case "Gemini CLI": return "gemini-cli";
|
|
68
|
+
case "Goose": return "goose";
|
|
69
|
+
case "Claude Desktop": return "claude-code";
|
|
70
|
+
case "MCPorter": return "mcporter";
|
|
71
|
+
case "Zed": return "zed";
|
|
72
|
+
default: return "";
|
|
73
|
+
}
|
|
85
74
|
}
|
|
86
75
|
/**
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
if (anyFailed) {
|
|
128
|
-
skillsSpinner?.stop("Agent skills installation for this project completed with errors");
|
|
129
|
-
if (!quiet)
|
|
130
|
-
log.info("You can manually install skills by running: npx skills add neondatabase/agent-skills --skill neon --skill neon-postgres");
|
|
131
|
-
return false;
|
|
132
|
-
}
|
|
133
|
-
skillsSpinner?.stop(dim("Agent skills installed ✓"));
|
|
134
|
-
return true;
|
|
76
|
+
* Installs Neon agent skills using Vercel's skills CLI.
|
|
77
|
+
*/
|
|
78
|
+
async function installAgentSkills(selectedEditors, options) {
|
|
79
|
+
const quiet = options?.json === true;
|
|
80
|
+
const editorsWithSkills = selectedEditors.filter((e) => editorToSkillsAgent(e) !== "");
|
|
81
|
+
if (editorsWithSkills.length === 0) return true;
|
|
82
|
+
const skillsSpinner = quiet ? null : spinner();
|
|
83
|
+
skillsSpinner?.start("Installing agent skills for Neon in this project...");
|
|
84
|
+
let anyFailed = false;
|
|
85
|
+
await ensureSkillsCli();
|
|
86
|
+
const skills = getSkillList(options?.preview);
|
|
87
|
+
for (const editor of editorsWithSkills) {
|
|
88
|
+
const agentName = editorToSkillsAgent(editor);
|
|
89
|
+
for (const skill of skills) try {
|
|
90
|
+
await execa("skills", [
|
|
91
|
+
"add",
|
|
92
|
+
"neondatabase/agent-skills",
|
|
93
|
+
"--skill",
|
|
94
|
+
skill,
|
|
95
|
+
"--agent",
|
|
96
|
+
agentName,
|
|
97
|
+
...options?.scope === "global" ? ["-g"] : [],
|
|
98
|
+
"-y"
|
|
99
|
+
], {
|
|
100
|
+
stdio: "pipe",
|
|
101
|
+
timeout: 12e4
|
|
102
|
+
});
|
|
103
|
+
} catch (error) {
|
|
104
|
+
if (!quiet) log.error(`Failed to install skill ${skill} for ${editor}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
105
|
+
anyFailed = true;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (anyFailed) {
|
|
109
|
+
skillsSpinner?.stop("Agent skills installation for this project completed with errors");
|
|
110
|
+
if (!quiet) log.info("You can manually install skills by running: npx skills add neondatabase/agent-skills --skill neon --skill neon-postgres");
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
skillsSpinner?.stop(dim("Agent skills installed ✓"));
|
|
114
|
+
return true;
|
|
135
115
|
}
|
|
136
|
-
|
|
137
|
-
// Evergreen skills: ensure skills are up to date (at most once per 12 hours)
|
|
138
|
-
// ---------------------------------------------------------------------------
|
|
139
|
-
const SKILLS_FRESHNESS_MS = 12 * 60 * 60 * 1000; // 12 hours
|
|
116
|
+
const SKILLS_FRESHNESS_MS = 432e5;
|
|
140
117
|
/**
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
118
|
+
* Agent skills directory paths by agent, keyed by scope.
|
|
119
|
+
* These are the directories that `skills add` writes to.
|
|
120
|
+
*/
|
|
144
121
|
const GLOBAL_SKILLS_DIRS = (() => {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
};
|
|
122
|
+
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
123
|
+
const agentsDir = resolve(home, ".agents", "skills");
|
|
124
|
+
return {
|
|
125
|
+
cursor: [resolve(home, ".cursor", "skills"), agentsDir],
|
|
126
|
+
"claude-code": [resolve(home, ".claude", "skills"), agentsDir],
|
|
127
|
+
"github-copilot": [resolve(home, ".vscode", "skills"), agentsDir],
|
|
128
|
+
codex: [resolve(home, ".codex", "skills"), agentsDir],
|
|
129
|
+
cline: [resolve(home, ".cline", "skills"), agentsDir]
|
|
130
|
+
};
|
|
155
131
|
})();
|
|
156
132
|
/**
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
133
|
+
* Checks whether skills were recently updated (within the freshness window).
|
|
134
|
+
* Checks both project-level (skills-lock.json mtime) and global (skills dir mtime).
|
|
135
|
+
*/
|
|
160
136
|
function skillsAreFresh(agent, requiredSkills) {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
const globalDirs = GLOBAL_SKILLS_DIRS[agentName] ?? [];
|
|
181
|
-
for (const dir of globalDirs) {
|
|
182
|
-
const allExist = requiredSkills.every((skill) => existsSync(resolve(dir, skill, "SKILL.md")));
|
|
183
|
-
if (allExist) {
|
|
184
|
-
// Check freshness of any one skill file
|
|
185
|
-
try {
|
|
186
|
-
const mtime = statSync(resolve(dir, requiredSkills[0], "SKILL.md")).mtimeMs;
|
|
187
|
-
if (now - mtime < SKILLS_FRESHNESS_MS)
|
|
188
|
-
return true;
|
|
189
|
-
}
|
|
190
|
-
catch { }
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
return false;
|
|
137
|
+
const now = Date.now();
|
|
138
|
+
const cwd = process.cwd();
|
|
139
|
+
const projectSkillDirs = [
|
|
140
|
+
".agents",
|
|
141
|
+
".cursor",
|
|
142
|
+
".claude"
|
|
143
|
+
];
|
|
144
|
+
const lockPath = resolve(cwd, "skills-lock.json");
|
|
145
|
+
if (existsSync(lockPath)) try {
|
|
146
|
+
if (now - statSync(lockPath).mtimeMs < SKILLS_FRESHNESS_MS) {
|
|
147
|
+
if (requiredSkills.every((skill) => projectSkillDirs.some((dir) => existsSync(resolve(cwd, dir, "skills", skill, "SKILL.md"))))) return true;
|
|
148
|
+
}
|
|
149
|
+
} catch {}
|
|
150
|
+
const agentName = getSkillsAgentName(agent);
|
|
151
|
+
const globalDirs = GLOBAL_SKILLS_DIRS[agentName] ?? [];
|
|
152
|
+
for (const dir of globalDirs) if (requiredSkills.every((skill) => existsSync(resolve(dir, skill, "SKILL.md")))) try {
|
|
153
|
+
if (now - statSync(resolve(dir, requiredSkills[0], "SKILL.md")).mtimeMs < SKILLS_FRESHNESS_MS) return true;
|
|
154
|
+
} catch {}
|
|
155
|
+
return false;
|
|
194
156
|
}
|
|
195
157
|
/**
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
"-y",
|
|
241
|
-
], { stdio: "pipe", timeout: 120000 });
|
|
242
|
-
}
|
|
243
|
-
catch {
|
|
244
|
-
allOk = false;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
return allOk;
|
|
158
|
+
* Ensures Neon agent skills are up to date. Runs `skills add` if the skills
|
|
159
|
+
* haven't been updated within the freshness window (12 hours).
|
|
160
|
+
*
|
|
161
|
+
* Designed to be called from any phase handler — cheap to call repeatedly
|
|
162
|
+
* since it's a no-op when skills are fresh.
|
|
163
|
+
*/
|
|
164
|
+
async function ensureSkillsUpToDate(agent, scope, preview) {
|
|
165
|
+
const resolvedAgent = agent || "cursor";
|
|
166
|
+
const skills = getSkillList(preview);
|
|
167
|
+
if (skillsAreFresh(resolvedAgent, skills)) return true;
|
|
168
|
+
await ensureSkillsCli();
|
|
169
|
+
const agentName = getSkillsAgentName(resolvedAgent);
|
|
170
|
+
let allOk = true;
|
|
171
|
+
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
172
|
+
const cwd = process.cwd();
|
|
173
|
+
const checkDirs = scope === "global" ? [
|
|
174
|
+
resolve(home, ".cursor", "skills"),
|
|
175
|
+
resolve(home, ".claude", "skills"),
|
|
176
|
+
resolve(home, ".agents", "skills")
|
|
177
|
+
] : [
|
|
178
|
+
resolve(cwd, ".cursor", "skills"),
|
|
179
|
+
resolve(cwd, ".claude", "skills"),
|
|
180
|
+
resolve(cwd, ".agents", "skills")
|
|
181
|
+
];
|
|
182
|
+
const missingSkills = skills.filter((skill) => !checkDirs.some((dir) => existsSync(resolve(dir, skill, "SKILL.md"))));
|
|
183
|
+
if (missingSkills.length === 0) return true;
|
|
184
|
+
for (const skill of missingSkills) try {
|
|
185
|
+
await execa("skills", [
|
|
186
|
+
"add",
|
|
187
|
+
"neondatabase/agent-skills",
|
|
188
|
+
"--skill",
|
|
189
|
+
skill,
|
|
190
|
+
"--agent",
|
|
191
|
+
agentName,
|
|
192
|
+
...scope === "global" ? ["-g"] : [],
|
|
193
|
+
"-y"
|
|
194
|
+
], {
|
|
195
|
+
stdio: "pipe",
|
|
196
|
+
timeout: 12e4
|
|
197
|
+
});
|
|
198
|
+
} catch {
|
|
199
|
+
allOk = false;
|
|
200
|
+
}
|
|
201
|
+
return allOk;
|
|
248
202
|
}
|
|
203
|
+
//#endregion
|
|
204
|
+
export { SKILL_REFERENCE_URLS, ensureSkillsUpToDate, getSkillList, installAgentSkills };
|