@usenaive-sdk/cli 0.15.1 → 1.0.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 (281) hide show
  1. package/README.md +43 -402
  2. package/dist/index.js +51775 -502
  3. package/package.json +22 -18
  4. package/dist/client.d.ts +0 -108
  5. package/dist/client.js +0 -458
  6. package/dist/client.js.map +0 -1
  7. package/dist/commands/account-kits.d.ts +0 -2
  8. package/dist/commands/account-kits.js +0 -71
  9. package/dist/commands/account-kits.js.map +0 -1
  10. package/dist/commands/aeo.d.ts +0 -2
  11. package/dist/commands/aeo.js +0 -451
  12. package/dist/commands/aeo.js.map +0 -1
  13. package/dist/commands/agent-profiles.d.ts +0 -11
  14. package/dist/commands/agent-profiles.js +0 -120
  15. package/dist/commands/agent-profiles.js.map +0 -1
  16. package/dist/commands/agents.d.ts +0 -2
  17. package/dist/commands/agents.js +0 -916
  18. package/dist/commands/agents.js.map +0 -1
  19. package/dist/commands/app-data.d.ts +0 -2
  20. package/dist/commands/app-data.js +0 -445
  21. package/dist/commands/app-data.js.map +0 -1
  22. package/dist/commands/approvals.d.ts +0 -2
  23. package/dist/commands/approvals.js +0 -242
  24. package/dist/commands/approvals.js.map +0 -1
  25. package/dist/commands/apps.d.ts +0 -9
  26. package/dist/commands/apps.js +0 -844
  27. package/dist/commands/apps.js.map +0 -1
  28. package/dist/commands/audio.d.ts +0 -9
  29. package/dist/commands/audio.js +0 -391
  30. package/dist/commands/audio.js.map +0 -1
  31. package/dist/commands/auth.d.ts +0 -31
  32. package/dist/commands/auth.js +0 -428
  33. package/dist/commands/auth.js.map +0 -1
  34. package/dist/commands/billing.d.ts +0 -2
  35. package/dist/commands/billing.js +0 -250
  36. package/dist/commands/billing.js.map +0 -1
  37. package/dist/commands/brain.d.ts +0 -2
  38. package/dist/commands/brain.js +0 -1300
  39. package/dist/commands/brain.js.map +0 -1
  40. package/dist/commands/browser.d.ts +0 -2
  41. package/dist/commands/browser.js +0 -378
  42. package/dist/commands/browser.js.map +0 -1
  43. package/dist/commands/business.d.ts +0 -2
  44. package/dist/commands/business.js +0 -566
  45. package/dist/commands/business.js.map +0 -1
  46. package/dist/commands/cards.d.ts +0 -2
  47. package/dist/commands/cards.js +0 -419
  48. package/dist/commands/cards.js.map +0 -1
  49. package/dist/commands/ceo.d.ts +0 -2
  50. package/dist/commands/ceo.js +0 -369
  51. package/dist/commands/ceo.js.map +0 -1
  52. package/dist/commands/clone.d.ts +0 -2
  53. package/dist/commands/clone.js +0 -203
  54. package/dist/commands/clone.js.map +0 -1
  55. package/dist/commands/companies.d.ts +0 -10
  56. package/dist/commands/companies.js +0 -283
  57. package/dist/commands/companies.js.map +0 -1
  58. package/dist/commands/company-data.d.ts +0 -2
  59. package/dist/commands/company-data.js +0 -168
  60. package/dist/commands/company-data.js.map +0 -1
  61. package/dist/commands/compute.d.ts +0 -2
  62. package/dist/commands/compute.js +0 -498
  63. package/dist/commands/compute.js.map +0 -1
  64. package/dist/commands/config.d.ts +0 -2
  65. package/dist/commands/config.js +0 -36
  66. package/dist/commands/config.js.map +0 -1
  67. package/dist/commands/connections.d.ts +0 -8
  68. package/dist/commands/connections.js +0 -137
  69. package/dist/commands/connections.js.map +0 -1
  70. package/dist/commands/cron-jobs.d.ts +0 -2
  71. package/dist/commands/cron-jobs.js +0 -245
  72. package/dist/commands/cron-jobs.js.map +0 -1
  73. package/dist/commands/domains.d.ts +0 -2
  74. package/dist/commands/domains.js +0 -474
  75. package/dist/commands/domains.js.map +0 -1
  76. package/dist/commands/ecommerce.d.ts +0 -2
  77. package/dist/commands/ecommerce.js +0 -277
  78. package/dist/commands/ecommerce.js.map +0 -1
  79. package/dist/commands/email.d.ts +0 -2
  80. package/dist/commands/email.js +0 -336
  81. package/dist/commands/email.js.map +0 -1
  82. package/dist/commands/employees.d.ts +0 -2
  83. package/dist/commands/employees.js +0 -190
  84. package/dist/commands/employees.js.map +0 -1
  85. package/dist/commands/env.d.ts +0 -7
  86. package/dist/commands/env.js +0 -112
  87. package/dist/commands/env.js.map +0 -1
  88. package/dist/commands/formation.d.ts +0 -2
  89. package/dist/commands/formation.js +0 -273
  90. package/dist/commands/formation.js.map +0 -1
  91. package/dist/commands/identity.d.ts +0 -2
  92. package/dist/commands/identity.js +0 -110
  93. package/dist/commands/identity.js.map +0 -1
  94. package/dist/commands/images.d.ts +0 -2
  95. package/dist/commands/images.js +0 -371
  96. package/dist/commands/images.js.map +0 -1
  97. package/dist/commands/init.d.ts +0 -5
  98. package/dist/commands/init.js +0 -43
  99. package/dist/commands/init.js.map +0 -1
  100. package/dist/commands/jobs.d.ts +0 -2
  101. package/dist/commands/jobs.js +0 -144
  102. package/dist/commands/jobs.js.map +0 -1
  103. package/dist/commands/keys.d.ts +0 -2
  104. package/dist/commands/keys.js +0 -156
  105. package/dist/commands/keys.js.map +0 -1
  106. package/dist/commands/legacy-auth.d.ts +0 -27
  107. package/dist/commands/legacy-auth.js +0 -64
  108. package/dist/commands/legacy-auth.js.map +0 -1
  109. package/dist/commands/llm.d.ts +0 -2
  110. package/dist/commands/llm.js +0 -125
  111. package/dist/commands/llm.js.map +0 -1
  112. package/dist/commands/login.d.ts +0 -2
  113. package/dist/commands/login.js +0 -65
  114. package/dist/commands/login.js.map +0 -1
  115. package/dist/commands/logout.d.ts +0 -7
  116. package/dist/commands/logout.js +0 -55
  117. package/dist/commands/logout.js.map +0 -1
  118. package/dist/commands/logs.d.ts +0 -2
  119. package/dist/commands/logs.js +0 -42
  120. package/dist/commands/logs.js.map +0 -1
  121. package/dist/commands/loops.d.ts +0 -2
  122. package/dist/commands/loops.js +0 -260
  123. package/dist/commands/loops.js.map +0 -1
  124. package/dist/commands/media.d.ts +0 -2
  125. package/dist/commands/media.js +0 -183
  126. package/dist/commands/media.js.map +0 -1
  127. package/dist/commands/memory.d.ts +0 -2
  128. package/dist/commands/memory.js +0 -151
  129. package/dist/commands/memory.js.map +0 -1
  130. package/dist/commands/mobile.d.ts +0 -4
  131. package/dist/commands/mobile.js +0 -382
  132. package/dist/commands/mobile.js.map +0 -1
  133. package/dist/commands/module.d.ts +0 -8
  134. package/dist/commands/module.js +0 -48
  135. package/dist/commands/module.js.map +0 -1
  136. package/dist/commands/objectives.d.ts +0 -2
  137. package/dist/commands/objectives.js +0 -243
  138. package/dist/commands/objectives.js.map +0 -1
  139. package/dist/commands/payments.d.ts +0 -2
  140. package/dist/commands/payments.js +0 -131
  141. package/dist/commands/payments.js.map +0 -1
  142. package/dist/commands/people.d.ts +0 -2
  143. package/dist/commands/people.js +0 -197
  144. package/dist/commands/people.js.map +0 -1
  145. package/dist/commands/phone.d.ts +0 -2
  146. package/dist/commands/phone.js +0 -289
  147. package/dist/commands/phone.js.map +0 -1
  148. package/dist/commands/projects.d.ts +0 -13
  149. package/dist/commands/projects.js +0 -220
  150. package/dist/commands/projects.js.map +0 -1
  151. package/dist/commands/queue.d.ts +0 -2
  152. package/dist/commands/queue.js +0 -121
  153. package/dist/commands/queue.js.map +0 -1
  154. package/dist/commands/register.d.ts +0 -2
  155. package/dist/commands/register.js +0 -88
  156. package/dist/commands/register.js.map +0 -1
  157. package/dist/commands/report.d.ts +0 -17
  158. package/dist/commands/report.js +0 -109
  159. package/dist/commands/report.js.map +0 -1
  160. package/dist/commands/sandbox.d.ts +0 -2
  161. package/dist/commands/sandbox.js +0 -558
  162. package/dist/commands/sandbox.js.map +0 -1
  163. package/dist/commands/search.d.ts +0 -2
  164. package/dist/commands/search.js +0 -223
  165. package/dist/commands/search.js.map +0 -1
  166. package/dist/commands/seo.d.ts +0 -2
  167. package/dist/commands/seo.js +0 -528
  168. package/dist/commands/seo.js.map +0 -1
  169. package/dist/commands/sessions.d.ts +0 -6
  170. package/dist/commands/sessions.js +0 -109
  171. package/dist/commands/sessions.js.map +0 -1
  172. package/dist/commands/social-data.d.ts +0 -2
  173. package/dist/commands/social-data.js +0 -245
  174. package/dist/commands/social-data.js.map +0 -1
  175. package/dist/commands/social.d.ts +0 -2
  176. package/dist/commands/social.js +0 -407
  177. package/dist/commands/social.js.map +0 -1
  178. package/dist/commands/status.d.ts +0 -2
  179. package/dist/commands/status.js +0 -79
  180. package/dist/commands/status.js.map +0 -1
  181. package/dist/commands/support.d.ts +0 -2
  182. package/dist/commands/support.js +0 -134
  183. package/dist/commands/support.js.map +0 -1
  184. package/dist/commands/tasks.d.ts +0 -2
  185. package/dist/commands/tasks.js +0 -409
  186. package/dist/commands/tasks.js.map +0 -1
  187. package/dist/commands/teams.d.ts +0 -69
  188. package/dist/commands/teams.js +0 -503
  189. package/dist/commands/teams.js.map +0 -1
  190. package/dist/commands/trading.d.ts +0 -2
  191. package/dist/commands/trading.js +0 -333
  192. package/dist/commands/trading.js.map +0 -1
  193. package/dist/commands/up.d.ts +0 -551
  194. package/dist/commands/up.js +0 -1149
  195. package/dist/commands/up.js.map +0 -1
  196. package/dist/commands/usage.d.ts +0 -2
  197. package/dist/commands/usage.js +0 -73
  198. package/dist/commands/usage.js.map +0 -1
  199. package/dist/commands/use.d.ts +0 -12
  200. package/dist/commands/use.js +0 -96
  201. package/dist/commands/use.js.map +0 -1
  202. package/dist/commands/users.d.ts +0 -10
  203. package/dist/commands/users.js +0 -82
  204. package/dist/commands/users.js.map +0 -1
  205. package/dist/commands/vault.d.ts +0 -2
  206. package/dist/commands/vault.js +0 -101
  207. package/dist/commands/vault.js.map +0 -1
  208. package/dist/commands/verification.d.ts +0 -2
  209. package/dist/commands/verification.js +0 -152
  210. package/dist/commands/verification.js.map +0 -1
  211. package/dist/commands/verify-email.d.ts +0 -19
  212. package/dist/commands/verify-email.js +0 -130
  213. package/dist/commands/verify-email.js.map +0 -1
  214. package/dist/commands/video.d.ts +0 -2
  215. package/dist/commands/video.js +0 -417
  216. package/dist/commands/video.js.map +0 -1
  217. package/dist/commands/voice.d.ts +0 -2
  218. package/dist/commands/voice.js +0 -516
  219. package/dist/commands/voice.js.map +0 -1
  220. package/dist/commands/wallet.d.ts +0 -2
  221. package/dist/commands/wallet.js +0 -244
  222. package/dist/commands/wallet.js.map +0 -1
  223. package/dist/commands/webhooks.d.ts +0 -13
  224. package/dist/commands/webhooks.js +0 -119
  225. package/dist/commands/webhooks.js.map +0 -1
  226. package/dist/commands/whoami.d.ts +0 -2
  227. package/dist/commands/whoami.js +0 -53
  228. package/dist/commands/whoami.js.map +0 -1
  229. package/dist/config.d.ts +0 -42
  230. package/dist/config.js +0 -83
  231. package/dist/config.js.map +0 -1
  232. package/dist/index.d.ts +0 -3
  233. package/dist/index.js.map +0 -1
  234. package/dist/lib/brain-select.d.ts +0 -193
  235. package/dist/lib/brain-select.js +0 -403
  236. package/dist/lib/brain-select.js.map +0 -1
  237. package/dist/lib/cli-validation.d.ts +0 -12
  238. package/dist/lib/cli-validation.js +0 -46
  239. package/dist/lib/cli-validation.js.map +0 -1
  240. package/dist/lib/config-errors.d.ts +0 -4
  241. package/dist/lib/config-errors.js +0 -13
  242. package/dist/lib/config-errors.js.map +0 -1
  243. package/dist/lib/deprecation.d.ts +0 -158
  244. package/dist/lib/deprecation.js +0 -140
  245. package/dist/lib/deprecation.js.map +0 -1
  246. package/dist/lib/duration.d.ts +0 -8
  247. package/dist/lib/duration.js +0 -11
  248. package/dist/lib/duration.js.map +0 -1
  249. package/dist/lib/http-response.d.ts +0 -11
  250. package/dist/lib/http-response.js +0 -96
  251. package/dist/lib/http-response.js.map +0 -1
  252. package/dist/lib/llm-paywall.d.ts +0 -82
  253. package/dist/lib/llm-paywall.js +0 -231
  254. package/dist/lib/llm-paywall.js.map +0 -1
  255. package/dist/lib/pricing.d.ts +0 -132
  256. package/dist/lib/pricing.js +0 -148
  257. package/dist/lib/pricing.js.map +0 -1
  258. package/dist/lib/starter-config.d.ts +0 -13
  259. package/dist/lib/starter-config.js +0 -71
  260. package/dist/lib/starter-config.js.map +0 -1
  261. package/dist/lib/stream-frames.d.ts +0 -114
  262. package/dist/lib/stream-frames.js +0 -169
  263. package/dist/lib/stream-frames.js.map +0 -1
  264. package/dist/lib/teams-catalog.d.ts +0 -141
  265. package/dist/lib/teams-catalog.js +0 -841
  266. package/dist/lib/teams-catalog.js.map +0 -1
  267. package/dist/lib/unknown-command.d.ts +0 -71
  268. package/dist/lib/unknown-command.js +0 -132
  269. package/dist/lib/unknown-command.js.map +0 -1
  270. package/dist/lib/version-check.d.ts +0 -26
  271. package/dist/lib/version-check.js +0 -21
  272. package/dist/lib/version-check.js.map +0 -1
  273. package/dist/output.d.ts +0 -246
  274. package/dist/output.js +0 -539
  275. package/dist/output.js.map +0 -1
  276. package/dist/prompt.d.ts +0 -17
  277. package/dist/prompt.js +0 -70
  278. package/dist/prompt.js.map +0 -1
  279. package/dist/version.d.ts +0 -2
  280. package/dist/version.js +0 -14
  281. package/dist/version.js.map +0 -1
@@ -1,844 +0,0 @@
1
- import { Command } from "commander";
2
- import { execFileSync } from "node:child_process";
3
- import { readFileSync, existsSync, rmSync } from "node:fs";
4
- import { tmpdir } from "node:os";
5
- import { join, resolve } from "node:path";
6
- import { apiRequest, apiUploadGzip, handleApiError } from "../client.js";
7
- import { agentError, agentOutput } from "../output.js";
8
- export const appsCmd = new Command("apps")
9
- .description("Web apps — create, deploy, manage Vercel-backed web applications with dedicated engineer agents")
10
- .addHelpText("after", `
11
- Subcommands:
12
- naive apps list List all apps
13
- naive apps create Create a new app
14
- naive apps templates List starter templates (GitHub repo + clone commands)
15
- naive apps show <id> Show app details
16
- naive apps delete <id> Delete an app
17
- naive apps deploy <id> [--dir <path>] Deploy (local directory upload, or agent workspace inside containers)
18
- naive apps publish <id> --deployment <id> Promote a deployment to production
19
- naive apps deployments <id> List deployment history
20
- naive apps retry <id> Retry failed provisioning (noop if healthy)
21
- naive apps secrets list <id> List env variable keys
22
- naive apps secrets set <id> <KEY> <VALUE> Set an env variable
23
- naive apps secrets delete <id> <KEY> Delete an env variable
24
- naive apps secrets reveal <id> <KEY> Reveal env variable value
25
- naive apps domains list <id> List app domains
26
- naive apps domains add <id> <domain> Add a custom domain
27
- naive apps domains remove <id> <domainId> Remove a domain
28
- naive apps domains set-primary <id> <domainId> Set the primary production domain
29
- naive apps domains connect <id> <domainId> Connect a company domain
30
- naive apps domains disconnect <id> <domainId> Disconnect a company domain
31
- naive apps domains verify-dns <id> <domainId> Verify DNS for connected domain
32
- naive apps db tables <id> List database tables (fullstack only)
33
- naive apps db query <id> "<sql>" Run SQL query (fullstack only)
34
- naive apps vercel <id> <method> <path> Call any Vercel API operation (scoped to the app)
35
- naive apps supabase <id> <method> <path> Call any Supabase Management API operation (scoped to the app)
36
-
37
- Typical Workflow (direct — no orchestration needed):
38
- 1. naive apps create --name "My Site" --type frontend_only
39
- → Creates Vercel project, returns the starter template clone command
40
- 2. git clone the starter template, build it locally
41
- 3. naive apps deploy <id> (run inside your project directory)
42
- → Uploads your code to Vercel, returns preview URL
43
- 4. naive apps publish <id> --deployment <deploymentId>
44
- → Promotes preview to production
45
- 5. naive apps domains connect <id> <domainId>
46
- → Points a custom domain to the production app
47
-
48
- Orchestrated Workflow (CEO / engineer agents):
49
- Same commands run inside the agent container deploy from the agent's
50
- workspace automatically — the engineer builds via the task system.
51
-
52
- Fullstack Workflow (adds Supabase):
53
- 1. naive apps create --name "My App" --type fullstack
54
- → Creates Vercel + Supabase project
55
- 2. naive apps db tables <id> → inspect database schema
56
- 3. naive apps db query <id> "..." → run ad-hoc queries
57
- 4. naive apps secrets set <id> KEY VALUE --target production
58
- → configure environment variables
59
-
60
- Direct Provider Access (advanced):
61
- Any operation supported by the Vercel REST API or Supabase Management API
62
- can be called through the scoped proxies — Naive injects the credentials:
63
- naive apps vercel <id> GET v6/deployments
64
- naive apps vercel <id> GET "v9/projects/<projectId>/domains"
65
- naive apps supabase <id> GET "v1/projects/<ref>/config/auth"
66
- naive apps supabase <id> POST "v1/projects/<ref>/database/query" --body '{"query":"select 1"}'
67
- Consult the official Vercel / Supabase API docs for endpoints and payloads.
68
-
69
- Each app gets a dedicated engineer agent that can build, deploy, and iterate
70
- on the code autonomously via the kanban task system.
71
- `);
72
- // ─── List ────────────────────────────────────────────────────────────────────
73
- appsCmd
74
- .command("list")
75
- .description("List all apps for the current company")
76
- .action(async () => {
77
- const resp = await apiRequest("GET", "/v1/apps");
78
- handleApiError("apps.list", resp);
79
- const data = resp.data;
80
- const count = data.apps?.length ?? 0;
81
- agentOutput({
82
- action: "apps.list",
83
- result: resp.data,
84
- next_steps: [
85
- ...(count > 0
86
- ? [{ command: `naive apps show ${data.apps[0].id}`, description: "View details of the first app" }]
87
- : []),
88
- { command: "naive apps create --name <name> --type frontend_only", description: "Create a new app" },
89
- ],
90
- hints: [`${count} app${count !== 1 ? "s" : ""} found`],
91
- related_commands: ["naive apps create", "naive apps show", "naive apps deploy"],
92
- });
93
- });
94
- // ─── Create ──────────────────────────────────────────────────────────────────
95
- appsCmd
96
- .command("create")
97
- .description("Create a new web app with a dedicated engineer agent")
98
- .requiredOption("--name <name>", "App name")
99
- .option("--type <type>", "App type: frontend_only or fullstack (default: frontend_only)", "frontend_only")
100
- .option("--variant <variant>", "Template variant: dark-premium, clean-minimal, bold-energetic, warm-human")
101
- // <desc...> so unquoted multi-word descriptions are not excess args
102
- .option("--description <desc...>", "Short description (unquoted multi-word OK)")
103
- .action(async (opts) => {
104
- const type = String(opts.type ?? "frontend_only").trim() || "frontend_only";
105
- if (type !== "frontend_only" && type !== "fullstack") {
106
- agentError({
107
- action: "apps.create",
108
- error: {
109
- code: "invalid_input",
110
- message: `Invalid --type "${type}". Use frontend_only or fullstack.`,
111
- },
112
- recovery_steps: [
113
- {
114
- command: 'naive apps create --name <name> --type frontend_only',
115
- description: "Create a frontend-only app (default)",
116
- },
117
- {
118
- command: 'naive apps create --name <name> --type fullstack',
119
- description: "Create a fullstack app with Supabase",
120
- },
121
- ],
122
- });
123
- }
124
- // `--description <desc...>` is variadic, so commander hands back a string[]
125
- // for an unquoted multi-word description and a string for a quoted one.
126
- const descriptionRaw = opts.description;
127
- const description = Array.isArray(descriptionRaw)
128
- ? descriptionRaw.join(" ").trim() || undefined
129
- : descriptionRaw
130
- ? String(descriptionRaw).trim() || undefined
131
- : undefined;
132
- const resp = await apiRequest("POST", "/v1/apps", {
133
- name: opts.name,
134
- type,
135
- ...(opts.variant && { variant: opts.variant }),
136
- ...(description && { description }),
137
- });
138
- handleApiError("apps.create", resp);
139
- const data = resp.data;
140
- const directMode = data.workspaceMode !== "container";
141
- agentOutput({
142
- action: "apps.create",
143
- result: resp.data,
144
- next_steps: [
145
- { command: `naive apps show ${data.id}`, description: "View app details" },
146
- ...(directMode && data.template?.cloneCommand
147
- ? [{ command: data.template.cloneCommand, description: "Clone the starter template to build locally" }]
148
- : []),
149
- { command: `naive apps deploy ${data.id}`, description: directMode ? "Deploy from your project directory" : "Trigger first deployment" },
150
- ],
151
- hints: [
152
- `App "${data.name}" created with status: ${data.status}`,
153
- ...(directMode
154
- ? [
155
- "Direct mode: clone the starter template, build locally, then run 'naive apps deploy' inside the project directory.",
156
- ...(data.template?.repoUrl ? [`Templates repo: ${data.template.repoUrl}`] : []),
157
- ]
158
- : ["An engineer agent has been provisioned and can build the app"]),
159
- ],
160
- related_commands: ["naive apps templates", "naive apps deploy", "naive apps secrets set", "naive apps show"],
161
- });
162
- });
163
- // ─── Templates ───────────────────────────────────────────────────────────────
164
- appsCmd
165
- .command("templates")
166
- .description("List starter templates — clone, customize, then 'naive apps deploy'")
167
- .action(async () => {
168
- const resp = await apiRequest("GET", "/v1/apps/templates");
169
- handleApiError("apps.templates", resp);
170
- agentOutput({
171
- action: "apps.templates",
172
- result: resp.data,
173
- next_steps: [
174
- { command: "naive apps create --name <name> --type frontend_only", description: "Create an app for your template" },
175
- ],
176
- hints: ["Clone a template, build it, then run 'naive apps deploy <app-id>' from the project directory"],
177
- related_commands: ["naive apps create", "naive apps deploy"],
178
- });
179
- });
180
- // ─── Show ────────────────────────────────────────────────────────────────────
181
- appsCmd
182
- .command("show <id>")
183
- .description("Show full details of an app")
184
- .action(async (id) => {
185
- const resp = await apiRequest("GET", `/v1/apps/${id}`);
186
- handleApiError("apps.show", resp);
187
- agentOutput({
188
- action: "apps.show",
189
- result: resp.data,
190
- next_steps: [
191
- { command: `naive apps deploy ${id}`, description: "Deploy latest code" },
192
- { command: `naive apps deployments ${id}`, description: "View deployment history" },
193
- { command: `naive apps secrets list ${id}`, description: "View environment variables" },
194
- ],
195
- related_commands: ["naive apps deploy", "naive apps publish", "naive apps secrets set", "naive apps delete"],
196
- });
197
- });
198
- // ─── Delete ──────────────────────────────────────────────────────────────────
199
- appsCmd
200
- .command("delete <id>")
201
- .description("Permanently delete an app and all infrastructure")
202
- .action(async (id) => {
203
- const resp = await apiRequest("DELETE", `/v1/apps/${id}`);
204
- handleApiError("apps.delete", resp);
205
- agentOutput({
206
- action: "apps.delete",
207
- result: resp.data,
208
- next_steps: [{ command: "naive apps list", description: "View remaining apps" }],
209
- hints: ["App and all associated resources have been deleted"],
210
- });
211
- });
212
- // ─── Deploy ──────────────────────────────────────────────────────────────────
213
- /** Pack a local project directory into a gzipped tarball (node_modules etc. excluded). */
214
- function packDirectory(dir) {
215
- const tarball = join(tmpdir(), `naive-deploy-${Date.now()}.tgz`);
216
- try {
217
- execFileSync("tar", [
218
- "czf", tarball,
219
- "--exclude", "node_modules",
220
- "--exclude", ".next",
221
- "--exclude", ".git",
222
- "--exclude", ".vercel",
223
- "-C", dir,
224
- ".",
225
- ], { stdio: "ignore" });
226
- return readFileSync(tarball);
227
- }
228
- finally {
229
- rmSync(tarball, { force: true });
230
- }
231
- }
232
- function looksLikeProject(dir) {
233
- return existsSync(join(dir, "package.json")) || existsSync(join(dir, "index.html"));
234
- }
235
- appsCmd
236
- .command("deploy <id>")
237
- .description("Deploy the app — uploads your local project directory, or deploys the agent workspace when run inside a container")
238
- .option("--dir <path>", "Local project directory to upload (default: current directory when outside a container)")
239
- .option("--workspace-path <path>", "Container workspace path override (orchestrated mode, relative to hermes home)")
240
- .action(async (id, opts) => {
241
- const hermesHome = process.env.HERMES_HOME;
242
- const cwd = process.cwd();
243
- const insideContainer = Boolean(hermesHome && cwd.startsWith(hermesHome));
244
- // ── Direct mode: pack & upload a local directory ──
245
- if (opts.dir || (!insideContainer && !opts.workspacePath)) {
246
- const dir = resolve(opts.dir ?? cwd);
247
- if (!looksLikeProject(dir)) {
248
- agentOutput({
249
- action: "apps.deploy",
250
- result: { error: `No package.json or index.html found in ${dir}` },
251
- next_steps: [
252
- { command: "naive apps templates", description: "Get the starter template clone command" },
253
- { command: `naive apps deploy ${id} --dir <project-path>`, description: "Point at your project directory" },
254
- ],
255
- hints: ["Run this command inside your project directory (or pass --dir)."],
256
- });
257
- process.exit(1);
258
- }
259
- const tarball = packDirectory(dir);
260
- const resp = await apiUploadGzip(`/v1/apps/${id}/deploy`, tarball);
261
- handleApiError("apps.deploy", resp);
262
- const data = resp.data;
263
- agentOutput({
264
- action: "apps.deploy",
265
- result: resp.data,
266
- next_steps: [
267
- { command: `naive apps publish ${id} --deployment ${data.id}`, description: "Promote to production" },
268
- { command: `naive apps deployments ${id}`, description: "View all deployments" },
269
- ],
270
- hints: [
271
- `Uploaded ${Math.round(tarball.length / 1024)}KB from ${dir}`,
272
- `Preview deployment: ${data.url}`,
273
- ],
274
- related_commands: ["naive apps publish", "naive apps deployments"],
275
- });
276
- return;
277
- }
278
- // ── Orchestrated mode: deploy from the container workspace ──
279
- const body = {};
280
- if (opts.workspacePath) {
281
- body.workspacePath = opts.workspacePath;
282
- }
283
- else if (insideContainer) {
284
- // Auto-detect: if CWD contains an app/ dir, send the relative path so
285
- // the API deploys from the right location
286
- if (existsSync(join(cwd, "app"))) {
287
- body.workspacePath = cwd.slice(hermesHome.length + 1);
288
- }
289
- }
290
- const resp = await apiRequest("POST", `/v1/apps/${id}/deploy`, Object.keys(body).length > 0 ? body : undefined);
291
- handleApiError("apps.deploy", resp);
292
- const data = resp.data;
293
- agentOutput({
294
- action: "apps.deploy",
295
- result: resp.data,
296
- next_steps: [
297
- { command: `naive apps publish ${id} --deployment ${data.id}`, description: "Promote to production" },
298
- { command: `naive apps deployments ${id}`, description: "View all deployments" },
299
- ],
300
- hints: [`Preview deployment: ${data.url}`],
301
- related_commands: ["naive apps publish", "naive apps deployments"],
302
- });
303
- });
304
- // ─── Publish ─────────────────────────────────────────────────────────────────
305
- appsCmd
306
- .command("publish <id>")
307
- .description("Promote a deployment to production")
308
- .requiredOption("--deployment <deploymentId>", "Deployment ID to promote")
309
- .action(async (id, opts) => {
310
- const resp = await apiRequest("POST", `/v1/apps/${id}/publish`, {
311
- deploymentId: opts.deployment,
312
- });
313
- handleApiError("apps.publish", resp);
314
- const data = resp.data;
315
- agentOutput({
316
- action: "apps.publish",
317
- result: resp.data,
318
- next_steps: [
319
- { command: `naive apps show ${id}`, description: "View updated app details" },
320
- { command: `naive apps domains connect ${id} <domainId>`, description: "Connect a custom domain" },
321
- ],
322
- hints: [`Production URL: ${data.url}`],
323
- });
324
- });
325
- // ─── Deployments ─────────────────────────────────────────────────────────────
326
- appsCmd
327
- .command("deployments <id>")
328
- .description("List deployment history for an app")
329
- .action(async (id) => {
330
- const resp = await apiRequest("GET", `/v1/apps/${id}/deployments`);
331
- handleApiError("apps.deployments", resp);
332
- const data = resp.data;
333
- const count = data.deployments?.length ?? 0;
334
- agentOutput({
335
- action: "apps.deployments",
336
- result: resp.data,
337
- next_steps: count > 0
338
- ? [{ command: `naive apps publish ${id} --deployment ${data.deployments[0].id}`, description: "Promote latest to production" }]
339
- : [{ command: `naive apps deploy ${id}`, description: "Trigger a deployment" }],
340
- hints: [`${count} deployment${count !== 1 ? "s" : ""}`],
341
- });
342
- });
343
- // ─── Secrets ─────────────────────────────────────────────────────────────────
344
- const secretsCmd = appsCmd
345
- .command("secrets")
346
- .description("Manage app environment variables");
347
- secretsCmd
348
- .command("list <appId>")
349
- .description("List environment variable keys (values are hidden)")
350
- .action(async (appId) => {
351
- const resp = await apiRequest("GET", `/v1/apps/${appId}/secrets`);
352
- handleApiError("apps.secrets.list", resp);
353
- agentOutput({
354
- action: "apps.secrets.list",
355
- result: resp.data,
356
- next_steps: [
357
- { command: `naive apps secrets set ${appId} MY_KEY my_value --target preview`, description: "Add a variable" },
358
- ],
359
- related_commands: ["naive apps secrets set", "naive apps secrets delete", "naive apps secrets reveal"],
360
- });
361
- });
362
- secretsCmd
363
- .command("set <appId> <key> <value>")
364
- .description("Create or update an environment variable")
365
- .requiredOption("--target <target>", "Target: preview or production")
366
- .action(async (appId, key, value, opts) => {
367
- const resp = await apiRequest("POST", `/v1/apps/${appId}/secrets`, {
368
- key,
369
- value,
370
- target: opts.target,
371
- });
372
- handleApiError("apps.secrets.set", resp);
373
- agentOutput({
374
- action: "apps.secrets.set",
375
- result: resp.data,
376
- next_steps: [
377
- { command: `naive apps secrets list ${appId}`, description: "View all variables" },
378
- { command: `naive apps deploy ${appId}`, description: "Redeploy to apply changes" },
379
- ],
380
- hints: [`Set ${key} for ${opts.target}. Redeploy for changes to take effect.`],
381
- });
382
- });
383
- secretsCmd
384
- .command("delete <appId> <key>")
385
- .description("Delete an environment variable")
386
- .requiredOption("--target <target>", "Target: preview or production")
387
- .action(async (appId, key, opts) => {
388
- const resp = await apiRequest("DELETE", `/v1/apps/${appId}/secrets/${encodeURIComponent(key)}?target=${opts.target}`);
389
- handleApiError("apps.secrets.delete", resp);
390
- agentOutput({
391
- action: "apps.secrets.delete",
392
- result: resp.data,
393
- next_steps: [{ command: `naive apps secrets list ${appId}`, description: "View remaining variables" }],
394
- hints: [`Deleted ${key} from ${opts.target}`],
395
- });
396
- });
397
- secretsCmd
398
- .command("reveal <appId> <key>")
399
- .description("Reveal the value of an environment variable")
400
- .option("--target <target>", "Target: preview or production (default: production)", "production")
401
- .action(async (appId, key, opts) => {
402
- // A typo must NOT silently fall through to production. `reveal` is the one
403
- // secrets verb with plaintext egress, so `--target prevew` answering with the
404
- // PRODUCTION value would hand the caller a secret it did not ask for.
405
- const target = String(opts.target ?? "production");
406
- if (target !== "preview" && target !== "production") {
407
- agentError({
408
- action: "apps.secrets.reveal",
409
- error: {
410
- code: "invalid_input",
411
- message: `Invalid --target "${target}". Use preview or production.`,
412
- },
413
- recovery_steps: [
414
- {
415
- command: `naive apps secrets reveal ${appId} ${key} --target production`,
416
- description: "Reveal the production value (default)",
417
- },
418
- {
419
- command: `naive apps secrets reveal ${appId} ${key} --target preview`,
420
- description: "Reveal the preview value",
421
- },
422
- ],
423
- });
424
- }
425
- const resp = await apiRequest("GET", `/v1/apps/${appId}/secrets/${encodeURIComponent(key)}/reveal?target=${target}`);
426
- handleApiError("apps.secrets.reveal", resp);
427
- agentOutput({
428
- action: "apps.secrets.reveal",
429
- result: resp.data,
430
- next_steps: [
431
- { command: `naive apps secrets set ${appId} ${key} <new-value> --target ${target}`, description: "Update this variable" },
432
- ],
433
- });
434
- });
435
- // ─── Domains ─────────────────────────────────────────────────────────────────
436
- const domainsCmd = appsCmd
437
- .command("domains")
438
- .description("Manage app domains");
439
- domainsCmd
440
- .command("list <appId>")
441
- .description("List domains attached to an app")
442
- .action(async (appId) => {
443
- const resp = await apiRequest("GET", `/v1/apps/${appId}/domains`);
444
- handleApiError("apps.domains.list", resp);
445
- agentOutput({
446
- action: "apps.domains.list",
447
- result: resp.data,
448
- next_steps: [
449
- { command: `naive apps domains add ${appId} example.com`, description: "Add a custom domain" },
450
- { command: `naive apps domains connect ${appId} <domainId>`, description: "Connect a company domain" },
451
- ],
452
- });
453
- });
454
- domainsCmd
455
- .command("add <appId> <domain>")
456
- .description("Add a custom domain to an app")
457
- .action(async (appId, domain) => {
458
- const resp = await apiRequest("POST", `/v1/apps/${appId}/domains`, { domain });
459
- handleApiError("apps.domains.add", resp);
460
- agentOutput({
461
- action: "apps.domains.add",
462
- result: resp.data,
463
- next_steps: [{ command: `naive apps domains list ${appId}`, description: "View all domains" }],
464
- hints: [`Added domain ${domain}. Configure DNS records to point to Vercel.`],
465
- });
466
- });
467
- domainsCmd
468
- .command("remove <appId> <domainId>")
469
- .description("Remove a domain from an app")
470
- .action(async (appId, domainId) => {
471
- const resp = await apiRequest("DELETE", `/v1/apps/${appId}/domains/${domainId}`);
472
- handleApiError("apps.domains.remove", resp);
473
- agentOutput({
474
- action: "apps.domains.remove",
475
- result: resp.data,
476
- next_steps: [{ command: `naive apps domains list ${appId}`, description: "View remaining domains" }],
477
- });
478
- });
479
- domainsCmd
480
- .command("set-primary <appId> <domainId>")
481
- .description("Set a domain as the app's primary production domain")
482
- .action(async (appId, domainId) => {
483
- const resp = await apiRequest("POST", `/v1/apps/${appId}/domains/${domainId}/set-primary`);
484
- handleApiError("apps.domains.set-primary", resp);
485
- agentOutput({
486
- action: "apps.domains.set-primary",
487
- result: resp.data,
488
- next_steps: [{ command: `naive apps domains list ${appId}`, description: "View updated domains" }],
489
- hints: ["Primary domain updated. The next publish will alias production to this domain."],
490
- });
491
- });
492
- domainsCmd
493
- .command("connect <appId> <domainId>")
494
- .description("Connect a company-owned domain to an app as its production domain")
495
- .action(async (appId, domainId) => {
496
- const resp = await apiRequest("POST", `/v1/apps/${appId}/connect-domain`, { domainId });
497
- handleApiError("apps.domains.connect", resp);
498
- const data = resp.data;
499
- const isSystem = /\.usenaive\.ai$/i.test(data.domain ?? "");
500
- agentOutput({
501
- action: "apps.domains.connect",
502
- result: resp.data,
503
- next_steps: data.pendingDns
504
- ? [{ command: `naive apps domains verify-dns ${appId} ${domainId}`, description: "Verify DNS after configuring records" }]
505
- : [{ command: `naive apps show ${appId}`, description: "View updated app" }],
506
- hints: data.pendingDns
507
- ? isSystem
508
- ? [`System domain ${data.domain}: platform writes DNS on usenaive.ai. Retry verify-dns shortly if still pending.`]
509
- : [`DNS records required for ${data.domain}. Add A and CNAME records, then verify.`]
510
- : [`Domain ${data.domain} connected successfully`],
511
- });
512
- });
513
- domainsCmd
514
- .command("disconnect <appId> <domainId>")
515
- .description("Disconnect a company domain from an app")
516
- .action(async (appId, domainId) => {
517
- const resp = await apiRequest("DELETE", `/v1/apps/${appId}/connect-domain/${domainId}`);
518
- handleApiError("apps.domains.disconnect", resp);
519
- agentOutput({
520
- action: "apps.domains.disconnect",
521
- result: resp.data,
522
- next_steps: [{ command: `naive apps show ${appId}`, description: "View updated app" }],
523
- });
524
- });
525
- domainsCmd
526
- .command("verify-dns <appId> <domainId>")
527
- .description("Verify DNS configuration for a connected domain")
528
- .action(async (appId, domainId) => {
529
- const resp = await apiRequest("POST", `/v1/apps/${appId}/verify-domain-dns`, { domainId });
530
- handleApiError("apps.domains.verify-dns", resp);
531
- const data = resp.data;
532
- agentOutput({
533
- action: "apps.domains.verify-dns",
534
- result: resp.data,
535
- next_steps: data.verified
536
- ? [{ command: `naive apps show ${appId}`, description: "View app with verified domain" }]
537
- : [{ command: `naive apps domains verify-dns ${appId} ${domainId}`, description: "Try again after DNS propagation (up to 48h)" }],
538
- hints: data.verified
539
- ? [`Domain ${data.domain} verified and connected`]
540
- : [`DNS not ready for ${data.domain}. Propagation can take up to 48 hours.`],
541
- });
542
- });
543
- // ─── Retry ──────────────────────────────────────────────────────────────────
544
- appsCmd
545
- .command("retry <id>")
546
- .description("Retry failed provisioning (Vercel/Supabase); no-op success if the app is already healthy")
547
- .action(async (id) => {
548
- const resp = await apiRequest("POST", `/v1/apps/${id}/retry`);
549
- handleApiError("apps.retry", resp);
550
- agentOutput({
551
- action: "apps.retry",
552
- result: resp.data,
553
- next_steps: [
554
- { command: `naive apps show ${id}`, description: "Check provisioning status" },
555
- ],
556
- hints: ["Retrying provisioning — check status in a few seconds"],
557
- related_commands: ["naive apps show", "naive apps deploy"],
558
- });
559
- });
560
- // ─── Database (fullstack apps) ──────────────────────────────────────────────
561
- const dbCmd = appsCmd
562
- .command("db")
563
- .description("Database operations for fullstack apps (Supabase)");
564
- dbCmd
565
- .command("tables <appId>")
566
- .description("List database tables for a fullstack app")
567
- .action(async (appId) => {
568
- const resp = await apiRequest("GET", `/v1/apps/${appId}/db/tables`);
569
- handleApiError("apps.db.tables", resp);
570
- agentOutput({
571
- action: "apps.db.tables",
572
- result: resp.data,
573
- next_steps: [
574
- { command: `naive apps db query ${appId} "SELECT * FROM <table> LIMIT 10"`, description: "Query a table" },
575
- ],
576
- related_commands: ["naive apps db query"],
577
- });
578
- });
579
- dbCmd
580
- // [sqlParts...] so unquoted multi-word SQL (agents / probe wrappers that
581
- // word-split) still reaches the API as one query string.
582
- .command("query <appId> [sqlParts...]")
583
- .description("Run a SQL query against the app's Supabase database")
584
- .action(async (appId, sqlParts) => {
585
- const sql = (sqlParts ?? []).join(" ").trim();
586
- if (!sql) {
587
- agentError({
588
- action: "apps.db.query",
589
- error: {
590
- code: "invalid_input",
591
- message: "Missing SQL. Usage: naive apps db query <appId> \"<sql>\"",
592
- },
593
- recovery_steps: [
594
- { command: `naive apps db query ${appId} "SELECT 1"`, description: "Run a quoted SQL query" },
595
- ],
596
- });
597
- }
598
- const resp = await apiRequest("POST", `/v1/apps/${appId}/db/query`, { sql });
599
- handleApiError("apps.db.query", resp);
600
- agentOutput({
601
- action: "apps.db.query",
602
- result: resp.data,
603
- next_steps: [
604
- { command: `naive apps db tables ${appId}`, description: "List available tables" },
605
- ],
606
- related_commands: ["naive apps db tables"],
607
- });
608
- });
609
- // ─── Provider Proxies (advanced) ─────────────────────────────────────────────
610
- /**
611
- * Scan an unquoted JSON value that may contain nested `()`, `{}`, `[]` and
612
- * embedded quotes (e.g. edge-function `content:Deno.serve(() => …)` after
613
- * shlex strips outer quotes — dogfood f877 B64).
614
- *
615
- * Agents often leave JSON-style `\"` inside the unquoted blob
616
- * (`run:\"f877\"`). Treat those as literal `"` in the value — do not enter
617
- * string mode on the escaped quote, or brace/paren depth tracking breaks.
618
- */
619
- function scanUnquotedValue(input, start) {
620
- let i = start;
621
- let depthParen = 0;
622
- let depthBrace = 0;
623
- let depthBracket = 0;
624
- let inStr = null;
625
- let escape = false;
626
- while (i < input.length) {
627
- const c = input[i];
628
- if (inStr) {
629
- if (escape) {
630
- escape = false;
631
- i++;
632
- continue;
633
- }
634
- if (c === "\\") {
635
- escape = true;
636
- i++;
637
- continue;
638
- }
639
- if (c === inStr)
640
- inStr = null;
641
- i++;
642
- continue;
643
- }
644
- // JSON-escaped quotes left after shlex strip → literal quote chars
645
- if (c === "\\" && (input[i + 1] === '"' || input[i + 1] === "'")) {
646
- i += 2;
647
- continue;
648
- }
649
- if (c === '"' || c === "'") {
650
- inStr = c;
651
- i++;
652
- continue;
653
- }
654
- if (c === "(") {
655
- depthParen++;
656
- i++;
657
- continue;
658
- }
659
- if (c === ")") {
660
- depthParen--;
661
- i++;
662
- continue;
663
- }
664
- if (c === "{") {
665
- depthBrace++;
666
- i++;
667
- continue;
668
- }
669
- if (c === "}") {
670
- if (depthBrace === 0 && depthParen === 0 && depthBracket === 0)
671
- break;
672
- depthBrace--;
673
- i++;
674
- continue;
675
- }
676
- if (c === "[") {
677
- depthBracket++;
678
- i++;
679
- continue;
680
- }
681
- if (c === "]") {
682
- if (depthBrace === 0 && depthParen === 0 && depthBracket === 0)
683
- break;
684
- depthBracket--;
685
- i++;
686
- continue;
687
- }
688
- if (c === "," && depthBrace === 0 && depthParen === 0 && depthBracket === 0)
689
- break;
690
- i++;
691
- }
692
- const raw = input.slice(start, i).trimEnd();
693
- // Turn leftover `\"` / `\'` into real quotes in the scalar value
694
- const value = raw.replace(/\\"/g, '"').replace(/\\'/g, "'");
695
- return { value, end: i };
696
- }
697
- /**
698
- * After quoting keys, quote remaining unquoted scalar values — including
699
- * code blobs with parens/braces that the simple `\w` regex cannot match.
700
- */
701
- function quoteUnquotedValues(input) {
702
- const out = [];
703
- let i = 0;
704
- let inString = false;
705
- let escape = false;
706
- while (i < input.length) {
707
- const c = input[i];
708
- if (inString) {
709
- out.push(c);
710
- if (escape)
711
- escape = false;
712
- else if (c === "\\")
713
- escape = true;
714
- else if (c === '"')
715
- inString = false;
716
- i++;
717
- continue;
718
- }
719
- if (c === '"') {
720
- inString = true;
721
- out.push(c);
722
- i++;
723
- continue;
724
- }
725
- if (c === ":") {
726
- out.push(c);
727
- i++;
728
- while (i < input.length && /\s/.test(input[i])) {
729
- out.push(input[i]);
730
- i++;
731
- }
732
- if (i >= input.length)
733
- break;
734
- const rest = input.slice(i);
735
- if (rest.startsWith('"') ||
736
- rest.startsWith("{") ||
737
- rest.startsWith("[") ||
738
- /^(true|false|null)(?=[,}\]\s]|$)/.test(rest) ||
739
- /^-?\d+(\.\d+)?([eE][+-]?\d+)?(?=[,}\]\s]|$)/.test(rest)) {
740
- continue;
741
- }
742
- const { value, end } = scanUnquotedValue(input, i);
743
- out.push(JSON.stringify(value));
744
- i = end;
745
- continue;
746
- }
747
- out.push(c);
748
- i++;
749
- }
750
- return out.join("");
751
- }
752
- /**
753
- * Parse --body JSON. Agents / shlex often strip quotes from
754
- * `{"a":"b"}` → `{a:b}`, and word-split leave `{` `a:b` `}` tokens.
755
- * Join tokens, try JSON.parse, then repair unquoted keys/values (including
756
- * nested edge-function `files[].content` source strings).
757
- */
758
- export function parseJsonBody(raw, flag) {
759
- if (raw == null)
760
- return undefined;
761
- const text = (Array.isArray(raw) ? raw.join(" ") : String(raw)).trim();
762
- if (!text)
763
- return undefined;
764
- try {
765
- return JSON.parse(text);
766
- }
767
- catch {
768
- // no-op — try repair below
769
- }
770
- try {
771
- const withQuotedKeys = text.replace(/([{\[,]\s*)([A-Za-z_][\w]*)(\s*:)/g, '$1"$2"$3');
772
- const repaired = quoteUnquotedValues(withQuotedKeys);
773
- return JSON.parse(repaired);
774
- }
775
- catch {
776
- console.error(`Invalid JSON passed to ${flag}`);
777
- process.exit(1);
778
- }
779
- }
780
- appsCmd
781
- .command("vercel <appId> <method> <path>")
782
- .description("Call any Vercel REST API operation, scoped to the app's Vercel project (credentials injected by Naive)")
783
- .option("--body <json...>", "JSON request body (unquoted / word-split OK for flat objects)")
784
- .addHelpText("after", `
785
- Examples:
786
- naive apps vercel <id> GET v6/deployments List deployments
787
- naive apps vercel <id> GET "v13/deployments/<deploymentId>" Deployment status
788
- naive apps vercel <id> GET "v3/deployments/<deploymentId>/events" Build logs
789
- naive apps vercel <id> GET "v9/projects/<projectId>/domains" Project domains
790
- naive apps vercel <id> PATCH "v9/projects/<projectId>" --body '{"buildCommand":"next build"}'
791
-
792
- Scope: only this app's project (vN/projects/{projectId}/**) and its
793
- deployments (vN/deployments/**) are reachable. Deleting the project itself is
794
- blocked — use 'naive apps delete'. See https://vercel.com/docs/rest-api.
795
- `)
796
- .action(async (appId, method, path, opts) => {
797
- const body = parseJsonBody(opts.body, "--body");
798
- const resp = await apiRequest(method.toUpperCase(), `/v1/apps/${appId}/vercel/proxy/${path.replace(/^\/+/, "")}`, body);
799
- handleApiError("apps.vercel", resp);
800
- agentOutput({
801
- action: "apps.vercel",
802
- result: resp.data,
803
- next_steps: [{ command: `naive apps show ${appId}`, description: "View app details" }],
804
- hints: [`Proxied ${method.toUpperCase()} ${path} to the Vercel API`],
805
- related_commands: ["naive apps supabase", "naive apps show"],
806
- });
807
- });
808
- appsCmd
809
- .command("supabase <appId> <method> <path>")
810
- .description("Call any Supabase Management API operation, scoped to the app's Supabase project (fullstack apps only)")
811
- .option("--body <json...>", "JSON request body (unquoted / word-split OK for flat objects)")
812
- .addHelpText("after", `
813
- Examples:
814
- naive apps supabase <id> GET "v1/projects/<ref>" Project details
815
- naive apps supabase <id> GET "v1/projects/<ref>/config/auth" Auth config
816
- naive apps supabase <id> PATCH "v1/projects/<ref>/config/auth" --body '{"site_url":"https://example.com"}'
817
- naive apps supabase <id> GET "v1/projects/<ref>/functions" List edge functions
818
- naive apps supabase <id> POST "v1/projects/<ref>/functions" --body '{"slug":"hello","name":"hello","verify_jwt":false,"body":"Deno.serve(() => new Response(\\"ok\\"))"}'
819
- naive apps supabase <id> POST "v1/projects/<ref>/functions/deploy?slug=hello" --body '{"name":"hello","verify_jwt":false,"files":[{"name":"index.ts","content":"Deno.serve(() => new Response(\\"ok\\"))"}]}'
820
- naive apps supabase <id> POST "v1/projects/<ref>/database/query" --body '{"query":"select * from users limit 10"}'
821
-
822
- Edge functions:
823
- - Create (JSON): POST …/functions with slug, name, and a source \`body\` string.
824
- - Deploy/update (preferred): POST …/functions/deploy?slug=<slug> with files:[{name,content}].
825
- The proxy converts that JSON into multipart file parts (one per source file).
826
- Docs: /docs/api-reference/functions/overview
827
-
828
- Scope: only this app's project (v1/projects/{ref}/**) is reachable. Deleting
829
- the project itself is blocked — use 'naive apps delete'. See
830
- https://supabase.com/docs/reference/api.
831
- `)
832
- .action(async (appId, method, path, opts) => {
833
- const body = parseJsonBody(opts.body, "--body");
834
- const resp = await apiRequest(method.toUpperCase(), `/v1/apps/${appId}/supabase/proxy/${path.replace(/^\/+/, "")}`, body);
835
- handleApiError("apps.supabase", resp);
836
- agentOutput({
837
- action: "apps.supabase",
838
- result: resp.data,
839
- next_steps: [{ command: `naive apps show ${appId}`, description: "View app details" }],
840
- hints: [`Proxied ${method.toUpperCase()} ${path} to the Supabase Management API`],
841
- related_commands: ["naive apps vercel", "naive apps db query"],
842
- });
843
- });
844
- //# sourceMappingURL=apps.js.map