@hina114514/chaite 1.9.3 → 1.9.4

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.
@@ -1,4 +1,4 @@
1
- import { d as init_adapters, f as createClient, g as AbstractClient, h as OpenAIClient, m as ClaudeClient, p as GeminiClient } from "./src-BjDIhdKO.mjs";
1
+ import { d as init_adapters, f as createClient, g as AbstractClient, h as OpenAIClient, m as ClaudeClient, p as GeminiClient } from "./src-DGgOl4PZ.mjs";
2
2
  import "./chunks/lop/index.mjs-BWbOMJZv.mjs";
3
3
  import "./chunks/bluebird/index.mjs-D4zFjek8.mjs";
4
4
  import "./chunks/mammoth/index.mjs-C9xwBIgf.mjs";
package/dist/index.d.ts CHANGED
@@ -1567,7 +1567,7 @@ declare const PROCESSOR_TYPE_MAP: {
1567
1567
  };
1568
1568
  //#endregion
1569
1569
  //#region src/version.d.ts
1570
- declare const VERSION = "1.9.3";
1570
+ declare const VERSION = "1.9.4";
1571
1571
  //#endregion
1572
1572
  //#region src/controllers/index.d.ts
1573
1573
  declare function createApp(configure?: (app: Application) => void): Application;
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as ChaiteStorage, A as FrontEndAuthHandler, B as VectorizerImpl, C as Channel, D as ExecutableShareableManager, E as ToolManager, F as PureTextFileParser, G as KVHistoryManager, H as RAGManager, I as DocxBufferParser, J as getKey, K as asyncLocalStorage, L as DocxFileParser, M as DEFAULT_PORT, N as GlobalConfig, O as NonExecutableShareableManager, P as PureTextBufferParser, Q as ChaiteResponse, R as PdfBufferParser, S as ChatPreset, T as DefaultCloudService, U as TextProcessor, V as AbstractVectorDatabase, W as InMemoryHistoryManager, X as useEvent, Y as saveAndLoadModule, Z as AbstractUserModeSelector, _ as TriggerManager, _t as AbstractShareable, a as EventTrigger, at as AbstractHistoryManager, b as ProcessorsManager, c as createApp, ct as DocumentFileParser, dt as ToolDTO, et as PostProcessor, f as createClient, ft as ToolsGroupDTO, g as AbstractClient, gt as MultipleKeyStrategyChoice, h as OpenAIClient, ht as DefaultLogger, i as CronTrigger, it as PROCESSOR_TYPE_MAP, j as DEFAULT_HOST, k as getLogger, l as runServer, lt as DocumentPathParser, m as ClaudeClient, mt as ChaiteContext, nt as ProcessorDTO, o as TriggerDTO, ot as SendMessageOption, p as GeminiClient, pt as BaseClientOptions, q as extractClassName, r as BaseTrigger, rt as CHANNEL_STATUS_MAP, s as Chaite, st as ChannelStatistics, t as init_src, tt as PreProcessor, u as VERSION, ut as CustomTool, v as ToolsGroupManager, w as DefaultChannelLoadBalancer, x as ChannelsManager, y as ChatPresetManager, z as PdfFileParser } from "./src-BjDIhdKO.mjs";
1
+ import { $ as ChaiteStorage, A as FrontEndAuthHandler, B as VectorizerImpl, C as Channel, D as ExecutableShareableManager, E as ToolManager, F as PureTextFileParser, G as KVHistoryManager, H as RAGManager, I as DocxBufferParser, J as getKey, K as asyncLocalStorage, L as DocxFileParser, M as DEFAULT_PORT, N as GlobalConfig, O as NonExecutableShareableManager, P as PureTextBufferParser, Q as ChaiteResponse, R as PdfBufferParser, S as ChatPreset, T as DefaultCloudService, U as TextProcessor, V as AbstractVectorDatabase, W as InMemoryHistoryManager, X as useEvent, Y as saveAndLoadModule, Z as AbstractUserModeSelector, _ as TriggerManager, _t as AbstractShareable, a as EventTrigger, at as AbstractHistoryManager, b as ProcessorsManager, c as createApp, ct as DocumentFileParser, dt as ToolDTO, et as PostProcessor, f as createClient, ft as ToolsGroupDTO, g as AbstractClient, gt as MultipleKeyStrategyChoice, h as OpenAIClient, ht as DefaultLogger, i as CronTrigger, it as PROCESSOR_TYPE_MAP, j as DEFAULT_HOST, k as getLogger, l as runServer, lt as DocumentPathParser, m as ClaudeClient, mt as ChaiteContext, nt as ProcessorDTO, o as TriggerDTO, ot as SendMessageOption, p as GeminiClient, pt as BaseClientOptions, q as extractClassName, r as BaseTrigger, rt as CHANNEL_STATUS_MAP, s as Chaite, st as ChannelStatistics, t as init_src, tt as PreProcessor, u as VERSION, ut as CustomTool, v as ToolsGroupManager, w as DefaultChannelLoadBalancer, x as ChannelsManager, y as ChatPresetManager, z as PdfFileParser } from "./src-DGgOl4PZ.mjs";
2
2
  import "./chunks/lop/index.mjs-BWbOMJZv.mjs";
3
3
  import "./chunks/bluebird/index.mjs-D4zFjek8.mjs";
4
4
  import "./chunks/mammoth/index.mjs-C9xwBIgf.mjs";
@@ -4441,7 +4441,7 @@ var init_trigger$1 = __esm({ "src/controllers/trigger.ts": (() => {
4441
4441
  //#region src/version.ts
4442
4442
  var VERSION;
4443
4443
  var init_version = __esm({ "src/version.ts": (() => {
4444
- VERSION = "1.9.3";
4444
+ VERSION = "1.9.4";
4445
4445
  }) });
4446
4446
 
4447
4447
  //#endregion
@@ -4567,8 +4567,8 @@ var init_basic = __esm({ "src/controllers/basic.ts": (() => {
4567
4567
  res.status(404).json(ChaiteResponse.fail(null, "Channel not found"));
4568
4568
  return;
4569
4569
  }
4570
- const { createClient: createClient$1 } = await import("./adapters-BeZFg37c.mjs");
4571
- const { ChaiteContext: ChaiteContext$1 } = await import("./types-6jzst6Q4.mjs");
4570
+ const { createClient: createClient$1 } = await import("./adapters-DLb1sL9p.mjs");
4571
+ const { ChaiteContext: ChaiteContext$1 } = await import("./types-BN6lBxWd.mjs");
4572
4572
  const ctx = new ChaiteContext$1(chaite.getLogger());
4573
4573
  ctx.setChaite(chaite);
4574
4574
  const client = createClient$1(channel.adapterType, channel.options, ctx);
@@ -1,4 +1,4 @@
1
- import { $ as ChaiteStorage, Q as ChaiteResponse, Z as AbstractUserModeSelector, _t as AbstractShareable, a as EventTrigger, at as AbstractHistoryManager, ct as DocumentFileParser, dt as ToolDTO, et as PostProcessor, ft as ToolsGroupDTO, gt as MultipleKeyStrategyChoice, ht as DefaultLogger, i as CronTrigger, lt as DocumentPathParser, mt as ChaiteContext, n as init_types, nt as ProcessorDTO, o as TriggerDTO, ot as SendMessageOption, pt as BaseClientOptions, r as BaseTrigger, st as ChannelStatistics, tt as PreProcessor, ut as CustomTool } from "./src-BjDIhdKO.mjs";
1
+ import { $ as ChaiteStorage, Q as ChaiteResponse, Z as AbstractUserModeSelector, _t as AbstractShareable, a as EventTrigger, at as AbstractHistoryManager, ct as DocumentFileParser, dt as ToolDTO, et as PostProcessor, ft as ToolsGroupDTO, gt as MultipleKeyStrategyChoice, ht as DefaultLogger, i as CronTrigger, lt as DocumentPathParser, mt as ChaiteContext, n as init_types, nt as ProcessorDTO, o as TriggerDTO, ot as SendMessageOption, pt as BaseClientOptions, r as BaseTrigger, st as ChannelStatistics, tt as PreProcessor, ut as CustomTool } from "./src-DGgOl4PZ.mjs";
2
2
  import "./chunks/lop/index.mjs-BWbOMJZv.mjs";
3
3
  import "./chunks/bluebird/index.mjs-D4zFjek8.mjs";
4
4
  import "./chunks/mammoth/index.mjs-C9xwBIgf.mjs";
@@ -1,537 +1,18 @@
1
- <!DOCTYPE html>
2
- <html lang="zh-CN">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Chaite Dashboard</title>
7
- <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>⚡</text></svg>">
8
- <style>
9
- :root {
10
- --bg: #0f1117;
11
- --surface: #1a1d27;
12
- --surface2: #252836;
13
- --border: #2d3040;
14
- --text: #e4e6f0;
15
- --text2: #8b8fa8;
16
- --accent: #6366f1;
17
- --accent2: #818cf8;
18
- --green: #22c55e;
19
- --red: #ef4444;
20
- --orange: #f59e0b;
21
- --radius: 10px;
22
- }
23
- * { margin: 0; padding: 0; box-sizing: border-box; }
24
- body {
25
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
26
- background: var(--bg);
27
- color: var(--text);
28
- min-height: 100vh;
29
- }
30
- .app { max-width: 1200px; margin: 0 auto; padding: 24px; }
31
-
32
- /* Header */
33
- .header {
34
- display: flex; justify-content: space-between; align-items: center;
35
- padding: 16px 0; margin-bottom: 24px;
36
- border-bottom: 1px solid var(--border);
37
- }
38
- .header h1 { font-size: 22px; font-weight: 600; }
39
- .header h1 span { color: var(--accent2); }
40
- .header .meta { display: flex; gap: 12px; align-items: center; }
41
- .badge {
42
- padding: 4px 10px; border-radius: 20px;
43
- font-size: 12px; font-weight: 500;
44
- background: var(--surface2); border: 1px solid var(--border);
45
- }
46
- .badge.ok { border-color: var(--green); color: var(--green); }
47
- .badge.err { border-color: var(--red); color: var(--red); }
48
-
49
- /* Cards grid */
50
- .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 16px; margin-bottom: 24px; }
51
- .card {
52
- background: var(--surface);
53
- border: 1px solid var(--border);
54
- border-radius: var(--radius);
55
- padding: 20px;
56
- transition: border-color .15s;
57
- }
58
- .card:hover { border-color: var(--accent); }
59
- .card .label { font-size: 12px; color: var(--text2); text-transform: uppercase; letter-spacing: .5px; margin-bottom: 8px; }
60
- .card .value { font-size: 28px; font-weight: 700; color: var(--text); }
61
- .card .sub { font-size: 13px; color: var(--text2); margin-top: 4px; }
62
-
63
- /* Section */
64
- .section { margin-bottom: 32px; }
65
- .section h2 {
66
- font-size: 16px; font-weight: 600; margin-bottom: 16px;
67
- display: flex; align-items: center; gap: 8px;
68
- }
69
- .section h2 .dot {
70
- width: 8px; height: 8px; border-radius: 50%; background: var(--accent);
71
- }
72
-
73
- /* Table */
74
- .table-wrap {
75
- background: var(--surface);
76
- border: 1px solid var(--border);
77
- border-radius: var(--radius);
78
- overflow: hidden;
79
- }
80
- table { width: 100%; border-collapse: collapse; }
81
- th {
82
- text-align: left; padding: 12px 16px;
83
- font-size: 11px; text-transform: uppercase; letter-spacing: .5px;
84
- color: var(--text2); border-bottom: 1px solid var(--border);
85
- background: var(--surface2);
86
- }
87
- td {
88
- padding: 12px 16px; font-size: 14px;
89
- border-bottom: 1px solid var(--border);
90
- }
91
- tr:last-child td { border-bottom: none; }
92
- tr:hover td { background: rgba(99,102,241,.04); }
93
-
94
- .status-dot {
95
- display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-right: 6px;
96
- }
97
- .status-dot.on { background: var(--green); }
98
- .status-dot.off { background: var(--red); }
99
-
100
- .model-tag {
101
- display: inline-block; padding: 2px 8px; border-radius: 4px;
102
- font-size: 11px; background: var(--surface2); color: var(--text2);
103
- margin: 2px 2px;
104
- }
105
-
106
- /* Button */
107
- .btn {
108
- padding: 8px 16px; border-radius: 6px; font-size: 13px; font-weight: 500;
109
- border: 1px solid var(--border); background: var(--surface2); color: var(--text);
110
- cursor: pointer; transition: all .15s;
111
- }
112
- .btn:hover { border-color: var(--accent); color: var(--accent2); }
113
- .btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
114
- .btn.primary:hover { background: var(--accent2); }
115
- .btn:disabled { opacity: .5; cursor: not-allowed; }
116
-
117
- /* Login */
118
- .login-overlay {
119
- position: fixed; inset: 0; background: var(--bg);
120
- display: flex; align-items: center; justify-content: center;
121
- z-index: 1000;
122
- }
123
- .login-box {
124
- background: var(--surface); border: 1px solid var(--border);
125
- border-radius: var(--radius); padding: 40px; width: 360px; text-align: center;
126
- }
127
- .login-box h2 { margin-bottom: 24px; font-size: 20px; }
128
- .login-box input {
129
- width: 100%; padding: 10px 14px; border-radius: 6px;
130
- border: 1px solid var(--border); background: var(--surface2);
131
- color: var(--text); font-size: 14px; margin-bottom: 16px; outline: none;
132
- }
133
- .login-box input:focus { border-color: var(--accent); }
134
- .login-box .error { color: var(--red); font-size: 13px; margin-bottom: 12px; min-height: 20px; }
135
- .login-box .btn { width: 100%; }
136
- .login-box .hint { font-size: 12px; color: var(--text2); margin-top: 12px; line-height: 1.5; }
137
-
138
- /* Refresh bar */
139
- .toolbar {
140
- display: flex; justify-content: space-between; align-items: center;
141
- margin-bottom: 16px;
142
- }
143
- .toolbar .info { font-size: 13px; color: var(--text2); }
144
-
145
- /* Spinner */
146
- .spinner {
147
- display: inline-block; width: 14px; height: 14px;
148
- border: 2px solid var(--border); border-top-color: var(--accent);
149
- border-radius: 50%; animation: spin .6s linear infinite;
150
- }
151
- @keyframes spin { to { transform: rotate(360deg); } }
152
-
153
- /* Test result */
154
- .test-result {
155
- margin-top: 16px; padding: 12px 16px;
156
- border-radius: var(--radius); font-size: 13px;
157
- }
158
- .test-result.ok { background: rgba(34,197,94,.1); border: 1px solid rgba(34,197,94,.3); }
159
- .test-result.err { background: rgba(239,68,68,.1); border: 1px solid rgba(239,68,68,.3); }
160
-
161
- /* Conversations */
162
- .conv-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 12px; }
163
- .conv-card {
164
- background: var(--surface); border: 1px solid var(--border);
165
- border-radius: var(--radius); padding: 16px;
166
- }
167
- .conv-card .uid { font-size: 14px; font-weight: 600; }
168
- .conv-card .cid { font-size: 12px; color: var(--text2); margin-top: 4px; word-break: break-all; }
169
- .conv-card .model { font-size: 12px; color: var(--accent2); margin-top: 4px; }
170
-
171
- @media (max-width: 640px) {
172
- .app { padding: 16px; }
173
- .grid { grid-template-columns: 1fr 1fr; }
174
- .conv-list { grid-template-columns: 1fr; }
175
- }
176
- </style>
177
- </head>
178
- <body>
179
- <div id="app"></div>
180
- <script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
181
- <script>
182
- const { createApp, ref, reactive, onMounted, onUnmounted } = Vue
183
-
184
- createApp({
185
- setup() {
186
- const jwt = ref(localStorage.getItem('chaite_jwt') || '')
187
- const loggedIn = ref(!!jwt.value)
188
- const loginError = ref('')
189
- const loginLoading = ref(false)
190
-
191
- const health = ref(null)
192
- const stats = ref(null)
193
- const channels = ref([])
194
- const conversations = ref([])
195
- const testResult = ref(null)
196
- const testLoading = ref(false)
197
- const loading = ref(true)
198
- const refreshTime = ref('')
199
- let timer = null
200
- let tokenExpiresAt = parseInt(localStorage.getItem('chaite_jwt_exp') || '0')
201
-
202
- const headers = () => ({
203
- 'Content-Type': 'application/json',
204
- 'Authorization': `Bearer ${jwt.value}`
205
- })
206
-
207
- // Extract ?token=xxx from URL
208
- function getUrlToken() {
209
- const params = new URLSearchParams(window.location.search)
210
- return params.get('token') || ''
211
- }
212
-
213
- function isTokenExpired() {
214
- if (!tokenExpiresAt) return false
215
- return Date.now() / 1000 > tokenExpiresAt - 300
216
- }
217
-
218
- // Auto-login: if ?token= is in URL, use it to get a JWT
219
- async function autoLogin() {
220
- const urlToken = getUrlToken()
221
- if (!urlToken) {
222
- // No URL token — check if we have a stored JWT
223
- if (jwt.value && !isTokenExpired()) {
224
- loggedIn.value = true
225
- refreshAll()
226
- } else if (jwt.value && isTokenExpired()) {
227
- // Try refresh
228
- tryRefresh()
229
- }
230
- return
231
- }
232
-
233
- // Exchange access token for JWT
234
- loginLoading.value = true
235
- loginError.value = ''
236
- try {
237
- const r = await fetch('/api/auth/login', {
238
- method: 'POST',
239
- headers: { 'Content-Type': 'application/json' },
240
- body: JSON.stringify({ token: urlToken })
241
- })
242
- const d = await r.json()
243
- if (d.data?.token) {
244
- jwt.value = d.data.token
245
- tokenExpiresAt = Math.floor(Date.now() / 1000) + (d.data.expiresIn || 604800)
246
- localStorage.setItem('chaite_jwt', d.data.token)
247
- localStorage.setItem('chaite_jwt_exp', String(tokenExpiresAt))
248
- loggedIn.value = true
249
- // Clean URL (remove ?token= from address bar)
250
- window.history.replaceState({}, '', window.location.pathname)
251
- refreshAll()
252
- } else {
253
- loginError.value = 'Invalid or expired access token'
254
- }
255
- } catch (e) {
256
- loginError.value = 'Network error'
257
- } finally {
258
- loginLoading.value = false
259
- }
260
- }
261
-
262
- async function tryRefresh() {
263
- try {
264
- const r = await fetch('/api/auth/refresh', { method: 'POST', headers: headers() })
265
- const d = await r.json()
266
- if (d.data?.token) {
267
- jwt.value = d.data.token
268
- tokenExpiresAt = Math.floor(Date.now() / 1000) + (d.data.expiresIn || 604800)
269
- localStorage.setItem('chaite_jwt', d.data.token)
270
- localStorage.setItem('chaite_jwt_exp', String(tokenExpiresAt))
271
- loggedIn.value = true
272
- refreshAll()
273
- } else {
274
- logout()
275
- }
276
- } catch {
277
- logout()
278
- }
279
- }
280
-
281
- function logout() {
282
- jwt.value = ''
283
- tokenExpiresAt = 0
284
- localStorage.removeItem('chaite_jwt')
285
- localStorage.removeItem('chaite_jwt_exp')
286
- loggedIn.value = false
287
- health.value = null
288
- stats.value = null
289
- channels.value = []
290
- }
291
-
292
- async function api(path) {
293
- if (isTokenExpired()) {
294
- await tryRefresh()
295
- if (!loggedIn.value) return null
296
- }
297
- const r = await fetch(path, { headers: headers() })
298
- if (r.status === 401) { logout(); return null }
299
- const d = await r.json()
300
- return d.data
301
- }
302
-
303
- async function refreshAll() {
304
- loading.value = true
305
- try {
306
- const [h, s, ch, cv] = await Promise.all([
307
- api('/api/system/health'),
308
- api('/api/system/stats'),
309
- api('/api/channels/list'),
310
- api('/api/state/conversations/list'),
311
- ])
312
- health.value = h
313
- stats.value = s
314
- channels.value = ch || []
315
- conversations.value = cv || []
316
- refreshTime.value = new Date().toLocaleTimeString()
317
- } catch (e) {
318
- console.error('refresh error', e)
319
- } finally {
320
- loading.value = false
321
- }
322
- }
323
-
324
- async function testChannel(channelId) {
325
- testLoading.value = true
326
- testResult.value = null
327
- try {
328
- const r = await fetch('/api/system/test-channel', {
329
- method: 'POST',
330
- headers: headers(),
331
- body: JSON.stringify({ channelId })
332
- })
333
- testResult.value = await r.json()
334
- } catch (e) {
335
- testResult.value = { data: { status: 'error', error: e.message } }
336
- } finally {
337
- testLoading.value = false
338
- }
339
- }
340
-
341
- function uptimeStr(s) {
342
- if (!s && s !== 0) return '-'
343
- const h = Math.floor(s / 3600)
344
- const m = Math.floor((s % 3600) / 60)
345
- const sec = s % 60
346
- return h ? `${h}h ${m}m` : m ? `${m}m ${sec}s` : `${sec}s`
347
- }
348
-
349
- function fmtNum(n) {
350
- if (!n && n !== 0) return '0'
351
- if (n >= 1e6) return (n / 1e6).toFixed(1) + 'M'
352
- if (n >= 1e3) return (n / 1e3).toFixed(1) + 'K'
353
- return String(n)
354
- }
355
-
356
- onMounted(() => {
357
- autoLogin()
358
- timer = setInterval(() => { if (loggedIn.value) refreshAll() }, 30000)
359
- })
360
- onUnmounted(() => clearInterval(timer))
361
-
362
- return {
363
- jwt, loggedIn, loginError, loginLoading,
364
- health, stats, channels, conversations,
365
- testResult, testLoading, loading, refreshTime,
366
- logout, refreshAll, testChannel,
367
- uptimeStr, fmtNum,
368
- }
369
- },
370
- template: `
371
- <!-- No token in URL and no stored JWT -->
372
- <div v-if="!loggedIn && !loginLoading" class="login-overlay">
373
- <div class="login-box">
374
- <h2>⚡ Chaite Dashboard</h2>
375
- <div class="error">{{ loginError }}</div>
376
- <div class="hint">
377
- No access token found.<br><br>
378
- Open the dashboard with your access token in the URL:<br>
379
- <code style="word-break:break-all;color:var(--accent2);">http://host:port?token=YOUR_TOKEN</code><br><br>
380
- The token is printed in the server console at startup.
381
- </div>
382
- </div>
383
- </div>
384
-
385
- <!-- Loading state (auto-login in progress) -->
386
- <div v-else-if="loginLoading" class="login-overlay">
387
- <div class="login-box">
388
- <h2>⚡ Chaite Dashboard</h2>
389
- <div class="spinner" style="margin:16px auto;"></div>
390
- <div style="color:var(--text2);font-size:13px;">Authenticating...</div>
391
- </div>
392
- </div>
393
-
394
- <div v-else class="app">
395
- <!-- Header -->
396
- <div class="header">
397
- <h1>⚡ <span>Chaite</span> Dashboard</h1>
398
- <div class="meta">
399
- <span class="badge" v-if="refreshTime">Updated {{ refreshTime }}</span>
400
- <span class="badge ok" v-if="health?.status === 'ok'">Healthy</span>
401
- <span class="badge err" v-else-if="health">Unhealthy</span>
402
- <button class="btn" @click="refreshAll" :disabled="loading">
403
- <span v-if="loading" class="spinner"></span>
404
- <span v-else>↻ Refresh</span>
405
- </button>
406
- <button class="btn" @click="logout">Logout</button>
407
- </div>
408
- </div>
409
-
410
- <!-- Stats cards -->
411
- <div class="grid" v-if="health">
412
- <div class="card">
413
- <div class="label">Uptime</div>
414
- <div class="value">{{ uptimeStr(health.uptime) }}</div>
415
- <div class="sub">v{{ health.version }} · Node {{ health.system?.nodeVersion }}</div>
416
- </div>
417
- <div class="card">
418
- <div class="label">Channels</div>
419
- <div class="value">{{ health.channels?.total }}</div>
420
- <div class="sub">{{ health.channels?.enabled }} enabled · {{ health.channels?.disabled }} disabled</div>
421
- </div>
422
- <div class="card">
423
- <div class="label">Models</div>
424
- <div class="value">{{ health.models?.count }}</div>
425
- <div class="sub">{{ health.tools?.count ?? 0 }} tools registered</div>
426
- </div>
427
- <div class="card">
428
- <div class="label">Memory</div>
429
- <div class="value">{{ health.system?.processMemory ?? '-' }} MB</div>
430
- <div class="sub">Heap {{ health.system?.heapUsed ?? '-' }} MB · Free {{ health.system?.freeMemory ?? '-' }} MB</div>
431
- </div>
432
- <div class="card" v-if="stats?.summary">
433
- <div class="label">Total Calls</div>
434
- <div class="value">{{ fmtNum(stats.summary.totalCalls) }}</div>
435
- <div class="sub">{{ fmtNum(stats.summary.totalTokens) }} tokens used</div>
436
- </div>
437
- </div>
438
-
439
- <!-- Channels -->
440
- <div class="section">
441
- <h2><span class="dot"></span> Channels</h2>
442
- <div class="table-wrap">
443
- <table>
444
- <thead>
445
- <tr>
446
- <th>Status</th>
447
- <th>Name</th>
448
- <th>Adapter</th>
449
- <th>Models</th>
450
- <th>Priority</th>
451
- <th>Calls</th>
452
- <th>Actions</th>
453
- </tr>
454
- </thead>
455
- <tbody>
456
- <tr v-for="ch in channels" :key="ch.id">
457
- <td>
458
- <span class="status-dot" :class="ch.status === 'enabled' ? 'on' : 'off'"></span>
459
- {{ ch.status }}
460
- </td>
461
- <td>{{ ch.name || ch.id?.slice(0, 8) }}</td>
462
- <td>{{ ch.adapterType }}</td>
463
- <td>
464
- <span class="model-tag" v-for="m in (ch.models || []).slice(0, 3)" :key="m">{{ m }}</span>
465
- <span v-if="(ch.models || []).length > 3" class="model-tag">+{{ ch.models.length - 3 }}</span>
466
- </td>
467
- <td>{{ ch.priority }}</td>
468
- <td>{{ ch.statistics?.callTimes ?? 0 }}</td>
469
- <td>
470
- <button class="btn" @click="testChannel(ch.id)" :disabled="testLoading"
471
- style="font-size:12px;padding:4px 10px;">
472
- <span v-if="testLoading" class="spinner"></span>
473
- <span v-else>Test</span>
474
- </button>
475
- </td>
476
- </tr>
477
- <tr v-if="!channels.length">
478
- <td colspan="7" style="text-align:center;color:var(--text2);padding:24px;">No channels configured</td>
479
- </tr>
480
- </tbody>
481
- </table>
482
- </div>
483
- <div v-if="testResult" class="test-result" :class="testResult.data?.status === 'ok' ? 'ok' : 'err'">
484
- <template v-if="testResult.data?.status === 'ok'">
485
- ✅ Channel test passed · Model: {{ testResult.data.model }} · Latency: {{ testResult.data.latency }}ms
486
- </template>
487
- <template v-else>
488
- ❌ Test failed: {{ testResult.data?.error || testResult.message }}
489
- </template>
490
- </div>
491
- </div>
492
-
493
- <!-- Models -->
494
- <div class="section" v-if="health?.models?.list?.length">
495
- <h2><span class="dot"></span> Available Models</h2>
496
- <div style="display:flex;flex-wrap:wrap;gap:6px;">
497
- <span class="model-tag" v-for="m in health.models.list" :key="m"
498
- style="font-size:13px;padding:5px 12px;">{{ m }}</span>
499
- </div>
500
- </div>
501
-
502
- <!-- Conversations -->
503
- <div class="section" v-if="conversations.length">
504
- <h2><span class="dot"></span> Active Conversations</h2>
505
- <div class="conv-list">
506
- <div class="conv-card" v-for="c in conversations" :key="c.userId">
507
- <div class="uid">User {{ c.userId }}</div>
508
- <div class="cid" v-if="c.conversationId">Conv: {{ c.conversationId }}</div>
509
- <div class="model" v-if="c.currentModel">Model: {{ c.currentModel }}</div>
510
- </div>
511
- </div>
512
- </div>
513
-
514
- <!-- Per-model stats -->
515
- <div class="section" v-if="stats?.perModel && Object.keys(stats.perModel).length">
516
- <h2><span class="dot"></span> Per-Model Stats</h2>
517
- <div class="table-wrap">
518
- <table>
519
- <thead>
520
- <tr><th>Model</th><th>Calls</th><th>Tokens</th></tr>
521
- </thead>
522
- <tbody>
523
- <tr v-for="(s, model) in stats.perModel" :key="model">
524
- <td>{{ model }}</td>
525
- <td>{{ fmtNum(s.calls) }}</td>
526
- <td>{{ fmtNum(s.tokens) }}</td>
527
- </tr>
528
- </tbody>
529
- </table>
530
- </div>
531
- </div>
532
- </div>
533
- `
534
- }).mount('#app')
535
- </script>
536
- </body>
537
- </html>
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <link rel="icon" href="/favicon.svg" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
+ <title>Chaite Dashboard</title>
9
+ <script type="module" crossorigin src="/assets/index-DzBQLoNi.js"></script>
10
+ <link rel="stylesheet" crossorigin href="/assets/index-Dn5ZzrRm.css">
11
+ </head>
12
+
13
+ <body>
14
+ <div id="appLoading"></div>
15
+ <div id="app"></div>
16
+ </body>
17
+
18
+ </html>
package/package.json CHANGED
@@ -1,71 +1,71 @@
1
- {
2
- "name": "@hina114514/chaite",
3
- "version": "1.9.3",
4
- "description": "core for chatgpt-plugin and karin-plugin-chatgpt",
5
- "keywords": [
6
- "yunzai",
7
- "karin",
8
- "chatgpt"
9
- ],
10
- "license": "ISC",
11
- "author": "ikechan8370",
12
- "sideEffects": true,
13
- "type": "module",
14
- "main": "dist/index.mjs",
15
- "types": "dist/index.d.ts",
16
- "files": [
17
- "dist",
18
- "frontend",
19
- "LICENSE",
20
- "README.md",
21
- "package.json"
22
- ],
23
- "scripts": {
24
- "build": "tsc --noEmit && tsdown",
25
- "dev": "nodemon --exec ts-node src/index.ts",
26
- "lint": "eslint . --ext .ts",
27
- "lint:fix": "eslint . --ext .ts --fix",
28
- "prebuild": "node scripts/generate-version.js",
29
- "prepublishOnly": "npm run build",
30
- "pub": "npm publish --access public",
31
- "test": "jest"
32
- },
33
- "devDependencies": {
34
- "@anthropic-ai/sdk": "^0.39.0",
35
- "@eslint/js": "^9.21.0",
36
- "@google/genai": "^1.8.0",
37
- "@karinjs/node-schedule": "^1.1.2",
38
- "@types/cors": "^2.8.17",
39
- "@types/express": "^5.0.0",
40
- "@types/jest": "^29.5.14",
41
- "@types/node": "^20.17.24",
42
- "@typescript-eslint/eslint-plugin": "^8.25.0",
43
- "@typescript-eslint/parser": "^8.25.0",
44
- "axios": "^1.8.1",
45
- "chokidar": "^4.0.3",
46
- "copyfiles": "^2.4.1",
47
- "cors": "^2.8.5",
48
- "eslint": "^9.21.0",
49
- "eslint-config-prettier": "^10.0.2",
50
- "eslint-plugin-prettier": "^5.2.3",
51
- "express": "^4.21.2",
52
- "jest": "^29.7.0",
53
- "mammoth": "^1.9.0",
54
- "openai": "^5.20.1",
55
- "pdf-parse": "^2.4.5",
56
- "prettier": "^3.5.2",
57
- "reflect-metadata": "^0.2.2",
58
- "ts-jest": "^29.2.6",
59
- "tsdown": "^0.16.0",
60
- "typescript": "^5.7.3",
61
- "typescript-eslint": "^8.25.0"
62
- },
63
- "peerDependencies": {
64
- "pdf-parse": "^2.4.5"
65
- },
66
- "peerDependenciesMeta": {
67
- "pdf-parse": {
68
- "optional": true
69
- }
70
- }
1
+ {
2
+ "name": "@hina114514/chaite",
3
+ "version": "1.9.4",
4
+ "description": "core for chatgpt-plugin and karin-plugin-chatgpt",
5
+ "keywords": [
6
+ "yunzai",
7
+ "karin",
8
+ "chatgpt"
9
+ ],
10
+ "license": "ISC",
11
+ "author": "ikechan8370",
12
+ "sideEffects": true,
13
+ "type": "module",
14
+ "main": "dist/index.mjs",
15
+ "types": "dist/index.d.ts",
16
+ "files": [
17
+ "dist",
18
+ "frontend",
19
+ "LICENSE",
20
+ "README.md",
21
+ "package.json"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsc --noEmit && tsdown",
25
+ "dev": "nodemon --exec ts-node src/index.ts",
26
+ "lint": "eslint . --ext .ts",
27
+ "lint:fix": "eslint . --ext .ts --fix",
28
+ "prebuild": "node scripts/generate-version.js",
29
+ "prepublishOnly": "npm run build",
30
+ "pub": "npm publish --access public",
31
+ "test": "jest"
32
+ },
33
+ "devDependencies": {
34
+ "@anthropic-ai/sdk": "^0.39.0",
35
+ "@eslint/js": "^9.21.0",
36
+ "@google/genai": "^1.8.0",
37
+ "@karinjs/node-schedule": "^1.1.2",
38
+ "@types/cors": "^2.8.17",
39
+ "@types/express": "^5.0.0",
40
+ "@types/jest": "^29.5.14",
41
+ "@types/node": "^20.17.24",
42
+ "@typescript-eslint/eslint-plugin": "^8.25.0",
43
+ "@typescript-eslint/parser": "^8.25.0",
44
+ "axios": "^1.8.1",
45
+ "chokidar": "^4.0.3",
46
+ "copyfiles": "^2.4.1",
47
+ "cors": "^2.8.5",
48
+ "eslint": "^9.21.0",
49
+ "eslint-config-prettier": "^10.0.2",
50
+ "eslint-plugin-prettier": "^5.2.3",
51
+ "express": "^4.21.2",
52
+ "jest": "^29.7.0",
53
+ "mammoth": "^1.9.0",
54
+ "openai": "^5.20.1",
55
+ "pdf-parse": "^2.4.5",
56
+ "prettier": "^3.5.2",
57
+ "reflect-metadata": "^0.2.2",
58
+ "ts-jest": "^29.2.6",
59
+ "tsdown": "^0.16.0",
60
+ "typescript": "^5.7.3",
61
+ "typescript-eslint": "^8.25.0"
62
+ },
63
+ "peerDependencies": {
64
+ "pdf-parse": "^2.4.5"
65
+ },
66
+ "peerDependenciesMeta": {
67
+ "pdf-parse": {
68
+ "optional": true
69
+ }
70
+ }
71
71
  }