@vatio-ai/cli 0.50.0 → 0.52.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/lib/api-client.mjs +18 -0
- package/lib/commands/deploy.mjs +13 -1
- package/lib/commands/knowledge.mjs +89 -5
- package/lib/commands/mcp.mjs +8 -3
- package/lib/help.mjs +5 -1
- package/package.json +1 -1
package/lib/api-client.mjs
CHANGED
|
@@ -127,6 +127,24 @@ export class ApiClient extends HttpClient {
|
|
|
127
127
|
return this.post(`/knowledge_bases/${encode(base)}/sites/refresh`, { url });
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
+
// Writes land in the base's draft, which preview answers from; live moves
|
|
131
|
+
// only on publish or rollback.
|
|
132
|
+
knowledgeChanges(base) {
|
|
133
|
+
return this.get(`/knowledge_bases/${encode(base)}/changes`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
publishKnowledgeBase({ base, note }) {
|
|
137
|
+
return this.post(`/knowledge_bases/${encode(base)}/publish`, { note });
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
knowledgeSnapshots(base) {
|
|
141
|
+
return this.get(`/knowledge_bases/${encode(base)}/snapshots`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
rollbackKnowledgeBase({ base, number }) {
|
|
145
|
+
return this.post(`/knowledge_bases/${encode(base)}/snapshots/${encode(String(number))}/rollback`, {});
|
|
146
|
+
}
|
|
147
|
+
|
|
130
148
|
// --- publishable tokens and the widget ------------------------------
|
|
131
149
|
|
|
132
150
|
listPublishableTokens() {
|
package/lib/commands/deploy.mjs
CHANGED
|
@@ -18,7 +18,7 @@ import { buildBundle, BundleError } from "../bundle.mjs";
|
|
|
18
18
|
import { ApiClient, CliClient } from "../api-client.mjs";
|
|
19
19
|
import { NotFoundError } from "../http.mjs";
|
|
20
20
|
import { deviceLogin } from "./auth.mjs";
|
|
21
|
-
import { detectGitSha, fail, takeEnv, takeFlag, takeValue } from "../support.mjs";
|
|
21
|
+
import { detectGitSha, fail, paint, takeEnv, takeFlag, takeValue } from "../support.mjs";
|
|
22
22
|
|
|
23
23
|
// The first command that makes something exist on a server, so the first one
|
|
24
24
|
// that needs to know whose it is.
|
|
@@ -141,6 +141,16 @@ export async function push(config, args) {
|
|
|
141
141
|
console.log(hint.message);
|
|
142
142
|
console.log(` ${hint.url}`);
|
|
143
143
|
}
|
|
144
|
+
printNotices(payload);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Something the platform wants the developer to know about the command they
|
|
148
|
+
// just ran -- a deprecation, usually. On stderr so scripts reading stdout keep
|
|
149
|
+
// working.
|
|
150
|
+
function printNotices(payload) {
|
|
151
|
+
for (const notice of asArray(payload.notices)) {
|
|
152
|
+
process.stderr.write(`\n${paint("yellow", `Notice: ${notice}`)}\n`);
|
|
153
|
+
}
|
|
144
154
|
}
|
|
145
155
|
|
|
146
156
|
export async function publish(config, args) {
|
|
@@ -156,12 +166,14 @@ export async function publish(config, args) {
|
|
|
156
166
|
const from = asArray(payload.published_from);
|
|
157
167
|
const source = from.length > 0 ? ` from ${from.join(", ")}` : "";
|
|
158
168
|
console.log(`Published live deployment #${payload.deployment_id}${source} (git_sha=${JSON.stringify(payload.git_sha ?? null)})`);
|
|
169
|
+
printNotices(payload);
|
|
159
170
|
}
|
|
160
171
|
|
|
161
172
|
export async function rollback(config) {
|
|
162
173
|
const workspace = config.resolveWorkspaceRequired();
|
|
163
174
|
const payload = await deployClient(config, workspace).rollback({ createdBy: process.env.USER ?? null });
|
|
164
175
|
console.log(`Rolled back to deployment #${payload.deployment_id} (from #${payload.rolled_back_from_id})`);
|
|
176
|
+
printNotices(payload);
|
|
165
177
|
}
|
|
166
178
|
|
|
167
179
|
export async function status(config) {
|
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
//
|
|
3
3
|
// A base belongs to the workspace, not to a deployment: `knowledge:` in
|
|
4
4
|
// vatio.yml is a list of *names*, and a push neither fills nor empties one.
|
|
5
|
-
// That is why this is a command and not part of the manifest
|
|
6
|
-
//
|
|
5
|
+
// That is why this is a command and not part of the manifest.
|
|
6
|
+
//
|
|
7
|
+
// Every write goes to the base's draft, which preview answers from. Live
|
|
8
|
+
// answers from the last published snapshot and changes only on `publish` --
|
|
9
|
+
// or `rollback`, which points it at an earlier one. So: write, try it on
|
|
10
|
+
// preview, publish.
|
|
7
11
|
//
|
|
8
12
|
// A base holds entries, and an entry is markdown. Either you wrote it, or a
|
|
9
13
|
// site wrote it from a page it read — and a site is one URL or one pattern,
|
|
@@ -30,6 +34,10 @@ export async function kb(config, args) {
|
|
|
30
34
|
case "follow": return await follow(client, workspace, args.shift(), args.shift());
|
|
31
35
|
case "unfollow": return await unfollow(client, workspace, args.shift(), args.shift());
|
|
32
36
|
case "refresh": return await refresh(client, workspace, args.shift(), args.shift());
|
|
37
|
+
case "status": return await status(client, workspace, args.shift());
|
|
38
|
+
case "publish": return await publish(client, workspace, args);
|
|
39
|
+
case "history": return await history(client, workspace, args.shift());
|
|
40
|
+
case "rollback": return await rollback(client, workspace, args.shift(), args.shift());
|
|
33
41
|
default: fail(`Unknown kb subcommand: ${sub}\n\n${usage()}`);
|
|
34
42
|
}
|
|
35
43
|
}
|
|
@@ -45,7 +53,11 @@ function usage() {
|
|
|
45
53
|
vatio kb rm-entry BASE ENTRY Delete one entry
|
|
46
54
|
vatio kb follow BASE URL Read a site into the base, nightly
|
|
47
55
|
vatio kb unfollow BASE URL Stop reading it, and drop its entries
|
|
48
|
-
vatio kb refresh BASE [URL] Read the sites again now
|
|
56
|
+
vatio kb refresh BASE [URL] Read the sites again now
|
|
57
|
+
vatio kb status BASE What the draft has that live does not
|
|
58
|
+
vatio kb publish BASE [-m NOTE] Take the draft live
|
|
59
|
+
vatio kb history BASE Every publication, newest first
|
|
60
|
+
vatio kb rollback BASE NUMBER Point live back at publication NUMBER`;
|
|
49
61
|
}
|
|
50
62
|
|
|
51
63
|
async function list(client, workspace) {
|
|
@@ -80,6 +92,7 @@ async function show(client, workspace, name) {
|
|
|
80
92
|
`${base.name} on workspace ${workspace}: entries=${base.entries_count} ` +
|
|
81
93
|
`ready=${base.answerable_count}${referenceNote(base)}`
|
|
82
94
|
);
|
|
95
|
+
console.log(` ${liveNote(base)}`);
|
|
83
96
|
|
|
84
97
|
const sites = asArray(base.sites);
|
|
85
98
|
if (sites.length > 0) {
|
|
@@ -106,10 +119,20 @@ async function show(client, workspace, name) {
|
|
|
106
119
|
console.log("\n entries:");
|
|
107
120
|
for (const entry of entries) {
|
|
108
121
|
const origin = entry.written ? "written here" : entry.url;
|
|
109
|
-
|
|
122
|
+
const version = entry.version ? ` v${entry.version}` : "";
|
|
123
|
+
console.log(` ${entry.name}${version} ${entry.state ?? "?"} ${origin}`);
|
|
110
124
|
}
|
|
111
125
|
}
|
|
112
126
|
|
|
127
|
+
// Where live stands, and whether the draft has moved past it.
|
|
128
|
+
function liveNote(base) {
|
|
129
|
+
const live = base.live_snapshot ? `live=publication #${base.live_snapshot}` : "live=never published";
|
|
130
|
+
const pending = base.pending_changes
|
|
131
|
+
? ` ${base.pending_changes} unpublished change${base.pending_changes === 1 ? "" : "s"} — \`vatio kb publish ${base.name}\``
|
|
132
|
+
: "";
|
|
133
|
+
return `${live}${pending}`;
|
|
134
|
+
}
|
|
135
|
+
|
|
113
136
|
// Several names, because the moment this command is most often run is a push
|
|
114
137
|
// that just refused for naming bases that do not exist yet -- and that push
|
|
115
138
|
// names all of them at once. One base per invocation turned a first deploy
|
|
@@ -165,7 +188,9 @@ async function write(client, workspace, args) {
|
|
|
165
188
|
}
|
|
166
189
|
|
|
167
190
|
const row = await client.writeKnowledgeEntry({ base, name, content });
|
|
168
|
-
|
|
191
|
+
const version = row.version ? ` (v${row.version})` : "";
|
|
192
|
+
console.log(`Wrote ${row.name}${version} to the draft of ${base} on workspace ${workspace}`);
|
|
193
|
+
console.log(`Preview answers with it now; \`vatio kb publish ${base}\` takes it live.`);
|
|
169
194
|
}
|
|
170
195
|
|
|
171
196
|
// Prints exactly what the platform holds, so a diff against the file you
|
|
@@ -221,6 +246,65 @@ async function refresh(client, workspace, base, url) {
|
|
|
221
246
|
console.log(`Runs in the background — check progress with \`vatio kb show ${base}\``);
|
|
222
247
|
}
|
|
223
248
|
|
|
249
|
+
// The draft against live, entry by entry -- what `publish` would do.
|
|
250
|
+
async function status(client, workspace, base) {
|
|
251
|
+
if (!base) fail("usage: vatio kb status BASE");
|
|
252
|
+
|
|
253
|
+
const changes = asArray((await client.knowledgeChanges(base)).data);
|
|
254
|
+
if (changes.length === 0) {
|
|
255
|
+
console.log(`${base} on workspace ${workspace}: everything is published`);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
console.log(`${base} on workspace ${workspace}: ${changes.length} unpublished change${changes.length === 1 ? "" : "s"}`);
|
|
260
|
+
for (const change of changes) {
|
|
261
|
+
const from = change.live_version ? `v${change.live_version}` : "—";
|
|
262
|
+
const to = change.draft_version ? `v${change.draft_version}` : "—";
|
|
263
|
+
console.log(` ${change.change.padEnd(8)} ${change.name} ${from} → ${to}`);
|
|
264
|
+
}
|
|
265
|
+
console.log(`\nPublish with \`vatio kb publish ${base} -m "what changed"\``);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
async function publish(client, workspace, args) {
|
|
269
|
+
const base = args.shift();
|
|
270
|
+
if (!base) fail("usage: vatio kb publish BASE [-m NOTE]");
|
|
271
|
+
|
|
272
|
+
let note = "";
|
|
273
|
+
const flag = args.findIndex((arg) => arg === "-m" || arg === "--note");
|
|
274
|
+
if (flag !== -1) note = args[flag + 1] ?? "";
|
|
275
|
+
|
|
276
|
+
const snapshot = await client.publishKnowledgeBase({ base, note });
|
|
277
|
+
console.log(`Published ${base} on workspace ${workspace} as #${snapshot.number} (${snapshot.entries} entries)`);
|
|
278
|
+
console.log(`Live answers from it now. Undo with \`vatio kb rollback ${base} NUMBER\` — see \`vatio kb history ${base}\`.`);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
async function history(client, workspace, base) {
|
|
282
|
+
if (!base) fail("usage: vatio kb history BASE");
|
|
283
|
+
|
|
284
|
+
const snapshots = asArray((await client.knowledgeSnapshots(base)).data);
|
|
285
|
+
if (snapshots.length === 0) {
|
|
286
|
+
console.log(`${base} on workspace ${workspace} was never published — \`vatio kb publish ${base}\``);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
console.log(`Publications of ${base} on workspace ${workspace}:`);
|
|
291
|
+
for (const snapshot of snapshots) {
|
|
292
|
+
const live = snapshot.live ? " ← live" : "";
|
|
293
|
+
const who = snapshot.author ? ` ${snapshot.author}` : "";
|
|
294
|
+
const note = snapshot.note ? ` ${snapshot.note}` : "";
|
|
295
|
+
console.log(` #${snapshot.number} ${snapshot.created_at}${who} entries=${snapshot.entries}${note}${live}`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Only the pointer moves: the draft, and every later publication, stay.
|
|
300
|
+
async function rollback(client, workspace, base, number) {
|
|
301
|
+
if (!base || !number || !/^\d+$/.test(number)) fail("usage: vatio kb rollback BASE NUMBER");
|
|
302
|
+
|
|
303
|
+
await client.rollbackKnowledgeBase({ base, number });
|
|
304
|
+
console.log(`Live for ${base} on workspace ${workspace} is publication #${number} again`);
|
|
305
|
+
console.log("The draft is untouched; publish again whenever it is ready.");
|
|
306
|
+
}
|
|
307
|
+
|
|
224
308
|
// Blocking on purpose: `vatio kb write docs refunds < refunds.md` should behave
|
|
225
309
|
// like every other filter, and a terminal with nobody piping into it returns ""
|
|
226
310
|
// rather than hanging on a read that will never end.
|
package/lib/commands/mcp.mjs
CHANGED
|
@@ -69,7 +69,8 @@ const COMMANDS = {
|
|
|
69
69
|
summary:
|
|
70
70
|
"Promote the latest push to live (or the preview `--env` names), which is what customers " +
|
|
71
71
|
"see. Ask the developer first: this is " +
|
|
72
|
-
"the one step that changes what real visitors get."
|
|
72
|
+
"the one step that changes what real visitors get. Refused when the workspace is connected " +
|
|
73
|
+
"to GitHub: there, live changes only by merging to the default branch.",
|
|
73
74
|
annotations: { readOnlyHint: false, destructiveHint: true }
|
|
74
75
|
},
|
|
75
76
|
rollback: {
|
|
@@ -94,10 +95,14 @@ const COMMANDS = {
|
|
|
94
95
|
annotations: { readOnlyHint: false }
|
|
95
96
|
},
|
|
96
97
|
kb: {
|
|
97
|
-
usage:
|
|
98
|
+
usage:
|
|
99
|
+
"[list] | show NAME | create NAME | write BASE ENTRY [FILE] | cat BASE ENTRY | rm-entry BASE ENTRY | " +
|
|
100
|
+
"follow BASE URL | unfollow BASE URL | refresh BASE [URL] | status BASE | publish BASE [-m NOTE] | " +
|
|
101
|
+
"history BASE | rollback BASE NUMBER",
|
|
98
102
|
summary:
|
|
99
103
|
"Knowledge bases, which belong to the workspace rather than to a deployment: `knowledge:` in " +
|
|
100
|
-
"vatio.yml is a list of names, and a push neither fills nor empties one."
|
|
104
|
+
"vatio.yml is a list of names, and a push neither fills nor empties one. Writes go to a draft that " +
|
|
105
|
+
"preview answers from; live changes only on publish.",
|
|
101
106
|
annotations: { readOnlyHint: false, openWorldHint: true }
|
|
102
107
|
},
|
|
103
108
|
tokens: {
|
package/lib/help.mjs
CHANGED
|
@@ -25,7 +25,8 @@ flag, the directory decides.
|
|
|
25
25
|
Deploy:
|
|
26
26
|
push [--env NAME] Validate the workspace, then update a preview
|
|
27
27
|
publish [--env NAME] Promote the latest push to live. --env promotes
|
|
28
|
-
a specific preview instead
|
|
28
|
+
a specific preview instead. Refused when GitHub
|
|
29
|
+
is connected: merge to the default branch
|
|
29
30
|
rollback Restore the previous live deployment
|
|
30
31
|
status Preview and live deployment state
|
|
31
32
|
diff [--env NAME] What this directory would change (default: preview)
|
|
@@ -49,6 +50,9 @@ flag, the directory decides.
|
|
|
49
50
|
kb rm-entry BASE ENTRY Delete one entry
|
|
50
51
|
kb follow BASE URL Read a site into the base, nightly
|
|
51
52
|
kb unfollow BASE URL | refresh BASE [URL]
|
|
53
|
+
kb status BASE What the draft has that live does not
|
|
54
|
+
kb publish BASE [-m NOTE] Take the draft live (preview already has it)
|
|
55
|
+
kb history BASE | rollback BASE NUMBER
|
|
52
56
|
|
|
53
57
|
Credentials and the widget:
|
|
54
58
|
secrets list|set KEY [VALUE]|rm KEY
|