@iola_adm/iola-cli 0.2.8 → 0.2.9
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 -0
- package/package.json +1 -1
- package/skills/personal-docs/SKILL.md +1 -0
- package/src/cli.js +156 -1
- package/wiki//320/232/320/276/320/274/320/260/320/275/320/264/321/213.md +1 -0
- package/wiki//320/236/320/261/320/273/320/260/321/207/320/275/321/213/320/265-/320/264/320/270/321/201/320/272/320/270.md +12 -1
- package/wiki//320/241/320/272/320/270/320/273/320/273/321/213-/320/264/320/273/321/217-/320/266/320/270/321/202/320/265/320/273/320/265/320/271.md +9 -0
package/README.md
CHANGED
|
@@ -179,6 +179,7 @@ iola geo services "Йошкар-Ола, улица Петрова, 15"
|
|
|
179
179
|
iola cloud setup yandex-disk
|
|
180
180
|
iola cloud setup mailru-cloud
|
|
181
181
|
iola cloud status
|
|
182
|
+
iola cloud mkdir /IOLA/Фото
|
|
182
183
|
iola cloud find "справка" --path /IOLA
|
|
183
184
|
iola cloud upload report.md /IOLA/reports/report.md
|
|
184
185
|
iola cloud share /IOLA/reports/report.md
|
package/package.json
CHANGED
|
@@ -12,6 +12,7 @@ description: Личные документы пользователя в обл
|
|
|
12
12
|
Основные сценарии:
|
|
13
13
|
|
|
14
14
|
- `cloud-find-document` - найти документ в подключенном облаке.
|
|
15
|
+
- `cloud-create-folder` - создать папку на подключенном облачном диске.
|
|
15
16
|
- `cloud-save-result` - сохранить ответ, отчет, карточку или список в облако.
|
|
16
17
|
- `cloud-share-link` - создать публичную ссылку на файл в Яндекс Диске.
|
|
17
18
|
- `cloud-document-pack` - собрать папку с материалами для обращения.
|
package/src/cli.js
CHANGED
|
@@ -2948,6 +2948,14 @@ async function handleCloud(args) {
|
|
|
2948
2948
|
return;
|
|
2949
2949
|
}
|
|
2950
2950
|
|
|
2951
|
+
if (action === "mkdir" || action === "create-folder") {
|
|
2952
|
+
const provider = await getCloudProvider(options.provider);
|
|
2953
|
+
const remotePath = target || `${cloudRootForProvider(provider)}/Новая папка`;
|
|
2954
|
+
const result = await cloudCreateFolder(provider, remotePath);
|
|
2955
|
+
printKeyValue(result);
|
|
2956
|
+
return;
|
|
2957
|
+
}
|
|
2958
|
+
|
|
2951
2959
|
if (action === "upload") {
|
|
2952
2960
|
if (!target) throw new Error('Пример: iola cloud upload report.md /IOLA/reports/report.md');
|
|
2953
2961
|
const provider = await getCloudProvider(options.provider);
|
|
@@ -3004,6 +3012,7 @@ async function handleCloud(args) {
|
|
|
3004
3012
|
iola cloud status|doctor
|
|
3005
3013
|
iola cloud use yandex-disk
|
|
3006
3014
|
iola cloud ls /IOLA
|
|
3015
|
+
iola cloud mkdir /IOLA/Фото
|
|
3007
3016
|
iola cloud find "справка" --path /IOLA
|
|
3008
3017
|
iola cloud upload local.txt /IOLA/local.txt
|
|
3009
3018
|
iola cloud download /IOLA/local.txt ./local.txt
|
|
@@ -3116,6 +3125,18 @@ async function cloudFind(provider, query, options = {}) {
|
|
|
3116
3125
|
throw new Error(`Провайдер не поддерживается: ${provider}`);
|
|
3117
3126
|
}
|
|
3118
3127
|
|
|
3128
|
+
async function cloudCreateFolder(provider, remotePath) {
|
|
3129
|
+
if (provider === "yandex-disk") {
|
|
3130
|
+
await ensureYandexDiskDir(remotePath, { allowExisting: true });
|
|
3131
|
+
return { provider, path: normalizeYandexDiskPath(remotePath), status: "created-or-exists" };
|
|
3132
|
+
}
|
|
3133
|
+
if (provider === "mailru-cloud") {
|
|
3134
|
+
await ensureMailruCloudDir(remotePath);
|
|
3135
|
+
return { provider, path: remotePath, status: "created-or-exists" };
|
|
3136
|
+
}
|
|
3137
|
+
throw new Error(`Провайдер не поддерживается: ${provider}`);
|
|
3138
|
+
}
|
|
3139
|
+
|
|
3119
3140
|
async function cloudShare(provider, remotePath) {
|
|
3120
3141
|
if (provider === "yandex-disk") return yandexDiskShare(remotePath);
|
|
3121
3142
|
throw new Error("Публичные ссылки через CLI сейчас поддерживаются только для Яндекс Диска.");
|
|
@@ -7873,6 +7894,20 @@ async function aiAsk(args, context = {}) {
|
|
|
7873
7894
|
const historyEnabled = !options.bare && !options["no-history"] && isFeatureEnabled("sqlite-history");
|
|
7874
7895
|
const sessionId = historyEnabled && isFeatureEnabled("sessions") ? ensureSessionForAsk(options, providerConfig, question) : null;
|
|
7875
7896
|
const history = context.history || (sessionId ? getSessionAiHistory(sessionId) : []);
|
|
7897
|
+
const cloudAnswer = await buildCloudDirectAnswer(question);
|
|
7898
|
+
if (cloudAnswer) {
|
|
7899
|
+
if (historyEnabled) {
|
|
7900
|
+
recordAskHistory({ question, answer: cloudAnswer, providerConfig, dataContext, error: "", sessionId });
|
|
7901
|
+
appendSessionExchange(sessionId, question, cloudAnswer, dataContext, "");
|
|
7902
|
+
}
|
|
7903
|
+
emitEvent(options, "answer", { length: cloudAnswer.length, sessionId, direct: true, cloud: true });
|
|
7904
|
+
if (options.output) {
|
|
7905
|
+
await assertPermission("writeFiles");
|
|
7906
|
+
await writeFile(options.output, cloudAnswer, "utf8");
|
|
7907
|
+
}
|
|
7908
|
+
if (!options.quiet) console.log(cloudAnswer);
|
|
7909
|
+
return cloudAnswer;
|
|
7910
|
+
}
|
|
7876
7911
|
const geoAnswer = await buildGeoDirectAnswer(question);
|
|
7877
7912
|
if (geoAnswer) {
|
|
7878
7913
|
if (historyEnabled) {
|
|
@@ -7973,6 +8008,119 @@ async function buildDirectDataAnswer(question, dataContext) {
|
|
|
7973
8008
|
].join("\n");
|
|
7974
8009
|
}
|
|
7975
8010
|
|
|
8011
|
+
async function buildCloudDirectAnswer(question) {
|
|
8012
|
+
if (!isCloudQuestion(question)) return "";
|
|
8013
|
+
const normalized = String(question || "").toLocaleLowerCase("ru-RU");
|
|
8014
|
+
try {
|
|
8015
|
+
const provider = await getCloudProvider();
|
|
8016
|
+
if (/(созда|сдела|добав).{0,30}(папк|директор)/iu.test(normalized) || /(папк|директор).{0,30}(созда|сдела|добав)/iu.test(normalized)) {
|
|
8017
|
+
const folderName = extractCloudFolderName(question) || "Новая папка";
|
|
8018
|
+
const remotePath = normalizeCloudUserPath(folderName, provider);
|
|
8019
|
+
const result = await cloudCreateFolder(provider, remotePath);
|
|
8020
|
+
return `Папка создана или уже была на облачном диске: ${result.path}`;
|
|
8021
|
+
}
|
|
8022
|
+
|
|
8023
|
+
if (/(покажи|список|что.+лежит|файлы|папки)/iu.test(normalized)) {
|
|
8024
|
+
const remotePath = extractCloudPath(question) || cloudRootForProvider(provider);
|
|
8025
|
+
const rows = await cloudList(provider, normalizeCloudUserPath(remotePath, provider));
|
|
8026
|
+
if (rows.length === 0) return `В папке ${normalizeCloudUserPath(remotePath, provider)} нет данных.`;
|
|
8027
|
+
return [
|
|
8028
|
+
`Облачный диск ${provider}, папка ${normalizeCloudUserPath(remotePath, provider)}:`,
|
|
8029
|
+
...rows.slice(0, 20).map((row, index) => `${index + 1}. ${row.type === "dir" ? "папка" : "файл"} ${row.name} — ${row.path}`),
|
|
8030
|
+
].join("\n");
|
|
8031
|
+
}
|
|
8032
|
+
|
|
8033
|
+
if (/(найди|поиск|где лежит)/iu.test(normalized)) {
|
|
8034
|
+
const query = cleanupCloudQuery(question);
|
|
8035
|
+
const rows = await cloudFind(provider, query, { path: cloudRootForProvider(provider), limit: 10 });
|
|
8036
|
+
if (rows.length === 0) return `На облачном диске не нашел: ${query}`;
|
|
8037
|
+
return [
|
|
8038
|
+
`Нашел на облачном диске ${provider}:`,
|
|
8039
|
+
...rows.map((row, index) => `${index + 1}. ${row.name} — ${row.path}`),
|
|
8040
|
+
].join("\n");
|
|
8041
|
+
}
|
|
8042
|
+
|
|
8043
|
+
if (/(ссылк|поделись|опубликуй)/iu.test(normalized)) {
|
|
8044
|
+
const remotePath = extractCloudPath(question);
|
|
8045
|
+
if (!remotePath) return "Укажите путь к файлу на облачном диске, например: /IOLA/reports/report.md";
|
|
8046
|
+
const result = await cloudShare(provider, normalizeCloudUserPath(remotePath, provider));
|
|
8047
|
+
return `Публичная ссылка: ${result.publicUrl}`;
|
|
8048
|
+
}
|
|
8049
|
+
|
|
8050
|
+
if (/(сохрани|запиши).{0,40}(на яндекс диске|в облак|на диск)/iu.test(normalized)) {
|
|
8051
|
+
const text = cleanupCloudSaveText(question);
|
|
8052
|
+
if (!text) return "Что сохранить на облачный диск?";
|
|
8053
|
+
const remotePath = `${cloudRootForProvider(provider)}/notes/iola-${timestampForFile()}.txt`;
|
|
8054
|
+
const tempPath = path.join(CONFIG_DIR, `cloud-save-${Date.now()}.txt`);
|
|
8055
|
+
await mkdir(CONFIG_DIR, { recursive: true });
|
|
8056
|
+
await writeFile(tempPath, text, "utf8");
|
|
8057
|
+
try {
|
|
8058
|
+
await cloudUpload(provider, tempPath, remotePath, { overwrite: true });
|
|
8059
|
+
} finally {
|
|
8060
|
+
await rm(tempPath, { force: true }).catch(() => {});
|
|
8061
|
+
}
|
|
8062
|
+
return `Сохранил текст на облачный диск: ${remotePath}`;
|
|
8063
|
+
}
|
|
8064
|
+
} catch (error) {
|
|
8065
|
+
return `Не смог выполнить облачный запрос: ${error instanceof Error ? error.message : String(error)}`;
|
|
8066
|
+
}
|
|
8067
|
+
return "";
|
|
8068
|
+
}
|
|
8069
|
+
|
|
8070
|
+
function isCloudQuestion(question) {
|
|
8071
|
+
return /(яндекс.?диск|yandex.?disk|облак|облачн|на диск|с диска|в диск|cloud|mail\.?ru|публичн.*ссылк|поделиться.*файл)/iu.test(String(question || ""));
|
|
8072
|
+
}
|
|
8073
|
+
|
|
8074
|
+
function normalizeCloudUserPath(value, provider = "yandex-disk") {
|
|
8075
|
+
const root = cloudRootForProvider(provider);
|
|
8076
|
+
let text = String(value || "").trim().replace(/\\/g, "/");
|
|
8077
|
+
text = text.replace(/^["'«»]+|["'«»]+$/gu, "").trim();
|
|
8078
|
+
if (!text) return root;
|
|
8079
|
+
if (text.startsWith("/")) return text;
|
|
8080
|
+
if (normalizeGeoText(text).startsWith(normalizeGeoText(root).replace(/^\//u, ""))) return `/${text.replace(/^\/+/u, "")}`;
|
|
8081
|
+
return `${root.replace(/\/+$/u, "")}/${text.replace(/^\/+/u, "")}`;
|
|
8082
|
+
}
|
|
8083
|
+
|
|
8084
|
+
function extractCloudFolderName(question) {
|
|
8085
|
+
const text = String(question || "").trim();
|
|
8086
|
+
const match = text.match(/(?:папк[ауи]?|директор(?:ию|ия|ии)?)\s+["'«]?([^"'».,!?]+)["'»]?/iu)
|
|
8087
|
+
|| text.match(/(?:названи(?:ем|е)|имя)\s+["'«]?([^"'».,!?]+)["'»]?/iu);
|
|
8088
|
+
if (!match?.[1]) return "";
|
|
8089
|
+
return cleanupCloudObjectName(match[1]);
|
|
8090
|
+
}
|
|
8091
|
+
|
|
8092
|
+
function extractCloudPath(question) {
|
|
8093
|
+
const text = String(question || "").trim();
|
|
8094
|
+
const pathMatch = text.match(/(?:^|\s)(\/IOLA\/[^\s]+|\/[^\s]+)/iu);
|
|
8095
|
+
if (pathMatch?.[1]) return pathMatch[1];
|
|
8096
|
+
const quoted = text.match(/["«]([^"»]+)["»]/u);
|
|
8097
|
+
if (quoted?.[1]) return quoted[1];
|
|
8098
|
+
const afterFolder = text.match(/(?:папк[аеуы]?|файл[ае]?)\s+([^,.!?]+)/iu);
|
|
8099
|
+
return afterFolder?.[1] ? cleanupCloudObjectName(afterFolder[1]) : "";
|
|
8100
|
+
}
|
|
8101
|
+
|
|
8102
|
+
function cleanupCloudObjectName(value) {
|
|
8103
|
+
return String(value || "")
|
|
8104
|
+
.replace(/\b(?:на|в|у меня|яндекс.?диск(?:е)?|диск(?:е)?|облак(?:е|о)?|создай|сделай|добавь|покажи)\b/giu, " ")
|
|
8105
|
+
.replace(/\s+/g, " ")
|
|
8106
|
+
.trim();
|
|
8107
|
+
}
|
|
8108
|
+
|
|
8109
|
+
function cleanupCloudQuery(question) {
|
|
8110
|
+
return String(question || "")
|
|
8111
|
+
.replace(/\b(?:найди|поиск|где лежит|на|в|яндекс.?диск(?:е)?|облак(?:е|о)?|диск(?:е)?|файл|документ)\b/giu, " ")
|
|
8112
|
+
.replace(/[?.!]+$/u, "")
|
|
8113
|
+
.replace(/\s+/g, " ")
|
|
8114
|
+
.trim();
|
|
8115
|
+
}
|
|
8116
|
+
|
|
8117
|
+
function cleanupCloudSaveText(question) {
|
|
8118
|
+
return String(question || "")
|
|
8119
|
+
.replace(/^.*?(?:сохрани|запиши)\s+/iu, "")
|
|
8120
|
+
.replace(/\s+(?:на яндекс диске|в облак[ео]|на диск).*$/iu, "")
|
|
8121
|
+
.trim();
|
|
8122
|
+
}
|
|
8123
|
+
|
|
7976
8124
|
function detectDirectDataFields(normalizedQuestion) {
|
|
7977
8125
|
const fields = [];
|
|
7978
8126
|
if (/(директ|руководител|заведующ|кто возглавляет)/iu.test(normalizedQuestion)) fields.push("head");
|
|
@@ -8256,6 +8404,11 @@ async function localToolAsk(question, providerConfig, options) {
|
|
|
8256
8404
|
if (!options.quiet) console.log(casualAnswer);
|
|
8257
8405
|
return casualAnswer;
|
|
8258
8406
|
}
|
|
8407
|
+
const cloudAnswer = await buildCloudDirectAnswer(question);
|
|
8408
|
+
if (cloudAnswer) {
|
|
8409
|
+
if (!options.quiet) console.log(cloudAnswer);
|
|
8410
|
+
return cloudAnswer;
|
|
8411
|
+
}
|
|
8259
8412
|
const geoAnswer = await buildGeoDirectAnswer(question);
|
|
8260
8413
|
if (geoAnswer) {
|
|
8261
8414
|
if (!options.quiet) console.log(geoAnswer);
|
|
@@ -10809,8 +10962,10 @@ function selectSkillsForPrompt(config, question = "", options = {}) {
|
|
|
10809
10962
|
if (enabled.has("local-model")) selected.add("local-model");
|
|
10810
10963
|
if (enabled.has("open-data") && shouldUseDataContext(question, options)) selected.add("open-data");
|
|
10811
10964
|
if (enabled.has("geo") && isGeoQuestion(normalized)) selected.add("geo");
|
|
10965
|
+
const cloudQuestion = isCloudQuestion(normalized);
|
|
10966
|
+
if (enabled.has("personal-docs") && cloudQuestion) selected.add("personal-docs");
|
|
10812
10967
|
if (enabled.has("reports") && /(отчет|отчёт|выгруз|csv|xlsx|качество|провер)/iu.test(normalized)) selected.add("reports");
|
|
10813
|
-
if (enabled.has("local-files") && (options.files || /(файл|папк|readme|документ|архив)/iu.test(normalized))) selected.add("local-files");
|
|
10968
|
+
if (enabled.has("local-files") && !cloudQuestion && (options.files || /(файл|папк|readme|документ|архив)/iu.test(normalized))) selected.add("local-files");
|
|
10814
10969
|
if (enabled.has("browser-agent") && /(браузер|сайт|страниц|url|https?:\/\/)/iu.test(normalized)) selected.add("browser-agent");
|
|
10815
10970
|
return selected;
|
|
10816
10971
|
}
|
|
@@ -50,6 +50,7 @@ iola cloud status
|
|
|
50
50
|
iola cloud doctor
|
|
51
51
|
iola cloud use yandex-disk
|
|
52
52
|
iola cloud ls /IOLA
|
|
53
|
+
iola cloud mkdir /IOLA/Фото
|
|
53
54
|
iola cloud find "справка" --path /IOLA
|
|
54
55
|
iola cloud upload report.md /IOLA/reports/report.md
|
|
55
56
|
iola cloud download /IOLA/reports/report.md ./report.md
|
|
@@ -18,6 +18,7 @@ iola cloud status
|
|
|
18
18
|
iola cloud doctor
|
|
19
19
|
iola cloud use yandex-disk
|
|
20
20
|
iola cloud ls /IOLA
|
|
21
|
+
iola cloud mkdir /IOLA/Фото
|
|
21
22
|
iola cloud find "справка" --path /IOLA
|
|
22
23
|
iola cloud upload report.md /IOLA/reports/report.md
|
|
23
24
|
iola cloud download /IOLA/reports/report.md ./report.md
|
|
@@ -45,7 +46,7 @@ iola cloud backup
|
|
|
45
46
|
5. Нажмите `Перейти к созданию`.
|
|
46
47
|
6. На шаге `Создание приложения` заполните:
|
|
47
48
|
- `Название вашего сервиса`: например `iola-cli`;
|
|
48
|
-
- `Иконка сервиса`: загрузите
|
|
49
|
+
- `Иконка сервиса`: загрузите PNG-иконку до 1 МБ. Готовая иконка iola-cli доступна по ссылке: `https://raw.githubusercontent.com/adm-iola/iola-cli/main/docs/assets/iola-oauth-icon.png`;
|
|
49
50
|
- `Почта для связи`: оставьте свою почту или укажите актуальную.
|
|
50
51
|
7. Нажмите `Продолжить`.
|
|
51
52
|
8. На шаге `Платформы приложений` выберите `Веб-сервисы`.
|
|
@@ -101,6 +102,16 @@ iola cloud doctor
|
|
|
101
102
|
|
|
102
103
|
Обычно такой токен выдается на длительный срок. Если доступ перестал работать, получите новый токен через ту же ссылку авторизации и повторите `iola cloud setup yandex-disk`.
|
|
103
104
|
|
|
105
|
+
После подключения можно работать с облаком обычными фразами в CLI:
|
|
106
|
+
|
|
107
|
+
```text
|
|
108
|
+
создай у меня на яндекс диске папку фото
|
|
109
|
+
покажи что лежит на яндекс диске
|
|
110
|
+
найди на яндекс диске справку
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Такие запросы обрабатывает skill `personal-docs`. Они не требуют включать локальный режим `iola files mode`, потому что это не работа с файлами на ПК.
|
|
114
|
+
|
|
104
115
|
## Облако Mail.ru
|
|
105
116
|
|
|
106
117
|
Облако Mail.ru подключается через WebDAV.
|
|
@@ -114,6 +114,15 @@ iola geo services "Йошкар-Ола, улица Петрова, 15"
|
|
|
114
114
|
|
|
115
115
|
Сохранить ответ CLI, отчет, карточку учреждения или список ближайших объектов в `/IOLA`.
|
|
116
116
|
|
|
117
|
+
### cloud-create-folder
|
|
118
|
+
|
|
119
|
+
Создать папку на подключенном облачном диске.
|
|
120
|
+
|
|
121
|
+
Пример:
|
|
122
|
+
|
|
123
|
+
- `создай у меня на яндекс диске папку фото`;
|
|
124
|
+
- `создай папку документы в облаке`.
|
|
125
|
+
|
|
117
126
|
### cloud-share-link
|
|
118
127
|
|
|
119
128
|
Создать публичную ссылку на файл. В первом контуре поддерживается для Яндекс Диска.
|