formal-ai 0.53.0

Formal symbolic AI proof of concept with OpenAI-compatible APIs
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
(function (global) {
  "use strict";

  var DEFAULT_LANGUAGE = "en";
  var SUPPORTED_LANGUAGES = ["en", "ru", "zh", "hi"];
  var PUBLISHED_RUNTIME_SOURCE = "lino-i18n@0.0.1";
  var LOCAL_RUNTIME_SOURCE = "local-fallback";
  var runtimeEngine = null;

  // Flat catalog keys match lino-i18n's runtime lookup API and keep the web
  // build usable when the CDN dependency is unavailable.
  var CATALOG = {
    en: {
      "buttons.reportIssue": "Report issue",
      "buttons.reportMissingRule": "Report missing rule",
      "buttons.exportMemory": "Export memory",
      "buttons.importMemory": "Import memory",
      "buttons.diagnostics": "Diagnostics",
      "buttons.diagnosticsOn": "Diagnostics on",
      "buttons.agent": "Agent",
      "buttons.chat": "Chat",
      "buttons.demo": "Demo",
      "buttons.demoOn": "Demo on",
      "buttons.openMenu": "Open menu",
      "buttons.closeMenu": "Close menu",
      "titles.reportIssue":
        "Report issue - open a pre-filled GitHub issue with the current session transcript. See docs/upload-memory.md for how to attach the full memory export (Gist or .zip).",
      "titles.exportMemory":
        "Export memory - save the full agent state to formal-ai-memory.lino: the entire seed, UI preferences, environment metadata, and the append-only event log. See docs/upload-memory.md for attaching it to a GitHub issue (Gist or .zip).",
      "titles.importMemory":
        "Import memory - load a previous export. Accepts both the new full-memory bundle and the legacy demo_memory event-only log. Migration hints are shown next to this bar.",
      "titles.diagnosticsShow":
        "Show reasoning trace, intent, evidence, and thinking-steps panels.",
      "titles.diagnosticsHide":
        "Hide reasoning trace, intent, evidence, and thinking-steps panels.",
      "titles.agentOn": "Agent mode is on - switch back to single-turn chat.",
      "titles.agentOff":
        "Chat mode - switch to agent mode and each message will be decomposed into sequential steps and executed as a plan.",
      "titles.demoOn":
        "Demo is on - stop the scripted dialog and resume manual chat.",
      "titles.demoOff": "Start the scripted demo dialog.",
      "titles.menuOpen": "Open the side panel (conversations, prompts, tools).",
      "titles.menuClose":
        "Close the side panel (conversations, prompts, tools).",
      "composer.placeholder.chat": "Message formal-ai",
      "composer.placeholder.agent":
        "Describe a multi-step task (separate steps with ; or 'then')",
      "composer.demoHint.before": "Demo is running - tap ",
      "composer.demoHint.after": " to stop and type your own message.",
      "composer.send": "Send",
      "conversation.new": "+ New conversation",
      "conversation.empty": "Start a new conversation.",
      "conversation.emptyTitle": "(empty)",
      "conversation.messageCount": "{count} msg",
      "message.author.user": "You",
      "message.thinking": "Thinking",
      "fetch.collapse": "Collapse",
      "fetch.expand": "Expand",
      "fetch.openInNewTab": "Open in new tab",
      "fetch.frameTitle": "Fetched page: {url}",
      "memory.exportTriggered":
        "Triggered Export memory. Your browser is downloading `formal-ai-memory.lino`.",
      "memory.importTriggered":
        "Triggered Import memory. Pick a `.lino` file in the open dialog to restore the saved memory.",
      "sidebar.conversations": "Conversations",
      "sidebar.examplePrompts": "Example prompts",
      "sidebar.tools": "Tools",
      "sidebar.trace": "Trace",
      "status.demoPlaying": "Demo playing",
      "status.manual": "Manual mode",
      "status.nextDialogIn": "Next dialog in {seconds}s",
      "status.memoryUnavailable": "Memory unavailable",
      "status.memoryExported":
        "Exported full memory: {events} event(s) + {seedFiles} seed file(s)",
      "status.memoryImportedBundle":
        "Imported {inserted} event(s) from full bundle",
      "status.memoryImportedEvents": "Imported {inserted} events",
      "status.migration": "{headline}. Migration: {suggestions}",
      "status.exportFailed": "Export failed",
      "status.importFailed": "Import failed",
      "status.working": "Working",
      "toolMode.agent": "agent",
      "toolMode.thinking": "thinking",
      "trace.model": "Model",
      "trace.mode": "Mode",
      "trace.intent": "Intent",
      "trace.data": "Data",
      "trace.seedFiles": "Seed files",
      "trace.toolsLoaded": "Tools loaded",
      "trace.conceptsLoaded": "Concepts loaded",
    },
    ru: {
      "buttons.reportIssue": "Сообщить о проблеме",
      "buttons.reportMissingRule": "Сообщить о недостающем правиле",
      "buttons.exportMemory": "Экспорт памяти",
      "buttons.importMemory": "Импорт памяти",
      "buttons.diagnostics": "Диагностика",
      "buttons.diagnosticsOn": "Диагностика включена",
      "buttons.agent": "Агент",
      "buttons.chat": "Чат",
      "buttons.demo": "Демо",
      "buttons.demoOn": "Демо включено",
      "buttons.openMenu": "Открыть меню",
      "buttons.closeMenu": "Закрыть меню",
      "titles.reportIssue":
        "Сообщить о проблеме - откроет заранее заполненный GitHub issue с текущим диалогом. См. docs/upload-memory.md, чтобы прикрепить полный экспорт памяти (Gist или .zip).",
      "titles.exportMemory":
        "Экспорт памяти - сохраняет полное состояние агента в formal-ai-memory.lino: весь seed, настройки UI, метаданные окружения и append-only журнал событий. См. docs/upload-memory.md, чтобы прикрепить экспорт к GitHub issue (Gist или .zip).",
      "titles.importMemory":
        "Импорт памяти - загружает предыдущий экспорт. Поддерживает новый полный bundle памяти и устаревший журнал demo_memory только с событиями. Подсказки миграции появятся рядом с панелью.",
      "titles.diagnosticsShow":
        "Показать диагностическую трассировку, намерение, доказательства и шаги рассуждения.",
      "titles.diagnosticsHide":
        "Скрыть диагностическую трассировку, намерение, доказательства и шаги рассуждения.",
      "titles.agentOn": "Режим агента включен - вернуться к одиночному чату.",
      "titles.agentOff":
        "Режим чата - перейти в режим агента, где каждое сообщение разбивается на последовательные шаги и выполняется как план.",
      "titles.demoOn":
        "Демо включено - остановить сценарный диалог и вернуться к ручному чату.",
      "titles.demoOff": "Запустить сценарный демо-диалог.",
      "titles.menuOpen": "Открыть боковую панель (разговоры, запросы, инструменты).",
      "titles.menuClose": "Закрыть боковую панель (разговоры, запросы, инструменты).",
      "composer.placeholder.chat": "Сообщение formal-ai",
      "composer.placeholder.agent":
        "Опишите задачу из нескольких шагов (разделяйте шаги ; или «затем»)",
      "composer.demoHint.before": "Демо выполняется - нажмите ",
      "composer.demoHint.after": ", чтобы остановить и написать свое сообщение.",
      "composer.send": "Отправить",
      "conversation.new": "+ Новый разговор",
      "conversation.empty": "Начните новый разговор.",
      "conversation.emptyTitle": "(пусто)",
      "conversation.messageCount": "{count} сообщ.",
      "message.author.user": "Вы",
      "message.thinking": "Мышление",
      "fetch.collapse": "Свернуть",
      "fetch.expand": "Развернуть",
      "fetch.openInNewTab": "Открыть в новой вкладке",
      "fetch.frameTitle": "Полученная страница: {url}",
      "memory.exportTriggered":
        "Запущен экспорт памяти. Браузер скачивает `formal-ai-memory.lino`.",
      "memory.importTriggered":
        "Запущен импорт памяти. Выберите файл `.lino` в открытом диалоге, чтобы восстановить сохраненную память.",
      "sidebar.conversations": "Разговоры",
      "sidebar.examplePrompts": "Примеры запросов",
      "sidebar.tools": "Инструменты",
      "sidebar.trace": "Трассировка",
      "status.demoPlaying": "Демо выполняется",
      "status.manual": "Ручной режим",
      "status.nextDialogIn": "Следующий диалог через {seconds} с",
      "status.memoryUnavailable": "Память недоступна",
      "status.memoryExported":
        "Полный экспорт памяти: {events} событ. + {seedFiles} seed-файл(ов)",
      "status.memoryImportedBundle":
        "Импортировано {inserted} событ. из полного bundle",
      "status.memoryImportedEvents": "Импортировано событий: {inserted}",
      "status.migration": "{headline}. Миграция: {suggestions}",
      "status.exportFailed": "Экспорт не удался",
      "status.importFailed": "Импорт не удался",
      "status.working": "В работе",
      "toolMode.agent": "агент",
      "toolMode.thinking": "мышление",
      "trace.model": "Модель",
      "trace.mode": "Режим",
      "trace.intent": "Намерение",
      "trace.data": "Данные",
      "trace.seedFiles": "Файлы seed",
      "trace.toolsLoaded": "Инструментов загружено",
      "trace.conceptsLoaded": "Понятий загружено",
    },
    zh: {
      "buttons.reportIssue": "报告问题",
      "buttons.reportMissingRule": "报告缺失规则",
      "buttons.exportMemory": "导出记忆",
      "buttons.importMemory": "导入记忆",
      "buttons.diagnostics": "诊断",
      "buttons.diagnosticsOn": "诊断开启",
      "buttons.agent": "代理",
      "buttons.chat": "聊天",
      "buttons.demo": "演示",
      "buttons.demoOn": "演示开启",
      "buttons.openMenu": "打开菜单",
      "buttons.closeMenu": "关闭菜单",
      "titles.reportIssue":
        "报告问题 - 打开已预填当前会话记录的 GitHub issue。请参阅 docs/upload-memory.md,了解如何附加完整记忆导出(Gist 或 .zip)。",
      "titles.exportMemory":
        "导出记忆 - 将完整代理状态保存为 formal-ai-memory.lino:全部 seed、UI 偏好、环境元数据和追加式事件日志。请参阅 docs/upload-memory.md,了解如何附加到 GitHub issue(Gist 或 .zip)。",
      "titles.importMemory":
        "导入记忆 - 加载以前的导出。支持新的完整记忆 bundle 和旧版 demo_memory 事件日志。迁移提示会显示在此栏旁边。",
      "titles.diagnosticsShow": "显示推理跟踪、意图、证据和思考步骤面板。",
      "titles.diagnosticsHide": "隐藏推理跟踪、意图、证据和思考步骤面板。",
      "titles.agentOn": "代理模式已开启 - 切回单轮聊天。",
      "titles.agentOff":
        "聊天模式 - 切换到代理模式,每条消息会被拆成连续步骤并作为计划执行。",
      "titles.demoOn": "演示已开启 - 停止脚本对话并恢复手动聊天。",
      "titles.demoOff": "启动脚本演示对话。",
      "titles.menuOpen": "打开侧边面板(对话、提示、工具)。",
      "titles.menuClose": "关闭侧边面板(对话、提示、工具)。",
      "composer.placeholder.chat": "给 formal-ai 发消息",
      "composer.placeholder.agent": "描述多步骤任务(用 ; 或“然后”分隔步骤)",
      "composer.demoHint.before": "演示正在运行 - 点按 ",
      "composer.demoHint.after": " 可停止并输入自己的消息。",
      "composer.send": "发送",
      "conversation.new": "+ 新对话",
      "conversation.empty": "开始一个新对话。",
      "conversation.emptyTitle": "(空)",
      "conversation.messageCount": "{count} 条消息",
      "message.author.user": "",
      "message.thinking": "思考",
      "fetch.collapse": "折叠",
      "fetch.expand": "展开",
      "fetch.openInNewTab": "在新标签页打开",
      "fetch.frameTitle": "已获取页面:{url}",
      "memory.exportTriggered":
        "已触发导出记忆。浏览器正在下载 `formal-ai-memory.lino`。",
      "memory.importTriggered":
        "已触发导入记忆。请在打开的对话框中选择 `.lino` 文件来恢复保存的记忆。",
      "sidebar.conversations": "对话",
      "sidebar.examplePrompts": "示例提示",
      "sidebar.tools": "工具",
      "sidebar.trace": "跟踪",
      "status.demoPlaying": "演示播放中",
      "status.manual": "手动模式",
      "status.nextDialogIn": "{seconds} 秒后下一个对话",
      "status.memoryUnavailable": "记忆不可用",
      "status.memoryExported":
        "已导出完整记忆:{events} 个事件 + {seedFiles} 个 seed 文件",
      "status.memoryImportedBundle":
        "已从完整 bundle 导入 {inserted} 个事件",
      "status.memoryImportedEvents": "已导入 {inserted} 个事件",
      "status.migration": "{headline}。迁移:{suggestions}",
      "status.exportFailed": "导出失败",
      "status.importFailed": "导入失败",
      "status.working": "工作中",
      "toolMode.agent": "代理",
      "toolMode.thinking": "思考",
      "trace.model": "模型",
      "trace.mode": "模式",
      "trace.intent": "意图",
      "trace.data": "数据",
      "trace.seedFiles": "Seed 文件",
      "trace.toolsLoaded": "已加载工具",
      "trace.conceptsLoaded": "已加载概念",
    },
    hi: {
      "buttons.reportIssue": "समस्या रिपोर्ट करें",
      "buttons.reportMissingRule": "छूटा नियम रिपोर्ट करें",
      "buttons.exportMemory": "स्मृति निर्यात करें",
      "buttons.importMemory": "स्मृति आयात करें",
      "buttons.diagnostics": "निदान",
      "buttons.diagnosticsOn": "निदान चालू",
      "buttons.agent": "एजेंट",
      "buttons.chat": "चैट",
      "buttons.demo": "डेमो",
      "buttons.demoOn": "डेमो चालू",
      "buttons.openMenu": "मेन्यू खोलें",
      "buttons.closeMenu": "मेन्यू बंद करें",
      "titles.reportIssue":
        "समस्या रिपोर्ट करें - वर्तमान सत्र transcript के साथ पहले से भरा GitHub issue खोलें। पूरा memory export जोड़ने के लिए docs/upload-memory.md देखें (Gist या .zip)।",
      "titles.exportMemory":
        "स्मृति निर्यात करें - पूरे agent state को formal-ai-memory.lino में सेव करें: पूरा seed, UI preferences, environment metadata, और append-only event log. GitHub issue में जोड़ने के लिए docs/upload-memory.md देखें (Gist या .zip)।",
      "titles.importMemory":
        "स्मृति आयात करें - पिछला export load करें। नया full-memory bundle और legacy demo_memory event-only log दोनों स्वीकार हैं। Migration hints इसी bar के पास दिखेंगे।",
      "titles.diagnosticsShow":
        "reasoning trace, intent, evidence, और thinking-steps panels दिखाएं।",
      "titles.diagnosticsHide":
        "reasoning trace, intent, evidence, और thinking-steps panels छिपाएं।",
      "titles.agentOn": "एजेंट मोड चालू है - single-turn chat पर लौटें।",
      "titles.agentOff":
        "चैट मोड - एजेंट मोड पर जाएं, जहां हर संदेश sequential steps में टूटकर plan की तरह चलेगा।",
      "titles.demoOn":
        "डेमो चालू है - scripted dialog रोकें और manual chat फिर शुरू करें।",
      "titles.demoOff": "scripted demo dialog शुरू करें।",
      "titles.menuOpen": "side panel खोलें (बातचीत, prompts, tools)।",
      "titles.menuClose": "side panel बंद करें (बातचीत, prompts, tools)।",
      "composer.placeholder.chat": "formal-ai को संदेश",
      "composer.placeholder.agent":
        "कई चरणों वाला कार्य लिखें (चरणों को ; या 'then' से अलग करें)",
      "composer.demoHint.before": "डेमो चल रहा है - ",
      "composer.demoHint.after": " दबाकर रोकें और अपना संदेश लिखें।",
      "composer.send": "भेजें",
      "conversation.new": "+ नई बातचीत",
      "conversation.empty": "नई बातचीत शुरू करें।",
      "conversation.emptyTitle": "(खाली)",
      "conversation.messageCount": "{count} संदेश",
      "message.author.user": "आप",
      "message.thinking": "सोच",
      "fetch.collapse": "समेटें",
      "fetch.expand": "फैलाएं",
      "fetch.openInNewTab": "नए टैब में खोलें",
      "fetch.frameTitle": "लाई गई पेज: {url}",
      "memory.exportTriggered":
        "स्मृति निर्यात शुरू हुआ। आपका browser `formal-ai-memory.lino` डाउनलोड कर रहा है।",
      "memory.importTriggered":
        "स्मृति आयात शुरू हुआ। saved memory restore करने के लिए खुले dialog में `.lino` file चुनें।",
      "sidebar.conversations": "बातचीत",
      "sidebar.examplePrompts": "उदाहरण प्रॉम्प्ट",
      "sidebar.tools": "टूल",
      "sidebar.trace": "ट्रेस",
      "status.demoPlaying": "डेमो चल रहा है",
      "status.manual": "मैनुअल मोड",
      "status.nextDialogIn": "{seconds}s में अगला संवाद",
      "status.memoryUnavailable": "स्मृति उपलब्ध नहीं",
      "status.memoryExported":
        "पूरी स्मृति निर्यात हुई: {events} event(s) + {seedFiles} seed file(s)",
      "status.memoryImportedBundle":
        "full bundle से {inserted} event(s) आयात हुए",
      "status.memoryImportedEvents": "{inserted} events आयात हुए",
      "status.migration": "{headline}. Migration: {suggestions}",
      "status.exportFailed": "निर्यात विफल",
      "status.importFailed": "आयात विफल",
      "status.working": "काम जारी है",
      "toolMode.agent": "एजेंट",
      "toolMode.thinking": "सोच",
      "trace.model": "मॉडल",
      "trace.mode": "मोड",
      "trace.intent": "इरादा",
      "trace.data": "डेटा",
      "trace.seedFiles": "Seed फाइलें",
      "trace.toolsLoaded": "लोड किए गए टूल",
      "trace.conceptsLoaded": "लोड किए गए कॉन्सेप्ट",
    },
  };

  function normalizeLanguageTag(value) {
    var raw = String(value || "").toLowerCase().trim();
    if (!raw || raw === "auto") return "";
    var base = raw.split(/[-_]/)[0];
    return SUPPORTED_LANGUAGES.indexOf(base) >= 0 ? base : "";
  }

  function resolveLanguage(preference, candidates) {
    var explicit = normalizeLanguageTag(preference);
    if (explicit) return explicit;
    var list = Array.isArray(candidates) ? candidates : [candidates];
    for (var index = 0; index < list.length; index += 1) {
      var normalized = normalizeLanguageTag(list[index]);
      if (normalized) return normalized;
    }
    return DEFAULT_LANGUAGE;
  }

  function browserLanguages() {
    var nav = global.navigator || {};
    if (Array.isArray(nav.languages) && nav.languages.length > 0) {
      return nav.languages.slice();
    }
    return nav.language ? [nav.language] : [];
  }

  function detectLanguage(preference) {
    return resolveLanguage(preference, browserLanguages());
  }

  function interpolate(template, params) {
    var values = params || {};
    return String(template).replace(/\{([a-zA-Z0-9_]+)\}/g, function (_, key) {
      return values[key] === undefined || values[key] === null
        ? ""
        : String(values[key]);
    });
  }

  function localTranslate(key, language, params) {
    var lang = normalizeLanguageTag(language) || DEFAULT_LANGUAGE;
    var table = CATALOG[lang] || CATALOG[DEFAULT_LANGUAGE];
    var fallback = CATALOG[DEFAULT_LANGUAGE] || {};
    var value =
      Object.prototype.hasOwnProperty.call(table, key)
        ? table[key]
        : fallback[key];
    return interpolate(value || key, params);
  }

  function t(key, language, params) {
    var lang = normalizeLanguageTag(language) || DEFAULT_LANGUAGE;
    if (runtimeEngine && typeof runtimeEngine.t === "function") {
      try {
        return runtimeEngine.t(key, params || {}, {
          locale: lang,
          defaultValue: localTranslate(key, lang, params),
        });
      } catch (_error) {
        return localTranslate(key, lang, params);
      }
    }
    return localTranslate(key, lang, params);
  }

  function dispatchReady() {
    if (typeof global.dispatchEvent !== "function") return;
    try {
      if (typeof global.CustomEvent === "function") {
        global.dispatchEvent(
          new global.CustomEvent("formal-ai:i18n-ready", {
            detail: { source: api.ENGINE_SOURCE },
          }),
        );
      } else {
        global.dispatchEvent({ type: "formal-ai:i18n-ready" });
      }
    } catch (_error) {
      // Event dispatch is best-effort; the fallback translator is already live.
    }
  }

  function importModule(specifier) {
    try {
      return new Function("specifier", "return import(specifier);")(specifier);
    } catch (error) {
      return Promise.reject(error);
    }
  }

  function loadPublishedRuntime() {
    return importModule("lino-i18n")
      .then(function (module) {
        if (!module || typeof module.createI18n !== "function") {
          throw new Error("lino-i18n did not export createI18n");
        }
        runtimeEngine = module.createI18n({
          locales: CATALOG,
          defaultLocale: DEFAULT_LANGUAGE,
          fallback: [DEFAULT_LANGUAGE],
        });
        api.ENGINE_SOURCE = PUBLISHED_RUNTIME_SOURCE;
        api.lastError = null;
        dispatchReady();
        return api;
      })
      .catch(function (error) {
        runtimeEngine = null;
        api.ENGINE_SOURCE = LOCAL_RUNTIME_SOURCE;
        api.lastError = error && error.message ? error.message : String(error);
        dispatchReady();
        return api;
      });
  }

  var api = {
    DEFAULT_LANGUAGE: DEFAULT_LANGUAGE,
    SUPPORTED_LANGUAGES: SUPPORTED_LANGUAGES.slice(),
    CATALOG: CATALOG,
    ENGINE_SOURCE: LOCAL_RUNTIME_SOURCE,
    PUBLISHED_RUNTIME_SOURCE: PUBLISHED_RUNTIME_SOURCE,
    lastError: null,
    browserLanguages: browserLanguages,
    detectLanguage: detectLanguage,
    normalizeLanguageTag: normalizeLanguageTag,
    resolveLanguage: resolveLanguage,
    t: t,
    ready: Promise.resolve(null),
  };

  global.FormalAiI18n = api;
  api.ready = loadPublishedRuntime();
})(typeof window !== "undefined" ? window : globalThis);