dexto 1.14.4 → 2.0.0-beta.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/dist/cli/auth/billing.d.ts +0 -6
- package/dist/cli/auth/billing.d.ts.map +1 -1
- package/dist/cli/auth/billing.js +0 -23
- package/dist/cli/auth/constants.d.ts +3 -31
- package/dist/cli/auth/constants.d.ts.map +1 -1
- package/dist/cli/auth/constants.js +9 -33
- package/dist/cli/auth/index.d.ts +2 -9
- package/dist/cli/auth/index.d.ts.map +1 -1
- package/dist/cli/auth/index.js +2 -7
- package/dist/cli/auth/sign-in-runtime.d.ts +12 -0
- package/dist/cli/auth/sign-in-runtime.d.ts.map +1 -0
- package/dist/cli/auth/sign-in-runtime.js +59 -0
- package/dist/cli/cloud/app-scopes.d.ts +4 -0
- package/dist/cli/cloud/app-scopes.d.ts.map +1 -0
- package/dist/cli/cloud/app-scopes.js +19 -0
- package/dist/cli/cloud/command.d.ts +143 -0
- package/dist/cli/cloud/command.d.ts.map +1 -0
- package/dist/cli/cloud/command.js +202 -0
- package/dist/cli/cloud/commands/account.d.ts +11 -0
- package/dist/cli/cloud/commands/account.d.ts.map +1 -0
- package/dist/cli/cloud/commands/account.js +128 -0
- package/dist/cli/cloud/commands/agents.d.ts +3 -0
- package/dist/cli/cloud/commands/agents.d.ts.map +1 -0
- package/dist/cli/cloud/commands/agents.js +524 -0
- package/dist/cli/cloud/commands/api.d.ts +3 -0
- package/dist/cli/cloud/commands/api.d.ts.map +1 -0
- package/dist/cli/cloud/commands/api.js +26 -0
- package/dist/cli/cloud/commands/app-files.d.ts +29 -0
- package/dist/cli/cloud/commands/app-files.d.ts.map +1 -0
- package/dist/cli/cloud/commands/app-files.js +72 -0
- package/dist/cli/cloud/commands/automations.d.ts +3 -0
- package/dist/cli/cloud/commands/automations.d.ts.map +1 -0
- package/dist/cli/cloud/commands/automations.js +232 -0
- package/dist/cli/cloud/commands/chats.d.ts +3 -0
- package/dist/cli/cloud/commands/chats.d.ts.map +1 -0
- package/dist/cli/cloud/commands/chats.js +189 -0
- package/dist/cli/cloud/commands/data-deletions.d.ts +3 -0
- package/dist/cli/cloud/commands/data-deletions.d.ts.map +1 -0
- package/dist/cli/cloud/commands/data-deletions.js +54 -0
- package/dist/cli/cloud/commands/deploys.d.ts +10 -0
- package/dist/cli/cloud/commands/deploys.d.ts.map +1 -0
- package/dist/cli/cloud/commands/deploys.js +223 -0
- package/dist/cli/cloud/commands/drive.d.ts +12 -0
- package/dist/cli/cloud/commands/drive.d.ts.map +1 -0
- package/dist/cli/cloud/commands/drive.js +320 -0
- package/dist/cli/cloud/commands/files.d.ts +24 -0
- package/dist/cli/cloud/commands/files.d.ts.map +1 -0
- package/dist/cli/cloud/commands/files.js +282 -0
- package/dist/cli/cloud/commands/find.d.ts +3 -0
- package/dist/cli/cloud/commands/find.d.ts.map +1 -0
- package/dist/cli/cloud/commands/find.js +63 -0
- package/dist/cli/cloud/commands/models.d.ts +3 -0
- package/dist/cli/cloud/commands/models.d.ts.map +1 -0
- package/dist/cli/cloud/commands/models.js +248 -0
- package/dist/cli/cloud/commands/profile.d.ts +3 -0
- package/dist/cli/cloud/commands/profile.d.ts.map +1 -0
- package/dist/cli/cloud/commands/profile.js +119 -0
- package/dist/cli/cloud/commands/projects.d.ts +5 -0
- package/dist/cli/cloud/commands/projects.d.ts.map +1 -0
- package/dist/cli/cloud/commands/projects.js +66 -0
- package/dist/cli/cloud/commands/publish.d.ts +3 -0
- package/dist/cli/cloud/commands/publish.d.ts.map +1 -0
- package/dist/cli/cloud/commands/publish.js +138 -0
- package/dist/cli/cloud/commands/sandboxes.d.ts +3 -0
- package/dist/cli/cloud/commands/sandboxes.d.ts.map +1 -0
- package/dist/cli/cloud/commands/sandboxes.js +265 -0
- package/dist/cli/cloud/commands/secrets.d.ts +3 -0
- package/dist/cli/cloud/commands/secrets.d.ts.map +1 -0
- package/dist/cli/cloud/commands/secrets.js +110 -0
- package/dist/cli/cloud/commands/skills.d.ts +3 -0
- package/dist/cli/cloud/commands/skills.d.ts.map +1 -0
- package/dist/cli/cloud/commands/skills.js +202 -0
- package/dist/cli/cloud/commands/web.d.ts +3 -0
- package/dist/cli/cloud/commands/web.d.ts.map +1 -0
- package/dist/cli/cloud/commands/web.js +53 -0
- package/dist/cli/cloud/commands/workspace-apps.d.ts +58 -0
- package/dist/cli/cloud/commands/workspace-apps.d.ts.map +1 -0
- package/dist/cli/cloud/commands/workspace-apps.js +656 -0
- package/dist/cli/cloud/commands/workspace.d.ts +36 -0
- package/dist/cli/cloud/commands/workspace.d.ts.map +1 -0
- package/dist/cli/cloud/commands/workspace.js +279 -0
- package/dist/cli/cloud/connection.d.ts +33 -0
- package/dist/cli/cloud/connection.d.ts.map +1 -0
- package/dist/cli/cloud/connection.js +38 -0
- package/dist/cli/cloud/events.d.ts +63 -0
- package/dist/cli/cloud/events.d.ts.map +1 -0
- package/dist/cli/cloud/events.js +72 -0
- package/dist/cli/cloud/host.d.ts +9 -0
- package/dist/cli/cloud/host.d.ts.map +1 -0
- package/dist/cli/cloud/host.js +105 -0
- package/dist/cli/cloud/local-chats.d.ts +73 -0
- package/dist/cli/cloud/local-chats.d.ts.map +1 -0
- package/dist/cli/cloud/local-chats.js +441 -0
- package/dist/cli/cloud/output.d.ts +34 -0
- package/dist/cli/cloud/output.d.ts.map +1 -0
- package/dist/cli/cloud/output.js +76 -0
- package/dist/cli/cloud/run.d.ts +26 -0
- package/dist/cli/cloud/run.d.ts.map +1 -0
- package/dist/cli/cloud/run.js +444 -0
- package/dist/cli/cloud/runtime.d.ts +33 -0
- package/dist/cli/cloud/runtime.d.ts.map +1 -0
- package/dist/cli/cloud/runtime.js +86 -0
- package/dist/cli/cloud/tar.d.ts +9 -0
- package/dist/cli/cloud/tar.d.ts.map +1 -0
- package/dist/cli/cloud/tar.js +69 -0
- package/dist/cli/cloud/transfer.d.ts +13 -0
- package/dist/cli/cloud/transfer.d.ts.map +1 -0
- package/dist/cli/cloud/transfer.js +35 -0
- package/dist/cli/cloud/v1.d.ts +19 -0
- package/dist/cli/cloud/v1.d.ts.map +1 -0
- package/dist/cli/cloud/v1.js +65 -0
- package/dist/cli/cloud/zip.d.ts +8 -0
- package/dist/cli/cloud/zip.d.ts.map +1 -0
- package/dist/cli/cloud/zip.js +66 -0
- package/dist/cli/commands/auth/sign-in-commands.d.ts +62 -0
- package/dist/cli/commands/auth/sign-in-commands.d.ts.map +1 -0
- package/dist/cli/commands/auth/sign-in-commands.js +247 -0
- package/dist/cli/commands/auth/sign-in-context.d.ts +16 -0
- package/dist/cli/commands/auth/sign-in-context.d.ts.map +1 -0
- package/dist/cli/commands/auth/sign-in-context.js +68 -0
- package/dist/cli/commands/cloud/register.d.ts +5 -0
- package/dist/cli/commands/cloud/register.d.ts.map +1 -1
- package/dist/cli/commands/cloud/register.js +42 -24
- package/dist/cli/commands/create-app.js +5 -6
- package/dist/cli/commands/create-image.d.ts.map +1 -1
- package/dist/cli/commands/create-image.js +9 -10
- package/dist/cli/commands/index.d.ts +0 -2
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +0 -2
- package/dist/cli/commands/init.d.ts +0 -2
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +5 -26
- package/dist/cli/commands/run/headless.js +2 -2
- package/dist/cli/commands/run/output.d.ts +29 -10
- package/dist/cli/commands/run/output.d.ts.map +1 -1
- package/dist/cli/commands/run/output.js +44 -22
- package/dist/cli/commands/run/register.d.ts.map +1 -1
- package/dist/cli/commands/run/register.js +21 -9
- package/dist/cli/commands/session/register.d.ts.map +1 -1
- package/dist/cli/commands/session/register.js +51 -21
- package/dist/cli/commands/session-commands.js +1 -1
- package/dist/cli/commands/setup.js +17 -14
- package/dist/cli/help-json.d.ts +22 -0
- package/dist/cli/help-json.d.ts.map +1 -0
- package/dist/cli/help-json.js +20 -0
- package/dist/cli/modes/cli.d.ts.map +1 -1
- package/dist/cli/modes/cli.js +42 -9
- package/dist/cli/modes/server.js +8 -8
- package/dist/cli/modes/web.js +3 -3
- package/dist/cli/utils/dexto-auth-check.d.ts +1 -1
- package/dist/cli/utils/dexto-auth-check.d.ts.map +1 -1
- package/dist/cli/utils/dexto-auth-check.js +4 -5
- package/dist/cli/utils/dexto-setup.d.ts +4 -5
- package/dist/cli/utils/dexto-setup.d.ts.map +1 -1
- package/dist/cli/utils/dexto-setup.js +17 -14
- package/dist/cli/utils/provider-setup.js +1 -1
- package/dist/cli/utils/scaffolding-utils.d.ts +9 -3
- package/dist/cli/utils/scaffolding-utils.d.ts.map +1 -1
- package/dist/cli/utils/scaffolding-utils.js +48 -40
- package/dist/cli/utils/version-check.d.ts.map +1 -1
- package/dist/cli/utils/version-check.js +2 -1
- package/dist/index-main.js +33 -65
- package/package.json +8 -7
- package/dist/cli/auth/api-client.d.ts +0 -125
- package/dist/cli/auth/api-client.d.ts.map +0 -1
- package/dist/cli/auth/api-client.js +0 -585
- package/dist/cli/auth/device.d.ts +0 -14
- package/dist/cli/auth/device.d.ts.map +0 -1
- package/dist/cli/auth/device.js +0 -84
- package/dist/cli/auth/dexto-api-key.d.ts +0 -34
- package/dist/cli/auth/dexto-api-key.d.ts.map +0 -1
- package/dist/cli/auth/dexto-api-key.js +0 -160
- package/dist/cli/auth/login-persistence.d.ts +0 -15
- package/dist/cli/auth/login-persistence.d.ts.map +0 -1
- package/dist/cli/auth/login-persistence.js +0 -72
- package/dist/cli/auth/oauth.d.ts +0 -39
- package/dist/cli/auth/oauth.d.ts.map +0 -1
- package/dist/cli/auth/oauth.js +0 -434
- package/dist/cli/auth/service.d.ts +0 -24
- package/dist/cli/auth/service.d.ts.map +0 -1
- package/dist/cli/auth/service.js +0 -161
- package/dist/cli/auth/types.d.ts +0 -11
- package/dist/cli/auth/types.d.ts.map +0 -1
- package/dist/cli/auth/types.js +0 -1
- package/dist/cli/cloud-chat.d.ts +0 -18
- package/dist/cli/cloud-chat.d.ts.map +0 -1
- package/dist/cli/cloud-chat.js +0 -734
- package/dist/cli/commands/auth/index.d.ts +0 -4
- package/dist/cli/commands/auth/index.d.ts.map +0 -1
- package/dist/cli/commands/auth/index.js +0 -4
- package/dist/cli/commands/auth/login.d.ts +0 -12
- package/dist/cli/commands/auth/login.d.ts.map +0 -1
- package/dist/cli/commands/auth/login.js +0 -153
- package/dist/cli/commands/auth/logout.d.ts +0 -5
- package/dist/cli/commands/auth/logout.d.ts.map +0 -1
- package/dist/cli/commands/auth/logout.js +0 -81
- package/dist/cli/commands/auth/register.d.ts +0 -3
- package/dist/cli/commands/auth/register.d.ts.map +0 -1
- package/dist/cli/commands/auth/register.js +0 -96
- package/dist/cli/commands/auth/status.d.ts +0 -2
- package/dist/cli/commands/auth/status.d.ts.map +0 -1
- package/dist/cli/commands/auth/status.js +0 -22
- package/dist/cli/commands/billing/index.d.ts +0 -2
- package/dist/cli/commands/billing/index.d.ts.map +0 -1
- package/dist/cli/commands/billing/index.js +0 -2
- package/dist/cli/commands/billing/register.d.ts +0 -3
- package/dist/cli/commands/billing/register.d.ts.map +0 -1
- package/dist/cli/commands/billing/register.js +0 -20
- package/dist/cli/commands/billing/status.d.ts +0 -8
- package/dist/cli/commands/billing/status.d.ts.map +0 -1
- package/dist/cli/commands/billing/status.js +0 -71
- package/dist/cli/commands/cloud/discovery.d.ts +0 -17
- package/dist/cli/commands/cloud/discovery.d.ts.map +0 -1
- package/dist/cli/commands/cloud/discovery.js +0 -88
- package/dist/cli/commands/deploy/client.d.ts +0 -113
- package/dist/cli/commands/deploy/client.d.ts.map +0 -1
- package/dist/cli/commands/deploy/client.js +0 -519
- package/dist/cli/commands/deploy/config.d.ts +0 -37
- package/dist/cli/commands/deploy/config.d.ts.map +0 -1
- package/dist/cli/commands/deploy/config.js +0 -144
- package/dist/cli/commands/deploy/entry-agent.d.ts +0 -3
- package/dist/cli/commands/deploy/entry-agent.d.ts.map +0 -1
- package/dist/cli/commands/deploy/entry-agent.js +0 -70
- package/dist/cli/commands/deploy/index.d.ts +0 -12
- package/dist/cli/commands/deploy/index.d.ts.map +0 -1
- package/dist/cli/commands/deploy/index.js +0 -370
- package/dist/cli/commands/deploy/links.d.ts +0 -3
- package/dist/cli/commands/deploy/links.d.ts.map +0 -1
- package/dist/cli/commands/deploy/links.js +0 -53
- package/dist/cli/commands/deploy/register.d.ts +0 -6
- package/dist/cli/commands/deploy/register.d.ts.map +0 -1
- package/dist/cli/commands/deploy/register.js +0 -128
- package/dist/cli/commands/deploy/snapshot.d.ts +0 -12
- package/dist/cli/commands/deploy/snapshot.d.ts.map +0 -1
- package/dist/cli/commands/deploy/snapshot.js +0 -76
- package/dist/cli/commands/deploy/state.d.ts +0 -13
- package/dist/cli/commands/deploy/state.d.ts.map +0 -1
- package/dist/cli/commands/deploy/state.js +0 -122
- package/dist/cli/commands/span/register.d.ts +0 -6
- package/dist/cli/commands/span/register.d.ts.map +0 -1
- package/dist/cli/commands/span/register.js +0 -25
- package/dist/cli/commands/trace/client.d.ts +0 -98
- package/dist/cli/commands/trace/client.d.ts.map +0 -1
- package/dist/cli/commands/trace/client.js +0 -150
- package/dist/cli/commands/trace/format.d.ts +0 -5
- package/dist/cli/commands/trace/format.d.ts.map +0 -1
- package/dist/cli/commands/trace/format.js +0 -58
- package/dist/cli/commands/trace/index.d.ts +0 -21
- package/dist/cli/commands/trace/index.d.ts.map +0 -1
- package/dist/cli/commands/trace/index.js +0 -49
- package/dist/cli/commands/trace/register.d.ts +0 -6
- package/dist/cli/commands/trace/register.d.ts.map +0 -1
- package/dist/cli/commands/trace/register.js +0 -71
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// `profile`: read and change your own Dexto profile, as Settings → Profile does.
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { CommandFailure, stringOption, UsageError, } from '../command.js';
|
|
4
|
+
import { queryWorkspaceTool } from './workspace.js';
|
|
5
|
+
const ProfileSchema = z.object({
|
|
6
|
+
bio: z.string().nullable(),
|
|
7
|
+
displayName: z.string(),
|
|
8
|
+
handle: z.string(),
|
|
9
|
+
links: z.array(z.unknown()),
|
|
10
|
+
showTokenUsage: z.boolean(),
|
|
11
|
+
visibility: z.enum(['private', 'public']),
|
|
12
|
+
workEntries: z.array(z.unknown()),
|
|
13
|
+
});
|
|
14
|
+
const get = {
|
|
15
|
+
path: ['profile', 'get'],
|
|
16
|
+
summary: 'Show your Dexto profile: handle, name, bio, links, work and whether it is public.',
|
|
17
|
+
async run(context) {
|
|
18
|
+
const profile = await readProfile(context, 'dexto_profile_get', {});
|
|
19
|
+
context.output.result({ profile }, describeProfile(profile));
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
const update = {
|
|
23
|
+
options: {
|
|
24
|
+
bio: {
|
|
25
|
+
description: 'Your bio; "" clears it.',
|
|
26
|
+
type: 'string',
|
|
27
|
+
valueName: 'TEXT',
|
|
28
|
+
},
|
|
29
|
+
'display-name': { description: 'Your display name.', type: 'string', valueName: 'NAME' },
|
|
30
|
+
handle: {
|
|
31
|
+
description: 'Your handle, unique across Dexto: 3 to 30 lowercase letters, digits and hyphens.',
|
|
32
|
+
type: 'string',
|
|
33
|
+
valueName: 'HANDLE',
|
|
34
|
+
},
|
|
35
|
+
links: {
|
|
36
|
+
description: 'Your links, replacing them all, as JSON: [{"kind":"github","url":"https://…"}] or {"kind":"custom","label":"…","url":"…"} entries.',
|
|
37
|
+
type: 'string',
|
|
38
|
+
valueName: 'JSON',
|
|
39
|
+
},
|
|
40
|
+
'token-usage': {
|
|
41
|
+
description: 'Whether your profile shows your token usage: show or hide.',
|
|
42
|
+
type: 'string',
|
|
43
|
+
valueName: 'show|hide',
|
|
44
|
+
},
|
|
45
|
+
visibility: {
|
|
46
|
+
description: 'private, or public for anyone with the link.',
|
|
47
|
+
type: 'string',
|
|
48
|
+
valueName: 'private|public',
|
|
49
|
+
},
|
|
50
|
+
work: {
|
|
51
|
+
description: 'Your work entries, replacing them all, as JSON: {"kind":"site","siteId":"…"} or {"kind":"external","title":"…","url":"…","description":null,"imageUrl":null} entries.',
|
|
52
|
+
type: 'string',
|
|
53
|
+
valueName: 'JSON',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
path: ['profile', 'update'],
|
|
57
|
+
summary: 'Change your Dexto profile: only the fields you pass change, such as --handle shaun --visibility public.',
|
|
58
|
+
async run(context, input) {
|
|
59
|
+
const changes = profileChanges(input);
|
|
60
|
+
if (Object.keys(changes).length === 0)
|
|
61
|
+
throw new UsageError('Pass at least one field to change, such as --handle or --visibility.');
|
|
62
|
+
const profile = await readProfile(context, 'dexto_profile_update', changes);
|
|
63
|
+
context.output.result({ profile }, `Updated.\n${describeProfile(profile)}`);
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
/** What `profile update` asks to change, in `dexto_profile_update`'s fields. */
|
|
67
|
+
function profileChanges(input) {
|
|
68
|
+
const visibility = stringOption(input, 'visibility');
|
|
69
|
+
if (visibility !== undefined && visibility !== 'private' && visibility !== 'public')
|
|
70
|
+
throw new UsageError('--visibility must be private or public.');
|
|
71
|
+
const tokenUsage = stringOption(input, 'token-usage');
|
|
72
|
+
if (tokenUsage !== undefined && tokenUsage !== 'show' && tokenUsage !== 'hide')
|
|
73
|
+
throw new UsageError('--token-usage must be show or hide.');
|
|
74
|
+
const bio = stringOption(input, 'bio');
|
|
75
|
+
const displayName = stringOption(input, 'display-name');
|
|
76
|
+
const handle = stringOption(input, 'handle');
|
|
77
|
+
const links = jsonListOption(input, 'links');
|
|
78
|
+
const work = jsonListOption(input, 'work');
|
|
79
|
+
return {
|
|
80
|
+
...(bio === undefined ? {} : { bio: bio.trim().length === 0 ? null : bio }),
|
|
81
|
+
...(displayName === undefined ? {} : { displayName }),
|
|
82
|
+
...(handle === undefined ? {} : { handle }),
|
|
83
|
+
...(links === undefined ? {} : { links }),
|
|
84
|
+
...(tokenUsage === undefined ? {} : { showTokenUsage: tokenUsage === 'show' }),
|
|
85
|
+
...(visibility === undefined ? {} : { visibility }),
|
|
86
|
+
...(work === undefined ? {} : { workEntries: work }),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/** A JSON list option: every link or work entry at once, replacing what is there. */
|
|
90
|
+
function jsonListOption(input, name) {
|
|
91
|
+
const value = stringOption(input, name);
|
|
92
|
+
if (value === undefined)
|
|
93
|
+
return undefined;
|
|
94
|
+
let parsed;
|
|
95
|
+
try {
|
|
96
|
+
parsed = JSON.parse(value);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
throw new UsageError(`--${name} must be a JSON list.`);
|
|
100
|
+
}
|
|
101
|
+
if (!Array.isArray(parsed))
|
|
102
|
+
throw new UsageError(`--${name} must be a JSON list.`);
|
|
103
|
+
return parsed;
|
|
104
|
+
}
|
|
105
|
+
async function readProfile(context, tool, input) {
|
|
106
|
+
const value = await queryWorkspaceTool(context, tool, input);
|
|
107
|
+
const parsed = z.object({ profile: ProfileSchema }).safeParse(value);
|
|
108
|
+
if (!parsed.success)
|
|
109
|
+
throw new CommandFailure('failed', "Dexto didn't return your profile.", null);
|
|
110
|
+
return parsed.data.profile;
|
|
111
|
+
}
|
|
112
|
+
function describeProfile(profile) {
|
|
113
|
+
return [
|
|
114
|
+
`@${profile.handle} (${profile.displayName}), ${profile.visibility}`,
|
|
115
|
+
...(profile.bio === null ? [] : [profile.bio]),
|
|
116
|
+
`${profile.links.length} links, ${profile.workEntries.length} work entries, token usage ${profile.showTokenUsage ? 'shown' : 'hidden'}`,
|
|
117
|
+
].join('\n');
|
|
118
|
+
}
|
|
119
|
+
export const profileCommands = [get, update];
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type Command } from '../command.js';
|
|
2
|
+
/** Chooses the project a person's sign-in acts in; `accounts` reads the same saved login. */
|
|
3
|
+
export declare function projectsUse(accountsDir: string): Command;
|
|
4
|
+
export declare const projectCommands: readonly Command[];
|
|
5
|
+
//# sourceMappingURL=projects.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../../../src/cli/cloud/commands/projects.ts"],"names":[],"mappings":"AAIA,OAAO,EAAwB,KAAK,OAAO,EAAuB,MAAM,eAAe,CAAC;AA8CxF,6FAA6F;AAC7F,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAkCxD;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,OAAO,EAAmB,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// `cloud projects`: the Cloud projects you can act in, and which one commands use.
|
|
2
|
+
import { dextoAccounts } from '@dexto/agent-management';
|
|
3
|
+
import { unwrap } from '@dexto/cloud-client';
|
|
4
|
+
import { argument, UsageError } from '../command.js';
|
|
5
|
+
async function listProjects(context) {
|
|
6
|
+
return await unwrap(await (await context.client()).GET('/v1/projects'));
|
|
7
|
+
}
|
|
8
|
+
const list = {
|
|
9
|
+
path: ['cloud', 'projects', 'list'],
|
|
10
|
+
summary: 'List the Cloud projects you can act in; * marks the current one.',
|
|
11
|
+
async run(context) {
|
|
12
|
+
const connection = await context.connection();
|
|
13
|
+
const projects = await listProjects(context);
|
|
14
|
+
context.output.list(projects, [
|
|
15
|
+
{
|
|
16
|
+
header: '',
|
|
17
|
+
value: (project) => project.id === connection.cloudProject ||
|
|
18
|
+
(connection.kind === 'api_key' && projects.data.length === 1)
|
|
19
|
+
? '*'
|
|
20
|
+
: '',
|
|
21
|
+
},
|
|
22
|
+
{ header: 'id', value: (project) => project.id },
|
|
23
|
+
{ header: 'name', value: (project) => project.name },
|
|
24
|
+
{ header: 'default', value: (project) => (project.is_default ? 'yes' : '') },
|
|
25
|
+
{ header: 'archived', value: (project) => project.archived_at },
|
|
26
|
+
]);
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
const create = {
|
|
30
|
+
arguments: '<name>',
|
|
31
|
+
path: ['cloud', 'projects', 'create'],
|
|
32
|
+
summary: 'Create a Cloud project. Owners and Admins create projects.',
|
|
33
|
+
async run(context, input) {
|
|
34
|
+
const project = await unwrap(await (await context.client()).POST('/v1/projects', { body: { name: argument(input, 0, 'name') } }));
|
|
35
|
+
context.output.result(project, `Created Cloud project ${project.name} (${project.id}). Act in it with dexto cloud projects use ${project.id}.`);
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
/** Chooses the project a person's sign-in acts in; `accounts` reads the same saved login. */
|
|
39
|
+
export function projectsUse(accountsDir) {
|
|
40
|
+
return {
|
|
41
|
+
arguments: '<project>',
|
|
42
|
+
path: ['cloud', 'projects', 'use'],
|
|
43
|
+
summary: 'Act in this Cloud project, by id or name, from now on. Dexto models bill it too.',
|
|
44
|
+
async run(context, input) {
|
|
45
|
+
const connection = await context.connection();
|
|
46
|
+
if (connection.kind !== 'oauth' || connection.source !== 'login')
|
|
47
|
+
throw new UsageError('A key acts only in its own project. Sign in with dexto login to choose projects.');
|
|
48
|
+
const wanted = argument(input, 0, 'project');
|
|
49
|
+
const projects = await listProjects(context);
|
|
50
|
+
const matches = projects.data.filter((project) => project.id === wanted || project.name === wanted);
|
|
51
|
+
const [project] = matches;
|
|
52
|
+
if (project === undefined)
|
|
53
|
+
throw new UsageError(`No Cloud project ${wanted}.`);
|
|
54
|
+
if (matches.length > 1)
|
|
55
|
+
throw new UsageError(`More than one project is named ${wanted}; use its id.`);
|
|
56
|
+
if (project.archived_at !== null)
|
|
57
|
+
throw new UsageError(`${project.name} is archived. Restore it in the Cloud app first.`);
|
|
58
|
+
await dextoAccounts.writeLogin(accountsDir, connection.profile, {
|
|
59
|
+
...connection.login,
|
|
60
|
+
cloudProject: { id: project.id, name: project.name },
|
|
61
|
+
});
|
|
62
|
+
context.output.result(project, `Acting in Cloud project ${project.name} (${project.id}).`);
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export const projectCommands = [list, create];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../../../src/cli/cloud/commands/publish.ts"],"names":[],"mappings":"AAQA,OAAO,EAOH,KAAK,OAAO,EACf,MAAM,eAAe,CAAC;AAiKvB,eAAO,MAAM,eAAe,EAAE,SAAS,OAAO,EAAc,CAAC"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// `publish`: puts a page, a document or a folder online as a link anyone with it can open.
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { readdir, readFile, stat } from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { argument, CommandFailure, stringOption, flag, UsageError, YES_OPTION, } from '../command.js';
|
|
7
|
+
import { sendBytes } from '../transfer.js';
|
|
8
|
+
import { zipArchive } from '../zip.js';
|
|
9
|
+
import { requireLoginScopes } from './deploys.js';
|
|
10
|
+
import { formatBytes } from './files.js';
|
|
11
|
+
import { agreeToCall, listWorkspaceTools, queryWorkspaceTool, toolCallLevel } from './workspace.js';
|
|
12
|
+
/** What a published link takes, as Dexto's Sites do: files, each file's size and their total. */
|
|
13
|
+
const MAX_FILES = 100;
|
|
14
|
+
const MAX_FILE_BYTES = 10 * 1024 * 1024;
|
|
15
|
+
const MAX_TOTAL_BYTES = 25 * 1024 * 1024;
|
|
16
|
+
/** The most the .zip that carries them can be, with room for its own headers. */
|
|
17
|
+
const MAX_UPLOAD_BYTES = MAX_TOTAL_BYTES + 1024 * 1024;
|
|
18
|
+
const PreparedSchema = z.object({
|
|
19
|
+
headers: z.record(z.string(), z.string()),
|
|
20
|
+
method: z.string(),
|
|
21
|
+
path: z.string(),
|
|
22
|
+
url: z.string(),
|
|
23
|
+
});
|
|
24
|
+
const PublishedSchema = z.object({
|
|
25
|
+
created: z.boolean(),
|
|
26
|
+
files: z.number(),
|
|
27
|
+
url: z.string(),
|
|
28
|
+
});
|
|
29
|
+
const publish = {
|
|
30
|
+
arguments: '<path>',
|
|
31
|
+
options: {
|
|
32
|
+
name: {
|
|
33
|
+
description: "What it's called: the page's title and, with your handle, its address (default: the file or folder's name). Publishing the same name again updates the same link.",
|
|
34
|
+
type: 'string',
|
|
35
|
+
},
|
|
36
|
+
slug: {
|
|
37
|
+
description: 'Publish at <slug>.dexto.dev instead of an address made from the name; a Site of yours there is updated.',
|
|
38
|
+
type: 'string',
|
|
39
|
+
},
|
|
40
|
+
title: { description: "The page's title (default: the name).", type: 'string' },
|
|
41
|
+
...YES_OPTION,
|
|
42
|
+
},
|
|
43
|
+
path: ['publish'],
|
|
44
|
+
summary: 'Publish a file, a folder or a .zip of one as a link anyone with it can open; publishing the same name again updates it.',
|
|
45
|
+
async run(context, input) {
|
|
46
|
+
await requireLoginScopes(context, ['sites:write']);
|
|
47
|
+
const target = path.resolve(argument(input, 0, 'path'));
|
|
48
|
+
const found = await stat(target).catch(() => null);
|
|
49
|
+
if (found === null || !(found.isFile() || found.isDirectory()))
|
|
50
|
+
throw new UsageError(`${target} isn't a file or folder.`);
|
|
51
|
+
const isZip = found.isFile() && /\.zip$/iu.test(target);
|
|
52
|
+
const name = stringOption(input, 'name') ??
|
|
53
|
+
(found.isDirectory()
|
|
54
|
+
? path.basename(target)
|
|
55
|
+
: path.basename(target, path.extname(target)));
|
|
56
|
+
const slug = stringOption(input, 'slug');
|
|
57
|
+
const title = stringOption(input, 'title');
|
|
58
|
+
let archive;
|
|
59
|
+
let count = null;
|
|
60
|
+
if (isZip)
|
|
61
|
+
archive = new Uint8Array(await readFile(target));
|
|
62
|
+
else {
|
|
63
|
+
const files = found.isDirectory()
|
|
64
|
+
? await readFolder(target)
|
|
65
|
+
: [{ bytes: await readFile(target), path: path.basename(target) }];
|
|
66
|
+
checkSizes(files);
|
|
67
|
+
archive = zipArchive(files);
|
|
68
|
+
count = files.length;
|
|
69
|
+
}
|
|
70
|
+
if (archive.byteLength > MAX_UPLOAD_BYTES)
|
|
71
|
+
throw new UsageError(`The .zip is ${formatBytes(archive.byteLength)}, over the ${formatBytes(MAX_UPLOAD_BYTES)} a published link's .zip can be.`);
|
|
72
|
+
const tool = (await listWorkspaceTools(context)).find((each) => each.name === 'dexto_site_publish');
|
|
73
|
+
if (tool === undefined)
|
|
74
|
+
throw new CommandFailure('failed', "This Dexto can't publish files yet.", null);
|
|
75
|
+
const call = {
|
|
76
|
+
name,
|
|
77
|
+
...(slug === undefined ? {} : { slug }),
|
|
78
|
+
...(title === undefined ? {} : { title }),
|
|
79
|
+
};
|
|
80
|
+
const agreed = await agreeToCall(context, {
|
|
81
|
+
level: toolCallLevel(tool, call),
|
|
82
|
+
schema: tool.inputSchema,
|
|
83
|
+
title: `Publish ${name} as a link anyone with it can open`,
|
|
84
|
+
}, flag(input, 'yes'));
|
|
85
|
+
const prepared = PreparedSchema.safeParse(await queryWorkspaceTool(context, 'dexto_upload_prepare', {
|
|
86
|
+
filename: `${path.basename(target, '.zip')}.zip`,
|
|
87
|
+
mimeType: 'application/zip',
|
|
88
|
+
purpose: 'site-files',
|
|
89
|
+
sha256: createHash('sha256').update(archive).digest('hex'),
|
|
90
|
+
sizeBytes: archive.byteLength,
|
|
91
|
+
}));
|
|
92
|
+
if (!prepared.success)
|
|
93
|
+
throw new CommandFailure('failed', "Dexto didn't say where to upload the files.", null);
|
|
94
|
+
const { headers, method, url } = prepared.data;
|
|
95
|
+
await sendBytes(context, { headers, method, url }, new globalThis.Blob([archive]));
|
|
96
|
+
const published = await queryWorkspaceTool(context, 'dexto_site_publish', {
|
|
97
|
+
...call,
|
|
98
|
+
uploadPath: prepared.data.path,
|
|
99
|
+
...agreed,
|
|
100
|
+
});
|
|
101
|
+
const shown = PublishedSchema.safeParse(published);
|
|
102
|
+
const files = shown.success ? shown.data.files : count;
|
|
103
|
+
context.output.result(published, shown.success
|
|
104
|
+
? `${shown.data.created ? 'Published' : 'Updated'} ${name} at ${shown.data.url} (${files} file${files === 1 ? '' : 's'}). Anyone with the link can open it.`
|
|
105
|
+
: JSON.stringify(published, null, 2));
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
/** The folder's files, by path, leaving out names that start with a dot and links. */
|
|
109
|
+
async function readFolder(folder) {
|
|
110
|
+
const found = [];
|
|
111
|
+
const visit = async (relative) => {
|
|
112
|
+
const entries = await readdir(path.join(folder, relative), { withFileTypes: true });
|
|
113
|
+
for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
|
|
114
|
+
if (entry.name.startsWith('.'))
|
|
115
|
+
continue;
|
|
116
|
+
const child = relative === '' ? entry.name : `${relative}/${entry.name}`;
|
|
117
|
+
if (entry.isDirectory())
|
|
118
|
+
await visit(child);
|
|
119
|
+
else if (entry.isFile())
|
|
120
|
+
found.push(child);
|
|
121
|
+
if (found.length > MAX_FILES)
|
|
122
|
+
throw new UsageError(`${folder} has more than ${MAX_FILES} files; a published link takes up to ${MAX_FILES}.`);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
await visit('');
|
|
126
|
+
if (found.length === 0)
|
|
127
|
+
throw new UsageError(`${folder} has no files to publish.`);
|
|
128
|
+
return await Promise.all(found.map(async (file) => ({ bytes: await readFile(path.join(folder, file)), path: file })));
|
|
129
|
+
}
|
|
130
|
+
function checkSizes(files) {
|
|
131
|
+
const large = files.find((file) => file.bytes.byteLength > MAX_FILE_BYTES);
|
|
132
|
+
if (large !== undefined)
|
|
133
|
+
throw new UsageError(`${large.path} is ${formatBytes(large.bytes.byteLength)}; a published file can be up to ${formatBytes(MAX_FILE_BYTES)}.`);
|
|
134
|
+
const total = files.reduce((sum, file) => sum + file.bytes.byteLength, 0);
|
|
135
|
+
if (total > MAX_TOTAL_BYTES)
|
|
136
|
+
throw new UsageError(`The files come to ${formatBytes(total)}; a published link takes up to ${formatBytes(MAX_TOTAL_BYTES)}.`);
|
|
137
|
+
}
|
|
138
|
+
export const publishCommands = [publish];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandboxes.d.ts","sourceRoot":"","sources":["../../../../src/cli/cloud/commands/sandboxes.ts"],"names":[],"mappings":"AAMA,OAAO,EAUH,KAAK,OAAO,EACf,MAAM,eAAe,CAAC;AAkUvB,eAAO,MAAM,eAAe,EAAE,SAAS,OAAO,EAc7C,CAAC"}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
// `cloud sandboxes`: create and control project sandboxes, run commands and move files.
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { unwrap } from '@dexto/cloud-client';
|
|
5
|
+
import { argument, flag, integerOption, PAGE_OPTIONS, pageQuery, requireConsent, stringOption, UsageError, YES_OPTION, } from '../command.js';
|
|
6
|
+
import { formatBytes } from './files.js';
|
|
7
|
+
/** A sandbox by id, for the calls under /v1/sandboxes/{sandbox_id}. */
|
|
8
|
+
function sandboxPath(id) {
|
|
9
|
+
return { params: { path: { sandbox_id: id } } };
|
|
10
|
+
}
|
|
11
|
+
/** A mutation that may be retried without doing it twice. */
|
|
12
|
+
function once() {
|
|
13
|
+
return { 'Idempotency-Key': randomUUID() };
|
|
14
|
+
}
|
|
15
|
+
const COLUMNS = [
|
|
16
|
+
{ header: 'id', value: (sandbox) => sandbox.id },
|
|
17
|
+
{ header: 'name', value: (sandbox) => sandbox.name },
|
|
18
|
+
{ header: 'status', value: (sandbox) => sandbox.status },
|
|
19
|
+
{ header: 'size', value: (sandbox) => sandbox.size },
|
|
20
|
+
{ header: 'updated', value: (sandbox) => sandbox.updated_at },
|
|
21
|
+
];
|
|
22
|
+
const list = {
|
|
23
|
+
options: PAGE_OPTIONS,
|
|
24
|
+
path: ['cloud', 'sandboxes', 'list'],
|
|
25
|
+
summary: "List the project's sandboxes.",
|
|
26
|
+
async run(context, input) {
|
|
27
|
+
context.output.list(await unwrap(await (await context.client()).GET('/v1/sandboxes', {
|
|
28
|
+
params: { query: pageQuery(input) },
|
|
29
|
+
})), COLUMNS);
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
const create = {
|
|
33
|
+
arguments: '<name>',
|
|
34
|
+
options: {
|
|
35
|
+
size: {
|
|
36
|
+
description: 'The sandbox size; large (4 vCPU, 8 GiB) is the only one.',
|
|
37
|
+
type: 'string',
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
path: ['cloud', 'sandboxes', 'create'],
|
|
41
|
+
summary: 'Create a sandbox. Start it before running commands in it.',
|
|
42
|
+
async run(context, input) {
|
|
43
|
+
const size = stringOption(input, 'size') ?? 'large';
|
|
44
|
+
if (size !== 'large')
|
|
45
|
+
throw new UsageError('large is the only sandbox size.');
|
|
46
|
+
const sandbox = await unwrap(await (await context.client()).POST('/v1/sandboxes', {
|
|
47
|
+
params: { header: once() },
|
|
48
|
+
body: { name: argument(input, 0, 'name'), size },
|
|
49
|
+
}));
|
|
50
|
+
context.output.result(sandbox, `Created sandbox ${sandbox.id} (${sandbox.name}), ${sandbox.status}.`);
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
const get = {
|
|
54
|
+
arguments: '<sandbox_id>',
|
|
55
|
+
path: ['cloud', 'sandboxes', 'get'],
|
|
56
|
+
summary: 'Show a sandbox.',
|
|
57
|
+
async run(context, input) {
|
|
58
|
+
context.output.record(await unwrap(await (await context.client()).GET('/v1/sandboxes/{sandbox_id}', sandboxPath(argument(input, 0, 'sandbox_id')))));
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
function lifecycle(action, summary) {
|
|
62
|
+
return {
|
|
63
|
+
arguments: '<sandbox_id>',
|
|
64
|
+
...(action === 'delete' ? { options: YES_OPTION } : {}),
|
|
65
|
+
path: ['cloud', 'sandboxes', action],
|
|
66
|
+
summary,
|
|
67
|
+
async run(context, input) {
|
|
68
|
+
const client = await context.client();
|
|
69
|
+
const id = argument(input, 0, 'sandbox_id');
|
|
70
|
+
if (action === 'delete') {
|
|
71
|
+
await requireConsent(context, flag(input, 'yes'), `Deleting sandbox ${id} deletes its workspace for good.`);
|
|
72
|
+
const result = await unwrap(await client.DELETE('/v1/sandboxes/{sandbox_id}', {
|
|
73
|
+
params: { path: { sandbox_id: id }, header: once() },
|
|
74
|
+
}));
|
|
75
|
+
return context.output.result(result, `Deleted sandbox ${id}.`);
|
|
76
|
+
}
|
|
77
|
+
const request = { params: { path: { sandbox_id: id }, header: once() } };
|
|
78
|
+
const sandbox = await unwrap(action === 'start'
|
|
79
|
+
? await client.POST('/v1/sandboxes/{sandbox_id}/start', request)
|
|
80
|
+
: await client.POST('/v1/sandboxes/{sandbox_id}/pause', request));
|
|
81
|
+
context.output.result(sandbox, `Sandbox ${id} is ${sandbox.status}.`);
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const exec = {
|
|
86
|
+
arguments: '<sandbox_id> <command...>',
|
|
87
|
+
options: {
|
|
88
|
+
cwd: { description: 'The working directory (default /workspace).', type: 'string' },
|
|
89
|
+
timeout: {
|
|
90
|
+
description: 'Milliseconds to wait, up to 120000 (default 60000).',
|
|
91
|
+
type: 'string',
|
|
92
|
+
valueName: 'MS',
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
path: ['cloud', 'sandboxes', 'exec'],
|
|
96
|
+
summary: 'Run a shell command and print its output; exits with its exit code. Put -- before a command with options.',
|
|
97
|
+
async run(context, input) {
|
|
98
|
+
const cwd = stringOption(input, 'cwd');
|
|
99
|
+
const timeout = integerOption(input, 'timeout');
|
|
100
|
+
const result = await unwrap(await (await context.client()).POST('/v1/sandboxes/{sandbox_id}/processes', {
|
|
101
|
+
...sandboxPath(argument(input, 0, 'sandbox_id')),
|
|
102
|
+
body: {
|
|
103
|
+
command: input.positionals.slice(1).join(' '),
|
|
104
|
+
...(cwd === undefined ? {} : { cwd }),
|
|
105
|
+
...(timeout === undefined ? {} : { timeout_ms: timeout }),
|
|
106
|
+
},
|
|
107
|
+
}));
|
|
108
|
+
if (context.output.jsonContent) {
|
|
109
|
+
context.output.record(result);
|
|
110
|
+
return result.exit_code;
|
|
111
|
+
}
|
|
112
|
+
context.runtime.writeOutput(result.stdout);
|
|
113
|
+
context.runtime.writeError(result.stderr);
|
|
114
|
+
if (result.stdout_truncated || result.stderr_truncated)
|
|
115
|
+
context.output.note('The output was cut short.');
|
|
116
|
+
return result.exit_code;
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
const ls = {
|
|
120
|
+
arguments: '<sandbox_id> [path]',
|
|
121
|
+
options: {
|
|
122
|
+
depth: { description: 'Levels to list (default 1).', type: 'string', valueName: 'N' },
|
|
123
|
+
},
|
|
124
|
+
path: ['cloud', 'sandboxes', 'ls'],
|
|
125
|
+
summary: 'List a sandbox directory (default /workspace).',
|
|
126
|
+
async run(context, input) {
|
|
127
|
+
const directory = input.positionals[1];
|
|
128
|
+
const depth = integerOption(input, 'depth');
|
|
129
|
+
const result = await unwrap(await (await context.client()).POST('/v1/sandboxes/{sandbox_id}/files/list', {
|
|
130
|
+
...sandboxPath(argument(input, 0, 'sandbox_id')),
|
|
131
|
+
body: {
|
|
132
|
+
...(directory === undefined ? {} : { path: directory }),
|
|
133
|
+
...(depth === undefined ? {} : { depth }),
|
|
134
|
+
},
|
|
135
|
+
}));
|
|
136
|
+
context.output.list(result, [
|
|
137
|
+
{
|
|
138
|
+
header: 'path',
|
|
139
|
+
value: (entry) => (entry.is_directory ? `${entry.path}/` : entry.path),
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
header: 'size',
|
|
143
|
+
value: (entry) => (entry.is_directory ? null : formatBytes(entry.size)),
|
|
144
|
+
},
|
|
145
|
+
{ header: 'modified', value: (entry) => entry.modified_at },
|
|
146
|
+
]);
|
|
147
|
+
if (result.truncated)
|
|
148
|
+
context.output.note('The listing was cut short.');
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
const cat = {
|
|
152
|
+
arguments: '<sandbox_id> <path>',
|
|
153
|
+
path: ['cloud', 'sandboxes', 'cat'],
|
|
154
|
+
summary: 'Print a UTF-8 sandbox file of up to 1 MiB.',
|
|
155
|
+
async run(context, input) {
|
|
156
|
+
const result = await unwrap(await (await context.client()).POST('/v1/sandboxes/{sandbox_id}/files/read', {
|
|
157
|
+
...sandboxPath(argument(input, 0, 'sandbox_id')),
|
|
158
|
+
body: { path: argument(input, 1, 'path') },
|
|
159
|
+
}));
|
|
160
|
+
if (context.output.jsonContent)
|
|
161
|
+
return context.output.record(result);
|
|
162
|
+
context.runtime.writeOutput(result.content);
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
const write = {
|
|
166
|
+
arguments: '<sandbox_id> <path>',
|
|
167
|
+
options: {
|
|
168
|
+
from: {
|
|
169
|
+
description: 'Read the content from this local file instead of stdin.',
|
|
170
|
+
type: 'string',
|
|
171
|
+
valueName: 'PATH',
|
|
172
|
+
},
|
|
173
|
+
parents: { description: 'Create missing directories.', short: 'p', type: 'boolean' },
|
|
174
|
+
},
|
|
175
|
+
path: ['cloud', 'sandboxes', 'write'],
|
|
176
|
+
summary: 'Write a UTF-8 sandbox file of up to 1 MiB from stdin or --from.',
|
|
177
|
+
async run(context, input) {
|
|
178
|
+
const from = stringOption(input, 'from');
|
|
179
|
+
const content = from === undefined ? await context.runtime.readStdin() : await readFile(from, 'utf8');
|
|
180
|
+
const result = await unwrap(await (await context.client()).POST('/v1/sandboxes/{sandbox_id}/files/write', {
|
|
181
|
+
...sandboxPath(argument(input, 0, 'sandbox_id')),
|
|
182
|
+
body: {
|
|
183
|
+
content,
|
|
184
|
+
create_directories: flag(input, 'parents'),
|
|
185
|
+
path: argument(input, 1, 'path'),
|
|
186
|
+
},
|
|
187
|
+
}));
|
|
188
|
+
context.output.result(result, `Wrote ${formatBytes(result.bytes_written)} to ${result.path}.`);
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
const rm = {
|
|
192
|
+
arguments: '<sandbox_id> <path>',
|
|
193
|
+
options: YES_OPTION,
|
|
194
|
+
path: ['cloud', 'sandboxes', 'rm'],
|
|
195
|
+
summary: 'Delete a sandbox file.',
|
|
196
|
+
async run(context, input) {
|
|
197
|
+
const path = argument(input, 1, 'path');
|
|
198
|
+
await requireConsent(context, flag(input, 'yes'), `Deleting ${path} can't be undone.`);
|
|
199
|
+
const result = await unwrap(await (await context.client()).POST('/v1/sandboxes/{sandbox_id}/files/delete', {
|
|
200
|
+
...sandboxPath(argument(input, 0, 'sandbox_id')),
|
|
201
|
+
body: { path },
|
|
202
|
+
}));
|
|
203
|
+
context.output.result(result, `Deleted ${path}.`);
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
const importFiles = {
|
|
207
|
+
arguments: '<sandbox_id> <file_id...>',
|
|
208
|
+
options: {
|
|
209
|
+
dir: {
|
|
210
|
+
description: 'The sandbox directory to copy into (default /workspace).',
|
|
211
|
+
type: 'string',
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
path: ['cloud', 'sandboxes', 'import'],
|
|
215
|
+
summary: 'Copy project files into a sandbox.',
|
|
216
|
+
async run(context, input) {
|
|
217
|
+
const directory = stringOption(input, 'dir');
|
|
218
|
+
const result = await unwrap(await (await context.client()).POST('/v1/sandboxes/{sandbox_id}/files/import', {
|
|
219
|
+
...sandboxPath(argument(input, 0, 'sandbox_id')),
|
|
220
|
+
body: {
|
|
221
|
+
file_ids: input.positionals.slice(1),
|
|
222
|
+
...(directory === undefined ? {} : { directory }),
|
|
223
|
+
},
|
|
224
|
+
}));
|
|
225
|
+
context.output.list(result, [
|
|
226
|
+
{ header: 'file', value: (entry) => entry.path },
|
|
227
|
+
{ header: 'sandbox path', value: (entry) => entry.sandbox_path },
|
|
228
|
+
{ header: 'size', value: (entry) => formatBytes(entry.size_bytes) },
|
|
229
|
+
]);
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
const exportFile = {
|
|
233
|
+
arguments: '<sandbox_id> <sandbox_path> <file_path>',
|
|
234
|
+
options: {
|
|
235
|
+
overwrite: { description: 'Replace a project file at file_path.', type: 'boolean' },
|
|
236
|
+
},
|
|
237
|
+
path: ['cloud', 'sandboxes', 'export'],
|
|
238
|
+
summary: 'Save a sandbox file as a project file.',
|
|
239
|
+
async run(context, input) {
|
|
240
|
+
const file = await unwrap(await (await context.client()).POST('/v1/sandboxes/{sandbox_id}/files/export', {
|
|
241
|
+
...sandboxPath(argument(input, 0, 'sandbox_id')),
|
|
242
|
+
body: {
|
|
243
|
+
file_path: argument(input, 2, 'file_path'),
|
|
244
|
+
overwrite: flag(input, 'overwrite'),
|
|
245
|
+
path: argument(input, 1, 'sandbox_path'),
|
|
246
|
+
},
|
|
247
|
+
}));
|
|
248
|
+
context.output.result(file, `Saved ${file.path} (${file.id}).`);
|
|
249
|
+
},
|
|
250
|
+
};
|
|
251
|
+
export const sandboxCommands = [
|
|
252
|
+
list,
|
|
253
|
+
create,
|
|
254
|
+
get,
|
|
255
|
+
lifecycle('start', 'Start or resume a sandbox.'),
|
|
256
|
+
lifecycle('pause', 'Pause a sandbox, keeping its workspace.'),
|
|
257
|
+
lifecycle('delete', 'Delete a sandbox and its workspace.'),
|
|
258
|
+
exec,
|
|
259
|
+
ls,
|
|
260
|
+
cat,
|
|
261
|
+
write,
|
|
262
|
+
rm,
|
|
263
|
+
importFiles,
|
|
264
|
+
exportFile,
|
|
265
|
+
];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../../../../src/cli/cloud/commands/secrets.ts"],"names":[],"mappings":"AAGA,OAAO,EAUH,KAAK,OAAO,EAGf,MAAM,eAAe,CAAC;AA8IvB,eAAO,MAAM,cAAc,EAAE,SAAS,OAAO,EAAwC,CAAC"}
|