@usenaive-sdk/cli 0.13.0 → 0.14.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.
- package/README.md +14 -0
- package/dist/commands/aeo.js +2 -2
- package/dist/commands/aeo.js.map +1 -1
- package/dist/commands/approvals.js +142 -9
- package/dist/commands/approvals.js.map +1 -1
- package/dist/commands/audio.js +1 -1
- package/dist/commands/audio.js.map +1 -1
- package/dist/commands/auth.js +27 -2
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/brain.js +57 -12
- package/dist/commands/brain.js.map +1 -1
- package/dist/commands/browser.js +1 -1
- package/dist/commands/clone.js +2 -2
- package/dist/commands/clone.js.map +1 -1
- package/dist/commands/compute.js +285 -15
- package/dist/commands/compute.js.map +1 -1
- package/dist/commands/connections.js +13 -1
- package/dist/commands/connections.js.map +1 -1
- package/dist/commands/cron-jobs.js +37 -0
- package/dist/commands/cron-jobs.js.map +1 -1
- package/dist/commands/domains.js +62 -18
- package/dist/commands/domains.js.map +1 -1
- package/dist/commands/formation.js +2 -2
- package/dist/commands/formation.js.map +1 -1
- package/dist/commands/images.js +2 -2
- package/dist/commands/images.js.map +1 -1
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.js +9 -51
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/llm.js +1 -1
- package/dist/commands/llm.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/people.js +4 -0
- package/dist/commands/people.js.map +1 -1
- package/dist/commands/phone.js +37 -5
- package/dist/commands/phone.js.map +1 -1
- package/dist/commands/sandbox.js +334 -21
- package/dist/commands/sandbox.js.map +1 -1
- package/dist/commands/search.js +1 -1
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/social-data.js +4 -3
- package/dist/commands/social-data.js.map +1 -1
- package/dist/commands/social.js +1 -1
- package/dist/commands/social.js.map +1 -1
- package/dist/commands/support.d.ts +2 -0
- package/dist/commands/support.js +134 -0
- package/dist/commands/support.js.map +1 -0
- package/dist/commands/tasks.js +9 -0
- package/dist/commands/tasks.js.map +1 -1
- package/dist/commands/teams.d.ts +3 -3
- package/dist/commands/teams.js +5 -5
- package/dist/commands/up.js +113 -6
- package/dist/commands/up.js.map +1 -1
- package/dist/commands/vault.js +3 -0
- 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 +3 -3
- package/dist/commands/video.js.map +1 -1
- package/dist/config.d.ts +7 -0
- package/dist/config.js +14 -0
- package/dist/config.js.map +1 -1
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/config-errors.d.ts +4 -0
- package/dist/lib/config-errors.js +13 -0
- package/dist/lib/config-errors.js.map +1 -0
- package/dist/lib/starter-config.d.ts +13 -0
- package/dist/lib/starter-config.js +71 -0
- package/dist/lib/starter-config.js.map +1 -0
- package/dist/lib/teams-catalog.js +81 -5
- package/dist/lib/teams-catalog.js.map +1 -1
- package/dist/lib/unknown-command.d.ts +18 -4
- package/dist/lib/unknown-command.js +45 -6
- package/dist/lib/unknown-command.js.map +1 -1
- package/dist/output.d.ts +28 -0
- package/dist/output.js +29 -1
- package/dist/output.js.map +1 -1
- package/package.json +1 -1
package/dist/commands/phone.js
CHANGED
|
@@ -6,6 +6,7 @@ export const phoneCmd = new Command("phone")
|
|
|
6
6
|
.addHelpText("after", `
|
|
7
7
|
Subcommands:
|
|
8
8
|
naive phone provision Buy a US number + register the carrier campaign
|
|
9
|
+
naive phone resend-otp Resend the sole-prop brand-verification SMS OTP
|
|
9
10
|
naive phone list List phone numbers for your company
|
|
10
11
|
naive phone status Show the carrier-registration pipeline
|
|
11
12
|
naive phone send Send an outbound SMS from a provisioned number
|
|
@@ -16,11 +17,17 @@ Subcommands:
|
|
|
16
17
|
naive phone release <id> Release a number back to the provider (stops billing)
|
|
17
18
|
|
|
18
19
|
Prerequisites:
|
|
19
|
-
|
|
20
|
-
against your business). The full chain is:
|
|
20
|
+
Standard provisioning requires a completed LLC formation (numbers are
|
|
21
|
+
carrier-registered against your business). The full chain is:
|
|
21
22
|
1. naive verification start (KYC for company members)
|
|
22
23
|
2. naive formation submit (LLC formation)
|
|
23
|
-
3. naive phone provision (this command)
|
|
24
|
+
3. naive phone provision (this command, with --ein)
|
|
25
|
+
|
|
26
|
+
Sole proprietors (no LLC/EIN) can provision with --sole-prop after passing
|
|
27
|
+
KYC. The brand is registered against the verified individual; Surge texts an
|
|
28
|
+
SMS OTP to their verified mobile to confirm brand identity ('naive phone
|
|
29
|
+
resend-otp' re-sends it). Sole-prop brands have lower carrier throughput
|
|
30
|
+
than EIN-registered brands.
|
|
24
31
|
|
|
25
32
|
How SMS gating works:
|
|
26
33
|
Inbound SMS works immediately on provisioning. Outbound SMS is blocked by the
|
|
@@ -34,7 +41,9 @@ Governance:
|
|
|
34
41
|
status "pending_approval" and the action runs after 'naive approvals approve <id>'.
|
|
35
42
|
|
|
36
43
|
Examples:
|
|
37
|
-
$ naive phone provision --area-code 415 --label "support line"
|
|
44
|
+
$ naive phone provision --ein 12-3456789 --area-code 415 --label "support line"
|
|
45
|
+
$ naive phone provision --sole-prop --area-code 415
|
|
46
|
+
$ naive phone resend-otp
|
|
38
47
|
$ naive phone status
|
|
39
48
|
$ naive phone send --from <phone_id> --to +14155551234 --body "Hello"
|
|
40
49
|
$ naive phone messages <phone_id> --limit 50
|
|
@@ -42,13 +51,16 @@ Examples:
|
|
|
42
51
|
phoneCmd
|
|
43
52
|
.command("provision")
|
|
44
53
|
.description("Buy a US number and register the carrier (10DLC) campaign")
|
|
45
|
-
.
|
|
54
|
+
.option("--ein <ein>", "Company EIN / tax id (9 digits, e.g. 12-3456789) — required for standard (formation-backed) registration")
|
|
55
|
+
.option("--sole-prop", "Register as a sole proprietor (passed KYC, no LLC/EIN; brand verified via SMS OTP)")
|
|
46
56
|
.option("--area-code <code>", "Preferred US area code (3 digits, e.g. 415)")
|
|
47
57
|
.option("--type <type>", "Number type: local (default) or toll_free")
|
|
48
58
|
.option("--label <label>", "Friendly label for the number")
|
|
49
59
|
.option("--agent-id <agentId>", "Connect an agent to the number on creation")
|
|
50
60
|
.action(async (opts) => {
|
|
51
61
|
const body = {};
|
|
62
|
+
if (opts.soleProp)
|
|
63
|
+
body.tier = "sole_proprietor";
|
|
52
64
|
if (opts.ein)
|
|
53
65
|
body.ein = opts.ein;
|
|
54
66
|
if (opts.areaCode)
|
|
@@ -70,14 +82,34 @@ phoneCmd
|
|
|
70
82
|
next_steps: [
|
|
71
83
|
{ command: "naive phone status", description: "Check carrier campaign progress" },
|
|
72
84
|
{ command: "naive phone list", description: "List all phone numbers" },
|
|
85
|
+
...(data.brand_verification === "pending_otp"
|
|
86
|
+
? [{ command: "naive phone resend-otp", description: "Resend the brand-verification SMS OTP if it didn't arrive" }]
|
|
87
|
+
: []),
|
|
73
88
|
],
|
|
74
89
|
hints: [
|
|
75
90
|
data.phone ? `Number ${data.phone.e164} is live for inbound SMS now.` : "Number provisioned.",
|
|
76
91
|
`Outbound SMS unlocks when the campaign is approved (${data.campaign?.eta ?? "~1-2 business days"}) — automatic, no action needed.`,
|
|
92
|
+
...(data.brand_verification === "pending_otp"
|
|
93
|
+
? ["Sole-prop brand verification: an SMS OTP was sent to the verified mobile — confirm it to complete carrier registration."]
|
|
94
|
+
: []),
|
|
77
95
|
],
|
|
78
96
|
related_commands: ["naive phone status", "naive phone list", "naive phone send"],
|
|
79
97
|
});
|
|
80
98
|
});
|
|
99
|
+
phoneCmd
|
|
100
|
+
.command("resend-otp")
|
|
101
|
+
.description("Resend the sole-proprietor brand-verification SMS OTP")
|
|
102
|
+
.action(async () => {
|
|
103
|
+
const resp = await apiRequest("POST", "/v1/phone/brand-verification/resend");
|
|
104
|
+
handleApiError("phone.resend_otp", resp);
|
|
105
|
+
agentOutput({
|
|
106
|
+
action: "phone.resend_otp",
|
|
107
|
+
result: resp.data,
|
|
108
|
+
next_steps: [{ command: "naive phone status", description: "Check carrier campaign progress" }],
|
|
109
|
+
hints: ["A new verification code was texted to the verified mobile number."],
|
|
110
|
+
related_commands: ["naive phone provision", "naive phone status"],
|
|
111
|
+
});
|
|
112
|
+
});
|
|
81
113
|
phoneCmd
|
|
82
114
|
.command("list", { isDefault: true })
|
|
83
115
|
.description("List phone numbers for your company")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"phone.js","sourceRoot":"","sources":["../../src/commands/phone.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;KACzC,WAAW,CAAC,8CAA8C,CAAC;KAC3D,WAAW,CAAC,OAAO,EAAE
|
|
1
|
+
{"version":3,"file":"phone.js","sourceRoot":"","sources":["../../src/commands/phone.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/sandbox.js
CHANGED
|
@@ -2,6 +2,61 @@ import { Command } from "commander";
|
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import { apiRequest, handleApiError } from "../client.js";
|
|
4
4
|
import { agentOutput } from "../output.js";
|
|
5
|
+
/**
|
|
6
|
+
* THE SUCCESS ENVELOPE.
|
|
7
|
+
*
|
|
8
|
+
* `naive --help` promises "every command returns structured JSON with result
|
|
9
|
+
* data, next steps, and contextual guidance for autonomous operation"
|
|
10
|
+
* (index.ts), and /cli/overview documents the same shape. `sandbox` shipped with
|
|
11
|
+
* 16 of its 20 success envelopes passing `next_steps: []` and none carrying
|
|
12
|
+
* `hints`, so an agent that created a sandbox and ran a command in it got the
|
|
13
|
+
* data and no route onward — on the one primitive where the route onward
|
|
14
|
+
* (`park`, `sleep`, `destroy`) is what stops the meter.
|
|
15
|
+
*
|
|
16
|
+
* Both are DERIVED from the response the API just returned — the id in a
|
|
17
|
+
* suggested command is the id the API echoed, a hint restates a field it
|
|
18
|
+
* actually sent — so neither can drift from what the platform did. Same rule as
|
|
19
|
+
* `creditCostHint` in output.ts. The API's own advisory `note` (`sleep` explains
|
|
20
|
+
* what wakes the sandbox) is lifted into `hints` rather than left buried inside
|
|
21
|
+
* `result`.
|
|
22
|
+
*/
|
|
23
|
+
/** The sandbox id for a suggested command: the one the API echoed (top level or
|
|
24
|
+
* nested under `sandbox`), else what the caller typed, so a next step is
|
|
25
|
+
* copy-pasteable rather than a `<id>` placeholder. */
|
|
26
|
+
function sid(data, typed) {
|
|
27
|
+
const d = (data ?? {});
|
|
28
|
+
const id = d.sandbox_id ?? d.sandbox?.sandbox_id;
|
|
29
|
+
return typeof id === "string" && id ? id : (typed ?? "<id>");
|
|
30
|
+
}
|
|
31
|
+
/** Hints echoed off a sandbox the API returned — restated, never asserted. */
|
|
32
|
+
function sandboxHints(data) {
|
|
33
|
+
const d = (data ?? {});
|
|
34
|
+
const sb = (d.sandbox && typeof d.sandbox === "object" ? d.sandbox : d);
|
|
35
|
+
const out = [];
|
|
36
|
+
if (typeof sb.status === "string")
|
|
37
|
+
out.push(`Status: ${sb.status}`);
|
|
38
|
+
if (typeof sb.size === "string")
|
|
39
|
+
out.push(`Size: ${sb.size}`);
|
|
40
|
+
if (typeof sb.metered_credits === "number" && Number.isFinite(sb.metered_credits)) {
|
|
41
|
+
const credits = Math.round(sb.metered_credits * 10000) / 10000;
|
|
42
|
+
out.push(`Metered so far: ${credits} ${credits === 1 ? "credit" : "credits"}`);
|
|
43
|
+
}
|
|
44
|
+
// Why a sandbox is in its current status ("Auto-destroyed: credits exhausted…")
|
|
45
|
+
// — the only way a tenant learns why one stopped, so it belongs in `hints`.
|
|
46
|
+
if (typeof sb.error === "string" && sb.error)
|
|
47
|
+
out.push(sb.error);
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
/** The API's own advisory `note`/`hint`, lifted out of `result` where it sent one. */
|
|
51
|
+
function apiNote(data) {
|
|
52
|
+
const d = (data ?? {});
|
|
53
|
+
const out = [];
|
|
54
|
+
if (typeof d.note === "string" && d.note)
|
|
55
|
+
out.push(d.note);
|
|
56
|
+
if (typeof d.hint === "string" && d.hint)
|
|
57
|
+
out.push(d.hint);
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
5
60
|
export const sandboxCmd = new Command("sandbox")
|
|
6
61
|
.description("Sandbox — disposable micro-VM code sandboxes (usage billed from credits)")
|
|
7
62
|
.addHelpText("after", `
|
|
@@ -35,7 +90,6 @@ Billing:
|
|
|
35
90
|
Sizes (ceilings, not reservations — you pay only for what you use):
|
|
36
91
|
s 1 vCPU · up to 16 GiB memory · up to 32 GiB disk
|
|
37
92
|
m 4 vCPU · up to 32 GiB memory · up to 128 GiB disk (default)
|
|
38
|
-
l 8 vCPU · up to 64 GiB memory · up to 256 GiB disk
|
|
39
93
|
|
|
40
94
|
Examples:
|
|
41
95
|
$ naive sandbox create --name scratch --size s
|
|
@@ -52,7 +106,22 @@ sandboxCmd
|
|
|
52
106
|
.action(async () => {
|
|
53
107
|
const resp = await apiRequest("GET", "/v1/sandboxes/status");
|
|
54
108
|
handleApiError("sandbox.status", resp);
|
|
55
|
-
|
|
109
|
+
const s = (resp.data ?? {});
|
|
110
|
+
agentOutput({
|
|
111
|
+
action: "sandbox.status",
|
|
112
|
+
result: resp.data,
|
|
113
|
+
next_steps: [
|
|
114
|
+
{ command: "naive sandbox list", description: "List the sandboxes you have" },
|
|
115
|
+
{ command: "naive sandbox create --size s", description: "Create one", when: "configured and reachable" },
|
|
116
|
+
],
|
|
117
|
+
hints: [
|
|
118
|
+
`Provider configured: ${s.configured === true}; reachable: ${s.reachable === true}.`,
|
|
119
|
+
`${s.sandboxes ?? 0} sandbox(es), ${s.running_sandboxes ?? 0} running.`,
|
|
120
|
+
...(s.error ? [s.error] : []),
|
|
121
|
+
"`rates` in the result are the per-hour usage rates the meter actually charges.",
|
|
122
|
+
],
|
|
123
|
+
related_commands: ["naive sandbox list", "naive sandbox create"],
|
|
124
|
+
});
|
|
56
125
|
});
|
|
57
126
|
sandboxCmd
|
|
58
127
|
.command("list", { isDefault: true })
|
|
@@ -60,7 +129,25 @@ sandboxCmd
|
|
|
60
129
|
.action(async () => {
|
|
61
130
|
const resp = await apiRequest("GET", "/v1/sandboxes");
|
|
62
131
|
handleApiError("sandbox.list", resp);
|
|
63
|
-
|
|
132
|
+
const boxes = (resp.data?.sandboxes ?? []);
|
|
133
|
+
const first = boxes[0]?.sandbox_id ?? "<id>";
|
|
134
|
+
const running = boxes.filter((b) => b.status === "running").length;
|
|
135
|
+
agentOutput({
|
|
136
|
+
action: "sandbox.list",
|
|
137
|
+
result: resp.data,
|
|
138
|
+
next_steps: [
|
|
139
|
+
{ command: `naive sandbox show ${first}`, description: "Inspect one — status, size, metered credits" },
|
|
140
|
+
{ command: `naive sandbox exec ${first} "<command>"`, description: "Run a shell command in it" },
|
|
141
|
+
{ command: `naive sandbox park ${first}`, description: "Checkpoint and stop its meter", when: "it is running and idle" },
|
|
142
|
+
],
|
|
143
|
+
hints: [
|
|
144
|
+
`${boxes.length} sandbox${boxes.length === 1 ? "" : "es"}, ${running} running.`,
|
|
145
|
+
...(running > 0
|
|
146
|
+
? ["Running sandboxes bill observed usage — `park` or `sleep` stops the meter without losing state."]
|
|
147
|
+
: ["Nothing is metering right now."]),
|
|
148
|
+
],
|
|
149
|
+
related_commands: ["naive sandbox show", "naive sandbox park", "naive sandbox destroy"],
|
|
150
|
+
});
|
|
64
151
|
});
|
|
65
152
|
sandboxCmd
|
|
66
153
|
.command("create")
|
|
@@ -77,13 +164,20 @@ sandboxCmd
|
|
|
77
164
|
disk_gib: opts.disk ? Number(opts.disk) : undefined,
|
|
78
165
|
});
|
|
79
166
|
handleApiError("sandbox.create", resp);
|
|
167
|
+
const id = sid(resp.data);
|
|
80
168
|
agentOutput({
|
|
81
169
|
action: "sandbox.create",
|
|
82
170
|
result: resp.data,
|
|
83
171
|
next_steps: [
|
|
84
|
-
{ command:
|
|
85
|
-
{ command:
|
|
172
|
+
{ command: `naive sandbox exec ${id} "<command>"`, description: "Run a shell command in the sandbox" },
|
|
173
|
+
{ command: `naive sandbox write ${id} <path> --file <local>`, description: "Upload a file into it" },
|
|
174
|
+
{ command: `naive sandbox park ${id}`, description: "Checkpoint and stop the usage meter", when: "done for now" },
|
|
175
|
+
],
|
|
176
|
+
hints: [
|
|
177
|
+
...sandboxHints(resp.data),
|
|
178
|
+
"The meter runs while the sandbox is running — `park` or `sleep` is free, `destroy` is final.",
|
|
86
179
|
],
|
|
180
|
+
related_commands: ["naive sandbox exec", "naive sandbox park", "naive sandbox destroy"],
|
|
87
181
|
});
|
|
88
182
|
});
|
|
89
183
|
sandboxCmd
|
|
@@ -92,7 +186,21 @@ sandboxCmd
|
|
|
92
186
|
.action(async (id) => {
|
|
93
187
|
const resp = await apiRequest("GET", `/v1/sandboxes/${id}`);
|
|
94
188
|
handleApiError("sandbox.show", resp);
|
|
95
|
-
|
|
189
|
+
const sb = sid(resp.data, id);
|
|
190
|
+
agentOutput({
|
|
191
|
+
action: "sandbox.show",
|
|
192
|
+
result: resp.data,
|
|
193
|
+
next_steps: [
|
|
194
|
+
{ command: `naive sandbox exec ${sb} "<command>"`, description: "Run a shell command in it" },
|
|
195
|
+
{ command: `naive sandbox ports ${sb}`, description: "See which guest ports are exposed" },
|
|
196
|
+
{ command: `naive sandbox park ${sb}`, description: "Checkpoint and stop the meter", when: "it is running and idle" },
|
|
197
|
+
],
|
|
198
|
+
hints: [
|
|
199
|
+
...sandboxHints(resp.data),
|
|
200
|
+
"`metered_credits` is what this sandbox has cost so far, not a forecast.",
|
|
201
|
+
],
|
|
202
|
+
related_commands: ["naive sandbox exec", "naive sandbox park", "naive sandbox destroy"],
|
|
203
|
+
});
|
|
96
204
|
});
|
|
97
205
|
sandboxCmd
|
|
98
206
|
.command("exec <id> <command...>")
|
|
@@ -106,7 +214,24 @@ sandboxCmd
|
|
|
106
214
|
timeout_ms: opts.timeout ? Number(opts.timeout) : undefined,
|
|
107
215
|
});
|
|
108
216
|
handleApiError("sandbox.exec", resp);
|
|
109
|
-
|
|
217
|
+
const sb = sid(resp.data, id);
|
|
218
|
+
const exit = resp.data?.exit_code;
|
|
219
|
+
agentOutput({
|
|
220
|
+
action: "sandbox.exec",
|
|
221
|
+
result: resp.data,
|
|
222
|
+
next_steps: [
|
|
223
|
+
{ command: `naive sandbox exec ${sb} "<command>"`, description: "Run the next command" },
|
|
224
|
+
{ command: `naive sandbox ls ${sb} <path>`, description: "Inspect what the command wrote" },
|
|
225
|
+
{ command: `naive sandbox park ${sb}`, description: "Checkpoint and stop the meter", when: "done for now" },
|
|
226
|
+
],
|
|
227
|
+
hints: [
|
|
228
|
+
typeof exit === "number"
|
|
229
|
+
? `Exit code: ${exit}${exit === 0 ? "" : " — stderr in the result has the reason"}.`
|
|
230
|
+
: "The command ran; `stdout`/`stderr` are in the result.",
|
|
231
|
+
"Output is truncated past 256 KiB — write large output to a file and `sandbox read` it.",
|
|
232
|
+
],
|
|
233
|
+
related_commands: ["naive sandbox read", "naive sandbox ls", "naive sandbox park"],
|
|
234
|
+
});
|
|
110
235
|
});
|
|
111
236
|
sandboxCmd
|
|
112
237
|
.command("write <id> <path>")
|
|
@@ -117,7 +242,21 @@ sandboxCmd
|
|
|
117
242
|
const content = opts.file ? readFileSync(opts.file, "utf8") : (opts.content ?? "");
|
|
118
243
|
const resp = await apiRequest("POST", `/v1/sandboxes/${id}/files`, { path, content });
|
|
119
244
|
handleApiError("sandbox.write", resp);
|
|
120
|
-
|
|
245
|
+
const sb = sid(resp.data, id);
|
|
246
|
+
const size = resp.data?.size;
|
|
247
|
+
agentOutput({
|
|
248
|
+
action: "sandbox.write",
|
|
249
|
+
result: resp.data,
|
|
250
|
+
next_steps: [
|
|
251
|
+
{ command: `naive sandbox read ${sb} ${path}`, description: "Read it back" },
|
|
252
|
+
{ command: `naive sandbox exec ${sb} "<command>"`, description: "Run it" },
|
|
253
|
+
],
|
|
254
|
+
hints: [
|
|
255
|
+
typeof size === "number" ? `Wrote ${size} byte${size === 1 ? "" : "s"} to ${path}.` : `Wrote ${path}.`,
|
|
256
|
+
"This surface caps a file at 4 MiB — use `sandbox exec` to fetch anything larger inside the VM.",
|
|
257
|
+
],
|
|
258
|
+
related_commands: ["naive sandbox read", "naive sandbox ls", "naive sandbox exec"],
|
|
259
|
+
});
|
|
121
260
|
});
|
|
122
261
|
sandboxCmd
|
|
123
262
|
.command("read <id> <path>")
|
|
@@ -125,7 +264,21 @@ sandboxCmd
|
|
|
125
264
|
.action(async (id, path) => {
|
|
126
265
|
const resp = await apiRequest("GET", `/v1/sandboxes/${id}/files?path=${encodeURIComponent(path)}`);
|
|
127
266
|
handleApiError("sandbox.read", resp);
|
|
128
|
-
|
|
267
|
+
const sb = sid(resp.data, id);
|
|
268
|
+
const size = resp.data?.size;
|
|
269
|
+
agentOutput({
|
|
270
|
+
action: "sandbox.read",
|
|
271
|
+
result: resp.data,
|
|
272
|
+
next_steps: [
|
|
273
|
+
{ command: `naive sandbox write ${sb} ${path} --content "<text>"`, description: "Overwrite it" },
|
|
274
|
+
{ command: `naive sandbox ls ${sb} <dir>`, description: "List the directory it lives in" },
|
|
275
|
+
],
|
|
276
|
+
hints: [
|
|
277
|
+
typeof size === "number" ? `${size} byte${size === 1 ? "" : "s"} from ${path}.` : `Read ${path}.`,
|
|
278
|
+
"Content comes back inside the envelope — binary files should be base64-encoded in the sandbox first.",
|
|
279
|
+
],
|
|
280
|
+
related_commands: ["naive sandbox write", "naive sandbox ls"],
|
|
281
|
+
});
|
|
129
282
|
});
|
|
130
283
|
sandboxCmd
|
|
131
284
|
.command("ls <id> <path>")
|
|
@@ -133,7 +286,21 @@ sandboxCmd
|
|
|
133
286
|
.action(async (id, path) => {
|
|
134
287
|
const resp = await apiRequest("GET", `/v1/sandboxes/${id}/files/ls?path=${encodeURIComponent(path)}`);
|
|
135
288
|
handleApiError("sandbox.ls", resp);
|
|
136
|
-
|
|
289
|
+
const sb = sid(resp.data, id);
|
|
290
|
+
const entries = (resp.data?.entries ?? []);
|
|
291
|
+
agentOutput({
|
|
292
|
+
action: "sandbox.ls",
|
|
293
|
+
result: resp.data,
|
|
294
|
+
next_steps: [
|
|
295
|
+
{ command: `naive sandbox read ${sb} ${path}/<name>`, description: "Read one of the entries" },
|
|
296
|
+
{ command: `naive sandbox rm ${sb} ${path}/<name>`, description: "Remove one", when: "you are cleaning up" },
|
|
297
|
+
],
|
|
298
|
+
hints: [
|
|
299
|
+
`${entries.length} entr${entries.length === 1 ? "y" : "ies"} in ${path}.`,
|
|
300
|
+
"This lists immediate entries only — it does not recurse.",
|
|
301
|
+
],
|
|
302
|
+
related_commands: ["naive sandbox read", "naive sandbox mkdir", "naive sandbox rm"],
|
|
303
|
+
});
|
|
137
304
|
});
|
|
138
305
|
sandboxCmd
|
|
139
306
|
.command("mkdir <id> <path>")
|
|
@@ -141,7 +308,20 @@ sandboxCmd
|
|
|
141
308
|
.action(async (id, path) => {
|
|
142
309
|
const resp = await apiRequest("POST", `/v1/sandboxes/${id}/files/mkdir`, { path });
|
|
143
310
|
handleApiError("sandbox.mkdir", resp);
|
|
144
|
-
|
|
311
|
+
const sb = sid(resp.data, id);
|
|
312
|
+
agentOutput({
|
|
313
|
+
action: "sandbox.mkdir",
|
|
314
|
+
result: resp.data,
|
|
315
|
+
next_steps: [
|
|
316
|
+
{ command: `naive sandbox write ${sb} ${path}/<name> --file <local>`, description: "Put a file in it" },
|
|
317
|
+
{ command: `naive sandbox ls ${sb} ${path}`, description: "Confirm what is there" },
|
|
318
|
+
],
|
|
319
|
+
hints: [
|
|
320
|
+
`Created ${path} (and any missing parents).`,
|
|
321
|
+
"It behaves like `mkdir -p` — creating an existing directory is not an error.",
|
|
322
|
+
],
|
|
323
|
+
related_commands: ["naive sandbox write", "naive sandbox ls"],
|
|
324
|
+
});
|
|
145
325
|
});
|
|
146
326
|
sandboxCmd
|
|
147
327
|
.command("rm <id> <path>")
|
|
@@ -149,7 +329,20 @@ sandboxCmd
|
|
|
149
329
|
.action(async (id, path) => {
|
|
150
330
|
const resp = await apiRequest("DELETE", `/v1/sandboxes/${id}/files?path=${encodeURIComponent(path)}`);
|
|
151
331
|
handleApiError("sandbox.rm", resp);
|
|
152
|
-
|
|
332
|
+
const sb = sid(resp.data, id);
|
|
333
|
+
agentOutput({
|
|
334
|
+
action: "sandbox.rm",
|
|
335
|
+
result: resp.data,
|
|
336
|
+
next_steps: [
|
|
337
|
+
{ command: `naive sandbox ls ${sb} <dir>`, description: "Confirm what is left" },
|
|
338
|
+
{ command: `naive sandbox destroy ${sb}`, description: "Throw the whole sandbox away", when: "you are done with it" },
|
|
339
|
+
],
|
|
340
|
+
hints: [
|
|
341
|
+
`Removed ${path}.`,
|
|
342
|
+
"This is recursive, like `rm -rf` — a checkpoint taken before it is the only way back.",
|
|
343
|
+
],
|
|
344
|
+
related_commands: ["naive sandbox ls", "naive sandbox checkpoint"],
|
|
345
|
+
});
|
|
153
346
|
});
|
|
154
347
|
sandboxCmd
|
|
155
348
|
.command("expose <id> <port>")
|
|
@@ -161,7 +354,21 @@ sandboxCmd
|
|
|
161
354
|
protocol: opts.protocol,
|
|
162
355
|
});
|
|
163
356
|
handleApiError("sandbox.expose", resp);
|
|
164
|
-
|
|
357
|
+
const sb = sid(resp.data, id);
|
|
358
|
+
const url = resp.data?.url;
|
|
359
|
+
agentOutput({
|
|
360
|
+
action: "sandbox.expose",
|
|
361
|
+
result: resp.data,
|
|
362
|
+
next_steps: [
|
|
363
|
+
{ command: `naive sandbox ports ${sb}`, description: "See every port this sandbox exposes" },
|
|
364
|
+
{ command: `naive sandbox unexpose ${sb} ${port}`, description: "Take it down again", when: "you are done" },
|
|
365
|
+
],
|
|
366
|
+
hints: [
|
|
367
|
+
typeof url === "string" && url ? `Reachable at ${url}` : `Port ${port} is exposed; the URL is in the result.`,
|
|
368
|
+
"A public port is reachable by anyone who has the URL — unexpose it when you are finished.",
|
|
369
|
+
],
|
|
370
|
+
related_commands: ["naive sandbox ports", "naive sandbox unexpose"],
|
|
371
|
+
});
|
|
165
372
|
});
|
|
166
373
|
sandboxCmd
|
|
167
374
|
.command("unexpose <id> <port>")
|
|
@@ -169,7 +376,20 @@ sandboxCmd
|
|
|
169
376
|
.action(async (id, port) => {
|
|
170
377
|
const resp = await apiRequest("DELETE", `/v1/sandboxes/${id}/expose/${Number(port)}`);
|
|
171
378
|
handleApiError("sandbox.unexpose", resp);
|
|
172
|
-
|
|
379
|
+
const sb = sid(resp.data, id);
|
|
380
|
+
agentOutput({
|
|
381
|
+
action: "sandbox.unexpose",
|
|
382
|
+
result: resp.data,
|
|
383
|
+
next_steps: [
|
|
384
|
+
{ command: `naive sandbox ports ${sb}`, description: "Confirm what is still exposed" },
|
|
385
|
+
{ command: `naive sandbox expose ${sb} ${port}`, description: "Expose it again", when: "you need it back" },
|
|
386
|
+
],
|
|
387
|
+
hints: [
|
|
388
|
+
`Port ${port} is no longer exposed.`,
|
|
389
|
+
"The process inside the sandbox keeps running — only the public listener is gone.",
|
|
390
|
+
],
|
|
391
|
+
related_commands: ["naive sandbox ports", "naive sandbox expose"],
|
|
392
|
+
});
|
|
173
393
|
});
|
|
174
394
|
sandboxCmd
|
|
175
395
|
.command("ports <id>")
|
|
@@ -177,7 +397,24 @@ sandboxCmd
|
|
|
177
397
|
.action(async (id) => {
|
|
178
398
|
const resp = await apiRequest("GET", `/v1/sandboxes/${id}/expose`);
|
|
179
399
|
handleApiError("sandbox.ports", resp);
|
|
180
|
-
|
|
400
|
+
const sb = sid(resp.data, id);
|
|
401
|
+
const ports = (resp.data?.ports ?? []);
|
|
402
|
+
agentOutput({
|
|
403
|
+
action: "sandbox.ports",
|
|
404
|
+
result: resp.data,
|
|
405
|
+
next_steps: [
|
|
406
|
+
{ command: `naive sandbox expose ${sb} <port>`, description: "Expose another guest port" },
|
|
407
|
+
...(ports.length > 0
|
|
408
|
+
? [{ command: `naive sandbox unexpose ${sb} ${ports[0].port ?? "<port>"}`, description: "Take one down" }]
|
|
409
|
+
: []),
|
|
410
|
+
{ command: `naive sandbox show ${sb}`, description: "Check the sandbox's status" },
|
|
411
|
+
],
|
|
412
|
+
hints: [
|
|
413
|
+
`${ports.length} exposed port${ports.length === 1 ? "" : "s"}.`,
|
|
414
|
+
"Listing ports does not wake a sleeping sandbox.",
|
|
415
|
+
],
|
|
416
|
+
related_commands: ["naive sandbox expose", "naive sandbox unexpose"],
|
|
417
|
+
});
|
|
181
418
|
});
|
|
182
419
|
sandboxCmd
|
|
183
420
|
.command("checkpoint <id>")
|
|
@@ -186,10 +423,21 @@ sandboxCmd
|
|
|
186
423
|
.action(async (id, opts) => {
|
|
187
424
|
const resp = await apiRequest("POST", `/v1/sandboxes/${id}/checkpoints`, { name: opts.name });
|
|
188
425
|
handleApiError("sandbox.checkpoint", resp);
|
|
426
|
+
const sb = sid(resp.data, id);
|
|
427
|
+
const cp = resp.data ?? {};
|
|
189
428
|
agentOutput({
|
|
190
429
|
action: "sandbox.checkpoint",
|
|
191
430
|
result: resp.data,
|
|
192
|
-
next_steps: [
|
|
431
|
+
next_steps: [
|
|
432
|
+
{ command: `naive sandbox fork ${sb}`, description: "Start a new sandbox from the checkpoint" },
|
|
433
|
+
{ command: `naive sandbox park ${sb}`, description: "Checkpoint and stop the meter", when: "done for now" },
|
|
434
|
+
],
|
|
435
|
+
hints: [
|
|
436
|
+
typeof cp.checkpoint_id === "string" ? `Checkpoint ${cp.checkpoint_id}.` : "Checkpoint taken.",
|
|
437
|
+
...(typeof cp.expires_at === "string" ? [`Expires ${cp.expires_at}.`] : []),
|
|
438
|
+
"The sandbox keeps running — checkpointing does not stop the meter, `park` does.",
|
|
439
|
+
],
|
|
440
|
+
related_commands: ["naive sandbox fork", "naive sandbox park"],
|
|
193
441
|
});
|
|
194
442
|
});
|
|
195
443
|
sandboxCmd
|
|
@@ -203,7 +451,21 @@ sandboxCmd
|
|
|
203
451
|
checkpoint_id: opts.checkpoint,
|
|
204
452
|
});
|
|
205
453
|
handleApiError("sandbox.fork", resp);
|
|
206
|
-
|
|
454
|
+
const forked = sid(resp.data);
|
|
455
|
+
agentOutput({
|
|
456
|
+
action: "sandbox.fork",
|
|
457
|
+
result: resp.data,
|
|
458
|
+
next_steps: [
|
|
459
|
+
{ command: `naive sandbox exec ${forked} "<command>"`, description: "Run a command in the fork" },
|
|
460
|
+
{ command: `naive sandbox park ${forked}`, description: "Checkpoint and stop the fork's meter", when: "done for now" },
|
|
461
|
+
{ command: "naive sandbox list", description: "See the original and the fork side by side" },
|
|
462
|
+
],
|
|
463
|
+
hints: [
|
|
464
|
+
...sandboxHints(resp.data),
|
|
465
|
+
`The fork is a separate sandbox with its own meter — ${id} keeps running independently.`,
|
|
466
|
+
],
|
|
467
|
+
related_commands: ["naive sandbox list", "naive sandbox exec", "naive sandbox park"],
|
|
468
|
+
});
|
|
207
469
|
});
|
|
208
470
|
sandboxCmd
|
|
209
471
|
.command("park <id>")
|
|
@@ -211,10 +473,20 @@ sandboxCmd
|
|
|
211
473
|
.action(async (id) => {
|
|
212
474
|
const resp = await apiRequest("POST", `/v1/sandboxes/${id}/park`, {});
|
|
213
475
|
handleApiError("sandbox.park", resp);
|
|
476
|
+
const sb = sid(resp.data, id);
|
|
214
477
|
agentOutput({
|
|
215
478
|
action: "sandbox.park",
|
|
216
479
|
result: resp.data,
|
|
217
|
-
next_steps: [
|
|
480
|
+
next_steps: [
|
|
481
|
+
{ command: `naive sandbox resume ${sb}`, description: "Restore the checkpoint and restart the meter" },
|
|
482
|
+
{ command: `naive sandbox destroy ${sb}`, description: "Throw it away for good", when: "you will not come back to it" },
|
|
483
|
+
],
|
|
484
|
+
hints: [
|
|
485
|
+
...sandboxHints(resp.data),
|
|
486
|
+
...apiNote(resp.data),
|
|
487
|
+
"Parked sandboxes are free — the meter is stopped, the checkpointed state is kept.",
|
|
488
|
+
],
|
|
489
|
+
related_commands: ["naive sandbox resume", "naive sandbox destroy"],
|
|
218
490
|
});
|
|
219
491
|
});
|
|
220
492
|
sandboxCmd
|
|
@@ -224,7 +496,23 @@ sandboxCmd
|
|
|
224
496
|
.action(async (id, opts) => {
|
|
225
497
|
const resp = await apiRequest("POST", `/v1/sandboxes/${id}/sleep`, opts.wakeAt ? { wake_at: opts.wakeAt } : {});
|
|
226
498
|
handleApiError("sandbox.sleep", resp);
|
|
227
|
-
|
|
499
|
+
const sb = sid(resp.data, id);
|
|
500
|
+
const wakeAt = resp.data?.wake_at;
|
|
501
|
+
agentOutput({
|
|
502
|
+
action: "sandbox.sleep",
|
|
503
|
+
result: resp.data,
|
|
504
|
+
next_steps: [
|
|
505
|
+
{ command: `naive sandbox resume ${sb}`, description: "Wake it now and restart the meter" },
|
|
506
|
+
{ command: `naive sandbox ports ${sb}`, description: "Check its exposed ports without waking it" },
|
|
507
|
+
],
|
|
508
|
+
hints: [
|
|
509
|
+
...sandboxHints(resp.data),
|
|
510
|
+
// The API explains what wakes it; that advisory is the point of the call.
|
|
511
|
+
...apiNote(resp.data),
|
|
512
|
+
...(typeof wakeAt === "string" ? [`Scheduled wake: ${wakeAt}.`] : []),
|
|
513
|
+
],
|
|
514
|
+
related_commands: ["naive sandbox resume", "naive sandbox park"],
|
|
515
|
+
});
|
|
228
516
|
});
|
|
229
517
|
sandboxCmd
|
|
230
518
|
.command("resume <id>")
|
|
@@ -232,7 +520,20 @@ sandboxCmd
|
|
|
232
520
|
.action(async (id) => {
|
|
233
521
|
const resp = await apiRequest("POST", `/v1/sandboxes/${id}/resume`, {});
|
|
234
522
|
handleApiError("sandbox.resume", resp);
|
|
235
|
-
|
|
523
|
+
const sb = sid(resp.data, id);
|
|
524
|
+
agentOutput({
|
|
525
|
+
action: "sandbox.resume",
|
|
526
|
+
result: resp.data,
|
|
527
|
+
next_steps: [
|
|
528
|
+
{ command: `naive sandbox exec ${sb} "<command>"`, description: "Carry on where you left off" },
|
|
529
|
+
{ command: `naive sandbox park ${sb}`, description: "Stop the meter again", when: "done for now" },
|
|
530
|
+
],
|
|
531
|
+
hints: [
|
|
532
|
+
...sandboxHints(resp.data),
|
|
533
|
+
"The meter restarts from the resume time — park or sleep it again when you stop working.",
|
|
534
|
+
],
|
|
535
|
+
related_commands: ["naive sandbox exec", "naive sandbox park"],
|
|
536
|
+
});
|
|
236
537
|
});
|
|
237
538
|
sandboxCmd
|
|
238
539
|
.command("destroy <id>")
|
|
@@ -240,6 +541,18 @@ sandboxCmd
|
|
|
240
541
|
.action(async (id) => {
|
|
241
542
|
const resp = await apiRequest("DELETE", `/v1/sandboxes/${id}`);
|
|
242
543
|
handleApiError("sandbox.destroy", resp);
|
|
243
|
-
agentOutput({
|
|
544
|
+
agentOutput({
|
|
545
|
+
action: "sandbox.destroy",
|
|
546
|
+
result: resp.data,
|
|
547
|
+
next_steps: [
|
|
548
|
+
{ command: "naive sandbox list", description: "Confirm what is left" },
|
|
549
|
+
{ command: "naive sandbox create --size s", description: "Start a fresh one", when: "you need another" },
|
|
550
|
+
],
|
|
551
|
+
hints: [
|
|
552
|
+
...sandboxHints(resp.data),
|
|
553
|
+
"Destroy is final and stops billing — un-checkpointed state is gone.",
|
|
554
|
+
],
|
|
555
|
+
related_commands: ["naive sandbox list", "naive sandbox create"],
|
|
556
|
+
});
|
|
244
557
|
});
|
|
245
558
|
//# sourceMappingURL=sandbox.js.map
|