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,110 @@
|
|
|
1
|
+
// `cloud secrets`: credentials the project's agents use without ever seeing them.
|
|
2
|
+
import { unwrap } from '@dexto/cloud-client';
|
|
3
|
+
import { argument, flag, listOption, PAGE_OPTIONS, pageQuery, readValue, requireConsent, stringOption, YES_OPTION, } from '../command.js';
|
|
4
|
+
const COLUMNS = [
|
|
5
|
+
{ header: 'id', value: (secret) => secret.id },
|
|
6
|
+
{ header: 'name', value: (secret) => secret.name },
|
|
7
|
+
{ header: 'hosts', value: (secret) => secret.hosts.join(',') },
|
|
8
|
+
{ header: 'hint', value: (secret) => secret.hint },
|
|
9
|
+
{ header: 'last used', value: (secret) => secret.last_used_at },
|
|
10
|
+
];
|
|
11
|
+
const PLACEMENT_OPTIONS = {
|
|
12
|
+
header: {
|
|
13
|
+
description: 'Send the value in this header instead of Authorization: Bearer.',
|
|
14
|
+
type: 'string',
|
|
15
|
+
valueName: 'NAME',
|
|
16
|
+
},
|
|
17
|
+
host: {
|
|
18
|
+
description: 'A public hostname the value may be sent to; repeat for more.',
|
|
19
|
+
multiple: true,
|
|
20
|
+
type: 'string',
|
|
21
|
+
},
|
|
22
|
+
prefix: { description: "Text before the value in --header, such as 'Token '.", type: 'string' },
|
|
23
|
+
};
|
|
24
|
+
const list = {
|
|
25
|
+
options: PAGE_OPTIONS,
|
|
26
|
+
path: ['cloud', 'secrets', 'list'],
|
|
27
|
+
summary: "List the project's secrets. Values are never shown.",
|
|
28
|
+
async run(context, input) {
|
|
29
|
+
const page = await unwrap(await (await context.client()).GET('/v1/secrets', { params: { query: pageQuery(input) } }));
|
|
30
|
+
context.output.list(page, COLUMNS);
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
const get = {
|
|
34
|
+
arguments: '<secret_id>',
|
|
35
|
+
path: ['cloud', 'secrets', 'get'],
|
|
36
|
+
summary: 'Show a secret, without its value.',
|
|
37
|
+
async run(context, input) {
|
|
38
|
+
context.output.record(await unwrap(await (await context.client()).GET('/v1/secrets/{secret_id}', {
|
|
39
|
+
params: { path: { secret_id: argument(input, 0, 'secret_id') } },
|
|
40
|
+
})));
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
const create = {
|
|
44
|
+
arguments: '<name>',
|
|
45
|
+
options: PLACEMENT_OPTIONS,
|
|
46
|
+
path: ['cloud', 'secrets', 'create'],
|
|
47
|
+
summary: 'Create a secret. Type the value when asked, or pipe it on stdin; it is never an argument.',
|
|
48
|
+
async run(context, input) {
|
|
49
|
+
const value = await readValue(context, 'Value: ', true);
|
|
50
|
+
const secret = await unwrap(await (await context.client()).POST('/v1/secrets', {
|
|
51
|
+
body: {
|
|
52
|
+
hosts: listOption(input, 'host'),
|
|
53
|
+
name: argument(input, 0, 'name'),
|
|
54
|
+
placement: placement(input) ?? { type: 'bearer' },
|
|
55
|
+
value,
|
|
56
|
+
},
|
|
57
|
+
}));
|
|
58
|
+
context.output.result(secret, `Created secret ${secret.id} (${secret.name}).`);
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
const update = {
|
|
62
|
+
arguments: '<secret_id>',
|
|
63
|
+
options: {
|
|
64
|
+
...PLACEMENT_OPTIONS,
|
|
65
|
+
value: {
|
|
66
|
+
description: 'Replace the value: type it when asked, or pipe it.',
|
|
67
|
+
type: 'boolean',
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
path: ['cloud', 'secrets', 'update'],
|
|
71
|
+
summary: "Change a secret's hosts, placement or value.",
|
|
72
|
+
async run(context, input) {
|
|
73
|
+
const hosts = listOption(input, 'host');
|
|
74
|
+
const newPlacement = placement(input);
|
|
75
|
+
const value = flag(input, 'value')
|
|
76
|
+
? await readValue(context, 'New value: ', true)
|
|
77
|
+
: undefined;
|
|
78
|
+
const secret = await unwrap(await (await context.client()).PATCH('/v1/secrets/{secret_id}', {
|
|
79
|
+
params: { path: { secret_id: argument(input, 0, 'secret_id') } },
|
|
80
|
+
body: {
|
|
81
|
+
...(hosts.length === 0 ? {} : { hosts }),
|
|
82
|
+
...(newPlacement === null ? {} : { placement: newPlacement }),
|
|
83
|
+
...(value === undefined ? {} : { value }),
|
|
84
|
+
},
|
|
85
|
+
}));
|
|
86
|
+
context.output.result(secret, `Updated secret ${secret.id}.`);
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
const remove = {
|
|
90
|
+
arguments: '<secret_id>',
|
|
91
|
+
options: YES_OPTION,
|
|
92
|
+
path: ['cloud', 'secrets', 'delete'],
|
|
93
|
+
summary: 'Delete a secret. Refused while an active agent uses it.',
|
|
94
|
+
async run(context, input) {
|
|
95
|
+
const id = argument(input, 0, 'secret_id');
|
|
96
|
+
await requireConsent(context, flag(input, 'yes'), `Deleting secret ${id} can't be undone.`);
|
|
97
|
+
const result = await unwrap(await (await context.client()).DELETE('/v1/secrets/{secret_id}', {
|
|
98
|
+
params: { path: { secret_id: id } },
|
|
99
|
+
}));
|
|
100
|
+
context.output.result(result, `Deleted secret ${id}.`);
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
function placement(input) {
|
|
104
|
+
const header = stringOption(input, 'header');
|
|
105
|
+
if (header === undefined)
|
|
106
|
+
return null;
|
|
107
|
+
const prefix = stringOption(input, 'prefix');
|
|
108
|
+
return { name: header, type: 'header', ...(prefix === undefined ? {} : { prefix }) };
|
|
109
|
+
}
|
|
110
|
+
export const secretCommands = [list, get, create, update, remove];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../../../src/cli/cloud/commands/skills.ts"],"names":[],"mappings":"AAQA,OAAO,EAOH,KAAK,OAAO,EAEf,MAAM,eAAe,CAAC;AA0PvB,eAAO,MAAM,aAAa,EAAE,SAAS,OAAO,EAAW,CAAC"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
// `skills push`: packs a local Skill folder and creates or updates it in the person's library.
|
|
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, flag, stringOption, UsageError, YES_OPTION, } from '../command.js';
|
|
7
|
+
import { tarArchive } from '../tar.js';
|
|
8
|
+
import { sendBytes } from '../transfer.js';
|
|
9
|
+
import { formatBytes } from './files.js';
|
|
10
|
+
import { agreeToCall, listWorkspaceTools, queryWorkspaceTool, toolCallLevel } from './workspace.js';
|
|
11
|
+
/** The most files a Skill bundle takes. */
|
|
12
|
+
const MAX_FILES = 200;
|
|
13
|
+
const SLUG = /^[a-z0-9._-]{1,80}$/u;
|
|
14
|
+
const PreparedSchema = z.object({
|
|
15
|
+
headers: z.record(z.string(), z.string()),
|
|
16
|
+
method: z.string(),
|
|
17
|
+
path: z.string(),
|
|
18
|
+
url: z.string(),
|
|
19
|
+
});
|
|
20
|
+
const SearchSchema = z.object({
|
|
21
|
+
skills: z.array(z.object({
|
|
22
|
+
slug: z.string(),
|
|
23
|
+
source: z.string(),
|
|
24
|
+
visibility: z.enum(['organization', 'private', 'shared']).nullable().default(null),
|
|
25
|
+
})),
|
|
26
|
+
});
|
|
27
|
+
const ImportedSchema = z.object({
|
|
28
|
+
location: z.object({ skillId: z.string() }),
|
|
29
|
+
slug: z.string(),
|
|
30
|
+
title: z.string(),
|
|
31
|
+
});
|
|
32
|
+
const push = {
|
|
33
|
+
arguments: '<folder>',
|
|
34
|
+
options: {
|
|
35
|
+
description: {
|
|
36
|
+
description: "What the Skill does (default: description in SKILL.md's header).",
|
|
37
|
+
type: 'string',
|
|
38
|
+
},
|
|
39
|
+
slug: {
|
|
40
|
+
description: "The Skill's slug (default: slug or name in SKILL.md's header, else the folder's name).",
|
|
41
|
+
type: 'string',
|
|
42
|
+
},
|
|
43
|
+
title: {
|
|
44
|
+
description: "The Skill's title (default: title in SKILL.md's header, else from the slug).",
|
|
45
|
+
type: 'string',
|
|
46
|
+
},
|
|
47
|
+
update: {
|
|
48
|
+
description: 'Update your Skill with this slug (default: update it if you have one, else create it).',
|
|
49
|
+
type: 'boolean',
|
|
50
|
+
},
|
|
51
|
+
...YES_OPTION,
|
|
52
|
+
},
|
|
53
|
+
path: ['skills', 'push'],
|
|
54
|
+
summary: 'Pack a local Skill folder (SKILL.md at its root, dotfiles left out) and create or update it in your library.',
|
|
55
|
+
async run(context, input) {
|
|
56
|
+
const folder = argument(input, 0, 'folder');
|
|
57
|
+
const files = await readSkillFolder(folder);
|
|
58
|
+
const header = skillHeader(new globalThis.TextDecoder().decode(files[0]?.bytes));
|
|
59
|
+
const named = header.name !== undefined && SLUG.test(header.name) ? header.name : null;
|
|
60
|
+
const slug = stringOption(input, 'slug') ??
|
|
61
|
+
header.slug ??
|
|
62
|
+
named ??
|
|
63
|
+
path.basename(path.resolve(folder));
|
|
64
|
+
if (!SLUG.test(slug))
|
|
65
|
+
throw new UsageError(`${slug} can't be a Skill's slug: use up to 80 lowercase letters, digits, dots, dashes and underscores. Pass --slug.`);
|
|
66
|
+
const title = stringOption(input, 'title') ??
|
|
67
|
+
header.title ??
|
|
68
|
+
(named === null ? header.name : undefined) ??
|
|
69
|
+
titleFromSlug(slug);
|
|
70
|
+
const description = stringOption(input, 'description') ?? header.description;
|
|
71
|
+
if (description === undefined)
|
|
72
|
+
throw new UsageError("SKILL.md's header has no description. Add one there, or pass --description.");
|
|
73
|
+
const mode = flag(input, 'update') || (await ownsSkill(context, slug)) ? 'update' : 'create';
|
|
74
|
+
const metadata = { description, mode, slug, title };
|
|
75
|
+
// Ask before anything is sent: the import is what changes the library.
|
|
76
|
+
const tool = (await listWorkspaceTools(context)).find((each) => each.name === 'dexto_skill_bundle_import');
|
|
77
|
+
const agreed = tool === undefined
|
|
78
|
+
? {}
|
|
79
|
+
: await agreeToCall(context, {
|
|
80
|
+
level: toolCallLevel(tool, metadata),
|
|
81
|
+
schema: tool.inputSchema,
|
|
82
|
+
title: `${mode === 'create' ? 'Create' : 'Update'} the Skill ${slug}`,
|
|
83
|
+
}, flag(input, 'yes'));
|
|
84
|
+
const archive = tarArchive(files);
|
|
85
|
+
const prepared = PreparedSchema.safeParse(await queryWorkspaceTool(context, 'dexto_upload_prepare', {
|
|
86
|
+
filename: `${slug}.tar`,
|
|
87
|
+
mimeType: 'application/x-tar',
|
|
88
|
+
purpose: 'skill-bundle',
|
|
89
|
+
sha256: createHash('sha256').update(archive).digest('hex'),
|
|
90
|
+
sizeBytes: archive.length,
|
|
91
|
+
}));
|
|
92
|
+
if (!prepared.success)
|
|
93
|
+
throw new CommandFailure('failed', "Dexto didn't say where to upload the bundle.", null);
|
|
94
|
+
const { headers, method, url } = prepared.data;
|
|
95
|
+
await sendBytes(context, { headers, method, url }, new globalThis.Blob([archive]));
|
|
96
|
+
const imported = await queryWorkspaceTool(context, 'dexto_skill_bundle_import', {
|
|
97
|
+
...metadata,
|
|
98
|
+
uploadPath: prepared.data.path,
|
|
99
|
+
...agreed,
|
|
100
|
+
});
|
|
101
|
+
const shown = ImportedSchema.safeParse(imported);
|
|
102
|
+
context.output.result(imported, shown.success
|
|
103
|
+
? `${mode === 'create' ? 'Created' : 'Updated'} ${shown.data.title} (${shown.data.slug}, ${files.length} file${files.length === 1 ? '' : 's'}, ${formatBytes(archive.length)}): skill ${shown.data.location.skillId}.`
|
|
104
|
+
: JSON.stringify(imported, null, 2));
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* The folder's files, SKILL.md first, as the bundle takes them: relative paths, the executable bit
|
|
109
|
+
* kept. Names starting with a dot (`.git`, the reserved `.dexto`) and links are left out.
|
|
110
|
+
*/
|
|
111
|
+
async function readSkillFolder(folder) {
|
|
112
|
+
if ((await stat(folder).catch(() => null))?.isDirectory() !== true)
|
|
113
|
+
throw new UsageError(`${folder} is not a folder.`);
|
|
114
|
+
const found = [];
|
|
115
|
+
const visit = async (relative) => {
|
|
116
|
+
const entries = await readdir(path.join(folder, relative), { withFileTypes: true });
|
|
117
|
+
for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
|
|
118
|
+
if (entry.name.startsWith('.'))
|
|
119
|
+
continue;
|
|
120
|
+
const child = relative === '' ? entry.name : `${relative}/${entry.name}`;
|
|
121
|
+
if (entry.isDirectory())
|
|
122
|
+
await visit(child);
|
|
123
|
+
else if (entry.isFile())
|
|
124
|
+
found.push({
|
|
125
|
+
executable: ((await stat(path.join(folder, child))).mode & 0o111) !== 0,
|
|
126
|
+
path: child,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
await visit('');
|
|
131
|
+
if (!found.some((file) => file.path === 'SKILL.md'))
|
|
132
|
+
throw new UsageError(`${folder} has no SKILL.md at its root.`);
|
|
133
|
+
if (found.length > MAX_FILES)
|
|
134
|
+
throw new UsageError(`${folder} has ${found.length} files; a Skill takes up to ${MAX_FILES}.`);
|
|
135
|
+
const ordered = [
|
|
136
|
+
...found.filter((file) => file.path === 'SKILL.md'),
|
|
137
|
+
...found.filter((file) => file.path !== 'SKILL.md'),
|
|
138
|
+
];
|
|
139
|
+
return await Promise.all(ordered.map(async (file) => ({
|
|
140
|
+
...file,
|
|
141
|
+
bytes: await readFile(path.join(folder, file.path)),
|
|
142
|
+
})));
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Whether the person has a Skill with this slug they can save over: their own, or their
|
|
146
|
+
* organization's. One someone shared with them is theirs to copy, so a push makes the person's own.
|
|
147
|
+
*/
|
|
148
|
+
async function ownsSkill(context, slug) {
|
|
149
|
+
const found = SearchSchema.safeParse(await queryWorkspaceTool(context, 'dexto_skills_search', {
|
|
150
|
+
limit: 50,
|
|
151
|
+
query: slug,
|
|
152
|
+
source: 'library',
|
|
153
|
+
}));
|
|
154
|
+
return (found.success &&
|
|
155
|
+
found.data.skills.some((skill) => skill.slug === slug &&
|
|
156
|
+
skill.source === 'user' &&
|
|
157
|
+
(skill.visibility === 'private' || skill.visibility === 'organization')));
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* The plain fields of SKILL.md's `---` header: one-line values, quoted or not, and `>` or `|` blocks
|
|
161
|
+
* on the indented lines below.
|
|
162
|
+
*/
|
|
163
|
+
function skillHeader(text) {
|
|
164
|
+
const lines = text.split(/\r?\n/u);
|
|
165
|
+
if (lines[0] !== '---')
|
|
166
|
+
return {};
|
|
167
|
+
const end = lines.indexOf('---', 1);
|
|
168
|
+
const body = lines.slice(1, end === -1 ? 1 : end);
|
|
169
|
+
const fields = {};
|
|
170
|
+
for (const [index, line] of body.entries()) {
|
|
171
|
+
const match = /^(description|name|slug|title):\s*(.*)$/u.exec(line);
|
|
172
|
+
if (match === null)
|
|
173
|
+
continue;
|
|
174
|
+
const [, key = '', raw = ''] = match;
|
|
175
|
+
const value = /^[>|][-+]?$/u.test(raw)
|
|
176
|
+
? blockValue(body.slice(index + 1), raw.startsWith('>') ? ' ' : '\n')
|
|
177
|
+
: unquote(raw.trim());
|
|
178
|
+
if (value.length > 0)
|
|
179
|
+
fields[key] = value;
|
|
180
|
+
}
|
|
181
|
+
return fields;
|
|
182
|
+
}
|
|
183
|
+
/** A `>` or `|` block: the indented lines after its key, joined. */
|
|
184
|
+
function blockValue(lines, separator) {
|
|
185
|
+
const end = lines.findIndex((line) => line.length > 0 && !/^\s/u.test(line));
|
|
186
|
+
return (end === -1 ? lines : lines.slice(0, end))
|
|
187
|
+
.map((line) => line.trim())
|
|
188
|
+
.join(separator)
|
|
189
|
+
.trim();
|
|
190
|
+
}
|
|
191
|
+
function unquote(value) {
|
|
192
|
+
return /^(["']).*\1$/u.test(value) ? value.slice(1, -1) : value;
|
|
193
|
+
}
|
|
194
|
+
/** `llm-wiki` is `Llm Wiki`. */
|
|
195
|
+
function titleFromSlug(slug) {
|
|
196
|
+
return slug
|
|
197
|
+
.split(/[-_.]+/u)
|
|
198
|
+
.filter((part) => part.length > 0)
|
|
199
|
+
.map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`)
|
|
200
|
+
.join(' ');
|
|
201
|
+
}
|
|
202
|
+
export const skillCommands = [push];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../../../src/cli/cloud/commands/web.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AA+D5D,eAAO,MAAM,WAAW,EAAE,SAAS,OAAO,EAAyB,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// `cloud search` and `cloud fetch`: the web as /v1/search and /v1/fetch serve it.
|
|
2
|
+
import { unwrap } from '@dexto/cloud-client';
|
|
3
|
+
import { integerOption } from '../command.js';
|
|
4
|
+
const search = {
|
|
5
|
+
arguments: '<query...>',
|
|
6
|
+
options: {
|
|
7
|
+
num: { description: 'How many results (default 10).', type: 'string', valueName: 'N' },
|
|
8
|
+
},
|
|
9
|
+
path: ['cloud', 'search'],
|
|
10
|
+
summary: 'Search the web.',
|
|
11
|
+
async run(context, input) {
|
|
12
|
+
const numResults = integerOption(input, 'num');
|
|
13
|
+
const result = await unwrap(await (await context.client()).POST('/v1/search', {
|
|
14
|
+
body: {
|
|
15
|
+
query: input.positionals.join(' '),
|
|
16
|
+
...(numResults === undefined ? {} : { num_results: numResults }),
|
|
17
|
+
},
|
|
18
|
+
}));
|
|
19
|
+
if (context.output.json)
|
|
20
|
+
return context.output.record(result);
|
|
21
|
+
for (const item of result.results)
|
|
22
|
+
context.runtime.writeOutput(`${item.title ?? item.url}\n ${item.url}${item.highlights.length === 0 ? '' : `\n ${item.highlights[0]}`}\n\n`);
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
const fetchPages = {
|
|
26
|
+
arguments: '<url...>',
|
|
27
|
+
options: {
|
|
28
|
+
'max-chars': {
|
|
29
|
+
description: 'Text characters per page, 100 to 100000 (default 20000).',
|
|
30
|
+
type: 'string',
|
|
31
|
+
valueName: 'N',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
path: ['cloud', 'fetch'],
|
|
35
|
+
summary: 'Read up to 10 web pages as text.',
|
|
36
|
+
async run(context, input) {
|
|
37
|
+
const maxCharacters = integerOption(input, 'max-chars');
|
|
38
|
+
const result = await unwrap(await (await context.client()).POST('/v1/fetch', {
|
|
39
|
+
body: {
|
|
40
|
+
urls: [...input.positionals],
|
|
41
|
+
...(maxCharacters === undefined ? {} : { max_characters: maxCharacters }),
|
|
42
|
+
},
|
|
43
|
+
}));
|
|
44
|
+
if (context.output.jsonContent)
|
|
45
|
+
return context.output.record(result);
|
|
46
|
+
for (const page of result.results)
|
|
47
|
+
context.runtime.writeOutput(page.status === 'ok'
|
|
48
|
+
? `# ${page.title ?? page.url}\n${page.url}\n\n${page.text ?? ''}\n\n`
|
|
49
|
+
: `# ${page.url}\nFailed: ${page.error?.code ?? 'error'}\n\n`);
|
|
50
|
+
return result.results.some((page) => page.status === 'error') ? 1 : 0;
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
export const webCommands = [search, fetchPages];
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { type CommandContext } from '../command.js';
|
|
2
|
+
import { type WorkspaceTool } from './workspace.js';
|
|
3
|
+
/** One app or service: how many of its tools the sign-in reaches, and how many App actions it has. */
|
|
4
|
+
export interface WorkspaceApp {
|
|
5
|
+
readonly actions: number;
|
|
6
|
+
readonly id: string;
|
|
7
|
+
readonly kind: string;
|
|
8
|
+
readonly tools: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* One thing an app does: a workspace tool, one action of a tool that is the whole app (such as
|
|
12
|
+
* `dexto_drive`), or an App action run through `dexto_apps_action`.
|
|
13
|
+
*/
|
|
14
|
+
export interface Operation {
|
|
15
|
+
readonly call: {
|
|
16
|
+
readonly kind: 'action';
|
|
17
|
+
readonly toolName: string;
|
|
18
|
+
} | {
|
|
19
|
+
readonly action: string | null;
|
|
20
|
+
/** Each action's own level, where a tool's actions differ (`dexto/action_levels`). */
|
|
21
|
+
readonly actionLevels: Readonly<Record<string, string>>;
|
|
22
|
+
readonly kind: 'tool';
|
|
23
|
+
readonly name: string;
|
|
24
|
+
};
|
|
25
|
+
/** The schema whose `confirm` field says the person agreed: the tool's, or `dexto_apps_action`'s. */
|
|
26
|
+
readonly confirmSchema: unknown;
|
|
27
|
+
readonly description: string;
|
|
28
|
+
readonly inputSchema: unknown;
|
|
29
|
+
readonly level: string;
|
|
30
|
+
readonly name: string;
|
|
31
|
+
readonly title: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The apps the sign-in reaches: those whose manifests provide its tools, and the Apps whose
|
|
35
|
+
* actions it can run. Tools a server lists without a provider stay under `workspace call`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function listWorkspaceApps(context: CommandContext): Promise<WorkspaceApp[]>;
|
|
38
|
+
/** A command the CLI itself adds to an app, such as `drive put`, listed with the app's operations. */
|
|
39
|
+
export interface AppCommand {
|
|
40
|
+
/** Its words after the app's, such as `put`. */
|
|
41
|
+
readonly name: string;
|
|
42
|
+
readonly summary: string;
|
|
43
|
+
readonly usage: string;
|
|
44
|
+
}
|
|
45
|
+
/** Runs `<app> [operation] [action] [--field value…]`; `commands` are the CLI's own for the app. */
|
|
46
|
+
export declare function runWorkspaceApp(context: CommandContext, args: readonly string[], help: boolean, commands: readonly AppCommand[]): Promise<number>;
|
|
47
|
+
/** A Dexto tool and the arguments to call it with, as search names a route's call. */
|
|
48
|
+
export interface ToolCall {
|
|
49
|
+
readonly arguments: Readonly<Record<string, unknown>>;
|
|
50
|
+
readonly tool: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The CLI command that makes a call: `dexto workspace <app> <operation> --field value`, or
|
|
54
|
+
* `workspace call` when no app operation does. A value written `<type>` is left for the caller to
|
|
55
|
+
* fill in. `operationsByApp` keeps each app's operations across calls.
|
|
56
|
+
*/
|
|
57
|
+
export declare function commandForCall(context: CommandContext, tools: readonly WorkspaceTool[], call: ToolCall, operationsByApp: Map<string, Operation[]>): Promise<string>;
|
|
58
|
+
//# sourceMappingURL=workspace-apps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-apps.d.ts","sourceRoot":"","sources":["../../../../src/cli/cloud/commands/workspace-apps.ts"],"names":[],"mappings":"AAKA,OAAO,EAKH,KAAK,cAAc,EACtB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAMH,KAAK,aAAa,EACrB,MAAM,gBAAgB,CAAC;AAExB,sGAAsG;AACtG,MAAM,WAAW,YAAY;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACtB,QAAQ,CAAC,IAAI,EACP;QAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GACtD;QACI,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,sFAAsF;QACtF,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;KACzB,CAAC;IACR,qGAAqG;IACrG,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAqBxF;AAED,sGAAsG;AACtG,MAAM,WAAW,UAAU;IACvB,gDAAgD;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CAC1B;AAED,oGAAoG;AACpG,wBAAsB,eAAe,CACjC,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,SAAS,UAAU,EAAE,GAChC,OAAO,CAAC,MAAM,CAAC,CAwDjB;AA0GD,sFAAsF;AACtF,MAAM,WAAW,QAAQ;IACrB,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAChC,OAAO,EAAE,cAAc,EACvB,KAAK,EAAE,SAAS,aAAa,EAAE,EAC/B,IAAI,EAAE,QAAQ,EACd,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,GAC1C,OAAO,CAAC,MAAM,CAAC,CA4CjB"}
|