@iola_adm/iola-cli 0.1.4 → 0.1.5
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 +22 -0
- package/package.json +1 -1
- package/src/cli.js +149 -0
package/README.md
CHANGED
|
@@ -75,6 +75,7 @@ iola help
|
|
|
75
75
|
|
|
76
76
|
```bash
|
|
77
77
|
iola banner
|
|
78
|
+
iola agent
|
|
78
79
|
iola ai doctor
|
|
79
80
|
iola ai setup ollama
|
|
80
81
|
iola health
|
|
@@ -91,6 +92,27 @@ iola setup codex
|
|
|
91
92
|
По умолчанию команды выводят компактную таблицу. Для полного ответа API
|
|
92
93
|
используйте `--json`.
|
|
93
94
|
|
|
95
|
+
## Интерактивный режим
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
iola agent
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Внутри agent доступны slash-команды:
|
|
102
|
+
|
|
103
|
+
```text
|
|
104
|
+
/help
|
|
105
|
+
/health
|
|
106
|
+
/layers
|
|
107
|
+
/schools --limit 10
|
|
108
|
+
/schools get --inn 1215067180
|
|
109
|
+
/kindergartens --search 29
|
|
110
|
+
/search лицей --limit 3
|
|
111
|
+
/mcp-info
|
|
112
|
+
/ai doctor
|
|
113
|
+
/exit
|
|
114
|
+
```
|
|
115
|
+
|
|
94
116
|
## Назначение
|
|
95
117
|
|
|
96
118
|
Первый релиз CLI дает прямой терминальный доступ к открытым данным и командам
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -27,6 +27,7 @@ const COMMANDS = new Map([
|
|
|
27
27
|
["help", showHelp],
|
|
28
28
|
["version", showVersion],
|
|
29
29
|
["banner", showBanner],
|
|
30
|
+
["agent", startAgent],
|
|
30
31
|
["ai", handleAi],
|
|
31
32
|
["health", checkHealth],
|
|
32
33
|
["layers", listLayers],
|
|
@@ -54,6 +55,7 @@ async function showHelp() {
|
|
|
54
55
|
|
|
55
56
|
Usage:
|
|
56
57
|
iola banner
|
|
58
|
+
iola agent
|
|
57
59
|
iola ai doctor [--json]
|
|
58
60
|
iola ai setup
|
|
59
61
|
iola ai setup ollama [--yes] [--model MODEL]
|
|
@@ -74,6 +76,119 @@ Environment:
|
|
|
74
76
|
`);
|
|
75
77
|
}
|
|
76
78
|
|
|
79
|
+
async function startAgent() {
|
|
80
|
+
showBanner();
|
|
81
|
+
console.log("Интерактивный режим. Введите /help для списка команд, /exit для выхода.");
|
|
82
|
+
|
|
83
|
+
const rl = readline.createInterface({ input, output, prompt: "iola> " });
|
|
84
|
+
let closed = false;
|
|
85
|
+
rl.on("close", () => {
|
|
86
|
+
closed = true;
|
|
87
|
+
});
|
|
88
|
+
safePrompt(rl);
|
|
89
|
+
|
|
90
|
+
for await (const rawLine of rl) {
|
|
91
|
+
const line = rawLine.trim();
|
|
92
|
+
|
|
93
|
+
if (!line) {
|
|
94
|
+
safePrompt(rl, closed);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
const shouldExit = await handleAgentLine(line);
|
|
100
|
+
if (shouldExit) {
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
safePrompt(rl, closed);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (!closed) {
|
|
111
|
+
rl.close();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function handleAgentLine(line) {
|
|
116
|
+
if (!line.startsWith("/")) {
|
|
117
|
+
console.log("AI-ответы будут добавлены следующим этапом. Сейчас используйте slash-команды, например /search лицей.");
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const [command, ...args] = splitCommandLine(line.slice(1));
|
|
122
|
+
|
|
123
|
+
if (command === "exit" || command === "quit") {
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (command === "help") {
|
|
128
|
+
printAgentHelp();
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (command === "banner") {
|
|
133
|
+
showBanner();
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (command === "ai") {
|
|
138
|
+
await handleAi(args);
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const mapped = {
|
|
143
|
+
health: ["health", args],
|
|
144
|
+
layers: ["layers", args],
|
|
145
|
+
schools: ["schools", args],
|
|
146
|
+
kindergartens: ["kindergartens", args],
|
|
147
|
+
search: ["search", args],
|
|
148
|
+
"mcp-info": ["mcp-info", args],
|
|
149
|
+
setup: ["setup", args],
|
|
150
|
+
}[command];
|
|
151
|
+
|
|
152
|
+
if (!mapped) {
|
|
153
|
+
console.log(`Неизвестная slash-команда: /${command}`);
|
|
154
|
+
printAgentHelp();
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const [cliCommand, cliArgs] = mapped;
|
|
159
|
+
await COMMANDS.get(cliCommand)(cliArgs);
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function printAgentHelp() {
|
|
164
|
+
console.log(`Slash-команды:
|
|
165
|
+
/help
|
|
166
|
+
/health
|
|
167
|
+
/layers
|
|
168
|
+
/schools --limit 10
|
|
169
|
+
/schools get --inn 1215067180
|
|
170
|
+
/kindergartens --search 29
|
|
171
|
+
/kindergartens get --inn 1215077421
|
|
172
|
+
/search лицей --limit 3
|
|
173
|
+
/mcp-info
|
|
174
|
+
/ai doctor
|
|
175
|
+
/ai setup ollama
|
|
176
|
+
/banner
|
|
177
|
+
/exit`);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function safePrompt(rl, closed = false) {
|
|
181
|
+
if (closed) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
try {
|
|
186
|
+
rl.prompt();
|
|
187
|
+
} catch {
|
|
188
|
+
// The input stream can close while an async slash-command is still running.
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
77
192
|
function showBanner() {
|
|
78
193
|
if (process.stdout.isTTY && process.env.NO_COLOR !== "1") {
|
|
79
194
|
console.log(BANNER);
|
|
@@ -386,6 +501,40 @@ function parseOptions(args) {
|
|
|
386
501
|
return result;
|
|
387
502
|
}
|
|
388
503
|
|
|
504
|
+
function splitCommandLine(line) {
|
|
505
|
+
const result = [];
|
|
506
|
+
let current = "";
|
|
507
|
+
let quote = null;
|
|
508
|
+
|
|
509
|
+
for (const char of line) {
|
|
510
|
+
if ((char === "\"" || char === "'") && quote === null) {
|
|
511
|
+
quote = char;
|
|
512
|
+
continue;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
if (char === quote) {
|
|
516
|
+
quote = null;
|
|
517
|
+
continue;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
if (/\s/.test(char) && quote === null) {
|
|
521
|
+
if (current) {
|
|
522
|
+
result.push(current);
|
|
523
|
+
current = "";
|
|
524
|
+
}
|
|
525
|
+
continue;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
current += char;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
if (current) {
|
|
532
|
+
result.push(current);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
return result;
|
|
536
|
+
}
|
|
537
|
+
|
|
389
538
|
function filterItems(items, query) {
|
|
390
539
|
const normalized = query.toLocaleLowerCase("ru-RU");
|
|
391
540
|
return items.filter((item) => JSON.stringify(item).toLocaleLowerCase("ru-RU").includes(normalized));
|