@usenaive-sdk/vetta-cli 0.1.0 → 0.3.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 +5 -3
- package/dist/index.js +140 -18
- package/package.json +11 -12
package/README.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# @usenaive-sdk/vetta-cli
|
|
2
2
|
|
|
3
3
|
The `vetta` command line — drive the whole Vetta API from a terminal or a script: agents, sessions,
|
|
4
|
-
computers, skills, files, identities, vaults, comms, deployments, webhooks and
|
|
4
|
+
computers, skills, files, identities, vaults, comms, deployments, webhooks, the monthly plan and
|
|
5
|
+
credits.
|
|
5
6
|
|
|
6
7
|
It is built on [`@usenaive-sdk/vetta`](https://www.npmjs.com/package/@usenaive-sdk/vetta), the same typed
|
|
7
8
|
client the dashboard uses, so the CLI and the API never drift apart.
|
|
@@ -17,6 +18,7 @@ npm i -g @usenaive-sdk/vetta-cli
|
|
|
17
18
|
```bash
|
|
18
19
|
vetta login --api-key sk_… # or: vetta login --email … --password …
|
|
19
20
|
vetta whoami
|
|
21
|
+
vetta plan show # an org with no plan is refused everywhere else
|
|
20
22
|
```
|
|
21
23
|
|
|
22
24
|
Credentials are stored on a named profile, so several organizations can be driven from one machine
|
|
@@ -29,8 +31,8 @@ vetta <group> <command> [flags]
|
|
|
29
31
|
```
|
|
30
32
|
|
|
31
33
|
Groups: `agent` `audit` `auth` `computer` `connections` `credits` `deploy` `domain` `email` `file`
|
|
32
|
-
`identity` `keys` `login` `logout` `models` `org` `phone` `run` `session` `skill` `vault`
|
|
33
|
-
`whoami`.
|
|
34
|
+
`identity` `keys` `login` `logout` `models` `org` `phone` `plan` `run` `session` `skill` `vault`
|
|
35
|
+
`webhook` `whoami`.
|
|
34
36
|
|
|
35
37
|
`vetta <group> --help` lists a group's commands.
|
|
36
38
|
|
package/dist/index.js
CHANGED
|
@@ -23448,6 +23448,10 @@ var SubscriptionSchema = external_exports.object({
|
|
|
23448
23448
|
cancel_at_period_end: external_exports.boolean(),
|
|
23449
23449
|
action_url: external_exports.string().nullable()
|
|
23450
23450
|
});
|
|
23451
|
+
var BillingPortalSessionSchema = external_exports.object({
|
|
23452
|
+
object: external_exports.literal("billing_portal_session"),
|
|
23453
|
+
action_url: external_exports.string()
|
|
23454
|
+
});
|
|
23451
23455
|
var AcknowledgedSchema = external_exports.object({
|
|
23452
23456
|
object: external_exports.string(),
|
|
23453
23457
|
delivery: external_exports.enum(["sent", "undeliverable"])
|
|
@@ -23455,7 +23459,12 @@ var AcknowledgedSchema = external_exports.object({
|
|
|
23455
23459
|
var auth = (config2) => ({
|
|
23456
23460
|
/** Who this credential is. No scope, no org id needed — that is the whole point (§20.1). */
|
|
23457
23461
|
me: () => request(config2, IdentitySchema22, { method: "GET", path: "/v1/me" }),
|
|
23458
|
-
/**
|
|
23462
|
+
/**
|
|
23463
|
+
* Sign in, finish an external sign-in, or re-scope the session already held to another
|
|
23464
|
+
* organization (§20.4). `provider_token` is the access token an external provider sign-in came
|
|
23465
|
+
* back with; the control plane re-verifies it against the provider and refuses an address the
|
|
23466
|
+
* provider has not proved.
|
|
23467
|
+
*/
|
|
23459
23468
|
session: (body) => request(config2, AuthSessionSchema, { method: "POST", path: "/v1/auth/session", body }),
|
|
23460
23469
|
register: (body) => request(
|
|
23461
23470
|
config2,
|
|
@@ -23531,7 +23540,17 @@ var credits = (config2) => ({
|
|
|
23531
23540
|
* Stops the plan at the end of the period already paid for — never immediately. The state
|
|
23532
23541
|
* follows the provider's callback, so the answer reports the request, not a completed change.
|
|
23533
23542
|
*/
|
|
23534
|
-
cancelSubscription: () => request(config2, SubscriptionSchema, { method: "DELETE", path: "/v1/credits/subscription" })
|
|
23543
|
+
cancelSubscription: () => request(config2, SubscriptionSchema, { method: "DELETE", path: "/v1/credits/subscription" }),
|
|
23544
|
+
/**
|
|
23545
|
+
* A link to the hosted account page: change the card, read the invoices, cancel. Opens nothing
|
|
23546
|
+
* and changes nothing — an organization that never subscribed has no account, and this answers
|
|
23547
|
+
* `404 not_found` rather than an empty page.
|
|
23548
|
+
*/
|
|
23549
|
+
billingPortal: () => request(config2, BillingPortalSessionSchema, {
|
|
23550
|
+
method: "POST",
|
|
23551
|
+
path: "/v1/credits/billing_portal",
|
|
23552
|
+
body: {}
|
|
23553
|
+
})
|
|
23535
23554
|
});
|
|
23536
23555
|
var auditLogs = (config2) => ({
|
|
23537
23556
|
list: (query = {}) => request(config2, page(AuditEntrySchema2), { method: "GET", path: "/v1/audit_logs", query })
|
|
@@ -23678,14 +23697,23 @@ var phones = (config2) => ({
|
|
|
23678
23697
|
body
|
|
23679
23698
|
})
|
|
23680
23699
|
});
|
|
23681
|
-
var CONNECTORS = ["email", "chat", "tracker", "crm", "docs"];
|
|
23682
23700
|
var CONNECTION_AUTHS = ["managed_oauth", "oauth", "api_key"];
|
|
23701
|
+
var ConnectionFieldSchema = external_exports.object({
|
|
23702
|
+
name: external_exports.string(),
|
|
23703
|
+
label: external_exports.string(),
|
|
23704
|
+
description: external_exports.string(),
|
|
23705
|
+
required: external_exports.boolean()
|
|
23706
|
+
});
|
|
23683
23707
|
var AuthConfigSchema = external_exports.object({
|
|
23684
23708
|
object: external_exports.literal("auth_config"),
|
|
23685
23709
|
id: external_exports.string(),
|
|
23686
23710
|
connector: external_exports.string(),
|
|
23687
23711
|
auth: external_exports.enum(CONNECTION_AUTHS),
|
|
23688
23712
|
scopes: external_exports.array(external_exports.string()),
|
|
23713
|
+
/** The operations a connection made from this config may call. Pinned at creation. */
|
|
23714
|
+
tools: external_exports.array(external_exports.string()),
|
|
23715
|
+
/** Supply these to `connect`, or the hosted page asks the person for them instead. */
|
|
23716
|
+
connect_fields: external_exports.array(ConnectionFieldSchema),
|
|
23689
23717
|
created_at: external_exports.string()
|
|
23690
23718
|
});
|
|
23691
23719
|
var ConnectionSchema = external_exports.object({
|
|
@@ -23702,7 +23730,38 @@ var ConnectionSchema = external_exports.object({
|
|
|
23702
23730
|
last_refreshed_at: external_exports.string().nullable(),
|
|
23703
23731
|
created_at: external_exports.string()
|
|
23704
23732
|
});
|
|
23733
|
+
var ConnectionAppSchema = external_exports.object({
|
|
23734
|
+
object: external_exports.literal("connection_app"),
|
|
23735
|
+
slug: external_exports.string(),
|
|
23736
|
+
name: external_exports.string(),
|
|
23737
|
+
description: external_exports.string(),
|
|
23738
|
+
categories: external_exports.array(external_exports.string()),
|
|
23739
|
+
/** Which setup paths work: `managed_oauth` is one call, `oauth` needs your own app first. */
|
|
23740
|
+
auth: external_exports.array(external_exports.enum(CONNECTION_AUTHS)),
|
|
23741
|
+
tool_count: external_exports.number()
|
|
23742
|
+
});
|
|
23743
|
+
var ConnectionAppDetailSchema = ConnectionAppSchema.extend({
|
|
23744
|
+
/** The operations pinned when `tools` is not given to `createAuthConfig`. */
|
|
23745
|
+
default_tools: external_exports.array(external_exports.string()),
|
|
23746
|
+
connect_fields: external_exports.array(ConnectionFieldSchema)
|
|
23747
|
+
});
|
|
23748
|
+
var ConnectionAppPage = external_exports.object({
|
|
23749
|
+
object: external_exports.literal("list"),
|
|
23750
|
+
data: external_exports.array(ConnectionAppSchema),
|
|
23751
|
+
has_more: external_exports.boolean(),
|
|
23752
|
+
next_cursor: external_exports.string().nullable()
|
|
23753
|
+
});
|
|
23705
23754
|
var connections = (config2) => ({
|
|
23755
|
+
/**
|
|
23756
|
+
* Search the app catalogue — the first call in the flow, and the one that replaced the enum.
|
|
23757
|
+
* `search` matches an app's name, id or description; the reply's `slug` is what `connector` takes.
|
|
23758
|
+
*/
|
|
23759
|
+
listApps: (query = {}) => request(config2, ConnectionAppPage, { method: "GET", path: "/v1/connections/apps", query }),
|
|
23760
|
+
/** One app, whole: auth methods, the operations pinned by default, what `connect` will ask for. */
|
|
23761
|
+
getApp: (slug) => request(config2, ConnectionAppDetailSchema, {
|
|
23762
|
+
method: "GET",
|
|
23763
|
+
path: `/v1/connections/apps/${slug}`
|
|
23764
|
+
}),
|
|
23706
23765
|
/** Org-level: *how* a connector authenticates. Shared across every identity that connects it. */
|
|
23707
23766
|
createAuthConfig: (body) => request(config2, AuthConfigSchema, {
|
|
23708
23767
|
method: "POST",
|
|
@@ -24638,23 +24697,46 @@ var computer = {
|
|
|
24638
24697
|
// src/commands/connections.ts
|
|
24639
24698
|
function authConfigBody(args) {
|
|
24640
24699
|
const connector = args.need("connector");
|
|
24641
|
-
if (!CONNECTORS.includes(connector)) {
|
|
24642
|
-
throw new UsageError(`--connector must be one of: ${CONNECTORS.join(", ")}`);
|
|
24643
|
-
}
|
|
24644
24700
|
const auth3 = args.str("auth");
|
|
24645
24701
|
if (auth3 !== void 0 && !CONNECTION_AUTHS.includes(auth3)) {
|
|
24646
24702
|
throw new UsageError(`--auth must be one of: ${CONNECTION_AUTHS.join(", ")}`);
|
|
24647
24703
|
}
|
|
24648
24704
|
const clientId = args.str("client-id");
|
|
24649
24705
|
const scopes2 = args.list("scope");
|
|
24706
|
+
const tools2 = args.list("tool");
|
|
24650
24707
|
return {
|
|
24651
24708
|
connector,
|
|
24652
24709
|
...auth3 === void 0 ? {} : { auth: auth3 },
|
|
24653
24710
|
...scopes2.length === 0 ? {} : { scopes: scopes2 },
|
|
24711
|
+
...tools2.length === 0 ? {} : { tools: tools2 },
|
|
24654
24712
|
...clientId === void 0 ? {} : { client_id: clientId }
|
|
24655
24713
|
};
|
|
24656
24714
|
}
|
|
24715
|
+
function fieldsFrom(args) {
|
|
24716
|
+
const out = {};
|
|
24717
|
+
for (const pair of args.list("field")) {
|
|
24718
|
+
const at = pair.indexOf("=");
|
|
24719
|
+
if (at < 1) throw new UsageError("--field takes name=value, e.g. --field subdomain=acme");
|
|
24720
|
+
out[pair.slice(0, at)] = pair.slice(at + 1);
|
|
24721
|
+
}
|
|
24722
|
+
return out;
|
|
24723
|
+
}
|
|
24657
24724
|
var connections2 = {
|
|
24725
|
+
/**
|
|
24726
|
+
* Search the catalogue. This is where a setup starts, and it is the command the five-word enum
|
|
24727
|
+
* made impossible: `--search helpdesk` finds what "triage my support tickets" needs.
|
|
24728
|
+
*/
|
|
24729
|
+
apps: async ({ client, args }) => ({
|
|
24730
|
+
out: await client.connections.listApps({
|
|
24731
|
+
search: args.str("search"),
|
|
24732
|
+
limit: args.int("limit"),
|
|
24733
|
+
after: args.str("after")
|
|
24734
|
+
})
|
|
24735
|
+
}),
|
|
24736
|
+
/** One app whole: the auth methods that work, the operations pinned by default, what `connect` asks for. */
|
|
24737
|
+
app: async ({ client, args }) => ({
|
|
24738
|
+
out: await client.connections.getApp(args.str("app") ?? args.at(0, "app-id"))
|
|
24739
|
+
}),
|
|
24658
24740
|
list: async ({ client, args }) => {
|
|
24659
24741
|
const identity3 = args.str("identity");
|
|
24660
24742
|
return { out: await client.connections.list(identity3 === void 0 ? {} : { identity: identity3 }) };
|
|
@@ -24673,12 +24755,16 @@ var connections2 = {
|
|
|
24673
24755
|
})
|
|
24674
24756
|
};
|
|
24675
24757
|
var passport = {
|
|
24676
|
-
connect: async ({ client, args }) =>
|
|
24677
|
-
|
|
24678
|
-
|
|
24679
|
-
|
|
24680
|
-
|
|
24681
|
-
|
|
24758
|
+
connect: async ({ client, args }) => {
|
|
24759
|
+
const fields2 = fieldsFrom(args);
|
|
24760
|
+
return {
|
|
24761
|
+
out: await client.connections.connect({
|
|
24762
|
+
auth_config_id: args.need("auth-config"),
|
|
24763
|
+
identity: args.str("identity") ?? args.at(0, "identity"),
|
|
24764
|
+
...Object.keys(fields2).length === 0 ? {} : { fields: fields2 }
|
|
24765
|
+
})
|
|
24766
|
+
};
|
|
24767
|
+
},
|
|
24682
24768
|
/** Revoke. The provider drops the stored credential and every later call is refused. */
|
|
24683
24769
|
disconnect: async ({ client, args }) => ({
|
|
24684
24770
|
out: await client.connections.disconnect(args.str("connection") ?? args.at(0, "connection-id"))
|
|
@@ -24711,6 +24797,26 @@ var credits2 = {
|
|
|
24711
24797
|
})
|
|
24712
24798
|
})
|
|
24713
24799
|
};
|
|
24800
|
+
var plan = {
|
|
24801
|
+
/** `status`, when the paid period ends, and whether it is already set to stop (§18b). */
|
|
24802
|
+
show: async ({ client }) => ({ out: await client.credits.subscription() }),
|
|
24803
|
+
/**
|
|
24804
|
+
* Opens the hosted checkout and changes **nothing**, exactly like `credits topup`: the plan turns
|
|
24805
|
+
* `active` only when the signed provider callback lands, whenever the customer gets round to
|
|
24806
|
+
* paying. So this prints `action_url` whole and returns, rather than blocking on a purchase it
|
|
24807
|
+
* cannot see, cannot complete and cannot cancel. `vetta plan show` is what reports the outcome.
|
|
24808
|
+
*/
|
|
24809
|
+
subscribe: async ({ client }) => ({ out: await client.credits.subscribe() }),
|
|
24810
|
+
/**
|
|
24811
|
+
* The hosted account page — card, invoices, cancellation. Symmetric with `subscribe`: it prints
|
|
24812
|
+
* an `action_url` a human opens and returns, because there is nothing here a terminal can drive.
|
|
24813
|
+
*
|
|
24814
|
+
* It is why `plan` still has no `cancel` command. A cancel command would be a second, narrower
|
|
24815
|
+
* way to do one of the four things this page already does, and it would leave the other three —
|
|
24816
|
+
* a dead card is what actually ends most plans — reachable only from the dashboard.
|
|
24817
|
+
*/
|
|
24818
|
+
portal: async ({ client }) => ({ out: await client.credits.billingPortal() })
|
|
24819
|
+
};
|
|
24714
24820
|
|
|
24715
24821
|
// src/commands/deploy.ts
|
|
24716
24822
|
function fields(args) {
|
|
@@ -24969,8 +25075,16 @@ function exitForStopReason(reason) {
|
|
|
24969
25075
|
function exitForError(cause) {
|
|
24970
25076
|
return cause instanceof UsageError ? EXIT_USAGE : EXIT_ERROR;
|
|
24971
25077
|
}
|
|
25078
|
+
var REMEDY = {
|
|
25079
|
+
subscription_required: "vetta plan subscribe"
|
|
25080
|
+
};
|
|
24972
25081
|
function describeError(cause) {
|
|
24973
|
-
if (cause instanceof ApiError)
|
|
25082
|
+
if (cause instanceof ApiError) {
|
|
25083
|
+
const remedy = REMEDY[cause.code];
|
|
25084
|
+
const fix = remedy === void 0 ? "" : `
|
|
25085
|
+
fix it with: ${remedy}`;
|
|
25086
|
+
return `error: ${cause.code}: ${cause.message} (${cause.requestId})${fix}`;
|
|
25087
|
+
}
|
|
24974
25088
|
if (cause instanceof UsageError) return `usage: ${cause.message}`;
|
|
24975
25089
|
return `error: ${cause instanceof Error ? cause.message : String(cause)}`;
|
|
24976
25090
|
}
|
|
@@ -25309,7 +25423,8 @@ var GROUPS = {
|
|
|
25309
25423
|
webhook,
|
|
25310
25424
|
org,
|
|
25311
25425
|
keys: keys2,
|
|
25312
|
-
credits: credits2
|
|
25426
|
+
credits: credits2,
|
|
25427
|
+
plan
|
|
25313
25428
|
};
|
|
25314
25429
|
var FLAGS = {
|
|
25315
25430
|
auth: {
|
|
@@ -25362,7 +25477,7 @@ var FLAGS = {
|
|
|
25362
25477
|
attach: "agent identity",
|
|
25363
25478
|
detach: "agent identity",
|
|
25364
25479
|
// Reached as `vetta identity connect|disconnect`; the sub-groups below carry the rest.
|
|
25365
|
-
connect: "identity auth-config",
|
|
25480
|
+
connect: "identity auth-config field",
|
|
25366
25481
|
disconnect: "connection"
|
|
25367
25482
|
},
|
|
25368
25483
|
/** Reached as `vetta identity domain <command>` (`SUBGROUPS`). Org-level: no `--identity`. */
|
|
@@ -25384,10 +25499,12 @@ var FLAGS = {
|
|
|
25384
25499
|
},
|
|
25385
25500
|
/** Reached as `vetta identity connections <command>`. */
|
|
25386
25501
|
connections: {
|
|
25502
|
+
apps: "search limit after",
|
|
25503
|
+
app: "app",
|
|
25387
25504
|
list: "identity",
|
|
25388
25505
|
show: "connection",
|
|
25389
25506
|
configs: "",
|
|
25390
|
-
"config-add": "connector auth scope client-id",
|
|
25507
|
+
"config-add": "connector auth scope tool client-id",
|
|
25391
25508
|
"config-rm": "auth-config"
|
|
25392
25509
|
},
|
|
25393
25510
|
/** Reached as `vetta identity phone <command>` (`SUBGROUPS` in `cli.ts`). */
|
|
@@ -25472,7 +25589,12 @@ var FLAGS = {
|
|
|
25472
25589
|
remove: ""
|
|
25473
25590
|
},
|
|
25474
25591
|
keys: { create: "name scopes", list: "limit after", rotate: "", revoke: "" },
|
|
25475
|
-
credits: { show: "", topup: "usd", ledger: "type session agent deployment from to limit after" }
|
|
25592
|
+
credits: { show: "", topup: "usd", ledger: "type session agent deployment from to limit after" },
|
|
25593
|
+
/**
|
|
25594
|
+
* The monthly plan (§18b). No command takes a flag: the plan has one price, and neither
|
|
25595
|
+
* `subscribe` nor `portal` has anything to configure — each answers a URL for a human to open.
|
|
25596
|
+
*/
|
|
25597
|
+
plan: { show: "", subscribe: "", portal: "" }
|
|
25476
25598
|
};
|
|
25477
25599
|
var GLOBAL_FLAGS = "json human profile api-key org api-base-url version help";
|
|
25478
25600
|
var UNSUPPORTED = {
|
|
@@ -25495,7 +25617,7 @@ var ALIASES = {
|
|
|
25495
25617
|
};
|
|
25496
25618
|
|
|
25497
25619
|
// src/cli.ts
|
|
25498
|
-
var VERSION = true ? "0.
|
|
25620
|
+
var VERSION = true ? "0.3.0" : "0.0.0-dev";
|
|
25499
25621
|
var GLOBAL_FLAGS_HELP = "global flags: --json (default) --human --profile <name> --api-key <key> --org <org_id> --api-base-url <url>";
|
|
25500
25622
|
function usage() {
|
|
25501
25623
|
const groups = [...Object.keys(GROUPS), ...Object.keys(ALIASES)].sort().join(", ");
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usenaive-sdk/vetta-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Vetta command line
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Vetta command line — create agents, run sessions, watch events, see cost.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -18,19 +18,18 @@
|
|
|
18
18
|
"publishConfig": {
|
|
19
19
|
"access": "public"
|
|
20
20
|
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/node": "22.20.1",
|
|
23
|
+
"esbuild": "0.28.2",
|
|
24
|
+
"yaml": "^2.9.0",
|
|
25
|
+
"@vetta/core": "0.0.0",
|
|
26
|
+
"@usenaive-sdk/vetta": "0.2.0"
|
|
27
|
+
},
|
|
21
28
|
"scripts": {
|
|
22
29
|
"build": "node build.mjs",
|
|
23
30
|
"typecheck": "tsc --noEmit",
|
|
24
31
|
"test": "vitest run",
|
|
25
32
|
"test:local": "vitest run",
|
|
26
|
-
"test:staging": "vitest run test/staging.e2e.ts"
|
|
27
|
-
"prepublishOnly": "pnpm run build"
|
|
28
|
-
},
|
|
29
|
-
"devDependencies": {
|
|
30
|
-
"@types/node": "catalog:",
|
|
31
|
-
"esbuild": "0.28.2",
|
|
32
|
-
"@vetta/core": "workspace:*",
|
|
33
|
-
"@usenaive-sdk/vetta": "workspace:*",
|
|
34
|
-
"yaml": "^2.9.0"
|
|
33
|
+
"test:staging": "vitest run test/staging.e2e.ts"
|
|
35
34
|
}
|
|
36
|
-
}
|
|
35
|
+
}
|