iobroker.assistant 1.0.2 → 1.0.3

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 (63) hide show
  1. package/README.md +3 -0
  2. package/admin/custom/.vite/manifest.json +91 -87
  3. package/admin/custom/assets/Components-C6qcpaRC.js +1 -0
  4. package/admin/custom/assets/{_virtual_mf-localSharedImportMap___mfe_internal__ConfigCustomAssistant__mf_owner__1-DcAGnE2z.js → _virtual_mf-localSharedImportMap___mfe_internal__ConfigCustomAssistant__mf_owner__1-A4gakomR.js} +1 -1
  5. package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__198531368674860__loadShare___mf_0_emotion_mf_1_react__loadShare__.js-CzBMxGFr.js → _virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__201375093093590__loadShare___mf_0_emotion_mf_1_react__loadShare__.js-BkH7fzDw.js} +1 -1
  6. package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__198531368674860__loadShare___mf_0_emotion_mf_1_styled__loadShare__.js-1XsLCK2M.js → _virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__201375093093590__loadShare___mf_0_emotion_mf_1_styled__loadShare__.js-CwqmfMvn.js} +1 -1
  7. package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__198531368674860__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-CMv8bcyA.js → _virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__201375093093590__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-BMuLYe6f.js} +80 -97
  8. package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__198531368674860__loadShare__shared-3mzaJWDF.js → _virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__201375093093590__loadShare__shared-BxjZmnpc.js} +2 -2
  9. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__201375093093590__prebuild___mf_0_iobroker_mf_1_json_mf_2_config__prebuild__-TM4l0OYm.js +122 -0
  10. package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__198531368674860__prebuild__react_mf_1_jsx_mf_2_runtime__prebuild__-B_v57Qfr.js → _virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__201375093093590__prebuild__react_mf_1_jsx_mf_2_runtime__prebuild__-M61rjtmp.js} +1 -1
  11. package/admin/custom/assets/{dist-DiU1y0R9.js → dist-B3E7IYuQ.js} +1 -1
  12. package/admin/custom/assets/helpers-DE61bb74.js +1 -0
  13. package/admin/custom/assets/{hostInit-MshDicd1.js → hostInit-4roC4hEj.js} +1 -1
  14. package/admin/custom/assets/{lib-DjwHKtRi.js → lib-CchzgTUs.js} +1 -1
  15. package/admin/custom/assets/{mf-entry-bootstrap-0-7c1ddf47.js → mf-entry-bootstrap-0-4806bbe4.js} +2 -2
  16. package/admin/custom/assets/{pendingShares-CaJDCKLB.js → pendingShares-DLlv8yFY.js} +2 -2
  17. package/admin/custom/assets/prod-ChPGnyiA.js +15 -0
  18. package/admin/custom/assets/rolldown-runtime-COiEfhsA.js +1 -0
  19. package/admin/custom/assets/utils-Bi7ATSfV.js +4 -0
  20. package/admin/custom/customComponents.js +2 -2
  21. package/admin/custom/i18n/de.json +25 -0
  22. package/admin/custom/i18n/en.json +25 -0
  23. package/admin/custom/i18n/es.json +25 -0
  24. package/admin/custom/i18n/fr.json +25 -0
  25. package/admin/custom/i18n/it.json +25 -0
  26. package/admin/custom/i18n/nl.json +25 -0
  27. package/admin/custom/i18n/pl.json +25 -0
  28. package/admin/custom/i18n/pt.json +25 -0
  29. package/admin/custom/i18n/ru.json +25 -0
  30. package/admin/custom/i18n/uk.json +25 -0
  31. package/admin/custom/i18n/zh-cn.json +25 -0
  32. package/admin/custom/index.html +2 -2
  33. package/admin/custom/mf-manifest.json +1 -1
  34. package/admin/custom/mf-stats.json +1 -1
  35. package/admin/i18n/de.json +3 -1
  36. package/admin/i18n/en.json +3 -1
  37. package/admin/i18n/es.json +3 -1
  38. package/admin/i18n/fr.json +3 -1
  39. package/admin/i18n/it.json +3 -1
  40. package/admin/i18n/nl.json +3 -1
  41. package/admin/i18n/pl.json +3 -1
  42. package/admin/i18n/pt.json +3 -1
  43. package/admin/i18n/ru.json +3 -1
  44. package/admin/i18n/uk.json +3 -1
  45. package/admin/i18n/zh-cn.json +3 -1
  46. package/admin/jsonConfig.json +13 -0
  47. package/build/lib/journal.js +273 -0
  48. package/build/lib/journal.js.map +1 -0
  49. package/build/lib/voice/esphome.js +9 -1
  50. package/build/lib/voice/esphome.js.map +1 -1
  51. package/build/lib/voice/voiceServer.js +3 -1
  52. package/build/lib/voice/voiceServer.js.map +1 -1
  53. package/build/lib/voice/wyoming.js +3 -1
  54. package/build/lib/voice/wyoming.js.map +1 -1
  55. package/build/main.js +146 -12
  56. package/build/main.js.map +1 -1
  57. package/io-package.json +36 -1
  58. package/package.json +7 -7
  59. package/admin/custom/assets/Components-7BDDNrGP.js +0 -1
  60. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__198531368674860__prebuild___mf_0_iobroker_mf_1_json_mf_2_config__prebuild__-DS8oaQQt.js +0 -122
  61. package/admin/custom/assets/helpers-Dot7vgQQ.js +0 -1
  62. package/admin/custom/assets/rolldown-runtime-Dd_uD5pT.js +0 -1
  63. package/admin/custom/assets/utils-towTPKqG.js +0 -4
package/build/main.js CHANGED
@@ -46,6 +46,7 @@ const timers_1 = require("./lib/timers");
46
46
  const alarms_1 = require("./lib/alarms");
47
47
  const memory_1 = require("./lib/memory");
48
48
  const weather_1 = require("./lib/weather");
49
+ const journal_1 = require("./lib/journal");
49
50
  const localLlm_1 = require("./lib/localLlm");
50
51
  const credentials_1 = require("./lib/credentials");
51
52
  const context_1 = require("./lib/context");
@@ -187,6 +188,8 @@ class Assistant extends adapter_core_1.Adapter {
187
188
  /** Set once `onReady` initialised the pipeline — with or without a cloud {@link agent}. */
188
189
  ready = false;
189
190
  mcp = null;
191
+ /** Who asked what and how it was answered (admin chat); null until `onReady` read the config. */
192
+ journal = null;
190
193
  /** Short-TTL cache for the expensive device/room/function listings; invalidated on enum changes. */
191
194
  listCache = null;
192
195
  /** Cache of a `<base>.SET` level state id → its writable boolean sibling switch (`<base>.ON_SET`/`.ON`), or ''. */
@@ -270,6 +273,7 @@ class Assistant extends adapter_core_1.Adapter {
270
273
  const provider = cfg.provider || 'openai';
271
274
  const localOnly = provider === 'none';
272
275
  const apiKey = localOnly ? '' : (0, llm_1.effectiveApiKey)(cfg.provider, await (0, credentials_1.resolveApiKey)(this, cfg));
276
+ await this.setupJournal();
273
277
  if (!localOnly && !apiKey) {
274
278
  this.log.warn(cfg.credentialType === 'manager'
275
279
  ? 'No credential selected (manager mode) — pick an API-key credential in the adapter settings.'
@@ -278,12 +282,12 @@ class Assistant extends adapter_core_1.Adapter {
278
282
  return;
279
283
  }
280
284
  try {
281
- this.mcp = await (0, mcp_server_1.createInProcessMcp)({
285
+ this.mcp = this.journalMcp(await (0, mcp_server_1.createInProcessMcp)({
282
286
  adapter: this,
283
287
  language: this.language,
284
288
  allowSetState: cfg.allowWriteStates,
285
289
  allowObjectChange: cfg.allowObjectChange,
286
- });
290
+ }));
287
291
  this.listCache = new tools_1.ListCache();
288
292
  const { tools, denied } = await (0, tools_1.buildMcpTools)(this.mcp, cfg, this.listCache, (id, fb) => this.resolveDeviceName(id, fb));
289
293
  // Let the cloud LLM handle timers/alarms too (for phrasings the rule-based NLU misses).
@@ -314,7 +318,7 @@ class Assistant extends adapter_core_1.Adapter {
314
318
  baseUrl: prov.baseUrl,
315
319
  systemPrompt: cfg.systemPrompt || '',
316
320
  maxTokens: cfg.maxTokens || 1024,
317
- tools,
321
+ tools: tools.map(t => this.journalTool(t)),
318
322
  log: this.log,
319
323
  });
320
324
  }
@@ -403,7 +407,7 @@ class Assistant extends adapter_core_1.Adapter {
403
407
  language,
404
408
  stt,
405
409
  tts,
406
- answer: question => this.answer(question, 'wyoming'),
410
+ answer: (question, sttMs) => this.answer(question, 'wyoming', { transport: 'wyoming', sttMs }),
407
411
  getHints: () => this.buildSttHints(),
408
412
  log: this.log,
409
413
  });
@@ -463,7 +467,12 @@ class Assistant extends adapter_core_1.Adapter {
463
467
  language,
464
468
  stt,
465
469
  tts,
466
- answer: (question, origin) => this.answerVoice(question, origin.device),
470
+ answer: (question, origin) => this.answerVoice(question, origin.device, {
471
+ transport: 'esphome',
472
+ room: origin.room,
473
+ wakeWord: origin.wakeWord,
474
+ sttMs: origin.sttMs,
475
+ }),
467
476
  getHints: () => this.buildSttHints(),
468
477
  media: this.media,
469
478
  mediaHost: (cfg.esphomeMediaHost || '').trim(),
@@ -536,7 +545,7 @@ class Assistant extends adapter_core_1.Adapter {
536
545
  language,
537
546
  stt,
538
547
  tts,
539
- answer: (question, ctx) => this.answerVoice(question, ctx.device),
548
+ answer: (question, ctx) => this.answerVoice(question, ctx.device, { transport: 'udp', room: ctx.room, sttMs: ctx.sttMs }),
540
549
  getHints: () => this.buildSttHints(),
541
550
  log: this.log,
542
551
  onStatus: (device, room, state) => {
@@ -586,11 +595,11 @@ class Assistant extends adapter_core_1.Adapter {
586
595
  * not re-trigger onStateChange). The state writes must not block the spoken reply, so they are
587
596
  * fire-and-forget.
588
597
  */
589
- async answerVoice(question, source) {
598
+ async answerVoice(question, source, origin = {}) {
590
599
  this.setStateAsync('text.request', { val: question, ack: true }).catch(() => { });
591
600
  this.setQuerySource(source);
592
601
  this.log.info(`Voice Q (${source}): ${question}`);
593
- const answer = await this.answer(question, source);
602
+ const answer = await this.answer(question, source, { satellite: source, ...origin });
594
603
  this.log.info(`Voice A (${source}): ${answer}`);
595
604
  this.setStateAsync('text.response', { val: answer, ack: true }).catch(() => { });
596
605
  return answer;
@@ -659,11 +668,17 @@ class Assistant extends adapter_core_1.Adapter {
659
668
  pcm = pcm.subarray(44);
660
669
  }
661
670
  const language = msg.language || engines.language;
671
+ const sttStart = Date.now();
662
672
  const text = (await engines.stt.transcribe(pcm, rate, language, await this.buildSttHints())).trim();
663
673
  if (!text) {
664
674
  return { text: '', answer: '' };
665
675
  }
666
- const answer = await this.answerVoice(text, source);
676
+ const answer = await this.answerVoice(text, source, {
677
+ transport: 'native',
678
+ room,
679
+ wakeWord: typeof msg.wakeWord === 'string' ? msg.wakeWord : undefined,
680
+ sttMs: Date.now() - sttStart,
681
+ });
667
682
  if (!answer) {
668
683
  return { text, answer: '' };
669
684
  }
@@ -2146,6 +2161,24 @@ class Assistant extends adapter_core_1.Adapter {
2146
2161
  }
2147
2162
  return;
2148
2163
  }
2164
+ // Admin chat: the journal of the last hours (message = { since?: ms }), and wiping it.
2165
+ if (obj.command === 'getJournal') {
2166
+ const since = Number(obj.message?.since) || 0;
2167
+ const result = this.journal?.enabled
2168
+ ? { enabled: true, entries: this.journal.list(since) }
2169
+ : { enabled: false, entries: [] };
2170
+ if (obj.callback) {
2171
+ this.sendTo(obj.from, obj.command, result, obj.callback);
2172
+ }
2173
+ return;
2174
+ }
2175
+ if (obj.command === 'clearJournal') {
2176
+ this.journal?.clear();
2177
+ if (obj.callback) {
2178
+ this.sendTo(obj.from, obj.command, { ok: true }, obj.callback);
2179
+ }
2180
+ return;
2181
+ }
2149
2182
  if (obj.command !== 'ask') {
2150
2183
  return;
2151
2184
  }
@@ -2168,13 +2201,14 @@ class Assistant extends adapter_core_1.Adapter {
2168
2201
  this.log.info(`A: ${answer}`);
2169
2202
  this.setStateAsync('text.response', { val: answer, ack: true }).catch(() => { });
2170
2203
  if (obj.callback) {
2171
- this.sendTo(obj.from, obj.command, { answer }, obj.callback);
2204
+ // `journaled`: the admin chat gets this exchange from the journal and must not add it twice.
2205
+ this.sendTo(obj.from, obj.command, { answer, journaled: !!this.journal?.enabled }, obj.callback);
2172
2206
  }
2173
2207
  }
2174
2208
  catch (e) {
2175
2209
  this.log.error(`Assistant error: ${e.message}`);
2176
2210
  if (obj.callback) {
2177
- this.sendTo(obj.from, obj.command, { error: e.message }, obj.callback);
2211
+ this.sendTo(obj.from, obj.command, { error: e.message, journaled: !!this.journal?.enabled }, obj.callback);
2178
2212
  }
2179
2213
  }
2180
2214
  }
@@ -2187,7 +2221,12 @@ class Assistant extends adapter_core_1.Adapter {
2187
2221
  * is applied to the cloud LLM tier; every completed exchange (whichever tier answered) is recorded so
2188
2222
  * later turns have the full thread.
2189
2223
  */
2190
- async answer(question, source = '') {
2224
+ answer(question, source = '', origin = {}) {
2225
+ return this.journal
2226
+ ? this.journal.run(question, source, origin, () => this.answerTracked(question, source))
2227
+ : this.answerTracked(question, source);
2228
+ }
2229
+ async answerTracked(question, source) {
2191
2230
  const useCtx = this.config.useConversationContext !== false;
2192
2231
  const history = useCtx ? this.context.get(source) : [];
2193
2232
  const raw = await this.produceAnswer(question, history, source);
@@ -2195,6 +2234,9 @@ class Assistant extends adapter_core_1.Adapter {
2195
2234
  // (see followUpHint). Strip it here so it's neither stored, shown nor spoken, and expose it as the
2196
2235
  // follow-up flag. Single-user voice → a shared field is race-free enough (read right after await).
2197
2236
  this.lastFollowUp = /\[\[LISTEN\]\]/i.test(raw);
2237
+ if (this.lastFollowUp) {
2238
+ this.journal?.note({ followUp: true });
2239
+ }
2198
2240
  const result = raw.replace(/\s*\[\[LISTEN\]\]\s*/gi, ' ').trim();
2199
2241
  if (useCtx && result) {
2200
2242
  this.context.add(source, question, result);
@@ -2278,6 +2320,7 @@ class Assistant extends adapter_core_1.Adapter {
2278
2320
  if (this.rings.length && (0, nlu_1.isStopCommand)(question)) {
2279
2321
  const n = this.stopRinging();
2280
2322
  this.log.info(`Ring stopped by voice (${n} session(s)).`);
2323
+ this.journal?.note({ tier: 'stop' });
2281
2324
  const lang = String(this.config.voiceLanguage || this.language || 'en');
2282
2325
  return lang === 'ru' ? 'Хорошо.' : lang === 'de' ? 'Ok.' : 'Okay.';
2283
2326
  }
@@ -2288,6 +2331,7 @@ class Assistant extends adapter_core_1.Adapter {
2288
2331
  const asked = this.pending.question(source);
2289
2332
  if (this.pending.deliver(source, question)) {
2290
2333
  this.log.info(`Answer to "${asked}" from source '${source || 'any'}': ${question}`);
2334
+ this.journal?.note({ tier: 'askReply', detail: asked || undefined });
2291
2335
  return '';
2292
2336
  }
2293
2337
  }
@@ -2297,6 +2341,7 @@ class Assistant extends adapter_core_1.Adapter {
2297
2341
  const routine = (0, routines_1.matchRoutine)(question, this.routines);
2298
2342
  if (routine) {
2299
2343
  this.log.info(`Routine '${routine.name}' triggered (source='${source}').`);
2344
+ this.journal?.note({ tier: 'routine', detail: routine.name });
2300
2345
  await this.runRoutine(routine, source);
2301
2346
  return routine.reply;
2302
2347
  }
@@ -2330,6 +2375,7 @@ class Assistant extends adapter_core_1.Adapter {
2330
2375
  const ans = await this.localLlm.ask(facts ? `${facts}\n\n${question}` : question);
2331
2376
  if (ans && !(0, localLlm_1.isHandoff)(ans)) {
2332
2377
  this.log.info(`Answered by local LLM (source='${source}').`);
2378
+ this.journal?.note({ tier: 'localLlm', detail: this.localLlmName() });
2333
2379
  return ans;
2334
2380
  }
2335
2381
  this.log.debug('Local LLM handed off to the cloud LLM.');
@@ -2347,6 +2393,7 @@ class Assistant extends adapter_core_1.Adapter {
2347
2393
  // Provider "none": no tier further down. Say so instead of failing — over voice an error is
2348
2394
  // read out as a technical message.
2349
2395
  this.log.info(`No local tier could answer and no LLM provider is configured (source='${source}').`);
2396
+ this.journal?.note({ tier: 'none' });
2350
2397
  return this.localOnlyFallback();
2351
2398
  }
2352
2399
  const ctx = await this.buildDeviceContext();
@@ -2359,6 +2406,10 @@ class Assistant extends adapter_core_1.Adapter {
2359
2406
  // Prepend the current date/time (and the weather line, if a source is configured) to the user turn —
2360
2407
  // cache-safe, see buildTimeContext. The stored history keeps the untouched question.
2361
2408
  const questionForLlm = [this.buildTimeContext(), weather, question].filter(Boolean).join('\n\n');
2409
+ this.journal?.note({
2410
+ tier: 'cloud',
2411
+ detail: `${this.config.provider || 'openai'} · ${this.agent.model || 'auto'}`,
2412
+ });
2362
2413
  return this.agent.ask(questionForLlm, sys, history);
2363
2414
  }
2364
2415
  /** Reply when nothing local understood the request and there is no cloud LLM (provider "none"). */
@@ -2431,6 +2482,81 @@ class Assistant extends adapter_core_1.Adapter {
2431
2482
  }
2432
2483
  api.registerUsedResource(type, data).catch(e => this.log.debug(`could not register ${type} ${port}: ${e.message}`));
2433
2484
  }
2485
+ /**
2486
+ * Open the conversation journal (shown in the admin chat). Every new or finished entry is mirrored to
2487
+ * `journal.last` as JSON — the chat subscribes to it, which is what makes the view live.
2488
+ */
2489
+ async setupJournal() {
2490
+ const hours = Math.max(0, Math.min(168, Number(this.config.journalHours ?? 24) || 0));
2491
+ const file = path.join(this.instanceDataDir(), 'journal.json');
2492
+ // Also in io-package `instanceObjects`; created here for instances that predate it.
2493
+ await this.setObjectNotExistsAsync('journal', {
2494
+ type: 'channel',
2495
+ common: { name: 'Conversation journal' },
2496
+ native: {},
2497
+ });
2498
+ await this.setObjectNotExistsAsync('journal.last', {
2499
+ type: 'state',
2500
+ common: {
2501
+ name: 'Latest journal entry (JSON; written when a request starts and when it is answered)',
2502
+ type: 'string',
2503
+ role: 'json',
2504
+ read: true,
2505
+ write: false,
2506
+ def: '',
2507
+ },
2508
+ native: {},
2509
+ });
2510
+ this.journal = new journal_1.Journal({
2511
+ hours,
2512
+ file,
2513
+ log: this.log,
2514
+ onChange: entry => {
2515
+ this.setStateAsync('journal.last', { val: JSON.stringify(entry), ack: true }).catch(() => { });
2516
+ },
2517
+ });
2518
+ if (hours) {
2519
+ await this.journal.load();
2520
+ }
2521
+ else {
2522
+ // Switched off: do not keep what was recorded while it was on.
2523
+ await fs.promises.rm(file, { force: true }).catch(() => { });
2524
+ }
2525
+ }
2526
+ /** Wrap the MCP connection so every state the pipeline reads or writes lands in the journal entry. */
2527
+ journalMcp(mcp) {
2528
+ return {
2529
+ listTools: () => mcp.listTools(),
2530
+ callTool: (name, args) => {
2531
+ this.journal?.stateAccess(name, args);
2532
+ return mcp.callTool(name, args);
2533
+ },
2534
+ close: () => mcp.close(),
2535
+ };
2536
+ }
2537
+ /** Wrap an LLM tool so its calls (arguments, result, duration) land in the journal entry. */
2538
+ journalTool(tool) {
2539
+ return {
2540
+ ...tool,
2541
+ run: async (args) => {
2542
+ const start = Date.now();
2543
+ try {
2544
+ const result = await tool.run(args);
2545
+ this.journal?.tool(tool.name, args, Date.now() - start, result);
2546
+ return result;
2547
+ }
2548
+ catch (e) {
2549
+ this.journal?.tool(tool.name, args, Date.now() - start, undefined, e.message);
2550
+ throw e;
2551
+ }
2552
+ },
2553
+ };
2554
+ }
2555
+ /** Short name of the local model for the journal ("qwen2.5-1.5b-instruct-q4_k_m"). */
2556
+ localLlmName() {
2557
+ const url = (this.config.localLlmModelUrl || '').trim() || localLlm_1.DEFAULT_LOCAL_MODEL_URL;
2558
+ return (url.split(/[/\\]/).pop() || url).replace(/\?.*$/, '').replace(/\.gguf$/i, '');
2559
+ }
2434
2560
  /** Writable per-instance data dir via the adapter-core function (with a fallback for old runtimes). */
2435
2561
  instanceDataDir() {
2436
2562
  try {
@@ -2559,6 +2685,7 @@ class Assistant extends adapter_core_1.Adapter {
2559
2685
  if (!intents.length || !intents.every(i => this.canExecuteNlu(i, devices.length))) {
2560
2686
  return null; // nothing matched, or one part cannot run here → let the LLM answer the whole thing
2561
2687
  }
2688
+ this.journal?.note({ tier: 'nlu', detail: intents.map(i => i.action).join(' + ') });
2562
2689
  const answers = [];
2563
2690
  let failed = false;
2564
2691
  for (const intent of intents) {
@@ -4153,6 +4280,7 @@ class Assistant extends adapter_core_1.Adapter {
4153
4280
  }
4154
4281
  try {
4155
4282
  await this.setForeignStateAsync(write.id, { val: write.value, ack: false });
4283
+ this.journal?.stateAccess('set_state', { id: write.id, value: write.value });
4156
4284
  this.log.info(`trigger '${def.id}': ${write.id} = ${JSON.stringify(write.value)}`);
4157
4285
  }
4158
4286
  catch (e) {
@@ -4888,6 +5016,12 @@ class Assistant extends adapter_core_1.Adapter {
4888
5016
  catch {
4889
5017
  // ignore
4890
5018
  }
5019
+ try {
5020
+ await this.journal?.flush();
5021
+ }
5022
+ catch {
5023
+ // ignore
5024
+ }
4891
5025
  try {
4892
5026
  await this.mcp?.close();
4893
5027
  }