@vatio-ai/cli 0.52.0 → 0.53.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 +1 -1
- package/lib/api-client.mjs +6 -1
- package/lib/commands/deploy.mjs +2 -2
- package/lib/commands/mcp.mjs +5 -4
- package/lib/commands/misc.mjs +7 -9
- package/lib/commands/workspace-admin.mjs +37 -9
- package/lib/help.mjs +5 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -71,7 +71,7 @@ kb write|cat|rm-entry Entries, from a file or stdin
|
|
|
71
71
|
kb follow|unfollow|refresh Read a site into a base, nightly
|
|
72
72
|
|
|
73
73
|
secrets list|set|rm Credentials your tools read
|
|
74
|
-
tokens list|create|revoke
|
|
74
|
+
tokens list|create|origins|revoke Publishable tokens and the origins each accepts
|
|
75
75
|
widget [--env NAME] What the platform enforces, and the tokens there are
|
|
76
76
|
auth --new-key Keypair that signs the visitor's JWT
|
|
77
77
|
|
package/lib/api-client.mjs
CHANGED
|
@@ -151,12 +151,17 @@ export class ApiClient extends HttpClient {
|
|
|
151
151
|
return this.get("/publishable_tokens");
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
createPublishableToken({ environment, label = null }) {
|
|
154
|
+
createPublishableToken({ environment, label = null, allowedOrigins = [] }) {
|
|
155
155
|
const body = { environment };
|
|
156
156
|
if (String(label ?? "").trim() !== "") body.label = String(label).trim();
|
|
157
|
+
if (allowedOrigins.length > 0) body.allowed_origins = allowedOrigins;
|
|
157
158
|
return this.post("/publishable_tokens", body);
|
|
158
159
|
}
|
|
159
160
|
|
|
161
|
+
setPublishableTokenOrigins({ prefix, allowedOrigins }) {
|
|
162
|
+
return this.patch(`/publishable_tokens/${encode(prefix)}`, { allowed_origins: allowedOrigins });
|
|
163
|
+
}
|
|
164
|
+
|
|
160
165
|
revokePublishableToken({ prefix }) {
|
|
161
166
|
return this.delete(`/publishable_tokens/${encode(prefix)}`);
|
|
162
167
|
}
|
package/lib/commands/deploy.mjs
CHANGED
|
@@ -106,8 +106,8 @@ export async function push(config, args) {
|
|
|
106
106
|
await ensureAuthorized(config);
|
|
107
107
|
|
|
108
108
|
// The remote has to exist before the workspace can be checked: the slug is in
|
|
109
|
-
// the URL of the call that checks it. It is created unnamed
|
|
110
|
-
//
|
|
109
|
+
// the URL of the call that checks it. It is created unnamed; the display name
|
|
110
|
+
// is a workspace setting edited in the console, not part of a push.
|
|
111
111
|
const clients = workspacesClient(config);
|
|
112
112
|
const created = !(await clients.workspaceExists(workspace));
|
|
113
113
|
if (created) {
|
package/lib/commands/mcp.mjs
CHANGED
|
@@ -106,17 +106,18 @@ const COMMANDS = {
|
|
|
106
106
|
annotations: { readOnlyHint: false, openWorldHint: true }
|
|
107
107
|
},
|
|
108
108
|
tokens: {
|
|
109
|
-
usage: "list | create [--env NAME] [--label NAME] | revoke PREFIX",
|
|
109
|
+
usage: "list | create [--env NAME] [--label NAME] [--origin URL]... | origins PREFIX URL... | revoke PREFIX",
|
|
110
110
|
summary:
|
|
111
111
|
"Publishable tokens for the widget and anything built on the SDK. A created token is shown in " +
|
|
112
|
-
"full exactly once."
|
|
112
|
+
"full exactly once. Each token works only from its own allowed origins (--origin, repeatable, or " +
|
|
113
|
+
"`origins PREFIX URL...` to replace the list); the install snippet's token is edited in the console.",
|
|
113
114
|
annotations: { readOnlyHint: false }
|
|
114
115
|
},
|
|
115
116
|
widget: {
|
|
116
117
|
usage: "[--env NAME]",
|
|
117
118
|
summary:
|
|
118
|
-
"What the platform will actually enforce for the widget, the
|
|
119
|
-
"that exist. Read-only:
|
|
119
|
+
"What the platform will actually enforce for the widget, the origins its tokens accept, and the " +
|
|
120
|
+
"tokens that exist. Read-only: the look is edited on the console's Brand page, whose URL it prints.",
|
|
120
121
|
annotations: { readOnlyHint: true }
|
|
121
122
|
},
|
|
122
123
|
whatsapp: {
|
package/lib/commands/misc.mjs
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import { existsSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
-
import { stringify as stringifyYaml } from "yaml";
|
|
6
5
|
|
|
7
6
|
import { KEYS, SLUG_FORMAT } from "../config.mjs";
|
|
8
7
|
import { MANIFEST_FILE, manifestPath } from "../workspace.mjs";
|
|
@@ -110,10 +109,13 @@ export async function init(config, args) {
|
|
|
110
109
|
}
|
|
111
110
|
|
|
112
111
|
const manifest = join(target, MANIFEST_FILE);
|
|
113
|
-
writeFileSync(manifest, starterManifest(slug
|
|
112
|
+
writeFileSync(manifest, starterManifest(slug));
|
|
114
113
|
|
|
115
114
|
console.log(`Wrote ${manifest}`);
|
|
116
115
|
if (!authorized) console.log(`Local only for now — \`vatio push\` is what creates ${slug} on the platform.`);
|
|
116
|
+
if (!authorized && String(name ?? "").trim() !== "") {
|
|
117
|
+
console.log("The display name is set in the console (the workspace's Brand page) once it exists.");
|
|
118
|
+
}
|
|
117
119
|
console.log("");
|
|
118
120
|
console.log("Next:");
|
|
119
121
|
console.log(` edit ${MANIFEST_FILE}, then \`vatio push\` and \`vatio publish\``);
|
|
@@ -121,14 +123,10 @@ export async function init(config, args) {
|
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
// The smallest file that deploys: which workspace, and what the agent does.
|
|
124
|
-
// The slug is already validated as a slug, so it needs no quoting
|
|
125
|
-
// name is
|
|
126
|
-
function starterManifest(slug
|
|
126
|
+
// The slug is already validated as a slug, so it needs no quoting. The display
|
|
127
|
+
// name is not here: it is a workspace setting, edited in the console.
|
|
128
|
+
function starterManifest(slug) {
|
|
127
129
|
const lines = ["# Which Vatio workspace this directory deploys to.", `workspace: ${slug}`, ""];
|
|
128
|
-
if (String(name ?? "").trim() !== "") {
|
|
129
|
-
lines.push(stringifyYaml({ business: { name: String(name).trim() } }).trimEnd());
|
|
130
|
-
lines.push("");
|
|
131
|
-
}
|
|
132
130
|
lines.push("agent:");
|
|
133
131
|
lines.push(" instructions: |");
|
|
134
132
|
lines.push(" Describe what this agent does and how it should answer.");
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
// secrets / tokens / widget — the three things a workspace has that its
|
|
2
2
|
// manifest deliberately does not carry.
|
|
3
3
|
//
|
|
4
|
-
// A secret is a credential, a publishable token is a credential
|
|
5
|
-
// screen is a read of what the platform
|
|
6
|
-
//
|
|
7
|
-
// vatio.yml and all of them are here.
|
|
4
|
+
// A secret is a credential, a publishable token is a credential (with the
|
|
5
|
+
// origins it accepts), and the widget screen is a read of what the platform
|
|
6
|
+
// will actually enforce, edited in the console. None of them are in vatio.yml.
|
|
8
7
|
|
|
9
8
|
import { deployClient } from "./deploy.mjs";
|
|
10
9
|
import { askSecret, fail, paint, takeValue } from "../support.mjs";
|
|
@@ -66,9 +65,19 @@ export async function secrets(config, args) {
|
|
|
66
65
|
fail("Usage: vatio secrets list|set KEY [VALUE]|rm KEY");
|
|
67
66
|
}
|
|
68
67
|
|
|
68
|
+
// Repeatable: `--origin https://a.com --origin https://b.com`.
|
|
69
|
+
function takeOrigins(args) {
|
|
70
|
+
const origins = [];
|
|
71
|
+
for (let value = takeValue(args, "--origin"); value !== null; value = takeValue(args, "--origin")) {
|
|
72
|
+
origins.push(value);
|
|
73
|
+
}
|
|
74
|
+
return origins;
|
|
75
|
+
}
|
|
76
|
+
|
|
69
77
|
export async function tokens(config, args) {
|
|
70
78
|
const environment = environmentOption(args, "live");
|
|
71
79
|
const label = takeValue(args, "--label") ?? takeValue(args, "-l");
|
|
80
|
+
const origins = takeOrigins(args);
|
|
72
81
|
const workspace = config.resolveWorkspaceRequired();
|
|
73
82
|
const client = deployClient(config, workspace);
|
|
74
83
|
const sub = args.shift() ?? "list";
|
|
@@ -78,7 +87,7 @@ export async function tokens(config, args) {
|
|
|
78
87
|
const list = asArray(payload.publishable_tokens);
|
|
79
88
|
if (list.length === 0) {
|
|
80
89
|
console.log(`No publishable tokens on workspace ${workspace}`);
|
|
81
|
-
console.log(" Create one: vatio tokens create --env live");
|
|
90
|
+
console.log(" Create one: vatio tokens create --env live --origin https://your-site.com");
|
|
82
91
|
return;
|
|
83
92
|
}
|
|
84
93
|
console.log(`Publishable tokens on workspace ${workspace} (${list.length}):`);
|
|
@@ -86,12 +95,14 @@ export async function tokens(config, args) {
|
|
|
86
95
|
const parts = [token.key_prefix ?? token.prefix, token.environment];
|
|
87
96
|
if (token.label) parts.push(token.label);
|
|
88
97
|
console.log(` ${parts.filter(Boolean).join(" ")}`);
|
|
98
|
+
console.log(` origins: ${originsLine(token.allowed_origins)}`);
|
|
89
99
|
}
|
|
90
100
|
return;
|
|
91
101
|
}
|
|
92
102
|
if (sub === "create") {
|
|
93
|
-
const payload = await client.createPublishableToken({ environment, label });
|
|
103
|
+
const payload = await client.createPublishableToken({ environment, label, allowedOrigins: origins });
|
|
94
104
|
console.log(`Created a publishable token for ${environment} on workspace ${workspace}`);
|
|
105
|
+
console.log(` origins: ${originsLine(payload.allowed_origins)}`);
|
|
95
106
|
console.log("");
|
|
96
107
|
// Shown in full exactly once: the platform stores a digest, so this is the
|
|
97
108
|
// only moment the value exists anywhere the developer can copy it.
|
|
@@ -100,6 +111,13 @@ export async function tokens(config, args) {
|
|
|
100
111
|
console.log("Copy it now — it is not shown again.");
|
|
101
112
|
return;
|
|
102
113
|
}
|
|
114
|
+
if (sub === "origins") {
|
|
115
|
+
const prefix = args.shift();
|
|
116
|
+
if (!prefix) fail("Usage: vatio tokens origins PREFIX [URL...] (no URL clears the list)");
|
|
117
|
+
const payload = await client.setPublishableTokenOrigins({ prefix, allowedOrigins: args.splice(0) });
|
|
118
|
+
console.log(`Origins for ${prefix}: ${originsLine(payload.allowed_origins)}`);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
103
121
|
if (sub === "revoke") {
|
|
104
122
|
const prefix = args.shift();
|
|
105
123
|
if (!prefix) fail("Usage: vatio tokens revoke PREFIX");
|
|
@@ -108,7 +126,16 @@ export async function tokens(config, args) {
|
|
|
108
126
|
return;
|
|
109
127
|
}
|
|
110
128
|
|
|
111
|
-
fail(
|
|
129
|
+
fail(
|
|
130
|
+
"Usage: vatio tokens list|create [--env live|preview|NAME] [--label NAME] [--origin URL]...|" +
|
|
131
|
+
"origins PREFIX URL...|revoke PREFIX"
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// An empty list is not "anywhere": only Vatio's own pages can use the token.
|
|
136
|
+
function originsLine(origins) {
|
|
137
|
+
const list = asArray(origins);
|
|
138
|
+
return list.length > 0 ? list.join(", ") : "none (add one with `vatio tokens origins PREFIX URL`)";
|
|
112
139
|
}
|
|
113
140
|
|
|
114
141
|
export async function widget(config, args) {
|
|
@@ -118,8 +145,9 @@ export async function widget(config, args) {
|
|
|
118
145
|
|
|
119
146
|
console.log(JSON.stringify(payload, null, 2));
|
|
120
147
|
console.log("");
|
|
121
|
-
console.log(
|
|
122
|
-
console.log(`
|
|
148
|
+
console.log(`The widget's look is edited in the console: ${payload.brand_url ?? "the workspace's Brand page"}`);
|
|
149
|
+
console.log(`Each token's allowed origins: ${payload.tokens_url ?? "the workspace's Tokens page"}`);
|
|
150
|
+
console.log(`A token for this environment: vatio tokens create --env ${environment} --origin https://your-site.com`);
|
|
123
151
|
}
|
|
124
152
|
|
|
125
153
|
function asArray(value) {
|
package/lib/help.mjs
CHANGED
|
@@ -57,8 +57,11 @@ flag, the directory decides.
|
|
|
57
57
|
Credentials and the widget:
|
|
58
58
|
secrets list|set KEY [VALUE]|rm KEY
|
|
59
59
|
Without VALUE, set asks for it with the input hidden
|
|
60
|
-
tokens list|create [--env NAME] [--label NAME]
|
|
61
|
-
|
|
60
|
+
tokens list|create [--env NAME] [--label NAME] [--origin URL]...|revoke PREFIX
|
|
61
|
+
tokens origins PREFIX URL...
|
|
62
|
+
The origins a token is accepted from (replaces the list)
|
|
63
|
+
widget [--env NAME] What the platform enforces, and the tokens there are;
|
|
64
|
+
the look is edited in the console
|
|
62
65
|
auth --new-key Keypair that signs the JWT saying who a visitor is
|
|
63
66
|
|
|
64
67
|
Channels (your own account serves live; the shared preview always serves preview):
|