@iola_adm/iola-cli 0.1.94 → 0.1.95

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/cli.js +46 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iola_adm/iola-cli",
3
- "version": "0.1.94",
3
+ "version": "0.1.95",
4
4
  "description": "CLI и AI-агент городского округа Йошкар-Ола.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/adm-iola/iola-cli#readme",
package/src/cli.js CHANGED
@@ -33,7 +33,7 @@ const LOCAL_CONFIG_FILE = path.join(PROJECT_IOLA_DIR, "local.json");
33
33
  const BROWSER_RUNTIME_DIR = path.join(CONFIG_DIR, "browser-runtime");
34
34
  const BROWSER_RUNTIME_PACKAGE = path.join(BROWSER_RUNTIME_DIR, "node_modules", "playwright", "package.json");
35
35
  const INDEXABLE_EXTENSIONS = /\.(md|txt|csv|json|html|docx|xlsx|pptx|pdf)$/i;
36
- const LOCAL_TOOLS = ["search_data", "search_entities", "resolve_entity_field", "get_card", "export_report", "file_read", "browser_open"];
36
+ const LOCAL_TOOLS = ["search_data", "search_entities", "resolve_entity_field", "get_card", "export_report", "file_read", "browser_open", "get_current_date"];
37
37
  const LEGACY_LOCAL_TOOLS = ["search_local", "export_data", "run_report", "save_view"];
38
38
  const FILE_TOOLS = ["files_tree", "files_read", "files_search", "files_write", "files_patch"];
39
39
  const ALL_LOCAL_TOOLS = [...LOCAL_TOOLS, ...FILE_TOOLS];
@@ -6436,6 +6436,11 @@ async function localToolAsk(question, providerConfig, options) {
6436
6436
  if (!options.quiet) console.log(guarded);
6437
6437
  return guarded;
6438
6438
  }
6439
+ const casualAnswer = buildCasualDirectAnswer(question);
6440
+ if (casualAnswer) {
6441
+ if (!options.quiet) console.log(casualAnswer);
6442
+ return casualAnswer;
6443
+ }
6439
6444
  await ensureLocalData();
6440
6445
  const plan = await buildLocalToolPlan(question, providerConfig, options);
6441
6446
  if (plan.directAnswer) {
@@ -6489,6 +6494,20 @@ function guardNonPublicQuestion(question) {
6489
6494
  return "";
6490
6495
  }
6491
6496
 
6497
+ function buildCasualDirectAnswer(question) {
6498
+ const normalized = String(question || "").toLocaleLowerCase("ru-RU").trim();
6499
+ if (/^(привет|здравствуй|здравствуйте|добрый день|доброе утро|добрый вечер|hi|hello|hey)([!.?\s]+(как дела|как ты|что нового)[?.!\s]*)?$/iu.test(normalized)) {
6500
+ return "Привет. Работаю нормально. Могу помочь с открытыми данными Йошкар-Олы: школами, детскими садами, адресами, телефонами, сайтами и ИНН.";
6501
+ }
6502
+ if (/^(как дела|как ты|что нового|ты тут|ты здесь)[?.!\s]*$/iu.test(normalized)) {
6503
+ return "Я на месте. Могу искать и проверять открытые городские данные.";
6504
+ }
6505
+ if (/^(спасибо|благодарю)[!.?\s]*$/iu.test(normalized)) {
6506
+ return "Пожалуйста.";
6507
+ }
6508
+ return "";
6509
+ }
6510
+
6492
6511
  function printToolPlan(plan) {
6493
6512
  console.log("План выполнения:");
6494
6513
  plan.steps.forEach((step, index) => {
@@ -6534,7 +6553,12 @@ async function buildLocalToolPlan(question, providerConfig, options) {
6534
6553
  function normalizeIolaRouterPlan(raw, question, options = {}) {
6535
6554
  const payload = typeof raw === "string" ? parseJsonObject(raw) : raw;
6536
6555
  if (payload.action === "tool_call") {
6537
- const tool = payload.tool === "get_entity_field" ? "resolve_entity_field" : payload.tool;
6556
+ const tool = normalizeIolaToolName(payload.tool);
6557
+ if (!availableToolNames(options).includes(tool)) {
6558
+ const casualAnswer = buildCasualDirectAnswer(question);
6559
+ if (casualAnswer) return { directAnswer: casualAnswer };
6560
+ return inferToolPlan(question, options);
6561
+ }
6538
6562
  return { steps: [{ tool, args: payload.args || {} }] };
6539
6563
  }
6540
6564
  if (payload.action === "direct_answer") {
@@ -6552,6 +6576,12 @@ function normalizeIolaRouterPlan(raw, question, options = {}) {
6552
6576
  throw new Error(`IOLA router вернул неподдерживаемое действие: ${payload.action || "unknown"}`);
6553
6577
  }
6554
6578
 
6579
+ function normalizeIolaToolName(tool) {
6580
+ if (tool === "get_entity_field") return "resolve_entity_field";
6581
+ if (tool === "current_date" || tool === "date_now" || tool === "today") return "get_current_date";
6582
+ return tool;
6583
+ }
6584
+
6555
6585
  function parseJsonObject(text) {
6556
6586
  const match = String(text).match(/\{[\s\S]*\}/);
6557
6587
  if (!match) throw new Error("JSON-план не найден.");
@@ -6704,6 +6734,9 @@ async function executeToolPlan(plan, options = {}) {
6704
6734
  const text = await runBrowserAutomation("text", { url: step.args?.url, waitMs: Number(step.args?.waitMs || 0), timeout: Number(step.args?.timeout || 30000), viewport: step.args?.viewport || "1366x768" });
6705
6735
  current = [{ url: step.args?.url, text }];
6706
6736
  outputs.push({ tool: step.tool, rows: 1 });
6737
+ } else if (step.tool === "get_current_date") {
6738
+ current = [getCurrentDateInfo()];
6739
+ outputs.push({ tool: step.tool, rows: current.length });
6707
6740
  } else if (String(step.tool || "").startsWith("mcp:")) {
6708
6741
  const result = await callConfiguredMcpTool(step.tool, step.args || {});
6709
6742
  current = Array.isArray(result) ? result : [result];
@@ -6742,6 +6775,16 @@ async function executeToolPlan(plan, options = {}) {
6742
6775
  return { rows: current, outputs };
6743
6776
  }
6744
6777
 
6778
+ function getCurrentDateInfo() {
6779
+ const now = new Date();
6780
+ return {
6781
+ name: "текущая дата",
6782
+ date: new Intl.DateTimeFormat("ru-RU", { dateStyle: "long" }).format(now),
6783
+ time: new Intl.DateTimeFormat("ru-RU", { timeStyle: "short" }).format(now),
6784
+ iso: now.toISOString(),
6785
+ };
6786
+ }
6787
+
6745
6788
  function getLocalMcpToolNames() {
6746
6789
  return mcpTools().map((tool) => `mcp:iola-local:${tool.name}`);
6747
6790
  }
@@ -6824,6 +6867,7 @@ function formatToolResult(result, options) {
6824
6867
  const name = row.entity.name || row.entity.inn || "организация";
6825
6868
  return `${name}: ${row.field} = ${row.value ?? "не указано"}`;
6826
6869
  }
6870
+ if (row.date && row.time) return `Сегодня ${row.date}, ${row.time}.`;
6827
6871
  return `${row.name || row.check || row.inn || "строка"}: ${row.address || row.phone || row.email || row.website || row.count || ""}`;
6828
6872
  }).join("\n");
6829
6873
  }