@polpo-ai/cli 0.6.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.
Files changed (68) hide show
  1. package/LICENSE +13 -0
  2. package/dist/commands/cloud/api.js +32 -0
  3. package/dist/commands/cloud/api.js.map +1 -0
  4. package/dist/commands/cloud/byok.js +125 -0
  5. package/dist/commands/cloud/byok.js.map +1 -0
  6. package/dist/commands/cloud/config.js +42 -0
  7. package/dist/commands/cloud/config.js.map +1 -0
  8. package/dist/commands/cloud/deploy.js +752 -0
  9. package/dist/commands/cloud/deploy.js.map +1 -0
  10. package/dist/commands/cloud/login.js +99 -0
  11. package/dist/commands/cloud/login.js.map +1 -0
  12. package/dist/commands/cloud/logout.js +11 -0
  13. package/dist/commands/cloud/logout.js.map +1 -0
  14. package/dist/commands/cloud/logs.js +114 -0
  15. package/dist/commands/cloud/logs.js.map +1 -0
  16. package/dist/commands/cloud/project-context.js +17 -0
  17. package/dist/commands/cloud/project-context.js.map +1 -0
  18. package/dist/commands/cloud/projects.js +95 -0
  19. package/dist/commands/cloud/projects.js.map +1 -0
  20. package/dist/commands/cloud/prompt.js +74 -0
  21. package/dist/commands/cloud/prompt.js.map +1 -0
  22. package/dist/commands/cloud/status.js +84 -0
  23. package/dist/commands/cloud/status.js.map +1 -0
  24. package/dist/commands/create.js +286 -0
  25. package/dist/commands/create.js.map +1 -0
  26. package/dist/commands/link.js +71 -0
  27. package/dist/commands/link.js.map +1 -0
  28. package/dist/commands/models.js +60 -0
  29. package/dist/commands/models.js.map +1 -0
  30. package/dist/commands/orgs.js +42 -0
  31. package/dist/commands/orgs.js.map +1 -0
  32. package/dist/commands/update.js +95 -0
  33. package/dist/commands/update.js.map +1 -0
  34. package/dist/commands/whoami.js +62 -0
  35. package/dist/commands/whoami.js.map +1 -0
  36. package/dist/index.js +138 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/interactive-menu.js +111 -0
  39. package/dist/interactive-menu.js.map +1 -0
  40. package/dist/update-check.js +106 -0
  41. package/dist/update-check.js.map +1 -0
  42. package/dist/util/api-keys.js +21 -0
  43. package/dist/util/api-keys.js.map +1 -0
  44. package/dist/util/auth.js +71 -0
  45. package/dist/util/auth.js.map +1 -0
  46. package/dist/util/base-url.js +43 -0
  47. package/dist/util/base-url.js.map +1 -0
  48. package/dist/util/browser.js +20 -0
  49. package/dist/util/browser.js.map +1 -0
  50. package/dist/util/device-code.js +103 -0
  51. package/dist/util/device-code.js.map +1 -0
  52. package/dist/util/errors.js +13 -0
  53. package/dist/util/errors.js.map +1 -0
  54. package/dist/util/install-cli.js +68 -0
  55. package/dist/util/install-cli.js.map +1 -0
  56. package/dist/util/org.js +53 -0
  57. package/dist/util/org.js.map +1 -0
  58. package/dist/util/polpo-config.js +39 -0
  59. package/dist/util/polpo-config.js.map +1 -0
  60. package/dist/util/project.js +87 -0
  61. package/dist/util/project.js.map +1 -0
  62. package/dist/util/skills.js +53 -0
  63. package/dist/util/skills.js.map +1 -0
  64. package/dist/util/slugify.js +19 -0
  65. package/dist/util/slugify.js.map +1 -0
  66. package/dist/util/template.js +118 -0
  67. package/dist/util/template.js.map +1 -0
  68. package/package.json +38 -0
@@ -0,0 +1,286 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import * as clack from "@clack/prompts";
4
+ import pc from "picocolors";
5
+ import { requireAuth } from "../util/auth.js";
6
+ import { createApiClient } from "./cloud/api.js";
7
+ import { pickOrg } from "../util/org.js";
8
+ import { createProject, waitForProjectActive } from "../util/project.js";
9
+ import { createProjectApiKey } from "../util/api-keys.js";
10
+ import { writePolpoConfig } from "../util/polpo-config.js";
11
+ import { TEMPLATES, findTemplate, writeBlankScaffold, scaffoldRemoteTemplate, } from "../util/template.js";
12
+ import { friendlyError } from "../util/errors.js";
13
+ import { slugify } from "../util/slugify.js";
14
+ import { installCodingAgentSkills, skillsInstallHint } from "../util/skills.js";
15
+ import { isPolpoOnPath, installPolpoGlobally, globalInstallHint } from "../util/install-cli.js";
16
+ import { POLPO_API_DOMAIN } from "../util/base-url.js";
17
+ export function registerCreateCommand(program) {
18
+ program
19
+ .command("create")
20
+ .description("Create a new cloud project + local scaffold")
21
+ .option("--name <name>", "Project name (default: current dir name)")
22
+ .option("--org-id <id>", "Organization ID")
23
+ .option("--template <id>", `Template: ${TEMPLATES.map((t) => t.id).join(", ")}`)
24
+ .option("--api-url <url>", "Override the API base URL (self-hosted, custom domain, dev)")
25
+ .option("--skills <scope>", "Coding-agent skills install: global | project | skip", "")
26
+ .option("--install-cli <yes|no>", "Install the polpo CLI globally after scaffold", "")
27
+ .option("-y, --yes", "Skip confirmations (use defaults)")
28
+ .action(async (opts) => {
29
+ clack.intro(pc.bold("Polpo — Create a new project"));
30
+ // Step 1: Auth (auto-browser if needed)
31
+ const creds = await requireAuth({
32
+ apiUrl: opts.apiUrl,
33
+ context: "Creating a project requires an authenticated session.",
34
+ });
35
+ const client = createApiClient({
36
+ apiKey: creds.apiKey,
37
+ baseUrl: opts.apiUrl ?? creds.baseUrl,
38
+ });
39
+ // Step 2: Organization
40
+ let orgId = opts.orgId;
41
+ if (!orgId) {
42
+ const org = await pickOrg(client);
43
+ orgId = org.id;
44
+ }
45
+ // Step 3: Project name
46
+ let projectName = opts.name;
47
+ if (!projectName) {
48
+ const defaultName = path.basename(process.cwd());
49
+ const name = await clack.text({
50
+ message: "Project name",
51
+ initialValue: defaultName,
52
+ validate: (v) => (v.length < 2 ? "Name must be at least 2 characters" : undefined),
53
+ });
54
+ if (clack.isCancel(name)) {
55
+ clack.cancel("Cancelled.");
56
+ process.exit(0);
57
+ }
58
+ projectName = name;
59
+ }
60
+ // Step 4: Template
61
+ let template;
62
+ if (opts.template) {
63
+ template = findTemplate(opts.template);
64
+ if (!template) {
65
+ clack.outro(pc.red(`Unknown template "${opts.template}". Valid: ${TEMPLATES.map((t) => t.id).join(", ")}`));
66
+ process.exit(1);
67
+ }
68
+ }
69
+ else {
70
+ const choice = await clack.select({
71
+ message: "How would you like to start?",
72
+ options: TEMPLATES.map((t) => ({
73
+ value: t.id,
74
+ label: t.label,
75
+ hint: t.hint,
76
+ })),
77
+ });
78
+ if (clack.isCancel(choice)) {
79
+ clack.cancel("Cancelled.");
80
+ process.exit(0);
81
+ }
82
+ template = findTemplate(choice);
83
+ }
84
+ // Step 5: Directory
85
+ // Blank templates can scaffold into cwd; remote templates always
86
+ // get their own subdirectory.
87
+ const originalCwd = process.cwd();
88
+ let targetDir = originalCwd;
89
+ let dirName = null;
90
+ if (template.kind === "remote") {
91
+ const defaultDir = slugify(projectName);
92
+ const input = opts.yes
93
+ ? defaultDir
94
+ : await clack.text({
95
+ message: "Directory name",
96
+ initialValue: defaultDir,
97
+ validate: (v) => (!v || v === "." || v === ".." ? "Invalid directory" : undefined),
98
+ });
99
+ if (clack.isCancel(input)) {
100
+ clack.cancel("Cancelled.");
101
+ process.exit(0);
102
+ }
103
+ dirName = path.basename(input).replace(/[^a-zA-Z0-9._-]/g, "-");
104
+ targetDir = path.resolve(originalCwd, dirName);
105
+ if (fs.existsSync(targetDir)) {
106
+ clack.outro(pc.red(`Directory "${dirName}" already exists.`));
107
+ process.exit(1);
108
+ }
109
+ }
110
+ // Step 6: Create cloud project
111
+ const s = clack.spinner();
112
+ s.start("Creating project...");
113
+ let project;
114
+ try {
115
+ project = await createProject(client, {
116
+ orgId,
117
+ name: projectName,
118
+ });
119
+ s.message("Waiting for project to become active...");
120
+ await waitForProjectActive(client, project.id);
121
+ s.stop(`Project "${project.name}" created`);
122
+ }
123
+ catch (err) {
124
+ s.stop("Project creation failed.");
125
+ clack.outro(pc.red(friendlyError(err.message)));
126
+ process.exit(1);
127
+ }
128
+ // Step 7: Project-scoped API key
129
+ s.start("Generating API key...");
130
+ let apiKey;
131
+ try {
132
+ apiKey = await createProjectApiKey(client, orgId, project.id, "Created by polpo create");
133
+ s.stop("API key generated");
134
+ }
135
+ catch (err) {
136
+ s.stop("API key generation failed.");
137
+ clack.log.warn(`Could not auto-create a project API key: ${err.message}`);
138
+ clack.log.info("You can create one later from the dashboard → /keys");
139
+ }
140
+ // Step 8: Scaffold
141
+ if (template.kind === "blank") {
142
+ s.start("Writing .polpo/ scaffold...");
143
+ try {
144
+ writeBlankScaffold(targetDir, projectName);
145
+ s.stop(".polpo/ scaffold written");
146
+ }
147
+ catch (err) {
148
+ s.stop("Scaffold failed.");
149
+ clack.outro(pc.red(err.message));
150
+ process.exit(1);
151
+ }
152
+ }
153
+ else {
154
+ s.start(`Scaffolding template (${template.id})...`);
155
+ try {
156
+ // Delegates to `create-polpo-app` which handles download + npm install.
157
+ await scaffoldRemoteTemplate({
158
+ templateId: template.id,
159
+ targetDir,
160
+ });
161
+ s.stop("Template ready");
162
+ }
163
+ catch (err) {
164
+ s.stop("Template scaffold failed.");
165
+ clack.log.warn(`${err.message}`);
166
+ clack.log.info("You can retry manually: `npx create-polpo-app@latest`. Falling back to blank scaffold.");
167
+ if (!fs.existsSync(targetDir))
168
+ fs.mkdirSync(targetDir, { recursive: true });
169
+ writeBlankScaffold(targetDir, projectName);
170
+ }
171
+ }
172
+ // Step 9: Write polpo.json + .env.local
173
+ // The data plane URL is derived from the slug — `{slug}.polpo.cloud`.
174
+ // For self-hosted or custom-domain users, set `apiUrl` in polpo.json
175
+ // (or the POLPO_API_URL env var at runtime) to override.
176
+ const tenantUrl = project.slug
177
+ ? `https://${project.slug}.${POLPO_API_DOMAIN}`
178
+ : creds.baseUrl;
179
+ writePolpoConfig(targetDir, {
180
+ project: project.name,
181
+ projectSlug: project.slug,
182
+ projectId: project.id,
183
+ });
184
+ if (apiKey) {
185
+ const envLocal = path.join(targetDir, ".env.local");
186
+ const envContent = `POLPO_API_KEY=${apiKey.rawKey}\n` +
187
+ `POLPO_API_URL=${tenantUrl}\n`;
188
+ try {
189
+ fs.writeFileSync(envLocal, envContent, { flag: "wx" });
190
+ clack.log.info(`Wrote ${pc.bold(".env.local")} with project credentials`);
191
+ }
192
+ catch {
193
+ // .env.local exists already — leave it alone, just log the key once.
194
+ clack.log.warn(".env.local exists — not overwriting. Your key:");
195
+ console.log(pc.bold(` POLPO_API_KEY=${apiKey.rawKey}`));
196
+ }
197
+ }
198
+ // Step 10: Coding-agent skills
199
+ let skillsScope;
200
+ if (opts.skills === "global" || opts.skills === "project" || opts.skills === "skip") {
201
+ skillsScope = opts.skills;
202
+ }
203
+ else if (opts.yes) {
204
+ skillsScope = "global";
205
+ }
206
+ else {
207
+ const choice = await clack.select({
208
+ message: "Install skills for your coding agent? (Cursor, Claude Code, Windsurf, …)",
209
+ options: [
210
+ { value: "global", label: "Yes, globally", hint: "recommended — once per machine" },
211
+ { value: "project", label: "Yes, just for this project" },
212
+ { value: "skip", label: "Skip" },
213
+ ],
214
+ initialValue: "global",
215
+ });
216
+ if (clack.isCancel(choice)) {
217
+ skillsScope = "skip";
218
+ }
219
+ else {
220
+ skillsScope = choice;
221
+ }
222
+ }
223
+ let skillsInstalled = false;
224
+ if (skillsScope !== "skip") {
225
+ s.start(`Installing coding-agent skills (${skillsScope})...`);
226
+ skillsInstalled = await installCodingAgentSkills({ scope: skillsScope, cwd: targetDir });
227
+ if (skillsInstalled) {
228
+ s.stop("Coding-agent skills installed");
229
+ }
230
+ else {
231
+ s.stop("Coding-agent skills install failed.");
232
+ clack.log.warn(`Install manually later: ${pc.bold(skillsInstallHint())}`);
233
+ }
234
+ }
235
+ // Step 11: Install polpo globally (skip if already on PATH)
236
+ let cliInstalled = false;
237
+ let cliInstallCommand = globalInstallHint();
238
+ if (!isPolpoOnPath()) {
239
+ let doInstall;
240
+ if (opts.installCli === "yes")
241
+ doInstall = true;
242
+ else if (opts.installCli === "no")
243
+ doInstall = false;
244
+ else if (opts.yes)
245
+ doInstall = true;
246
+ else {
247
+ const choice = await clack.confirm({
248
+ message: "Install polpo CLI globally so you can run `polpo` from anywhere?",
249
+ initialValue: true,
250
+ });
251
+ doInstall = !clack.isCancel(choice) && !!choice;
252
+ }
253
+ if (doInstall) {
254
+ s.start("Installing polpo CLI globally...");
255
+ const result = await installPolpoGlobally();
256
+ cliInstallCommand = result.command;
257
+ if (result.ok) {
258
+ s.stop("polpo CLI installed");
259
+ cliInstalled = true;
260
+ }
261
+ else {
262
+ s.stop("Global install failed.");
263
+ clack.log.warn(`Install manually later: ${pc.bold(result.command)}`);
264
+ }
265
+ }
266
+ }
267
+ else {
268
+ cliInstalled = true; // already on PATH
269
+ }
270
+ // Outro
271
+ const relDir = dirName ?? ".";
272
+ const polpoRun = cliInstalled ? "polpo" : `npx ${CLI_PACKAGE_FOR_OUTRO}`;
273
+ const nextSteps = [
274
+ dirName ? `cd ${dirName}` : undefined,
275
+ template.installsDeps ? "npm run dev" : undefined,
276
+ `${polpoRun} deploy`,
277
+ skillsScope === "skip" ? `# skills: ${skillsInstallHint()}` : undefined,
278
+ !cliInstalled ? `# install polpo: ${cliInstallCommand}` : undefined,
279
+ ].filter(Boolean);
280
+ clack.outro(pc.green(`✓ Project "${project.name}" ready in ${relDir}\n`) +
281
+ pc.dim(" Next:\n") +
282
+ nextSteps.map((step) => pc.dim(` ${step}\n`)).join(""));
283
+ });
284
+ }
285
+ const CLI_PACKAGE_FOR_OUTRO = "@polpo-ai/cli";
286
+ //# sourceMappingURL=create.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ import * as path from "node:path";
2
+ import * as clack from "@clack/prompts";
3
+ import pc from "picocolors";
4
+ import { requireAuth } from "../util/auth.js";
5
+ import { createApiClient } from "./cloud/api.js";
6
+ import { getProject } from "../util/project.js";
7
+ import { writePolpoConfig, readPolpoConfig } from "../util/polpo-config.js";
8
+ import { friendlyError } from "../util/errors.js";
9
+ export function registerLinkCommand(program) {
10
+ program
11
+ .command("link")
12
+ .description("Link the current directory to an existing cloud project")
13
+ .requiredOption("--project-id <id>", "Cloud project UUID")
14
+ .option("-d, --dir <path>", "Working directory", ".")
15
+ .option("--api-url <url>", "Override the API base URL (self-hosted, custom domain, dev)")
16
+ .action(async (opts) => {
17
+ clack.intro(pc.bold("Polpo — Link project"));
18
+ const creds = await requireAuth({
19
+ apiUrl: opts.apiUrl,
20
+ context: "Linking a project requires an authenticated session.",
21
+ });
22
+ const client = createApiClient({
23
+ apiKey: creds.apiKey,
24
+ baseUrl: opts.apiUrl ?? creds.baseUrl,
25
+ });
26
+ const s = clack.spinner();
27
+ s.start("Verifying project...");
28
+ let project;
29
+ try {
30
+ project = await getProject(client, opts.projectId);
31
+ if (!project) {
32
+ s.stop("Project not found.");
33
+ clack.outro(pc.red(`No project with id ${opts.projectId} — check the URL or run `) +
34
+ pc.bold("polpo projects"));
35
+ process.exit(1);
36
+ }
37
+ s.stop(`Project: ${project.name}`);
38
+ }
39
+ catch (err) {
40
+ s.stop("Failed to verify project.");
41
+ clack.outro(pc.red(friendlyError(err.message)));
42
+ process.exit(1);
43
+ }
44
+ const cwd = path.resolve(opts.dir);
45
+ // Warn if already linked to a different project.
46
+ const existing = readPolpoConfig(cwd);
47
+ if (existing?.projectId && existing.projectId !== project.id) {
48
+ const ok = await clack.confirm({
49
+ message: `This directory is already linked to "${existing.project ?? existing.projectId}". Replace?`,
50
+ initialValue: false,
51
+ });
52
+ if (clack.isCancel(ok) || !ok) {
53
+ clack.cancel("Cancelled.");
54
+ process.exit(0);
55
+ }
56
+ }
57
+ // Persist slug as the canonical identifier; UUID is kept for display.
58
+ // Don't pin apiUrl — the slug derives the data plane URL automatically.
59
+ // Self-hosted users can add `apiUrl` manually to override.
60
+ writePolpoConfig(cwd, {
61
+ project: project.name,
62
+ projectSlug: project.slug,
63
+ projectId: project.id,
64
+ });
65
+ clack.log.success(`Wrote ${pc.bold(".polpo/polpo.json")}`);
66
+ clack.outro(pc.green("✓ Linked. Next: ") +
67
+ pc.bold("polpo deploy") +
68
+ pc.dim(" to push your agents."));
69
+ });
70
+ }
71
+ //# sourceMappingURL=link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.js","sourceRoot":"","sources":["../../src/commands/link.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import pc from "picocolors";
2
+ const GATEWAY_URL = "https://polpo.sh/api/gateway/models";
3
+ export function registerModelsCommands(parent) {
4
+ const models = parent
5
+ .command("models")
6
+ .description("List available AI models");
7
+ models
8
+ .command("list")
9
+ .description("List available models from the AI Gateway")
10
+ .option("--provider <name>", "Filter by provider (e.g. anthropic, openai, xai)")
11
+ .option("--json", "Output as JSON")
12
+ .option("--plain", "One model per line (machine-friendly)")
13
+ .action(async (opts) => {
14
+ let data;
15
+ try {
16
+ const res = await fetch(GATEWAY_URL);
17
+ if (!res.ok) {
18
+ console.error(`Error: Could not fetch models (HTTP ${res.status})`);
19
+ process.exit(1);
20
+ }
21
+ const json = await res.json();
22
+ data = json.data ?? json ?? [];
23
+ }
24
+ catch (err) {
25
+ console.error(`Error: ${err.message}`);
26
+ process.exit(1);
27
+ }
28
+ if (opts.provider) {
29
+ data = data.filter(m => m.id.startsWith(`${opts.provider}/`));
30
+ }
31
+ if (opts.json) {
32
+ console.log(JSON.stringify(data, null, 2));
33
+ return;
34
+ }
35
+ if (opts.plain) {
36
+ for (const m of data)
37
+ console.log(m.id);
38
+ return;
39
+ }
40
+ // Group by provider
41
+ const byProvider = new Map();
42
+ for (const m of data) {
43
+ const provider = m.id.split("/")[0] ?? m.owned_by;
44
+ if (!byProvider.has(provider))
45
+ byProvider.set(provider, []);
46
+ byProvider.get(provider).push(m);
47
+ }
48
+ console.log(`\n ${pc.bold(`${data.length} models`)} from ${byProvider.size} providers\n`);
49
+ for (const [provider, models] of byProvider) {
50
+ console.log(` ${pc.bold(provider)} (${models.length})`);
51
+ for (const m of models) {
52
+ const ctx = m.context_window ? pc.dim(` ${(m.context_window / 1000).toFixed(0)}k`) : "";
53
+ const price = m.pricing ? pc.dim(` $${m.pricing.input}/$${m.pricing.output}`) : "";
54
+ console.log(` ${m.id}${ctx}${price}`);
55
+ }
56
+ console.log();
57
+ }
58
+ });
59
+ }
60
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/commands/models.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import pc from "picocolors";
2
+ import { requireAuth } from "../util/auth.js";
3
+ import { createApiClient } from "./cloud/api.js";
4
+ export function registerOrgsCommand(program) {
5
+ const orgs = program
6
+ .command("orgs")
7
+ .description("List organizations you belong to");
8
+ orgs
9
+ .command("list", { isDefault: true })
10
+ .alias("ls")
11
+ .description("List organizations")
12
+ .option("--json", "Output as JSON")
13
+ .action(async (opts) => {
14
+ const creds = await requireAuth();
15
+ const client = createApiClient({ apiKey: creds.apiKey, baseUrl: creds.baseUrl });
16
+ let list = [];
17
+ try {
18
+ const res = await client.get("/v1/orgs");
19
+ list = Array.isArray(res.data) ? res.data : [];
20
+ }
21
+ catch (err) {
22
+ console.error(pc.red(`Failed to list orgs: ${err.message}`));
23
+ process.exit(1);
24
+ }
25
+ if (opts.json) {
26
+ console.log(JSON.stringify(list, null, 2));
27
+ return;
28
+ }
29
+ if (list.length === 0) {
30
+ console.log(pc.dim("No organizations found."));
31
+ return;
32
+ }
33
+ console.log();
34
+ for (const o of list) {
35
+ const slug = o.slug ? pc.dim(` (${o.slug})`) : "";
36
+ console.log(` ${pc.bold(o.name)}${slug}`);
37
+ console.log(pc.dim(` id: ${o.id}`));
38
+ }
39
+ console.log();
40
+ });
41
+ }
42
+ //# sourceMappingURL=orgs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orgs.js","sourceRoot":"","sources":["../../src/commands/orgs.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AASjD,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,MAAM,IAAI,GAAG,OAAO;SACjB,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,kCAAkC,CAAC,CAAC;IAEnD,IAAI;SACD,OAAO,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;SACpC,KAAK,CAAC,IAAI,CAAC;SACX,WAAW,CAAC,oBAAoB,CAAC;SACjC,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;SAClC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACrB,MAAM,KAAK,GAAG,MAAM,WAAW,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAEjF,IAAI,IAAI,GAAU,EAAE,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,GAAG,CAAQ,UAAU,CAAC,CAAC;YAChD,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,wBAAyB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC3C,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,CAAC;YAC/C,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACnD,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,95 @@
1
+ import { execSync } from "node:child_process";
2
+ import pc from "picocolors";
3
+ /**
4
+ * Check if running inside an Electron (desktop) app.
5
+ */
6
+ function isDesktopApp() {
7
+ if (process.versions.electron)
8
+ return true;
9
+ const execPath = process.execPath || "";
10
+ return (execPath.includes("Polpo.app") ||
11
+ execPath.includes("polpo-server") ||
12
+ !!process.env.ELECTRON_RUN_AS_NODE);
13
+ }
14
+ /**
15
+ * Detect which package manager installed polpo globally.
16
+ */
17
+ function detectPackageManager() {
18
+ try {
19
+ const out = execSync("pnpm list -g polpo-ai --depth=0 2>/dev/null", {
20
+ encoding: "utf-8",
21
+ timeout: 10_000,
22
+ });
23
+ if (out.includes("polpo-ai"))
24
+ return "pnpm";
25
+ }
26
+ catch { /* not pnpm */ }
27
+ return "npm";
28
+ }
29
+ /**
30
+ * Get the latest version from the npm registry.
31
+ */
32
+ async function getLatestVersion() {
33
+ const res = await fetch("https://registry.npmjs.org/polpo-ai/latest", {
34
+ headers: { Accept: "application/json" },
35
+ });
36
+ if (!res.ok)
37
+ throw new Error(`Registry returned ${res.status}`);
38
+ const data = (await res.json());
39
+ return data.version;
40
+ }
41
+ export function registerUpdateCommand(program) {
42
+ program
43
+ .command("update")
44
+ .alias("upgrade")
45
+ .description("Update Polpo to the latest version")
46
+ .option("--check", "Only check for updates, don't install")
47
+ .action(async (opts) => {
48
+ try {
49
+ const currentVersion = program.version();
50
+ console.log(pc.dim(` Current version: ${currentVersion}`));
51
+ console.log(pc.dim(" Checking for updates..."));
52
+ const latest = await getLatestVersion();
53
+ if (latest === currentVersion) {
54
+ console.log(pc.green(`\n Already up to date (${currentVersion})`));
55
+ return;
56
+ }
57
+ console.log(`\n ${pc.yellow("Update available:")} ${pc.dim(currentVersion)} → ${pc.bold(pc.cyan(latest))}`);
58
+ if (opts.check) {
59
+ console.log(pc.dim(`\n Run ${pc.white("polpo update")} to install.`));
60
+ return;
61
+ }
62
+ const pm = detectPackageManager();
63
+ // Clear cache to avoid stale versions
64
+ try {
65
+ if (pm === "npm")
66
+ execSync("npm cache clean --force", { stdio: "ignore", timeout: 30_000 });
67
+ }
68
+ catch { /* best effort */ }
69
+ const cmd = pm === "pnpm"
70
+ ? `pnpm add -g polpo-ai@${latest}`
71
+ : `npm install -g polpo-ai@${latest}`;
72
+ console.log(pc.dim(`\n Updating via ${pm}...`));
73
+ console.log(pc.dim(` $ ${cmd}\n`));
74
+ execSync(cmd, { stdio: "inherit", timeout: 120_000 });
75
+ // Verify
76
+ try {
77
+ const newVer = execSync("polpo --version", { encoding: "utf-8" }).trim();
78
+ console.log(pc.green(`\n Updated to ${newVer}`));
79
+ }
80
+ catch {
81
+ console.log(pc.green(`\n Update complete. Restart your shell to use the new version.`));
82
+ }
83
+ if (isDesktopApp()) {
84
+ console.log(pc.yellow(`\n You're running inside the Polpo desktop app.`));
85
+ console.log(pc.yellow(` Restart the app to apply the update to the desktop binary.`));
86
+ }
87
+ }
88
+ catch (err) {
89
+ console.error(pc.red(`\n Update failed: ${err.message}`));
90
+ console.log(pc.dim(" Try manually: npm install -g polpo-ai@latest"));
91
+ process.exit(1);
92
+ }
93
+ });
94
+ }
95
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}