runcloud 0.1.92 → 0.1.94
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/login.js +20 -4
- package/dist/commands/sandbox.js +22 -2
- package/dist/config.js +9 -0
- package/dist/deviceLogin.js +8 -2
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/skills/run-cloud-sandboxes/SKILL.md +3 -1
package/dist/commands/login.js
CHANGED
|
@@ -3,7 +3,7 @@ import crypto from 'node:crypto';
|
|
|
3
3
|
import { hostname } from 'node:os';
|
|
4
4
|
import { spawn } from 'node:child_process';
|
|
5
5
|
import { ApiClient, ApiError } from '../api.js';
|
|
6
|
-
import { clearCredentials, credentialsDisplayPath, loadCredentials, loginCommandName, normalizeApiUrl, saveCredentials, } from '../config.js';
|
|
6
|
+
import { clearCredentials, credentialsDisplayPath, loadCredentials, loginCommandName, normalizeApiUrl, sanitizeAccount, saveCredentials, } from '../config.js';
|
|
7
7
|
import { acquirePromptIO, ask, PromptAbortedError, select, } from '../prompt.js';
|
|
8
8
|
import { AuthError, createApiKey, fetchProviders, isValidEmail, isValidOtp, normalizeOtp, sendEmailCode, verifyEmailCode, } from '../runCloudAuth.js';
|
|
9
9
|
const LOGIN_TIMEOUT_MS = 5 * 60 * 1000;
|
|
@@ -91,7 +91,13 @@ export async function startCallbackServer(state, appOrigin, timeoutMs) {
|
|
|
91
91
|
res.writeHead(200, { ...corsHeaders, 'Content-Type': 'application/json' });
|
|
92
92
|
res.end(JSON.stringify({ ok: true }));
|
|
93
93
|
clearTimeout(timer);
|
|
94
|
-
|
|
94
|
+
const account = sanitizeAccount(parsed.account);
|
|
95
|
+
resolvePayload({
|
|
96
|
+
token: parsed.token,
|
|
97
|
+
expiresIn: parsed.expiresIn,
|
|
98
|
+
apiUrl: parsed.apiUrl,
|
|
99
|
+
...(account ? { account } : {}),
|
|
100
|
+
});
|
|
95
101
|
}
|
|
96
102
|
catch {
|
|
97
103
|
res.writeHead(400, corsHeaders);
|
|
@@ -186,7 +192,13 @@ export function parseManualCredential(blob) {
|
|
|
186
192
|
throw new Error('Pasted credential is missing required fields (expected JSON with token, expiresIn, apiUrl). ' +
|
|
187
193
|
'Copy the entire blob shown in the browser.');
|
|
188
194
|
}
|
|
189
|
-
|
|
195
|
+
const account = sanitizeAccount(c.account);
|
|
196
|
+
return {
|
|
197
|
+
token: c.token,
|
|
198
|
+
expiresIn: c.expiresIn,
|
|
199
|
+
apiUrl: c.apiUrl,
|
|
200
|
+
...(account ? { account } : {}),
|
|
201
|
+
};
|
|
190
202
|
}
|
|
191
203
|
export async function verifyRunCloudCredential(apiUrl, token) {
|
|
192
204
|
try {
|
|
@@ -318,6 +330,7 @@ export function registerLogin(program) {
|
|
|
318
330
|
apiUrl: parsed.apiUrl,
|
|
319
331
|
appUrl: opts.appUrl,
|
|
320
332
|
expiresAt: Math.floor(Date.now() / 1000) + parsed.expiresIn,
|
|
333
|
+
...(parsed.account ? { account: parsed.account } : {}),
|
|
321
334
|
});
|
|
322
335
|
console.log('Logged in.');
|
|
323
336
|
return;
|
|
@@ -380,6 +393,7 @@ export function registerLogin(program) {
|
|
|
380
393
|
appUrl: opts.appUrl,
|
|
381
394
|
expiresAt: Math.floor(Date.now() / 1000) + payload.expiresIn,
|
|
382
395
|
revocable: true,
|
|
396
|
+
...(payload.account ? { account: payload.account } : {}),
|
|
383
397
|
});
|
|
384
398
|
console.log(`Logged in. Credentials saved to ${credentialsDisplayPath()}`);
|
|
385
399
|
return;
|
|
@@ -400,8 +414,10 @@ export function registerLogin(program) {
|
|
|
400
414
|
apiUrl: payload.apiUrl,
|
|
401
415
|
appUrl: opts.appUrl,
|
|
402
416
|
expiresAt: Math.floor(Date.now() / 1000) + payload.expiresIn,
|
|
417
|
+
...(payload.account ? { account: payload.account } : {}),
|
|
403
418
|
});
|
|
404
|
-
console.log(`Logged in.
|
|
419
|
+
console.log(`Logged in${payload.account ? ` as ${payload.account}` : ''}. ` +
|
|
420
|
+
`Credentials saved to ${credentialsDisplayPath()}`);
|
|
405
421
|
}
|
|
406
422
|
finally {
|
|
407
423
|
close();
|
package/dist/commands/sandbox.js
CHANGED
|
@@ -358,8 +358,17 @@ export function registerSandbox(program) {
|
|
|
358
358
|
else
|
|
359
359
|
console.log(renderSandbox(exposedRecord, 'created'));
|
|
360
360
|
}));
|
|
361
|
-
withOutput(sandbox
|
|
362
|
-
|
|
361
|
+
withOutput(sandbox
|
|
362
|
+
.command('list')
|
|
363
|
+
.description('List sandboxes')
|
|
364
|
+
.option('--state <state>', 'filter by state')
|
|
365
|
+
.option('--name <name>', 'filter by name (exact)')).action((opts) => run(async () => {
|
|
366
|
+
const query = new URLSearchParams();
|
|
367
|
+
if (opts.state)
|
|
368
|
+
query.set('state', opts.state);
|
|
369
|
+
if (opts.name)
|
|
370
|
+
query.set('name', opts.name);
|
|
371
|
+
const qs = query.size ? `?${query}` : '';
|
|
363
372
|
const api = runCloudApi();
|
|
364
373
|
const [data, boxes] = await Promise.all([
|
|
365
374
|
api.get(`/run-cloud/sandboxes${qs}`),
|
|
@@ -525,6 +534,17 @@ export function registerSandbox(program) {
|
|
|
525
534
|
console.log(`${style.green('✓')} ${lifecycle.pastTense} ${id}`);
|
|
526
535
|
}));
|
|
527
536
|
}
|
|
537
|
+
withOutput(sandbox
|
|
538
|
+
.command('rename')
|
|
539
|
+
.description('Change a sandbox name (the label `list --name` filters on)')
|
|
540
|
+
.argument('<id>', 'sandbox id')
|
|
541
|
+
.argument('<name>', 'new name; pass "" to clear it')).action((id, name, opts) => run(async () => {
|
|
542
|
+
const record = await runCloudApi().post(`/run-cloud/sandboxes/${encodeURIComponent(id)}/name`, { name });
|
|
543
|
+
if (opts.json)
|
|
544
|
+
printJson(record);
|
|
545
|
+
else
|
|
546
|
+
console.log(`${style.green('✓')} Renamed ${id} to ${name || '(no name)'}`);
|
|
547
|
+
}));
|
|
528
548
|
withOutput(sandbox
|
|
529
549
|
.command('logs')
|
|
530
550
|
.description('Show saved console logs (available after a sandbox is deleted)')
|
package/dist/config.js
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { homedir } from 'node:os';
|
|
3
3
|
import { basename, join } from 'node:path';
|
|
4
|
+
const MAX_ACCOUNT_LENGTH = 320;
|
|
5
|
+
export function sanitizeAccount(value) {
|
|
6
|
+
if (typeof value !== 'string')
|
|
7
|
+
return undefined;
|
|
8
|
+
const trimmed = value.trim();
|
|
9
|
+
if (trimmed.length === 0 || trimmed.length > MAX_ACCOUNT_LENGTH)
|
|
10
|
+
return undefined;
|
|
11
|
+
return trimmed;
|
|
12
|
+
}
|
|
4
13
|
export function isRunCloud() {
|
|
5
14
|
const names = [process.argv[1], process.execPath].map((path) => basename(path ?? ''));
|
|
6
15
|
return names.some((name) => name === 'runcloud' || name === 'run-cloud' || name === 'run-cloud.js');
|
package/dist/deviceLogin.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { normalizeApiUrl } from "./config.js";
|
|
1
|
+
import { normalizeApiUrl, sanitizeAccount } from "./config.js";
|
|
2
2
|
export async function runDeviceLogin(deps) {
|
|
3
3
|
const fetchFn = deps.fetchFn ?? fetch;
|
|
4
4
|
const log = deps.log ?? ((m) => console.log(m));
|
|
@@ -32,7 +32,13 @@ export async function runDeviceLogin(deps) {
|
|
|
32
32
|
});
|
|
33
33
|
if (res.ok) {
|
|
34
34
|
const body = (await res.json());
|
|
35
|
-
|
|
35
|
+
const account = sanitizeAccount(body.account);
|
|
36
|
+
return {
|
|
37
|
+
token: body.token,
|
|
38
|
+
apiUrl: body.apiUrl,
|
|
39
|
+
expiresIn: body.expiresIn,
|
|
40
|
+
...(account ? { account } : {}),
|
|
41
|
+
};
|
|
36
42
|
}
|
|
37
43
|
const { error } = (await res.json().catch(() => ({ error: "unknown" })));
|
|
38
44
|
if (error === "authorization_pending")
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const CLI_VERSION = '0.1.
|
|
1
|
+
export const CLI_VERSION = '0.1.94';
|
package/package.json
CHANGED
|
@@ -54,11 +54,13 @@ runcloud sandbox exec "$SANDBOX_ID" "npm install && npm test"
|
|
|
54
54
|
The main lifecycle commands are:
|
|
55
55
|
|
|
56
56
|
- `runcloud sandbox create`
|
|
57
|
-
- `runcloud sandbox list [--state <state>]`
|
|
57
|
+
- `runcloud sandbox list [--state <state>] [--name <name>]`
|
|
58
58
|
- `runcloud sandbox get <id>`
|
|
59
59
|
- `runcloud sandbox exec <id> <cmd...>`
|
|
60
60
|
- `runcloud sandbox shell <id>`
|
|
61
61
|
- `runcloud sandbox pause|resume <id>`
|
|
62
|
+
- `runcloud sandbox rename <id> <name>` — relabel an existing sandbox; pair with
|
|
63
|
+
`list --name` to find a sandbox again instead of creating a second one
|
|
62
64
|
- `runcloud sandbox logs <id> [--lines <n>]`
|
|
63
65
|
- `runcloud sandbox metrics <id> [--range <range>] [--watch]`
|
|
64
66
|
- `runcloud sandbox rm <id>`
|