@usenaive-sdk/cli 0.12.5 → 0.13.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/README.md +69 -6
- package/dist/client.d.ts +48 -0
- package/dist/client.js +199 -27
- package/dist/client.js.map +1 -1
- package/dist/commands/aeo.js +58 -23
- package/dist/commands/aeo.js.map +1 -1
- package/dist/commands/app-data.js +29 -11
- package/dist/commands/app-data.js.map +1 -1
- package/dist/commands/approvals.js +142 -9
- package/dist/commands/approvals.js.map +1 -1
- package/dist/commands/apps.d.ts +7 -0
- package/dist/commands/apps.js +255 -18
- package/dist/commands/apps.js.map +1 -1
- package/dist/commands/audio.d.ts +9 -0
- package/dist/commands/audio.js +391 -0
- package/dist/commands/audio.js.map +1 -0
- package/dist/commands/auth.d.ts +1 -0
- package/dist/commands/auth.js +47 -19
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/billing.js +9 -9
- package/dist/commands/billing.js.map +1 -1
- package/dist/commands/brain.js +813 -54
- package/dist/commands/brain.js.map +1 -1
- package/dist/commands/browser.js +8 -8
- package/dist/commands/browser.js.map +1 -1
- package/dist/commands/business.js +117 -16
- package/dist/commands/business.js.map +1 -1
- package/dist/commands/clone.js +8 -4
- package/dist/commands/clone.js.map +1 -1
- package/dist/commands/companies.d.ts +8 -0
- package/dist/commands/companies.js +137 -47
- package/dist/commands/companies.js.map +1 -1
- package/dist/commands/company-data.d.ts +2 -0
- package/dist/commands/company-data.js +168 -0
- package/dist/commands/company-data.js.map +1 -0
- package/dist/commands/compute.js +295 -18
- package/dist/commands/compute.js.map +1 -1
- package/dist/commands/connections.d.ts +6 -0
- package/dist/commands/connections.js +42 -2
- package/dist/commands/connections.js.map +1 -1
- package/dist/commands/domains.js +63 -19
- package/dist/commands/domains.js.map +1 -1
- package/dist/commands/ecommerce.js +19 -9
- package/dist/commands/ecommerce.js.map +1 -1
- package/dist/commands/email.js +56 -9
- package/dist/commands/email.js.map +1 -1
- package/dist/commands/formation.js +5 -5
- package/dist/commands/formation.js.map +1 -1
- package/dist/commands/identity.js +4 -3
- package/dist/commands/identity.js.map +1 -1
- package/dist/commands/images.js +86 -12
- package/dist/commands/images.js.map +1 -1
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.js +44 -36
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/jobs.js +1 -0
- package/dist/commands/jobs.js.map +1 -1
- package/dist/commands/legacy-auth.d.ts +27 -0
- package/dist/commands/legacy-auth.js +64 -0
- package/dist/commands/legacy-auth.js.map +1 -0
- package/dist/commands/llm.js +14 -1
- package/dist/commands/llm.js.map +1 -1
- package/dist/commands/login.js +2 -0
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.d.ts +7 -0
- package/dist/commands/logout.js +55 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/media.js +3 -3
- package/dist/commands/media.js.map +1 -1
- package/dist/commands/mobile.d.ts +2 -0
- package/dist/commands/mobile.js +42 -1
- package/dist/commands/mobile.js.map +1 -1
- package/dist/commands/payments.js +1 -1
- package/dist/commands/people.d.ts +2 -0
- package/dist/commands/people.js +197 -0
- package/dist/commands/people.js.map +1 -0
- package/dist/commands/phone.js +40 -83
- package/dist/commands/phone.js.map +1 -1
- package/dist/commands/projects.d.ts +13 -0
- package/dist/commands/projects.js +220 -0
- package/dist/commands/projects.js.map +1 -0
- package/dist/commands/register.js +13 -5
- package/dist/commands/register.js.map +1 -1
- package/dist/commands/sandbox.d.ts +2 -0
- package/dist/commands/sandbox.js +558 -0
- package/dist/commands/sandbox.js.map +1 -0
- package/dist/commands/search.js +27 -13
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/seo.js +16 -8
- package/dist/commands/seo.js.map +1 -1
- package/dist/commands/sessions.d.ts +6 -0
- package/dist/commands/sessions.js +109 -0
- package/dist/commands/sessions.js.map +1 -0
- package/dist/commands/social-data.d.ts +2 -0
- package/dist/commands/social-data.js +245 -0
- package/dist/commands/social-data.js.map +1 -0
- package/dist/commands/social.js +9 -7
- package/dist/commands/social.js.map +1 -1
- package/dist/commands/tasks.js +9 -0
- package/dist/commands/tasks.js.map +1 -1
- package/dist/commands/teams.d.ts +69 -0
- package/dist/commands/teams.js +503 -0
- package/dist/commands/teams.js.map +1 -0
- package/dist/commands/up.d.ts +150 -0
- package/dist/commands/up.js +465 -15
- package/dist/commands/up.js.map +1 -1
- package/dist/commands/usage.js +15 -4
- package/dist/commands/usage.js.map +1 -1
- package/dist/commands/use.d.ts +9 -0
- package/dist/commands/use.js +76 -11
- package/dist/commands/use.js.map +1 -1
- package/dist/commands/users.d.ts +8 -0
- package/dist/commands/users.js +28 -9
- package/dist/commands/users.js.map +1 -1
- package/dist/commands/vault.js +31 -1
- package/dist/commands/vault.js.map +1 -1
- package/dist/commands/verification.js +1 -1
- package/dist/commands/verification.js.map +1 -1
- package/dist/commands/video.js +118 -19
- package/dist/commands/video.js.map +1 -1
- package/dist/commands/wallet.js +3 -3
- package/dist/commands/wallet.js.map +1 -1
- package/dist/commands/whoami.js +17 -1
- package/dist/commands/whoami.js.map +1 -1
- package/dist/config.d.ts +16 -1
- package/dist/config.js +15 -1
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +250 -24
- package/dist/index.js.map +1 -1
- package/dist/lib/brain-select.d.ts +193 -0
- package/dist/lib/brain-select.js +403 -0
- package/dist/lib/brain-select.js.map +1 -0
- package/dist/lib/cli-validation.d.ts +12 -0
- package/dist/lib/cli-validation.js +46 -0
- package/dist/lib/cli-validation.js.map +1 -0
- package/dist/lib/deprecation.d.ts +158 -0
- package/dist/lib/deprecation.js +140 -0
- package/dist/lib/deprecation.js.map +1 -0
- package/dist/lib/duration.d.ts +8 -0
- package/dist/lib/duration.js +11 -0
- package/dist/lib/duration.js.map +1 -0
- package/dist/lib/http-response.d.ts +11 -0
- package/dist/lib/http-response.js +96 -0
- package/dist/lib/http-response.js.map +1 -0
- package/dist/lib/pricing.d.ts +132 -0
- package/dist/lib/pricing.js +148 -0
- package/dist/lib/pricing.js.map +1 -0
- package/dist/lib/stream-frames.d.ts +114 -0
- package/dist/lib/stream-frames.js +169 -0
- package/dist/lib/stream-frames.js.map +1 -0
- package/dist/lib/teams-catalog.d.ts +141 -0
- package/dist/lib/teams-catalog.js +765 -0
- package/dist/lib/teams-catalog.js.map +1 -0
- package/dist/lib/unknown-command.d.ts +55 -1
- package/dist/lib/unknown-command.js +113 -0
- package/dist/lib/unknown-command.js.map +1 -1
- package/dist/output.d.ts +127 -5
- package/dist/output.js +189 -12
- package/dist/output.js.map +1 -1
- package/package.json +3 -3
- package/dist/commands/link.d.ts +0 -3
- package/dist/commands/link.js +0 -91
- package/dist/commands/link.js.map +0 -1
|
@@ -1,10 +1,90 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import { apiRequest, handleApiError, activeUserId } from "../client.js";
|
|
3
3
|
import { agentOutput } from "../output.js";
|
|
4
|
+
/**
|
|
5
|
+
* THE SUCCESS ENVELOPE.
|
|
6
|
+
*
|
|
7
|
+
* `naive --help` promises "every command returns structured JSON with result
|
|
8
|
+
* data, next steps, and contextual guidance for autonomous operation"
|
|
9
|
+
* (index.ts), /cli/overview documents the same shape. `approvals` shipped with
|
|
10
|
+
* `next_steps: []` on `get`/`deny`/`watch`, `<id>` placeholders on `list`, and
|
|
11
|
+
* no `hints` anywhere — so an agent that listed its own frozen actions was told
|
|
12
|
+
* neither which id to act on nor that a pending action has not run yet.
|
|
13
|
+
*
|
|
14
|
+
* Both are DERIVED from the response the API just returned — the id in a
|
|
15
|
+
* suggested command is an id the API echoed (`serializeApproval`,
|
|
16
|
+
* api/src/services/approvals.ts:410), a hint restates a field it actually sent —
|
|
17
|
+
* so neither can drift from the queue's real state. Same rule `workloadHints`
|
|
18
|
+
* follows in compute.ts and `creditCostHint` in output.ts.
|
|
19
|
+
*/
|
|
4
20
|
/** Resolve the user path segment — explicit --user wins, else active, else "default". */
|
|
5
21
|
function userPath(user) {
|
|
6
22
|
return `/v1/users/${user ?? activeUserId() ?? "default"}`;
|
|
7
23
|
}
|
|
24
|
+
/** A non-empty string field, or undefined — the API sends `null` for unset. */
|
|
25
|
+
function str(o, k) {
|
|
26
|
+
const v = o?.[k];
|
|
27
|
+
return typeof v === "string" && v ? v : undefined;
|
|
28
|
+
}
|
|
29
|
+
/** The id for a suggested command: the one the API echoed, else what the caller
|
|
30
|
+
* typed, so a next step is copy-pasteable rather than an `<id>` placeholder. */
|
|
31
|
+
function aid(data, typed) {
|
|
32
|
+
return str(data, "id") ?? typed ?? "<id>";
|
|
33
|
+
}
|
|
34
|
+
/** The rows of a queue read — the API answers `{ approvals: [...] }`. */
|
|
35
|
+
function rows(data) {
|
|
36
|
+
const a = data?.approvals;
|
|
37
|
+
if (!Array.isArray(a))
|
|
38
|
+
return [];
|
|
39
|
+
return a.filter((r) => !!r && typeof r === "object");
|
|
40
|
+
}
|
|
41
|
+
/** What `pending` MEANS, stated once — the action is frozen and has not run. */
|
|
42
|
+
const FROZEN = "Pending means frozen: the action has NOT run yet, and runs only if it is approved.";
|
|
43
|
+
/** Hints echoed off one approval the API returned — restated, never asserted. */
|
|
44
|
+
function approvalHints(data) {
|
|
45
|
+
const out = [];
|
|
46
|
+
const status = str(data, "status");
|
|
47
|
+
if (status)
|
|
48
|
+
out.push(`Status: ${status}`);
|
|
49
|
+
const title = str(data, "title");
|
|
50
|
+
if (title)
|
|
51
|
+
out.push(`Action: ${title}`);
|
|
52
|
+
const type = str(data, "action_type");
|
|
53
|
+
if (type)
|
|
54
|
+
out.push(`Action type: ${type}`);
|
|
55
|
+
const reason = str(data, "reason");
|
|
56
|
+
if (reason)
|
|
57
|
+
out.push(`Reason on record: ${reason}`);
|
|
58
|
+
const err = str(data, "error");
|
|
59
|
+
if (err)
|
|
60
|
+
out.push(`Failed with: ${err}`);
|
|
61
|
+
if (status === "pending")
|
|
62
|
+
out.push(FROZEN);
|
|
63
|
+
if (status === "executed")
|
|
64
|
+
out.push("Already replayed by the API — `result` holds what the action returned.");
|
|
65
|
+
if (status === "denied")
|
|
66
|
+
out.push("Denied — this action will never run.");
|
|
67
|
+
// The contract is a NON-EMPTY hints array; a row the API sent with none of the
|
|
68
|
+
// fields above still has to say something true rather than nothing.
|
|
69
|
+
return out.length > 0 ? out : ["The API returned this approval with no status or title."];
|
|
70
|
+
}
|
|
71
|
+
/** Hints for a queue read — the shape of the queue the API just returned. */
|
|
72
|
+
function queueHints(list, filter) {
|
|
73
|
+
const out = [list.length === 1 ? "1 approval." : `${list.length} approvals.`];
|
|
74
|
+
if (filter)
|
|
75
|
+
out.push(`Filtered by status: ${filter}.`);
|
|
76
|
+
const counts = new Map();
|
|
77
|
+
for (const r of list)
|
|
78
|
+
counts.set(str(r, "status") ?? "unknown", (counts.get(str(r, "status") ?? "unknown") ?? 0) + 1);
|
|
79
|
+
if (counts.size > 0)
|
|
80
|
+
out.push(`Statuses: ${[...counts].map(([s, n]) => `${s} ${n}`).join(", ")}.`);
|
|
81
|
+
if ((counts.get("pending") ?? 0) > 0)
|
|
82
|
+
out.push(FROZEN);
|
|
83
|
+
if (list.length === 0) {
|
|
84
|
+
out.push('Only actions that require human approval land here — a gated action returns HTTP 202 with status "pending_approval" and waits.');
|
|
85
|
+
}
|
|
86
|
+
return out;
|
|
87
|
+
}
|
|
8
88
|
export const approvalsCmd = new Command("approvals")
|
|
9
89
|
.alias("approval")
|
|
10
90
|
.description("Governance — review & resolve agent-requested approvals for sensitive actions")
|
|
@@ -39,13 +119,25 @@ approvalsCmd
|
|
|
39
119
|
const q = opts.status ? `?status=${encodeURIComponent(opts.status)}` : "";
|
|
40
120
|
const resp = await apiRequest("GET", `${userPath(opts.user)}/approvals${q}`, undefined, { userId: opts.user });
|
|
41
121
|
handleApiError("approvals.list", resp);
|
|
122
|
+
const list = rows(resp.data);
|
|
123
|
+
// Point at a REAL row — a pending one first, since that is the only state
|
|
124
|
+
// approve/deny can act on. With an empty queue there is no id to name, so
|
|
125
|
+
// the next step is the re-read that would surface one.
|
|
126
|
+
const target = list.find((r) => str(r, "status") === "pending") ?? list[0];
|
|
127
|
+
const next = target
|
|
128
|
+
? [
|
|
129
|
+
{ command: `naive approvals get ${aid(target)}`, description: "Show this approval's frozen payload" },
|
|
130
|
+
{ command: `naive approvals approve ${aid(target)}`, description: "Approve it — the API replays the action" },
|
|
131
|
+
{ command: `naive approvals deny ${aid(target)}`, description: "Deny it — the action never runs" },
|
|
132
|
+
]
|
|
133
|
+
: opts.status
|
|
134
|
+
? [{ command: "naive approvals list", description: `Show every approval, not just "${opts.status}"` }]
|
|
135
|
+
: [{ command: "naive approvals list --status pending", description: "Re-check for newly frozen actions" }];
|
|
42
136
|
agentOutput({
|
|
43
137
|
action: "approvals.list",
|
|
44
138
|
result: resp.data,
|
|
45
|
-
next_steps:
|
|
46
|
-
|
|
47
|
-
{ command: "naive approvals deny <id>", description: "Deny a pending action" },
|
|
48
|
-
],
|
|
139
|
+
next_steps: next,
|
|
140
|
+
hints: queueHints(list, opts.status),
|
|
49
141
|
});
|
|
50
142
|
});
|
|
51
143
|
approvalsCmd
|
|
@@ -56,7 +148,20 @@ approvalsCmd
|
|
|
56
148
|
.action(async (id, opts) => {
|
|
57
149
|
const resp = await apiRequest("GET", `${userPath(opts.user)}/approvals/${id}`, undefined, { userId: opts.user });
|
|
58
150
|
handleApiError("approvals.get", resp);
|
|
59
|
-
agentOutput({
|
|
151
|
+
agentOutput({
|
|
152
|
+
action: "approvals.get",
|
|
153
|
+
result: resp.data,
|
|
154
|
+
// Only a pending approval can be approved, denied or waited on; once it is
|
|
155
|
+
// resolved the honest next move is back to the queue.
|
|
156
|
+
next_steps: str(resp.data, "status") === "pending"
|
|
157
|
+
? [
|
|
158
|
+
{ command: `naive approvals approve ${aid(resp.data, id)}`, description: "Approve — the API replays the frozen action" },
|
|
159
|
+
{ command: `naive approvals deny ${aid(resp.data, id)}`, description: "Deny — the action never runs" },
|
|
160
|
+
{ command: `naive approvals watch ${aid(resp.data, id)}`, description: "Block until someone resolves it" },
|
|
161
|
+
]
|
|
162
|
+
: [{ command: "naive approvals list --status pending", description: "Back to the actions still awaiting a decision" }],
|
|
163
|
+
hints: approvalHints(resp.data),
|
|
164
|
+
});
|
|
60
165
|
});
|
|
61
166
|
approvalsCmd
|
|
62
167
|
.command("approve")
|
|
@@ -71,7 +176,11 @@ approvalsCmd
|
|
|
71
176
|
agentOutput({
|
|
72
177
|
action: "approvals.approve",
|
|
73
178
|
result: resp.data,
|
|
74
|
-
next_steps: [
|
|
179
|
+
next_steps: [
|
|
180
|
+
{ command: `naive approvals get ${aid(resp.data, id)}`, description: "Inspect the execution result" },
|
|
181
|
+
{ command: "naive approvals list --status pending", description: "Continue with the rest of the queue" },
|
|
182
|
+
],
|
|
183
|
+
hints: approvalHints(resp.data),
|
|
75
184
|
});
|
|
76
185
|
});
|
|
77
186
|
approvalsCmd
|
|
@@ -83,7 +192,15 @@ approvalsCmd
|
|
|
83
192
|
.action(async (id, opts) => {
|
|
84
193
|
const resp = await apiRequest("POST", `${userPath(opts.user)}/approvals/${id}/deny`, { reason: opts.reason }, { userId: opts.user });
|
|
85
194
|
handleApiError("approvals.deny", resp);
|
|
86
|
-
agentOutput({
|
|
195
|
+
agentOutput({
|
|
196
|
+
action: "approvals.deny",
|
|
197
|
+
result: resp.data,
|
|
198
|
+
next_steps: [
|
|
199
|
+
{ command: `naive approvals get ${aid(resp.data, id)}`, description: "Confirm the recorded denial and its reason" },
|
|
200
|
+
{ command: "naive approvals list --status pending", description: "Continue with the rest of the queue" },
|
|
201
|
+
],
|
|
202
|
+
hints: approvalHints(resp.data),
|
|
203
|
+
});
|
|
87
204
|
});
|
|
88
205
|
approvalsCmd
|
|
89
206
|
.command("watch")
|
|
@@ -99,8 +216,24 @@ approvalsCmd
|
|
|
99
216
|
const resp = await apiRequest("GET", `${userPath(opts.user)}/approvals/${id}`, undefined, { userId: opts.user });
|
|
100
217
|
handleApiError("approvals.watch", resp);
|
|
101
218
|
const status = resp.data.status;
|
|
102
|
-
|
|
103
|
-
|
|
219
|
+
const timedOut = Date.now() >= deadline;
|
|
220
|
+
if (status !== "pending" || timedOut) {
|
|
221
|
+
// Two very different exits share this return: resolved, or gave up while
|
|
222
|
+
// still pending. The envelope has to say which one happened.
|
|
223
|
+
const gaveUp = status === "pending" && timedOut;
|
|
224
|
+
agentOutput({
|
|
225
|
+
action: "approvals.watch",
|
|
226
|
+
result: resp.data,
|
|
227
|
+
next_steps: gaveUp
|
|
228
|
+
? [
|
|
229
|
+
{ command: `naive approvals watch ${aid(resp.data, id)}`, description: "Keep waiting — it is still pending" },
|
|
230
|
+
{ command: `naive approvals approve ${aid(resp.data, id)}`, description: "Stop waiting and approve it now" },
|
|
231
|
+
]
|
|
232
|
+
: [{ command: "naive approvals list --status pending", description: "Back to the actions still awaiting a decision" }],
|
|
233
|
+
hints: gaveUp
|
|
234
|
+
? [...approvalHints(resp.data), `Timed out after ${opts.timeout ?? "300000"}ms while still pending — nothing was decided.`]
|
|
235
|
+
: approvalHints(resp.data),
|
|
236
|
+
});
|
|
104
237
|
return;
|
|
105
238
|
}
|
|
106
239
|
await new Promise((r) => setTimeout(r, interval));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approvals.js","sourceRoot":"","sources":["../../src/commands/approvals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,yFAAyF;AACzF,SAAS,QAAQ,CAAC,IAAa;IAC7B,OAAO,aAAa,IAAI,IAAI,YAAY,EAAE,IAAI,SAAS,EAAE,CAAC;AAC5D,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,WAAW,CAAC;KACjD,KAAK,CAAC,UAAU,CAAC;KACjB,WAAW,CAAC,+EAA+E,CAAC;KAC5F,WAAW,CACV,OAAO,EACP;;;;;;;;;;;;;;;;;;;;;CAqBH,CACE,CAAC;AAEJ,YAAY;KACT,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,8CAA8C,CAAC;KAC3D,MAAM,CAAC,aAAa,EAAE,+BAA+B,CAAC;KACtD,MAAM,CAAC,mBAAmB,EAAE,gDAAgD,CAAC;KAC7E,MAAM,CAAC,KAAK,EAAE,IAAwC,EAAE,EAAE;IACzD,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1E,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/G,cAAc,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;IACvC,
|
|
1
|
+
{"version":3,"file":"approvals.js","sourceRoot":"","sources":["../../src/commands/approvals.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/apps.d.ts
CHANGED
|
@@ -1,2 +1,9 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
export declare const appsCmd: Command;
|
|
3
|
+
/**
|
|
4
|
+
* Parse --body JSON. Agents / shlex often strip quotes from
|
|
5
|
+
* `{"a":"b"}` → `{a:b}`, and word-split leave `{` `a:b` `}` tokens.
|
|
6
|
+
* Join tokens, try JSON.parse, then repair unquoted keys/values (including
|
|
7
|
+
* nested edge-function `files[].content` source strings).
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseJsonBody(raw: string | string[] | undefined, flag: string): Record<string, unknown> | undefined;
|
package/dist/commands/apps.js
CHANGED
|
@@ -4,7 +4,7 @@ import { readFileSync, existsSync, rmSync } from "node:fs";
|
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
5
|
import { join, resolve } from "node:path";
|
|
6
6
|
import { apiRequest, apiUploadGzip, handleApiError } from "../client.js";
|
|
7
|
-
import { agentOutput } from "../output.js";
|
|
7
|
+
import { agentError, agentOutput } from "../output.js";
|
|
8
8
|
export const appsCmd = new Command("apps")
|
|
9
9
|
.description("Web apps — create, deploy, manage Vercel-backed web applications with dedicated engineer agents")
|
|
10
10
|
.addHelpText("after", `
|
|
@@ -17,7 +17,7 @@ Subcommands:
|
|
|
17
17
|
naive apps deploy <id> [--dir <path>] Deploy (local directory upload, or agent workspace inside containers)
|
|
18
18
|
naive apps publish <id> --deployment <id> Promote a deployment to production
|
|
19
19
|
naive apps deployments <id> List deployment history
|
|
20
|
-
naive apps retry <id> Retry failed provisioning
|
|
20
|
+
naive apps retry <id> Retry failed provisioning (noop if healthy)
|
|
21
21
|
naive apps secrets list <id> List env variable keys
|
|
22
22
|
naive apps secrets set <id> <KEY> <VALUE> Set an env variable
|
|
23
23
|
naive apps secrets delete <id> <KEY> Delete an env variable
|
|
@@ -96,15 +96,44 @@ appsCmd
|
|
|
96
96
|
.command("create")
|
|
97
97
|
.description("Create a new web app with a dedicated engineer agent")
|
|
98
98
|
.requiredOption("--name <name>", "App name")
|
|
99
|
-
.
|
|
99
|
+
.option("--type <type>", "App type: frontend_only or fullstack (default: frontend_only)", "frontend_only")
|
|
100
100
|
.option("--variant <variant>", "Template variant: dark-premium, clean-minimal, bold-energetic, warm-human")
|
|
101
|
-
|
|
101
|
+
// <desc...> so unquoted multi-word descriptions are not excess args
|
|
102
|
+
.option("--description <desc...>", "Short description (unquoted multi-word OK)")
|
|
102
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;
|
|
103
132
|
const resp = await apiRequest("POST", "/v1/apps", {
|
|
104
133
|
name: opts.name,
|
|
105
|
-
type
|
|
134
|
+
type,
|
|
106
135
|
...(opts.variant && { variant: opts.variant }),
|
|
107
|
-
...(
|
|
136
|
+
...(description && { description }),
|
|
108
137
|
});
|
|
109
138
|
handleApiError("apps.create", resp);
|
|
110
139
|
const data = resp.data;
|
|
@@ -368,15 +397,38 @@ secretsCmd
|
|
|
368
397
|
secretsCmd
|
|
369
398
|
.command("reveal <appId> <key>")
|
|
370
399
|
.description("Reveal the value of an environment variable")
|
|
371
|
-
.
|
|
400
|
+
.option("--target <target>", "Target: preview or production (default: production)", "production")
|
|
372
401
|
.action(async (appId, key, opts) => {
|
|
373
|
-
|
|
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}`);
|
|
374
426
|
handleApiError("apps.secrets.reveal", resp);
|
|
375
427
|
agentOutput({
|
|
376
428
|
action: "apps.secrets.reveal",
|
|
377
429
|
result: resp.data,
|
|
378
430
|
next_steps: [
|
|
379
|
-
{ command: `naive apps secrets set ${appId} ${key} <new-value> --target ${
|
|
431
|
+
{ command: `naive apps secrets set ${appId} ${key} <new-value> --target ${target}`, description: "Update this variable" },
|
|
380
432
|
],
|
|
381
433
|
});
|
|
382
434
|
});
|
|
@@ -444,6 +496,7 @@ domainsCmd
|
|
|
444
496
|
const resp = await apiRequest("POST", `/v1/apps/${appId}/connect-domain`, { domainId });
|
|
445
497
|
handleApiError("apps.domains.connect", resp);
|
|
446
498
|
const data = resp.data;
|
|
499
|
+
const isSystem = /\.usenaive\.ai$/i.test(data.domain ?? "");
|
|
447
500
|
agentOutput({
|
|
448
501
|
action: "apps.domains.connect",
|
|
449
502
|
result: resp.data,
|
|
@@ -451,7 +504,9 @@ domainsCmd
|
|
|
451
504
|
? [{ command: `naive apps domains verify-dns ${appId} ${domainId}`, description: "Verify DNS after configuring records" }]
|
|
452
505
|
: [{ command: `naive apps show ${appId}`, description: "View updated app" }],
|
|
453
506
|
hints: data.pendingDns
|
|
454
|
-
?
|
|
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.`]
|
|
455
510
|
: [`Domain ${data.domain} connected successfully`],
|
|
456
511
|
});
|
|
457
512
|
});
|
|
@@ -488,7 +543,7 @@ domainsCmd
|
|
|
488
543
|
// ─── Retry ──────────────────────────────────────────────────────────────────
|
|
489
544
|
appsCmd
|
|
490
545
|
.command("retry <id>")
|
|
491
|
-
.description("Retry failed provisioning (Vercel/Supabase
|
|
546
|
+
.description("Retry failed provisioning (Vercel/Supabase); no-op success if the app is already healthy")
|
|
492
547
|
.action(async (id) => {
|
|
493
548
|
const resp = await apiRequest("POST", `/v1/apps/${id}/retry`);
|
|
494
549
|
handleApiError("apps.retry", resp);
|
|
@@ -522,9 +577,24 @@ dbCmd
|
|
|
522
577
|
});
|
|
523
578
|
});
|
|
524
579
|
dbCmd
|
|
525
|
-
|
|
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...]")
|
|
526
583
|
.description("Run a SQL query against the app's Supabase database")
|
|
527
|
-
.action(async (appId,
|
|
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
|
+
}
|
|
528
598
|
const resp = await apiRequest("POST", `/v1/apps/${appId}/db/query`, { sql });
|
|
529
599
|
handleApiError("apps.db.query", resp);
|
|
530
600
|
agentOutput({
|
|
@@ -537,11 +607,170 @@ dbCmd
|
|
|
537
607
|
});
|
|
538
608
|
});
|
|
539
609
|
// ─── Provider Proxies (advanced) ─────────────────────────────────────────────
|
|
540
|
-
|
|
541
|
-
|
|
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)
|
|
542
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
|
+
}
|
|
543
770
|
try {
|
|
544
|
-
|
|
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);
|
|
545
774
|
}
|
|
546
775
|
catch {
|
|
547
776
|
console.error(`Invalid JSON passed to ${flag}`);
|
|
@@ -551,7 +780,7 @@ function parseJsonBody(raw, flag) {
|
|
|
551
780
|
appsCmd
|
|
552
781
|
.command("vercel <appId> <method> <path>")
|
|
553
782
|
.description("Call any Vercel REST API operation, scoped to the app's Vercel project (credentials injected by Naive)")
|
|
554
|
-
.option("--body <json
|
|
783
|
+
.option("--body <json...>", "JSON request body (unquoted / word-split OK for flat objects)")
|
|
555
784
|
.addHelpText("after", `
|
|
556
785
|
Examples:
|
|
557
786
|
naive apps vercel <id> GET v6/deployments List deployments
|
|
@@ -579,15 +808,23 @@ blocked — use 'naive apps delete'. See https://vercel.com/docs/rest-api.
|
|
|
579
808
|
appsCmd
|
|
580
809
|
.command("supabase <appId> <method> <path>")
|
|
581
810
|
.description("Call any Supabase Management API operation, scoped to the app's Supabase project (fullstack apps only)")
|
|
582
|
-
.option("--body <json
|
|
811
|
+
.option("--body <json...>", "JSON request body (unquoted / word-split OK for flat objects)")
|
|
583
812
|
.addHelpText("after", `
|
|
584
813
|
Examples:
|
|
585
814
|
naive apps supabase <id> GET "v1/projects/<ref>" Project details
|
|
586
815
|
naive apps supabase <id> GET "v1/projects/<ref>/config/auth" Auth config
|
|
587
816
|
naive apps supabase <id> PATCH "v1/projects/<ref>/config/auth" --body '{"site_url":"https://example.com"}'
|
|
588
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\\"))"}]}'
|
|
589
820
|
naive apps supabase <id> POST "v1/projects/<ref>/database/query" --body '{"query":"select * from users limit 10"}'
|
|
590
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
|
+
|
|
591
828
|
Scope: only this app's project (v1/projects/{ref}/**) is reachable. Deleting
|
|
592
829
|
the project itself is blocked — use 'naive apps delete'. See
|
|
593
830
|
https://supabase.com/docs/reference/api.
|