opencami 1.9.1 → 2.1.0

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 (74) hide show
  1. package/dist/client/assets/{CSPContext-B3PAVjBL.js → CSPContext-CxrBvJ99.js} +1 -1
  2. package/dist/client/assets/{DirectionContext-CR5CCisG.js → DirectionContext-BOL0P_1j.js} +1 -1
  3. package/dist/client/assets/_sessionKey-CTtu2ipR.js +25 -0
  4. package/dist/client/assets/agents-D7JS19Lo.js +2 -0
  5. package/dist/client/assets/{agents-screen--ZMzN5cB.js → agents-screen-CqdzZKaR.js} +1 -1
  6. package/dist/client/assets/bots-DAInzfLx.js +2 -0
  7. package/dist/client/assets/{bots-screen-C_uJBNwI.js → bots-screen-RYovD6cu.js} +1 -1
  8. package/dist/client/assets/button-Bv-7bwZZ.js +1 -0
  9. package/dist/client/assets/{composite-DArWbFHm.js → composite-DwQIZFe9.js} +1 -1
  10. package/dist/client/assets/{connect-B48HecjN.js → connect-DZSrhhNT.js} +1 -1
  11. package/dist/client/assets/{dashboard-BVKx9FMy.js → dashboard-y8KVUVF-.js} +1 -1
  12. package/dist/client/assets/{event-BCwqPPkP.js → event-Cnr9OETn.js} +1 -1
  13. package/dist/client/assets/file-explorer-screen-C_mYUJsr.js +1 -0
  14. package/dist/client/assets/files-CG0jFYdO.js +2 -0
  15. package/dist/client/assets/follow-up-suggestions-C6RzpstA.js +2 -0
  16. package/dist/client/assets/{index-0gdwm1_H.js → index-3-ASY4Cl.js} +1 -1
  17. package/dist/client/assets/index-BZxJSF4T.js +3 -0
  18. package/dist/client/assets/{keyboard-shortcuts-dialog-CK_XTzLr.js → keyboard-shortcuts-dialog-jm4-DftO.js} +1 -1
  19. package/dist/client/assets/{main-B2CrcRuC.js → main-CbISK-pm.js} +3 -3
  20. package/dist/client/assets/{markdown-CdkuX06F.js → markdown-UD7RzskQ.js} +1 -1
  21. package/dist/client/assets/memory-BYRJ1l_4.js +2 -0
  22. package/dist/client/assets/{memory-screen-C1RfLy-d.js → memory-screen-BRsm-Q8A.js} +1 -1
  23. package/dist/client/assets/{menu-CIwnliij.js → menu-DRjoHFvG.js} +1 -1
  24. package/dist/client/assets/{opencami-logo-SVuYD55V.js → opencami-logo-D2mv84sX.js} +1 -1
  25. package/dist/client/assets/{proxy-BijR8W1L.js → proxy-DtxqfBHY.js} +1 -1
  26. package/dist/client/assets/{react-DWx7OvUo.js → react-C_7UlEtd.js} +1 -1
  27. package/dist/client/assets/{search-dialog-CB4KE8ec.js → search-dialog-lsT8JUtT.js} +1 -1
  28. package/dist/client/assets/{search-sources-badge-B8Z-8sSf.js → search-sources-badge-BnqKxoia.js} +1 -1
  29. package/dist/client/assets/{session-export-dialog-tDiFuv3a.js → session-export-dialog-DHHpvwI8.js} +1 -1
  30. package/dist/client/assets/settings-dialog-vrd0eJGw.js +1 -0
  31. package/dist/client/assets/skills-Svd-7oxQ.js +2 -0
  32. package/dist/client/assets/{skills-panel-fjJQVMog.js → skills-panel-Dkuo0yyD.js} +1 -1
  33. package/dist/client/assets/styles-CWabEzNU.css +1 -0
  34. package/dist/client/assets/{switch-Bn5uei2k.js → switch-BYFBYPmi.js} +1 -1
  35. package/dist/client/assets/{tabs-DOBNAUVE.js → tabs-1jrPkdUE.js} +1 -1
  36. package/dist/client/assets/{thinking-dfGrFAMV.js → thinking-D9BBn5kK.js} +1 -1
  37. package/dist/client/assets/{tooltip-DOKkNFvu.js → tooltip-DzFgDY86.js} +1 -1
  38. package/dist/client/assets/{use-file-explorer-state-BAa6Cxyr.js → use-file-explorer-state-Dwhw6Mpg.js} +2 -2
  39. package/dist/client/assets/{useBaseUiId-DFpBD0sg.js → useBaseUiId-BdQC9KF3.js} +1 -1
  40. package/dist/client/assets/useCompositeItem-BI09zNFD.js +1 -0
  41. package/dist/client/assets/{useControlled-CQHE0ITz.js → useControlled-Bc2Emhlx.js} +1 -1
  42. package/dist/client/assets/{useMutation-BFl-7GnD.js → useMutation-CMp81lDO.js} +1 -1
  43. package/dist/client/assets/{useOnFirstRender-DlXHIIGk.js → useOnFirstRender-DpB3w0o4.js} +1 -1
  44. package/dist/client/assets/{useQuery-D-sF8Tld.js → useQuery-_BEWdUe1.js} +1 -1
  45. package/dist/server/assets/{_sessionKey-D8TGrDRM.js → _sessionKey-COz7RLKC.js} +170 -279
  46. package/dist/server/assets/_tanstack-start-manifest_v-D0f-0Utn.js +4 -0
  47. package/dist/server/assets/{connect-CTVBm0Vc.js → connect-sd_NDvQN.js} +1 -1
  48. package/dist/server/assets/follow-up-suggestions-DRQqO8_S.js +183 -0
  49. package/dist/server/assets/{index-B_F4DTUu.js → index-197lqzv2.js} +2 -0
  50. package/dist/server/assets/{index-gRco4Ina.js → index-sXe2QC5V.js} +1 -1
  51. package/dist/server/assets/{markdown-CFdYXCRQ.js → markdown-Dk1YdosA.js} +1 -1
  52. package/dist/server/assets/{memory-screen-vqXczcVo.js → memory-screen-DA_o-N1Z.js} +2 -2
  53. package/dist/server/assets/{memory-rBB015W-.js → memory-woPzJFfs.js} +1 -1
  54. package/dist/server/assets/{router-DaKDqc9w.js → router-CZhxPkYW.js} +347 -355
  55. package/dist/server/assets/{search-dialog-DSSK93kq.js → search-dialog-DlvWfq1e.js} +5 -5
  56. package/dist/server/assets/{settings-dialog-DyWNblva.js → settings-dialog-BGtrS2RJ.js} +63 -255
  57. package/dist/server/assets/{thinking-CU0FRlzT.js → thinking-fzwT_aVT.js} +5 -5
  58. package/dist/server/server.js +2 -2
  59. package/package.json +1 -1
  60. package/dist/client/assets/_sessionKey-Bg_9uype.js +0 -23
  61. package/dist/client/assets/agents-BiTHBb6Z.js +0 -2
  62. package/dist/client/assets/bots-DxhRnQp5.js +0 -2
  63. package/dist/client/assets/button-BciDmec0.js +0 -1
  64. package/dist/client/assets/file-explorer-screen-DPs-FWeA.js +0 -1
  65. package/dist/client/assets/files-SEycwYCa.js +0 -2
  66. package/dist/client/assets/follow-up-suggestions-BPjWBpiy.js +0 -5
  67. package/dist/client/assets/index-CGeJcqZ3.js +0 -3
  68. package/dist/client/assets/memory-C7lKdkmc.js +0 -2
  69. package/dist/client/assets/settings-dialog-aL-AH4Rt.js +0 -1
  70. package/dist/client/assets/skills-D1T6uemU.js +0 -2
  71. package/dist/client/assets/styles-D0L88B64.css +0 -1
  72. package/dist/client/assets/useCompositeItem-B-Axq9-D.js +0 -1
  73. package/dist/server/assets/_tanstack-start-manifest_v-DalBo2bY.js +0 -4
  74. package/dist/server/assets/follow-up-suggestions-C65ptDij.js +0 -336
@@ -0,0 +1,183 @@
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 { u as useChatSettings } from "./index-197lqzv2.js";
6
+ import { c as cn } from "./button-kI8fEIZQ.js";
7
+ import "zustand";
8
+ import "zustand/middleware";
9
+ import "@base-ui/react/merge-props";
10
+ import "@base-ui/react/use-render";
11
+ import "class-variance-authority";
12
+ import "clsx";
13
+ import "tailwind-merge";
14
+ async function fetchFollowUpsViaOpenclaw(conversationContext, model, signal) {
15
+ const res = await fetch("/api/llm-features", {
16
+ method: "POST",
17
+ headers: {
18
+ "Content-Type": "application/json"
19
+ },
20
+ body: JSON.stringify({
21
+ action: "followups",
22
+ conversationContext,
23
+ model
24
+ }),
25
+ signal
26
+ });
27
+ if (!res.ok) {
28
+ throw new Error(`API error: ${res.status}`);
29
+ }
30
+ const data = await res.json();
31
+ if (data.ok && Array.isArray(data.suggestions) && data.suggestions.length > 0) {
32
+ return data.suggestions;
33
+ }
34
+ return [];
35
+ }
36
+ function useFollowUpSuggestions(responseText, conversationContext, options) {
37
+ const { settings } = useChatSettings();
38
+ const { minResponseLength = 50, heuristicsOnly = false, enabled = true } = options ?? {};
39
+ const [suggestions, setSuggestions] = useState([]);
40
+ const [isLoading, setIsLoading] = useState(false);
41
+ const [error, setError] = useState(null);
42
+ const [source, setSource] = useState(null);
43
+ const lastResponseRef = useRef("");
44
+ const abortControllerRef = useRef(null);
45
+ useEffect(() => {
46
+ if (!enabled) {
47
+ if (abortControllerRef.current) {
48
+ abortControllerRef.current.abort();
49
+ }
50
+ setSuggestions([]);
51
+ setSource(null);
52
+ setIsLoading(false);
53
+ setError(null);
54
+ return;
55
+ }
56
+ if (!responseText || responseText.trim().length < minResponseLength) {
57
+ setSuggestions([]);
58
+ setSource(null);
59
+ setIsLoading(false);
60
+ setError(null);
61
+ return;
62
+ }
63
+ const responseKey = `${settings.llmFeaturesModel}:${responseText.slice(0, 200)}${responseText.length}`;
64
+ if (responseKey === lastResponseRef.current) {
65
+ return;
66
+ }
67
+ lastResponseRef.current = responseKey;
68
+ if (abortControllerRef.current) {
69
+ abortControllerRef.current.abort();
70
+ }
71
+ if (heuristicsOnly) {
72
+ setSuggestions([]);
73
+ setSource(null);
74
+ setIsLoading(false);
75
+ setError(null);
76
+ return;
77
+ }
78
+ const controller = new AbortController();
79
+ abortControllerRef.current = controller;
80
+ setIsLoading(true);
81
+ setError(null);
82
+ setSuggestions([]);
83
+ setSource(null);
84
+ const requestContext = conversationContext?.trim().length ? conversationContext.trim() : `Assistant's response:
85
+ ${responseText.slice(0, 2e3)}`;
86
+ fetchFollowUpsViaOpenclaw(
87
+ requestContext,
88
+ settings.llmFeaturesModel ? `openclaw/${settings.llmFeaturesModel}` : void 0,
89
+ controller.signal
90
+ ).then((openclawSuggestions) => {
91
+ if (controller.signal.aborted) return;
92
+ if (openclawSuggestions.length > 0) {
93
+ setSuggestions(openclawSuggestions);
94
+ setSource("openclaw");
95
+ }
96
+ setIsLoading(false);
97
+ }).catch((err) => {
98
+ if (controller.signal.aborted) return;
99
+ setSuggestions([]);
100
+ setSource(null);
101
+ setError(err instanceof Error ? err.message : String(err));
102
+ setIsLoading(false);
103
+ });
104
+ }, [
105
+ responseText,
106
+ conversationContext,
107
+ enabled,
108
+ minResponseLength,
109
+ heuristicsOnly,
110
+ settings.llmFeaturesModel
111
+ ]);
112
+ return { suggestions, isLoading, error, source };
113
+ }
114
+ function FollowUpSuggestionsComponent({
115
+ responseText,
116
+ conversationContext,
117
+ onSuggestionClick,
118
+ disabled = false,
119
+ className
120
+ }) {
121
+ const { suggestions, isLoading, source } = useFollowUpSuggestions(
122
+ responseText,
123
+ conversationContext,
124
+ {
125
+ minResponseLength: 50
126
+ }
127
+ );
128
+ if (suggestions.length === 0 && !isLoading) {
129
+ return null;
130
+ }
131
+ const showHeader = isLoading || suggestions.length > 0;
132
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-2 mt-3", className), children: [
133
+ showHeader ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-xs text-primary-500", children: [
134
+ /* @__PURE__ */ jsx("span", { className: "text-primary-400", children: "✨" }),
135
+ /* @__PURE__ */ jsx("span", { children: isLoading ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
136
+ "Thinking of follow-ups",
137
+ /* @__PURE__ */ jsx(
138
+ HugeiconsIcon,
139
+ {
140
+ icon: Loading03Icon,
141
+ size: 12,
142
+ strokeWidth: 2,
143
+ className: "animate-spin text-primary-400"
144
+ }
145
+ )
146
+ ] }) : source === "openclaw" ? "AI suggestions" : "Follow-up suggestions" })
147
+ ] }) : null,
148
+ /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: suggestions.map((suggestion, index) => /* @__PURE__ */ jsxs(
149
+ "button",
150
+ {
151
+ type: "button",
152
+ disabled,
153
+ onClick: () => onSuggestionClick(suggestion),
154
+ className: cn(
155
+ "group inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full",
156
+ "text-sm text-primary-700 bg-primary-50 border border-primary-200",
157
+ "hover:bg-primary-100 hover:border-primary-300 hover:text-primary-900",
158
+ "focus:outline-none focus:ring-2 focus:ring-primary-500/20 focus:ring-offset-1",
159
+ "transition-all duration-150 cursor-pointer",
160
+ "disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-primary-50 disabled:hover:border-primary-200",
161
+ isLoading && "opacity-75"
162
+ ),
163
+ children: [
164
+ /* @__PURE__ */ jsx("span", { children: suggestion }),
165
+ /* @__PURE__ */ jsx(
166
+ HugeiconsIcon,
167
+ {
168
+ icon: ArrowRight01Icon,
169
+ size: 14,
170
+ strokeWidth: 2,
171
+ className: "text-primary-400 group-hover:text-primary-600 group-hover:translate-x-0.5 transition-all duration-150"
172
+ }
173
+ )
174
+ ]
175
+ },
176
+ `${index}-${suggestion.slice(0, 20)}`
177
+ )) })
178
+ ] });
179
+ }
180
+ const MemoizedFollowUpSuggestions = memo(FollowUpSuggestionsComponent);
181
+ export {
182
+ MemoizedFollowUpSuggestions as FollowUpSuggestions
183
+ };
@@ -12,7 +12,9 @@ const useChatSettingsStore = create()(
12
12
  showToolMessages: true,
13
13
  showReasoningBlocks: true,
14
14
  showSearchSources: true,
15
+ showFollowUps: true,
15
16
  inlineFilePreview: false,
17
+ llmFeaturesModel: "gpt54mini",
16
18
  theme: "system",
17
19
  fontFamily: "system",
18
20
  density: "comfortable",
@@ -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-DaKDqc9w.js";
3
+ import { R as Route } from "./router-CZhxPkYW.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-B_F4DTUu.js";
7
+ import { r as resolveLanguage, C as CodeBlock } from "./index-197lqzv2.js";
8
8
  import { u as useFileExplorerState, D as DialogRoot, a as DialogContent, b as DialogTitle, d as DialogClose } from "./use-file-explorer-state-E6cUvMva.js";
9
9
  import { c as cn, B as Button } from "./button-kI8fEIZQ.js";
10
10
  import { useNavigate, Link } from "@tanstack/react-router";
@@ -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-kI8fEIZQ.js";
6
- import { M as Markdown } from "./markdown-CFdYXCRQ.js";
6
+ import { M as Markdown } from "./markdown-Dk1YdosA.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-B_F4DTUu.js";
16
+ import "./index-197lqzv2.js";
17
17
  import "@hugeicons/react";
18
18
  import "@hugeicons/core-free-icons";
19
19
  import "zustand";
@@ -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-vqXczcVo.js").then((m) => ({
3
+ const MemoryScreen = lazy(() => import("./memory-screen-DA_o-N1Z.js").then((m) => ({
4
4
  default: m.MemoryScreen
5
5
  })));
6
6
  function MemoryRoute() {