opencami 1.4.0 → 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.
- package/README.md +60 -0
- package/dist/client/assets/CSPContext-EgWK8bIJ.js +1 -0
- package/dist/client/assets/DirectionContext-DXtY05YF.js +1 -0
- package/dist/client/assets/_sessionKey-B89e7G3y.js +100 -0
- package/dist/client/assets/agents-screen-1BiEZ9od.js +1 -0
- package/dist/client/assets/agents-x54ocA9z.js +2 -0
- package/dist/client/assets/bots-screen-BNQciUeJ.js +1 -0
- package/dist/client/assets/bots-x86ZHG4b.js +2 -0
- package/dist/client/assets/button-nDcsaNPl.js +1 -0
- package/dist/client/assets/{connect-D3baVDFL.js → connect-w4lLOqiJ.js} +1 -1
- package/dist/client/assets/file-explorer-screen-CAsjd3w8.js +1 -0
- package/dist/client/assets/files-Bype5Mnb.js +2 -0
- package/dist/client/assets/{index-ByIsZcHh.js → index-36G0WCxU.js} +1 -1
- package/dist/client/assets/{index-CVV4XiZo.js → index-BXkRE220.js} +2 -2
- package/dist/client/assets/keyboard-shortcuts-dialog-BdCeXRjD.js +1 -0
- package/dist/client/assets/{main-CkIF0soY.js → main-B3N0eQFg.js} +129 -17
- package/dist/client/assets/{opencami-logo-CIxSO1oo.js → opencami-logo-DD0DPFRQ.js} +1 -1
- package/dist/client/assets/{react-BhVdgA5r.js → react-B16OrBeM.js} +1 -1
- package/dist/client/assets/search-dialog-BjTPceEl.js +1 -0
- package/dist/client/assets/session-export-dialog-DtHKG2zW.js +1 -0
- package/dist/client/assets/settings-dialog-hiqdk_UD.js +1 -0
- package/dist/client/assets/skills-DhwyFq3y.js +2 -0
- package/dist/client/assets/skills-panel-BLUjzfjJ.js +5 -0
- package/dist/client/assets/styles-CHP4l6vZ.css +1 -0
- package/dist/client/assets/switch-J6wLIVu2.js +1 -0
- package/dist/client/assets/tabs-DvPgTz5I.js +1 -0
- package/dist/client/assets/tooltip-C14vdXHK.js +1 -0
- package/dist/client/assets/use-file-explorer-state-BnaJEqRP.js +12 -0
- package/dist/client/assets/useButton-Bnnac1eR.js +1 -0
- package/dist/client/assets/useCompositeItem-BgiEMKAt.js +1 -0
- package/dist/client/assets/{useControlled-Y306krcC.js → useControlled-BhUuiHAm.js} +1 -1
- package/dist/client/assets/{useMutation-0WgW4xQJ.js → useMutation-CFmVaBag.js} +1 -1
- package/dist/client/assets/visuallyHidden-DCCICp6T.js +9 -0
- package/dist/server/assets/{_sessionKey-BhFH4uWY.js → _sessionKey-tRze5NLR.js} +178 -46
- package/dist/server/assets/_tanstack-start-manifest_v-CyfoMvUa.js +4 -0
- package/dist/server/assets/{agents-Dz_i76VW.js → agents-CmQ4vvXm.js} +1 -1
- package/dist/server/assets/{agents-screen-CqQPJndp.js → agents-screen-bmrIyFbk.js} +43 -35
- package/dist/server/assets/{bots-6ryCIgKh.js → bots-Byt6jv0a.js} +1 -1
- package/dist/server/assets/bots-screen-C2TGFv42.js +474 -0
- package/dist/server/assets/{button-DtQ3rV1m.js → button-CwY2OHFj.js} +2 -2
- package/dist/server/assets/{connect-B8jpGQGK.js → connect-d3AqjAqe.js} +2 -2
- package/dist/server/assets/{file-explorer-screen-DCfS_Ajx.js → file-explorer-screen-CVlFiAFu.js} +36 -36
- package/dist/server/assets/{files-D2GIrPF4.js → files-BIEcSPGp.js} +1 -1
- package/dist/server/assets/{index-BNSsDaLb.js → index-CNIATlJ9.js} +22 -3
- package/dist/server/assets/{index-B2JHn34C.js → index-CRfLKh30.js} +2 -1
- package/dist/server/assets/{keyboard-shortcuts-dialog-CqIm8aYF.js → keyboard-shortcuts-dialog-CsNP85q8.js} +2 -2
- package/dist/server/assets/{router-Dme7USeO.js → router-rn7pJO_D.js} +356 -64
- package/dist/server/assets/{search-dialog-DG0D9KRN.js → search-dialog-Bz4Cu0KW.js} +23 -6
- package/dist/server/assets/{session-export-dialog-DLPZVlQV.js → session-export-dialog-CwclV0Aj.js} +2 -2
- package/dist/server/assets/{settings-dialog-BaGT4e5l.js → settings-dialog-BBM7jCjE.js} +386 -95
- package/dist/server/assets/skills-Cy8xclXY.js +11 -0
- package/dist/server/assets/skills-panel-BnRNb7u9.js +762 -0
- package/dist/server/assets/{switch-DnX0MjGS.js → switch-BbkUeVDV.js} +1 -1
- package/dist/server/assets/tabs-DDFZob0m.js +67 -0
- package/dist/server/assets/{tooltip-gbV6rEVv.js → tooltip-DgsSPocE.js} +1 -1
- package/dist/server/assets/{use-file-explorer-state-DfAKF2gZ.js → use-file-explorer-state-Il1LlBAe.js} +1 -1
- package/dist/server/server.js +2 -2
- package/package.json +6 -2
- package/dist/client/assets/_sessionKey-DB95zj1L.js +0 -97
- package/dist/client/assets/agents-LFrWe-HX.js +0 -2
- package/dist/client/assets/agents-screen-CEBBk1yO.js +0 -1
- package/dist/client/assets/bots-CxDwf_WK.js +0 -2
- package/dist/client/assets/bots-screen-D6qma1wK.js +0 -1
- package/dist/client/assets/button-Il3CHIzX.js +0 -1
- package/dist/client/assets/file-explorer-screen-rtV6n-5_.js +0 -1
- package/dist/client/assets/files-DMemuq9D.js +0 -2
- package/dist/client/assets/keyboard-shortcuts-dialog-DXC0YHoy.js +0 -1
- package/dist/client/assets/search-dialog-I1jJplIh.js +0 -1
- package/dist/client/assets/session-export-dialog-CH5unryw.js +0 -1
- package/dist/client/assets/settings-dialog-B8v-GVJ8.js +0 -1
- package/dist/client/assets/styles-BaTVzdPa.css +0 -1
- package/dist/client/assets/switch-sQnv1YsK.js +0 -1
- package/dist/client/assets/tooltip-j_viC_EE.js +0 -1
- package/dist/client/assets/use-file-explorer-state-BUH-u7Jv.js +0 -12
- package/dist/client/assets/useButton-9VAzplAB.js +0 -9
- package/dist/server/assets/_tanstack-start-manifest_v-BaIrL1VQ.js +0 -4
- package/dist/server/assets/bots-screen-DS_ZF9Ec.js +0 -417
|
@@ -3,13 +3,14 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { QueryClientProvider, QueryClient } from "@tanstack/react-query";
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
5
5
|
import WebSocket from "ws";
|
|
6
|
-
import { readFileSync } from "node:fs";
|
|
6
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
7
7
|
import path, { join, resolve, relative, extname } from "node:path";
|
|
8
8
|
import os, { homedir } from "node:os";
|
|
9
9
|
import { json } from "@tanstack/router-core/ssr/client";
|
|
10
|
+
import { execSync } from "node:child_process";
|
|
10
11
|
import { readFile, mkdir, writeFile, rename, stat, readdir, rm, realpath, lstat } from "node:fs/promises";
|
|
11
12
|
import { posix } from "path";
|
|
12
|
-
const appCss = "/assets/styles-
|
|
13
|
+
const appCss = "/assets/styles-CHP4l6vZ.css";
|
|
13
14
|
const swRegisterScript = `
|
|
14
15
|
(() => {
|
|
15
16
|
// Skip PWA service worker inside Capacitor native shell — they conflict
|
|
@@ -46,15 +47,21 @@ const themeScript = `
|
|
|
46
47
|
if (stored) {
|
|
47
48
|
const parsed = JSON.parse(stored)
|
|
48
49
|
const storedTheme = parsed?.state?.settings?.theme
|
|
49
|
-
if (storedTheme === 'light' || storedTheme === 'dark' || storedTheme === 'system' || storedTheme === 'chameleon') {
|
|
50
|
+
if (storedTheme === 'light' || storedTheme === 'dark' || storedTheme === 'system' || storedTheme === 'chameleon' || storedTheme === 'frost-light' || storedTheme === 'frost-dark') {
|
|
50
51
|
theme = storedTheme
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
54
|
const root = document.documentElement
|
|
54
55
|
const media = window.matchMedia('(prefers-color-scheme: dark)')
|
|
55
56
|
const apply = () => {
|
|
56
|
-
root.classList.remove('light', 'dark', 'system', 'chameleon')
|
|
57
|
+
root.classList.remove('light', 'dark', 'system', 'chameleon', 'frost', 'frost-light', 'frost-dark')
|
|
57
58
|
root.classList.add(theme)
|
|
59
|
+
if (theme === 'frost-light' || theme === 'frost-dark') {
|
|
60
|
+
root.classList.add('frost')
|
|
61
|
+
}
|
|
62
|
+
if (theme === 'frost-dark') {
|
|
63
|
+
root.classList.add('dark')
|
|
64
|
+
}
|
|
58
65
|
if (theme === 'system' && media.matches) {
|
|
59
66
|
root.classList.add('dark')
|
|
60
67
|
}
|
|
@@ -66,6 +73,13 @@ const themeScript = `
|
|
|
66
73
|
} catch {}
|
|
67
74
|
})()
|
|
68
75
|
`;
|
|
76
|
+
const tauriDetectScript = `
|
|
77
|
+
(() => {
|
|
78
|
+
if (window.__TAURI_INTERNALS__ || window.__TAURI__) {
|
|
79
|
+
document.documentElement.classList.add('tauri')
|
|
80
|
+
}
|
|
81
|
+
})()
|
|
82
|
+
`;
|
|
69
83
|
const textSizeScript = `
|
|
70
84
|
(() => {
|
|
71
85
|
try {
|
|
@@ -76,13 +90,119 @@ const textSizeScript = `
|
|
|
76
90
|
} catch {}
|
|
77
91
|
})()
|
|
78
92
|
`;
|
|
93
|
+
const fontFamilyScript = `
|
|
94
|
+
(() => {
|
|
95
|
+
try {
|
|
96
|
+
const stored = localStorage.getItem('opencami-font-family')
|
|
97
|
+
const map = {
|
|
98
|
+
'system': '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
99
|
+
'inter': '"Inter", sans-serif',
|
|
100
|
+
'ibm-plex-sans': '"IBM Plex Sans", sans-serif',
|
|
101
|
+
'jetbrains-mono': '"JetBrains Mono", monospace',
|
|
102
|
+
'merriweather': '"Merriweather", serif',
|
|
103
|
+
'roboto': '"Roboto", sans-serif',
|
|
104
|
+
}
|
|
105
|
+
const value = map[stored] || map.system
|
|
106
|
+
document.documentElement.style.setProperty('--opencami-font-family', value)
|
|
107
|
+
} catch {}
|
|
108
|
+
})()
|
|
109
|
+
`;
|
|
110
|
+
const densityScript = `
|
|
111
|
+
(() => {
|
|
112
|
+
try {
|
|
113
|
+
const stored = localStorage.getItem('opencami-density')
|
|
114
|
+
const value = stored === 'compact' || stored === 'spacious' || stored === 'comfortable'
|
|
115
|
+
? stored
|
|
116
|
+
: 'comfortable'
|
|
117
|
+
const root = document.documentElement
|
|
118
|
+
root.style.setProperty('--opencami-density', value)
|
|
119
|
+
|
|
120
|
+
if (value === 'compact') {
|
|
121
|
+
root.style.setProperty('--opencami-msg-padding-y', '0.25rem')
|
|
122
|
+
root.style.setProperty('--opencami-msg-gap', '0.25rem')
|
|
123
|
+
root.style.setProperty('--opencami-user-bubble-py', '0.4rem')
|
|
124
|
+
} else if (value === 'spacious') {
|
|
125
|
+
root.style.setProperty('--opencami-msg-padding-y', '1.25rem')
|
|
126
|
+
root.style.setProperty('--opencami-msg-gap', '1rem')
|
|
127
|
+
root.style.setProperty('--opencami-user-bubble-py', '1rem')
|
|
128
|
+
} else {
|
|
129
|
+
root.style.setProperty('--opencami-msg-padding-y', '0.75rem')
|
|
130
|
+
root.style.setProperty('--opencami-msg-gap', '0.5rem')
|
|
131
|
+
root.style.setProperty('--opencami-user-bubble-py', '0.625rem')
|
|
132
|
+
}
|
|
133
|
+
} catch {}
|
|
134
|
+
})()
|
|
135
|
+
`;
|
|
136
|
+
const accentColorScript = `
|
|
137
|
+
(() => {
|
|
138
|
+
try {
|
|
139
|
+
const stored = localStorage.getItem('opencami-accent-color')
|
|
140
|
+
const map = {
|
|
141
|
+
green: { accent: '#22c55e', hover: '#16a34a', light: 'rgba(34, 197, 94, 0.10)' },
|
|
142
|
+
blue: { accent: '#3b82f6', hover: '#2563eb', light: 'rgba(59, 130, 246, 0.10)' },
|
|
143
|
+
purple: { accent: '#8b5cf6', hover: '#7c3aed', light: 'rgba(139, 92, 246, 0.10)' },
|
|
144
|
+
orange: { accent: '#f97316', hover: '#ea580c', light: 'rgba(249, 115, 22, 0.10)' },
|
|
145
|
+
pink: { accent: '#ec4899', hover: '#db2777', light: 'rgba(236, 72, 153, 0.10)' },
|
|
146
|
+
red: { accent: '#ef4444', hover: '#dc2626', light: 'rgba(239, 68, 68, 0.10)' },
|
|
147
|
+
cyan: { accent: '#06b6d4', hover: '#0891b2', light: 'rgba(6, 182, 212, 0.10)' },
|
|
148
|
+
yellow: { accent: '#eab308', hover: '#ca8a04', light: 'rgba(234, 179, 8, 0.10)' },
|
|
149
|
+
}
|
|
150
|
+
const selected = map[stored] || map.green
|
|
151
|
+
const root = document.documentElement
|
|
152
|
+
root.style.setProperty('--opencami-accent', selected.accent)
|
|
153
|
+
root.style.setProperty('--opencami-accent-hover', selected.hover)
|
|
154
|
+
root.style.setProperty('--opencami-accent-light', selected.light)
|
|
155
|
+
} catch {}
|
|
156
|
+
})()
|
|
157
|
+
`;
|
|
158
|
+
const chatWidthScript = `
|
|
159
|
+
(() => {
|
|
160
|
+
try {
|
|
161
|
+
const stored = localStorage.getItem('opencami-chat-width')
|
|
162
|
+
const map = {
|
|
163
|
+
narrow: '640px',
|
|
164
|
+
medium: '800px',
|
|
165
|
+
wide: '1000px',
|
|
166
|
+
full: '100%',
|
|
167
|
+
}
|
|
168
|
+
const value = map[stored] || map.wide
|
|
169
|
+
document.documentElement.style.setProperty('--opencami-chat-width', value)
|
|
170
|
+
} catch {}
|
|
171
|
+
})()
|
|
172
|
+
`;
|
|
173
|
+
const sidebarWidthScript = `
|
|
174
|
+
(() => {
|
|
175
|
+
try {
|
|
176
|
+
const stored = localStorage.getItem('opencami-sidebar-width')
|
|
177
|
+
const map = {
|
|
178
|
+
compact: '200px',
|
|
179
|
+
normal: '260px',
|
|
180
|
+
wide: '320px',
|
|
181
|
+
xl: '400px',
|
|
182
|
+
}
|
|
183
|
+
const value = map[stored] || map.normal
|
|
184
|
+
document.documentElement.style.setProperty('--opencami-sidebar-width', value)
|
|
185
|
+
} catch {}
|
|
186
|
+
})()
|
|
187
|
+
`;
|
|
188
|
+
const bubbleStyleScript = `
|
|
189
|
+
(() => {
|
|
190
|
+
try {
|
|
191
|
+
const stored = localStorage.getItem('opencami-bubble-style')
|
|
192
|
+
const value = stored === 'bubbles' || stored === 'minimal' || stored === 'default'
|
|
193
|
+
? stored
|
|
194
|
+
: 'default'
|
|
195
|
+
document.documentElement.setAttribute('data-opencami-bubble-style', value)
|
|
196
|
+
} catch {}
|
|
197
|
+
})()
|
|
198
|
+
`;
|
|
79
199
|
function NotFoundRedirect() {
|
|
80
200
|
if (typeof window !== "undefined") {
|
|
81
201
|
window.location.href = "/chat/main";
|
|
82
202
|
}
|
|
83
203
|
return null;
|
|
84
204
|
}
|
|
85
|
-
const Route$
|
|
205
|
+
const Route$w = createRootRoute({
|
|
86
206
|
notFoundComponent: NotFoundRedirect,
|
|
87
207
|
head: () => ({
|
|
88
208
|
meta: [
|
|
@@ -172,7 +292,14 @@ function RootLayout() {
|
|
|
172
292
|
function RootDocument({ children }) {
|
|
173
293
|
return /* @__PURE__ */ jsxs("html", { lang: "en", suppressHydrationWarning: true, children: [
|
|
174
294
|
/* @__PURE__ */ jsxs("head", { children: [
|
|
295
|
+
/* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: tauriDetectScript } }),
|
|
175
296
|
/* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: textSizeScript } }),
|
|
297
|
+
/* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: fontFamilyScript } }),
|
|
298
|
+
/* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: densityScript } }),
|
|
299
|
+
/* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: accentColorScript } }),
|
|
300
|
+
/* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: chatWidthScript } }),
|
|
301
|
+
/* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: sidebarWidthScript } }),
|
|
302
|
+
/* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: bubbleStyleScript } }),
|
|
176
303
|
/* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: themeScript } }),
|
|
177
304
|
/* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: swRegisterScript } }),
|
|
178
305
|
/* @__PURE__ */ jsx(HeadContent, {})
|
|
@@ -183,8 +310,12 @@ function RootDocument({ children }) {
|
|
|
183
310
|
] })
|
|
184
311
|
] });
|
|
185
312
|
}
|
|
313
|
+
const $$splitComponentImporter$7 = () => import("./skills-Cy8xclXY.js");
|
|
314
|
+
const Route$v = createFileRoute("/skills")({
|
|
315
|
+
component: lazyRouteComponent($$splitComponentImporter$7, "component")
|
|
316
|
+
});
|
|
186
317
|
const $$splitComponentImporter$6 = () => import("./new-Dzk5YxE9.js");
|
|
187
|
-
const Route$
|
|
318
|
+
const Route$u = createFileRoute("/new")({
|
|
188
319
|
beforeLoad: function redirectToNewChat() {
|
|
189
320
|
throw redirect({
|
|
190
321
|
to: "/chat/$sessionKey",
|
|
@@ -196,28 +327,28 @@ const Route$t = createFileRoute("/new")({
|
|
|
196
327
|
},
|
|
197
328
|
component: lazyRouteComponent($$splitComponentImporter$6, "component")
|
|
198
329
|
});
|
|
199
|
-
const $$splitComponentImporter$5 = () => import("./files-
|
|
200
|
-
const Route$
|
|
330
|
+
const $$splitComponentImporter$5 = () => import("./files-BIEcSPGp.js");
|
|
331
|
+
const Route$t = createFileRoute("/files")({
|
|
201
332
|
component: lazyRouteComponent($$splitComponentImporter$5, "component")
|
|
202
333
|
});
|
|
203
|
-
const $$splitComponentImporter$4 = () => import("./connect-
|
|
204
|
-
const Route$
|
|
334
|
+
const $$splitComponentImporter$4 = () => import("./connect-d3AqjAqe.js");
|
|
335
|
+
const Route$s = createFileRoute("/connect")({
|
|
205
336
|
component: lazyRouteComponent($$splitComponentImporter$4, "component")
|
|
206
337
|
});
|
|
207
|
-
const $$splitComponentImporter$3 = () => import("./bots-
|
|
208
|
-
const Route$
|
|
338
|
+
const $$splitComponentImporter$3 = () => import("./bots-Byt6jv0a.js");
|
|
339
|
+
const Route$r = createFileRoute("/bots")({
|
|
209
340
|
component: lazyRouteComponent($$splitComponentImporter$3, "component")
|
|
210
341
|
});
|
|
211
|
-
const $$splitComponentImporter$2 = () => import("./agents-
|
|
212
|
-
const Route$
|
|
342
|
+
const $$splitComponentImporter$2 = () => import("./agents-CmQ4vvXm.js");
|
|
343
|
+
const Route$q = createFileRoute("/agents")({
|
|
213
344
|
component: lazyRouteComponent($$splitComponentImporter$2, "component")
|
|
214
345
|
});
|
|
215
|
-
const $$splitComponentImporter$1 = () => import("./index-
|
|
216
|
-
const Route$
|
|
346
|
+
const $$splitComponentImporter$1 = () => import("./index-CRfLKh30.js");
|
|
347
|
+
const Route$p = createFileRoute("/")({
|
|
217
348
|
component: lazyRouteComponent($$splitComponentImporter$1, "component")
|
|
218
349
|
});
|
|
219
|
-
const $$splitComponentImporter = () => import("./_sessionKey-
|
|
220
|
-
const Route$
|
|
350
|
+
const $$splitComponentImporter = () => import("./_sessionKey-tRze5NLR.js").then((n) => n.$);
|
|
351
|
+
const Route$o = createFileRoute("/chat/$sessionKey")({
|
|
221
352
|
component: lazyRouteComponent($$splitComponentImporter, "component")
|
|
222
353
|
});
|
|
223
354
|
function getGatewayConfig() {
|
|
@@ -584,7 +715,7 @@ async function ttsEdge(text, voice) {
|
|
|
584
715
|
}
|
|
585
716
|
});
|
|
586
717
|
}
|
|
587
|
-
const Route$
|
|
718
|
+
const Route$n = createFileRoute("/api/tts")({
|
|
588
719
|
server: {
|
|
589
720
|
handlers: {
|
|
590
721
|
POST: async ({ request }) => {
|
|
@@ -739,7 +870,7 @@ async function sttOpenAI(audioBlob, apiKey, language) {
|
|
|
739
870
|
const data = await res.json();
|
|
740
871
|
return { text: data.text || "" };
|
|
741
872
|
}
|
|
742
|
-
const Route$
|
|
873
|
+
const Route$m = createFileRoute("/api/stt")({
|
|
743
874
|
server: {
|
|
744
875
|
handlers: {
|
|
745
876
|
POST: async ({ request }) => {
|
|
@@ -841,7 +972,7 @@ const Route$l = createFileRoute("/api/stt")({
|
|
|
841
972
|
}
|
|
842
973
|
}
|
|
843
974
|
});
|
|
844
|
-
const Route$
|
|
975
|
+
const Route$l = createFileRoute("/api/stream")({
|
|
845
976
|
server: {
|
|
846
977
|
handlers: {
|
|
847
978
|
GET: async ({ request }) => {
|
|
@@ -946,6 +1077,155 @@ data: ${JSON.stringify(data)}
|
|
|
946
1077
|
}
|
|
947
1078
|
}
|
|
948
1079
|
});
|
|
1080
|
+
const MY_SKILLS_CONFIG = resolve(process.cwd(), ".clawhub-my-skills.json");
|
|
1081
|
+
const RECOMMENDED_SKILLS = [
|
|
1082
|
+
"web-search-plus",
|
|
1083
|
+
"elevenlabs-voices",
|
|
1084
|
+
"sports-ticker",
|
|
1085
|
+
"personas",
|
|
1086
|
+
"agent-chronicle",
|
|
1087
|
+
"summarize",
|
|
1088
|
+
"weather",
|
|
1089
|
+
"muninn",
|
|
1090
|
+
"clawd-docs-v2",
|
|
1091
|
+
"therapy-mode"
|
|
1092
|
+
];
|
|
1093
|
+
function runCmd(cmd) {
|
|
1094
|
+
try {
|
|
1095
|
+
return execSync(cmd, { encoding: "utf-8", timeout: 3e4 }).trim();
|
|
1096
|
+
} catch (err) {
|
|
1097
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1098
|
+
throw new Error(`Command failed: ${msg}`);
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
function loadMySkillsSlugs() {
|
|
1102
|
+
try {
|
|
1103
|
+
if (!existsSync(MY_SKILLS_CONFIG)) return [];
|
|
1104
|
+
const data = JSON.parse(readFileSync(MY_SKILLS_CONFIG, "utf-8"));
|
|
1105
|
+
return Array.isArray(data.slugs) ? data.slugs : [];
|
|
1106
|
+
} catch {
|
|
1107
|
+
return [];
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
function parseInstalledSkills(output) {
|
|
1111
|
+
if (!output) return [];
|
|
1112
|
+
return output.split("\n").filter((line) => line.trim()).map((line) => {
|
|
1113
|
+
const match = line.match(/^(.+?)\s+v?([\d.]+.*)$/);
|
|
1114
|
+
if (match) return { name: match[1].trim(), version: match[2].trim() };
|
|
1115
|
+
return { name: line.trim(), version: "" };
|
|
1116
|
+
});
|
|
1117
|
+
}
|
|
1118
|
+
function parseSearchResults(output) {
|
|
1119
|
+
if (!output) return [];
|
|
1120
|
+
return output.split("\n").filter((line) => line.trim()).map((line) => {
|
|
1121
|
+
const match = line.match(/^(.+?)\s+v([\d.]+)\s+(.+?)(?:\s+\(([\d.]+)\))?$/);
|
|
1122
|
+
if (match) {
|
|
1123
|
+
return {
|
|
1124
|
+
slug: match[1].trim(),
|
|
1125
|
+
displayName: match[1].trim(),
|
|
1126
|
+
version: match[2].trim(),
|
|
1127
|
+
summary: match[3].trim(),
|
|
1128
|
+
score: match[4] ? parseFloat(match[4]) : void 0
|
|
1129
|
+
};
|
|
1130
|
+
}
|
|
1131
|
+
return { slug: line.trim(), displayName: line.trim(), version: "", summary: "" };
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1134
|
+
const Route$k = createFileRoute("/api/skills")({
|
|
1135
|
+
server: {
|
|
1136
|
+
handlers: {
|
|
1137
|
+
GET: async ({ request }) => {
|
|
1138
|
+
try {
|
|
1139
|
+
const url = new URL(request.url);
|
|
1140
|
+
const action = url.searchParams.get("action") || "installed";
|
|
1141
|
+
if (action === "installed") {
|
|
1142
|
+
const output = runCmd("clawhub list");
|
|
1143
|
+
return json({ ok: true, skills: parseInstalledSkills(output) });
|
|
1144
|
+
}
|
|
1145
|
+
if (action === "explore") {
|
|
1146
|
+
const sort = url.searchParams.get("sort") || "trending";
|
|
1147
|
+
const limit = url.searchParams.get("limit") || "25";
|
|
1148
|
+
const safeSort = sort.replace(/[^a-z-]/gi, "");
|
|
1149
|
+
const safeLimit = String(parseInt(limit, 10) || 25);
|
|
1150
|
+
const raw = runCmd(`clawhub explore --json --limit ${safeLimit} --sort ${safeSort}`);
|
|
1151
|
+
const output = raw.substring(raw.indexOf("{"));
|
|
1152
|
+
try {
|
|
1153
|
+
const data = JSON.parse(output);
|
|
1154
|
+
return json({ ok: true, skills: Array.isArray(data) ? data : data.items || data.skills || data.results || [] });
|
|
1155
|
+
} catch {
|
|
1156
|
+
return json({ ok: true, skills: [] });
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
if (action === "search") {
|
|
1160
|
+
const q = url.searchParams.get("q") || "";
|
|
1161
|
+
const limit = url.searchParams.get("limit") || "10";
|
|
1162
|
+
if (!q.trim()) return json({ ok: true, skills: [] });
|
|
1163
|
+
const safeLimit = String(parseInt(limit, 10) || 10);
|
|
1164
|
+
const safeQ = q.replace(/"/g, '\\"');
|
|
1165
|
+
const raw = runCmd(`clawhub search "${safeQ}" --limit ${safeLimit}`);
|
|
1166
|
+
const output = raw.replace(/^- Searching\n?/, "");
|
|
1167
|
+
return json({ ok: true, skills: parseSearchResults(output) });
|
|
1168
|
+
}
|
|
1169
|
+
if (action === "my-skills" || action === "recommended") {
|
|
1170
|
+
const targetSlugs = action === "my-skills" ? loadMySkillsSlugs() : RECOMMENDED_SKILLS;
|
|
1171
|
+
if (targetSlugs.length === 0) {
|
|
1172
|
+
return json({ ok: true, skills: [] });
|
|
1173
|
+
}
|
|
1174
|
+
const slugSet = new Set(targetSlugs);
|
|
1175
|
+
const found = /* @__PURE__ */ new Map();
|
|
1176
|
+
for (const sort of ["downloads", "installs", "newest", "trending"]) {
|
|
1177
|
+
if (found.size >= slugSet.size) break;
|
|
1178
|
+
try {
|
|
1179
|
+
const raw = runCmd(`clawhub explore --json --limit 200 --sort ${sort}`);
|
|
1180
|
+
const output = raw.substring(raw.indexOf("{"));
|
|
1181
|
+
const data = JSON.parse(output);
|
|
1182
|
+
const items = Array.isArray(data) ? data : data.items || [];
|
|
1183
|
+
for (const item of items) {
|
|
1184
|
+
if (item.slug && slugSet.has(item.slug) && !found.has(item.slug)) {
|
|
1185
|
+
found.set(item.slug, item);
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
} catch {
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
const skills = Array.from(found.values());
|
|
1192
|
+
skills.sort((a, b) => (b.stats?.downloads || 0) - (a.stats?.downloads || 0));
|
|
1193
|
+
return json({ ok: true, skills });
|
|
1194
|
+
}
|
|
1195
|
+
return json({ ok: false, error: "Unknown action" }, { status: 400 });
|
|
1196
|
+
} catch (err) {
|
|
1197
|
+
return json(
|
|
1198
|
+
{ ok: false, error: err instanceof Error ? err.message : String(err) },
|
|
1199
|
+
{ status: 500 }
|
|
1200
|
+
);
|
|
1201
|
+
}
|
|
1202
|
+
},
|
|
1203
|
+
POST: async ({ request }) => {
|
|
1204
|
+
try {
|
|
1205
|
+
const body = await request.json().catch(() => ({}));
|
|
1206
|
+
const action = typeof body.action === "string" ? body.action : "";
|
|
1207
|
+
const slug = typeof body.slug === "string" ? body.slug.trim() : "";
|
|
1208
|
+
if (!slug) return json({ ok: false, error: "slug is required" }, { status: 400 });
|
|
1209
|
+
const safeSlug = slug.replace(/[^a-zA-Z0-9/_-]/g, "");
|
|
1210
|
+
if (action === "install") {
|
|
1211
|
+
const output = runCmd(`clawhub install ${safeSlug} --no-input`);
|
|
1212
|
+
return json({ ok: true, output });
|
|
1213
|
+
}
|
|
1214
|
+
if (action === "update") {
|
|
1215
|
+
const output = runCmd(`clawhub update ${safeSlug} --no-input`);
|
|
1216
|
+
return json({ ok: true, output });
|
|
1217
|
+
}
|
|
1218
|
+
return json({ ok: false, error: "Unknown action" }, { status: 400 });
|
|
1219
|
+
} catch (err) {
|
|
1220
|
+
return json(
|
|
1221
|
+
{ ok: false, error: err instanceof Error ? err.message : String(err) },
|
|
1222
|
+
{ status: 500 }
|
|
1223
|
+
);
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
});
|
|
949
1229
|
function deriveFriendlyIdFromKey(key) {
|
|
950
1230
|
if (typeof key !== "string" || key.trim().length === 0) return "main";
|
|
951
1231
|
const parts = key.split(":");
|
|
@@ -2993,155 +3273,165 @@ const Route = createFileRoute("/api/files/delete")({
|
|
|
2993
3273
|
}
|
|
2994
3274
|
}
|
|
2995
3275
|
});
|
|
2996
|
-
const
|
|
3276
|
+
const SkillsRoute = Route$v.update({
|
|
3277
|
+
id: "/skills",
|
|
3278
|
+
path: "/skills",
|
|
3279
|
+
getParentRoute: () => Route$w
|
|
3280
|
+
});
|
|
3281
|
+
const NewRoute = Route$u.update({
|
|
2997
3282
|
id: "/new",
|
|
2998
3283
|
path: "/new",
|
|
2999
|
-
getParentRoute: () => Route$
|
|
3284
|
+
getParentRoute: () => Route$w
|
|
3000
3285
|
});
|
|
3001
|
-
const FilesRoute = Route$
|
|
3286
|
+
const FilesRoute = Route$t.update({
|
|
3002
3287
|
id: "/files",
|
|
3003
3288
|
path: "/files",
|
|
3004
|
-
getParentRoute: () => Route$
|
|
3289
|
+
getParentRoute: () => Route$w
|
|
3005
3290
|
});
|
|
3006
|
-
const ConnectRoute = Route$
|
|
3291
|
+
const ConnectRoute = Route$s.update({
|
|
3007
3292
|
id: "/connect",
|
|
3008
3293
|
path: "/connect",
|
|
3009
|
-
getParentRoute: () => Route$
|
|
3294
|
+
getParentRoute: () => Route$w
|
|
3010
3295
|
});
|
|
3011
|
-
const BotsRoute = Route$
|
|
3296
|
+
const BotsRoute = Route$r.update({
|
|
3012
3297
|
id: "/bots",
|
|
3013
3298
|
path: "/bots",
|
|
3014
|
-
getParentRoute: () => Route$
|
|
3299
|
+
getParentRoute: () => Route$w
|
|
3015
3300
|
});
|
|
3016
|
-
const AgentsRoute = Route$
|
|
3301
|
+
const AgentsRoute = Route$q.update({
|
|
3017
3302
|
id: "/agents",
|
|
3018
3303
|
path: "/agents",
|
|
3019
|
-
getParentRoute: () => Route$
|
|
3304
|
+
getParentRoute: () => Route$w
|
|
3020
3305
|
});
|
|
3021
|
-
const IndexRoute = Route$
|
|
3306
|
+
const IndexRoute = Route$p.update({
|
|
3022
3307
|
id: "/",
|
|
3023
3308
|
path: "/",
|
|
3024
|
-
getParentRoute: () => Route$
|
|
3309
|
+
getParentRoute: () => Route$w
|
|
3025
3310
|
});
|
|
3026
|
-
const ChatSessionKeyRoute = Route$
|
|
3311
|
+
const ChatSessionKeyRoute = Route$o.update({
|
|
3027
3312
|
id: "/chat/$sessionKey",
|
|
3028
3313
|
path: "/chat/$sessionKey",
|
|
3029
|
-
getParentRoute: () => Route$
|
|
3314
|
+
getParentRoute: () => Route$w
|
|
3030
3315
|
});
|
|
3031
|
-
const ApiTtsRoute = Route$
|
|
3316
|
+
const ApiTtsRoute = Route$n.update({
|
|
3032
3317
|
id: "/api/tts",
|
|
3033
3318
|
path: "/api/tts",
|
|
3034
|
-
getParentRoute: () => Route$
|
|
3319
|
+
getParentRoute: () => Route$w
|
|
3035
3320
|
});
|
|
3036
|
-
const ApiSttRoute = Route$
|
|
3321
|
+
const ApiSttRoute = Route$m.update({
|
|
3037
3322
|
id: "/api/stt",
|
|
3038
3323
|
path: "/api/stt",
|
|
3039
|
-
getParentRoute: () => Route$
|
|
3324
|
+
getParentRoute: () => Route$w
|
|
3040
3325
|
});
|
|
3041
|
-
const ApiStreamRoute = Route$
|
|
3326
|
+
const ApiStreamRoute = Route$l.update({
|
|
3042
3327
|
id: "/api/stream",
|
|
3043
3328
|
path: "/api/stream",
|
|
3044
|
-
getParentRoute: () => Route$
|
|
3329
|
+
getParentRoute: () => Route$w
|
|
3330
|
+
});
|
|
3331
|
+
const ApiSkillsRoute = Route$k.update({
|
|
3332
|
+
id: "/api/skills",
|
|
3333
|
+
path: "/api/skills",
|
|
3334
|
+
getParentRoute: () => Route$w
|
|
3045
3335
|
});
|
|
3046
3336
|
const ApiSessionsRoute = Route$j.update({
|
|
3047
3337
|
id: "/api/sessions",
|
|
3048
3338
|
path: "/api/sessions",
|
|
3049
|
-
getParentRoute: () => Route$
|
|
3339
|
+
getParentRoute: () => Route$w
|
|
3050
3340
|
});
|
|
3051
3341
|
const ApiSendRoute = Route$i.update({
|
|
3052
3342
|
id: "/api/send",
|
|
3053
3343
|
path: "/api/send",
|
|
3054
|
-
getParentRoute: () => Route$
|
|
3344
|
+
getParentRoute: () => Route$w
|
|
3055
3345
|
});
|
|
3056
3346
|
const ApiPingRoute = Route$h.update({
|
|
3057
3347
|
id: "/api/ping",
|
|
3058
3348
|
path: "/api/ping",
|
|
3059
|
-
getParentRoute: () => Route$
|
|
3349
|
+
getParentRoute: () => Route$w
|
|
3060
3350
|
});
|
|
3061
3351
|
const ApiPersonasRoute = Route$g.update({
|
|
3062
3352
|
id: "/api/personas",
|
|
3063
3353
|
path: "/api/personas",
|
|
3064
|
-
getParentRoute: () => Route$
|
|
3354
|
+
getParentRoute: () => Route$w
|
|
3065
3355
|
});
|
|
3066
3356
|
const ApiPathsRoute = Route$f.update({
|
|
3067
3357
|
id: "/api/paths",
|
|
3068
3358
|
path: "/api/paths",
|
|
3069
|
-
getParentRoute: () => Route$
|
|
3359
|
+
getParentRoute: () => Route$w
|
|
3070
3360
|
});
|
|
3071
3361
|
const ApiModelsRoute = Route$e.update({
|
|
3072
3362
|
id: "/api/models",
|
|
3073
3363
|
path: "/api/models",
|
|
3074
|
-
getParentRoute: () => Route$
|
|
3364
|
+
getParentRoute: () => Route$w
|
|
3075
3365
|
});
|
|
3076
3366
|
const ApiLlmFeaturesRoute = Route$d.update({
|
|
3077
3367
|
id: "/api/llm-features",
|
|
3078
3368
|
path: "/api/llm-features",
|
|
3079
|
-
getParentRoute: () => Route$
|
|
3369
|
+
getParentRoute: () => Route$w
|
|
3080
3370
|
});
|
|
3081
3371
|
const ApiHistoryRoute = Route$c.update({
|
|
3082
3372
|
id: "/api/history",
|
|
3083
3373
|
path: "/api/history",
|
|
3084
|
-
getParentRoute: () => Route$
|
|
3374
|
+
getParentRoute: () => Route$w
|
|
3085
3375
|
});
|
|
3086
3376
|
const ApiFollowUpsRoute = Route$b.update({
|
|
3087
3377
|
id: "/api/follow-ups",
|
|
3088
3378
|
path: "/api/follow-ups",
|
|
3089
|
-
getParentRoute: () => Route$
|
|
3379
|
+
getParentRoute: () => Route$w
|
|
3090
3380
|
});
|
|
3091
3381
|
const ApiCronRoute = Route$a.update({
|
|
3092
3382
|
id: "/api/cron",
|
|
3093
3383
|
path: "/api/cron",
|
|
3094
|
-
getParentRoute: () => Route$
|
|
3384
|
+
getParentRoute: () => Route$w
|
|
3095
3385
|
});
|
|
3096
3386
|
const ApiAgentsRoute = Route$9.update({
|
|
3097
3387
|
id: "/api/agents",
|
|
3098
3388
|
path: "/api/agents",
|
|
3099
|
-
getParentRoute: () => Route$
|
|
3389
|
+
getParentRoute: () => Route$w
|
|
3100
3390
|
});
|
|
3101
3391
|
const ApiFilesUploadRoute = Route$8.update({
|
|
3102
3392
|
id: "/api/files/upload",
|
|
3103
3393
|
path: "/api/files/upload",
|
|
3104
|
-
getParentRoute: () => Route$
|
|
3394
|
+
getParentRoute: () => Route$w
|
|
3105
3395
|
});
|
|
3106
3396
|
const ApiFilesSaveRoute = Route$7.update({
|
|
3107
3397
|
id: "/api/files/save",
|
|
3108
3398
|
path: "/api/files/save",
|
|
3109
|
-
getParentRoute: () => Route$
|
|
3399
|
+
getParentRoute: () => Route$w
|
|
3110
3400
|
});
|
|
3111
3401
|
const ApiFilesRenameRoute = Route$6.update({
|
|
3112
3402
|
id: "/api/files/rename",
|
|
3113
3403
|
path: "/api/files/rename",
|
|
3114
|
-
getParentRoute: () => Route$
|
|
3404
|
+
getParentRoute: () => Route$w
|
|
3115
3405
|
});
|
|
3116
3406
|
const ApiFilesReadRoute = Route$5.update({
|
|
3117
3407
|
id: "/api/files/read",
|
|
3118
3408
|
path: "/api/files/read",
|
|
3119
|
-
getParentRoute: () => Route$
|
|
3409
|
+
getParentRoute: () => Route$w
|
|
3120
3410
|
});
|
|
3121
3411
|
const ApiFilesMkdirRoute = Route$4.update({
|
|
3122
3412
|
id: "/api/files/mkdir",
|
|
3123
3413
|
path: "/api/files/mkdir",
|
|
3124
|
-
getParentRoute: () => Route$
|
|
3414
|
+
getParentRoute: () => Route$w
|
|
3125
3415
|
});
|
|
3126
3416
|
const ApiFilesListRoute = Route$3.update({
|
|
3127
3417
|
id: "/api/files/list",
|
|
3128
3418
|
path: "/api/files/list",
|
|
3129
|
-
getParentRoute: () => Route$
|
|
3419
|
+
getParentRoute: () => Route$w
|
|
3130
3420
|
});
|
|
3131
3421
|
const ApiFilesInfoRoute = Route$2.update({
|
|
3132
3422
|
id: "/api/files/info",
|
|
3133
3423
|
path: "/api/files/info",
|
|
3134
|
-
getParentRoute: () => Route$
|
|
3424
|
+
getParentRoute: () => Route$w
|
|
3135
3425
|
});
|
|
3136
3426
|
const ApiFilesDownloadRoute = Route$1.update({
|
|
3137
3427
|
id: "/api/files/download",
|
|
3138
3428
|
path: "/api/files/download",
|
|
3139
|
-
getParentRoute: () => Route$
|
|
3429
|
+
getParentRoute: () => Route$w
|
|
3140
3430
|
});
|
|
3141
3431
|
const ApiFilesDeleteRoute = Route.update({
|
|
3142
3432
|
id: "/api/files/delete",
|
|
3143
3433
|
path: "/api/files/delete",
|
|
3144
|
-
getParentRoute: () => Route$
|
|
3434
|
+
getParentRoute: () => Route$w
|
|
3145
3435
|
});
|
|
3146
3436
|
const rootRouteChildren = {
|
|
3147
3437
|
IndexRoute,
|
|
@@ -3150,6 +3440,7 @@ const rootRouteChildren = {
|
|
|
3150
3440
|
ConnectRoute,
|
|
3151
3441
|
FilesRoute,
|
|
3152
3442
|
NewRoute,
|
|
3443
|
+
SkillsRoute,
|
|
3153
3444
|
ApiAgentsRoute,
|
|
3154
3445
|
ApiCronRoute,
|
|
3155
3446
|
ApiFollowUpsRoute,
|
|
@@ -3161,6 +3452,7 @@ const rootRouteChildren = {
|
|
|
3161
3452
|
ApiPingRoute,
|
|
3162
3453
|
ApiSendRoute,
|
|
3163
3454
|
ApiSessionsRoute,
|
|
3455
|
+
ApiSkillsRoute,
|
|
3164
3456
|
ApiStreamRoute,
|
|
3165
3457
|
ApiSttRoute,
|
|
3166
3458
|
ApiTtsRoute,
|
|
@@ -3175,7 +3467,7 @@ const rootRouteChildren = {
|
|
|
3175
3467
|
ApiFilesSaveRoute,
|
|
3176
3468
|
ApiFilesUploadRoute
|
|
3177
3469
|
};
|
|
3178
|
-
const routeTree = Route$
|
|
3470
|
+
const routeTree = Route$w._addFileChildren(rootRouteChildren)._addFileTypes();
|
|
3179
3471
|
const getRouter = () => {
|
|
3180
3472
|
const router2 = createRouter({
|
|
3181
3473
|
routeTree,
|
|
@@ -3190,7 +3482,7 @@ const router = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
|
|
|
3190
3482
|
getRouter
|
|
3191
3483
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
3192
3484
|
export {
|
|
3193
|
-
Route$
|
|
3194
|
-
Route$
|
|
3485
|
+
Route$p as R,
|
|
3486
|
+
Route$o as a,
|
|
3195
3487
|
router as r
|
|
3196
3488
|
};
|