@velaro/cli 0.2.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/bin/velaro.js +56 -56
- package/lib/commands/article.js +280 -0
- package/lib/commands/bot.js +137 -137
- package/lib/commands/kb.js +241 -132
- package/lib/commands/login.js +60 -59
- package/lib/commands/mcp-key.js +100 -63
- package/lib/commands/rule.js +85 -85
- package/lib/commands/workflow.js +98 -98
- package/lib/config.js +3 -1
- package/lib/oauth.js +2 -1
- package/lib/run.js +6 -1
- package/lib/track.js +35 -0
- package/package.json +1 -1
package/lib/commands/bot.js
CHANGED
|
@@ -1,137 +1,137 @@
|
|
|
1
|
-
import { readFileSync } from 'fs';
|
|
2
|
-
import { get, post } from '../api.js';
|
|
3
|
-
import { requireFeature } from '../subscription.js';
|
|
4
|
-
import { runCommand } from '../run.js';
|
|
5
|
-
|
|
6
|
-
export const botCommand = {
|
|
7
|
-
command: 'bot <subcommand>',
|
|
8
|
-
describe: 'Manage AI bots',
|
|
9
|
-
builder: (yargs) =>
|
|
10
|
-
yargs
|
|
11
|
-
.command(botListCommand)
|
|
12
|
-
.command(botGetCommand)
|
|
13
|
-
.command(botSetupCommand)
|
|
14
|
-
.command(botPromptCommand)
|
|
15
|
-
.demandCommand(1, 'Specify a subcommand: list, get, setup, prompt'),
|
|
16
|
-
handler: () => {},
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
// ── list ───────────────────────────────────────────────────────────────────────
|
|
20
|
-
|
|
21
|
-
const botListCommand = {
|
|
22
|
-
command: 'list',
|
|
23
|
-
describe: 'List AI bots on your site',
|
|
24
|
-
handler: runCommand(async () => {
|
|
25
|
-
await requireFeature('enableAI', 'AI Bots');
|
|
26
|
-
|
|
27
|
-
const bots = await get('/AIConfiguration/list');
|
|
28
|
-
if (!bots?.length) {
|
|
29
|
-
console.log('No bots found. Create one with: velaro bot setup --name "My Bot"');
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
console.log(`Found ${bots.length} bot(s):\n`);
|
|
33
|
-
for (const b of bots) {
|
|
34
|
-
console.log(` [${b.id}] ${b.name} model=${b.aiModel ?? '(default)'} status=${b.status ?? 'ready'}`);
|
|
35
|
-
}
|
|
36
|
-
}),
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
// ── get ────────────────────────────────────────────────────────────────────────
|
|
40
|
-
|
|
41
|
-
const botGetCommand = {
|
|
42
|
-
command: 'get <id>',
|
|
43
|
-
describe: 'Show full configuration for a bot',
|
|
44
|
-
builder: (y) => y.positional('id', { type: 'number', describe: 'Bot ID' }),
|
|
45
|
-
handler: runCommand(async (argv) => {
|
|
46
|
-
await requireFeature('enableAI', 'AI Bots');
|
|
47
|
-
|
|
48
|
-
const bot = await get(`/AIConfiguration/${argv.id}`);
|
|
49
|
-
if (!bot) { console.error(`Bot ${argv.id} not found.`); process.exit(1); }
|
|
50
|
-
|
|
51
|
-
console.log(`\n[${bot.id}] ${bot.name}`);
|
|
52
|
-
console.log(` Model: ${bot.aiModel ?? '(default)'}`);
|
|
53
|
-
console.log(` Tone: ${bot.tone ?? '—'}`);
|
|
54
|
-
console.log(` Reply length: ${bot.replyLength ?? '—'}`);
|
|
55
|
-
console.log(` Status: ${bot.status ?? 'ready'}`);
|
|
56
|
-
if (bot.prompt) {
|
|
57
|
-
console.log(`\nSystem prompt:\n`);
|
|
58
|
-
console.log(bot.prompt);
|
|
59
|
-
} else {
|
|
60
|
-
console.log(`\nSystem prompt: (none)`);
|
|
61
|
-
}
|
|
62
|
-
}),
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
// ── setup ──────────────────────────────────────────────────────────────────────
|
|
66
|
-
|
|
67
|
-
const botSetupCommand = {
|
|
68
|
-
command: 'setup',
|
|
69
|
-
describe: 'Create or update an AI bot (upsert by name)',
|
|
70
|
-
builder: (y) =>
|
|
71
|
-
y
|
|
72
|
-
.option('name', { describe: 'Bot name', type: 'string', demandOption: true })
|
|
73
|
-
.option('prompt', { describe: 'System prompt text (inline)', type: 'string' })
|
|
74
|
-
.option('prompt-file', { describe: 'Path to a file containing the system prompt', type: 'string' })
|
|
75
|
-
.option('model', { describe: 'AI model', choices: ['velaro-gpt-4o-mini','velaro-gpt-4o'], type: 'string', default: 'velaro-gpt-4o-mini' })
|
|
76
|
-
.option('tone', { describe: 'Response tone', choices: ['Professional','Friendly','Formal','Casual'], default: 'Professional' })
|
|
77
|
-
.option('reply-length', { describe: 'Response length', choices: ['Short','Medium','Long'], default: 'Medium' })
|
|
78
|
-
.option('urls', { describe: 'Comma-separated data source URLs', type: 'string' })
|
|
79
|
-
.conflicts('prompt', 'prompt-file'),
|
|
80
|
-
|
|
81
|
-
handler: runCommand(async (argv) => {
|
|
82
|
-
await requireFeature('enableAI', 'AI Bots');
|
|
83
|
-
|
|
84
|
-
let promptText = argv.prompt;
|
|
85
|
-
if (argv['prompt-file']) {
|
|
86
|
-
promptText = readFileSync(argv['prompt-file'], 'utf8').trim();
|
|
87
|
-
console.log(`Read ${promptText.length} chars from ${argv['prompt-file']}`);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const payload = {
|
|
91
|
-
name: argv.name,
|
|
92
|
-
aiModel: argv.model,
|
|
93
|
-
tone: argv.tone,
|
|
94
|
-
replyLength: argv['reply-length'],
|
|
95
|
-
};
|
|
96
|
-
if (promptText) payload.prompt = promptText;
|
|
97
|
-
if (argv.urls) payload.dataUrls = argv.urls.split(',').map((u) => u.trim()).filter(Boolean);
|
|
98
|
-
|
|
99
|
-
const result = await post('/AIConfiguration', payload);
|
|
100
|
-
console.log(`Saved: [${result.id}] ${result.name}`);
|
|
101
|
-
}),
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
// ── prompt ─────────────────────────────────────────────────────────────────────
|
|
105
|
-
|
|
106
|
-
const botPromptCommand = {
|
|
107
|
-
command: 'prompt <id>',
|
|
108
|
-
describe: 'Get or update a bot\'s system prompt',
|
|
109
|
-
builder: (y) =>
|
|
110
|
-
y
|
|
111
|
-
.positional('id', { type: 'number', describe: 'Bot ID' })
|
|
112
|
-
.option('set', { describe: 'New prompt text (inline)', type: 'string' })
|
|
113
|
-
.option('file', { describe: 'Path to a .txt/.md prompt file', type: 'string' })
|
|
114
|
-
.conflicts('set', 'file'),
|
|
115
|
-
|
|
116
|
-
handler: runCommand(async (argv) => {
|
|
117
|
-
await requireFeature('enableAI', 'AI Bots');
|
|
118
|
-
|
|
119
|
-
const bot = await get(`/AIConfiguration/${argv.id}`);
|
|
120
|
-
if (!bot) { console.error(`Bot ${argv.id} not found.`); process.exit(1); }
|
|
121
|
-
|
|
122
|
-
if (!argv.set && !argv.file) {
|
|
123
|
-
// Read mode — print current prompt
|
|
124
|
-
console.log(bot.prompt ?? '(no system prompt set)');
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
let promptText = argv.set;
|
|
129
|
-
if (argv.file) {
|
|
130
|
-
promptText = readFileSync(argv.file, 'utf8').trim();
|
|
131
|
-
console.log(`Read ${promptText.length} chars from ${argv.file}`);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
await post('/AIConfiguration', { ...bot, prompt: promptText });
|
|
135
|
-
console.log(`Bot [${argv.id}] "${bot.name}" prompt updated (${promptText.length} chars).`);
|
|
136
|
-
}),
|
|
137
|
-
};
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import { get, post } from '../api.js';
|
|
3
|
+
import { requireFeature } from '../subscription.js';
|
|
4
|
+
import { runCommand } from '../run.js';
|
|
5
|
+
|
|
6
|
+
export const botCommand = {
|
|
7
|
+
command: 'bot <subcommand>',
|
|
8
|
+
describe: 'Manage AI bots',
|
|
9
|
+
builder: (yargs) =>
|
|
10
|
+
yargs
|
|
11
|
+
.command(botListCommand)
|
|
12
|
+
.command(botGetCommand)
|
|
13
|
+
.command(botSetupCommand)
|
|
14
|
+
.command(botPromptCommand)
|
|
15
|
+
.demandCommand(1, 'Specify a subcommand: list, get, setup, prompt'),
|
|
16
|
+
handler: () => {},
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// ── list ───────────────────────────────────────────────────────────────────────
|
|
20
|
+
|
|
21
|
+
const botListCommand = {
|
|
22
|
+
command: 'list',
|
|
23
|
+
describe: 'List AI bots on your site',
|
|
24
|
+
handler: runCommand(async () => {
|
|
25
|
+
await requireFeature('enableAI', 'AI Bots');
|
|
26
|
+
|
|
27
|
+
const bots = await get('/AIConfiguration/list');
|
|
28
|
+
if (!bots?.length) {
|
|
29
|
+
console.log('No bots found. Create one with: velaro bot setup --name "My Bot"');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
console.log(`Found ${bots.length} bot(s):\n`);
|
|
33
|
+
for (const b of bots) {
|
|
34
|
+
console.log(` [${b.id}] ${b.name} model=${b.aiModel ?? '(default)'} status=${b.status ?? 'ready'}`);
|
|
35
|
+
}
|
|
36
|
+
}),
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// ── get ────────────────────────────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
const botGetCommand = {
|
|
42
|
+
command: 'get <id>',
|
|
43
|
+
describe: 'Show full configuration for a bot',
|
|
44
|
+
builder: (y) => y.positional('id', { type: 'number', describe: 'Bot ID' }),
|
|
45
|
+
handler: runCommand(async (argv) => {
|
|
46
|
+
await requireFeature('enableAI', 'AI Bots');
|
|
47
|
+
|
|
48
|
+
const bot = await get(`/AIConfiguration/${argv.id}`);
|
|
49
|
+
if (!bot) { console.error(`Bot ${argv.id} not found.`); process.exit(1); }
|
|
50
|
+
|
|
51
|
+
console.log(`\n[${bot.id}] ${bot.name}`);
|
|
52
|
+
console.log(` Model: ${bot.aiModel ?? '(default)'}`);
|
|
53
|
+
console.log(` Tone: ${bot.tone ?? '—'}`);
|
|
54
|
+
console.log(` Reply length: ${bot.replyLength ?? '—'}`);
|
|
55
|
+
console.log(` Status: ${bot.status ?? 'ready'}`);
|
|
56
|
+
if (bot.prompt) {
|
|
57
|
+
console.log(`\nSystem prompt:\n`);
|
|
58
|
+
console.log(bot.prompt);
|
|
59
|
+
} else {
|
|
60
|
+
console.log(`\nSystem prompt: (none)`);
|
|
61
|
+
}
|
|
62
|
+
}),
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// ── setup ──────────────────────────────────────────────────────────────────────
|
|
66
|
+
|
|
67
|
+
const botSetupCommand = {
|
|
68
|
+
command: 'setup',
|
|
69
|
+
describe: 'Create or update an AI bot (upsert by name)',
|
|
70
|
+
builder: (y) =>
|
|
71
|
+
y
|
|
72
|
+
.option('name', { describe: 'Bot name', type: 'string', demandOption: true })
|
|
73
|
+
.option('prompt', { describe: 'System prompt text (inline)', type: 'string' })
|
|
74
|
+
.option('prompt-file', { describe: 'Path to a file containing the system prompt', type: 'string' })
|
|
75
|
+
.option('model', { describe: 'AI model', choices: ['velaro-gpt-4o-mini','velaro-gpt-4o'], type: 'string', default: 'velaro-gpt-4o-mini' })
|
|
76
|
+
.option('tone', { describe: 'Response tone', choices: ['Professional','Friendly','Formal','Casual'], default: 'Professional' })
|
|
77
|
+
.option('reply-length', { describe: 'Response length', choices: ['Short','Medium','Long'], default: 'Medium' })
|
|
78
|
+
.option('urls', { describe: 'Comma-separated data source URLs', type: 'string' })
|
|
79
|
+
.conflicts('prompt', 'prompt-file'),
|
|
80
|
+
|
|
81
|
+
handler: runCommand(async (argv) => {
|
|
82
|
+
await requireFeature('enableAI', 'AI Bots');
|
|
83
|
+
|
|
84
|
+
let promptText = argv.prompt;
|
|
85
|
+
if (argv['prompt-file']) {
|
|
86
|
+
promptText = readFileSync(argv['prompt-file'], 'utf8').trim();
|
|
87
|
+
console.log(`Read ${promptText.length} chars from ${argv['prompt-file']}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const payload = {
|
|
91
|
+
name: argv.name,
|
|
92
|
+
aiModel: argv.model,
|
|
93
|
+
tone: argv.tone,
|
|
94
|
+
replyLength: argv['reply-length'],
|
|
95
|
+
};
|
|
96
|
+
if (promptText) payload.prompt = promptText;
|
|
97
|
+
if (argv.urls) payload.dataUrls = argv.urls.split(',').map((u) => u.trim()).filter(Boolean);
|
|
98
|
+
|
|
99
|
+
const result = await post('/AIConfiguration', payload);
|
|
100
|
+
console.log(`Saved: [${result.id}] ${result.name}`);
|
|
101
|
+
}),
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// ── prompt ─────────────────────────────────────────────────────────────────────
|
|
105
|
+
|
|
106
|
+
const botPromptCommand = {
|
|
107
|
+
command: 'prompt <id>',
|
|
108
|
+
describe: 'Get or update a bot\'s system prompt',
|
|
109
|
+
builder: (y) =>
|
|
110
|
+
y
|
|
111
|
+
.positional('id', { type: 'number', describe: 'Bot ID' })
|
|
112
|
+
.option('set', { describe: 'New prompt text (inline)', type: 'string' })
|
|
113
|
+
.option('file', { describe: 'Path to a .txt/.md prompt file', type: 'string' })
|
|
114
|
+
.conflicts('set', 'file'),
|
|
115
|
+
|
|
116
|
+
handler: runCommand(async (argv) => {
|
|
117
|
+
await requireFeature('enableAI', 'AI Bots');
|
|
118
|
+
|
|
119
|
+
const bot = await get(`/AIConfiguration/${argv.id}`);
|
|
120
|
+
if (!bot) { console.error(`Bot ${argv.id} not found.`); process.exit(1); }
|
|
121
|
+
|
|
122
|
+
if (!argv.set && !argv.file) {
|
|
123
|
+
// Read mode — print current prompt
|
|
124
|
+
console.log(bot.prompt ?? '(no system prompt set)');
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
let promptText = argv.set;
|
|
129
|
+
if (argv.file) {
|
|
130
|
+
promptText = readFileSync(argv.file, 'utf8').trim();
|
|
131
|
+
console.log(`Read ${promptText.length} chars from ${argv.file}`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
await post('/AIConfiguration', { ...bot, prompt: promptText });
|
|
135
|
+
console.log(`Bot [${argv.id}] "${bot.name}" prompt updated (${promptText.length} chars).`);
|
|
136
|
+
}),
|
|
137
|
+
};
|