opencami 1.3.2 → 1.5.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 (75) hide show
  1. package/README.md +60 -0
  2. package/dist/client/assets/CSPContext-EgWK8bIJ.js +1 -0
  3. package/dist/client/assets/DirectionContext-DXtY05YF.js +1 -0
  4. package/dist/client/assets/_sessionKey-B89e7G3y.js +100 -0
  5. package/dist/client/assets/agents-screen-1BiEZ9od.js +1 -0
  6. package/dist/client/assets/agents-x54ocA9z.js +2 -0
  7. package/dist/client/assets/bots-screen-BNQciUeJ.js +1 -0
  8. package/dist/client/assets/bots-x86ZHG4b.js +2 -0
  9. package/dist/client/assets/button-nDcsaNPl.js +1 -0
  10. package/dist/client/assets/{connect-CtDn993i.js → connect-w4lLOqiJ.js} +1 -1
  11. package/dist/client/assets/file-explorer-screen-CAsjd3w8.js +1 -0
  12. package/dist/client/assets/files-Bype5Mnb.js +2 -0
  13. package/dist/client/assets/{index-N9-2R5hZ.js → index-36G0WCxU.js} +1 -1
  14. package/dist/client/assets/index-BXkRE220.js +153 -0
  15. package/dist/client/assets/keyboard-shortcuts-dialog-BdCeXRjD.js +1 -0
  16. package/dist/client/assets/{main-DrVY5UJU.js → main-B3N0eQFg.js} +129 -17
  17. package/dist/client/assets/opencami-logo-DD0DPFRQ.js +1 -0
  18. package/dist/client/assets/{react-CzqI3gbN.js → react-B16OrBeM.js} +1 -1
  19. package/dist/client/assets/search-dialog-BjTPceEl.js +1 -0
  20. package/dist/client/assets/session-export-dialog-DtHKG2zW.js +1 -0
  21. package/dist/client/assets/settings-dialog-hiqdk_UD.js +1 -0
  22. package/dist/client/assets/skills-DhwyFq3y.js +2 -0
  23. package/dist/client/assets/skills-panel-BLUjzfjJ.js +5 -0
  24. package/dist/client/assets/styles-CHP4l6vZ.css +1 -0
  25. package/dist/client/assets/switch-J6wLIVu2.js +1 -0
  26. package/dist/client/assets/tabs-DvPgTz5I.js +1 -0
  27. package/dist/client/assets/tooltip-C14vdXHK.js +1 -0
  28. package/dist/client/assets/use-file-explorer-state-BnaJEqRP.js +12 -0
  29. package/dist/client/assets/useButton-Bnnac1eR.js +1 -0
  30. package/dist/client/assets/useCompositeItem-BgiEMKAt.js +1 -0
  31. package/dist/client/assets/useControlled-BhUuiHAm.js +1 -0
  32. package/dist/client/assets/useMutation-CFmVaBag.js +1 -0
  33. package/dist/client/assets/visuallyHidden-DCCICp6T.js +9 -0
  34. package/dist/server/assets/{_sessionKey-DVNrEYFh.js → _sessionKey-tRze5NLR.js} +493 -92
  35. package/dist/server/assets/_tanstack-start-manifest_v-CyfoMvUa.js +4 -0
  36. package/dist/server/assets/{agents-Dz_i76VW.js → agents-CmQ4vvXm.js} +1 -1
  37. package/dist/server/assets/{agents-screen-CqQPJndp.js → agents-screen-bmrIyFbk.js} +43 -35
  38. package/dist/server/assets/bots-Byt6jv0a.js +11 -0
  39. package/dist/server/assets/bots-screen-C2TGFv42.js +474 -0
  40. package/dist/server/assets/{button-DtQ3rV1m.js → button-CwY2OHFj.js} +2 -2
  41. package/dist/server/assets/{connect-CIDOw12K.js → connect-d3AqjAqe.js} +2 -2
  42. package/dist/server/assets/{file-explorer-screen-Cx0jiLRU.js → file-explorer-screen-CVlFiAFu.js} +39 -40
  43. package/dist/server/assets/{files-Trs1M5ba.js → files-BIEcSPGp.js} +1 -1
  44. package/dist/server/assets/{index-CmbNTqa2.js → index-CNIATlJ9.js} +93 -38
  45. package/dist/server/assets/{index-Dv2RXDa2.js → index-CRfLKh30.js} +2 -1
  46. package/dist/server/assets/{keyboard-shortcuts-dialog-7OEtXUlW.js → keyboard-shortcuts-dialog-CsNP85q8.js} +2 -2
  47. package/dist/server/assets/{router-OoQe2c20.js → router-rn7pJO_D.js} +515 -78
  48. package/dist/server/assets/{search-dialog-Bq0Pnxdb.js → search-dialog-Bz4Cu0KW.js} +23 -6
  49. package/dist/server/assets/{session-export-dialog-DRVbC8Q-.js → session-export-dialog-CwclV0Aj.js} +2 -2
  50. package/dist/server/assets/{settings-dialog-BsJsnMiu.js → settings-dialog-BBM7jCjE.js} +409 -95
  51. package/dist/server/assets/skills-Cy8xclXY.js +11 -0
  52. package/dist/server/assets/skills-panel-BnRNb7u9.js +762 -0
  53. package/dist/server/assets/{switch-DnX0MjGS.js → switch-BbkUeVDV.js} +1 -1
  54. package/dist/server/assets/tabs-DDFZob0m.js +67 -0
  55. package/dist/server/assets/{tooltip-gbV6rEVv.js → tooltip-DgsSPocE.js} +1 -1
  56. package/dist/server/assets/{use-file-explorer-state-DMHdtb7D.js → use-file-explorer-state-Il1LlBAe.js} +13 -1
  57. package/dist/server/server.js +2 -2
  58. package/package.json +6 -2
  59. package/dist/client/assets/_sessionKey-Z6Wcnj0N.js +0 -97
  60. package/dist/client/assets/agents-D8ZHVQ1Z.js +0 -2
  61. package/dist/client/assets/agents-screen-BVK0QTRH.js +0 -1
  62. package/dist/client/assets/button-CuH8u1uR.js +0 -1
  63. package/dist/client/assets/file-explorer-screen-DMUuR1uG.js +0 -1
  64. package/dist/client/assets/files-CDMLoJ0u.js +0 -2
  65. package/dist/client/assets/index-IGP-Igwt.js +0 -153
  66. package/dist/client/assets/keyboard-shortcuts-dialog-DW--4YLF.js +0 -1
  67. package/dist/client/assets/opencami-logo-ChD2XR2j.js +0 -1
  68. package/dist/client/assets/search-dialog-DYyFYJmw.js +0 -1
  69. package/dist/client/assets/session-export-dialog-BFizBmGb.js +0 -1
  70. package/dist/client/assets/settings-dialog-UvgVi2It.js +0 -1
  71. package/dist/client/assets/styles-BGTCU8mq.css +0 -1
  72. package/dist/client/assets/switch-DxW2OWPG.js +0 -1
  73. package/dist/client/assets/use-file-explorer-state-Cii59H70.js +0 -12
  74. package/dist/client/assets/useButton-hZdvKtl_.js +0 -9
  75. package/dist/server/assets/_tanstack-start-manifest_v-PwRq_yJS.js +0 -4
@@ -1,13 +1,13 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { useState, useRef, useEffect } from "react";
3
- import { c as cn, B as Button } from "./button-DtQ3rV1m.js";
2
+ import { useState, useEffect, useRef } from "react";
3
+ import { B as Button, c as cn } from "./button-CwY2OHFj.js";
4
4
  import { HugeiconsIcon } from "@hugeicons/react";
5
- import { Cancel01Icon, Link01Icon, PaintBoardIcon, MessageEdit01Icon, UserIcon, VoiceIcon, AiBrain01Icon, InformationCircleIcon, ComputerIcon, Sun01Icon, Moon01Icon, Leaf01Icon, Loading02Icon, Tick01Icon, Cancel02Icon } from "@hugeicons/core-free-icons";
6
- import { D as DialogRoot, a as DialogContent, b as DialogTitle, c as DialogDescription, d as DialogClose } from "./use-file-explorer-state-DMHdtb7D.js";
7
- import { S as Switch } from "./switch-DnX0MjGS.js";
8
- import { Tabs as Tabs$1 } from "@base-ui/react/tabs";
9
- import { a as useChatSettings } from "./index-CmbNTqa2.js";
10
- import { u as useLlmSettings, g as getLlmProviderDefaults } from "./_sessionKey-DVNrEYFh.js";
5
+ import { Cancel01Icon, Link01Icon, PaintBoardIcon, MessageEdit01Icon, UserIcon, VoiceIcon, AiBrain01Icon, InformationCircleIcon, ComputerIcon, Sun01Icon, Moon01Icon, Leaf01Icon, DropletIcon, Loading02Icon, Tick01Icon, Cancel02Icon } from "@hugeicons/core-free-icons";
6
+ import { D as DialogRoot, a as DialogContent, b as DialogTitle, c as DialogDescription, d as DialogClose } from "./use-file-explorer-state-Il1LlBAe.js";
7
+ import { S as Switch } from "./switch-BbkUeVDV.js";
8
+ import { T as Tabs, a as TabsList, b as TabsTab } from "./tabs-DDFZob0m.js";
9
+ import { u as useChatSettings } from "./index-CNIATlJ9.js";
10
+ import { u as useLlmSettings, g as getLlmProviderDefaults } from "./_sessionKey-tRze5NLR.js";
11
11
  import "@base-ui/react/merge-props";
12
12
  import "@base-ui/react/use-render";
13
13
  import "class-variance-authority";
@@ -17,6 +17,7 @@ import "@base-ui/react/dialog";
17
17
  import "@base-ui/react/menu";
18
18
  import "zustand";
19
19
  import "@base-ui/react/switch";
20
+ import "@base-ui/react/tabs";
20
21
  import "shiki/core";
21
22
  import "shiki/engine/javascript";
22
23
  import "@shikijs/themes/vitesse-dark";
@@ -53,7 +54,7 @@ import "@shikijs/langs/yaml";
53
54
  import "zustand/middleware";
54
55
  import "@tanstack/react-router";
55
56
  import "@tanstack/react-query";
56
- import "./tooltip-gbV6rEVv.js";
57
+ import "./tooltip-DgsSPocE.js";
57
58
  import "@base-ui/react/tooltip";
58
59
  import "motion/react";
59
60
  import "@base-ui/react/alert-dialog";
@@ -65,91 +66,42 @@ import "react-markdown";
65
66
  import "remark-breaks";
66
67
  import "remark-gfm";
67
68
  import "react-dom";
68
- import "./router-OoQe2c20.js";
69
+ import "./router-rn7pJO_D.js";
69
70
  import "node:crypto";
70
71
  import "ws";
71
72
  import "node:fs";
72
73
  import "node:path";
73
74
  import "node:os";
74
75
  import "@tanstack/router-core/ssr/client";
76
+ import "node:child_process";
75
77
  import "node:fs/promises";
76
78
  import "path";
77
- function Tabs({ className, ...props }) {
78
- return /* @__PURE__ */ jsx(
79
- Tabs$1.Root,
80
- {
81
- className: cn(
82
- "flex flex-col gap-2 data-[orientation=vertical]:flex-row",
83
- className
84
- ),
85
- "data-slot": "tabs",
86
- ...props
87
- }
88
- );
89
- }
90
- function TabsList({
91
- variant = "default",
92
- className,
93
- children,
94
- ...props
95
- }) {
96
- return /* @__PURE__ */ jsxs(
97
- Tabs$1.List,
98
- {
99
- className: cn(
100
- "relative z-0 flex w-fit items-center justify-center gap-x-0.5 text-primary-600",
101
- "data-[orientation=vertical]:flex-col",
102
- variant === "default" ? "p-0.5 text-primary-600/80" : "data-[orientation=vertical]:px-1 data-[orientation=horizontal]:py-1",
103
- className
104
- ),
105
- "data-slot": "tabs-list",
106
- ...props,
107
- children: [
108
- children,
109
- /* @__PURE__ */ jsx(
110
- Tabs$1.Indicator,
111
- {
112
- className: cn(
113
- "-translate-y-(--active-tab-bottom) absolute bottom-0 left-0 h-(--active-tab-height) w-(--active-tab-width) translate-x-(--active-tab-left) transition-[width,translate] duration-200 ease-in-out",
114
- variant === "underline" ? "data-[orientation=vertical]:-translate-x-px z-10 bg-primary-900 data-[orientation=horizontal]:h-0.5 data-[orientation=vertical]:w-0.5 data-[orientation=horizontal]:translate-y-px" : "z-0 rounded-md bg-primary-200"
115
- ),
116
- "data-slot": "tab-indicator"
117
- }
118
- )
119
- ]
120
- }
121
- );
122
- }
123
- function TabsTab({ className, ...props }) {
124
- return /* @__PURE__ */ jsx(
125
- Tabs$1.Tab,
126
- {
127
- className: cn(
128
- '[&_svg]:-mx-0.5 relative z-10 flex h-8 shrink-0 grow cursor-pointer items-center justify-center gap-1.5 whitespace-nowrap rounded-md px-3 text-sm font-medium outline-none transition-[color,background-color,box-shadow] hover:text-primary-900 focus-visible:ring-2 focus-visible:ring-primary-400 data-disabled:pointer-events-none data-[orientation=vertical]:w-full data-[orientation=vertical]:justify-start data-active:text-primary-900 data-disabled:opacity-64 [&_svg:not([class*="size-"])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0',
129
- className
130
- ),
131
- "data-slot": "tabs-tab",
132
- ...props
133
- }
134
- );
135
- }
136
79
  function SettingsSection({ title, tabId, activeTab, children }) {
137
80
  const hiddenOnDesktop = tabId && activeTab && tabId !== activeTab;
138
81
  return /* @__PURE__ */ jsxs("div", { className: cn(
139
- "border-b border-primary-200 py-4 last:border-0",
82
+ "border-b border-primary-200 py-2 last:border-0",
140
83
  hiddenOnDesktop && "md:hidden"
141
84
  ), children: [
142
- /* @__PURE__ */ jsx("h3", { className: "mb-3 text-sm font-medium text-primary-900", children: title }),
143
- /* @__PURE__ */ jsx("div", { className: "space-y-3", children })
85
+ /* @__PURE__ */ jsx("h3", { className: "mb-1.5 text-sm font-semibold text-primary-700", children: title }),
86
+ /* @__PURE__ */ jsx("div", { className: "space-y-1.5", children })
144
87
  ] });
145
88
  }
146
- function SettingsRow({ label, description, children }) {
147
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
148
- /* @__PURE__ */ jsxs("div", { className: "flex-1 select-none", children: [
149
- /* @__PURE__ */ jsx("div", { className: "text-sm text-primary-800", children: label }),
89
+ function SettingsRow({ label, description, inline, children }) {
90
+ if (inline) {
91
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
92
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 select-none", children: [
93
+ /* @__PURE__ */ jsx("div", { className: "text-[13px] font-medium text-primary-800", children: label }),
94
+ description && /* @__PURE__ */ jsx("div", { className: "text-xs text-primary-500", children: description })
95
+ ] }),
96
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children })
97
+ ] });
98
+ }
99
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
100
+ /* @__PURE__ */ jsxs("div", { className: "select-none", children: [
101
+ /* @__PURE__ */ jsx("div", { className: "text-[13px] font-medium text-primary-800", children: label }),
150
102
  description && /* @__PURE__ */ jsx("div", { className: "text-xs text-primary-500", children: description })
151
103
  ] }),
152
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children })
104
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 flex-wrap", children })
153
105
  ] });
154
106
  }
155
107
  const textSizeOptions = [
@@ -158,9 +110,79 @@ const textSizeOptions = [
158
110
  { value: "18px", label: "L" },
159
111
  { value: "20px", label: "XL" }
160
112
  ];
113
+ const fontFamilyOptions = [
114
+ {
115
+ value: "system",
116
+ label: "System",
117
+ cssValue: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
118
+ previewClass: "font-sans"
119
+ },
120
+ {
121
+ value: "inter",
122
+ label: "Inter",
123
+ cssValue: '"Inter", sans-serif',
124
+ previewClass: 'font-["Inter",sans-serif]'
125
+ },
126
+ {
127
+ value: "roboto",
128
+ label: "Roboto",
129
+ cssValue: '"Roboto", sans-serif',
130
+ previewClass: 'font-["Roboto",sans-serif]'
131
+ }
132
+ ];
133
+ const densityOptions = [
134
+ { value: "compact", label: "Compact" },
135
+ { value: "comfortable", label: "Comfortable" },
136
+ { value: "spacious", label: "Spacious" }
137
+ ];
138
+ const accentColorOptions = [
139
+ { value: "green", label: "Green", accent: "#22c55e", hover: "#16a34a", light: "rgba(34, 197, 94, 0.10)" },
140
+ { value: "blue", label: "Blue", accent: "#3b82f6", hover: "#2563eb", light: "rgba(59, 130, 246, 0.10)" },
141
+ { value: "purple", label: "Purple", accent: "#8b5cf6", hover: "#7c3aed", light: "rgba(139, 92, 246, 0.10)" },
142
+ { value: "orange", label: "Orange", accent: "#f97316", hover: "#ea580c", light: "rgba(249, 115, 22, 0.10)" },
143
+ { value: "pink", label: "Pink", accent: "#ec4899", hover: "#db2777", light: "rgba(236, 72, 153, 0.10)" },
144
+ { value: "red", label: "Red", accent: "#ef4444", hover: "#dc2626", light: "rgba(239, 68, 68, 0.10)" },
145
+ { value: "cyan", label: "Cyan", accent: "#06b6d4", hover: "#0891b2", light: "rgba(6, 182, 212, 0.10)" },
146
+ { value: "yellow", label: "Yellow", accent: "#eab308", hover: "#ca8a04", light: "rgba(234, 179, 8, 0.10)" }
147
+ ];
148
+ const chatWidthOptions = [
149
+ { value: "narrow", label: "Narrow", cssValue: "640px" },
150
+ { value: "medium", label: "Medium", cssValue: "800px" },
151
+ { value: "wide", label: "Wide", cssValue: "1000px" },
152
+ { value: "full", label: "Full", cssValue: "100%" }
153
+ ];
154
+ const sidebarWidthOptions = [
155
+ { value: "compact", label: "Compact", cssValue: "200px" },
156
+ { value: "normal", label: "Normal", cssValue: "260px" },
157
+ { value: "wide", label: "Wide", cssValue: "320px" },
158
+ { value: "xl", label: "XL", cssValue: "400px" }
159
+ ];
160
+ const bubbleStyleOptions = [
161
+ { value: "default", label: "Default" },
162
+ { value: "bubbles", label: "Bubbles" },
163
+ { value: "minimal", label: "Minimal" }
164
+ ];
161
165
  function isTextSizeValue(value) {
162
166
  return textSizeOptions.some((option) => option.value === value);
163
167
  }
168
+ function isFontFamilyValue(value) {
169
+ return fontFamilyOptions.some((option) => option.value === value);
170
+ }
171
+ function isDensityValue(value) {
172
+ return densityOptions.some((option) => option.value === value);
173
+ }
174
+ function isAccentColorValue(value) {
175
+ return accentColorOptions.some((option) => option.value === value);
176
+ }
177
+ function isChatWidthValue(value) {
178
+ return chatWidthOptions.some((option) => option.value === value);
179
+ }
180
+ function isSidebarWidthValue(value) {
181
+ return sidebarWidthOptions.some((option) => option.value === value);
182
+ }
183
+ function isBubbleStyleValue(value) {
184
+ return bubbleStyleOptions.some((option) => option.value === value);
185
+ }
164
186
  function SettingsDialog({
165
187
  open,
166
188
  onOpenChange,
@@ -219,6 +241,90 @@ function SettingsDialog({
219
241
  return "auto";
220
242
  }
221
243
  });
244
+ useEffect(() => {
245
+ if (typeof window === "undefined") return;
246
+ try {
247
+ const storedFontFamily = localStorage.getItem("opencami-font-family");
248
+ if (storedFontFamily && isFontFamilyValue(storedFontFamily)) {
249
+ applyFontFamily(storedFontFamily);
250
+ if (settings.fontFamily !== storedFontFamily) {
251
+ updateSettings({ fontFamily: storedFontFamily });
252
+ }
253
+ } else {
254
+ applyFontFamily(settings.fontFamily);
255
+ }
256
+ const storedDensity = localStorage.getItem("opencami-density");
257
+ if (storedDensity && isDensityValue(storedDensity)) {
258
+ applyDensity(storedDensity);
259
+ if (settings.density !== storedDensity) {
260
+ updateSettings({ density: storedDensity });
261
+ }
262
+ } else {
263
+ applyDensity(settings.density);
264
+ }
265
+ const storedAccentColor = localStorage.getItem("opencami-accent-color");
266
+ if (storedAccentColor && isAccentColorValue(storedAccentColor)) {
267
+ applyAccentColor(storedAccentColor);
268
+ if (settings.accentColor !== storedAccentColor) {
269
+ updateSettings({ accentColor: storedAccentColor });
270
+ }
271
+ } else {
272
+ applyAccentColor(settings.accentColor);
273
+ }
274
+ const storedChatWidth = localStorage.getItem("opencami-chat-width");
275
+ if (storedChatWidth && isChatWidthValue(storedChatWidth)) {
276
+ applyChatWidth(storedChatWidth);
277
+ if (settings.chatWidth !== storedChatWidth) {
278
+ updateSettings({ chatWidth: storedChatWidth });
279
+ }
280
+ } else {
281
+ applyChatWidth(settings.chatWidth);
282
+ }
283
+ const storedSidebarWidth = localStorage.getItem("opencami-sidebar-width");
284
+ if (storedSidebarWidth && isSidebarWidthValue(storedSidebarWidth)) {
285
+ applySidebarWidth(storedSidebarWidth);
286
+ if (settings.sidebarWidth !== storedSidebarWidth) {
287
+ updateSettings({ sidebarWidth: storedSidebarWidth });
288
+ }
289
+ } else {
290
+ applySidebarWidth(settings.sidebarWidth);
291
+ }
292
+ const storedBubbleStyle = localStorage.getItem("opencami-bubble-style");
293
+ if (storedBubbleStyle && isBubbleStyleValue(storedBubbleStyle)) {
294
+ applyBubbleStyle(storedBubbleStyle);
295
+ if (settings.bubbleStyle !== storedBubbleStyle) {
296
+ updateSettings({ bubbleStyle: storedBubbleStyle });
297
+ }
298
+ } else {
299
+ applyBubbleStyle(settings.bubbleStyle);
300
+ }
301
+ } catch {
302
+ applyFontFamily(settings.fontFamily);
303
+ applyDensity(settings.density);
304
+ applyAccentColor(settings.accentColor);
305
+ applyChatWidth(settings.chatWidth);
306
+ applySidebarWidth(settings.sidebarWidth);
307
+ applyBubbleStyle(settings.bubbleStyle);
308
+ }
309
+ }, []);
310
+ useEffect(() => {
311
+ applyFontFamily(settings.fontFamily);
312
+ }, [settings.fontFamily]);
313
+ useEffect(() => {
314
+ applyDensity(settings.density);
315
+ }, [settings.density]);
316
+ useEffect(() => {
317
+ applyAccentColor(settings.accentColor);
318
+ }, [settings.accentColor]);
319
+ useEffect(() => {
320
+ applyChatWidth(settings.chatWidth);
321
+ }, [settings.chatWidth]);
322
+ useEffect(() => {
323
+ applySidebarWidth(settings.sidebarWidth);
324
+ }, [settings.sidebarWidth]);
325
+ useEffect(() => {
326
+ applyBubbleStyle(settings.bubbleStyle);
327
+ }, [settings.bubbleStyle]);
222
328
  const handleTtsProviderChange = (value) => {
223
329
  setTtsProvider(value);
224
330
  try {
@@ -244,6 +350,54 @@ function SettingsDialog({
244
350
  if (typeof document === "undefined") return;
245
351
  document.documentElement.style.setProperty("--opencami-text-size", value);
246
352
  }
353
+ function applyFontFamily(value) {
354
+ if (typeof document === "undefined") return;
355
+ const selected = fontFamilyOptions.find((option) => option.value === value);
356
+ const cssValue = selected?.cssValue ?? fontFamilyOptions[0].cssValue;
357
+ document.documentElement.style.setProperty("--opencami-font-family", cssValue);
358
+ }
359
+ function applyDensity(value) {
360
+ if (typeof document === "undefined") return;
361
+ const root = document.documentElement;
362
+ root.style.setProperty("--opencami-density", value);
363
+ if (value === "compact") {
364
+ root.style.setProperty("--opencami-msg-padding-y", "0.25rem");
365
+ root.style.setProperty("--opencami-msg-gap", "0.25rem");
366
+ root.style.setProperty("--opencami-user-bubble-py", "0.4rem");
367
+ return;
368
+ }
369
+ if (value === "spacious") {
370
+ root.style.setProperty("--opencami-msg-padding-y", "1.25rem");
371
+ root.style.setProperty("--opencami-msg-gap", "1rem");
372
+ root.style.setProperty("--opencami-user-bubble-py", "1rem");
373
+ return;
374
+ }
375
+ root.style.setProperty("--opencami-msg-padding-y", "0.75rem");
376
+ root.style.setProperty("--opencami-msg-gap", "0.5rem");
377
+ root.style.setProperty("--opencami-user-bubble-py", "0.625rem");
378
+ }
379
+ function applyAccentColor(value) {
380
+ if (typeof document === "undefined") return;
381
+ const selected = accentColorOptions.find((option) => option.value === value) ?? accentColorOptions[0];
382
+ const root = document.documentElement;
383
+ root.style.setProperty("--opencami-accent", selected.accent);
384
+ root.style.setProperty("--opencami-accent-hover", selected.hover);
385
+ root.style.setProperty("--opencami-accent-light", selected.light);
386
+ }
387
+ function applyChatWidth(value) {
388
+ if (typeof document === "undefined") return;
389
+ const selected = chatWidthOptions.find((option) => option.value === value) ?? chatWidthOptions[2];
390
+ document.documentElement.style.setProperty("--opencami-chat-width", selected.cssValue);
391
+ }
392
+ function applySidebarWidth(value) {
393
+ if (typeof document === "undefined") return;
394
+ const selected = sidebarWidthOptions.find((option) => option.value === value) ?? sidebarWidthOptions[1];
395
+ document.documentElement.style.setProperty("--opencami-sidebar-width", selected.cssValue);
396
+ }
397
+ function applyBubbleStyle(value) {
398
+ if (typeof document === "undefined") return;
399
+ document.documentElement.setAttribute("data-opencami-bubble-style", value);
400
+ }
247
401
  const handleTextSizeChange = (value) => {
248
402
  if (!isTextSizeValue(value)) return;
249
403
  setTextSize(value);
@@ -253,6 +407,60 @@ function SettingsDialog({
253
407
  } catch {
254
408
  }
255
409
  };
410
+ const handleFontFamilyChange = (value) => {
411
+ if (!isFontFamilyValue(value)) return;
412
+ applyFontFamily(value);
413
+ updateSettings({ fontFamily: value });
414
+ try {
415
+ localStorage.setItem("opencami-font-family", value);
416
+ } catch {
417
+ }
418
+ };
419
+ const handleDensityChange = (value) => {
420
+ if (!isDensityValue(value)) return;
421
+ applyDensity(value);
422
+ updateSettings({ density: value });
423
+ try {
424
+ localStorage.setItem("opencami-density", value);
425
+ } catch {
426
+ }
427
+ };
428
+ const handleAccentColorChange = (value) => {
429
+ if (!isAccentColorValue(value)) return;
430
+ applyAccentColor(value);
431
+ updateSettings({ accentColor: value });
432
+ try {
433
+ localStorage.setItem("opencami-accent-color", value);
434
+ } catch {
435
+ }
436
+ };
437
+ const handleChatWidthChange = (value) => {
438
+ if (!isChatWidthValue(value)) return;
439
+ applyChatWidth(value);
440
+ updateSettings({ chatWidth: value });
441
+ try {
442
+ localStorage.setItem("opencami-chat-width", value);
443
+ } catch {
444
+ }
445
+ };
446
+ const handleSidebarWidthChange = (value) => {
447
+ if (!isSidebarWidthValue(value)) return;
448
+ applySidebarWidth(value);
449
+ updateSettings({ sidebarWidth: value });
450
+ try {
451
+ localStorage.setItem("opencami-sidebar-width", value);
452
+ } catch {
453
+ }
454
+ };
455
+ const handleBubbleStyleChange = (value) => {
456
+ if (!isBubbleStyleValue(value)) return;
457
+ applyBubbleStyle(value);
458
+ updateSettings({ bubbleStyle: value });
459
+ try {
460
+ localStorage.setItem("opencami-bubble-style", value);
461
+ } catch {
462
+ }
463
+ };
256
464
  const handleTtsToggle = (checked) => {
257
465
  setTtsEnabled(checked);
258
466
  try {
@@ -333,22 +541,30 @@ function SettingsDialog({
333
541
  setTestResult(null);
334
542
  };
335
543
  const themeOptions = [
336
- { value: "system", label: "System", icon: ComputerIcon },
544
+ { value: "system", label: "Auto", icon: ComputerIcon },
337
545
  { value: "light", label: "Light", icon: Sun01Icon },
338
546
  { value: "dark", label: "Dark", icon: Moon01Icon },
339
- { value: "chameleon", label: "Chameleon", icon: Leaf01Icon }
547
+ { value: "chameleon", label: "Cham", icon: Leaf01Icon },
548
+ { value: "frost-light", label: "Ice", icon: DropletIcon },
549
+ { value: "frost-dark", label: "Noir", icon: DropletIcon }
340
550
  ];
341
551
  function applyTheme(theme) {
342
552
  if (typeof document === "undefined") return;
343
553
  const root = document.documentElement;
344
554
  const media = window.matchMedia("(prefers-color-scheme: dark)");
345
- root.classList.remove("light", "dark", "system", "chameleon");
555
+ root.classList.remove("light", "dark", "system", "chameleon", "frost", "frost-light", "frost-dark");
346
556
  root.classList.add(theme);
557
+ if (theme === "frost-light" || theme === "frost-dark") {
558
+ root.classList.add("frost");
559
+ }
560
+ if (theme === "frost-dark") {
561
+ root.classList.add("dark");
562
+ }
347
563
  if (theme === "system" && media.matches) {
348
564
  root.classList.add("dark");
349
565
  }
350
566
  }
351
- return /* @__PURE__ */ jsx(DialogRoot, { open, onOpenChange, children: /* @__PURE__ */ jsx(DialogContent, { className: "w-[min(720px,92vw)] max-h-[80vh] overflow-hidden", children: /* @__PURE__ */ jsxs("div", { className: "p-4", children: [
567
+ return /* @__PURE__ */ jsx(DialogRoot, { open, onOpenChange, children: /* @__PURE__ */ jsx(DialogContent, { className: "w-[min(680px,92vw)] max-h-[85vh] overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "p-3", children: [
352
568
  /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between", children: [
353
569
  /* @__PURE__ */ jsxs("div", { children: [
354
570
  /* @__PURE__ */ jsx(DialogTitle, { className: "mb-1", children: "Settings" }),
@@ -377,7 +593,7 @@ function SettingsDialog({
377
593
  }
378
594
  )
379
595
  ] }),
380
- /* @__PURE__ */ jsxs("div", { className: "mt-3 flex md:flex-row flex-col md:gap-4 gap-0 md:min-h-[400px]", children: [
596
+ /* @__PURE__ */ jsxs("div", { className: "mt-2 flex md:flex-row flex-col md:gap-3 gap-0 md:min-h-[400px]", children: [
381
597
  /* @__PURE__ */ jsx("nav", { className: "hidden md:flex flex-col gap-0.5 min-w-[160px] border-r border-primary-200 pr-3", children: [
382
598
  { id: "connection", label: "Connection", icon: Link01Icon },
383
599
  { id: "appearance", label: "Appearance", icon: PaintBoardIcon },
@@ -392,8 +608,9 @@ function SettingsDialog({
392
608
  onClick: () => setActiveTab(tab.id),
393
609
  className: cn(
394
610
  "flex items-center gap-2 px-2.5 py-1.5 rounded-md text-sm text-left transition-colors",
395
- activeTab === tab.id ? "bg-primary-100 text-primary-900 font-medium" : "text-primary-600 hover:text-primary-900 hover:bg-primary-50"
611
+ activeTab === tab.id ? "text-primary-900 font-medium" : "text-primary-600 hover:text-primary-900 hover:bg-primary-50"
396
612
  ),
613
+ style: activeTab === tab.id ? { backgroundColor: "var(--opencami-accent-light)" } : void 0,
397
614
  children: [
398
615
  /* @__PURE__ */ jsx(HugeiconsIcon, { icon: tab.icon, size: 16, strokeWidth: 1.5 }),
399
616
  tab.label
@@ -401,8 +618,8 @@ function SettingsDialog({
401
618
  },
402
619
  tab.id
403
620
  )) }),
404
- /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto md:max-h-[calc(80vh-100px)] max-h-none", children: [
405
- /* @__PURE__ */ jsx(SettingsSection, { title: "Connection", tabId: "connection", activeTab, children: /* @__PURE__ */ jsx(SettingsRow, { label: "Status", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-sm text-green-600", children: [
621
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto md:max-h-[calc(85vh-90px)] max-h-none", children: [
622
+ /* @__PURE__ */ jsx(SettingsSection, { title: "Connection", tabId: "connection", activeTab, children: /* @__PURE__ */ jsx(SettingsRow, { inline: true, label: "Status", children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 text-sm text-green-600", children: [
406
623
  /* @__PURE__ */ jsx("span", { className: "size-2 rounded-full bg-green-500" }),
407
624
  "Connected"
408
625
  ] }) }) }),
@@ -420,13 +637,13 @@ function SettingsDialog({
420
637
  TabsList,
421
638
  {
422
639
  variant: "default",
423
- className: "gap-2 *:data-[slot=tab-indicator]:duration-0",
424
- children: themeOptions.map((option) => /* @__PURE__ */ jsxs(TabsTab, { value: option.value, children: [
425
- /* @__PURE__ */ jsx(
640
+ className: "gap-1.5 flex-wrap *:data-[slot=tab-indicator]:duration-0",
641
+ children: themeOptions.map((option) => /* @__PURE__ */ jsxs(TabsTab, { value: option.value, className: "text-[11px] px-1 py-0.5 gap-0.5", children: [
642
+ option.icon && /* @__PURE__ */ jsx(
426
643
  HugeiconsIcon,
427
644
  {
428
645
  icon: option.icon,
429
- size: 20,
646
+ size: 13,
430
647
  strokeWidth: 1.5
431
648
  }
432
649
  ),
@@ -436,11 +653,44 @@ function SettingsDialog({
436
653
  )
437
654
  }
438
655
  ) }),
656
+ /* @__PURE__ */ jsx(
657
+ SettingsRow,
658
+ {
659
+ label: "Accent Color",
660
+ children: /* @__PURE__ */ jsx("div", { className: "flex gap-0.5 flex-wrap", children: accentColorOptions.map((option) => {
661
+ const selected = settings.accentColor === option.value;
662
+ return /* @__PURE__ */ jsx(
663
+ "button",
664
+ {
665
+ type: "button",
666
+ onClick: () => handleAccentColorChange(option.value),
667
+ className: cn(
668
+ "flex items-center justify-center rounded-md p-1 transition-all duration-150",
669
+ selected ? "scale-110" : "hover:bg-primary-50 hover:scale-105"
670
+ ),
671
+ children: /* @__PURE__ */ jsx(
672
+ "span",
673
+ {
674
+ className: cn(
675
+ "size-6 rounded-full transition-shadow duration-150",
676
+ selected ? "ring-2 ring-offset-2" : "border-2 border-primary-200"
677
+ ),
678
+ style: {
679
+ backgroundColor: option.accent,
680
+ ...selected ? { "--tw-ring-color": option.accent } : {}
681
+ }
682
+ }
683
+ )
684
+ },
685
+ option.value
686
+ );
687
+ }) })
688
+ }
689
+ ),
439
690
  /* @__PURE__ */ jsx(
440
691
  SettingsRow,
441
692
  {
442
693
  label: "Text Size",
443
- description: "Adjust chat and composer text",
444
694
  children: /* @__PURE__ */ jsx(Tabs, { value: textSize, onValueChange: handleTextSizeChange, children: /* @__PURE__ */ jsx(
445
695
  TabsList,
446
696
  {
@@ -450,24 +700,29 @@ function SettingsDialog({
450
700
  }
451
701
  ) })
452
702
  }
453
- )
703
+ ),
704
+ /* @__PURE__ */ jsx(SettingsRow, { inline: true, label: "Font", children: /* @__PURE__ */ jsx(Tabs, { value: settings.fontFamily, onValueChange: handleFontFamilyChange, children: /* @__PURE__ */ jsx(TabsList, { variant: "default", className: "gap-1 *:data-[slot=tab-indicator]:duration-0", children: fontFamilyOptions.map((option) => /* @__PURE__ */ jsx(TabsTab, { value: option.value, children: /* @__PURE__ */ jsx("span", { className: "text-xs", style: { fontFamily: option.cssValue }, children: option.label }) }, option.value)) }) }) }),
705
+ /* @__PURE__ */ jsx(SettingsRow, { inline: true, label: "Density", children: /* @__PURE__ */ jsx(Tabs, { value: settings.density, onValueChange: handleDensityChange, children: /* @__PURE__ */ jsx(TabsList, { variant: "default", className: "gap-1 *:data-[slot=tab-indicator]:duration-0", children: densityOptions.map((option) => /* @__PURE__ */ jsx(TabsTab, { value: option.value, children: /* @__PURE__ */ jsx("span", { className: "text-xs", children: option.label }) }, option.value)) }) }) }),
706
+ /* @__PURE__ */ jsx(SettingsRow, { inline: true, label: "Bubbles", children: /* @__PURE__ */ jsx(Tabs, { value: settings.bubbleStyle, onValueChange: handleBubbleStyleChange, children: /* @__PURE__ */ jsx(TabsList, { variant: "default", className: "gap-1 *:data-[slot=tab-indicator]:duration-0", children: bubbleStyleOptions.map((option) => /* @__PURE__ */ jsx(TabsTab, { value: option.value, children: /* @__PURE__ */ jsx("span", { className: "text-xs", children: option.label }) }, option.value)) }) }) }),
707
+ /* @__PURE__ */ jsx(SettingsRow, { inline: true, label: "Chat Width", children: /* @__PURE__ */ jsx(Tabs, { value: settings.chatWidth, onValueChange: handleChatWidthChange, children: /* @__PURE__ */ jsx(TabsList, { variant: "default", className: "gap-1 *:data-[slot=tab-indicator]:duration-0", children: chatWidthOptions.map((option) => /* @__PURE__ */ jsx(TabsTab, { value: option.value, children: /* @__PURE__ */ jsx("span", { className: "text-xs", children: option.label }) }, option.value)) }) }) }),
708
+ /* @__PURE__ */ jsx(SettingsRow, { inline: true, label: "Sidebar", children: /* @__PURE__ */ jsx(Tabs, { value: settings.sidebarWidth, onValueChange: handleSidebarWidthChange, children: /* @__PURE__ */ jsx(TabsList, { variant: "default", className: "gap-1 *:data-[slot=tab-indicator]:duration-0", children: sidebarWidthOptions.map((option) => /* @__PURE__ */ jsx(TabsTab, { value: option.value, children: /* @__PURE__ */ jsx("span", { className: "text-xs", children: option.label }) }, option.value)) }) }) })
454
709
  ] }),
455
710
  /* @__PURE__ */ jsxs(SettingsSection, { title: "Chat", tabId: "chat", activeTab, children: [
456
- /* @__PURE__ */ jsx(SettingsRow, { label: "Show tool messages", children: /* @__PURE__ */ jsx(
711
+ /* @__PURE__ */ jsx(SettingsRow, { inline: true, label: "Show tool messages", children: /* @__PURE__ */ jsx(
457
712
  Switch,
458
713
  {
459
714
  checked: settings.showToolMessages,
460
715
  onCheckedChange: (checked) => updateSettings({ showToolMessages: checked })
461
716
  }
462
717
  ) }),
463
- /* @__PURE__ */ jsx(SettingsRow, { label: "Show reasoning blocks", children: /* @__PURE__ */ jsx(
718
+ /* @__PURE__ */ jsx(SettingsRow, { inline: true, label: "Show reasoning blocks", children: /* @__PURE__ */ jsx(
464
719
  Switch,
465
720
  {
466
721
  checked: settings.showReasoningBlocks,
467
722
  onCheckedChange: (checked) => updateSettings({ showReasoningBlocks: checked })
468
723
  }
469
724
  ) }),
470
- /* @__PURE__ */ jsx(SettingsRow, { label: "Show search sources", children: /* @__PURE__ */ jsx(
725
+ /* @__PURE__ */ jsx(SettingsRow, { inline: true, label: "Show search sources", children: /* @__PURE__ */ jsx(
471
726
  Switch,
472
727
  {
473
728
  checked: settings.showSearchSources,
@@ -477,6 +732,7 @@ function SettingsDialog({
477
732
  /* @__PURE__ */ jsx(
478
733
  SettingsRow,
479
734
  {
735
+ inline: true,
480
736
  label: "Agent Manager (Beta)",
481
737
  description: "Show Agent Manager in sidebar for creating and managing agents",
482
738
  children: /* @__PURE__ */ jsx(
@@ -500,6 +756,55 @@ function SettingsDialog({
500
756
  /* @__PURE__ */ jsx(
501
757
  SettingsRow,
502
758
  {
759
+ inline: true,
760
+ label: "Skills Browser (Beta)",
761
+ description: "Browse and install skills from ClawHub",
762
+ children: /* @__PURE__ */ jsx(
763
+ Switch,
764
+ {
765
+ checked: (() => {
766
+ try {
767
+ return localStorage.getItem("opencami-skills-browser") === "true";
768
+ } catch {
769
+ return false;
770
+ }
771
+ })(),
772
+ onCheckedChange: (checked) => {
773
+ localStorage.setItem("opencami-skills-browser", String(checked));
774
+ window.location.reload();
775
+ }
776
+ }
777
+ )
778
+ }
779
+ ),
780
+ /* @__PURE__ */ jsx(
781
+ SettingsRow,
782
+ {
783
+ inline: true,
784
+ label: "Cron Jobs Panel (Beta)",
785
+ description: "Show Cron Jobs in sidebar for managing OpenClaw cron schedules",
786
+ children: /* @__PURE__ */ jsx(
787
+ Switch,
788
+ {
789
+ checked: (() => {
790
+ try {
791
+ return localStorage.getItem("opencami-cron-manager") === "true";
792
+ } catch {
793
+ return false;
794
+ }
795
+ })(),
796
+ onCheckedChange: (checked) => {
797
+ localStorage.setItem("opencami-cron-manager", String(checked));
798
+ window.location.reload();
799
+ }
800
+ }
801
+ )
802
+ }
803
+ ),
804
+ /* @__PURE__ */ jsx(
805
+ SettingsRow,
806
+ {
807
+ inline: true,
503
808
  label: "Inline File Preview",
504
809
  description: "Make file paths in messages clickable to preview file contents",
505
810
  children: /* @__PURE__ */ jsx(
@@ -516,6 +821,7 @@ function SettingsDialog({
516
821
  personasAvailable ? /* @__PURE__ */ jsx(
517
822
  SettingsRow,
518
823
  {
824
+ inline: true,
519
825
  label: "Persona Picker",
520
826
  description: "Show persona picker in chat (20 personalities)",
521
827
  children: /* @__PURE__ */ jsx(
@@ -529,6 +835,7 @@ function SettingsDialog({
529
835
  ) : /* @__PURE__ */ jsx(
530
836
  SettingsRow,
531
837
  {
838
+ inline: true,
532
839
  label: "Persona Picker",
533
840
  description: "Install the Personas skill to unlock 20 AI personalities",
534
841
  children: /* @__PURE__ */ jsx(Switch, { checked: false, disabled: true })
@@ -549,6 +856,7 @@ function SettingsDialog({
549
856
  /* @__PURE__ */ jsx(
550
857
  SettingsRow,
551
858
  {
859
+ inline: true,
552
860
  label: "Voice Playback",
553
861
  description: "Add a 🔊 button to AI messages for text-to-speech",
554
862
  children: /* @__PURE__ */ jsx(
@@ -563,6 +871,7 @@ function SettingsDialog({
563
871
  /* @__PURE__ */ jsx(
564
872
  SettingsRow,
565
873
  {
874
+ inline: true,
566
875
  label: "TTS Provider",
567
876
  description: "Choose which service generates speech",
568
877
  children: /* @__PURE__ */ jsxs(
@@ -584,6 +893,7 @@ function SettingsDialog({
584
893
  ttsProvider === "openai" && /* @__PURE__ */ jsx(
585
894
  SettingsRow,
586
895
  {
896
+ inline: true,
587
897
  label: "Voice",
588
898
  description: "OpenAI voice selection",
589
899
  children: /* @__PURE__ */ jsx(
@@ -601,6 +911,7 @@ function SettingsDialog({
601
911
  /* @__PURE__ */ jsx(SettingsSection, { title: "Speech-to-Text", tabId: "voice", activeTab, children: /* @__PURE__ */ jsx(
602
912
  SettingsRow,
603
913
  {
914
+ inline: true,
604
915
  label: "STT Provider",
605
916
  description: "Choose which service transcribes your voice",
606
917
  children: /* @__PURE__ */ jsxs(
@@ -628,6 +939,7 @@ function SettingsDialog({
628
939
  /* @__PURE__ */ jsx(
629
940
  SettingsRow,
630
941
  {
942
+ inline: true,
631
943
  label: "Provider",
632
944
  description: "Choose LLM provider for titles & follow-ups",
633
945
  children: /* @__PURE__ */ jsxs(
@@ -656,6 +968,7 @@ function SettingsDialog({
656
968
  /* @__PURE__ */ jsx(
657
969
  SettingsRow,
658
970
  {
971
+ inline: true,
659
972
  label: "Smart session titles",
660
973
  description: "Generate concise titles using AI",
661
974
  children: /* @__PURE__ */ jsx(
@@ -671,6 +984,7 @@ function SettingsDialog({
671
984
  /* @__PURE__ */ jsx(
672
985
  SettingsRow,
673
986
  {
987
+ inline: true,
674
988
  label: "Smart follow-up suggestions",
675
989
  description: "AI-generated contextual follow-ups",
676
990
  children: /* @__PURE__ */ jsx(
@@ -818,7 +1132,7 @@ function SettingsDialog({
818
1132
  ] })
819
1133
  ] })
820
1134
  ] }),
821
- /* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-end", children: /* @__PURE__ */ jsx(DialogClose, { onClick: onClose, children: "Close" }) })
1135
+ /* @__PURE__ */ jsx("div", { className: "mt-2 flex justify-end", children: /* @__PURE__ */ jsx(DialogClose, { onClick: onClose, children: "Close" }) })
822
1136
  ] }) }) });
823
1137
  }
824
1138
  export {