@prisma/cli 3.0.0-dev.104.1 → 3.0.0-dev.105.1

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.
Files changed (44) hide show
  1. package/dist/adapters/local-state.js +14 -3
  2. package/dist/adapters/token-storage.js +1 -1
  3. package/dist/cli2.js +4 -2
  4. package/dist/commands/agent/index.js +60 -0
  5. package/dist/commands/app/index.js +2 -2
  6. package/dist/commands/auth/index.js +1 -1
  7. package/dist/commands/git/index.js +1 -1
  8. package/dist/commands/project/index.js +1 -1
  9. package/dist/controllers/agent.js +228 -0
  10. package/dist/controllers/app.js +58 -8
  11. package/dist/controllers/auth.js +38 -3
  12. package/dist/controllers/project.js +2 -2
  13. package/dist/controllers/select-prompt-port.js +1 -0
  14. package/dist/lib/agent/cli-command.js +17 -0
  15. package/dist/lib/agent/constants.js +12 -0
  16. package/dist/lib/agent/package-manager.js +99 -0
  17. package/dist/lib/agent/setup-status.js +83 -0
  18. package/dist/lib/app/branch-database-deploy.js +3 -2
  19. package/dist/lib/app/branch-database.js +2 -1
  20. package/dist/lib/app/build-settings.js +1 -1
  21. package/dist/lib/app/build.js +2 -2
  22. package/dist/lib/app/bun-project.js +1 -1
  23. package/dist/lib/app/compute-config.js +1 -1
  24. package/dist/lib/app/env-file.js +1 -1
  25. package/dist/lib/app/local-dev.js +1 -1
  26. package/dist/lib/app/production-deploy-gate.js +2 -1
  27. package/dist/lib/auth/login.js +1 -1
  28. package/dist/lib/git/local-branch.js +1 -1
  29. package/dist/lib/project/interactive-setup.js +1 -0
  30. package/dist/lib/project/local-pin.js +1 -1
  31. package/dist/lib/project/resolution.js +2 -2
  32. package/dist/lib/project/setup.js +1 -1
  33. package/dist/presenters/agent.js +74 -0
  34. package/dist/presenters/auth.js +1 -1
  35. package/dist/presenters/project.js +1 -1
  36. package/dist/shell/cli-command.js +12 -0
  37. package/dist/shell/command-arguments.js +7 -1
  38. package/dist/shell/command-meta.js +71 -0
  39. package/dist/shell/command-runner.js +1 -1
  40. package/dist/shell/help.js +6 -5
  41. package/dist/shell/prompt.js +7 -3
  42. package/dist/shell/runtime.js +2 -2
  43. package/dist/shell/update-check.js +2 -2
  44. package/package.json +2 -1
@@ -1,5 +1,5 @@
1
- import { mkdir, readFile, writeFile } from "node:fs/promises";
2
1
  import path from "node:path";
2
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
3
3
  //#region src/adapters/local-state.ts
4
4
  const DEFAULT_STATE = {
5
5
  auth: null,
@@ -12,7 +12,8 @@ const DEFAULT_STATE = {
12
12
  app: {
13
13
  selectedByProject: {},
14
14
  knownLiveDeploymentByProject: {}
15
- }
15
+ },
16
+ agent: { setupPromptDismissedAt: null }
16
17
  };
17
18
  const DEFAULT_STATE_FILE_NAME = "state.json";
18
19
  function resolveLocalStateFilePath(stateDir) {
@@ -43,7 +44,8 @@ var LocalStateStore = class {
43
44
  app: {
44
45
  selectedByProject: parsed.app?.selectedByProject ?? {},
45
46
  knownLiveDeploymentByProject: parsed.app?.knownLiveDeploymentByProject ?? {}
46
- }
47
+ },
48
+ agent: { setupPromptDismissedAt: parsed.agent?.setupPromptDismissedAt ?? null }
47
49
  };
48
50
  } catch (error) {
49
51
  if (error.code === "ENOENT") return structuredClone(DEFAULT_STATE);
@@ -139,6 +141,15 @@ var LocalStateStore = class {
139
141
  await this.write(state);
140
142
  return state;
141
143
  }
144
+ async readAgentSetupPromptDismissedAt() {
145
+ return (await this.read()).agent.setupPromptDismissedAt;
146
+ }
147
+ async setAgentSetupPromptDismissedAt(dismissedAt) {
148
+ const state = await this.read();
149
+ state.agent.setupPromptDismissedAt = dismissedAt;
150
+ await this.write(state);
151
+ return state;
152
+ }
142
153
  };
143
154
  //#endregion
144
155
  export { LocalStateStore, resolveLocalStateFilePath };
@@ -1,6 +1,6 @@
1
1
  import { getAuthFilePath } from "../lib/auth/client.js";
2
- import fs from "node:fs/promises";
3
2
  import path from "node:path";
3
+ import fs from "node:fs/promises";
4
4
  import { randomUUID } from "node:crypto";
5
5
  import { CredentialsStore } from "@prisma/credentials-store";
6
6
  //#region src/adapters/token-storage.ts
package/dist/cli2.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import { CliError } from "./shell/errors.js";
2
- import "./shell/prompt.js";
3
2
  import { attachCommandDescriptor } from "./shell/command-meta.js";
4
- import { addCompactGlobalFlags } from "./shell/global-flags.js";
5
3
  import { createShellUi } from "./shell/ui.js";
4
+ import { addCompactGlobalFlags } from "./shell/global-flags.js";
6
5
  import { configureRuntimeCommand, createCommandContext } from "./shell/runtime.js";
7
6
  import { formatUnexpectedError, writeHumanError, writeJsonError, writeJsonSuccess } from "./shell/output.js";
7
+ import { createAgentCommand } from "./commands/agent/index.js";
8
+ import "./shell/prompt.js";
8
9
  import { createAppCommand } from "./commands/app/index.js";
9
10
  import { createAuthCommand } from "./commands/auth/index.js";
10
11
  import { createBranchCommand } from "./commands/branch/index.js";
@@ -46,6 +47,7 @@ function createProgram(runtime) {
46
47
  program.addOption(new Option("--version", "Print the CLI version and exit."));
47
48
  program.name("prisma").showSuggestionAfterError();
48
49
  program.addCommand(createVersionCommand(runtime));
50
+ program.addCommand(createAgentCommand(runtime));
49
51
  program.addCommand(createAuthCommand(runtime));
50
52
  program.addCommand(createProjectCommand(runtime));
51
53
  program.addCommand(createGitCommand(runtime));
@@ -0,0 +1,60 @@
1
+ import { runAgentInstall, runAgentStatus } from "../../controllers/agent.js";
2
+ import { attachCommandDescriptor } from "../../shell/command-meta.js";
3
+ import { renderAgentInstall, renderAgentStatus, serializeAgentInstall, serializeAgentStatus } from "../../presenters/agent.js";
4
+ import { addCompactGlobalFlags, addGlobalFlags } from "../../shell/global-flags.js";
5
+ import { configureRuntimeCommand } from "../../shell/runtime.js";
6
+ import { runCommand } from "../../shell/command-runner.js";
7
+ import { Command, Option } from "commander";
8
+ //#region src/commands/agent/index.ts
9
+ function createAgentCommand(runtime) {
10
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("agent"), runtime), "agent");
11
+ addCompactGlobalFlags(command);
12
+ command.addCommand(createAgentInstallCommand(runtime));
13
+ command.addCommand(createAgentUpdateCommand(runtime));
14
+ command.addCommand(createAgentStatusCommand(runtime));
15
+ return command;
16
+ }
17
+ function createAgentInstallCommand(runtime) {
18
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("install"), runtime), "agent.install");
19
+ addAgentInstallOptions(command);
20
+ addGlobalFlags(command);
21
+ command.action(async (options) => {
22
+ await runCommand(runtime, "agent.install", options, (context) => runAgentInstall(context, options, "install"), {
23
+ renderHuman: (context, descriptor, result) => renderAgentInstall(context, descriptor, result),
24
+ renderJson: (result) => serializeAgentInstall(result)
25
+ });
26
+ });
27
+ return command;
28
+ }
29
+ function createAgentUpdateCommand(runtime) {
30
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("update"), runtime), "agent.update");
31
+ addAgentInstallOptions(command);
32
+ addGlobalFlags(command);
33
+ command.action(async (options) => {
34
+ await runCommand(runtime, "agent.update", options, (context) => runAgentInstall(context, options, "update"), {
35
+ renderHuman: (context, descriptor, result) => renderAgentInstall(context, descriptor, result),
36
+ renderJson: (result) => serializeAgentInstall(result)
37
+ });
38
+ });
39
+ return command;
40
+ }
41
+ function createAgentStatusCommand(runtime) {
42
+ const command = attachCommandDescriptor(configureRuntimeCommand(new Command("status"), runtime), "agent.status");
43
+ command.addOption(new Option("--global", "Check globally installed Prisma skills instead of project skills"));
44
+ addGlobalFlags(command);
45
+ command.action(async (options) => {
46
+ await runCommand(runtime, "agent.status", options, (context) => runAgentStatus(context, options), {
47
+ renderHuman: (context, descriptor, result) => renderAgentStatus(context, descriptor, result),
48
+ renderJson: (result) => serializeAgentStatus(result)
49
+ });
50
+ });
51
+ return command;
52
+ }
53
+ function addAgentInstallOptions(command) {
54
+ command.addOption(new Option("--agent <agent>", "Agent target for Prisma skills; repeat for multiple agents").argParser(collectValues)).addOption(new Option("--all-agents", "Install Prisma skills for every agent supported by the skills CLI")).addOption(new Option("--skill <skill>", "Prisma skill to install; repeat for multiple skills").argParser(collectValues)).addOption(new Option("--global", "Install skills into the user directory instead of the project")).addOption(new Option("--copy", "Ask the skills CLI to copy files instead of symlinking them")).addOption(new Option("--dry-run", "Show changes without writing files"));
55
+ }
56
+ function collectValues(value, previous) {
57
+ return [...previous ?? [], value];
58
+ }
59
+ //#endregion
60
+ export { createAgentCommand };
@@ -1,11 +1,11 @@
1
1
  import { usageError } from "../../shell/errors.js";
2
- import { APP_BUILD_TYPES } from "../../lib/app/build.js";
3
2
  import { attachCommandDescriptor } from "../../shell/command-meta.js";
4
3
  import { addCompactGlobalFlags, addGlobalFlags } from "../../shell/global-flags.js";
5
4
  import { configureRuntimeCommand } from "../../shell/runtime.js";
5
+ import { runCommand, runStreamingCommand } from "../../shell/command-runner.js";
6
+ import { APP_BUILD_TYPES } from "../../lib/app/build.js";
6
7
  import { runAppBuild, runAppDeploy, runAppDomainAdd, runAppDomainRemove, runAppDomainRetry, runAppDomainShow, runAppDomainWait, runAppListDeploys, runAppLogs, runAppOpen, runAppPromote, runAppRemove, runAppRollback, runAppRun, runAppShow, runAppShowDeploy } from "../../controllers/app.js";
7
8
  import { isAppDeployAllResult, renderAppBuild, renderAppDeploy, renderAppDeployAll, renderAppDomainAdd, renderAppDomainRemove, renderAppDomainRetry, renderAppDomainShow, renderAppListDeploys, renderAppOpen, renderAppPromote, renderAppRemove, renderAppRollback, renderAppRun, renderAppShow, renderAppShowDeploy, serializeAppBuild, serializeAppDeploy, serializeAppDeployAll, serializeAppDomainAdd, serializeAppDomainRemove, serializeAppDomainRetry, serializeAppDomainShow, serializeAppListDeploys, serializeAppOpen, serializeAppPromote, serializeAppRemove, serializeAppRollback, serializeAppRun, serializeAppShow, serializeAppShowDeploy } from "../../presenters/app.js";
8
- import { runCommand, runStreamingCommand } from "../../shell/command-runner.js";
9
9
  import { Command, Option } from "commander";
10
10
  import { FRAMEWORK_KEYS, LOCAL_DEV_BUILD_TYPES } from "@prisma/compute-sdk/config";
11
11
  //#region src/commands/app/index.ts
@@ -1,8 +1,8 @@
1
1
  import { attachCommandDescriptor } from "../../shell/command-meta.js";
2
2
  import { addCompactGlobalFlags, addGlobalFlags } from "../../shell/global-flags.js";
3
3
  import { configureRuntimeCommand } from "../../shell/runtime.js";
4
- import { runAuthLogin, runAuthLogout, runAuthWhoAmI, runAuthWorkspaceList, runAuthWorkspaceLogout, runAuthWorkspaceUse } from "../../controllers/auth.js";
5
4
  import { runCommand } from "../../shell/command-runner.js";
5
+ import { runAuthLogin, runAuthLogout, runAuthWhoAmI, runAuthWorkspaceList, runAuthWorkspaceLogout, runAuthWorkspaceUse } from "../../controllers/auth.js";
6
6
  import { renderAuthSuccess, renderAuthWorkspaceList, renderAuthWorkspaceLogout, renderAuthWorkspaceUse, serializeAuthWorkspaceList, serializeAuthWorkspaceLogout, serializeAuthWorkspaceUse } from "../../presenters/auth.js";
7
7
  import { Command, Option } from "commander";
8
8
  //#region src/commands/auth/index.ts
@@ -1,8 +1,8 @@
1
1
  import { attachCommandDescriptor } from "../../shell/command-meta.js";
2
2
  import { addCompactGlobalFlags, addGlobalFlags } from "../../shell/global-flags.js";
3
3
  import { configureRuntimeCommand } from "../../shell/runtime.js";
4
- import { runGitConnect, runGitDisconnect } from "../../controllers/project.js";
5
4
  import { runCommand } from "../../shell/command-runner.js";
5
+ import { runGitConnect, runGitDisconnect } from "../../controllers/project.js";
6
6
  import { renderGitConnect, renderGitDisconnect } from "../../presenters/project.js";
7
7
  import { Command } from "commander";
8
8
  //#region src/commands/git/index.ts
@@ -1,8 +1,8 @@
1
1
  import { attachCommandDescriptor } from "../../shell/command-meta.js";
2
2
  import { addCompactGlobalFlags, addGlobalFlags } from "../../shell/global-flags.js";
3
3
  import { configureRuntimeCommand } from "../../shell/runtime.js";
4
- import { runProjectCreate, runProjectLink, runProjectList, runProjectShow } from "../../controllers/project.js";
5
4
  import { runCommand } from "../../shell/command-runner.js";
5
+ import { runProjectCreate, runProjectLink, runProjectList, runProjectShow } from "../../controllers/project.js";
6
6
  import { renderProjectList, renderProjectSetup, renderProjectShow, serializeProjectList, serializeProjectSetup, serializeProjectShow } from "../../presenters/project.js";
7
7
  import { createEnvCommand } from "../env.js";
8
8
  import { Command } from "commander";
@@ -0,0 +1,228 @@
1
+ import { resolveSkillsPackageRunner } from "../lib/agent/package-manager.js";
2
+ import { resolvePrismaCliPackageCommand } from "../lib/agent/cli-command.js";
3
+ import { DEFAULT_PRISMA_AGENT_SKILLS, DEFAULT_PRISMA_AGENT_TARGETS, PRISMA_AGENT_INSTALL_ARGS, PRISMA_AGENT_STATUS_ARGS, PRISMA_SKILLS_SOURCE, SKILLS_CLI_PACKAGE } from "../lib/agent/constants.js";
4
+ import { readPrismaAgentSetupStatus, resolvePrismaAgentSetupCwd } from "../lib/agent/setup-status.js";
5
+ import { formatShellCommand } from "../shell/command-arguments.js";
6
+ import { CliError } from "../shell/errors.js";
7
+ import { execa } from "execa";
8
+ //#region src/controllers/agent.ts
9
+ async function runAgentInstall(context, options, operation = "install", runOptions = {}) {
10
+ const dryRun = options.dryRun === true;
11
+ const cwd = await resolvePrismaAgentSetupCwd({
12
+ cwd: runOptions.cwd ?? context.runtime.cwd,
13
+ signal: context.runtime.signal
14
+ });
15
+ const skills = await installSkills(context, {
16
+ command: await buildSkillsInstallCommand(context, options, cwd),
17
+ cwd,
18
+ dryRun
19
+ });
20
+ const nextSteps = await resolveAgentInstallNextSteps(context, {
21
+ cwd,
22
+ dryRun,
23
+ global: options.global === true
24
+ });
25
+ return {
26
+ command: `agent.${operation}`,
27
+ result: {
28
+ operation,
29
+ skills
30
+ },
31
+ warnings: [],
32
+ nextSteps
33
+ };
34
+ }
35
+ async function resolveAgentInstallNextSteps(context, options) {
36
+ if (options.dryRun) return [];
37
+ return [`Run ${await resolvePrismaCliPackageCommand({
38
+ cwd: options.cwd,
39
+ signal: context.runtime.signal,
40
+ args: options.global ? [...PRISMA_AGENT_STATUS_ARGS, "--global"] : PRISMA_AGENT_STATUS_ARGS
41
+ })} to verify the installed Prisma skills.`];
42
+ }
43
+ async function runAgentStatus(context, options = {}) {
44
+ const statusScope = options.global ? "global" : "project";
45
+ const cwd = await resolvePrismaAgentSetupCwd({
46
+ cwd: context.runtime.cwd,
47
+ signal: context.runtime.signal
48
+ });
49
+ const status = await readPrismaAgentSetupStatus({
50
+ cwd,
51
+ stateStore: context.stateStore,
52
+ signal: context.runtime.signal
53
+ });
54
+ const installCommand = await resolvePrismaCliPackageCommand({
55
+ cwd,
56
+ signal: context.runtime.signal,
57
+ args: options.global ? [...PRISMA_AGENT_INSTALL_ARGS, "--global"] : PRISMA_AGENT_INSTALL_ARGS
58
+ });
59
+ const skillsList = await listInstalledPrismaSkills(context, cwd, statusScope);
60
+ const skillsInstalled = skillsList.status === "ok" ? skillsList.skills.length > 0 : statusScope === "project" && status.skillsInstalled;
61
+ const warnings = skillsList.status === "ok" ? [] : [statusScope === "project" ? `Could not read installed skills with ${formatShellCommand(skillsList.command)}: ${skillsList.message}. Falling back to ${status.skillsLockPath}.` : `Could not read globally installed skills with ${formatShellCommand(skillsList.command)}: ${skillsList.message}.`];
62
+ const statusSource = resolveStatusSource(skillsList, statusScope);
63
+ return {
64
+ command: "agent.status",
65
+ result: {
66
+ skills: skillsList.status === "ok" ? skillsList.skills : [],
67
+ skillsListCommand: skillsList.command,
68
+ statusScope,
69
+ skillsLockPath: status.skillsLockPath,
70
+ skillsLockInstalled: status.skillsInstalled,
71
+ skillsInstalled,
72
+ statusSource,
73
+ promptDismissedAt: status.promptDismissedAt
74
+ },
75
+ warnings,
76
+ nextSteps: skillsInstalled ? [] : [`Run ${installCommand} to install or refresh Prisma skills.`]
77
+ };
78
+ }
79
+ async function buildSkillsInstallCommand(context, options, cwd) {
80
+ const command = [
81
+ ...await resolveSkillsPackageRunner({
82
+ cwd,
83
+ signal: context.runtime.signal
84
+ }),
85
+ SKILLS_CLI_PACKAGE,
86
+ "add",
87
+ PRISMA_SKILLS_SOURCE
88
+ ];
89
+ const skills = options.skill && options.skill.length > 0 ? options.skill : DEFAULT_PRISMA_AGENT_SKILLS;
90
+ const agents = resolveTargetAgents(options);
91
+ for (const skill of skills) command.push("--skill", skill);
92
+ for (const agent of agents) command.push("--agent", agent);
93
+ if (options.global) command.push("--global");
94
+ if (options.copy || process.platform === "win32") command.push("--copy");
95
+ command.push("--yes");
96
+ return command;
97
+ }
98
+ function resolveTargetAgents(options) {
99
+ if (options.allAgents) return ["*"];
100
+ if (options.agent && options.agent.length > 0) return options.agent;
101
+ return DEFAULT_PRISMA_AGENT_TARGETS;
102
+ }
103
+ async function installSkills(context, options) {
104
+ if (options.dryRun) return {
105
+ status: "would-install",
106
+ command: options.command
107
+ };
108
+ await runChildProcess(context, options.command, options.cwd);
109
+ return {
110
+ status: "installed",
111
+ command: options.command
112
+ };
113
+ }
114
+ async function listInstalledPrismaSkills(context, cwd, scope) {
115
+ const command = [
116
+ ...await resolveSkillsPackageRunner({
117
+ cwd,
118
+ signal: context.runtime.signal
119
+ }),
120
+ SKILLS_CLI_PACKAGE,
121
+ "list",
122
+ ...scope === "global" ? ["-g"] : [],
123
+ "--json"
124
+ ];
125
+ try {
126
+ const { stdout } = await runChildProcessCapture(context, command, cwd);
127
+ return {
128
+ status: "ok",
129
+ command,
130
+ skills: parseSkillsListOutput(stdout).filter((skill) => isPrismaSkillName(skill.name))
131
+ };
132
+ } catch (error) {
133
+ if (isAbortError(error) || context.runtime.signal.aborted) throw error;
134
+ return {
135
+ status: "failed",
136
+ command,
137
+ message: error instanceof Error ? error.message : String(error)
138
+ };
139
+ }
140
+ }
141
+ async function runChildProcess(context, command, cwd) {
142
+ const [executable, args] = splitCommand(command);
143
+ try {
144
+ await execa(executable, args, {
145
+ cwd,
146
+ env: context.runtime.env,
147
+ cancelSignal: context.runtime.signal,
148
+ stdin: "ignore"
149
+ });
150
+ } catch (error) {
151
+ if (isAbortError(error)) throw error;
152
+ throw skillsInstallFailed(command, exitCodeFromError(error), error);
153
+ }
154
+ }
155
+ async function runChildProcessCapture(context, command, cwd) {
156
+ const [executable, args] = splitCommand(command);
157
+ const result = await execa(executable, args, {
158
+ cwd,
159
+ env: context.runtime.env,
160
+ cancelSignal: context.runtime.signal,
161
+ stdin: "ignore"
162
+ });
163
+ return {
164
+ stdout: result.stdout ?? "",
165
+ stderr: result.stderr ?? ""
166
+ };
167
+ }
168
+ function splitCommand(command) {
169
+ const [executable, ...args] = command;
170
+ if (!executable) throw new Error("Cannot run an empty command.");
171
+ return [executable, args];
172
+ }
173
+ function isAbortError(error) {
174
+ return error instanceof Error && error.name === "AbortError" || isObject(error) && error.isCanceled === true;
175
+ }
176
+ function exitCodeFromError(error) {
177
+ if (!isObject(error) || typeof error.exitCode !== "number") return null;
178
+ return error.exitCode;
179
+ }
180
+ function isObject(value) {
181
+ return typeof value === "object" && value !== null;
182
+ }
183
+ function resolveStatusSource(skillsList, statusScope) {
184
+ if (skillsList.status === "ok") return "skills-cli";
185
+ return statusScope === "project" ? "skills-lock" : "unavailable";
186
+ }
187
+ function parseSkillsListOutput(output) {
188
+ const parsed = JSON.parse(output);
189
+ if (!Array.isArray(parsed)) throw new Error("skills list did not return a JSON array");
190
+ return parsed.flatMap((item) => {
191
+ const skill = parseInstalledSkill(item);
192
+ return skill ? [skill] : [];
193
+ });
194
+ }
195
+ function parseInstalledSkill(value) {
196
+ if (typeof value !== "object" || value === null) return null;
197
+ const candidate = value;
198
+ if (typeof candidate.name !== "string" || typeof candidate.path !== "string" || typeof candidate.scope !== "string" || !Array.isArray(candidate.agents)) return null;
199
+ return {
200
+ name: candidate.name,
201
+ path: candidate.path,
202
+ scope: candidate.scope,
203
+ agents: candidate.agents.filter((agent) => typeof agent === "string")
204
+ };
205
+ }
206
+ function isPrismaSkillName(name) {
207
+ return name === "prisma" || name.startsWith("prisma-");
208
+ }
209
+ function skillsInstallFailed(command, code, error) {
210
+ const commandText = formatShellCommand(command);
211
+ return new CliError({
212
+ code: "AGENT_SKILLS_INSTALL_FAILED",
213
+ domain: "cli",
214
+ summary: "Prisma skills install failed",
215
+ why: `The skills installer exited with code ${code ?? "unknown"}.`,
216
+ fix: "Run the command below to retry the installer directly.",
217
+ debug: formatErrorDebug(error),
218
+ exitCode: 1,
219
+ nextSteps: [commandText]
220
+ });
221
+ }
222
+ function formatErrorDebug(error) {
223
+ if (error instanceof Error) return error.stack ?? error.message;
224
+ if (error === void 0) return;
225
+ return String(error);
226
+ }
227
+ //#endregion
228
+ export { runAgentInstall, runAgentStatus };
@@ -1,16 +1,21 @@
1
+ import { resolvePrismaCliPackageCommand } from "../lib/agent/cli-command.js";
2
+ import { PRISMA_AGENT_INSTALL_ARGS, PRISMA_COMPUTE_AGENT_SKILL } from "../lib/agent/constants.js";
3
+ import { readPrismaAgentSetupStatus, shouldOfferPrismaAgentSetup } from "../lib/agent/setup-status.js";
4
+ import { formatCommandArgument } from "../shell/command-arguments.js";
5
+ import { CliError, authRequiredError, featureUnavailableError, usageError, workspaceRequiredError } from "../shell/errors.js";
6
+ import { runAgentInstall } from "./agent.js";
7
+ import { renderCommandHeader, renderSummaryLine } from "../shell/ui.js";
8
+ import { canPrompt } from "../shell/runtime.js";
9
+ import { writeJsonEvent } from "../shell/output.js";
1
10
  import { SERVICE_TOKEN_ENV_VAR, getApiBaseUrl } from "../lib/auth/client.js";
2
11
  import { FileTokenStorage } from "../adapters/token-storage.js";
3
- import { CliError, authRequiredError, featureUnavailableError, usageError, workspaceRequiredError } from "../shell/errors.js";
4
12
  import { confirmPrompt, selectPrompt, textPrompt } from "../shell/prompt.js";
5
13
  import "../lib/app/app-interaction.js";
6
14
  import { PRISMA_APP_CONFIG_FILENAME, detectLegacyBuildSettings, resolveConfiguredAppBuildSettings, resolveInferredAppBuildSettings } from "../lib/app/build-settings.js";
7
15
  import { APP_BUILD_TYPES, APP_BUILD_TYPE_LABELS, RESOLVED_APP_BUILD_TYPES, executeAppBuild } from "../lib/app/build.js";
8
16
  import { envVarNames, parseEnvInputs } from "../lib/app/env-vars.js";
9
17
  import { DomainApiError, createAppProvider } from "../lib/app/app-provider.js";
10
- import { renderCommandHeader } from "../shell/ui.js";
11
- import { canPrompt } from "../shell/runtime.js";
12
18
  import { LOCAL_RESOLUTION_PIN_RELATIVE_PATH, readLocalResolutionPin } from "../lib/project/local-pin.js";
13
- import { formatCommandArgument } from "../shell/command-arguments.js";
14
19
  import { buildProjectSetupNextActions, inferTargetName, localProjectWorkspaceMismatchError, projectNotFoundError, projectResolutionErrorToCliError, resolveDurablePlatformMapping, resolveProjectTarget, sortProjects } from "../lib/project/resolution.js";
15
20
  import { bindProjectToDirectory, projectCreateFailedError, projectDirectoryBindingErrorToCliError, projectSetupNameRequiredError, resolveProjectForSetup, toProjectSummary } from "../lib/project/setup.js";
16
21
  import { maybeSetupBranchDatabase } from "../lib/app/branch-database-deploy.js";
@@ -27,13 +32,12 @@ import { requireComputeAuth } from "../lib/auth/guard.js";
27
32
  import { readAuthState } from "../lib/auth/auth-ops.js";
28
33
  import { readLocalGitBranch } from "../lib/git/local-branch.js";
29
34
  import { promptForProjectSetupChoice } from "../lib/project/interactive-setup.js";
30
- import { writeJsonEvent } from "../shell/output.js";
31
35
  import { createSelectPromptPort } from "./select-prompt-port.js";
32
36
  import { requireAuthenticatedAuthState } from "./auth.js";
33
37
  import { listRealWorkspaceProjects } from "./project.js";
34
- import { COMPUTE_REGIONS, ENTRYPOINT_BUILD_TYPES, FRAMEWORKS, LOCAL_DEV_BUILD_TYPES, frameworkByKey, frameworkFromAlias, isConfigBackedBuildType } from "@prisma/compute-sdk/config";
35
- import { access, readFile } from "node:fs/promises";
36
38
  import path from "node:path";
39
+ import { access, readFile } from "node:fs/promises";
40
+ import { COMPUTE_REGIONS, ENTRYPOINT_BUILD_TYPES, FRAMEWORKS, LOCAL_DEV_BUILD_TYPES, frameworkByKey, frameworkFromAlias, isConfigBackedBuildType } from "@prisma/compute-sdk/config";
37
41
  import { Result, matchError } from "better-result";
38
42
  import open from "open";
39
43
  //#region src/controllers/app.ts
@@ -265,6 +269,7 @@ async function runSingleAppDeploy(context, appName, options, preloadedConfig) {
265
269
  });
266
270
  const appDir = await resolveComputeAppDir(context, computeConfig);
267
271
  const projectDir = computeConfig.config?.configDir ?? context.runtime.cwd;
272
+ const agentSetupWarnings = await maybePromptForAgentSetup(context, projectDir);
268
273
  const localPinReadResult = Boolean(envProjectId || options?.projectRef || options?.createProjectName) ? Result.ok({ kind: "missing" }) : await readLocalResolutionPin(projectDir, context.runtime.signal);
269
274
  if (localPinReadResult.isErr()) throw localPinReadErrorToDeployError(localPinReadResult.error);
270
275
  const localPin = localPinReadResult.value;
@@ -414,7 +419,11 @@ async function runSingleAppDeploy(context, appName, options, preloadedConfig) {
414
419
  durationMs: deployDurationMs,
415
420
  localPin: localPinResult
416
421
  },
417
- warnings: [...legacyWarnings, ...branchDatabaseSetup.warnings],
422
+ warnings: [
423
+ ...agentSetupWarnings,
424
+ ...legacyWarnings,
425
+ ...branchDatabaseSetup.warnings
426
+ ],
418
427
  nextSteps: ["prisma-cli app list-deploys", `prisma-cli app show-deploy ${deployResult.deployment.id}`]
419
428
  };
420
429
  }
@@ -1117,6 +1126,7 @@ async function confirmDomainRemoval(context, target, hostname) {
1117
1126
  if (!await confirmPrompt({
1118
1127
  input: context.runtime.stdin,
1119
1128
  output: context.output.stderr,
1129
+ signal: context.runtime.signal,
1120
1130
  message: `Detach ${hostname} from App "${target.app.name}"?`,
1121
1131
  initialValue: false
1122
1132
  })) throw usageError("Custom domain removal canceled", "The command was canceled before the domain was detached.", "Rerun the command and confirm removal, or pass --yes.", [`prisma-cli app domain remove ${hostname} --app ${target.app.name} --yes`], "app");
@@ -1456,6 +1466,7 @@ async function confirmAppRemoval(context, app) {
1456
1466
  await textPrompt({
1457
1467
  input: context.runtime.stdin,
1458
1468
  output: context.output.stderr,
1469
+ signal: context.runtime.signal,
1459
1470
  message: `Type ${app.name} to confirm app removal`,
1460
1471
  placeholder: app.name,
1461
1472
  validate: (value) => value === app.name ? void 0 : `Type "${app.name}" to confirm removal.`
@@ -2080,6 +2091,42 @@ function maybeRenderProjectLinked(context, directory, projectName, localPinPath)
2080
2091
  if (context.flags.json || context.flags.quiet) return;
2081
2092
  context.output.stderr.write(`${context.ui.success("✔")} Linked "${directory}" to Project "${projectName}"\nSaved ${localPinPath}\n\n`);
2082
2093
  }
2094
+ async function maybePromptForAgentSetup(context, projectDir) {
2095
+ if (!canPrompt(context) || context.flags.yes) return [];
2096
+ if (!shouldOfferPrismaAgentSetup(await readPrismaAgentSetupStatus({
2097
+ cwd: projectDir,
2098
+ stateStore: context.stateStore,
2099
+ signal: context.runtime.signal,
2100
+ requiredSkill: "prisma-compute"
2101
+ }))) return [];
2102
+ if (!await confirmPrompt({
2103
+ input: context.runtime.stdin,
2104
+ output: context.runtime.stderr,
2105
+ signal: context.runtime.signal,
2106
+ message: "Install the Prisma Compute skill for this project?",
2107
+ initialValue: true
2108
+ })) {
2109
+ await context.stateStore.setAgentSetupPromptDismissedAt((/* @__PURE__ */ new Date()).toISOString());
2110
+ return [];
2111
+ }
2112
+ try {
2113
+ await runAgentInstall(context, { skill: [PRISMA_COMPUTE_AGENT_SKILL] }, "install", { cwd: projectDir });
2114
+ if (!context.flags.quiet && !context.flags.json) context.output.stderr.write(`${renderSummaryLine(context.ui, "success", "Installed the Prisma Compute skill for this project.")}\n\n`);
2115
+ return [];
2116
+ } catch (error) {
2117
+ const message = error instanceof Error ? error.message : "Prisma skill install failed.";
2118
+ if (!context.flags.quiet && !context.flags.json) context.output.stderr.write(`${renderSummaryLine(context.ui, "warning", `Skipped Prisma skill install: ${message}`)}\n\n`);
2119
+ return [`The Prisma Compute skill was not installed. Run ${await resolvePrismaCliPackageCommand({
2120
+ cwd: projectDir,
2121
+ signal: context.runtime.signal,
2122
+ args: [
2123
+ ...PRISMA_AGENT_INSTALL_ARGS,
2124
+ "--skill",
2125
+ PRISMA_COMPUTE_AGENT_SKILL
2126
+ ]
2127
+ })} to try again.`];
2128
+ }
2129
+ }
2083
2130
  async function maybeCustomizeDeploySettings(context, options) {
2084
2131
  if (!options.firstDeploy || context.flags.yes || options.explicitFramework || options.explicitEntrypoint || options.explicitHttpPort || !canPrompt(context)) return {
2085
2132
  framework: options.framework,
@@ -2092,6 +2139,7 @@ async function maybeCustomizeDeploySettings(context, options) {
2092
2139
  if (!await confirmPrompt({
2093
2140
  input: context.runtime.stdin,
2094
2141
  output: context.runtime.stderr,
2142
+ signal: context.runtime.signal,
2095
2143
  message: "Customize build settings?",
2096
2144
  initialValue: false
2097
2145
  })) return {
@@ -2101,6 +2149,7 @@ async function maybeCustomizeDeploySettings(context, options) {
2101
2149
  const framework = frameworkFromUserFacingValue(await selectPrompt({
2102
2150
  input: context.runtime.stdin,
2103
2151
  output: context.runtime.stderr,
2152
+ signal: context.runtime.signal,
2104
2153
  message: `Framework (${options.framework.displayName})`,
2105
2154
  choices: FRAMEWORKS.map((framework) => ({
2106
2155
  label: framework.displayName,
@@ -2110,6 +2159,7 @@ async function maybeCustomizeDeploySettings(context, options) {
2110
2159
  const requestedPort = await textPrompt({
2111
2160
  input: context.runtime.stdin,
2112
2161
  output: context.runtime.stderr,
2162
+ signal: context.runtime.signal,
2113
2163
  message: `HTTP port (${options.runtime.port})`,
2114
2164
  placeholder: String(options.runtime.port),
2115
2165
  validate: validateDeployHttpPortText
@@ -1,7 +1,10 @@
1
- import { CLIENT_ID, SERVICE_TOKEN_ENV_VAR, getApiBaseUrl } from "../lib/auth/client.js";
2
- import { FileTokenStorage, WorkspaceSelectionError } from "../adapters/token-storage.js";
1
+ import { resolvePrismaCliPackageCommand } from "../lib/agent/cli-command.js";
2
+ import { PRISMA_AGENT_INSTALL_ARGS } from "../lib/agent/constants.js";
3
+ import { isLikelyProjectDirectory, readPrismaAgentSetupStatus, resolvePrismaAgentSetupCwd, shouldOfferPrismaAgentSetup } from "../lib/agent/setup-status.js";
3
4
  import { authRequiredError, usageError, workspaceAmbiguousError, workspaceNotAuthenticatedError, workspaceSwitchUnavailableError } from "../shell/errors.js";
4
5
  import { canPrompt } from "../shell/runtime.js";
6
+ import { CLIENT_ID, SERVICE_TOKEN_ENV_VAR, getApiBaseUrl } from "../lib/auth/client.js";
7
+ import { FileTokenStorage, WorkspaceSelectionError } from "../adapters/token-storage.js";
5
8
  import { performLogin, performLogout, readAuthState } from "../lib/auth/auth-ops.js";
6
9
  import { createAuthUseCases } from "../use-cases/auth.js";
7
10
  import { createCliUseCaseGateways } from "../use-cases/create-cli-gateways.js";
@@ -17,7 +20,16 @@ async function runAuthLogin(context, options) {
17
20
  await performLogin(context.runtime.env, context.runtime.signal);
18
21
  result = await readAuthState(context.runtime.env, context.runtime.signal);
19
22
  } else result = await loginWithSelectionFlow(context, createAuthUseCases(createCliUseCaseGateways(context)), options);
20
- return createAuthSuccess("auth.login", result, ["prisma-cli auth whoami", "prisma-cli project list"]);
23
+ const agentSetupTipCommand = await resolveAgentSetupTipCommand(context);
24
+ if (agentSetupTipCommand) result = {
25
+ ...result,
26
+ agentSetupTip: { command: agentSetupTipCommand }
27
+ };
28
+ return createAuthSuccess("auth.login", result, [
29
+ "prisma-cli auth whoami",
30
+ "prisma-cli project list",
31
+ ...result.agentSetupTip ? [result.agentSetupTip.command] : []
32
+ ]);
21
33
  }
22
34
  async function runAuthLogout(context) {
23
35
  let result;
@@ -312,5 +324,28 @@ function createAuthSuccess(command, result, nextSteps) {
312
324
  nextSteps
313
325
  };
314
326
  }
327
+ async function resolveAgentSetupTipCommand(context) {
328
+ if (context.flags.json || context.flags.quiet) return null;
329
+ if (context.runtime.env.CI && context.flags.interactive !== true) return null;
330
+ if (!context.runtime.stderr.isTTY && context.flags.interactive !== true) return null;
331
+ const setupCwd = await resolvePrismaAgentSetupCwd({
332
+ cwd: context.runtime.cwd,
333
+ signal: context.runtime.signal
334
+ });
335
+ if (!await isLikelyProjectDirectory({
336
+ cwd: setupCwd,
337
+ signal: context.runtime.signal
338
+ })) return null;
339
+ if (!shouldOfferPrismaAgentSetup(await readPrismaAgentSetupStatus({
340
+ cwd: setupCwd,
341
+ stateStore: context.stateStore,
342
+ signal: context.runtime.signal
343
+ }))) return null;
344
+ return await resolvePrismaCliPackageCommand({
345
+ cwd: setupCwd,
346
+ signal: context.runtime.signal,
347
+ args: PRISMA_AGENT_INSTALL_ARGS
348
+ });
349
+ }
315
350
  //#endregion
316
351
  export { requireAuthenticatedAuthState, runAuthLogin, runAuthLogout, runAuthWhoAmI, runAuthWorkspaceList, runAuthWorkspaceLogout, runAuthWorkspaceUse };
@@ -1,9 +1,9 @@
1
+ import { formatCommandArgument } from "../shell/command-arguments.js";
1
2
  import { CliError, authRequiredError, featureUnavailableError, usageError, workspaceRequiredError } from "../shell/errors.js";
2
- import { createAppProvider } from "../lib/app/app-provider.js";
3
3
  import { renderSummaryLine } from "../shell/ui.js";
4
4
  import { canPrompt } from "../shell/runtime.js";
5
+ import { createAppProvider } from "../lib/app/app-provider.js";
5
6
  import { readLocalResolutionPin } from "../lib/project/local-pin.js";
6
- import { formatCommandArgument } from "../shell/command-arguments.js";
7
7
  import { buildProjectSetupNextActions, inferTargetName, inspectProjectBinding, projectResolutionErrorToCliError, resolveProjectTarget, sortProjects } from "../lib/project/resolution.js";
8
8
  import { bindProjectToDirectory, isValidProjectSetupName, projectCreateFailedError, projectDirectoryBindingErrorToCliError, projectSetupNameRequiredError, resolveProjectForSetup, toProjectSummary } from "../lib/project/setup.js";
9
9
  import { requireComputeAuth } from "../lib/auth/guard.js";
@@ -4,6 +4,7 @@ function createSelectPromptPort(context) {
4
4
  return { select: ({ message, choices }) => selectPrompt({
5
5
  input: context.runtime.stdin,
6
6
  output: context.runtime.stderr,
7
+ signal: context.runtime.signal,
7
8
  message,
8
9
  choices
9
10
  }) };
@@ -0,0 +1,17 @@
1
+ import { formatPrismaCliCommand } from "../../shell/cli-command.js";
2
+ import { resolvePackageRunner, resolvePackageRunnerSync } from "./package-manager.js";
3
+ //#region src/lib/agent/cli-command.ts
4
+ async function resolvePrismaCliPackageCommandFormatter(options) {
5
+ return createPrismaCliPackageCommandFormatter(await resolvePackageRunner(options));
6
+ }
7
+ async function resolvePrismaCliPackageCommand(options) {
8
+ return (await resolvePrismaCliPackageCommandFormatter(options))(options.args);
9
+ }
10
+ function resolvePrismaCliPackageCommandFormatterSync(cwd) {
11
+ return createPrismaCliPackageCommandFormatter(resolvePackageRunnerSync(cwd));
12
+ }
13
+ function createPrismaCliPackageCommandFormatter(packageRunner) {
14
+ return (args) => formatPrismaCliCommand(args, { packageRunner });
15
+ }
16
+ //#endregion
17
+ export { resolvePrismaCliPackageCommand, resolvePrismaCliPackageCommandFormatterSync };