opencami 1.4.0 → 1.5.1

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 (112) hide show
  1. package/README.md +60 -0
  2. package/dist/client/assets/CSPContext-BBLAL_m_.js +1 -0
  3. package/dist/client/assets/DirectionContext-DXnZc0zz.js +1 -0
  4. package/dist/client/assets/_sessionKey-BidmO1-D.js +100 -0
  5. package/dist/client/assets/agents-CtZs_u1j.js +2 -0
  6. package/dist/client/assets/agents-screen-Basce5qo.js +1 -0
  7. package/dist/client/assets/bots-C_dWjy3z.js +2 -0
  8. package/dist/client/assets/bots-screen-n_xhYOEE.js +1 -0
  9. package/dist/client/assets/button-BaHefIXU.js +1 -0
  10. package/dist/client/assets/c-BIGW1oBm.js +1 -0
  11. package/dist/client/assets/{connect-D3baVDFL.js → connect-DHr3hhUR.js} +1 -1
  12. package/dist/client/assets/core-BrHBc0Zp.js +12 -0
  13. package/dist/client/assets/cpp-B-lmv-kZ.js +1 -0
  14. package/dist/client/assets/csharp-K5feNrxe.js +1 -0
  15. package/dist/client/assets/css-DPfMkruS.js +1 -0
  16. package/dist/client/assets/diff-D97Zzqfu.js +1 -0
  17. package/dist/client/assets/dockerfile-BcOcwvcX.js +1 -0
  18. package/dist/client/assets/engine-javascript-PwbX1GN8.js +141 -0
  19. package/dist/client/assets/file-explorer-screen-8t6M4Xco.js +1 -0
  20. package/dist/client/assets/files-BdlpK3Cy.js +2 -0
  21. package/dist/client/assets/go-Dn2_MT6a.js +1 -0
  22. package/dist/client/assets/graphql-ChdNCCLP.js +1 -0
  23. package/dist/client/assets/html-GMplVEZG.js +1 -0
  24. package/dist/client/assets/index-B2iG4EM1.js +3 -0
  25. package/dist/client/assets/{index-ByIsZcHh.js → index-GTR-Xzl2.js} +1 -1
  26. package/dist/client/assets/index-T4TOjvD0.js +1 -0
  27. package/dist/client/assets/java-CylS5w8V.js +1 -0
  28. package/dist/client/assets/javascript-wDzz0qaB.js +1 -0
  29. package/dist/client/assets/json-Cp-IABpG.js +1 -0
  30. package/dist/client/assets/jsx-g9-lgVsj.js +1 -0
  31. package/dist/client/assets/keyboard-shortcuts-dialog-CcKSlK52.js +1 -0
  32. package/dist/client/assets/kotlin-BdnUsdx6.js +1 -0
  33. package/dist/client/assets/{main-CkIF0soY.js → main-mIHr_ble.js} +129 -17
  34. package/dist/client/assets/markdown-Cvjx9yec.js +1 -0
  35. package/dist/client/assets/{opencami-logo-CIxSO1oo.js → opencami-logo-CRIdKbbZ.js} +1 -1
  36. package/dist/client/assets/php-CDn_0X-4.js +1 -0
  37. package/dist/client/assets/python-B6aJPvgy.js +1 -0
  38. package/dist/client/assets/react-Cfq4ot0g.js +1 -0
  39. package/dist/client/assets/regexp-CDVJQ6XC.js +1 -0
  40. package/dist/client/assets/ruby-FDmvQDUv.js +1 -0
  41. package/dist/client/assets/rust-B1yitclQ.js +1 -0
  42. package/dist/client/assets/search-dialog-D19x_xaG.js +1 -0
  43. package/dist/client/assets/session-export-dialog-DRlJwhMa.js +1 -0
  44. package/dist/client/assets/settings-dialog-BA5FjiyP.js +1 -0
  45. package/dist/client/assets/shell-DfDnw5Jg.js +1 -0
  46. package/dist/client/assets/skills-lmNPZksG.js +2 -0
  47. package/dist/client/assets/skills-panel-Cv-N_MDk.js +5 -0
  48. package/dist/client/assets/sql-BLtJtn59.js +1 -0
  49. package/dist/client/assets/styles-JgjN_ZCd.css +1 -0
  50. package/dist/client/assets/swift-Dg5xB15N.js +1 -0
  51. package/dist/client/assets/switch-Bh9tVOYh.js +1 -0
  52. package/dist/client/assets/tabs-BfaEc9zS.js +1 -0
  53. package/dist/client/assets/toml-vGWfd6FD.js +1 -0
  54. package/dist/client/assets/tooltip-w9D-e_R-.js +1 -0
  55. package/dist/client/assets/tsx-COt5Ahok.js +1 -0
  56. package/dist/client/assets/typescript-BPQ3VLAy.js +1 -0
  57. package/dist/client/assets/use-file-explorer-state-CLaDuI9X.js +12 -0
  58. package/dist/client/assets/useButton-DsMdJPGn.js +1 -0
  59. package/dist/client/assets/useCompositeItem-CaYygSfB.js +1 -0
  60. package/dist/client/assets/{useControlled-Y306krcC.js → useControlled-wOKVgKF4.js} +1 -1
  61. package/dist/client/assets/{useMutation-0WgW4xQJ.js → useMutation-fJnleJAb.js} +1 -1
  62. package/dist/client/assets/visuallyHidden-CqGRL_Oq.js +9 -0
  63. package/dist/client/assets/vitesse-dark-D0r3Knsf.js +1 -0
  64. package/dist/client/assets/vitesse-light-CVO1_9PV.js +1 -0
  65. package/dist/client/assets/xml-sdJ4AIDG.js +1 -0
  66. package/dist/client/assets/yaml-Buea-lGh.js +1 -0
  67. package/dist/server/assets/{_sessionKey-BhFH4uWY.js → _sessionKey-B5UHBd2U.js} +190 -54
  68. package/dist/server/assets/_tanstack-start-manifest_v-D11xMFUx.js +4 -0
  69. package/dist/server/assets/{agents-Dz_i76VW.js → agents-CmQ4vvXm.js} +1 -1
  70. package/dist/server/assets/{agents-screen-CqQPJndp.js → agents-screen-bmrIyFbk.js} +43 -35
  71. package/dist/server/assets/{bots-6ryCIgKh.js → bots-Byt6jv0a.js} +1 -1
  72. package/dist/server/assets/bots-screen-C2TGFv42.js +474 -0
  73. package/dist/server/assets/{button-DtQ3rV1m.js → button-CwY2OHFj.js} +2 -2
  74. package/dist/server/assets/{connect-B8jpGQGK.js → connect-CbgijWz4.js} +2 -35
  75. package/dist/server/assets/{file-explorer-screen-DCfS_Ajx.js → file-explorer-screen-CVlFiAFu.js} +36 -36
  76. package/dist/server/assets/{files-D2GIrPF4.js → files-BIEcSPGp.js} +1 -1
  77. package/dist/server/assets/{index-B2JHn34C.js → index--_jH_0mX.js} +2 -1
  78. package/dist/server/assets/{index-BNSsDaLb.js → index-Dl2BOKP7.js} +116 -82
  79. package/dist/server/assets/{keyboard-shortcuts-dialog-CqIm8aYF.js → keyboard-shortcuts-dialog-CsNP85q8.js} +2 -2
  80. package/dist/server/assets/{router-Dme7USeO.js → router-DJA7GtMo.js} +356 -64
  81. package/dist/server/assets/{search-dialog-DG0D9KRN.js → search-dialog-C2a3OYm_.js} +64 -83
  82. package/dist/server/assets/{session-export-dialog-DLPZVlQV.js → session-export-dialog-CwclV0Aj.js} +2 -2
  83. package/dist/server/assets/{settings-dialog-BaGT4e5l.js → settings-dialog-CHVzrou9.js} +390 -128
  84. package/dist/server/assets/skills-Cy8xclXY.js +11 -0
  85. package/dist/server/assets/skills-panel-BnRNb7u9.js +762 -0
  86. package/dist/server/assets/{switch-DnX0MjGS.js → switch-BbkUeVDV.js} +1 -1
  87. package/dist/server/assets/tabs-DDFZob0m.js +67 -0
  88. package/dist/server/assets/{tooltip-gbV6rEVv.js → tooltip-DgsSPocE.js} +1 -1
  89. package/dist/server/assets/{use-file-explorer-state-DfAKF2gZ.js → use-file-explorer-state-Il1LlBAe.js} +1 -1
  90. package/dist/server/server.js +2 -2
  91. package/package.json +7 -2
  92. package/dist/client/assets/_sessionKey-DB95zj1L.js +0 -97
  93. package/dist/client/assets/agents-LFrWe-HX.js +0 -2
  94. package/dist/client/assets/agents-screen-CEBBk1yO.js +0 -1
  95. package/dist/client/assets/bots-CxDwf_WK.js +0 -2
  96. package/dist/client/assets/bots-screen-D6qma1wK.js +0 -1
  97. package/dist/client/assets/button-Il3CHIzX.js +0 -1
  98. package/dist/client/assets/file-explorer-screen-rtV6n-5_.js +0 -1
  99. package/dist/client/assets/files-DMemuq9D.js +0 -2
  100. package/dist/client/assets/index-CVV4XiZo.js +0 -153
  101. package/dist/client/assets/keyboard-shortcuts-dialog-DXC0YHoy.js +0 -1
  102. package/dist/client/assets/react-BhVdgA5r.js +0 -1
  103. package/dist/client/assets/search-dialog-I1jJplIh.js +0 -1
  104. package/dist/client/assets/session-export-dialog-CH5unryw.js +0 -1
  105. package/dist/client/assets/settings-dialog-B8v-GVJ8.js +0 -1
  106. package/dist/client/assets/styles-BaTVzdPa.css +0 -1
  107. package/dist/client/assets/switch-sQnv1YsK.js +0 -1
  108. package/dist/client/assets/tooltip-j_viC_EE.js +0 -1
  109. package/dist/client/assets/use-file-explorer-state-BUH-u7Jv.js +0 -12
  110. package/dist/client/assets/useButton-9VAzplAB.js +0 -9
  111. package/dist/server/assets/_tanstack-start-manifest_v-BaIrL1VQ.js +0 -4
  112. package/dist/server/assets/bots-screen-DS_ZF9Ec.js +0 -417
@@ -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-DfAKF2gZ.js";
7
- import { S as Switch } from "./switch-DnX0MjGS.js";
8
- import { Tabs as Tabs$1 } from "@base-ui/react/tabs";
9
- import { u as useChatSettings } from "./index-BNSsDaLb.js";
10
- import { u as useLlmSettings, g as getLlmProviderDefaults } from "./_sessionKey-BhFH4uWY.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-Dl2BOKP7.js";
10
+ import { u as useLlmSettings, g as getLlmProviderDefaults } from "./_sessionKey-B5UHBd2U.js";
11
11
  import "@base-ui/react/merge-props";
12
12
  import "@base-ui/react/use-render";
13
13
  import "class-variance-authority";
@@ -17,43 +17,11 @@ 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 "shiki/core";
21
- import "shiki/engine/javascript";
22
- import "@shikijs/themes/vitesse-dark";
23
- import "@shikijs/themes/vitesse-light";
24
- import "@shikijs/langs/bash";
25
- import "@shikijs/langs/c";
26
- import "@shikijs/langs/cpp";
27
- import "@shikijs/langs/csharp";
28
- import "@shikijs/langs/css";
29
- import "@shikijs/langs/diff";
30
- import "@shikijs/langs/dockerfile";
31
- import "@shikijs/langs/go";
32
- import "@shikijs/langs/graphql";
33
- import "@shikijs/langs/html";
34
- import "@shikijs/langs/java";
35
- import "@shikijs/langs/javascript";
36
- import "@shikijs/langs/json";
37
- import "@shikijs/langs/jsx";
38
- import "@shikijs/langs/kotlin";
39
- import "@shikijs/langs/markdown";
40
- import "@shikijs/langs/php";
41
- import "@shikijs/langs/python";
42
- import "@shikijs/langs/regexp";
43
- import "@shikijs/langs/ruby";
44
- import "@shikijs/langs/rust";
45
- import "@shikijs/langs/shell";
46
- import "@shikijs/langs/sql";
47
- import "@shikijs/langs/swift";
48
- import "@shikijs/langs/toml";
49
- import "@shikijs/langs/typescript";
50
- import "@shikijs/langs/tsx";
51
- import "@shikijs/langs/xml";
52
- import "@shikijs/langs/yaml";
20
+ import "@base-ui/react/tabs";
53
21
  import "zustand/middleware";
54
22
  import "@tanstack/react-router";
55
23
  import "@tanstack/react-query";
56
- import "./tooltip-gbV6rEVv.js";
24
+ import "./tooltip-DgsSPocE.js";
57
25
  import "@base-ui/react/tooltip";
58
26
  import "motion/react";
59
27
  import "@base-ui/react/alert-dialog";
@@ -65,91 +33,42 @@ import "react-markdown";
65
33
  import "remark-breaks";
66
34
  import "remark-gfm";
67
35
  import "react-dom";
68
- import "./router-Dme7USeO.js";
36
+ import "./router-DJA7GtMo.js";
69
37
  import "node:crypto";
70
38
  import "ws";
71
39
  import "node:fs";
72
40
  import "node:path";
73
41
  import "node:os";
74
42
  import "@tanstack/router-core/ssr/client";
43
+ import "node:child_process";
75
44
  import "node:fs/promises";
76
45
  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
46
  function SettingsSection({ title, tabId, activeTab, children }) {
137
47
  const hiddenOnDesktop = tabId && activeTab && tabId !== activeTab;
138
48
  return /* @__PURE__ */ jsxs("div", { className: cn(
139
- "border-b border-primary-200 py-4 last:border-0",
49
+ "border-b border-primary-200 py-2 last:border-0",
140
50
  hiddenOnDesktop && "md:hidden"
141
51
  ), 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 })
52
+ /* @__PURE__ */ jsx("h3", { className: "mb-1.5 text-sm font-semibold text-primary-700", children: title }),
53
+ /* @__PURE__ */ jsx("div", { className: "space-y-1.5", children })
144
54
  ] });
145
55
  }
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 }),
56
+ function SettingsRow({ label, description, inline, children }) {
57
+ if (inline) {
58
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
59
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 select-none", children: [
60
+ /* @__PURE__ */ jsx("div", { className: "text-[13px] font-medium text-primary-800", children: label }),
61
+ description && /* @__PURE__ */ jsx("div", { className: "text-xs text-primary-500", children: description })
62
+ ] }),
63
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children })
64
+ ] });
65
+ }
66
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
67
+ /* @__PURE__ */ jsxs("div", { className: "select-none", children: [
68
+ /* @__PURE__ */ jsx("div", { className: "text-[13px] font-medium text-primary-800", children: label }),
150
69
  description && /* @__PURE__ */ jsx("div", { className: "text-xs text-primary-500", children: description })
151
70
  ] }),
152
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children })
71
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 flex-wrap", children })
153
72
  ] });
154
73
  }
155
74
  const textSizeOptions = [
@@ -158,9 +77,79 @@ const textSizeOptions = [
158
77
  { value: "18px", label: "L" },
159
78
  { value: "20px", label: "XL" }
160
79
  ];
80
+ const fontFamilyOptions = [
81
+ {
82
+ value: "system",
83
+ label: "System",
84
+ cssValue: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
85
+ previewClass: "font-sans"
86
+ },
87
+ {
88
+ value: "inter",
89
+ label: "Inter",
90
+ cssValue: '"Inter", sans-serif',
91
+ previewClass: 'font-["Inter",sans-serif]'
92
+ },
93
+ {
94
+ value: "roboto",
95
+ label: "Roboto",
96
+ cssValue: '"Roboto", sans-serif',
97
+ previewClass: 'font-["Roboto",sans-serif]'
98
+ }
99
+ ];
100
+ const densityOptions = [
101
+ { value: "compact", label: "Compact" },
102
+ { value: "comfortable", label: "Comfortable" },
103
+ { value: "spacious", label: "Spacious" }
104
+ ];
105
+ const accentColorOptions = [
106
+ { value: "green", label: "Green", accent: "#22c55e", hover: "#16a34a", light: "rgba(34, 197, 94, 0.10)" },
107
+ { value: "blue", label: "Blue", accent: "#3b82f6", hover: "#2563eb", light: "rgba(59, 130, 246, 0.10)" },
108
+ { value: "purple", label: "Purple", accent: "#8b5cf6", hover: "#7c3aed", light: "rgba(139, 92, 246, 0.10)" },
109
+ { value: "orange", label: "Orange", accent: "#f97316", hover: "#ea580c", light: "rgba(249, 115, 22, 0.10)" },
110
+ { value: "pink", label: "Pink", accent: "#ec4899", hover: "#db2777", light: "rgba(236, 72, 153, 0.10)" },
111
+ { value: "red", label: "Red", accent: "#ef4444", hover: "#dc2626", light: "rgba(239, 68, 68, 0.10)" },
112
+ { value: "cyan", label: "Cyan", accent: "#06b6d4", hover: "#0891b2", light: "rgba(6, 182, 212, 0.10)" },
113
+ { value: "yellow", label: "Yellow", accent: "#eab308", hover: "#ca8a04", light: "rgba(234, 179, 8, 0.10)" }
114
+ ];
115
+ const chatWidthOptions = [
116
+ { value: "narrow", label: "Narrow", cssValue: "640px" },
117
+ { value: "medium", label: "Medium", cssValue: "800px" },
118
+ { value: "wide", label: "Wide", cssValue: "1000px" },
119
+ { value: "full", label: "Full", cssValue: "100%" }
120
+ ];
121
+ const sidebarWidthOptions = [
122
+ { value: "compact", label: "Compact", cssValue: "200px" },
123
+ { value: "normal", label: "Normal", cssValue: "260px" },
124
+ { value: "wide", label: "Wide", cssValue: "320px" },
125
+ { value: "xl", label: "XL", cssValue: "400px" }
126
+ ];
127
+ const bubbleStyleOptions = [
128
+ { value: "default", label: "Default" },
129
+ { value: "bubbles", label: "Bubbles" },
130
+ { value: "minimal", label: "Minimal" }
131
+ ];
161
132
  function isTextSizeValue(value) {
162
133
  return textSizeOptions.some((option) => option.value === value);
163
134
  }
135
+ function isFontFamilyValue(value) {
136
+ return fontFamilyOptions.some((option) => option.value === value);
137
+ }
138
+ function isDensityValue(value) {
139
+ return densityOptions.some((option) => option.value === value);
140
+ }
141
+ function isAccentColorValue(value) {
142
+ return accentColorOptions.some((option) => option.value === value);
143
+ }
144
+ function isChatWidthValue(value) {
145
+ return chatWidthOptions.some((option) => option.value === value);
146
+ }
147
+ function isSidebarWidthValue(value) {
148
+ return sidebarWidthOptions.some((option) => option.value === value);
149
+ }
150
+ function isBubbleStyleValue(value) {
151
+ return bubbleStyleOptions.some((option) => option.value === value);
152
+ }
164
153
  function SettingsDialog({
165
154
  open,
166
155
  onOpenChange,
@@ -219,6 +208,90 @@ function SettingsDialog({
219
208
  return "auto";
220
209
  }
221
210
  });
211
+ useEffect(() => {
212
+ if (typeof window === "undefined") return;
213
+ try {
214
+ const storedFontFamily = localStorage.getItem("opencami-font-family");
215
+ if (storedFontFamily && isFontFamilyValue(storedFontFamily)) {
216
+ applyFontFamily(storedFontFamily);
217
+ if (settings.fontFamily !== storedFontFamily) {
218
+ updateSettings({ fontFamily: storedFontFamily });
219
+ }
220
+ } else {
221
+ applyFontFamily(settings.fontFamily);
222
+ }
223
+ const storedDensity = localStorage.getItem("opencami-density");
224
+ if (storedDensity && isDensityValue(storedDensity)) {
225
+ applyDensity(storedDensity);
226
+ if (settings.density !== storedDensity) {
227
+ updateSettings({ density: storedDensity });
228
+ }
229
+ } else {
230
+ applyDensity(settings.density);
231
+ }
232
+ const storedAccentColor = localStorage.getItem("opencami-accent-color");
233
+ if (storedAccentColor && isAccentColorValue(storedAccentColor)) {
234
+ applyAccentColor(storedAccentColor);
235
+ if (settings.accentColor !== storedAccentColor) {
236
+ updateSettings({ accentColor: storedAccentColor });
237
+ }
238
+ } else {
239
+ applyAccentColor(settings.accentColor);
240
+ }
241
+ const storedChatWidth = localStorage.getItem("opencami-chat-width");
242
+ if (storedChatWidth && isChatWidthValue(storedChatWidth)) {
243
+ applyChatWidth(storedChatWidth);
244
+ if (settings.chatWidth !== storedChatWidth) {
245
+ updateSettings({ chatWidth: storedChatWidth });
246
+ }
247
+ } else {
248
+ applyChatWidth(settings.chatWidth);
249
+ }
250
+ const storedSidebarWidth = localStorage.getItem("opencami-sidebar-width");
251
+ if (storedSidebarWidth && isSidebarWidthValue(storedSidebarWidth)) {
252
+ applySidebarWidth(storedSidebarWidth);
253
+ if (settings.sidebarWidth !== storedSidebarWidth) {
254
+ updateSettings({ sidebarWidth: storedSidebarWidth });
255
+ }
256
+ } else {
257
+ applySidebarWidth(settings.sidebarWidth);
258
+ }
259
+ const storedBubbleStyle = localStorage.getItem("opencami-bubble-style");
260
+ if (storedBubbleStyle && isBubbleStyleValue(storedBubbleStyle)) {
261
+ applyBubbleStyle(storedBubbleStyle);
262
+ if (settings.bubbleStyle !== storedBubbleStyle) {
263
+ updateSettings({ bubbleStyle: storedBubbleStyle });
264
+ }
265
+ } else {
266
+ applyBubbleStyle(settings.bubbleStyle);
267
+ }
268
+ } catch {
269
+ applyFontFamily(settings.fontFamily);
270
+ applyDensity(settings.density);
271
+ applyAccentColor(settings.accentColor);
272
+ applyChatWidth(settings.chatWidth);
273
+ applySidebarWidth(settings.sidebarWidth);
274
+ applyBubbleStyle(settings.bubbleStyle);
275
+ }
276
+ }, []);
277
+ useEffect(() => {
278
+ applyFontFamily(settings.fontFamily);
279
+ }, [settings.fontFamily]);
280
+ useEffect(() => {
281
+ applyDensity(settings.density);
282
+ }, [settings.density]);
283
+ useEffect(() => {
284
+ applyAccentColor(settings.accentColor);
285
+ }, [settings.accentColor]);
286
+ useEffect(() => {
287
+ applyChatWidth(settings.chatWidth);
288
+ }, [settings.chatWidth]);
289
+ useEffect(() => {
290
+ applySidebarWidth(settings.sidebarWidth);
291
+ }, [settings.sidebarWidth]);
292
+ useEffect(() => {
293
+ applyBubbleStyle(settings.bubbleStyle);
294
+ }, [settings.bubbleStyle]);
222
295
  const handleTtsProviderChange = (value) => {
223
296
  setTtsProvider(value);
224
297
  try {
@@ -244,6 +317,54 @@ function SettingsDialog({
244
317
  if (typeof document === "undefined") return;
245
318
  document.documentElement.style.setProperty("--opencami-text-size", value);
246
319
  }
320
+ function applyFontFamily(value) {
321
+ if (typeof document === "undefined") return;
322
+ const selected = fontFamilyOptions.find((option) => option.value === value);
323
+ const cssValue = selected?.cssValue ?? fontFamilyOptions[0].cssValue;
324
+ document.documentElement.style.setProperty("--opencami-font-family", cssValue);
325
+ }
326
+ function applyDensity(value) {
327
+ if (typeof document === "undefined") return;
328
+ const root = document.documentElement;
329
+ root.style.setProperty("--opencami-density", value);
330
+ if (value === "compact") {
331
+ root.style.setProperty("--opencami-msg-padding-y", "0.25rem");
332
+ root.style.setProperty("--opencami-msg-gap", "0.25rem");
333
+ root.style.setProperty("--opencami-user-bubble-py", "0.4rem");
334
+ return;
335
+ }
336
+ if (value === "spacious") {
337
+ root.style.setProperty("--opencami-msg-padding-y", "1.25rem");
338
+ root.style.setProperty("--opencami-msg-gap", "1rem");
339
+ root.style.setProperty("--opencami-user-bubble-py", "1rem");
340
+ return;
341
+ }
342
+ root.style.setProperty("--opencami-msg-padding-y", "0.75rem");
343
+ root.style.setProperty("--opencami-msg-gap", "0.5rem");
344
+ root.style.setProperty("--opencami-user-bubble-py", "0.625rem");
345
+ }
346
+ function applyAccentColor(value) {
347
+ if (typeof document === "undefined") return;
348
+ const selected = accentColorOptions.find((option) => option.value === value) ?? accentColorOptions[0];
349
+ const root = document.documentElement;
350
+ root.style.setProperty("--opencami-accent", selected.accent);
351
+ root.style.setProperty("--opencami-accent-hover", selected.hover);
352
+ root.style.setProperty("--opencami-accent-light", selected.light);
353
+ }
354
+ function applyChatWidth(value) {
355
+ if (typeof document === "undefined") return;
356
+ const selected = chatWidthOptions.find((option) => option.value === value) ?? chatWidthOptions[2];
357
+ document.documentElement.style.setProperty("--opencami-chat-width", selected.cssValue);
358
+ }
359
+ function applySidebarWidth(value) {
360
+ if (typeof document === "undefined") return;
361
+ const selected = sidebarWidthOptions.find((option) => option.value === value) ?? sidebarWidthOptions[1];
362
+ document.documentElement.style.setProperty("--opencami-sidebar-width", selected.cssValue);
363
+ }
364
+ function applyBubbleStyle(value) {
365
+ if (typeof document === "undefined") return;
366
+ document.documentElement.setAttribute("data-opencami-bubble-style", value);
367
+ }
247
368
  const handleTextSizeChange = (value) => {
248
369
  if (!isTextSizeValue(value)) return;
249
370
  setTextSize(value);
@@ -253,6 +374,60 @@ function SettingsDialog({
253
374
  } catch {
254
375
  }
255
376
  };
377
+ const handleFontFamilyChange = (value) => {
378
+ if (!isFontFamilyValue(value)) return;
379
+ applyFontFamily(value);
380
+ updateSettings({ fontFamily: value });
381
+ try {
382
+ localStorage.setItem("opencami-font-family", value);
383
+ } catch {
384
+ }
385
+ };
386
+ const handleDensityChange = (value) => {
387
+ if (!isDensityValue(value)) return;
388
+ applyDensity(value);
389
+ updateSettings({ density: value });
390
+ try {
391
+ localStorage.setItem("opencami-density", value);
392
+ } catch {
393
+ }
394
+ };
395
+ const handleAccentColorChange = (value) => {
396
+ if (!isAccentColorValue(value)) return;
397
+ applyAccentColor(value);
398
+ updateSettings({ accentColor: value });
399
+ try {
400
+ localStorage.setItem("opencami-accent-color", value);
401
+ } catch {
402
+ }
403
+ };
404
+ const handleChatWidthChange = (value) => {
405
+ if (!isChatWidthValue(value)) return;
406
+ applyChatWidth(value);
407
+ updateSettings({ chatWidth: value });
408
+ try {
409
+ localStorage.setItem("opencami-chat-width", value);
410
+ } catch {
411
+ }
412
+ };
413
+ const handleSidebarWidthChange = (value) => {
414
+ if (!isSidebarWidthValue(value)) return;
415
+ applySidebarWidth(value);
416
+ updateSettings({ sidebarWidth: value });
417
+ try {
418
+ localStorage.setItem("opencami-sidebar-width", value);
419
+ } catch {
420
+ }
421
+ };
422
+ const handleBubbleStyleChange = (value) => {
423
+ if (!isBubbleStyleValue(value)) return;
424
+ applyBubbleStyle(value);
425
+ updateSettings({ bubbleStyle: value });
426
+ try {
427
+ localStorage.setItem("opencami-bubble-style", value);
428
+ } catch {
429
+ }
430
+ };
256
431
  const handleTtsToggle = (checked) => {
257
432
  setTtsEnabled(checked);
258
433
  try {
@@ -333,22 +508,29 @@ function SettingsDialog({
333
508
  setTestResult(null);
334
509
  };
335
510
  const themeOptions = [
336
- { value: "system", label: "System", icon: ComputerIcon },
511
+ { value: "system", label: "Auto", icon: ComputerIcon },
337
512
  { value: "light", label: "Light", icon: Sun01Icon },
338
513
  { value: "dark", label: "Dark", icon: Moon01Icon },
339
- { value: "chameleon", label: "Chameleon", icon: Leaf01Icon }
514
+ { value: "chameleon", label: "Cham", icon: Leaf01Icon },
515
+ { value: "frost-light", label: "Ice", icon: DropletIcon }
340
516
  ];
341
517
  function applyTheme(theme) {
342
518
  if (typeof document === "undefined") return;
343
519
  const root = document.documentElement;
344
520
  const media = window.matchMedia("(prefers-color-scheme: dark)");
345
- root.classList.remove("light", "dark", "system", "chameleon");
521
+ root.classList.remove("light", "dark", "system", "chameleon", "frost", "frost-light", "frost-dark");
346
522
  root.classList.add(theme);
523
+ if (theme === "frost-light" || theme === "frost-dark") {
524
+ root.classList.add("frost");
525
+ }
526
+ if (theme === "frost-dark") {
527
+ root.classList.add("dark");
528
+ }
347
529
  if (theme === "system" && media.matches) {
348
530
  root.classList.add("dark");
349
531
  }
350
532
  }
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: [
533
+ 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
534
  /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between", children: [
353
535
  /* @__PURE__ */ jsxs("div", { children: [
354
536
  /* @__PURE__ */ jsx(DialogTitle, { className: "mb-1", children: "Settings" }),
@@ -377,7 +559,7 @@ function SettingsDialog({
377
559
  }
378
560
  )
379
561
  ] }),
380
- /* @__PURE__ */ jsxs("div", { className: "mt-3 flex md:flex-row flex-col md:gap-4 gap-0 md:min-h-[400px]", children: [
562
+ /* @__PURE__ */ jsxs("div", { className: "mt-2 flex md:flex-row flex-col md:gap-3 gap-0 md:min-h-[400px]", children: [
381
563
  /* @__PURE__ */ jsx("nav", { className: "hidden md:flex flex-col gap-0.5 min-w-[160px] border-r border-primary-200 pr-3", children: [
382
564
  { id: "connection", label: "Connection", icon: Link01Icon },
383
565
  { id: "appearance", label: "Appearance", icon: PaintBoardIcon },
@@ -392,8 +574,9 @@ function SettingsDialog({
392
574
  onClick: () => setActiveTab(tab.id),
393
575
  className: cn(
394
576
  "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"
577
+ activeTab === tab.id ? "text-primary-900 font-medium" : "text-primary-600 hover:text-primary-900 hover:bg-primary-50"
396
578
  ),
579
+ style: activeTab === tab.id ? { backgroundColor: "var(--opencami-accent-light)" } : void 0,
397
580
  children: [
398
581
  /* @__PURE__ */ jsx(HugeiconsIcon, { icon: tab.icon, size: 16, strokeWidth: 1.5 }),
399
582
  tab.label
@@ -401,8 +584,8 @@ function SettingsDialog({
401
584
  },
402
585
  tab.id
403
586
  )) }),
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: [
587
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto md:max-h-[calc(85vh-90px)] max-h-none", children: [
588
+ /* @__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
589
  /* @__PURE__ */ jsx("span", { className: "size-2 rounded-full bg-green-500" }),
407
590
  "Connected"
408
591
  ] }) }) }),
@@ -420,13 +603,13 @@ function SettingsDialog({
420
603
  TabsList,
421
604
  {
422
605
  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(
606
+ className: "gap-1.5 flex-wrap *:data-[slot=tab-indicator]:duration-0",
607
+ children: themeOptions.map((option) => /* @__PURE__ */ jsxs(TabsTab, { value: option.value, className: "text-[11px] px-1 py-0.5 gap-0.5", children: [
608
+ option.icon && /* @__PURE__ */ jsx(
426
609
  HugeiconsIcon,
427
610
  {
428
611
  icon: option.icon,
429
- size: 20,
612
+ size: 13,
430
613
  strokeWidth: 1.5
431
614
  }
432
615
  ),
@@ -436,11 +619,44 @@ function SettingsDialog({
436
619
  )
437
620
  }
438
621
  ) }),
622
+ /* @__PURE__ */ jsx(
623
+ SettingsRow,
624
+ {
625
+ label: "Accent Color",
626
+ children: /* @__PURE__ */ jsx("div", { className: "flex gap-0.5 flex-wrap", children: accentColorOptions.map((option) => {
627
+ const selected = settings.accentColor === option.value;
628
+ return /* @__PURE__ */ jsx(
629
+ "button",
630
+ {
631
+ type: "button",
632
+ onClick: () => handleAccentColorChange(option.value),
633
+ className: cn(
634
+ "flex items-center justify-center rounded-md p-1 transition-all duration-150",
635
+ selected ? "scale-110" : "hover:bg-primary-50 hover:scale-105"
636
+ ),
637
+ children: /* @__PURE__ */ jsx(
638
+ "span",
639
+ {
640
+ className: cn(
641
+ "size-6 rounded-full transition-shadow duration-150",
642
+ selected ? "ring-2 ring-offset-2" : "border-2 border-primary-200"
643
+ ),
644
+ style: {
645
+ backgroundColor: option.accent,
646
+ ...selected ? { "--tw-ring-color": option.accent } : {}
647
+ }
648
+ }
649
+ )
650
+ },
651
+ option.value
652
+ );
653
+ }) })
654
+ }
655
+ ),
439
656
  /* @__PURE__ */ jsx(
440
657
  SettingsRow,
441
658
  {
442
659
  label: "Text Size",
443
- description: "Adjust chat and composer text",
444
660
  children: /* @__PURE__ */ jsx(Tabs, { value: textSize, onValueChange: handleTextSizeChange, children: /* @__PURE__ */ jsx(
445
661
  TabsList,
446
662
  {
@@ -450,24 +666,29 @@ function SettingsDialog({
450
666
  }
451
667
  ) })
452
668
  }
453
- )
669
+ ),
670
+ /* @__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)) }) }) }),
671
+ /* @__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)) }) }) }),
672
+ /* @__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)) }) }) }),
673
+ /* @__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)) }) }) }),
674
+ /* @__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
675
  ] }),
455
676
  /* @__PURE__ */ jsxs(SettingsSection, { title: "Chat", tabId: "chat", activeTab, children: [
456
- /* @__PURE__ */ jsx(SettingsRow, { label: "Show tool messages", children: /* @__PURE__ */ jsx(
677
+ /* @__PURE__ */ jsx(SettingsRow, { inline: true, label: "Show tool messages", children: /* @__PURE__ */ jsx(
457
678
  Switch,
458
679
  {
459
680
  checked: settings.showToolMessages,
460
681
  onCheckedChange: (checked) => updateSettings({ showToolMessages: checked })
461
682
  }
462
683
  ) }),
463
- /* @__PURE__ */ jsx(SettingsRow, { label: "Show reasoning blocks", children: /* @__PURE__ */ jsx(
684
+ /* @__PURE__ */ jsx(SettingsRow, { inline: true, label: "Show reasoning blocks", children: /* @__PURE__ */ jsx(
464
685
  Switch,
465
686
  {
466
687
  checked: settings.showReasoningBlocks,
467
688
  onCheckedChange: (checked) => updateSettings({ showReasoningBlocks: checked })
468
689
  }
469
690
  ) }),
470
- /* @__PURE__ */ jsx(SettingsRow, { label: "Show search sources", children: /* @__PURE__ */ jsx(
691
+ /* @__PURE__ */ jsx(SettingsRow, { inline: true, label: "Show search sources", children: /* @__PURE__ */ jsx(
471
692
  Switch,
472
693
  {
473
694
  checked: settings.showSearchSources,
@@ -477,6 +698,7 @@ function SettingsDialog({
477
698
  /* @__PURE__ */ jsx(
478
699
  SettingsRow,
479
700
  {
701
+ inline: true,
480
702
  label: "Agent Manager (Beta)",
481
703
  description: "Show Agent Manager in sidebar for creating and managing agents",
482
704
  children: /* @__PURE__ */ jsx(
@@ -500,6 +722,31 @@ function SettingsDialog({
500
722
  /* @__PURE__ */ jsx(
501
723
  SettingsRow,
502
724
  {
725
+ inline: true,
726
+ label: "Skills Browser (Beta)",
727
+ description: "Browse and install skills from ClawHub",
728
+ children: /* @__PURE__ */ jsx(
729
+ Switch,
730
+ {
731
+ checked: (() => {
732
+ try {
733
+ return localStorage.getItem("opencami-skills-browser") === "true";
734
+ } catch {
735
+ return false;
736
+ }
737
+ })(),
738
+ onCheckedChange: (checked) => {
739
+ localStorage.setItem("opencami-skills-browser", String(checked));
740
+ window.location.reload();
741
+ }
742
+ }
743
+ )
744
+ }
745
+ ),
746
+ /* @__PURE__ */ jsx(
747
+ SettingsRow,
748
+ {
749
+ inline: true,
503
750
  label: "Cron Jobs Panel (Beta)",
504
751
  description: "Show Cron Jobs in sidebar for managing OpenClaw cron schedules",
505
752
  children: /* @__PURE__ */ jsx(
@@ -523,6 +770,7 @@ function SettingsDialog({
523
770
  /* @__PURE__ */ jsx(
524
771
  SettingsRow,
525
772
  {
773
+ inline: true,
526
774
  label: "Inline File Preview",
527
775
  description: "Make file paths in messages clickable to preview file contents",
528
776
  children: /* @__PURE__ */ jsx(
@@ -539,6 +787,7 @@ function SettingsDialog({
539
787
  personasAvailable ? /* @__PURE__ */ jsx(
540
788
  SettingsRow,
541
789
  {
790
+ inline: true,
542
791
  label: "Persona Picker",
543
792
  description: "Show persona picker in chat (20 personalities)",
544
793
  children: /* @__PURE__ */ jsx(
@@ -552,6 +801,7 @@ function SettingsDialog({
552
801
  ) : /* @__PURE__ */ jsx(
553
802
  SettingsRow,
554
803
  {
804
+ inline: true,
555
805
  label: "Persona Picker",
556
806
  description: "Install the Personas skill to unlock 20 AI personalities",
557
807
  children: /* @__PURE__ */ jsx(Switch, { checked: false, disabled: true })
@@ -572,6 +822,7 @@ function SettingsDialog({
572
822
  /* @__PURE__ */ jsx(
573
823
  SettingsRow,
574
824
  {
825
+ inline: true,
575
826
  label: "Voice Playback",
576
827
  description: "Add a 🔊 button to AI messages for text-to-speech",
577
828
  children: /* @__PURE__ */ jsx(
@@ -586,6 +837,7 @@ function SettingsDialog({
586
837
  /* @__PURE__ */ jsx(
587
838
  SettingsRow,
588
839
  {
840
+ inline: true,
589
841
  label: "TTS Provider",
590
842
  description: "Choose which service generates speech",
591
843
  children: /* @__PURE__ */ jsxs(
@@ -607,6 +859,7 @@ function SettingsDialog({
607
859
  ttsProvider === "openai" && /* @__PURE__ */ jsx(
608
860
  SettingsRow,
609
861
  {
862
+ inline: true,
610
863
  label: "Voice",
611
864
  description: "OpenAI voice selection",
612
865
  children: /* @__PURE__ */ jsx(
@@ -624,6 +877,7 @@ function SettingsDialog({
624
877
  /* @__PURE__ */ jsx(SettingsSection, { title: "Speech-to-Text", tabId: "voice", activeTab, children: /* @__PURE__ */ jsx(
625
878
  SettingsRow,
626
879
  {
880
+ inline: true,
627
881
  label: "STT Provider",
628
882
  description: "Choose which service transcribes your voice",
629
883
  children: /* @__PURE__ */ jsxs(
@@ -651,6 +905,7 @@ function SettingsDialog({
651
905
  /* @__PURE__ */ jsx(
652
906
  SettingsRow,
653
907
  {
908
+ inline: true,
654
909
  label: "Provider",
655
910
  description: "Choose LLM provider for titles & follow-ups",
656
911
  children: /* @__PURE__ */ jsxs(
@@ -679,6 +934,7 @@ function SettingsDialog({
679
934
  /* @__PURE__ */ jsx(
680
935
  SettingsRow,
681
936
  {
937
+ inline: true,
682
938
  label: "Smart session titles",
683
939
  description: "Generate concise titles using AI",
684
940
  children: /* @__PURE__ */ jsx(
@@ -694,6 +950,7 @@ function SettingsDialog({
694
950
  /* @__PURE__ */ jsx(
695
951
  SettingsRow,
696
952
  {
953
+ inline: true,
697
954
  label: "Smart follow-up suggestions",
698
955
  description: "AI-generated contextual follow-ups",
699
956
  children: /* @__PURE__ */ jsx(
@@ -737,6 +994,11 @@ function SettingsDialog({
737
994
  /* @__PURE__ */ jsxs("div", { className: "mt-4 pt-3 border-t border-primary-100", children: [
738
995
  /* @__PURE__ */ jsx("div", { className: "text-sm text-primary-800 mb-2", children: llmSettings.llmProvider === "ollama" ? "API Key (optional)" : "API Key" }),
739
996
  /* @__PURE__ */ jsx("div", { className: "text-xs text-primary-500 mb-2", children: llmSettings.llmProvider === "ollama" ? "Not required for local Ollama" : llmStatus.hasEnvKey && llmSettings.llmProvider === "openai" ? "Optional: Override server key with your own" : `Required for ${llmSettings.llmProvider === "openrouter" ? "OpenRouter" : "LLM features"} (stored locally)` }),
997
+ /* @__PURE__ */ jsxs("div", { className: "text-xs text-amber-600 bg-amber-50 border border-amber-200 rounded-md px-2 py-1.5 mb-2", children: [
998
+ "⚠️ ",
999
+ /* @__PURE__ */ jsx("strong", { children: "Security Note:" }),
1000
+ " API keys are stored in your browser's localStorage. This is convenient but not secure for shared computers. For production use, configure keys server-side via environment variables (OPENAI_API_KEY, OPENROUTER_API_KEY)."
1001
+ ] }),
740
1002
  /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
741
1003
  /* @__PURE__ */ jsx(
742
1004
  "input",
@@ -841,7 +1103,7 @@ function SettingsDialog({
841
1103
  ] })
842
1104
  ] })
843
1105
  ] }),
844
- /* @__PURE__ */ jsx("div", { className: "mt-4 flex justify-end", children: /* @__PURE__ */ jsx(DialogClose, { onClick: onClose, children: "Close" }) })
1106
+ /* @__PURE__ */ jsx("div", { className: "mt-2 flex justify-end", children: /* @__PURE__ */ jsx(DialogClose, { onClick: onClose, children: "Close" }) })
845
1107
  ] }) }) });
846
1108
  }
847
1109
  export {