@vatio-ai/cli 0.43.0 → 0.45.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/commands/knowledge.mjs +25 -8
- package/lib/commands/support-commands.mjs +60 -3
- package/lib/help.mjs +1 -0
- package/package.json +1 -1
|
@@ -22,7 +22,7 @@ export async function kb(config, args) {
|
|
|
22
22
|
switch (sub) {
|
|
23
23
|
case "list": return await list(client, workspace);
|
|
24
24
|
case "show": return await show(client, workspace, args.shift());
|
|
25
|
-
case "create": return await create(client, workspace, args.
|
|
25
|
+
case "create": return await create(client, workspace, args.splice(0));
|
|
26
26
|
case "rm": return await remove(client, workspace, args.shift());
|
|
27
27
|
case "write": return await write(client, workspace, args);
|
|
28
28
|
case "cat": return await cat(client, args.shift(), args.shift());
|
|
@@ -38,7 +38,7 @@ function usage() {
|
|
|
38
38
|
return `usage:
|
|
39
39
|
vatio kb List knowledge bases
|
|
40
40
|
vatio kb show NAME One base: its sites and its entries
|
|
41
|
-
vatio kb create NAME
|
|
41
|
+
vatio kb create NAME [NAME...] Create one base, or several
|
|
42
42
|
vatio kb rm NAME Delete a base (must be unreferenced)
|
|
43
43
|
vatio kb write BASE ENTRY [FILE] Write an entry, from FILE or stdin
|
|
44
44
|
vatio kb cat BASE ENTRY Print an entry's markdown
|
|
@@ -110,13 +110,30 @@ async function show(client, workspace, name) {
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
// Several names, because the moment this command is most often run is a push
|
|
114
|
+
// that just refused for naming bases that do not exist yet -- and that push
|
|
115
|
+
// names all of them at once. One base per invocation turned a first deploy
|
|
116
|
+
// into one round trip per name.
|
|
117
|
+
//
|
|
118
|
+
// Still never implicit: a base is created because someone typed its name here,
|
|
119
|
+
// which is what keeps `knowledge: [defualt]` a failed push instead of an empty
|
|
120
|
+
// base the agent searches forever.
|
|
121
|
+
async function create(client, workspace, names) {
|
|
122
|
+
const wanted = names.filter((name) => name.trim() !== "");
|
|
123
|
+
if (wanted.length === 0) fail("usage: vatio kb create NAME [NAME...]");
|
|
124
|
+
|
|
125
|
+
const created = [];
|
|
126
|
+
for (const name of wanted) {
|
|
127
|
+
const base = await client.createKnowledgeBase(name);
|
|
128
|
+
created.push(base.name);
|
|
129
|
+
console.log(`Created knowledge base ${base.name} on workspace ${workspace}`);
|
|
130
|
+
}
|
|
115
131
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
console.log(`
|
|
132
|
+
console.log(created.length === 1
|
|
133
|
+
? "It is empty and nothing reads it yet."
|
|
134
|
+
: "They are empty and nothing reads them yet.");
|
|
135
|
+
console.log("Fill with `vatio kb write` or `vatio kb follow`, then add");
|
|
136
|
+
console.log(`\`knowledge: [${created.join(", ")}]\` to the agent in vatio.yml and push.`);
|
|
120
137
|
}
|
|
121
138
|
|
|
122
139
|
async function remove(client, workspace, name) {
|
|
@@ -4,9 +4,11 @@
|
|
|
4
4
|
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { dirname, resolve } from "node:path";
|
|
6
6
|
|
|
7
|
+
import { buildBundle } from "../bundle.mjs";
|
|
7
8
|
import { HttpClient } from "../http.mjs";
|
|
8
9
|
import { VERSION } from "../version.mjs";
|
|
9
10
|
import { fail, takeFlag, takeValue } from "../support.mjs";
|
|
11
|
+
import { findWorkspaceRoot } from "../workspace.mjs";
|
|
10
12
|
import { DOCS_URL } from "./misc.mjs";
|
|
11
13
|
|
|
12
14
|
// The whole developer contract as markdown, live from the platform. Fetched
|
|
@@ -50,6 +52,9 @@ function issuesClient(config) {
|
|
|
50
52
|
// `vatio issue` is a change worth making, written against a template the
|
|
51
53
|
// platform also validates against. It is not an issue tracker: there are no
|
|
52
54
|
// states, labels, assignees or backlog, and that is on purpose.
|
|
55
|
+
//
|
|
56
|
+
// Sent from a workspace, it carries the workspace -- see workspaceSource
|
|
57
|
+
// below, and `--no-source` to send the sentence alone.
|
|
53
58
|
export async function issue(config, args) {
|
|
54
59
|
const sub = args[0];
|
|
55
60
|
if (sub === "list") return await issueList(config);
|
|
@@ -58,6 +63,7 @@ export async function issue(config, args) {
|
|
|
58
63
|
|
|
59
64
|
if (takeFlag(args, "--template")) return await issueTemplate(config);
|
|
60
65
|
|
|
66
|
+
const withoutSource = takeFlag(args, "--no-source");
|
|
61
67
|
const file = takeValue(args, "--file");
|
|
62
68
|
const workspace = takeValue(args, "--workspace") ?? safeWorkspace(config);
|
|
63
69
|
|
|
@@ -67,6 +73,14 @@ export async function issue(config, args) {
|
|
|
67
73
|
|
|
68
74
|
const body = { cli_version: VERSION };
|
|
69
75
|
if (workspace) body.workspace = workspace;
|
|
76
|
+
|
|
77
|
+
const source = withoutSource ? null : workspaceSource();
|
|
78
|
+
if (source?.files) {
|
|
79
|
+
body.files = source.files;
|
|
80
|
+
console.log(`Attaching ${source.root} — ${source.files.length} files, the same ones \`vatio push\` sends.`);
|
|
81
|
+
} else if (source?.error) {
|
|
82
|
+
console.log(`Not attaching your workspace: ${source.error}`);
|
|
83
|
+
}
|
|
70
84
|
if (file) {
|
|
71
85
|
body.markdown = readFileSync(file, "utf8");
|
|
72
86
|
} else {
|
|
@@ -75,7 +89,8 @@ export async function issue(config, args) {
|
|
|
75
89
|
fail(
|
|
76
90
|
"Usage: vatio issue \"what should change\"\n" +
|
|
77
91
|
" vatio issue --file ISSUE.md\n" +
|
|
78
|
-
" vatio issue --template
|
|
92
|
+
" vatio issue --template # the shape it is read against\n" +
|
|
93
|
+
" vatio issue --no-source # without your workspace attached"
|
|
79
94
|
);
|
|
80
95
|
}
|
|
81
96
|
body.message = message;
|
|
@@ -96,18 +111,42 @@ async function issueTemplate(config) {
|
|
|
96
111
|
process.stdout.write(await response.text());
|
|
97
112
|
}
|
|
98
113
|
|
|
114
|
+
// Where a report stands, in the words the developer is actually asking in:
|
|
115
|
+
// has anyone looked at it, and is the ball with them or with us. There is no
|
|
116
|
+
// `status` field to print -- an issue has no states -- so this reads the few
|
|
117
|
+
// facts the platform does publish about the thread.
|
|
118
|
+
function issueStatus(row) {
|
|
119
|
+
if (row.resolved) return "closed";
|
|
120
|
+
// The developer wrote last and nothing has gone back yet.
|
|
121
|
+
if (row.awaiting_us) return "with us";
|
|
122
|
+
if (row.answered) return "answered";
|
|
123
|
+
if (row.answers > 0) return "in progress";
|
|
124
|
+
return "sent";
|
|
125
|
+
}
|
|
126
|
+
|
|
99
127
|
async function issueList(config) {
|
|
128
|
+
// `data`, the same envelope every other read in this CLI unwraps. Reading
|
|
129
|
+
// `issues` here is how `list` spent its whole life reporting that a
|
|
130
|
+
// developer had sent nothing while `show` returned those same issues by id.
|
|
100
131
|
const payload = await issuesClient(config).get("/cli/issues");
|
|
101
|
-
const issues = Array.isArray(payload.
|
|
132
|
+
const issues = Array.isArray(payload.data) ? payload.data : [];
|
|
102
133
|
if (issues.length === 0) {
|
|
103
134
|
console.log("You have not sent any issues yet.");
|
|
104
135
|
console.log(' Send one: vatio issue "what should change"');
|
|
105
136
|
return;
|
|
106
137
|
}
|
|
107
138
|
console.log(`Your issues (${issues.length}):`);
|
|
139
|
+
const idWidth = Math.max(...issues.map((row) => String(row.id).length));
|
|
140
|
+
const statusWidth = Math.max(...issues.map((row) => issueStatus(row).length));
|
|
141
|
+
// The pull request goes under the title it belongs to, so the id and status
|
|
142
|
+
// columns stay readable as columns.
|
|
143
|
+
const indent = " ".repeat(2 + idWidth + 3 + statusWidth + 2);
|
|
108
144
|
for (const row of issues) {
|
|
109
|
-
|
|
145
|
+
const id = `[${String(row.id).padStart(idWidth)}]`;
|
|
146
|
+
console.log(` ${id} ${issueStatus(row).padEnd(statusWidth)} ${row.title ?? ""}`.trimEnd());
|
|
147
|
+
if (row.pull_request_url) console.log(`${indent}${row.pull_request_url}`);
|
|
110
148
|
}
|
|
149
|
+
console.log("Read one, conversation included: vatio issue show ID");
|
|
111
150
|
}
|
|
112
151
|
|
|
113
152
|
// The markdown view, which is the same document Vatio's own triage agent
|
|
@@ -136,6 +175,24 @@ async function issueComment(config, id, rest) {
|
|
|
136
175
|
console.log(`Replied on issue ${id}.`);
|
|
137
176
|
}
|
|
138
177
|
|
|
178
|
+
// The directory the issue was typed in, sent whole -- the same bundle `check`
|
|
179
|
+
// and `push` send, because which files matter is the platform's contract and
|
|
180
|
+
// this client does not get a second answer to it.
|
|
181
|
+
//
|
|
182
|
+
// Nothing here can stop an issue from being sent: a directory that is not a
|
|
183
|
+
// workspace, or one too large to bundle, travels without its source. The call
|
|
184
|
+
// site says so out loud, since a developer is entitled to know what left their
|
|
185
|
+
// machine, and `--no-source` declines in advance.
|
|
186
|
+
function workspaceSource() {
|
|
187
|
+
try {
|
|
188
|
+
const root = findWorkspaceRoot(process.cwd());
|
|
189
|
+
if (!root) return null;
|
|
190
|
+
return { root, files: buildBundle(root) };
|
|
191
|
+
} catch (error) {
|
|
192
|
+
return { error: error.message };
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
139
196
|
// A workspace is useful context on an issue but never required: `vatio issue`
|
|
140
197
|
// has to work from anywhere, including a directory that is not a workspace.
|
|
141
198
|
function safeWorkspace(config) {
|
package/lib/help.mjs
CHANGED
|
@@ -61,6 +61,7 @@ flag, the directory decides.
|
|
|
61
61
|
|
|
62
62
|
Everything else:
|
|
63
63
|
issue "what should change"|list|show ID|comment ID "reply"|--template
|
|
64
|
+
Sends your workspace along; --no-source to not
|
|
64
65
|
mcp Speak MCP over stdio, for a coding agent
|
|
65
66
|
config show|get KEY|set KEY VALUE|unset KEY
|
|
66
67
|
Keys: base_url, token
|