opencami 1.8.6 → 1.8.8

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 (89) hide show
  1. package/README.md +0 -1
  2. package/dist/client/assets/{CSPContext-6t3O1emU.js → CSPContext-nHSyQniZ.js} +1 -1
  3. package/dist/client/assets/{DirectionContext-C6goXEY_.js → DirectionContext-B1cuzwIr.js} +1 -1
  4. package/dist/client/assets/_sessionKey-CNw4O2rY.js +19 -0
  5. package/dist/client/assets/agents-C6Ev94B1.js +2 -0
  6. package/dist/client/assets/agents-screen-DpNSh5Ok.js +1 -0
  7. package/dist/client/assets/bots-B2_u-OmP.js +2 -0
  8. package/dist/client/assets/bots-screen-Qh_IK9hC.js +1 -0
  9. package/dist/client/assets/button-DdG8c-XQ.js +1 -0
  10. package/dist/client/assets/{composite-feK0c-xF.js → composite-Cx-QHT9o.js} +1 -1
  11. package/dist/client/assets/{connect-02tmQV_v.js → connect-CSbeSBTn.js} +1 -1
  12. package/dist/client/assets/{dashboard-DQ0zDQKd.js → dashboard-DA1fTRcH.js} +1 -1
  13. package/dist/client/assets/event-Dwf9IDxK.js +1 -0
  14. package/dist/client/assets/file-explorer-screen-DzDX4HcB.js +1 -0
  15. package/dist/client/assets/files-PsZnGOUx.js +2 -0
  16. package/dist/client/assets/follow-up-suggestions-BYWq-d8P.js +5 -0
  17. package/dist/client/assets/{index-lK3yGoTI.js → index-B551ln24.js} +1 -1
  18. package/dist/client/assets/index-BxsgifDH.js +3 -0
  19. package/dist/client/assets/keyboard-shortcuts-dialog-BX-hH4Wf.js +1 -0
  20. package/dist/client/assets/main-DBmooBKx.js +210 -0
  21. package/dist/client/assets/markdown-Bpat4kTr.js +87 -0
  22. package/dist/client/assets/memory-Bs8hOoEv.js +2 -0
  23. package/dist/client/assets/memory-screen-1DgDLyZf.js +1 -0
  24. package/dist/client/assets/menu-ByR1BVmq.js +1 -0
  25. package/dist/client/assets/{opencami-logo-zuSBm5Br.js → opencami-logo-BV1uPYe6.js} +1 -1
  26. package/dist/client/assets/popupStateMapping-CGDLUl5Y.js +1 -0
  27. package/dist/client/assets/proxy-DYrSkM35.js +9 -0
  28. package/dist/client/assets/{react-BLyCEWpN.js → react-dSDkXQu6.js} +1 -1
  29. package/dist/client/assets/search-dialog-B3XJLq-O.js +1 -0
  30. package/dist/client/assets/search-sources-badge-CTd0gLuz.js +1 -0
  31. package/dist/client/assets/session-export-dialog-Cib97JLm.js +1 -0
  32. package/dist/client/assets/settings-dialog-B4NLq1ZS.js +1 -0
  33. package/dist/client/assets/{skills-panel-BH27r3nC.js → skills-panel-Cj7yHGbX.js} +1 -1
  34. package/dist/client/assets/skills-pueagQNc.js +2 -0
  35. package/dist/client/assets/styles-Ce2xZzc4.css +1 -0
  36. package/dist/client/assets/switch-kXs1I0oW.js +1 -0
  37. package/dist/client/assets/tabs-B6GW7TBf.js +1 -0
  38. package/dist/client/assets/thinking-DTP9JDQl.js +1 -0
  39. package/dist/client/assets/tooltip-CtHpm-sQ.js +1 -0
  40. package/dist/client/assets/use-file-explorer-state-C-D2CShe.js +12 -0
  41. package/dist/client/assets/{useBaseUiId-MgM4ouhx.js → useBaseUiId-Ckx_aJky.js} +1 -1
  42. package/dist/client/assets/useCompositeItem-CkvfeGmG.js +1 -0
  43. package/dist/client/assets/{useControlled-BQxTgsOd.js → useControlled-8D4PSDAL.js} +1 -1
  44. package/dist/client/assets/{useMutation-12DyB3Ox.js → useMutation-DckvFKPC.js} +1 -1
  45. package/dist/client/assets/{useQuery-Ctiljcrr.js → useQuery-CtUiG53w.js} +1 -1
  46. package/dist/server/assets/{_sessionKey-DzsJfprr.js → _sessionKey-LV6xK9IM.js} +548 -947
  47. package/dist/server/assets/{_tanstack-start-manifest_v-C5HBDfQB.js → _tanstack-start-manifest_v-qVhiIEVc.js} +1 -1
  48. package/dist/server/assets/{connect-CbgijWz4.js → connect-BNabuqpW.js} +1 -1
  49. package/dist/server/assets/follow-up-suggestions-CSSc4PDe.js +336 -0
  50. package/dist/server/assets/{index-Dl2BOKP7.js → index-BEWnDAH6.js} +24 -5
  51. package/dist/server/assets/{index-BFHEmXpN.js → index-DMKS4aeI.js} +1 -1
  52. package/dist/server/assets/{markdown-BFE5y9YH.js → markdown-DoX5Q7qh.js} +50 -26
  53. package/dist/server/assets/{memory-BqZOoD7Q.js → memory-Cxu7i8ej.js} +1 -1
  54. package/dist/server/assets/{memory-screen-BK5phS8K.js → memory-screen-B5l1NZRY.js} +2 -2
  55. package/dist/server/assets/{router-BZPatFG9.js → router-Cr2xCvGA.js} +5 -5
  56. package/dist/server/assets/{search-dialog-DQRkARXw.js → search-dialog-DR6zBnui.js} +4 -4
  57. package/dist/server/assets/search-sources-badge-B0rAEDs_.js +106 -0
  58. package/dist/server/assets/{settings-dialog-Bc1ta26X.js → settings-dialog-DEMlCMCP.js} +4 -4
  59. package/dist/server/assets/thinking-BpAc3itF.js +92 -0
  60. package/dist/server/server.js +38 -195
  61. package/package.json +2 -6
  62. package/dist/client/assets/_sessionKey-B5Viv43f.js +0 -23
  63. package/dist/client/assets/agents-BmE6QOwl.js +0 -2
  64. package/dist/client/assets/agents-screen-pHUzJxX5.js +0 -1
  65. package/dist/client/assets/bots-BeOkwrXr.js +0 -2
  66. package/dist/client/assets/bots-screen-B79bAYvf.js +0 -1
  67. package/dist/client/assets/button-CK8tKQ-Z.js +0 -1
  68. package/dist/client/assets/event-BsD1rqGT.js +0 -1
  69. package/dist/client/assets/file-explorer-screen-Ds7LeJTd.js +0 -1
  70. package/dist/client/assets/files-e40B1zFy.js +0 -2
  71. package/dist/client/assets/index-rljDU_1M.js +0 -3
  72. package/dist/client/assets/keyboard-shortcuts-dialog-Bb_GOr9L.js +0 -1
  73. package/dist/client/assets/main-Dq6jpr6-.js +0 -210
  74. package/dist/client/assets/markdown-C7_Aipwd.js +0 -87
  75. package/dist/client/assets/memory-C7UG-1le.js +0 -2
  76. package/dist/client/assets/memory-screen-CUFBWsq5.js +0 -1
  77. package/dist/client/assets/menu-n6L--M9R.js +0 -1
  78. package/dist/client/assets/proxy-BU8Bw1Vt.js +0 -9
  79. package/dist/client/assets/search-dialog-yB4w5ajo.js +0 -1
  80. package/dist/client/assets/session-export-dialog-qbZgd2Zo.js +0 -1
  81. package/dist/client/assets/settings-dialog-CHJbvpgk.js +0 -1
  82. package/dist/client/assets/skills-DoKPPhNY.js +0 -2
  83. package/dist/client/assets/styles-CXV5jZiD.css +0 -1
  84. package/dist/client/assets/switch-BD3a0LRm.js +0 -1
  85. package/dist/client/assets/tabs-DI1e-kzz.js +0 -1
  86. package/dist/client/assets/tooltip-BbH3QWvK.js +0 -1
  87. package/dist/client/assets/use-file-explorer-state-DBfLeAyz.js +0 -12
  88. package/dist/client/assets/useCompositeItem-OhltNFdZ.js +0 -1
  89. package/dist/client/assets/useOnFirstRender-7qoaK5sI.js +0 -1
@@ -1,4 +1,4 @@
1
- const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "/root/opencami/src/routes/__root.tsx", "children": ["/", "/agents", "/bots", "/connect", "/dashboard", "/files", "/memory", "/new", "/skills", "/api/agents", "/api/cron", "/api/follow-ups", "/api/history", "/api/llm-features", "/api/models", "/api/paths", "/api/personas", "/api/ping", "/api/send", "/api/sessions", "/api/skills", "/api/stream", "/api/stt", "/api/tts", "/chat/$sessionKey", "/api/dashboard/crons", "/api/dashboard/gateway", "/api/dashboard/system", "/api/files/delete", "/api/files/download", "/api/files/info", "/api/files/list", "/api/files/mkdir", "/api/files/read", "/api/files/rename", "/api/files/save", "/api/files/upload"], "preloads": ["/assets/main-Dq6jpr6-.js"], "assets": [] }, "/": { "filePath": "/root/opencami/src/routes/index.tsx", "assets": [], "preloads": ["/assets/index-lK3yGoTI.js"] }, "/agents": { "filePath": "/root/opencami/src/routes/agents.tsx", "assets": [], "preloads": ["/assets/agents-BmE6QOwl.js"] }, "/bots": { "filePath": "/root/opencami/src/routes/bots.tsx", "assets": [], "preloads": ["/assets/bots-BeOkwrXr.js"] }, "/connect": { "filePath": "/root/opencami/src/routes/connect.tsx", "assets": [], "preloads": ["/assets/connect-02tmQV_v.js", "/assets/index-rljDU_1M.js", "/assets/button-CK8tKQ-Z.js", "/assets/react-BLyCEWpN.js"] }, "/dashboard": { "filePath": "/root/opencami/src/routes/dashboard.tsx", "assets": [], "preloads": ["/assets/dashboard-DQ0zDQKd.js", "/assets/useQuery-Ctiljcrr.js"] }, "/files": { "filePath": "/root/opencami/src/routes/files.tsx", "assets": [], "preloads": ["/assets/files-e40B1zFy.js"] }, "/memory": { "filePath": "/root/opencami/src/routes/memory.tsx", "assets": [], "preloads": ["/assets/memory-C7UG-1le.js"] }, "/new": { "filePath": "/root/opencami/src/routes/new.tsx", "assets": [], "preloads": ["/assets/new-DLlBm66g.js"] }, "/skills": { "filePath": "/root/opencami/src/routes/skills.tsx", "assets": [], "preloads": ["/assets/skills-DoKPPhNY.js"] }, "/api/agents": { "filePath": "/root/opencami/src/routes/api/agents.ts" }, "/api/cron": { "filePath": "/root/opencami/src/routes/api/cron.ts" }, "/api/follow-ups": { "filePath": "/root/opencami/src/routes/api/follow-ups.ts" }, "/api/history": { "filePath": "/root/opencami/src/routes/api/history.ts" }, "/api/llm-features": { "filePath": "/root/opencami/src/routes/api/llm-features.ts" }, "/api/models": { "filePath": "/root/opencami/src/routes/api/models.ts" }, "/api/paths": { "filePath": "/root/opencami/src/routes/api/paths.ts" }, "/api/personas": { "filePath": "/root/opencami/src/routes/api/personas.ts" }, "/api/ping": { "filePath": "/root/opencami/src/routes/api/ping.ts" }, "/api/send": { "filePath": "/root/opencami/src/routes/api/send.ts" }, "/api/sessions": { "filePath": "/root/opencami/src/routes/api/sessions.ts" }, "/api/skills": { "filePath": "/root/opencami/src/routes/api/skills.ts" }, "/api/stream": { "filePath": "/root/opencami/src/routes/api/stream.ts" }, "/api/stt": { "filePath": "/root/opencami/src/routes/api/stt.ts" }, "/api/tts": { "filePath": "/root/opencami/src/routes/api/tts.ts" }, "/chat/$sessionKey": { "filePath": "/root/opencami/src/routes/chat/$sessionKey.tsx", "assets": [], "preloads": ["/assets/_sessionKey-B5Viv43f.js", "/assets/useQuery-Ctiljcrr.js", "/assets/tooltip-BbH3QWvK.js", "/assets/button-CK8tKQ-Z.js", "/assets/useMutation-12DyB3Ox.js", "/assets/use-file-explorer-state-DBfLeAyz.js", "/assets/useBaseUiId-MgM4ouhx.js", "/assets/useControlled-BQxTgsOd.js", "/assets/useOnFirstRender-7qoaK5sI.js", "/assets/event-BsD1rqGT.js", "/assets/CSPContext-6t3O1emU.js", "/assets/DirectionContext-C6goXEY_.js", "/assets/menu-n6L--M9R.js", "/assets/opencami-logo-zuSBm5Br.js", "/assets/proxy-BU8Bw1Vt.js", "/assets/markdown-C7_Aipwd.js", "/assets/index-rljDU_1M.js", "/assets/react-BLyCEWpN.js"] }, "/api/dashboard/crons": { "filePath": "/root/opencami/src/routes/api/dashboard/crons.ts" }, "/api/dashboard/gateway": { "filePath": "/root/opencami/src/routes/api/dashboard/gateway.ts" }, "/api/dashboard/system": { "filePath": "/root/opencami/src/routes/api/dashboard/system.ts" }, "/api/files/delete": { "filePath": "/root/opencami/src/routes/api/files/delete.ts" }, "/api/files/download": { "filePath": "/root/opencami/src/routes/api/files/download.ts" }, "/api/files/info": { "filePath": "/root/opencami/src/routes/api/files/info.ts" }, "/api/files/list": { "filePath": "/root/opencami/src/routes/api/files/list.ts" }, "/api/files/mkdir": { "filePath": "/root/opencami/src/routes/api/files/mkdir.ts" }, "/api/files/read": { "filePath": "/root/opencami/src/routes/api/files/read.ts" }, "/api/files/rename": { "filePath": "/root/opencami/src/routes/api/files/rename.ts" }, "/api/files/save": { "filePath": "/root/opencami/src/routes/api/files/save.ts" }, "/api/files/upload": { "filePath": "/root/opencami/src/routes/api/files/upload.ts" } }, "clientEntry": "/assets/main-Dq6jpr6-.js" });
1
+ const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "/root/opencami/src/routes/__root.tsx", "children": ["/", "/agents", "/bots", "/connect", "/dashboard", "/files", "/memory", "/new", "/skills", "/api/agents", "/api/cron", "/api/follow-ups", "/api/history", "/api/llm-features", "/api/models", "/api/paths", "/api/personas", "/api/ping", "/api/send", "/api/sessions", "/api/skills", "/api/stream", "/api/stt", "/api/tts", "/chat/$sessionKey", "/api/dashboard/crons", "/api/dashboard/gateway", "/api/dashboard/system", "/api/files/delete", "/api/files/download", "/api/files/info", "/api/files/list", "/api/files/mkdir", "/api/files/read", "/api/files/rename", "/api/files/save", "/api/files/upload"], "preloads": ["/assets/main-DBmooBKx.js"], "assets": [] }, "/": { "filePath": "/root/opencami/src/routes/index.tsx", "assets": [], "preloads": ["/assets/index-B551ln24.js"] }, "/agents": { "filePath": "/root/opencami/src/routes/agents.tsx", "assets": [], "preloads": ["/assets/agents-C6Ev94B1.js"] }, "/bots": { "filePath": "/root/opencami/src/routes/bots.tsx", "assets": [], "preloads": ["/assets/bots-B2_u-OmP.js"] }, "/connect": { "filePath": "/root/opencami/src/routes/connect.tsx", "assets": [], "preloads": ["/assets/connect-CSbeSBTn.js", "/assets/index-BxsgifDH.js", "/assets/button-DdG8c-XQ.js", "/assets/react-dSDkXQu6.js"] }, "/dashboard": { "filePath": "/root/opencami/src/routes/dashboard.tsx", "assets": [], "preloads": ["/assets/dashboard-DA1fTRcH.js", "/assets/useQuery-CtUiG53w.js"] }, "/files": { "filePath": "/root/opencami/src/routes/files.tsx", "assets": [], "preloads": ["/assets/files-PsZnGOUx.js"] }, "/memory": { "filePath": "/root/opencami/src/routes/memory.tsx", "assets": [], "preloads": ["/assets/memory-Bs8hOoEv.js"] }, "/new": { "filePath": "/root/opencami/src/routes/new.tsx", "assets": [], "preloads": ["/assets/new-DLlBm66g.js"] }, "/skills": { "filePath": "/root/opencami/src/routes/skills.tsx", "assets": [], "preloads": ["/assets/skills-pueagQNc.js"] }, "/api/agents": { "filePath": "/root/opencami/src/routes/api/agents.ts" }, "/api/cron": { "filePath": "/root/opencami/src/routes/api/cron.ts" }, "/api/follow-ups": { "filePath": "/root/opencami/src/routes/api/follow-ups.ts" }, "/api/history": { "filePath": "/root/opencami/src/routes/api/history.ts" }, "/api/llm-features": { "filePath": "/root/opencami/src/routes/api/llm-features.ts" }, "/api/models": { "filePath": "/root/opencami/src/routes/api/models.ts" }, "/api/paths": { "filePath": "/root/opencami/src/routes/api/paths.ts" }, "/api/personas": { "filePath": "/root/opencami/src/routes/api/personas.ts" }, "/api/ping": { "filePath": "/root/opencami/src/routes/api/ping.ts" }, "/api/send": { "filePath": "/root/opencami/src/routes/api/send.ts" }, "/api/sessions": { "filePath": "/root/opencami/src/routes/api/sessions.ts" }, "/api/skills": { "filePath": "/root/opencami/src/routes/api/skills.ts" }, "/api/stream": { "filePath": "/root/opencami/src/routes/api/stream.ts" }, "/api/stt": { "filePath": "/root/opencami/src/routes/api/stt.ts" }, "/api/tts": { "filePath": "/root/opencami/src/routes/api/tts.ts" }, "/chat/$sessionKey": { "filePath": "/root/opencami/src/routes/chat/$sessionKey.tsx", "assets": [], "preloads": ["/assets/_sessionKey-CNw4O2rY.js", "/assets/useQuery-CtUiG53w.js", "/assets/tooltip-CtHpm-sQ.js", "/assets/button-DdG8c-XQ.js", "/assets/useMutation-DckvFKPC.js", "/assets/use-file-explorer-state-C-D2CShe.js", "/assets/useBaseUiId-Ckx_aJky.js", "/assets/useControlled-8D4PSDAL.js", "/assets/popupStateMapping-CGDLUl5Y.js", "/assets/event-Dwf9IDxK.js", "/assets/CSPContext-nHSyQniZ.js", "/assets/DirectionContext-B1cuzwIr.js", "/assets/menu-ByR1BVmq.js", "/assets/opencami-logo-BV1uPYe6.js", "/assets/proxy-DYrSkM35.js", "/assets/markdown-Bpat4kTr.js", "/assets/index-BxsgifDH.js", "/assets/react-dSDkXQu6.js"] }, "/api/dashboard/crons": { "filePath": "/root/opencami/src/routes/api/dashboard/crons.ts" }, "/api/dashboard/gateway": { "filePath": "/root/opencami/src/routes/api/dashboard/gateway.ts" }, "/api/dashboard/system": { "filePath": "/root/opencami/src/routes/api/dashboard/system.ts" }, "/api/files/delete": { "filePath": "/root/opencami/src/routes/api/files/delete.ts" }, "/api/files/download": { "filePath": "/root/opencami/src/routes/api/files/download.ts" }, "/api/files/info": { "filePath": "/root/opencami/src/routes/api/files/info.ts" }, "/api/files/list": { "filePath": "/root/opencami/src/routes/api/files/list.ts" }, "/api/files/mkdir": { "filePath": "/root/opencami/src/routes/api/files/mkdir.ts" }, "/api/files/read": { "filePath": "/root/opencami/src/routes/api/files/read.ts" }, "/api/files/rename": { "filePath": "/root/opencami/src/routes/api/files/rename.ts" }, "/api/files/save": { "filePath": "/root/opencami/src/routes/api/files/save.ts" }, "/api/files/upload": { "filePath": "/root/opencami/src/routes/api/files/upload.ts" } }, "clientEntry": "/assets/main-DBmooBKx.js" });
2
2
  export {
3
3
  tsrStartManifest
4
4
  };
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { C as CodeBlock } from "./index-Dl2BOKP7.js";
2
+ import { C as CodeBlock } from "./index-BEWnDAH6.js";
3
3
  import "react";
4
4
  import "@hugeicons/react";
5
5
  import "@hugeicons/core-free-icons";
@@ -0,0 +1,336 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { useState, useRef, useEffect, memo } from "react";
3
+ import { HugeiconsIcon } from "@hugeicons/react";
4
+ import { Loading03Icon, ArrowRight01Icon } from "@hugeicons/core-free-icons";
5
+ import { a as useLlmSettingsStore, b as getLlmHeaders } from "./_sessionKey-LV6xK9IM.js";
6
+ import { c as cn } from "./button-CwY2OHFj.js";
7
+ import "@tanstack/react-router";
8
+ import "@tanstack/react-query";
9
+ import "./tooltip-DgsSPocE.js";
10
+ import "@base-ui/react/tooltip";
11
+ import "motion/react";
12
+ import "@base-ui/react/alert-dialog";
13
+ import "./use-file-explorer-state-s7CS50ho.js";
14
+ import "@base-ui/react/dialog";
15
+ import "zustand";
16
+ import "@base-ui/react/collapsible";
17
+ import "@base-ui/react/scroll-area";
18
+ import "./menu-D90CDTi2.js";
19
+ import "@base-ui/react/menu";
20
+ import "./opencami-logo-C-43FL3R.js";
21
+ import "./markdown-DoX5Q7qh.js";
22
+ import "marked";
23
+ import "react-markdown";
24
+ import "remark-breaks";
25
+ import "remark-gfm";
26
+ import "./index-BEWnDAH6.js";
27
+ import "zustand/middleware";
28
+ import "react-dom";
29
+ import "./router-Cr2xCvGA.js";
30
+ import "node:crypto";
31
+ import "node:fs";
32
+ import "node:os";
33
+ import "node:path";
34
+ import "ws";
35
+ import "@tanstack/router-core/ssr/client";
36
+ import "node:stream";
37
+ import "node:child_process";
38
+ import "node:util";
39
+ import "node:fs/promises";
40
+ import "path";
41
+ import "@base-ui/react/merge-props";
42
+ import "@base-ui/react/use-render";
43
+ import "class-variance-authority";
44
+ import "clsx";
45
+ import "tailwind-merge";
46
+ const CODE_PATTERNS = [
47
+ /```[\s\S]*?```/g,
48
+ /`[^`]+`/g,
49
+ /\b(function|const|let|var|class|import|export|return|async|await)\b/g
50
+ ];
51
+ function extractTopics(text) {
52
+ const topics = [];
53
+ const quoted = text.match(/"([^"]+)"|'([^']+)'/g);
54
+ if (quoted) {
55
+ topics.push(...quoted.map((q) => q.replace(/['"]/g, "")));
56
+ }
57
+ const capitalized = text.match(/\b[A-Z][a-z]+(?:\s+[A-Z][a-z]+)*\b/g);
58
+ if (capitalized) {
59
+ topics.push(
60
+ ...capitalized.filter((t) => !["I", "The", "A", "An", "This"].includes(t))
61
+ );
62
+ }
63
+ const backticked = text.match(/`([^`]+)`/g);
64
+ if (backticked) {
65
+ topics.push(...backticked.map((t) => t.replace(/`/g, "")));
66
+ }
67
+ return [...new Set(topics)].slice(0, 5);
68
+ }
69
+ function hasCode(text) {
70
+ return CODE_PATTERNS.some((pattern) => pattern.test(text));
71
+ }
72
+ function hasList(text) {
73
+ return /^[\s]*[-*•\d]+[.)\s]/m.test(text) || /\b(first|second|third|1\.|2\.|3\.)/i.test(text);
74
+ }
75
+ function hasAlternatives(text) {
76
+ return /\b(alternatively|another|other option|could also|you might|consider)\b/i.test(text);
77
+ }
78
+ function isExplanatory(text) {
79
+ return /\b(because|since|due to|reason|why|how|what|when|where)\b/i.test(text);
80
+ }
81
+ function hasCaveats(text) {
82
+ return /\b(however|but|note|warning|caution|careful|important|keep in mind|be aware)\b/i.test(text);
83
+ }
84
+ function generateHeuristicFollowUps(responseText) {
85
+ const suggestions = [];
86
+ const topics = extractTopics(responseText);
87
+ if (hasCode(responseText)) {
88
+ suggestions.push({
89
+ text: "Can you explain this code step by step?",
90
+ type: "clarify"
91
+ });
92
+ suggestions.push({
93
+ text: "How would I modify this for my use case?",
94
+ type: "actionable"
95
+ });
96
+ }
97
+ if (hasList(responseText)) {
98
+ suggestions.push({
99
+ text: "Can you elaborate on the first point?",
100
+ type: "expand"
101
+ });
102
+ suggestions.push({
103
+ text: "Which of these is most important to start with?",
104
+ type: "actionable"
105
+ });
106
+ }
107
+ if (hasAlternatives(responseText)) {
108
+ suggestions.push({
109
+ text: "What are the pros and cons of each approach?",
110
+ type: "alternative"
111
+ });
112
+ suggestions.push({
113
+ text: "Which option would you recommend and why?",
114
+ type: "clarify"
115
+ });
116
+ }
117
+ if (isExplanatory(responseText) && suggestions.length < 3) {
118
+ suggestions.push({
119
+ text: "Can you give me a practical example?",
120
+ type: "example"
121
+ });
122
+ }
123
+ if (hasCaveats(responseText) && suggestions.length < 3) {
124
+ suggestions.push({
125
+ text: "What potential issues should I watch out for?",
126
+ type: "clarify"
127
+ });
128
+ }
129
+ if (topics.length > 0 && suggestions.length < 3) {
130
+ const topic = topics[0];
131
+ suggestions.push({
132
+ text: `Tell me more about ${topic}`,
133
+ type: "expand"
134
+ });
135
+ }
136
+ const fallbacks = [
137
+ { text: "Can you give me a concrete example?", type: "example" },
138
+ { text: "What would be the next steps?", type: "actionable" },
139
+ { text: "How does this work in practice?", type: "expand" },
140
+ { text: "Are there any common mistakes to avoid?", type: "clarify" },
141
+ { text: "Can you simplify this explanation?", type: "clarify" }
142
+ ];
143
+ const usedTypes = new Set(suggestions.map((s) => s.type));
144
+ for (const fallback of fallbacks) {
145
+ if (suggestions.length >= 3) break;
146
+ if (!usedTypes.has(fallback.type)) {
147
+ suggestions.push(fallback);
148
+ usedTypes.add(fallback.type);
149
+ }
150
+ }
151
+ for (const fallback of fallbacks) {
152
+ if (suggestions.length >= 3) break;
153
+ if (!suggestions.some((s) => s.text === fallback.text)) {
154
+ suggestions.push(fallback);
155
+ }
156
+ }
157
+ return suggestions.slice(0, 3);
158
+ }
159
+ function getHeuristicFollowUpTexts(responseText) {
160
+ return generateHeuristicFollowUps(responseText).map((s) => s.text);
161
+ }
162
+ async function fetchLlmFollowUps(conversationContext, signal) {
163
+ const headers = {
164
+ "Content-Type": "application/json",
165
+ ...getLlmHeaders()
166
+ };
167
+ const res = await fetch("/api/llm-features", {
168
+ method: "POST",
169
+ headers,
170
+ body: JSON.stringify({
171
+ action: "followups",
172
+ conversationContext
173
+ }),
174
+ signal
175
+ });
176
+ if (!res.ok) {
177
+ throw new Error(`API error: ${res.status}`);
178
+ }
179
+ const data = await res.json();
180
+ if (data.ok && Array.isArray(data.suggestions) && data.suggestions.length > 0) {
181
+ return data.suggestions;
182
+ }
183
+ return [];
184
+ }
185
+ function useFollowUpSuggestions(responseText, contextSummary, options) {
186
+ const llmSettings = useLlmSettingsStore((state) => state.settings);
187
+ const useLlmFollowUps = llmSettings.useLlmFollowUps;
188
+ const {
189
+ minResponseLength = 50,
190
+ timeoutMs = 8e3,
191
+ // Use heuristics only if explicitly set OR if LLM follow-ups are disabled
192
+ heuristicsOnly: forceHeuristicsOnly
193
+ } = options ?? {};
194
+ const heuristicsOnly = forceHeuristicsOnly ?? !useLlmFollowUps;
195
+ const [suggestions, setSuggestions] = useState([]);
196
+ const [isLoading, setIsLoading] = useState(false);
197
+ const [error, setError] = useState(null);
198
+ const [source, setSource] = useState(null);
199
+ const lastResponseRef = useRef("");
200
+ const abortControllerRef = useRef(null);
201
+ useEffect(() => {
202
+ if (!responseText || responseText.trim().length < minResponseLength) {
203
+ setSuggestions([]);
204
+ setSource(null);
205
+ setIsLoading(false);
206
+ setError(null);
207
+ return;
208
+ }
209
+ const responseKey = responseText.slice(0, 200) + responseText.length;
210
+ if (responseKey === lastResponseRef.current) {
211
+ return;
212
+ }
213
+ lastResponseRef.current = responseKey;
214
+ if (abortControllerRef.current) {
215
+ abortControllerRef.current.abort();
216
+ }
217
+ if (heuristicsOnly) {
218
+ const heuristicSuggestions2 = getHeuristicFollowUpTexts(responseText);
219
+ setSuggestions(heuristicSuggestions2);
220
+ setSource("heuristic");
221
+ setIsLoading(false);
222
+ setError(null);
223
+ return;
224
+ }
225
+ const controller = new AbortController();
226
+ abortControllerRef.current = controller;
227
+ setIsLoading(true);
228
+ setError(null);
229
+ const heuristicSuggestions = getHeuristicFollowUpTexts(responseText);
230
+ setSuggestions(heuristicSuggestions);
231
+ setSource("heuristic");
232
+ const conversationContext = contextSummary ? `Context: ${contextSummary}
233
+
234
+ Assistant's response:
235
+ ${responseText.slice(0, 2e3)}` : `Assistant's response:
236
+ ${responseText.slice(0, 2e3)}`;
237
+ fetchLlmFollowUps(conversationContext, controller.signal).then((llmSuggestions) => {
238
+ if (controller.signal.aborted) {
239
+ return;
240
+ }
241
+ if (llmSuggestions.length > 0) {
242
+ setSuggestions(llmSuggestions);
243
+ setSource("llm");
244
+ }
245
+ setIsLoading(false);
246
+ }).catch((err) => {
247
+ if (controller.signal.aborted) return;
248
+ setError(err instanceof Error ? err.message : String(err));
249
+ setIsLoading(false);
250
+ });
251
+ return () => {
252
+ };
253
+ }, [
254
+ responseText,
255
+ contextSummary,
256
+ minResponseLength,
257
+ timeoutMs,
258
+ heuristicsOnly,
259
+ llmSettings.llmApiKey,
260
+ llmSettings.llmBaseUrl,
261
+ llmSettings.llmModel,
262
+ llmSettings.llmProvider
263
+ ]);
264
+ return { suggestions, isLoading, error, source };
265
+ }
266
+ function FollowUpSuggestionsComponent({
267
+ responseText,
268
+ contextSummary,
269
+ onSuggestionClick,
270
+ disabled = false,
271
+ className
272
+ }) {
273
+ const { suggestions, isLoading, source } = useFollowUpSuggestions(
274
+ responseText,
275
+ contextSummary,
276
+ {
277
+ minResponseLength: 50,
278
+ timeoutMs: 8e3
279
+ }
280
+ );
281
+ if (suggestions.length === 0 && !isLoading) {
282
+ return null;
283
+ }
284
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-2 mt-3", className), children: [
285
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-xs text-primary-500", children: [
286
+ /* @__PURE__ */ jsx("span", { className: "text-primary-400", children: "✨" }),
287
+ /* @__PURE__ */ jsx("span", { children: isLoading ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
288
+ "Thinking of follow-ups",
289
+ /* @__PURE__ */ jsx(
290
+ HugeiconsIcon,
291
+ {
292
+ icon: Loading03Icon,
293
+ size: 12,
294
+ strokeWidth: 2,
295
+ className: "animate-spin text-primary-400"
296
+ }
297
+ )
298
+ ] }) : source === "llm" ? "AI suggestions" : "Follow-up suggestions" })
299
+ ] }),
300
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: suggestions.map((suggestion, index) => /* @__PURE__ */ jsxs(
301
+ "button",
302
+ {
303
+ type: "button",
304
+ disabled,
305
+ onClick: () => onSuggestionClick(suggestion),
306
+ className: cn(
307
+ "group inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full",
308
+ "text-sm text-primary-700 bg-primary-50 border border-primary-200",
309
+ "hover:bg-primary-100 hover:border-primary-300 hover:text-primary-900",
310
+ "focus:outline-none focus:ring-2 focus:ring-primary-500/20 focus:ring-offset-1",
311
+ "transition-all duration-150 cursor-pointer",
312
+ "disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-primary-50 disabled:hover:border-primary-200",
313
+ // Subtle animation when suggestions update from heuristic to LLM
314
+ isLoading && "opacity-75"
315
+ ),
316
+ children: [
317
+ /* @__PURE__ */ jsx("span", { children: suggestion }),
318
+ /* @__PURE__ */ jsx(
319
+ HugeiconsIcon,
320
+ {
321
+ icon: ArrowRight01Icon,
322
+ size: 14,
323
+ strokeWidth: 2,
324
+ className: "text-primary-400 group-hover:text-primary-600 group-hover:translate-x-0.5 transition-all duration-150"
325
+ }
326
+ )
327
+ ]
328
+ },
329
+ `${index}-${suggestion.slice(0, 20)}`
330
+ )) })
331
+ ] });
332
+ }
333
+ const MemoizedFollowUpSuggestions = memo(FollowUpSuggestionsComponent);
334
+ export {
335
+ MemoizedFollowUpSuggestions as FollowUpSuggestions
336
+ };
@@ -191,7 +191,12 @@ let highlighterPromise = null;
191
191
  const loadedLanguages = /* @__PURE__ */ new Set();
192
192
  async function getHighlighter() {
193
193
  if (!highlighterPromise) {
194
- const [{ createHighlighterCore }, { createJavaScriptRegexEngine }, vitesseDark, vitesseLight] = await Promise.all([
194
+ const [
195
+ { createHighlighterCore },
196
+ { createJavaScriptRegexEngine },
197
+ vitesseDark,
198
+ vitesseLight
199
+ ] = await Promise.all([
195
200
  import("shiki/core"),
196
201
  import("shiki/engine/javascript"),
197
202
  import("@shikijs/themes/vitesse-dark").then((m) => m.default),
@@ -229,7 +234,8 @@ function CodeBlock({
229
234
  ariaLabel,
230
235
  language = "text",
231
236
  filename,
232
- className
237
+ className,
238
+ isStreaming = false
233
239
  }) {
234
240
  const resolvedTheme = useResolvedTheme();
235
241
  const [copied, setCopied] = useState(false);
@@ -244,11 +250,19 @@ function CodeBlock({
244
250
  const themeName = resolvedTheme === "dark" ? "vitesse-dark" : "vitesse-light";
245
251
  useEffect(() => {
246
252
  let active = true;
253
+ let highlightTimer = null;
254
+ const baseLang = resolveLanguage(normalizedLanguage);
255
+ setResolvedLanguage(baseLang);
256
+ if (isStreaming) {
257
+ setHtml(null);
258
+ return () => {
259
+ active = false;
260
+ };
261
+ }
247
262
  async function highlight() {
248
263
  try {
249
264
  const highlighter = await getHighlighter();
250
265
  if (!active) return;
251
- const baseLang = resolveLanguage(normalizedLanguage);
252
266
  const lang = await ensureLanguageLoaded(highlighter, baseLang);
253
267
  if (!active) return;
254
268
  const highlighted = highlighter.codeToHtml(content, {
@@ -265,11 +279,16 @@ function CodeBlock({
265
279
  if (active) setHtml(null);
266
280
  }
267
281
  }
268
- highlight();
282
+ highlightTimer = window.setTimeout(() => {
283
+ void highlight();
284
+ }, 160);
269
285
  return () => {
270
286
  active = false;
287
+ if (highlightTimer) {
288
+ window.clearTimeout(highlightTimer);
289
+ }
271
290
  };
272
- }, [content, normalizedLanguage, themeName]);
291
+ }, [content, isStreaming, normalizedLanguage, themeName]);
273
292
  useEffect(() => {
274
293
  if (typeof window === "undefined") return;
275
294
  const saved = window.localStorage.getItem("opencami-code-wrap");
@@ -1,6 +1,6 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { useEffect } from "react";
3
- import { R as Route } from "./router-BZPatFG9.js";
3
+ import { R as Route } from "./router-Cr2xCvGA.js";
4
4
  import "@tanstack/react-router";
5
5
  import "@tanstack/react-query";
6
6
  import "node:crypto";
@@ -4,7 +4,7 @@ import { memo, useId, useMemo, useState, useCallback, useEffect } from "react";
4
4
  import ReactMarkdown from "react-markdown";
5
5
  import remarkBreaks from "remark-breaks";
6
6
  import remarkGfm from "remark-gfm";
7
- import { r as resolveLanguage, C as CodeBlock } from "./index-Dl2BOKP7.js";
7
+ import { r as resolveLanguage, C as CodeBlock } from "./index-BEWnDAH6.js";
8
8
  import { u as useFileExplorerState, D as DialogRoot, a as DialogContent, b as DialogTitle, d as DialogClose } from "./use-file-explorer-state-s7CS50ho.js";
9
9
  import { c as cn, B as Button } from "./button-CwY2OHFj.js";
10
10
  import { useNavigate, Link } from "@tanstack/react-router";
@@ -314,7 +314,7 @@ const BASE_COMPONENTS = {
314
314
  return /* @__PURE__ */ jsx("td", { className: "px-3 py-2 text-primary-950", children });
315
315
  }
316
316
  };
317
- function createDefaultComponents(onOpenFilePreview) {
317
+ function createDefaultComponents(onOpenFilePreview, isStreaming = false) {
318
318
  return {
319
319
  ...BASE_COMPONENTS,
320
320
  a: function AComponent({ children, href }) {
@@ -356,7 +356,8 @@ function createDefaultComponents(onOpenFilePreview) {
356
356
  content: String(children ?? ""),
357
357
  language,
358
358
  filename,
359
- className: "w-full"
359
+ className: "w-full",
360
+ isStreaming
360
361
  }
361
362
  );
362
363
  }
@@ -405,30 +406,39 @@ function MarkdownComponent({
405
406
  children,
406
407
  id,
407
408
  className,
408
- components
409
+ components,
410
+ isStreaming = false
409
411
  }) {
410
412
  const generatedId = useId();
411
413
  const blockId = id ?? generatedId;
412
414
  const blocks = useMemo(() => parseMarkdownIntoBlocks(children), [children]);
413
- const [filePreview, setFilePreview] = useState({ status: "idle" });
415
+ const [filePreview, setFilePreview] = useState({
416
+ status: "idle"
417
+ });
414
418
  const navigate = useNavigate();
415
- const openDirectoryInExplorer = useCallback((path) => {
416
- const workspacePath = toWorkspacePath(path);
417
- useFileExplorerState.getState().navigateTo(workspacePath);
418
- setFilePreview({ status: "idle" });
419
- navigate({ to: "/files" });
420
- }, [navigate]);
421
- const onOpenFilePreview = useCallback((path) => {
422
- const resolvedPath = normalizeClickedPath(path);
423
- if (isDirectoryPathHeuristic(resolvedPath)) {
424
- openDirectoryInExplorer(resolvedPath);
425
- return;
426
- }
427
- setFilePreview({ status: "loading", path: resolvedPath });
428
- }, [openDirectoryInExplorer]);
419
+ const openDirectoryInExplorer = useCallback(
420
+ (path) => {
421
+ const workspacePath = toWorkspacePath(path);
422
+ useFileExplorerState.getState().navigateTo(workspacePath);
423
+ setFilePreview({ status: "idle" });
424
+ navigate({ to: "/files" });
425
+ },
426
+ [navigate]
427
+ );
428
+ const onOpenFilePreview = useCallback(
429
+ (path) => {
430
+ const resolvedPath = normalizeClickedPath(path);
431
+ if (isDirectoryPathHeuristic(resolvedPath)) {
432
+ openDirectoryInExplorer(resolvedPath);
433
+ return;
434
+ }
435
+ setFilePreview({ status: "loading", path: resolvedPath });
436
+ },
437
+ [openDirectoryInExplorer]
438
+ );
429
439
  const defaultComponents = useMemo(
430
- () => createDefaultComponents(onOpenFilePreview),
431
- [onOpenFilePreview]
440
+ () => createDefaultComponents(onOpenFilePreview, isStreaming),
441
+ [isStreaming, onOpenFilePreview]
432
442
  );
433
443
  const mergedComponents = useMemo(
434
444
  () => ({ ...defaultComponents, ...components || {} }),
@@ -447,7 +457,10 @@ function MarkdownComponent({
447
457
  openDirectoryInExplorer(path);
448
458
  return;
449
459
  }
450
- const error = fileErrorMessageFromResponse(response.status, payload.code);
460
+ const error = fileErrorMessageFromResponse(
461
+ response.status,
462
+ payload.code
463
+ );
451
464
  setFilePreview({ status: "error", path, message: error });
452
465
  return;
453
466
  }
@@ -465,7 +478,11 @@ function MarkdownComponent({
465
478
  });
466
479
  }).catch(() => {
467
480
  if (controller.signal.aborted) return;
468
- setFilePreview({ status: "error", path, message: "Failed to load file preview" });
481
+ setFilePreview({
482
+ status: "error",
483
+ path,
484
+ message: "Failed to load file preview"
485
+ });
469
486
  });
470
487
  return () => controller.abort();
471
488
  }, [filePreview, openDirectoryInExplorer]);
@@ -474,12 +491,19 @@ function MarkdownComponent({
474
491
  /* @__PURE__ */ jsx(
475
492
  "div",
476
493
  {
477
- className: cn("flex min-w-0 max-w-full flex-col gap-2 overflow-x-hidden", className),
494
+ className: cn(
495
+ "flex min-w-0 max-w-full flex-col gap-2 overflow-x-hidden",
496
+ className
497
+ ),
478
498
  onClickCapture: (event) => {
479
499
  const target = event.target;
480
- const anchor = target?.closest?.('a[href^="openclaw-file://"]');
500
+ const anchor = target?.closest?.(
501
+ 'a[href^="openclaw-file://"]'
502
+ );
481
503
  if (!anchor) return;
482
- const filePath = markdownHrefToFilePath(anchor.getAttribute("href") ?? void 0);
504
+ const filePath = markdownHrefToFilePath(
505
+ anchor.getAttribute("href") ?? void 0
506
+ );
483
507
  if (!filePath) return;
484
508
  event.preventDefault();
485
509
  event.stopPropagation();
@@ -1,6 +1,6 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { Suspense, lazy } from "react";
3
- const MemoryScreen = lazy(() => import("./memory-screen-BK5phS8K.js").then((m) => ({
3
+ const MemoryScreen = lazy(() => import("./memory-screen-B5l1NZRY.js").then((m) => ({
4
4
  default: m.MemoryScreen
5
5
  })));
6
6
  function MemoryRoute() {
@@ -3,7 +3,7 @@ import { useState, useEffect, useCallback } from "react";
3
3
  import { useQueryClient, useQuery, useMutation } from "@tanstack/react-query";
4
4
  import { Link } from "@tanstack/react-router";
5
5
  import { c as cn, B as Button, b as buttonVariants } from "./button-CwY2OHFj.js";
6
- import { M as Markdown } from "./markdown-BFE5y9YH.js";
6
+ import { M as Markdown } from "./markdown-DoX5Q7qh.js";
7
7
  import "@base-ui/react/merge-props";
8
8
  import "@base-ui/react/use-render";
9
9
  import "class-variance-authority";
@@ -13,7 +13,7 @@ import "marked";
13
13
  import "react-markdown";
14
14
  import "remark-breaks";
15
15
  import "remark-gfm";
16
- import "./index-Dl2BOKP7.js";
16
+ import "./index-BEWnDAH6.js";
17
17
  import "@hugeicons/react";
18
18
  import "@hugeicons/core-free-icons";
19
19
  import "zustand";
@@ -12,7 +12,7 @@ import { execFile, execSync } from "node:child_process";
12
12
  import { promisify } from "node:util";
13
13
  import { readFile, mkdir, writeFile, rename, stat, readdir, rm, realpath, lstat } from "node:fs/promises";
14
14
  import { posix } from "path";
15
- const appCss = "/assets/styles-CXV5jZiD.css";
15
+ const appCss = "/assets/styles-Ce2xZzc4.css";
16
16
  const swRegisterScript = `
17
17
  (() => {
18
18
  // Skip PWA service worker inside Capacitor native shell — they conflict
@@ -346,7 +346,7 @@ const Route$z = createFileRoute("/new")({
346
346
  },
347
347
  component: lazyRouteComponent($$splitComponentImporter$8, "component")
348
348
  });
349
- const $$splitComponentImporter$7 = () => import("./memory-BqZOoD7Q.js");
349
+ const $$splitComponentImporter$7 = () => import("./memory-Cxu7i8ej.js");
350
350
  const Route$y = createFileRoute("/memory")({
351
351
  component: lazyRouteComponent($$splitComponentImporter$7, "component")
352
352
  });
@@ -358,7 +358,7 @@ const $$splitComponentImporter$5 = () => import("./dashboard-GCKodTiJ.js");
358
358
  const Route$w = createFileRoute("/dashboard")({
359
359
  component: lazyRouteComponent($$splitComponentImporter$5, "component")
360
360
  });
361
- const $$splitComponentImporter$4 = () => import("./connect-CbgijWz4.js");
361
+ const $$splitComponentImporter$4 = () => import("./connect-BNabuqpW.js");
362
362
  const Route$v = createFileRoute("/connect")({
363
363
  component: lazyRouteComponent($$splitComponentImporter$4, "component")
364
364
  });
@@ -370,11 +370,11 @@ const $$splitComponentImporter$2 = () => import("./agents-CmQ4vvXm.js");
370
370
  const Route$t = createFileRoute("/agents")({
371
371
  component: lazyRouteComponent($$splitComponentImporter$2, "component")
372
372
  });
373
- const $$splitComponentImporter$1 = () => import("./index-BFHEmXpN.js");
373
+ const $$splitComponentImporter$1 = () => import("./index-DMKS4aeI.js");
374
374
  const Route$s = createFileRoute("/")({
375
375
  component: lazyRouteComponent($$splitComponentImporter$1, "component")
376
376
  });
377
- const $$splitComponentImporter = () => import("./_sessionKey-DzsJfprr.js").then((n) => n.$);
377
+ const $$splitComponentImporter = () => import("./_sessionKey-LV6xK9IM.js").then((n) => n.$);
378
378
  const Route$r = createFileRoute("/chat/$sessionKey")({
379
379
  component: lazyRouteComponent($$splitComponentImporter, "component")
380
380
  });