vercel 51.5.0 → 51.5.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.
- package/dist/chunks/{add-RNQLGEYS.js → add-CSYGALLC.js} +4 -4
- package/dist/chunks/chunk-3VIDEX7A.js +692 -0
- package/dist/chunks/{chunk-6CWW4JIG.js → chunk-4T7RWBT7.js} +3 -3
- package/dist/chunks/{chunk-BRQBLRFB.js → chunk-5I2ESU2C.js} +1 -1
- package/dist/chunks/{chunk-5NTBJ33M.js → chunk-7IM2OOGY.js} +1 -1
- package/dist/chunks/{chunk-FBY3IEDZ.js → chunk-7V43C2HB.js} +7 -7
- package/dist/chunks/{chunk-4DR2FV6O.js → chunk-CXTJ4RY4.js} +1 -1
- package/dist/chunks/{chunk-L2JUC7NX.js → chunk-EQIXUYBY.js} +1 -1
- package/dist/chunks/{chunk-5VKKTHMP.js → chunk-GZF6VMKA.js} +8 -4
- package/dist/chunks/{chunk-D2D4FJ6S.js → chunk-JHVQUIP6.js} +2 -2
- package/dist/chunks/{chunk-NKJC5SI4.js → chunk-K3HUUZM5.js} +1 -1
- package/dist/chunks/{chunk-6C33Y3DC.js → chunk-KAKD6QXJ.js} +6 -6
- package/dist/chunks/{chunk-7ZDERWUW.js → chunk-KNZNWP2U.js} +2 -2
- package/dist/chunks/{chunk-7MF47FW3.js → chunk-LR5Y63NG.js} +1 -1
- package/dist/chunks/{chunk-SG4QOQTF.js → chunk-NJ7GOUCE.js} +2 -2
- package/dist/chunks/{chunk-537JTK2U.js → chunk-P445TBWL.js} +1 -1
- package/dist/chunks/{chunk-DKFFXOHJ.js → chunk-QO2ED7OU.js} +2 -2
- package/dist/chunks/{chunk-HNU5CXW4.js → chunk-SVYO7LZ5.js} +1 -1
- package/dist/chunks/{chunk-HQXVCOH6.js → chunk-T7LHO6SF.js} +1 -1
- package/dist/chunks/{chunk-P56KWLXY.js → chunk-TX6K3Z5E.js} +1 -1
- package/dist/chunks/{chunk-AUSDBXUD.js → chunk-TY6AGA4P.js} +2 -2
- package/dist/chunks/{compile-vercel-config-ZVY7LBE3.js → compile-vercel-config-OLTGIW27.js} +1 -1
- package/dist/chunks/{delete-SKTJMJNP.js → delete-XAYXXDEB.js} +2 -2
- package/dist/chunks/{disable-AG7I6DPV.js → disable-PNN5ZWF4.js} +2 -2
- package/dist/chunks/{discard-LUK6LBLT.js → discard-QUK6T2AQ.js} +2 -2
- package/dist/chunks/{edit-3BR5HP3U.js → edit-D2OHUFQ6.js} +3 -3
- package/dist/chunks/{enable-4JNLOKSM.js → enable-SJV7HD2Y.js} +2 -2
- package/dist/chunks/{export-YLZ6QSHG.js → export-SN3F75NH.js} +2 -2
- package/dist/chunks/{inspect-HUJLUQAV.js → inspect-C2ZW7BZA.js} +3 -3
- package/dist/chunks/{list-EPU4SB3E.js → list-2DKITLDE.js} +2 -2
- package/dist/chunks/{list-RMA56KYZ.js → list-EUXU6BVD.js} +3 -3
- package/dist/chunks/{ls-7HHDYE6F.js → ls-7R3DRCUY.js} +4 -4
- package/dist/chunks/{publish-6YE4OUDI.js → publish-HNGKZNDH.js} +2 -2
- package/dist/chunks/{query-X6Q4ZSZO.js → query-G4SY7VMM.js} +2 -2
- package/dist/chunks/{reorder-VFM23ESC.js → reorder-Q2LYGVZK.js} +2 -2
- package/dist/chunks/{restore-VX34SXVF.js → restore-YJUUQLZG.js} +2 -2
- package/dist/chunks/{rm-5KXF2PY3.js → rm-XEV4FF6H.js} +4 -4
- package/dist/chunks/{rule-inspect-JG7AE5TI.js → rule-inspect-JNZMBVJF.js} +4 -4
- package/dist/chunks/{rules-XRJBT22L.js → rules-5PJVEET5.js} +6 -6
- package/dist/chunks/{schema-IMD4VV73.js → schema-OU7FKPQZ.js} +2 -2
- package/dist/chunks/{update-4FMWTIJK.js → update-6LXBPVBH.js} +4 -4
- package/dist/commands/build/index.js +13 -13
- package/dist/commands/deploy/index.js +13 -14
- package/dist/commands/dev/index.js +8 -8
- package/dist/commands/env/index.js +25 -11
- package/dist/commands/link/index.js +11 -11
- package/dist/commands/list/index.js +3 -3
- package/dist/commands-bulk.js +70 -51
- package/dist/index.js +10 -10
- package/dist/version.mjs +1 -1
- package/package.json +16 -16
- package/dist/chunks/chunk-O7SQKNIT.js +0 -247
- package/dist/chunks/chunk-RJD5NYGF.js +0 -149
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
handleRulesApiError,
|
|
10
10
|
parseRulesFlagsAndScope,
|
|
11
11
|
rulesCollectionPath
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-T7LHO6SF.js";
|
|
13
|
+
import "./chunk-KNZNWP2U.js";
|
|
14
14
|
import "./chunk-HTOH3MSD.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-EQIXUYBY.js";
|
|
16
16
|
import {
|
|
17
17
|
validateJsonOutput
|
|
18
18
|
} from "./chunk-XPKWKPWA.js";
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
import {
|
|
23
23
|
AGENT_REASON
|
|
24
24
|
} from "./chunk-E3NE4SKN.js";
|
|
25
|
-
import "./chunk-
|
|
25
|
+
import "./chunk-P445TBWL.js";
|
|
26
26
|
import "./chunk-U3WLEFHU.js";
|
|
27
27
|
import {
|
|
28
28
|
buildCommandWithGlobalFlags,
|
|
@@ -0,0 +1,692 @@
|
|
|
1
|
+
import { createRequire as __createRequire } from 'node:module';
|
|
2
|
+
import { fileURLToPath as __fileURLToPath } from 'node:url';
|
|
3
|
+
import { dirname as __dirname_ } from 'node:path';
|
|
4
|
+
const require = __createRequire(import.meta.url);
|
|
5
|
+
const __filename = __fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = __dirname_(__filename);
|
|
7
|
+
import {
|
|
8
|
+
AGENT_ACTION
|
|
9
|
+
} from "./chunk-E3NE4SKN.js";
|
|
10
|
+
import {
|
|
11
|
+
getEnvTargetPlaceholder,
|
|
12
|
+
global_path_default
|
|
13
|
+
} from "./chunk-P445TBWL.js";
|
|
14
|
+
import {
|
|
15
|
+
yesOption
|
|
16
|
+
} from "./chunk-RFMC2QXQ.js";
|
|
17
|
+
import {
|
|
18
|
+
packageName
|
|
19
|
+
} from "./chunk-ECRBC4HL.js";
|
|
20
|
+
import {
|
|
21
|
+
output_manager_default
|
|
22
|
+
} from "./chunk-ZQKJVHXY.js";
|
|
23
|
+
import {
|
|
24
|
+
require_source
|
|
25
|
+
} from "./chunk-S7KYDPEM.js";
|
|
26
|
+
import {
|
|
27
|
+
__toESM
|
|
28
|
+
} from "./chunk-TZ2YI2VH.js";
|
|
29
|
+
|
|
30
|
+
// src/commands/build/command.ts
|
|
31
|
+
var buildCommand = {
|
|
32
|
+
name: "build",
|
|
33
|
+
aliases: [],
|
|
34
|
+
description: "Build the project.",
|
|
35
|
+
arguments: [],
|
|
36
|
+
options: [
|
|
37
|
+
{
|
|
38
|
+
name: "prod",
|
|
39
|
+
description: "Build a production deployment",
|
|
40
|
+
shorthand: null,
|
|
41
|
+
type: Boolean,
|
|
42
|
+
deprecated: false
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: "target",
|
|
46
|
+
shorthand: null,
|
|
47
|
+
type: String,
|
|
48
|
+
argument: "TARGET",
|
|
49
|
+
deprecated: false,
|
|
50
|
+
description: "Specify the target environment"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "output",
|
|
54
|
+
description: "Directory where built assets will be written to",
|
|
55
|
+
shorthand: null,
|
|
56
|
+
argument: "DIR",
|
|
57
|
+
type: String,
|
|
58
|
+
deprecated: false
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
...yesOption,
|
|
62
|
+
description: "Skip the confirmation prompt about pulling environment variables and project settings when not found locally"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "standalone",
|
|
66
|
+
description: "Create a standalone build with all dependencies inlined into function output folders",
|
|
67
|
+
shorthand: null,
|
|
68
|
+
type: Boolean,
|
|
69
|
+
deprecated: false
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: "id",
|
|
73
|
+
description: "Deployment ID to pull environment variables from (e.g. dpl_xxx)",
|
|
74
|
+
shorthand: null,
|
|
75
|
+
type: String,
|
|
76
|
+
argument: "ID",
|
|
77
|
+
deprecated: false
|
|
78
|
+
}
|
|
79
|
+
],
|
|
80
|
+
examples: [
|
|
81
|
+
{
|
|
82
|
+
name: "Build the project",
|
|
83
|
+
value: `${packageName} build`
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: "Build the project in a specific directory",
|
|
87
|
+
value: `${packageName} build --cwd ./path-to-project`
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: "Build with deployment-scoped environment variables",
|
|
91
|
+
value: `${packageName} build --id dpl_xxx`
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// src/util/agent/auto-install-agentic.ts
|
|
97
|
+
var import_chalk = __toESM(require_source(), 1);
|
|
98
|
+
import { readFile, writeFile } from "fs/promises";
|
|
99
|
+
import { access } from "fs/promises";
|
|
100
|
+
import { join } from "path";
|
|
101
|
+
import { homedir } from "os";
|
|
102
|
+
import { spawn } from "child_process";
|
|
103
|
+
import { KNOWN_AGENTS } from "@vercel/detect-agent";
|
|
104
|
+
var PREFS_FILE = "agent-preferences.json";
|
|
105
|
+
var CLAUDE_LEGACY_PLUGIN_ID = "vercel-plugin@vercel";
|
|
106
|
+
var CLAUDE_OFFICIAL_PLUGIN_ID = "vercel@claude-plugins-official";
|
|
107
|
+
var VERCEL_PLUGIN_VERSION_URL = "https://raw.githubusercontent.com/vercel/vercel-plugin/main/.claude-plugin/plugin.json";
|
|
108
|
+
var AGENT_TO_TARGET = {
|
|
109
|
+
[KNOWN_AGENTS.CLAUDE]: "claude-code",
|
|
110
|
+
[KNOWN_AGENTS.COWORK]: "claude-code"
|
|
111
|
+
};
|
|
112
|
+
function getPluginTargetForAgent(agentName) {
|
|
113
|
+
if (!agentName) {
|
|
114
|
+
return void 0;
|
|
115
|
+
}
|
|
116
|
+
return AGENT_TO_TARGET[agentName];
|
|
117
|
+
}
|
|
118
|
+
async function fileExists(filePath) {
|
|
119
|
+
try {
|
|
120
|
+
await access(filePath);
|
|
121
|
+
return true;
|
|
122
|
+
} catch {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async function readPrefs() {
|
|
127
|
+
try {
|
|
128
|
+
const raw = await readFile(
|
|
129
|
+
join(global_path_default(), PREFS_FILE),
|
|
130
|
+
"utf-8"
|
|
131
|
+
);
|
|
132
|
+
return JSON.parse(raw);
|
|
133
|
+
} catch {
|
|
134
|
+
return {};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
async function writePrefs(prefs) {
|
|
138
|
+
try {
|
|
139
|
+
const normalizedPrefs = {};
|
|
140
|
+
if (prefs.pluginDeclined) {
|
|
141
|
+
normalizedPrefs.pluginDeclined = true;
|
|
142
|
+
}
|
|
143
|
+
if (prefs.lastPromptedAt) {
|
|
144
|
+
normalizedPrefs.lastPromptedAt = prefs.lastPromptedAt;
|
|
145
|
+
}
|
|
146
|
+
await writeFile(
|
|
147
|
+
join(global_path_default(), PREFS_FILE),
|
|
148
|
+
JSON.stringify(normalizedPrefs, null, 2),
|
|
149
|
+
"utf-8"
|
|
150
|
+
);
|
|
151
|
+
} catch {
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
async function getPluginTargets(agentName) {
|
|
155
|
+
const targetForAgent = getPluginTargetForAgent(agentName);
|
|
156
|
+
if (targetForAgent) {
|
|
157
|
+
return [targetForAgent];
|
|
158
|
+
}
|
|
159
|
+
if (agentName) {
|
|
160
|
+
return [];
|
|
161
|
+
}
|
|
162
|
+
const home = homedir();
|
|
163
|
+
const targets = [];
|
|
164
|
+
if (await fileExists(join(home, ".claude"))) {
|
|
165
|
+
targets.push("claude-code");
|
|
166
|
+
}
|
|
167
|
+
return targets;
|
|
168
|
+
}
|
|
169
|
+
async function readClaudeInstalledPluginsFromRegistry() {
|
|
170
|
+
try {
|
|
171
|
+
const raw = await readFile(
|
|
172
|
+
join(homedir(), ".claude", "plugins", "installed_plugins.json"),
|
|
173
|
+
"utf-8"
|
|
174
|
+
);
|
|
175
|
+
const data = JSON.parse(raw);
|
|
176
|
+
const plugins = data?.plugins ?? {};
|
|
177
|
+
const entries = [];
|
|
178
|
+
for (const [id, installs] of Object.entries(plugins)) {
|
|
179
|
+
if (!Array.isArray(installs))
|
|
180
|
+
continue;
|
|
181
|
+
for (const install of installs) {
|
|
182
|
+
if (!install || typeof install !== "object")
|
|
183
|
+
continue;
|
|
184
|
+
entries.push({
|
|
185
|
+
id,
|
|
186
|
+
...install,
|
|
187
|
+
enabled: true
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return entries;
|
|
192
|
+
} catch {
|
|
193
|
+
return [];
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
async function isPluginInstalledForTarget(target) {
|
|
197
|
+
if (target === "claude-code") {
|
|
198
|
+
const status = await getClaudePluginStatus();
|
|
199
|
+
return status.state === "official-only";
|
|
200
|
+
}
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
async function confirm(client, message) {
|
|
204
|
+
if (!client.stdin.isTTY) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
return client.input.confirm(message, true);
|
|
208
|
+
}
|
|
209
|
+
function getTodayKey() {
|
|
210
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
211
|
+
}
|
|
212
|
+
function wasPromptedToday(prefs) {
|
|
213
|
+
return prefs.lastPromptedAt === getTodayKey();
|
|
214
|
+
}
|
|
215
|
+
async function markPromptedToday(prefs) {
|
|
216
|
+
prefs.lastPromptedAt = getTodayKey();
|
|
217
|
+
await writePrefs(prefs);
|
|
218
|
+
}
|
|
219
|
+
async function runCommand(command, args) {
|
|
220
|
+
return await new Promise((resolve) => {
|
|
221
|
+
const child = spawn(command, args, { stdio: "pipe" });
|
|
222
|
+
let stdout = "";
|
|
223
|
+
let stderr = "";
|
|
224
|
+
child.stdout.on("data", (chunk) => {
|
|
225
|
+
stdout += chunk.toString();
|
|
226
|
+
});
|
|
227
|
+
child.stderr.on("data", (chunk) => {
|
|
228
|
+
stderr += chunk.toString();
|
|
229
|
+
});
|
|
230
|
+
child.on("close", (code) => {
|
|
231
|
+
resolve({ exitCode: code ?? 1, stdout, stderr });
|
|
232
|
+
});
|
|
233
|
+
child.on("error", (err) => {
|
|
234
|
+
resolve({ exitCode: 1, stdout, stderr: `${stderr}${String(err)}` });
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
async function getClaudeInstalledPlugins() {
|
|
239
|
+
const result = await runCommand("claude", ["plugins", "list", "--json"]);
|
|
240
|
+
if (result.exitCode === 0) {
|
|
241
|
+
try {
|
|
242
|
+
const parsed = JSON.parse(result.stdout);
|
|
243
|
+
if (Array.isArray(parsed)) {
|
|
244
|
+
return parsed;
|
|
245
|
+
}
|
|
246
|
+
} catch (err) {
|
|
247
|
+
output_manager_default.debug(`Failed to parse Claude plugin list JSON: ${err}`);
|
|
248
|
+
}
|
|
249
|
+
} else if (result.stderr.trim().length > 0) {
|
|
250
|
+
output_manager_default.debug(
|
|
251
|
+
`Failed to run 'claude plugins list --json': ${result.stderr}`
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
return readClaudeInstalledPluginsFromRegistry();
|
|
255
|
+
}
|
|
256
|
+
async function fetchLatestVercelPluginVersion() {
|
|
257
|
+
try {
|
|
258
|
+
const response = await fetch(VERCEL_PLUGIN_VERSION_URL);
|
|
259
|
+
if (!response.ok) {
|
|
260
|
+
output_manager_default.debug(
|
|
261
|
+
`Failed to fetch latest Vercel plugin version: ${response.status}`
|
|
262
|
+
);
|
|
263
|
+
return void 0;
|
|
264
|
+
}
|
|
265
|
+
const manifest = await response.json();
|
|
266
|
+
return typeof manifest.version === "string" ? manifest.version : void 0;
|
|
267
|
+
} catch (err) {
|
|
268
|
+
output_manager_default.debug(`Failed to fetch latest Vercel plugin version: ${err}`);
|
|
269
|
+
return void 0;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function comparePluginVersions(a, b) {
|
|
273
|
+
if (!a && !b)
|
|
274
|
+
return 0;
|
|
275
|
+
if (!a)
|
|
276
|
+
return -1;
|
|
277
|
+
if (!b)
|
|
278
|
+
return 1;
|
|
279
|
+
const parse = (value) => value.split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
280
|
+
const left = parse(a);
|
|
281
|
+
const right = parse(b);
|
|
282
|
+
const maxLength = Math.max(left.length, right.length);
|
|
283
|
+
for (let i = 0; i < maxLength; i++) {
|
|
284
|
+
const l = left[i] ?? 0;
|
|
285
|
+
const r = right[i] ?? 0;
|
|
286
|
+
if (l > r)
|
|
287
|
+
return 1;
|
|
288
|
+
if (l < r)
|
|
289
|
+
return -1;
|
|
290
|
+
}
|
|
291
|
+
return 0;
|
|
292
|
+
}
|
|
293
|
+
function buildClaudePluginStatus(installedPlugins, latestVersion) {
|
|
294
|
+
const legacy = installedPlugins.find(
|
|
295
|
+
(plugin) => plugin.id === CLAUDE_LEGACY_PLUGIN_ID
|
|
296
|
+
);
|
|
297
|
+
const official = installedPlugins.find(
|
|
298
|
+
(plugin) => plugin.id === CLAUDE_OFFICIAL_PLUGIN_ID
|
|
299
|
+
);
|
|
300
|
+
let state = "none";
|
|
301
|
+
if (legacy && official)
|
|
302
|
+
state = "both";
|
|
303
|
+
else if (legacy)
|
|
304
|
+
state = "legacy-only";
|
|
305
|
+
else if (official)
|
|
306
|
+
state = "official-only";
|
|
307
|
+
return {
|
|
308
|
+
state,
|
|
309
|
+
legacy,
|
|
310
|
+
official,
|
|
311
|
+
latestVersion
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
function buildClaudePluginMigrationPlan(status) {
|
|
315
|
+
const plan = {
|
|
316
|
+
installOfficial: false,
|
|
317
|
+
updateOfficial: false,
|
|
318
|
+
removeLegacy: false,
|
|
319
|
+
removeLegacyMarketplace: false
|
|
320
|
+
};
|
|
321
|
+
switch (status.state) {
|
|
322
|
+
case "none":
|
|
323
|
+
plan.installOfficial = true;
|
|
324
|
+
break;
|
|
325
|
+
case "legacy-only":
|
|
326
|
+
plan.installOfficial = true;
|
|
327
|
+
plan.removeLegacy = true;
|
|
328
|
+
plan.removeLegacyMarketplace = true;
|
|
329
|
+
break;
|
|
330
|
+
case "both":
|
|
331
|
+
plan.removeLegacy = true;
|
|
332
|
+
plan.removeLegacyMarketplace = true;
|
|
333
|
+
break;
|
|
334
|
+
case "official-only":
|
|
335
|
+
break;
|
|
336
|
+
}
|
|
337
|
+
if (status.official?.version && status.latestVersion && comparePluginVersions(status.official.version, status.latestVersion) < 0) {
|
|
338
|
+
plan.updateOfficial = true;
|
|
339
|
+
}
|
|
340
|
+
return plan;
|
|
341
|
+
}
|
|
342
|
+
function hasClaudeMigrationActions(plan) {
|
|
343
|
+
return plan.installOfficial || plan.updateOfficial || plan.removeLegacy || plan.removeLegacyMarketplace;
|
|
344
|
+
}
|
|
345
|
+
function buildClaudePromptCopy(status, plan) {
|
|
346
|
+
if (plan.installOfficial && status.state === "none") {
|
|
347
|
+
return {
|
|
348
|
+
message: "",
|
|
349
|
+
confirm: "Working with Vercel is easier with the Vercel Plugin for Claude Code. Would you like to install it?"
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
if (plan.installOfficial && status.state === "legacy-only") {
|
|
353
|
+
return {
|
|
354
|
+
message: "",
|
|
355
|
+
confirm: "Working with Vercel is easier with the latest Vercel Plugin for Claude Code. Would you like to update it?"
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
if (status.state === "both" && plan.removeLegacy) {
|
|
359
|
+
return {
|
|
360
|
+
message: "",
|
|
361
|
+
confirm: "Working with Vercel is easier with the latest Vercel Plugin for Claude Code. Would you like to update it?"
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
if (plan.updateOfficial) {
|
|
365
|
+
const fromVersion = status.official?.version ?? "your current version";
|
|
366
|
+
const toVersion = status.latestVersion ?? "the latest version";
|
|
367
|
+
return {
|
|
368
|
+
message: "",
|
|
369
|
+
confirm: `Working with Vercel is easier with the latest Vercel Plugin for Claude Code. Would you like to update from ${fromVersion} to ${toVersion}?`
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
return {
|
|
373
|
+
message: "The Vercel plugin needs attention in Claude Code before your agent harness is fully up to date.",
|
|
374
|
+
confirm: "Apply the Vercel plugin changes for Claude Code?"
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
function buildClaudeActionRequiredMessage(status, plan) {
|
|
378
|
+
if (status.state === "legacy-only") {
|
|
379
|
+
return `Working with Vercel is easier with the latest Vercel Plugin for Claude Code. It will run:
|
|
380
|
+
1. claude plugins install ${CLAUDE_OFFICIAL_PLUGIN_ID}
|
|
381
|
+
2. claude plugins uninstall ${CLAUDE_LEGACY_PLUGIN_ID}
|
|
382
|
+
Would you like me to update it?`;
|
|
383
|
+
}
|
|
384
|
+
if (status.state === "both" || plan.removeLegacy) {
|
|
385
|
+
return `Working with Vercel is easier with the latest Vercel Plugin for Claude Code. It will run:
|
|
386
|
+
1. claude plugins uninstall ${CLAUDE_LEGACY_PLUGIN_ID}
|
|
387
|
+
Would you like me to update it?`;
|
|
388
|
+
}
|
|
389
|
+
if (plan.updateOfficial) {
|
|
390
|
+
return `Working with Vercel is easier with the latest Vercel Plugin for Claude Code. It will run:
|
|
391
|
+
1. claude plugins update ${CLAUDE_OFFICIAL_PLUGIN_ID}
|
|
392
|
+
Would you like me to update it?`;
|
|
393
|
+
}
|
|
394
|
+
return `Working with Vercel is easier with the Vercel Plugin for Claude Code. It will run:
|
|
395
|
+
1. claude plugins install ${CLAUDE_OFFICIAL_PLUGIN_ID}
|
|
396
|
+
Would you like me to install it?`;
|
|
397
|
+
}
|
|
398
|
+
function buildClaudeActionRequiredLabel(status, plan) {
|
|
399
|
+
if (status.state === "legacy-only" || status.state === "both" || plan.removeLegacy || plan.updateOfficial) {
|
|
400
|
+
return "Update it";
|
|
401
|
+
}
|
|
402
|
+
return "Install it";
|
|
403
|
+
}
|
|
404
|
+
function getClaudeActionRequiredCommand(status, plan) {
|
|
405
|
+
if (plan.installOfficial && status.state === "none") {
|
|
406
|
+
return `claude plugins install ${CLAUDE_OFFICIAL_PLUGIN_ID}`;
|
|
407
|
+
}
|
|
408
|
+
if (status.state === "both" && plan.removeLegacy) {
|
|
409
|
+
return `claude plugins uninstall ${CLAUDE_LEGACY_PLUGIN_ID}`;
|
|
410
|
+
}
|
|
411
|
+
if (plan.updateOfficial && status.state === "official-only") {
|
|
412
|
+
return `claude plugins update ${CLAUDE_OFFICIAL_PLUGIN_ID}`;
|
|
413
|
+
}
|
|
414
|
+
return `claude plugins install ${CLAUDE_OFFICIAL_PLUGIN_ID}`;
|
|
415
|
+
}
|
|
416
|
+
function getClaudeActionRequiredNextSteps(status, plan) {
|
|
417
|
+
const next = [
|
|
418
|
+
{
|
|
419
|
+
command: getClaudeActionRequiredCommand(status, plan),
|
|
420
|
+
when: buildClaudeActionRequiredLabel(status, plan)
|
|
421
|
+
}
|
|
422
|
+
];
|
|
423
|
+
if (status.state === "legacy-only" && plan.removeLegacy) {
|
|
424
|
+
next.push({
|
|
425
|
+
command: `claude plugins uninstall ${CLAUDE_LEGACY_PLUGIN_ID}`,
|
|
426
|
+
when: "Remove the old plugin after the update"
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
return next;
|
|
430
|
+
}
|
|
431
|
+
async function runClaudeCommand(spinnerMessage, successMessage, failureMessage, args, options) {
|
|
432
|
+
output_manager_default.spinner(spinnerMessage);
|
|
433
|
+
const result = await runCommand("claude", args);
|
|
434
|
+
output_manager_default.stopSpinner();
|
|
435
|
+
if (result.exitCode === 0) {
|
|
436
|
+
if (!options?.quietSuccess) {
|
|
437
|
+
output_manager_default.success(successMessage);
|
|
438
|
+
}
|
|
439
|
+
return true;
|
|
440
|
+
}
|
|
441
|
+
output_manager_default.warn(failureMessage);
|
|
442
|
+
output_manager_default.debug(
|
|
443
|
+
`Claude command failed: claude ${args.join(" ")}
|
|
444
|
+
${result.stderr || result.stdout}`
|
|
445
|
+
);
|
|
446
|
+
return false;
|
|
447
|
+
}
|
|
448
|
+
async function runClaudeMigration(plan) {
|
|
449
|
+
if (plan.installOfficial) {
|
|
450
|
+
const installed = await runClaudeCommand(
|
|
451
|
+
"Installing the official Vercel Claude plugin...",
|
|
452
|
+
"Updated the Vercel plugin",
|
|
453
|
+
"Failed to install the official Vercel Claude plugin.",
|
|
454
|
+
["plugins", "install", CLAUDE_OFFICIAL_PLUGIN_ID]
|
|
455
|
+
);
|
|
456
|
+
if (!installed) {
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
} else if (plan.updateOfficial) {
|
|
460
|
+
await runClaudeCommand(
|
|
461
|
+
"Updating the official Vercel Claude plugin...",
|
|
462
|
+
"Updated the Vercel plugin",
|
|
463
|
+
"Failed to update the official Vercel Claude plugin.",
|
|
464
|
+
["plugins", "update", CLAUDE_OFFICIAL_PLUGIN_ID]
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
const statusAfterInstall = await getClaudePluginStatus();
|
|
468
|
+
if (!statusAfterInstall.official) {
|
|
469
|
+
output_manager_default.warn(
|
|
470
|
+
"Skipping Claude cleanup because the official Vercel plugin is not installed."
|
|
471
|
+
);
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
if (plan.removeLegacy && statusAfterInstall.legacy) {
|
|
475
|
+
const removedLegacy = await runClaudeCommand(
|
|
476
|
+
"Removing the legacy Vercel Claude plugin...",
|
|
477
|
+
"Removed the legacy Vercel Claude plugin",
|
|
478
|
+
"Installed the official Vercel Claude plugin, but could not remove the legacy install.",
|
|
479
|
+
["plugins", "uninstall", CLAUDE_LEGACY_PLUGIN_ID],
|
|
480
|
+
{ quietSuccess: true }
|
|
481
|
+
);
|
|
482
|
+
if (!removedLegacy) {
|
|
483
|
+
output_manager_default.log(
|
|
484
|
+
`Cleanup command: claude plugins uninstall ${CLAUDE_LEGACY_PLUGIN_ID}`
|
|
485
|
+
);
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
if (plan.removeLegacyMarketplace) {
|
|
490
|
+
const finalStatus = await getClaudePluginStatus();
|
|
491
|
+
if (!finalStatus.legacy) {
|
|
492
|
+
const removedMarketplace = await runClaudeCommand(
|
|
493
|
+
"Removing the legacy Vercel marketplace...",
|
|
494
|
+
"Removed the legacy Vercel marketplace",
|
|
495
|
+
"Removed the legacy Vercel plugin, but could not remove the legacy marketplace.",
|
|
496
|
+
["plugins", "marketplace", "remove", "vercel"],
|
|
497
|
+
{ quietSuccess: true }
|
|
498
|
+
);
|
|
499
|
+
if (!removedMarketplace) {
|
|
500
|
+
output_manager_default.log("Cleanup command: claude plugins marketplace remove vercel");
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
async function getClaudePluginStatus() {
|
|
506
|
+
const [installedPlugins, latestVersion] = await Promise.all([
|
|
507
|
+
getClaudeInstalledPlugins(),
|
|
508
|
+
fetchLatestVercelPluginVersion()
|
|
509
|
+
]);
|
|
510
|
+
return buildClaudePluginStatus(installedPlugins, latestVersion);
|
|
511
|
+
}
|
|
512
|
+
async function applyPluginActions(targets, claudePlan) {
|
|
513
|
+
for (const target of targets) {
|
|
514
|
+
if (target === "claude-code" && claudePlan) {
|
|
515
|
+
await runClaudeMigration(claudePlan);
|
|
516
|
+
} else {
|
|
517
|
+
output_manager_default.debug(`Skipping unsupported plugin target: ${target}`);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
async function autoInstallVercelPlugin(client, options) {
|
|
522
|
+
try {
|
|
523
|
+
const prefs = await readPrefs();
|
|
524
|
+
const applyMode = options?.mode === "apply";
|
|
525
|
+
if (!prefs.pluginDeclined || applyMode) {
|
|
526
|
+
const targets = await getPluginTargets(client.agentName);
|
|
527
|
+
const uninstalledTargets = [];
|
|
528
|
+
const claudeStatus = targets.includes("claude-code") ? await getClaudePluginStatus() : void 0;
|
|
529
|
+
const claudePlan = claudeStatus ? buildClaudePluginMigrationPlan(claudeStatus) : void 0;
|
|
530
|
+
for (const target of targets) {
|
|
531
|
+
if (target === "claude-code") {
|
|
532
|
+
if (claudePlan && hasClaudeMigrationActions(claudePlan)) {
|
|
533
|
+
uninstalledTargets.push(target);
|
|
534
|
+
}
|
|
535
|
+
continue;
|
|
536
|
+
}
|
|
537
|
+
if (!await isPluginInstalledForTarget(target)) {
|
|
538
|
+
uninstalledTargets.push(target);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
if (uninstalledTargets.length > 0) {
|
|
542
|
+
if (!applyMode && wasPromptedToday(prefs)) {
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
if (applyMode) {
|
|
546
|
+
prefs.pluginDeclined = false;
|
|
547
|
+
await writePrefs(prefs);
|
|
548
|
+
await applyPluginActions(uninstalledTargets, claudePlan);
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
const promptMessages = [];
|
|
552
|
+
let confirmMessage = "Install the Vercel plugin?";
|
|
553
|
+
if (uninstalledTargets.includes("claude-code") && claudeStatus && claudePlan) {
|
|
554
|
+
const claudePrompt = buildClaudePromptCopy(claudeStatus, claudePlan);
|
|
555
|
+
promptMessages.push(claudePrompt.message);
|
|
556
|
+
confirmMessage = claudePrompt.confirm;
|
|
557
|
+
}
|
|
558
|
+
if (client.isAgent && !client.stdin.isTTY) {
|
|
559
|
+
const actionRequiredMessage = uninstalledTargets.includes("claude-code") && claudeStatus && claudePlan ? buildClaudeActionRequiredMessage(claudeStatus, claudePlan) : promptMessages.join(" ");
|
|
560
|
+
const next = uninstalledTargets.includes("claude-code") && claudeStatus && claudePlan ? getClaudeActionRequiredNextSteps(claudeStatus, claudePlan) : [
|
|
561
|
+
{
|
|
562
|
+
command: `claude plugins install ${CLAUDE_OFFICIAL_PLUGIN_ID}`,
|
|
563
|
+
when: "Install it"
|
|
564
|
+
}
|
|
565
|
+
];
|
|
566
|
+
client.stdout.write(
|
|
567
|
+
`${JSON.stringify(
|
|
568
|
+
{
|
|
569
|
+
status: "action_required",
|
|
570
|
+
reason: "plugin_install",
|
|
571
|
+
action: AGENT_ACTION.CONFIRMATION_REQUIRED,
|
|
572
|
+
message: actionRequiredMessage,
|
|
573
|
+
userActionRequired: true,
|
|
574
|
+
next
|
|
575
|
+
},
|
|
576
|
+
null,
|
|
577
|
+
2
|
|
578
|
+
)}
|
|
579
|
+
`
|
|
580
|
+
);
|
|
581
|
+
await markPromptedToday(prefs);
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
const promptMessage = promptMessages.join(" ").trim();
|
|
585
|
+
if (promptMessage) {
|
|
586
|
+
output_manager_default.log(promptMessage);
|
|
587
|
+
}
|
|
588
|
+
const accepted = await confirm(client, confirmMessage);
|
|
589
|
+
await markPromptedToday(prefs);
|
|
590
|
+
if (accepted) {
|
|
591
|
+
prefs.pluginDeclined = false;
|
|
592
|
+
await writePrefs(prefs);
|
|
593
|
+
await applyPluginActions(uninstalledTargets, claudePlan);
|
|
594
|
+
} else {
|
|
595
|
+
prefs.pluginDeclined = true;
|
|
596
|
+
await writePrefs(prefs);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
} catch (err) {
|
|
601
|
+
output_manager_default.debug(`Auto-install agent tooling failed: ${err}`);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
async function showPluginTipIfNeeded() {
|
|
605
|
+
try {
|
|
606
|
+
const prefs = await readPrefs();
|
|
607
|
+
if (prefs.pluginDeclined)
|
|
608
|
+
return;
|
|
609
|
+
const targets = await getPluginTargets();
|
|
610
|
+
for (const target of targets) {
|
|
611
|
+
if (!await isPluginInstalledForTarget(target)) {
|
|
612
|
+
output_manager_default.log(
|
|
613
|
+
import_chalk.default.dim(
|
|
614
|
+
"Tip: Run `npx plugins add vercel/vercel-plugin` to enhance your agent experience"
|
|
615
|
+
)
|
|
616
|
+
);
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
} catch {
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// src/commands/pull/command.ts
|
|
625
|
+
var pullCommand = {
|
|
626
|
+
name: "pull",
|
|
627
|
+
aliases: [],
|
|
628
|
+
description: "Pull latest environment variables and project settings from Vercel. ",
|
|
629
|
+
arguments: [
|
|
630
|
+
{
|
|
631
|
+
name: "project-path",
|
|
632
|
+
required: false
|
|
633
|
+
}
|
|
634
|
+
],
|
|
635
|
+
options: [
|
|
636
|
+
{
|
|
637
|
+
name: "environment",
|
|
638
|
+
description: "Deployment environment [development]",
|
|
639
|
+
argument: "TARGET",
|
|
640
|
+
shorthand: null,
|
|
641
|
+
type: String,
|
|
642
|
+
deprecated: false
|
|
643
|
+
},
|
|
644
|
+
{
|
|
645
|
+
name: "git-branch",
|
|
646
|
+
description: "Specify the Git branch to pull specific Environment Variables for",
|
|
647
|
+
argument: "NAME",
|
|
648
|
+
shorthand: null,
|
|
649
|
+
type: String,
|
|
650
|
+
deprecated: false
|
|
651
|
+
},
|
|
652
|
+
{
|
|
653
|
+
name: "prod",
|
|
654
|
+
shorthand: null,
|
|
655
|
+
type: Boolean,
|
|
656
|
+
deprecated: false
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
...yesOption,
|
|
660
|
+
description: "Skip questions when setting up new project using default scope and settings"
|
|
661
|
+
}
|
|
662
|
+
],
|
|
663
|
+
examples: [
|
|
664
|
+
{
|
|
665
|
+
name: "Pull the latest Environment Variables and Project Settings from the cloud",
|
|
666
|
+
value: `${packageName} pull`
|
|
667
|
+
},
|
|
668
|
+
{
|
|
669
|
+
name: "Pull the latest Environment Variables and Project Settings from the cloud targeting a directory",
|
|
670
|
+
value: `${packageName} pull ./path-to-project`
|
|
671
|
+
},
|
|
672
|
+
{
|
|
673
|
+
name: "Pull for a specific environment",
|
|
674
|
+
value: `${packageName} pull --environment=${getEnvTargetPlaceholder()}`
|
|
675
|
+
},
|
|
676
|
+
{
|
|
677
|
+
name: "Pull for a preview feature branch",
|
|
678
|
+
value: `${packageName} pull --environment=preview --git-branch=feature-branch`
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
name: "If you want to download environment variables to a specific file, use `vercel env pull` instead",
|
|
682
|
+
value: `${packageName} env pull`
|
|
683
|
+
}
|
|
684
|
+
]
|
|
685
|
+
};
|
|
686
|
+
|
|
687
|
+
export {
|
|
688
|
+
buildCommand,
|
|
689
|
+
pullCommand,
|
|
690
|
+
autoInstallVercelPlugin,
|
|
691
|
+
showPluginTipIfNeeded
|
|
692
|
+
};
|