sensorium-mcp 2.16.98 → 2.16.100
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/dist/dashboard/spa.html +64 -1164
- package/dist/server/factory.d.ts.map +1 -1
- package/dist/server/factory.js +11 -1
- package/dist/server/factory.js.map +1 -1
- package/dist/tools/defs/session-defs.d.ts.map +1 -1
- package/dist/tools/defs/session-defs.js +8 -0
- package/dist/tools/defs/session-defs.js.map +1 -1
- package/dist/tools/thread-lifecycle.d.ts +6 -0
- package/dist/tools/thread-lifecycle.d.ts.map +1 -1
- package/dist/tools/thread-lifecycle.js +203 -19
- package/dist/tools/thread-lifecycle.js.map +1 -1
- package/dist/watcher-service.d.ts.map +1 -1
- package/dist/watcher-service.js +2 -1
- package/dist/watcher-service.js.map +1 -1
- package/package.json +7 -3
package/dist/dashboard/spa.html
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html lang="en" class="dark">
|
|
3
|
-
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Sensorium Dashboard</title>
|
|
7
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
8
|
+
<script>
|
|
9
9
|
tailwind.config = {
|
|
10
10
|
darkMode: 'class',
|
|
11
11
|
theme: {
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
muted: '#6b7280',
|
|
23
23
|
textPrimary: '#e5e7eb',
|
|
24
24
|
textSecondary: '#9ca3af',
|
|
25
|
+
border: '#374151',
|
|
25
26
|
},
|
|
26
27
|
fontFamily: {
|
|
27
28
|
sans: ['Inter', 'system-ui', '-apple-system', 'sans-serif'],
|
|
@@ -33,1165 +34,64 @@
|
|
|
33
34
|
'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
|
34
35
|
},
|
|
35
36
|
keyframes: {
|
|
36
|
-
fadeIn: { '0%': { opacity: 0 }, '100%': { opacity: 1 } },
|
|
37
|
-
slideUp: { '0%': { opacity: 0, transform: 'translateY(12px)' }, '100%': { opacity: 1, transform: 'translateY(0)' } },
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
};
|
|
42
|
-
</script>
|
|
43
|
-
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
44
|
-
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
45
|
-
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
|
46
|
-
<style>
|
|
47
|
-
body { background: #0f1419; }
|
|
48
|
-
::-webkit-scrollbar { width: 6px; }
|
|
49
|
-
::-webkit-scrollbar-track { background: #1a1f2e; }
|
|
50
|
-
::-webkit-scrollbar-thumb { background: #374151; border-radius: 3px; }
|
|
51
|
-
::-webkit-scrollbar-thumb:hover { background: #4b5563; }
|
|
52
|
-
.glass { background: rgba(26, 31, 46, 0.8); backdrop-filter: blur(12px); border: 1px solid rgba(99, 102, 241, 0.1); }
|
|
53
|
-
.stat-glow { box-shadow: 0 0 20px rgba(99, 102, 241, 0.08); }
|
|
54
|
-
.priority-2 { border-left: 3px solid #ef4444; }
|
|
55
|
-
.priority-1 { border-left: 3px solid #f59e0b; }
|
|
56
|
-
.priority-0 { border-left: 3px solid transparent; }
|
|
57
|
-
.type-badge { font-size: 0.65rem; padding: 2px 6px; border-radius: 9999px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; }
|
|
58
|
-
.type-fact { background: rgba(59, 130, 246, 0.15); color: #60a5fa; }
|
|
59
|
-
.type-preference { background: rgba(168, 85, 247, 0.15); color: #c084fc; }
|
|
60
|
-
.type-pattern { background: rgba(34, 197, 94, 0.15); color: #4ade80; }
|
|
61
|
-
.type-entity { background: rgba(251, 191, 36, 0.15); color: #fbbf24; }
|
|
62
|
-
.type-relationship { background: rgba(244, 114, 182, 0.15); color: #f472b6; }
|
|
63
|
-
.tab-active { border-bottom: 2px solid #6366f1; color: #e5e7eb; }
|
|
64
|
-
.tab-inactive { border-bottom: 2px solid transparent; color: #6b7280; }
|
|
65
|
-
.tab-inactive:hover { color: #9ca3af; }
|
|
66
|
-
</style>
|
|
67
|
-
</head>
|
|
68
|
-
<body class="font-sans text-textPrimary min-h-screen">
|
|
69
|
-
<!-- Auth overlay -->
|
|
70
|
-
<div id="auth-overlay" class="fixed inset-0 z-50 flex items-center justify-center bg-surface/95 backdrop-blur-sm">
|
|
71
|
-
<div class="glass rounded-2xl p-8 max-w-md w-full mx-4 animate-slide-up">
|
|
72
|
-
<div class="flex items-center gap-3 mb-6">
|
|
73
|
-
<div class="w-10 h-10 rounded-xl bg-accent/20 flex items-center justify-center">
|
|
74
|
-
<svg class="w-5 h-5 text-accent" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
75
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/>
|
|
76
|
-
</svg>
|
|
77
|
-
</div>
|
|
78
|
-
<div>
|
|
79
|
-
<h2 class="text-lg font-semibold">Sensorium MCP</h2>
|
|
80
|
-
<p class="text-sm text-textSecondary">Enter your API token</p>
|
|
81
|
-
</div>
|
|
82
|
-
</div>
|
|
83
|
-
<input id="token-input" type="password" placeholder="MCP_HTTP_SECRET"
|
|
84
|
-
class="w-full px-4 py-3 rounded-xl bg-surface border border-gray-700 text-textPrimary placeholder-muted focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent transition font-mono text-sm" />
|
|
85
|
-
<button onclick="authenticate()" class="w-full mt-4 px-4 py-3 rounded-xl bg-accent hover:bg-accentLight text-white font-medium transition">
|
|
86
|
-
Connect
|
|
87
|
-
</button>
|
|
88
|
-
<p id="auth-error" class="mt-3 text-sm text-danger hidden"></p>
|
|
89
|
-
</div>
|
|
90
|
-
</div>
|
|
91
|
-
|
|
92
|
-
<!-- Main dashboard -->
|
|
93
|
-
<div id="dashboard" class="hidden">
|
|
94
|
-
<!-- Header -->
|
|
95
|
-
<header class="glass sticky top-0 z-40 border-b border-gray-800/50">
|
|
96
|
-
<div class="max-w-7xl mx-auto px-4 sm:px-6 py-4 flex items-center justify-between">
|
|
97
|
-
<div class="flex items-center gap-3">
|
|
98
|
-
<div class="w-8 h-8 rounded-lg bg-gradient-to-br from-accent to-purple-500 flex items-center justify-center">
|
|
99
|
-
<span class="text-white text-sm font-bold">S</span>
|
|
100
|
-
</div>
|
|
101
|
-
<div>
|
|
102
|
-
<h1 class="text-lg font-semibold tracking-tight">Sensorium MCP</h1>
|
|
103
|
-
<p class="text-xs text-textSecondary">Agent Dashboard</p>
|
|
104
|
-
</div>
|
|
105
|
-
</div>
|
|
106
|
-
<div class="flex items-center gap-4">
|
|
107
|
-
<div id="connection-status" class="flex items-center gap-2 text-sm">
|
|
108
|
-
<span class="w-2 h-2 rounded-full bg-success animate-pulse-slow"></span>
|
|
109
|
-
<span class="text-textSecondary">Connected</span>
|
|
110
|
-
</div>
|
|
111
|
-
<div id="uptime-display" class="text-sm text-textSecondary font-mono"></div>
|
|
112
|
-
<button onclick="logout()" class="text-sm text-muted hover:text-textSecondary transition">Disconnect</button>
|
|
113
|
-
</div>
|
|
114
|
-
</div>
|
|
115
|
-
</header>
|
|
116
|
-
|
|
117
|
-
<!-- Stats bar -->
|
|
118
|
-
<div class="max-w-7xl mx-auto px-4 sm:px-6 py-6">
|
|
119
|
-
<div id="stats-grid" class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-3">
|
|
120
|
-
<!-- Filled by JS -->
|
|
121
|
-
</div>
|
|
122
|
-
</div>
|
|
123
|
-
|
|
124
|
-
<!-- Tabs -->
|
|
125
|
-
<div class="max-w-7xl mx-auto px-4 sm:px-6">
|
|
126
|
-
<nav class="flex gap-6 border-b border-gray-800/50 mb-6">
|
|
127
|
-
<button onclick="switchTab('sessions')" id="tab-sessions" class="pb-3 text-sm font-medium tab-active transition">Sessions</button>
|
|
128
|
-
<button onclick="switchTab('notes')" id="tab-notes" class="pb-3 text-sm font-medium tab-inactive transition">Memory Notes</button>
|
|
129
|
-
<button onclick="switchTab('episodes')" id="tab-episodes" class="pb-3 text-sm font-medium tab-inactive transition">Episodes</button>
|
|
130
|
-
<button onclick="switchTab('topics')" id="tab-topics" class="pb-3 text-sm font-medium tab-inactive transition">Topics</button>
|
|
131
|
-
<button onclick="switchTab('templates')" id="tab-templates" class="pb-3 text-sm font-medium tab-inactive transition">Templates</button>
|
|
132
|
-
<button onclick="switchTab('skills')" id="tab-skills" class="pb-3 text-sm font-medium tab-inactive transition">Skills</button>
|
|
133
|
-
</nav>
|
|
134
|
-
</div>
|
|
135
|
-
|
|
136
|
-
<!-- Tab content -->
|
|
137
|
-
<div class="max-w-7xl mx-auto px-4 sm:px-6 pb-12">
|
|
138
|
-
<!-- Sessions -->
|
|
139
|
-
<div id="panel-sessions" class="animate-fade-in">
|
|
140
|
-
<div id="sessions-list" class="space-y-3"></div>
|
|
141
|
-
<p id="sessions-empty" class="hidden text-center text-textSecondary py-12">No sessions</p>
|
|
142
|
-
</div>
|
|
143
|
-
|
|
144
|
-
<!-- Notes -->
|
|
145
|
-
<div id="panel-notes" class="hidden animate-fade-in">
|
|
146
|
-
<div class="flex flex-wrap items-center gap-3 mb-4">
|
|
147
|
-
<input id="notes-search" type="text" placeholder="Search notes..."
|
|
148
|
-
class="flex-1 min-w-[200px] px-4 py-2 rounded-xl bg-card border border-gray-700 text-sm text-textPrimary placeholder-muted focus:outline-none focus:border-accent transition" />
|
|
149
|
-
<select id="notes-type" onchange="loadNotes()"
|
|
150
|
-
class="px-3 py-2 rounded-xl bg-card border border-gray-700 text-sm text-textPrimary focus:outline-none">
|
|
151
|
-
<option value="">All types</option>
|
|
152
|
-
<option value="fact">Facts</option>
|
|
153
|
-
<option value="preference">Preferences</option>
|
|
154
|
-
<option value="pattern">Patterns</option>
|
|
155
|
-
<option value="entity">Entities</option>
|
|
156
|
-
<option value="relationship">Relationships</option>
|
|
157
|
-
</select>
|
|
158
|
-
<select id="notes-sort" onchange="loadNotes()"
|
|
159
|
-
class="px-3 py-2 rounded-xl bg-card border border-gray-700 text-sm text-textPrimary focus:outline-none">
|
|
160
|
-
<option value="created_at">Newest</option>
|
|
161
|
-
<option value="confidence">Confidence</option>
|
|
162
|
-
<option value="access_count">Most accessed</option>
|
|
163
|
-
</select>
|
|
164
|
-
</div>
|
|
165
|
-
<div id="notes-list" class="space-y-2"></div>
|
|
166
|
-
</div>
|
|
167
|
-
|
|
168
|
-
<!-- Episodes -->
|
|
169
|
-
<div id="panel-episodes" class="hidden animate-fade-in">
|
|
170
|
-
<div class="flex items-center gap-3 mb-4">
|
|
171
|
-
<input id="episodes-thread" type="number" placeholder="Thread ID (optional)"
|
|
172
|
-
class="w-48 px-4 py-2 rounded-xl bg-card border border-gray-700 text-sm text-textPrimary placeholder-muted focus:outline-none focus:border-accent transition" />
|
|
173
|
-
<button onclick="loadEpisodes()" class="px-4 py-2 rounded-xl bg-accent hover:bg-accentLight text-white text-sm font-medium transition">Load</button>
|
|
174
|
-
</div>
|
|
175
|
-
<div id="episodes-list" class="space-y-2"></div>
|
|
176
|
-
</div>
|
|
177
|
-
|
|
178
|
-
<!-- Topics -->
|
|
179
|
-
<div id="panel-topics" class="hidden animate-fade-in">
|
|
180
|
-
<div id="topics-grid" class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-3"></div>
|
|
181
|
-
</div>
|
|
182
|
-
|
|
183
|
-
<!-- Templates -->
|
|
184
|
-
<div id="panel-templates" class="hidden animate-fade-in">
|
|
185
|
-
<!-- Settings -->
|
|
186
|
-
<div class="glass rounded-xl p-4 mb-4">
|
|
187
|
-
<div class="flex flex-wrap items-center gap-4 mb-4">
|
|
188
|
-
<label for="agent-type-select" class="text-sm font-medium text-textSecondary">Agent Type</label>
|
|
189
|
-
<select id="agent-type-select" onchange="changeAgentType()"
|
|
190
|
-
class="px-3 py-2 rounded-xl bg-card border border-gray-700 text-sm text-textPrimary focus:outline-none focus:border-accent transition">
|
|
191
|
-
<option value="copilot">Copilot</option>
|
|
192
|
-
<option value="claude">Claude</option>
|
|
193
|
-
<option value="cursor">Cursor</option>
|
|
194
|
-
</select>
|
|
195
|
-
<span id="agent-type-status" class="text-sm"></span>
|
|
196
|
-
<span class="text-xs text-muted">Changes which default reminders template is used</span>
|
|
197
|
-
</div>
|
|
198
|
-
<div class="flex flex-wrap items-center gap-3">
|
|
199
|
-
<label for="claude-mcp-config-input" class="text-sm font-medium text-textSecondary">Claude MCP Config Path</label>
|
|
200
|
-
<input id="claude-mcp-config-input" type="text"
|
|
201
|
-
placeholder="~/.claude/settings.json"
|
|
202
|
-
class="flex-1 min-w-[260px] px-3 py-2 rounded-xl bg-card border border-gray-700 text-sm text-textPrimary placeholder-muted font-mono focus:outline-none focus:border-accent transition" />
|
|
203
|
-
<button onclick="saveClaudeMcpConfig()" class="px-4 py-2 rounded-xl bg-accent hover:bg-accentLight text-white text-sm font-medium transition">Save</button>
|
|
204
|
-
<span id="claude-mcp-config-status" class="text-sm"></span>
|
|
205
|
-
</div>
|
|
206
|
-
</div>
|
|
207
|
-
<div class="glass rounded-xl p-6">
|
|
208
|
-
<div class="flex flex-wrap items-center justify-between gap-4 mb-4">
|
|
209
|
-
<div>
|
|
210
|
-
<h3 class="text-lg font-semibold">Reminders Template</h3>
|
|
211
|
-
<p class="text-sm text-textSecondary mt-1">Edit the system prompt template sent with every reminder</p>
|
|
212
|
-
</div>
|
|
213
|
-
<div class="flex items-center gap-2">
|
|
214
|
-
<span id="tpl-status" class="text-sm"></span>
|
|
215
|
-
<button onclick="resetTemplate()" class="px-4 py-2 rounded-xl bg-card hover:bg-cardHover border border-gray-700 text-sm text-textSecondary hover:text-textPrimary transition">Reset to Default</button>
|
|
216
|
-
<button onclick="saveTemplate()" class="px-4 py-2 rounded-xl bg-accent hover:bg-accentLight text-white text-sm font-medium transition">Save</button>
|
|
217
|
-
</div>
|
|
218
|
-
</div>
|
|
219
|
-
<div id="tpl-default-badge" class="hidden mb-3">
|
|
220
|
-
<span class="type-badge" style="background:rgba(245,158,11,0.15);color:#fbbf24">USING DEFAULT — edit and save to customize</span>
|
|
221
|
-
</div>
|
|
222
|
-
<textarea id="tpl-editor" rows="20" spellcheck="false"
|
|
223
|
-
class="w-full px-4 py-3 rounded-xl bg-surface border border-gray-700 text-textPrimary font-mono text-sm leading-relaxed focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent transition resize-y"
|
|
224
|
-
placeholder="Loading..."></textarea>
|
|
225
|
-
<div class="mt-4">
|
|
226
|
-
<div id="tpl-preview-header" class="flex items-center gap-2 mb-2 cursor-pointer select-none" onclick="toggleTplPreview()">
|
|
227
|
-
<svg id="tpl-preview-arrow" class="w-4 h-4 text-textSecondary transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
228
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
|
|
229
|
-
</svg>
|
|
230
|
-
<span class="text-sm font-medium text-textSecondary">Preview with highlighted variables</span>
|
|
231
|
-
</div>
|
|
232
|
-
<div id="tpl-preview" class="hidden glass rounded-xl p-4 font-mono text-sm leading-relaxed whitespace-pre-wrap break-words"></div>
|
|
233
|
-
</div>
|
|
234
|
-
<details class="mt-4">
|
|
235
|
-
<summary class="text-sm font-medium text-textSecondary cursor-pointer hover:text-textPrimary transition">Available Variables</summary>
|
|
236
|
-
<div class="mt-2 glass rounded-xl p-4 grid grid-cols-1 sm:grid-cols-2 gap-2 text-sm">
|
|
237
|
-
<div><code class="text-accentLight">{{OPERATOR_MESSAGE}}</code> <span class="text-textSecondary">— latest operator message</span></div>
|
|
238
|
-
<div><code class="text-accentLight">{{THREAD_ID}}</code> <span class="text-textSecondary">— Telegram thread ID</span></div>
|
|
239
|
-
<div><code class="text-accentLight">{{TIME}}</code> <span class="text-textSecondary">— formatted timestamp</span></div>
|
|
240
|
-
<div><code class="text-accentLight">{{UPTIME}}</code> <span class="text-textSecondary">— session uptime</span></div>
|
|
241
|
-
<div><code class="text-accentLight">{{VERSION}}</code> <span class="text-textSecondary">— package version</span></div>
|
|
242
|
-
<div><code class="text-accentLight">{{MODE}}</code> <span class="text-textSecondary">— "autonomous" or "standard"</span></div>
|
|
243
|
-
</div>
|
|
244
|
-
</details>
|
|
245
|
-
</div>
|
|
246
|
-
|
|
247
|
-
<!-- Drive Framing Template -->
|
|
248
|
-
<div class="glass rounded-xl p-6 mt-6">
|
|
249
|
-
<div class="flex flex-wrap items-center justify-between gap-4 mb-4">
|
|
250
|
-
<div>
|
|
251
|
-
<h3 class="text-lg font-semibold">Drive Framing Template</h3>
|
|
252
|
-
<p class="text-sm text-textSecondary mt-1">Customize the autonomous drive prompt sent when the operator is away</p>
|
|
253
|
-
</div>
|
|
254
|
-
<div class="flex items-center gap-2">
|
|
255
|
-
<span id="drive-tpl-status" class="text-sm"></span>
|
|
256
|
-
<button onclick="resetDriveTemplate()" class="px-4 py-2 rounded-xl bg-card hover:bg-cardHover border border-gray-700 text-sm text-textSecondary hover:text-textPrimary transition">Reset to Default</button>
|
|
257
|
-
<button onclick="saveDriveTemplate()" class="px-4 py-2 rounded-xl bg-accent hover:bg-accentLight text-white text-sm font-medium transition">Save</button>
|
|
258
|
-
</div>
|
|
259
|
-
</div>
|
|
260
|
-
<div class="mb-4 flex flex-wrap items-center gap-3">
|
|
261
|
-
<label class="text-sm text-textSecondary">Drive Activation Period:</label>
|
|
262
|
-
<div class="flex items-center gap-2">
|
|
263
|
-
<input id="drive-activation-hours" type="number" min="0.5" step="0.5" class="w-20 px-3 py-1.5 rounded-lg bg-surface border border-gray-700 text-textPrimary font-mono text-sm focus:outline-none focus:border-accent transition" />
|
|
264
|
-
<span class="text-sm text-textSecondary">hours</span>
|
|
265
|
-
</div>
|
|
266
|
-
<span class="text-xs text-muted">(informational — requires server restart via DMN_ACTIVATION_HOURS env var)</span>
|
|
267
|
-
</div>
|
|
268
|
-
<div id="drive-tpl-default-badge" class="hidden mb-3">
|
|
269
|
-
<span class="type-badge" style="background:rgba(245,158,11,0.15);color:#fbbf24">(Default — edit to override)</span>
|
|
270
|
-
</div>
|
|
271
|
-
<div class="flex flex-wrap gap-2 mb-3">
|
|
272
|
-
<span class="text-sm text-textSecondary self-center">Presets:</span>
|
|
273
|
-
<button onclick="loadPreset('operator-instruction')" class="px-3 py-1.5 rounded-lg bg-card hover:bg-cardHover border border-gray-700 text-xs text-textSecondary hover:text-textPrimary transition">📋 Direct Instruction</button>
|
|
274
|
-
<button onclick="loadPreset('operator-notes')" class="px-3 py-1.5 rounded-lg bg-card hover:bg-cardHover border border-gray-700 text-xs text-textSecondary hover:text-textPrimary transition">📝 Operator Notes</button>
|
|
275
|
-
<button onclick="loadPreset('dispatcher')" class="px-3 py-1.5 rounded-lg bg-card hover:bg-cardHover border border-gray-700 text-xs text-textSecondary hover:text-textPrimary transition">⚡ Dispatcher</button>
|
|
276
|
-
<button onclick="loadPreset('first-person')" class="px-3 py-1.5 rounded-lg bg-card hover:bg-cardHover border border-gray-700 text-xs text-textSecondary hover:text-textPrimary transition">💭 Open Autonomy</button>
|
|
277
|
-
</div>
|
|
278
|
-
<textarea id="drive-tpl-editor" rows="15" spellcheck="false"
|
|
279
|
-
class="w-full px-4 py-3 rounded-xl bg-surface border border-gray-700 text-textPrimary font-mono text-sm leading-relaxed focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent transition resize-y"
|
|
280
|
-
placeholder="Load a preset or type a custom drive template..."></textarea>
|
|
281
|
-
<div class="mt-4">
|
|
282
|
-
<div id="drive-tpl-preview-header" class="flex items-center gap-2 mb-2 cursor-pointer select-none" onclick="toggleDriveTplPreview()">
|
|
283
|
-
<svg id="drive-tpl-preview-arrow" class="w-4 h-4 text-textSecondary transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
284
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
|
|
285
|
-
</svg>
|
|
286
|
-
<span class="text-sm font-medium text-textSecondary">Preview with sample values</span>
|
|
287
|
-
</div>
|
|
288
|
-
<div id="drive-tpl-preview" class="hidden glass rounded-xl p-4 font-mono text-sm leading-relaxed whitespace-pre-wrap break-words"></div>
|
|
289
|
-
</div>
|
|
290
|
-
<details class="mt-4">
|
|
291
|
-
<summary class="text-sm font-medium text-textSecondary cursor-pointer hover:text-textPrimary transition">Available Variables</summary>
|
|
292
|
-
<div class="mt-2 glass rounded-xl p-4 grid grid-cols-1 sm:grid-cols-2 gap-2 text-sm">
|
|
293
|
-
<div><code class="text-accentLight">{{IDLE_HOURS}}</code> <span class="text-textSecondary">— hours since last operator interaction</span></div>
|
|
294
|
-
<div><code class="text-accentLight">{{TIME}}</code> <span class="text-textSecondary">— ISO timestamp</span></div>
|
|
295
|
-
<div><code class="text-accentLight">{{PROBABILITY}}</code> <span class="text-textSecondary">— drive activation probability (0.2–1.0)</span></div>
|
|
296
|
-
</div>
|
|
297
|
-
</details>
|
|
298
|
-
</div>
|
|
299
|
-
</div>
|
|
300
|
-
|
|
301
|
-
<!-- Skills -->
|
|
302
|
-
<div id="panel-skills" class="hidden animate-fade-in">
|
|
303
|
-
<div class="glass rounded-xl p-6 mb-6">
|
|
304
|
-
<div class="flex flex-wrap items-center justify-between gap-4 mb-4">
|
|
305
|
-
<div>
|
|
306
|
-
<h3 class="text-lg font-semibold">Skill Library</h3>
|
|
307
|
-
<p class="text-sm text-textSecondary mt-1">Manage intent-routing skills — user overrides, defaults, and project skills</p>
|
|
308
|
-
</div>
|
|
309
|
-
<button onclick="showNewSkillForm()" class="px-4 py-2 rounded-xl bg-accent hover:bg-accentLight text-white text-sm font-medium transition">+ New Skill</button>
|
|
310
|
-
</div>
|
|
311
|
-
|
|
312
|
-
<!-- New skill form (hidden by default) -->
|
|
313
|
-
<div id="skill-new-form" class="hidden glass rounded-xl p-4 mb-4 border border-accent/30">
|
|
314
|
-
<h4 class="text-sm font-semibold mb-3">Create New Skill</h4>
|
|
315
|
-
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3 mb-3">
|
|
316
|
-
<div>
|
|
317
|
-
<label class="text-xs text-textSecondary block mb-1">Name</label>
|
|
318
|
-
<input id="skill-new-name" type="text" placeholder="my-skill"
|
|
319
|
-
class="w-full px-3 py-2 rounded-lg bg-surface border border-gray-700 text-sm text-textPrimary font-mono focus:outline-none focus:border-accent transition" />
|
|
320
|
-
</div>
|
|
321
|
-
<div>
|
|
322
|
-
<label class="text-xs text-textSecondary block mb-1">Triggers (comma-separated)</label>
|
|
323
|
-
<input id="skill-new-triggers" type="text" placeholder="trigger1, trigger2"
|
|
324
|
-
class="w-full px-3 py-2 rounded-lg bg-surface border border-gray-700 text-sm text-textPrimary focus:outline-none focus:border-accent transition" />
|
|
325
|
-
</div>
|
|
326
|
-
</div>
|
|
327
|
-
<div class="flex items-center gap-4 mb-3">
|
|
328
|
-
<label class="flex items-center gap-2 text-sm text-textSecondary cursor-pointer">
|
|
329
|
-
<input id="skill-new-replaces" type="checkbox" class="rounded" />
|
|
330
|
-
<span>Replaces orchestrator</span>
|
|
331
|
-
</label>
|
|
332
|
-
</div>
|
|
333
|
-
<div class="flex items-center gap-2">
|
|
334
|
-
<button onclick="createNewSkill()" class="px-4 py-2 rounded-xl bg-accent hover:bg-accentLight text-white text-sm font-medium transition">Create</button>
|
|
335
|
-
<button onclick="hideNewSkillForm()" class="px-4 py-2 rounded-xl bg-card hover:bg-cardHover border border-gray-700 text-sm text-textSecondary hover:text-textPrimary transition">Cancel</button>
|
|
336
|
-
<span id="skill-new-status" class="text-sm"></span>
|
|
337
|
-
</div>
|
|
338
|
-
</div>
|
|
339
|
-
|
|
340
|
-
<!-- Skills list -->
|
|
341
|
-
<div id="skills-list" class="space-y-2"></div>
|
|
342
|
-
<p id="skills-empty" class="hidden text-center text-textSecondary py-12">No skills loaded</p>
|
|
343
|
-
</div>
|
|
344
|
-
|
|
345
|
-
<!-- Skill editor (hidden until a skill is selected) -->
|
|
346
|
-
<div id="skill-editor-panel" class="hidden glass rounded-xl p-6">
|
|
347
|
-
<div class="flex flex-wrap items-center justify-between gap-4 mb-4">
|
|
348
|
-
<div>
|
|
349
|
-
<h3 class="text-lg font-semibold" id="skill-editor-title">Edit Skill</h3>
|
|
350
|
-
<p class="text-sm text-textSecondary mt-1" id="skill-editor-source"></p>
|
|
351
|
-
</div>
|
|
352
|
-
<div class="flex items-center gap-2">
|
|
353
|
-
<span id="skill-editor-status" class="text-sm"></span>
|
|
354
|
-
<button onclick="closeSkillEditor()" class="px-4 py-2 rounded-xl bg-card hover:bg-cardHover border border-gray-700 text-sm text-textSecondary hover:text-textPrimary transition">Close</button>
|
|
355
|
-
<button onclick="saveSkill()" class="px-4 py-2 rounded-xl bg-accent hover:bg-accentLight text-white text-sm font-medium transition">Save</button>
|
|
356
|
-
</div>
|
|
357
|
-
</div>
|
|
358
|
-
<div class="grid grid-cols-1 sm:grid-cols-3 gap-3 mb-4">
|
|
359
|
-
<div>
|
|
360
|
-
<label class="text-xs text-textSecondary block mb-1">Name</label>
|
|
361
|
-
<input id="skill-edit-name" type="text" readonly
|
|
362
|
-
class="w-full px-3 py-2 rounded-lg bg-surface border border-gray-700 text-sm text-textPrimary font-mono opacity-60 cursor-not-allowed" />
|
|
363
|
-
</div>
|
|
364
|
-
<div>
|
|
365
|
-
<label class="text-xs text-textSecondary block mb-1">Triggers (comma-separated)</label>
|
|
366
|
-
<input id="skill-edit-triggers" type="text"
|
|
367
|
-
class="w-full px-3 py-2 rounded-lg bg-surface border border-gray-700 text-sm text-textPrimary focus:outline-none focus:border-accent transition" />
|
|
368
|
-
</div>
|
|
369
|
-
<div class="flex items-end">
|
|
370
|
-
<label class="flex items-center gap-2 text-sm text-textSecondary cursor-pointer pb-2">
|
|
371
|
-
<input id="skill-edit-replaces" type="checkbox" class="rounded" />
|
|
372
|
-
<span>Replaces orchestrator</span>
|
|
373
|
-
</label>
|
|
374
|
-
</div>
|
|
375
|
-
</div>
|
|
376
|
-
<textarea id="skill-edit-content" rows="20" spellcheck="false"
|
|
377
|
-
class="w-full px-4 py-3 rounded-xl bg-surface border border-gray-700 text-textPrimary font-mono text-sm leading-relaxed focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent transition resize-y"
|
|
378
|
-
placeholder="Skill body (markdown)..."></textarea>
|
|
379
|
-
</div>
|
|
380
|
-
</div>
|
|
381
|
-
|
|
382
|
-
</div>
|
|
383
|
-
</div>
|
|
384
|
-
|
|
385
|
-
<script>
|
|
386
|
-
// ─── State ─────────────────────────────────────────────────────────
|
|
387
|
-
let token = localStorage.getItem('sensorium_token') || '';
|
|
388
|
-
let currentTab = 'sessions';
|
|
389
|
-
let refreshTimer = null;
|
|
390
|
-
|
|
391
|
-
// ─── Auth ──────────────────────────────────────────────────────────
|
|
392
|
-
async function authenticate() {
|
|
393
|
-
var authErr = document.getElementById('auth-error');
|
|
394
|
-
authErr.classList.add('hidden');
|
|
395
|
-
const input = document.getElementById('token-input');
|
|
396
|
-
token = input.value.trim();
|
|
397
|
-
if (!token) { token = 'no-auth'; } // allow no-auth mode
|
|
398
|
-
try {
|
|
399
|
-
const res = await api('/api/status');
|
|
400
|
-
if (res) {
|
|
401
|
-
localStorage.setItem('sensorium_token', token);
|
|
402
|
-
document.getElementById('auth-overlay').classList.add('hidden');
|
|
403
|
-
document.getElementById('dashboard').classList.remove('hidden');
|
|
404
|
-
startRefresh();
|
|
405
|
-
}
|
|
406
|
-
} catch (e) {
|
|
407
|
-
var msg = 'Connection failed';
|
|
408
|
-
if (e && e.message) {
|
|
409
|
-
if (e.message === 'Unauthorized' || e.status === 401) msg = 'Invalid token';
|
|
410
|
-
else if (/5\d\d|Internal/.test(e.message)) msg = 'Server error — try again in a moment';
|
|
411
|
-
else msg = e.message;
|
|
412
|
-
}
|
|
413
|
-
authErr.textContent = msg;
|
|
414
|
-
authErr.classList.remove('hidden');
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
function logout() {
|
|
419
|
-
localStorage.removeItem('sensorium_token');
|
|
420
|
-
token = '';
|
|
421
|
-
if (refreshTimer) clearInterval(refreshTimer);
|
|
422
|
-
document.getElementById('dashboard').classList.add('hidden');
|
|
423
|
-
document.getElementById('auth-overlay').classList.remove('hidden');
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
// Auto-connect if token saved
|
|
427
|
-
if (token) {
|
|
428
|
-
var savedToken = token;
|
|
429
|
-
api('/api/status').then(data => {
|
|
430
|
-
if (data) {
|
|
431
|
-
document.getElementById('auth-overlay').classList.add('hidden');
|
|
432
|
-
document.getElementById('dashboard').classList.remove('hidden');
|
|
433
|
-
startRefresh();
|
|
434
|
-
}
|
|
435
|
-
}).catch(() => {
|
|
436
|
-
// Only clear if token hasn't been changed by a manual authenticate()
|
|
437
|
-
if (token === savedToken) {
|
|
438
|
-
localStorage.removeItem('sensorium_token');
|
|
439
|
-
token = '';
|
|
440
|
-
}
|
|
441
|
-
});
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
// Enter key on token input
|
|
445
|
-
document.getElementById('token-input').addEventListener('keydown', e => {
|
|
446
|
-
if (e.key === 'Enter') authenticate();
|
|
447
|
-
});
|
|
448
|
-
|
|
449
|
-
// ─── API ───────────────────────────────────────────────────────────
|
|
450
|
-
async function api(path) {
|
|
451
|
-
const res = await fetch(path, {
|
|
452
|
-
headers: { 'Authorization': 'Bearer ' + token },
|
|
453
|
-
});
|
|
454
|
-
if (!res.ok) { var err = new Error(res.statusText); err.status = res.status; throw err; }
|
|
455
|
-
return res.json();
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
// ─── Rendering ─────────────────────────────────────────────────────
|
|
459
|
-
function formatUptime(seconds) {
|
|
460
|
-
const d = Math.floor(seconds / 86400);
|
|
461
|
-
const h = Math.floor((seconds % 86400) / 3600);
|
|
462
|
-
const m = Math.floor((seconds % 3600) / 60);
|
|
463
|
-
if (d > 0) return d + 'd ' + h + 'h';
|
|
464
|
-
if (h > 0) return h + 'h ' + m + 'm';
|
|
465
|
-
return m + 'm';
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
function timeAgo(iso) {
|
|
469
|
-
if (!iso) return 'never';
|
|
470
|
-
const diff = Date.now() - new Date(iso).getTime();
|
|
471
|
-
const mins = Math.floor(diff / 60000);
|
|
472
|
-
if (mins < 1) return 'just now';
|
|
473
|
-
if (mins < 60) return mins + 'm ago';
|
|
474
|
-
const hours = Math.floor(mins / 60);
|
|
475
|
-
if (hours < 24) return hours + 'h ago';
|
|
476
|
-
return Math.floor(hours / 24) + 'd ago';
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
function statCard(label, value, icon, color = 'accent') {
|
|
480
|
-
return '<div class="glass rounded-xl p-4 stat-glow animate-slide-up">' +
|
|
481
|
-
'<div class="flex items-center gap-2 mb-2">' +
|
|
482
|
-
'<span class="text-' + color + '">' + icon + '</span>' +
|
|
483
|
-
'<span class="text-xs text-textSecondary font-medium uppercase tracking-wider">' + label + '</span>' +
|
|
484
|
-
'</div>' +
|
|
485
|
-
'<div class="text-2xl font-bold font-mono">' + value + '</div>' +
|
|
486
|
-
'</div>';
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
function updateEl(el, html) { if (el && el.innerHTML !== html) el.innerHTML = html; }
|
|
490
|
-
|
|
491
|
-
function renderStats(data) {
|
|
492
|
-
const m = data.memory || {};
|
|
493
|
-
const grid = document.getElementById('stats-grid');
|
|
494
|
-
const statsHtml =
|
|
495
|
-
statCard('Sessions', data.activeSessions,
|
|
496
|
-
'<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z"/></svg>',
|
|
497
|
-
'success') +
|
|
498
|
-
statCard('Notes', m.totalSemanticNotes,
|
|
499
|
-
'<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/></svg>',
|
|
500
|
-
'accentLight') +
|
|
501
|
-
statCard('Episodes', m.totalEpisodes,
|
|
502
|
-
'<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/></svg>',
|
|
503
|
-
'warn') +
|
|
504
|
-
statCard('Unconsolidated', m.unconsolidatedEpisodes,
|
|
505
|
-
'<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>',
|
|
506
|
-
m.unconsolidatedEpisodes > 10 ? 'danger' : 'success') +
|
|
507
|
-
statCard('Procedures', m.totalProcedures,
|
|
508
|
-
'<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.066 2.573c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.573 1.066c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.066-2.573c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/></svg>') +
|
|
509
|
-
statCard('Uptime', formatUptime(data.uptime),
|
|
510
|
-
'<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14M12 5l7 7-7 7"/></svg>',
|
|
511
|
-
'success');
|
|
512
|
-
updateEl(grid, statsHtml);
|
|
513
|
-
|
|
514
|
-
document.getElementById('uptime-display').textContent = formatUptime(data.uptime);
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
function renderSessions(sessions) {
|
|
518
|
-
const list = document.getElementById('sessions-list');
|
|
519
|
-
const empty = document.getElementById('sessions-empty');
|
|
520
|
-
if (!Array.isArray(sessions) || !sessions.length) {
|
|
521
|
-
if (list.innerHTML !== '') list.innerHTML = '';
|
|
522
|
-
empty.classList.remove('hidden');
|
|
523
|
-
return;
|
|
524
|
-
}
|
|
525
|
-
empty.classList.add('hidden');
|
|
526
|
-
// Sort: active first, then disconnected by most recent activity
|
|
527
|
-
sessions.sort(function(a, b) {
|
|
528
|
-
if (a.status === 'active' && b.status !== 'active') return -1;
|
|
529
|
-
if (a.status !== 'active' && b.status === 'active') return 1;
|
|
530
|
-
return b.lastActivity - a.lastActivity;
|
|
531
|
-
});
|
|
532
|
-
const html = sessions.map(s => {
|
|
533
|
-
const isDisconnected = s.status === 'disconnected';
|
|
534
|
-
const idle = Math.floor((Date.now() - s.lastActivity) / 60000);
|
|
535
|
-
var statusColor, statusLabel;
|
|
536
|
-
if (isDisconnected) {
|
|
537
|
-
statusColor = 'muted';
|
|
538
|
-
statusLabel = 'Disconnected' + (idle > 0 ? ' — ' + idle + 'm ago' : '');
|
|
539
|
-
} else {
|
|
540
|
-
statusColor = idle < 5 ? 'success' : idle < 30 ? 'warn' : 'danger';
|
|
541
|
-
statusLabel = idle < 5 ? 'Active' : idle < 30 ? 'Idle ' + idle + 'm' : 'Dormant ' + idle + 'm';
|
|
542
|
-
}
|
|
543
|
-
// Wait-for-instructions heartbeat indicator
|
|
544
|
-
var pollLabel = '';
|
|
545
|
-
if (s.lastWaitCallAt) {
|
|
546
|
-
var waitAgo = Math.floor((Date.now() - s.lastWaitCallAt) / 60000);
|
|
547
|
-
if (waitAgo < 5) {
|
|
548
|
-
pollLabel = '<span class="text-xs text-success ml-2">Polling — ' + (waitAgo === 0 ? 'just now' : waitAgo + 'm ago') + '</span>';
|
|
549
|
-
} else {
|
|
550
|
-
pollLabel = '<span class="text-xs text-warn ml-2">Last poll — ' + waitAgo + 'm ago</span>';
|
|
37
|
+
fadeIn: { '0%': { opacity: '0' }, '100%': { opacity: '1' } },
|
|
38
|
+
slideUp: { '0%': { opacity: '0', transform: 'translateY(12px)' }, '100%': { opacity: '1', transform: 'translateY(0)' } },
|
|
551
39
|
}
|
|
552
40
|
}
|
|
553
|
-
return '<div class="glass rounded-xl p-4 animate-slide-up' + (isDisconnected ? ' opacity-60' : '') + '">' +
|
|
554
|
-
'<div class="flex items-center justify-between">' +
|
|
555
|
-
'<div class="flex items-center gap-3">' +
|
|
556
|
-
'<span class="w-2.5 h-2.5 rounded-full bg-' + statusColor + '"></span>' +
|
|
557
|
-
'<div>' +
|
|
558
|
-
'<div class="font-medium">' + (s.topicName ? '<span class="text-accentLight">' + escapeHtml(s.topicName) + '</span> <span class="text-textSecondary text-xs">(thread ' + s.threadId + ')</span>' : (s.threadId != null ? 'Thread ' + s.threadId : '<span class="text-muted italic">Awaiting start_session\u2026</span>')) + '</div>' +
|
|
559
|
-
'<div class="text-xs text-textSecondary font-mono">' + s.mcpSessionId.slice(0, 12) + '...</div>' +
|
|
560
|
-
'</div>' +
|
|
561
|
-
'</div>' +
|
|
562
|
-
'<div class="text-right">' +
|
|
563
|
-
'<div class="text-sm font-medium text-' + statusColor + '">' + statusLabel + pollLabel + '</div>' +
|
|
564
|
-
'<div class="text-xs text-textSecondary">' + s.transportType + '</div>' +
|
|
565
|
-
'</div>' +
|
|
566
|
-
'</div>' +
|
|
567
|
-
'</div>';
|
|
568
|
-
}).join('');
|
|
569
|
-
if (list.innerHTML !== html) list.innerHTML = html;
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
function renderNotes(notes) {
|
|
573
|
-
const list = document.getElementById('notes-list');
|
|
574
|
-
const html = (notes || []).map(n => {
|
|
575
|
-
const pClass = 'priority-' + (n.priority || 0);
|
|
576
|
-
return '<div class="glass rounded-xl p-4 ' + pClass + ' animate-fade-in">' +
|
|
577
|
-
'<div class="flex items-start justify-between gap-3">' +
|
|
578
|
-
'<div class="flex-1 min-w-0">' +
|
|
579
|
-
'<div class="flex items-center gap-2 mb-1">' +
|
|
580
|
-
'<span class="type-badge type-' + n.type + '">' + n.type + '</span>' +
|
|
581
|
-
(n.priority >= 2 ? '<span class="type-badge" style="background:rgba(239,68,68,0.15);color:#f87171">HIGH IMPORTANCE</span>' : '') +
|
|
582
|
-
(n.priority === 1 ? '<span class="type-badge" style="background:rgba(245,158,11,0.15);color:#fbbf24">NOTABLE</span>' : '') +
|
|
583
|
-
'<span class="text-xs text-textSecondary">' + n.noteId + '</span>' +
|
|
584
|
-
'</div>' +
|
|
585
|
-
'<p class="text-sm text-textPrimary leading-relaxed">' + escapeHtml(n.content) + '</p>' +
|
|
586
|
-
'<div class="flex flex-wrap gap-1.5 mt-2">' +
|
|
587
|
-
(n.keywords || []).map(k => '<span class="text-xs px-2 py-0.5 rounded-full bg-accent/10 text-accentLight">' + escapeHtml(k) + '</span>').join('') +
|
|
588
|
-
'</div>' +
|
|
589
|
-
'</div>' +
|
|
590
|
-
'<div class="text-right shrink-0">' +
|
|
591
|
-
'<div class="text-sm font-mono text-textSecondary">' + ((Number(n.confidence) || 0) * 100).toFixed(0) + '%</div>' +
|
|
592
|
-
'<div class="text-xs text-muted">' + timeAgo(n.createdAt) + '</div>' +
|
|
593
|
-
'<div class="text-xs text-muted">' + (n.accessCount ?? 0) + ' hits</div>' +
|
|
594
|
-
'</div>' +
|
|
595
|
-
'</div>' +
|
|
596
|
-
'</div>';
|
|
597
|
-
}).join('');
|
|
598
|
-
if (list.innerHTML !== html) list.innerHTML = html;
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
function renderEpisodes(episodes) {
|
|
602
|
-
const list = document.getElementById('episodes-list');
|
|
603
|
-
if (!episodes || !episodes.length) { list.innerHTML = '<p class="text-textSecondary text-center py-12">No episodes</p>'; return; }
|
|
604
|
-
const modalityIcons = {
|
|
605
|
-
text: '💬', voice: '🎤', image: '🖼️', file: '📎', system: '⚙️'
|
|
606
|
-
};
|
|
607
|
-
const html = episodes.map(ep => {
|
|
608
|
-
const icon = modalityIcons[ep.modality] || '📝';
|
|
609
|
-
const content = ep.content ? (typeof ep.content === 'object' ? JSON.stringify(ep.content).slice(0, 300) : String(ep.content).slice(0, 300)) : '(no content)';
|
|
610
|
-
const type = ep.type || 'unknown';
|
|
611
|
-
const episodeId = ep.episodeId || '-';
|
|
612
|
-
const importance = (Number(ep.importance) || 0);
|
|
613
|
-
return '<div class="glass rounded-xl p-4 animate-fade-in">' +
|
|
614
|
-
'<div class="flex items-start gap-3">' +
|
|
615
|
-
'<span class="text-lg">' + icon + '</span>' +
|
|
616
|
-
'<div class="flex-1 min-w-0">' +
|
|
617
|
-
'<div class="flex items-center gap-2 mb-1">' +
|
|
618
|
-
'<span class="type-badge type-fact">' + escapeHtml(type) + '</span>' +
|
|
619
|
-
'<span class="text-xs text-textSecondary font-mono">' + escapeHtml(episodeId) + '</span>' +
|
|
620
|
-
'<span class="text-xs text-muted">' + timeAgo(ep.createdAt) + '</span>' +
|
|
621
|
-
'</div>' +
|
|
622
|
-
'<p class="text-sm text-textSecondary leading-relaxed break-words">' + escapeHtml(content) + '</p>' +
|
|
623
|
-
'</div>' +
|
|
624
|
-
'<div class="text-xs text-muted shrink-0">imp: ' + (importance * 100).toFixed(0) + '%</div>' +
|
|
625
|
-
'</div>' +
|
|
626
|
-
'</div>';
|
|
627
|
-
}).join('');
|
|
628
|
-
if (list.innerHTML !== html) list.innerHTML = html;
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
function renderTopics(topics) {
|
|
632
|
-
const grid = document.getElementById('topics-grid');
|
|
633
|
-
if (!topics.length) { grid.innerHTML = '<p class="text-textSecondary col-span-full text-center py-12">No topics yet</p>'; return; }
|
|
634
|
-
const maxCount = Math.max(...topics.map(t => (t.semanticCount || 0) + (t.proceduralCount || 0))) || 1;
|
|
635
|
-
const html = topics.map(t => {
|
|
636
|
-
const count = (t.semanticCount || 0) + (t.proceduralCount || 0);
|
|
637
|
-
const intensity = Math.max(0.15, count / maxCount);
|
|
638
|
-
return '<div class="glass rounded-xl p-4 animate-slide-up" style="border-left: 3px solid rgba(99,102,241,' + intensity + ')">' +
|
|
639
|
-
'<div class="font-medium text-sm">' + escapeHtml(t.topic || 'Unknown') + '</div>' +
|
|
640
|
-
'<div class="flex items-center justify-between mt-2">' +
|
|
641
|
-
'<span class="text-lg font-bold font-mono text-accent">' + count + '</span>' +
|
|
642
|
-
'<span class="text-xs text-muted">' + timeAgo(t.lastUpdated) + '</span>' +
|
|
643
|
-
'</div>' +
|
|
644
|
-
'</div>';
|
|
645
|
-
}).join('');
|
|
646
|
-
if (grid.innerHTML !== html) grid.innerHTML = html;
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
function renderRateLimits(data) {
|
|
650
|
-
const summary = document.getElementById('ratelimits-summary');
|
|
651
|
-
const grid = document.getElementById('ratelimits-grid');
|
|
652
|
-
summary.innerHTML =
|
|
653
|
-
'<div class="flex items-center justify-between">' +
|
|
654
|
-
'<div>' +
|
|
655
|
-
'<div class="text-sm text-textSecondary">Active Agents Sharing Resources</div>' +
|
|
656
|
-
'<div class="text-3xl font-bold font-mono text-accent">' + data.activeSessions + '</div>' +
|
|
657
|
-
'</div>' +
|
|
658
|
-
'<div class="text-right">' +
|
|
659
|
-
'<div class="text-sm text-textSecondary">Total Calls (Last Hour)</div>' +
|
|
660
|
-
'<div class="text-3xl font-bold font-mono">' + data.totalCallsLastHour + '</div>' +
|
|
661
|
-
'</div>' +
|
|
662
|
-
'</div>';
|
|
663
|
-
if (!data.services || !data.services.length) {
|
|
664
|
-
grid.innerHTML = '<p class="text-textSecondary col-span-full text-center py-8">No services tracked yet</p>';
|
|
665
|
-
return;
|
|
666
|
-
}
|
|
667
|
-
grid.innerHTML = data.services.map(function(svc) {
|
|
668
|
-
var pct = svc.usagePercent;
|
|
669
|
-
var barColor = pct > 80 ? 'danger' : pct > 50 ? 'warn' : 'success';
|
|
670
|
-
var breakdown = '';
|
|
671
|
-
if (svc.sessionBreakdown && svc.sessionBreakdown.length > 0) {
|
|
672
|
-
breakdown = '<div class="mt-3 space-y-1">' +
|
|
673
|
-
'<div class="text-xs text-textSecondary font-medium uppercase tracking-wider">Per-Session Breakdown</div>' +
|
|
674
|
-
svc.sessionBreakdown.map(function(s) {
|
|
675
|
-
return '<div class="flex items-center justify-between text-xs">' +
|
|
676
|
-
'<span class="text-textSecondary font-mono">Thread ' + (s.threadId || '?') + '</span>' +
|
|
677
|
-
'<span class="font-mono text-textPrimary">' + s.calls + ' calls</span>' +
|
|
678
|
-
'</div>';
|
|
679
|
-
}).join('') +
|
|
680
|
-
'</div>';
|
|
681
|
-
}
|
|
682
|
-
return '<div class="glass rounded-xl p-4 animate-slide-up">' +
|
|
683
|
-
'<div class="flex items-center justify-between mb-3">' +
|
|
684
|
-
'<div>' +
|
|
685
|
-
'<div class="font-medium text-sm">' + escapeHtml(svc.description) + '</div>' +
|
|
686
|
-
'<div class="text-xs text-muted font-mono">' + escapeHtml(svc.service) + '</div>' +
|
|
687
|
-
'</div>' +
|
|
688
|
-
'<div class="text-right">' +
|
|
689
|
-
'<div class="text-lg font-bold font-mono text-' + barColor + '">' + pct + '%</div>' +
|
|
690
|
-
'</div>' +
|
|
691
|
-
'</div>' +
|
|
692
|
-
'<div class="w-full h-2 bg-surface rounded-full overflow-hidden mb-3">' +
|
|
693
|
-
'<div class="h-full bg-' + barColor + ' rounded-full transition-all" style="width:' + Math.min(pct, 100) + '%"></div>' +
|
|
694
|
-
'</div>' +
|
|
695
|
-
'<div class="grid grid-cols-2 gap-2 text-xs">' +
|
|
696
|
-
'<div><span class="text-textSecondary">Window:</span> <span class="font-mono">' + svc.callsInWindow + '/' + svc.maxPerWindow + '</span></div>' +
|
|
697
|
-
'<div><span class="text-textSecondary">Burst:</span> <span class="font-mono">' + svc.availableTokens + '/' + svc.burstCapacity + '</span></div>' +
|
|
698
|
-
'</div>' +
|
|
699
|
-
breakdown +
|
|
700
|
-
'</div>';
|
|
701
|
-
}).join('');
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
// ─── Tab switching ──────────────────────────────────────────────────
|
|
705
|
-
function switchTab(tab) {
|
|
706
|
-
const tabs = ['sessions', 'notes', 'episodes', 'topics', 'templates', 'skills'];
|
|
707
|
-
tabs.forEach(t => {
|
|
708
|
-
document.getElementById('panel-' + t).classList.toggle('hidden', t !== tab);
|
|
709
|
-
document.getElementById('tab-' + t).className = 'pb-3 text-sm font-medium transition ' + (t === tab ? 'tab-active' : 'tab-inactive');
|
|
710
|
-
});
|
|
711
|
-
currentTab = tab;
|
|
712
|
-
refreshCurrentTab();
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
// ─── Data loading ─────────────────────────────────────────────────
|
|
716
|
-
let searchDebounce = null;
|
|
717
|
-
document.getElementById('notes-search')?.addEventListener('input', () => {
|
|
718
|
-
clearTimeout(searchDebounce);
|
|
719
|
-
searchDebounce = setTimeout(() => loadNotes(), 300);
|
|
720
|
-
});
|
|
721
|
-
|
|
722
|
-
async function loadNotes() {
|
|
723
|
-
try {
|
|
724
|
-
const q = document.getElementById('notes-search').value.trim();
|
|
725
|
-
const type = document.getElementById('notes-type').value;
|
|
726
|
-
const sort = document.getElementById('notes-sort').value;
|
|
727
|
-
let notes;
|
|
728
|
-
if (q) {
|
|
729
|
-
notes = await api('/api/search?q=' + encodeURIComponent(q) + '&limit=50');
|
|
730
|
-
} else {
|
|
731
|
-
notes = await api('/api/notes?limit=50' + (type ? '&type=' + type : '') + '&sort=' + sort);
|
|
732
|
-
}
|
|
733
|
-
renderNotes(notes);
|
|
734
|
-
} catch (e) { console.error('Notes load error:', e); }
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
async function loadEpisodes() {
|
|
738
|
-
try {
|
|
739
|
-
const threadId = document.getElementById('episodes-thread').value;
|
|
740
|
-
let url = '/api/episodes?limit=30';
|
|
741
|
-
if (threadId) url += '&threadId=' + threadId;
|
|
742
|
-
const episodes = await api(url);
|
|
743
|
-
renderEpisodes(episodes);
|
|
744
|
-
} catch (e) { console.error('Episodes load error:', e); }
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
async function loadTopics() {
|
|
748
|
-
try {
|
|
749
|
-
const topics = await api('/api/topics');
|
|
750
|
-
renderTopics(topics);
|
|
751
|
-
} catch (e) { console.error('Topics load error:', e); }
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
async function refreshCurrentTab() {
|
|
755
|
-
try {
|
|
756
|
-
const data = await api('/api/status').catch(() => null);
|
|
757
|
-
if (data && data.memory) {
|
|
758
|
-
renderStats(data);
|
|
759
|
-
renderSessions(data.sessions || []);
|
|
760
|
-
} else if (data && data.error) {
|
|
761
|
-
console.error('Dashboard API error:', data.error);
|
|
762
|
-
}
|
|
763
|
-
} catch (e) {
|
|
764
|
-
console.error('Dashboard refresh error:', e);
|
|
765
41
|
}
|
|
766
|
-
try {
|
|
767
|
-
if (currentTab === 'notes') loadNotes();
|
|
768
|
-
if (currentTab === 'episodes') loadEpisodes();
|
|
769
|
-
if (currentTab === 'topics') loadTopics();
|
|
770
|
-
if (currentTab === 'templates') { loadAgentType(); loadClaudeMcpConfig(); loadTemplates(); loadDriveTemplate(); }
|
|
771
|
-
if (currentTab === 'skills') loadSkills();
|
|
772
|
-
} catch (e) {
|
|
773
|
-
console.error('Tab load error:', e);
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
function startRefresh() {
|
|
778
|
-
refreshCurrentTab();
|
|
779
|
-
if (refreshTimer) clearInterval(refreshTimer);
|
|
780
|
-
refreshTimer = setInterval(refreshCurrentTab, 30000);
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
// ─── Templates ────────────────────────────────────────────────────
|
|
784
|
-
let tplPreviewOpen = false;
|
|
785
|
-
|
|
786
|
-
async function loadTemplates() {
|
|
787
|
-
try {
|
|
788
|
-
const data = await api('/api/templates');
|
|
789
|
-
if (data.templates && data.templates.length > 0) {
|
|
790
|
-
const tpl = data.templates[0];
|
|
791
|
-
document.getElementById('tpl-editor').value = tpl.content;
|
|
792
|
-
document.getElementById('tpl-default-badge').classList.toggle('hidden', !tpl.isDefault);
|
|
793
|
-
updateTplPreview();
|
|
794
|
-
}
|
|
795
|
-
} catch (e) { console.error('Templates load error:', e); }
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
async function loadAgentType() {
|
|
799
|
-
try {
|
|
800
|
-
const data = await api('/api/settings/agent-type');
|
|
801
|
-
document.getElementById('agent-type-select').value = data.agentType || 'copilot';
|
|
802
|
-
} catch (e) { console.error('Agent type load error:', e); }
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
async function loadClaudeMcpConfig() {
|
|
806
|
-
try {
|
|
807
|
-
const data = await api('/api/settings/claude-mcp-config');
|
|
808
|
-
document.getElementById('claude-mcp-config-input').value = data.path || '';
|
|
809
|
-
} catch (e) { console.error('Claude MCP config load error:', e); }
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
async function saveClaudeMcpConfig() {
|
|
813
|
-
const status = document.getElementById('claude-mcp-config-status');
|
|
814
|
-
const val = document.getElementById('claude-mcp-config-input').value.trim();
|
|
815
|
-
if (!val) { status.textContent = 'Path is empty'; status.className = 'text-sm text-warn'; setTimeout(function() { status.textContent = ''; }, 3000); return; }
|
|
816
|
-
try {
|
|
817
|
-
const r = await fetch('/api/settings/claude-mcp-config', {
|
|
818
|
-
method: 'POST',
|
|
819
|
-
headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' },
|
|
820
|
-
body: JSON.stringify({ path: val }),
|
|
821
|
-
});
|
|
822
|
-
if (!r.ok) throw new Error(r.statusText);
|
|
823
|
-
status.textContent = 'Saved \u2713';
|
|
824
|
-
status.className = 'text-sm text-success';
|
|
825
|
-
setTimeout(function() { status.textContent = ''; }, 3000);
|
|
826
|
-
} catch (e) {
|
|
827
|
-
status.textContent = 'Error: ' + e.message;
|
|
828
|
-
status.className = 'text-sm text-danger';
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
async function changeAgentType() {
|
|
833
|
-
const status = document.getElementById('agent-type-status');
|
|
834
|
-
const agentType = document.getElementById('agent-type-select').value;
|
|
835
|
-
try {
|
|
836
|
-
const r = await fetch('/api/settings/agent-type', {
|
|
837
|
-
method: 'POST',
|
|
838
|
-
headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' },
|
|
839
|
-
body: JSON.stringify({ agentType }),
|
|
840
|
-
});
|
|
841
|
-
if (!r.ok) throw new Error(r.statusText);
|
|
842
|
-
// Reset custom template so the new agent-type default loads
|
|
843
|
-
await fetch('/api/templates/reminders', {
|
|
844
|
-
method: 'DELETE',
|
|
845
|
-
headers: { 'Authorization': 'Bearer ' + token },
|
|
846
|
-
});
|
|
847
|
-
status.textContent = 'Saved \u2713';
|
|
848
|
-
status.className = 'text-sm text-success';
|
|
849
|
-
setTimeout(function() { status.textContent = ''; }, 3000);
|
|
850
|
-
await loadTemplates();
|
|
851
|
-
} catch (e) {
|
|
852
|
-
status.textContent = 'Error: ' + e.message;
|
|
853
|
-
status.className = 'text-sm text-danger';
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
|
|
857
|
-
async function saveTemplate() {
|
|
858
|
-
const status = document.getElementById('tpl-status');
|
|
859
|
-
try {
|
|
860
|
-
const content = document.getElementById('tpl-editor').value;
|
|
861
|
-
const r = await fetch('/api/templates/reminders', {
|
|
862
|
-
method: 'POST',
|
|
863
|
-
headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' },
|
|
864
|
-
body: JSON.stringify({ content }),
|
|
865
|
-
});
|
|
866
|
-
if (!r.ok) throw new Error(r.statusText);
|
|
867
|
-
await r.json();
|
|
868
|
-
status.textContent = 'Saved ✓';
|
|
869
|
-
status.className = 'text-sm text-success';
|
|
870
|
-
document.getElementById('tpl-default-badge').classList.add('hidden');
|
|
871
|
-
setTimeout(function() { status.textContent = ''; }, 3000);
|
|
872
|
-
} catch (e) {
|
|
873
|
-
status.textContent = 'Error: ' + e.message;
|
|
874
|
-
status.className = 'text-sm text-danger';
|
|
875
|
-
}
|
|
876
|
-
}
|
|
877
|
-
|
|
878
|
-
async function resetTemplate() {
|
|
879
|
-
if (!confirm('Reset to default template? Your customizations will be lost.')) return;
|
|
880
|
-
const status = document.getElementById('tpl-status');
|
|
881
|
-
try {
|
|
882
|
-
const r = await fetch('/api/templates/reminders', {
|
|
883
|
-
method: 'DELETE',
|
|
884
|
-
headers: { 'Authorization': 'Bearer ' + token },
|
|
885
|
-
});
|
|
886
|
-
if (!r.ok) throw new Error(r.statusText);
|
|
887
|
-
await r.json();
|
|
888
|
-
await loadTemplates();
|
|
889
|
-
status.textContent = 'Reset to default ✓';
|
|
890
|
-
status.className = 'text-sm text-success';
|
|
891
|
-
setTimeout(function() { status.textContent = ''; }, 3000);
|
|
892
|
-
} catch (e) {
|
|
893
|
-
status.textContent = 'Error: ' + e.message;
|
|
894
|
-
status.className = 'text-sm text-danger';
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
function updateTplPreview() {
|
|
899
|
-
const content = document.getElementById('tpl-editor').value;
|
|
900
|
-
const preview = document.getElementById('tpl-preview');
|
|
901
|
-
const highlighted = escapeHtml(content).replace(/{{([A-Z_]+)}}/g,
|
|
902
|
-
'<span class="text-accentLight bg-accent/10 px-1 rounded">{{$1}}</span>');
|
|
903
|
-
preview.innerHTML = highlighted;
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
function toggleTplPreview() {
|
|
907
|
-
tplPreviewOpen = !tplPreviewOpen;
|
|
908
|
-
document.getElementById('tpl-preview').classList.toggle('hidden', !tplPreviewOpen);
|
|
909
|
-
document.getElementById('tpl-preview-arrow').style.transform = tplPreviewOpen ? 'rotate(90deg)' : '';
|
|
910
|
-
if (tplPreviewOpen) updateTplPreview();
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
document.getElementById('tpl-editor')?.addEventListener('input', function() {
|
|
914
|
-
if (tplPreviewOpen) updateTplPreview();
|
|
915
|
-
});
|
|
916
|
-
|
|
917
|
-
// ─── Drive Templates ──────────────────────────────────────────────
|
|
918
|
-
let drivePresets = [];
|
|
919
|
-
let driveTplPreviewOpen = false;
|
|
920
|
-
|
|
921
|
-
async function loadDriveTemplate() {
|
|
922
|
-
try {
|
|
923
|
-
const [driveData, presetsData, settingsData] = await Promise.all([
|
|
924
|
-
api('/api/templates/drive'),
|
|
925
|
-
api('/api/templates/drive-presets'),
|
|
926
|
-
api('/api/settings/dmn-activation-hours'),
|
|
927
|
-
]);
|
|
928
|
-
drivePresets = presetsData.presets || [];
|
|
929
|
-
document.getElementById('drive-activation-hours').value = settingsData.value;
|
|
930
|
-
if (driveData.custom) {
|
|
931
|
-
document.getElementById('drive-tpl-editor').value = driveData.custom;
|
|
932
|
-
document.getElementById('drive-tpl-default-badge').classList.add('hidden');
|
|
933
|
-
document.getElementById('drive-tpl-editor').style.borderColor = '';
|
|
934
|
-
} else {
|
|
935
|
-
document.getElementById('drive-tpl-editor').value = driveData.default || '';
|
|
936
|
-
document.getElementById('drive-tpl-default-badge').classList.remove('hidden');
|
|
937
|
-
document.getElementById('drive-tpl-editor').style.borderColor = 'rgba(245,158,11,0.4)';
|
|
938
|
-
}
|
|
939
|
-
updateDriveTplPreview();
|
|
940
|
-
} catch (e) { console.error('Drive template load error:', e); }
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
async function saveDriveTemplate() {
|
|
944
|
-
const status = document.getElementById('drive-tpl-status');
|
|
945
|
-
try {
|
|
946
|
-
const content = document.getElementById('drive-tpl-editor').value;
|
|
947
|
-
if (!content.trim()) {
|
|
948
|
-
status.textContent = 'Template is empty — load a preset first';
|
|
949
|
-
status.className = 'text-sm text-warn';
|
|
950
|
-
setTimeout(function() { status.textContent = ''; }, 3000);
|
|
951
|
-
return;
|
|
952
|
-
}
|
|
953
|
-
const r = await fetch('/api/templates/drive', {
|
|
954
|
-
method: 'POST',
|
|
955
|
-
headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' },
|
|
956
|
-
body: JSON.stringify({ content }),
|
|
957
|
-
});
|
|
958
|
-
if (!r.ok) throw new Error(r.statusText);
|
|
959
|
-
await r.json();
|
|
960
|
-
status.textContent = 'Saved ✓';
|
|
961
|
-
status.className = 'text-sm text-success';
|
|
962
|
-
document.getElementById('drive-tpl-default-badge').classList.add('hidden');
|
|
963
|
-
document.getElementById('drive-tpl-editor').style.borderColor = '';
|
|
964
|
-
setTimeout(function() { status.textContent = ''; }, 3000);
|
|
965
|
-
} catch (e) {
|
|
966
|
-
status.textContent = 'Error: ' + e.message;
|
|
967
|
-
status.className = 'text-sm text-danger';
|
|
968
|
-
}
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
async function resetDriveTemplate() {
|
|
972
|
-
if (!confirm('Reset drive template? The custom template will be removed and the system will use hardcoded drive prompts.')) return;
|
|
973
|
-
const status = document.getElementById('drive-tpl-status');
|
|
974
|
-
try {
|
|
975
|
-
const r = await fetch('/api/templates/drive', {
|
|
976
|
-
method: 'DELETE',
|
|
977
|
-
headers: { 'Authorization': 'Bearer ' + token },
|
|
978
|
-
});
|
|
979
|
-
if (!r.ok) throw new Error(r.statusText);
|
|
980
|
-
await r.json();
|
|
981
|
-
await loadDriveTemplate();
|
|
982
|
-
status.textContent = 'Reset to default ✓';
|
|
983
|
-
status.className = 'text-sm text-success';
|
|
984
|
-
setTimeout(function() { status.textContent = ''; }, 3000);
|
|
985
|
-
} catch (e) {
|
|
986
|
-
status.textContent = 'Error: ' + e.message;
|
|
987
|
-
status.className = 'text-sm text-danger';
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
function loadPreset(key) {
|
|
992
|
-
var preset = drivePresets.find(function(p) { return p.key === key; });
|
|
993
|
-
if (preset) {
|
|
994
|
-
document.getElementById('drive-tpl-editor').value = preset.content;
|
|
995
|
-
document.getElementById('drive-tpl-default-badge').classList.add('hidden');
|
|
996
|
-
updateDriveTplPreview();
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
function updateDriveTplPreview() {
|
|
1001
|
-
var content = document.getElementById('drive-tpl-editor').value;
|
|
1002
|
-
var preview = document.getElementById('drive-tpl-preview');
|
|
1003
|
-
if (!content) {
|
|
1004
|
-
preview.innerHTML = '<span class="text-muted">(no template loaded)</span>';
|
|
1005
|
-
return;
|
|
1006
|
-
}
|
|
1007
|
-
var highlighted = escapeHtml(content).replace(/{{([A-Z_]+)}}/g,
|
|
1008
|
-
'<span class="text-accentLight bg-accent/10 px-1 rounded">{{$1}}</span>');
|
|
1009
|
-
preview.innerHTML = highlighted;
|
|
1010
|
-
}
|
|
1011
|
-
|
|
1012
|
-
function toggleDriveTplPreview() {
|
|
1013
|
-
driveTplPreviewOpen = !driveTplPreviewOpen;
|
|
1014
|
-
document.getElementById('drive-tpl-preview').classList.toggle('hidden', !driveTplPreviewOpen);
|
|
1015
|
-
document.getElementById('drive-tpl-preview-arrow').style.transform = driveTplPreviewOpen ? 'rotate(90deg)' : '';
|
|
1016
|
-
if (driveTplPreviewOpen) updateDriveTplPreview();
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
|
-
document.getElementById('drive-tpl-editor')?.addEventListener('input', function() {
|
|
1020
|
-
if (driveTplPreviewOpen) updateDriveTplPreview();
|
|
1021
|
-
});
|
|
1022
|
-
|
|
1023
|
-
// ─── Skills ────────────────────────────────────────────────────────
|
|
1024
|
-
let skillsData = [];
|
|
1025
|
-
let editingSkillName = null;
|
|
1026
|
-
|
|
1027
|
-
async function loadSkills() {
|
|
1028
|
-
try {
|
|
1029
|
-
const data = await api('/api/skills');
|
|
1030
|
-
skillsData = data.skills || [];
|
|
1031
|
-
renderSkills(skillsData);
|
|
1032
|
-
} catch (e) { console.error('Skills load error:', e); }
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
|
-
function skillSourceType(source) {
|
|
1036
|
-
if (!source) return 'unknown';
|
|
1037
|
-
if (source.includes('.remote-copilot-mcp') && source.includes('skills')) return 'user';
|
|
1038
|
-
if (source.endsWith('.default.md')) return 'default';
|
|
1039
|
-
if (source.endsWith('.skill.md')) return 'project';
|
|
1040
|
-
return 'unknown';
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
function sourceTypeBadge(type) {
|
|
1044
|
-
const styles = {
|
|
1045
|
-
user: 'background:rgba(99,102,241,0.15);color:#818cf8',
|
|
1046
|
-
default: 'background:rgba(107,114,128,0.15);color:#9ca3af',
|
|
1047
|
-
project: 'background:rgba(34,197,94,0.15);color:#4ade80',
|
|
1048
|
-
unknown: 'background:rgba(107,114,128,0.15);color:#9ca3af',
|
|
1049
|
-
};
|
|
1050
|
-
return '<span class="type-badge" style="' + (styles[type] || styles.unknown) + '">' + type + '</span>';
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
function renderSkills(skills) {
|
|
1054
|
-
const list = document.getElementById('skills-list');
|
|
1055
|
-
const empty = document.getElementById('skills-empty');
|
|
1056
|
-
if (!skills || !skills.length) {
|
|
1057
|
-
list.innerHTML = '';
|
|
1058
|
-
empty.classList.remove('hidden');
|
|
1059
|
-
return;
|
|
1060
|
-
}
|
|
1061
|
-
empty.classList.add('hidden');
|
|
1062
|
-
const html = skills.map(function(sk) {
|
|
1063
|
-
const sType = skillSourceType(sk.source);
|
|
1064
|
-
const triggers = (sk.triggers || []).map(function(t) {
|
|
1065
|
-
return '<span class="text-xs px-2 py-0.5 rounded-full bg-accent/10 text-accentLight">' + escapeHtml(t) + '</span>';
|
|
1066
|
-
}).join(' ');
|
|
1067
|
-
const active = editingSkillName === sk.name ? ' border-accent' : ' border-transparent';
|
|
1068
|
-
return '<div class="glass rounded-xl p-4 cursor-pointer hover:bg-cardHover transition border' + active + '" onclick="openSkillEditor(\'' + escapeHtml(sk.name).replace(/'/g, "\\'") + '\')">' +
|
|
1069
|
-
'<div class="flex items-start justify-between gap-3">' +
|
|
1070
|
-
'<div class="flex-1 min-w-0">' +
|
|
1071
|
-
'<div class="flex items-center gap-2 mb-1">' +
|
|
1072
|
-
'<span class="font-medium text-sm">' + escapeHtml(sk.name) + '</span>' +
|
|
1073
|
-
sourceTypeBadge(sType) +
|
|
1074
|
-
(sk.replacesOrchestrator ? '<span class="type-badge" style="background:rgba(245,158,11,0.15);color:#fbbf24">REPLACES ORCH</span>' : '') +
|
|
1075
|
-
'</div>' +
|
|
1076
|
-
'<div class="flex flex-wrap gap-1.5 mt-1">' + triggers + '</div>' +
|
|
1077
|
-
'</div>' +
|
|
1078
|
-
'<div class="text-xs text-muted font-mono shrink-0 max-w-[200px] truncate" title="' + escapeHtml(sk.source || '') + '">' + escapeHtml((sk.source || '').split(/[\\/]/).pop() || '') + '</div>' +
|
|
1079
|
-
'</div>' +
|
|
1080
|
-
'</div>';
|
|
1081
|
-
}).join('');
|
|
1082
|
-
list.innerHTML = html;
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
function openSkillEditor(name) {
|
|
1086
|
-
const sk = skillsData.find(function(s) { return s.name === name; });
|
|
1087
|
-
if (!sk) return;
|
|
1088
|
-
editingSkillName = name;
|
|
1089
|
-
renderSkills(skillsData); // update highlight
|
|
1090
|
-
document.getElementById('skill-editor-panel').classList.remove('hidden');
|
|
1091
|
-
document.getElementById('skill-editor-title').textContent = 'Edit: ' + sk.name;
|
|
1092
|
-
var sType = skillSourceType(sk.source);
|
|
1093
|
-
document.getElementById('skill-editor-source').textContent = sk.source || '(unknown source)';
|
|
1094
|
-
document.getElementById('skill-edit-name').value = sk.name;
|
|
1095
|
-
document.getElementById('skill-edit-triggers').value = (sk.triggers || []).join(', ');
|
|
1096
|
-
document.getElementById('skill-edit-replaces').checked = !!sk.replacesOrchestrator;
|
|
1097
|
-
// Reconstruct full markdown content with frontmatter
|
|
1098
|
-
var content = sk.content || '';
|
|
1099
|
-
document.getElementById('skill-edit-content').value = content;
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
function closeSkillEditor() {
|
|
1103
|
-
editingSkillName = null;
|
|
1104
|
-
document.getElementById('skill-editor-panel').classList.add('hidden');
|
|
1105
|
-
renderSkills(skillsData);
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
function buildSkillMarkdown(name, triggers, replacesOrchestrator, body) {
|
|
1109
|
-
var fm = '---\nname: ' + name + '\ntriggers:\n';
|
|
1110
|
-
triggers.forEach(function(t) { fm += ' - ' + t.trim() + '\n'; });
|
|
1111
|
-
if (replacesOrchestrator) fm += 'replaces_orchestrator: true\n';
|
|
1112
|
-
fm += '---\n\n';
|
|
1113
|
-
return fm + body;
|
|
1114
|
-
}
|
|
1115
|
-
|
|
1116
|
-
async function saveSkill() {
|
|
1117
|
-
const status = document.getElementById('skill-editor-status');
|
|
1118
|
-
const name = document.getElementById('skill-edit-name').value.trim();
|
|
1119
|
-
if (!name) return;
|
|
1120
|
-
try {
|
|
1121
|
-
// Build full content from the editor fields
|
|
1122
|
-
var triggers = document.getElementById('skill-edit-triggers').value.split(',').map(function(t) { return t.trim(); }).filter(Boolean);
|
|
1123
|
-
var replaces = document.getElementById('skill-edit-replaces').checked;
|
|
1124
|
-
var rawContent = document.getElementById('skill-edit-content').value;
|
|
1125
|
-
// If content already has frontmatter, use as-is; otherwise reconstruct
|
|
1126
|
-
var content;
|
|
1127
|
-
if (rawContent.trimStart().startsWith('---')) {
|
|
1128
|
-
content = rawContent;
|
|
1129
|
-
} else {
|
|
1130
|
-
content = buildSkillMarkdown(name, triggers, replaces, rawContent);
|
|
1131
|
-
}
|
|
1132
|
-
const r = await fetch('/api/skills/' + encodeURIComponent(name), {
|
|
1133
|
-
method: 'PUT',
|
|
1134
|
-
headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' },
|
|
1135
|
-
body: JSON.stringify({ content: content }),
|
|
1136
|
-
});
|
|
1137
|
-
if (!r.ok) throw new Error(r.statusText);
|
|
1138
|
-
await r.json();
|
|
1139
|
-
status.textContent = 'Saved \u2713';
|
|
1140
|
-
status.className = 'text-sm text-success';
|
|
1141
|
-
setTimeout(function() { status.textContent = ''; }, 3000);
|
|
1142
|
-
await loadSkills();
|
|
1143
|
-
} catch (e) {
|
|
1144
|
-
status.textContent = 'Error: ' + e.message;
|
|
1145
|
-
status.className = 'text-sm text-danger';
|
|
1146
|
-
}
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
function showNewSkillForm() {
|
|
1150
|
-
document.getElementById('skill-new-form').classList.remove('hidden');
|
|
1151
|
-
document.getElementById('skill-new-name').value = '';
|
|
1152
|
-
document.getElementById('skill-new-triggers').value = '';
|
|
1153
|
-
document.getElementById('skill-new-replaces').checked = false;
|
|
1154
|
-
document.getElementById('skill-new-status').textContent = '';
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
|
-
function hideNewSkillForm() {
|
|
1158
|
-
document.getElementById('skill-new-form').classList.add('hidden');
|
|
1159
|
-
}
|
|
1160
|
-
|
|
1161
|
-
async function createNewSkill() {
|
|
1162
|
-
const status = document.getElementById('skill-new-status');
|
|
1163
|
-
const name = document.getElementById('skill-new-name').value.trim();
|
|
1164
|
-
const triggersRaw = document.getElementById('skill-new-triggers').value;
|
|
1165
|
-
const replaces = document.getElementById('skill-new-replaces').checked;
|
|
1166
|
-
if (!name) { status.textContent = 'Name is required'; status.className = 'text-sm text-warn'; return; }
|
|
1167
|
-
var triggers = triggersRaw.split(',').map(function(t) { return t.trim(); }).filter(Boolean);
|
|
1168
|
-
if (!triggers.length) { status.textContent = 'At least one trigger is required'; status.className = 'text-sm text-warn'; return; }
|
|
1169
|
-
var content = buildSkillMarkdown(name, triggers, replaces, '<!-- Write your skill instructions here -->\n');
|
|
1170
|
-
try {
|
|
1171
|
-
const r = await fetch('/api/skills/' + encodeURIComponent(name), {
|
|
1172
|
-
method: 'PUT',
|
|
1173
|
-
headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' },
|
|
1174
|
-
body: JSON.stringify({ content: content }),
|
|
1175
|
-
});
|
|
1176
|
-
if (!r.ok) throw new Error(r.statusText);
|
|
1177
|
-
await r.json();
|
|
1178
|
-
status.textContent = 'Created \u2713';
|
|
1179
|
-
status.className = 'text-sm text-success';
|
|
1180
|
-
hideNewSkillForm();
|
|
1181
|
-
await loadSkills();
|
|
1182
|
-
// Auto-open the new skill in editor
|
|
1183
|
-
openSkillEditor(name);
|
|
1184
|
-
} catch (e) {
|
|
1185
|
-
status.textContent = 'Error: ' + e.message;
|
|
1186
|
-
status.className = 'text-sm text-danger';
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
|
|
1190
|
-
// ─── Utilities ──────────────────────────────────────────────────────
|
|
1191
|
-
function escapeHtml(str) {
|
|
1192
|
-
if (!str) return '';
|
|
1193
|
-
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
1194
42
|
}
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
43
|
+
</script>
|
|
44
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
45
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
46
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
|
47
|
+
<style>
|
|
48
|
+
body { background: #0f1419; }
|
|
49
|
+
::-webkit-scrollbar { width: 6px; }
|
|
50
|
+
::-webkit-scrollbar-track { background: #1a1f2e; }
|
|
51
|
+
::-webkit-scrollbar-thumb { background: #374151; border-radius: 3px; }
|
|
52
|
+
::-webkit-scrollbar-thumb:hover { background: #4b5563; }
|
|
53
|
+
.glass { background: rgba(26, 31, 46, 0.8); backdrop-filter: blur(12px); border: 1px solid rgba(99, 102, 241, 0.1); }
|
|
54
|
+
.stat-glow { box-shadow: 0 0 20px rgba(99, 102, 241, 0.08); }
|
|
55
|
+
.priority-2 { border-left: 3px solid #ef4444; }
|
|
56
|
+
.priority-1 { border-left: 3px solid #f59e0b; }
|
|
57
|
+
.priority-0 { border-left: 3px solid transparent; }
|
|
58
|
+
.type-badge { font-size: 0.65rem; padding: 2px 6px; border-radius: 9999px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; }
|
|
59
|
+
.type-fact { background: rgba(59, 130, 246, 0.15); color: #60a5fa; }
|
|
60
|
+
.type-preference { background: rgba(168, 85, 247, 0.15); color: #c084fc; }
|
|
61
|
+
.type-pattern { background: rgba(34, 197, 94, 0.15); color: #4ade80; }
|
|
62
|
+
.type-entity { background: rgba(251, 191, 36, 0.15); color: #fbbf24; }
|
|
63
|
+
.type-relationship { background: rgba(244, 114, 182, 0.15); color: #f472b6; }
|
|
64
|
+
.tab-active { border-bottom: 2px solid #6366f1; color: #e5e7eb; }
|
|
65
|
+
.tab-inactive { border-bottom: 2px solid transparent; color: #6b7280; }
|
|
66
|
+
.tab-inactive:hover { color: #9ca3af; }
|
|
67
|
+
</style>
|
|
68
|
+
<script type="module" crossorigin>(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))n(o);new MutationObserver(o=>{for(const r of o)if(r.type==="childList")for(const i of r.addedNodes)i.tagName==="LINK"&&i.rel==="modulepreload"&&n(i)}).observe(document,{childList:!0,subtree:!0});function s(o){const r={};return o.integrity&&(r.integrity=o.integrity),o.referrerPolicy&&(r.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?r.credentials="include":o.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function n(o){if(o.ep)return;o.ep=!0;const r=s(o);fetch(o.href,r)}})();/**
|
|
69
|
+
* @vue/shared v3.5.31
|
|
70
|
+
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
|
71
|
+
* @license MIT
|
|
72
|
+
**/function Xs(e){const t=Object.create(null);for(const s of e.split(","))t[s]=1;return s=>s in t}const ee={},_t=[],Be=()=>{},io=()=>!1,vs=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),ys=e=>e.startsWith("onUpdate:"),fe=Object.assign,en=(e,t)=>{const s=e.indexOf(t);s>-1&&e.splice(s,1)},gr=Object.prototype.hasOwnProperty,Y=(e,t)=>gr.call(e,t),j=Array.isArray,wt=e=>Zt(e)==="[object Map]",Pt=e=>Zt(e)==="[object Set]",Cn=e=>Zt(e)==="[object Date]",B=e=>typeof e=="function",ie=e=>typeof e=="string",We=e=>typeof e=="symbol",Q=e=>e!==null&&typeof e=="object",lo=e=>(Q(e)||B(e))&&B(e.then)&&B(e.catch),ao=Object.prototype.toString,Zt=e=>ao.call(e),xr=e=>Zt(e).slice(8,-1),co=e=>Zt(e)==="[object Object]",tn=e=>ie(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,jt=Xs(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),bs=e=>{const t=Object.create(null);return(s=>t[s]||(t[s]=e(s)))},vr=/-\w/g,be=bs(e=>e.replace(vr,t=>t.slice(1).toUpperCase())),yr=/\B([A-Z])/g,at=bs(e=>e.replace(yr,"-$1").toLowerCase()),_s=bs(e=>e.charAt(0).toUpperCase()+e.slice(1)),Ms=bs(e=>e?`on${_s(e)}`:""),Ve=(e,t)=>!Object.is(e,t),ls=(e,...t)=>{for(let s=0;s<e.length;s++)e[s](...t)},uo=(e,t,s,n=!1)=>{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:n,value:s})},ws=e=>{const t=parseFloat(e);return isNaN(t)?e:t};let Tn;const Ss=()=>Tn||(Tn=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Qt(e){if(j(e)){const t={};for(let s=0;s<e.length;s++){const n=e[s],o=ie(n)?Sr(n):Qt(n);if(o)for(const r in o)t[r]=o[r]}return t}else if(ie(e)||Q(e))return e}const br=/;(?![^(]*\))/g,_r=/:([^]+)/,wr=/\/\*[^]*?\*\//g;function Sr(e){const t={};return e.replace(wr,"").split(br).forEach(s=>{if(s){const n=s.split(_r);n.length>1&&(t[n[0].trim()]=n[1].trim())}}),t}function Se(e){let t="";if(ie(e))t=e;else if(j(e))for(let s=0;s<e.length;s++){const n=Se(e[s]);n&&(t+=n+" ")}else if(Q(e))for(const s in e)e[s]&&(t+=s+" ");return t.trim()}const Cr="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly",Tr=Xs(Cr);function fo(e){return!!e||e===""}function $r(e,t){if(e.length!==t.length)return!1;let s=!0;for(let n=0;s&&n<e.length;n++)s=At(e[n],t[n]);return s}function At(e,t){if(e===t)return!0;let s=Cn(e),n=Cn(t);if(s||n)return s&&n?e.getTime()===t.getTime():!1;if(s=We(e),n=We(t),s||n)return e===t;if(s=j(e),n=j(t),s||n)return s&&n?$r(e,t):!1;if(s=Q(e),n=Q(t),s||n){if(!s||!n)return!1;const o=Object.keys(e).length,r=Object.keys(t).length;if(o!==r)return!1;for(const i in e){const l=e.hasOwnProperty(i),a=t.hasOwnProperty(i);if(l&&!a||!l&&a||!At(e[i],t[i]))return!1}}return String(e)===String(t)}function sn(e,t){return e.findIndex(s=>At(s,t))}const po=e=>!!(e&&e.__v_isRef===!0),N=e=>ie(e)?e:e==null?"":j(e)||Q(e)&&(e.toString===ao||!B(e.toString))?po(e)?N(e.value):JSON.stringify(e,ho,2):String(e),ho=(e,t)=>po(t)?ho(e,t.value):wt(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((s,[n,o],r)=>(s[Os(n,r)+" =>"]=o,s),{})}:Pt(t)?{[`Set(${t.size})`]:[...t.values()].map(s=>Os(s))}:We(t)?Os(t):Q(t)&&!j(t)&&!co(t)?String(t):t,Os=(e,t="")=>{var s;return We(e)?`Symbol(${(s=e.description)!=null?s:t})`:e};/**
|
|
73
|
+
* @vue/reactivity v3.5.31
|
|
74
|
+
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
|
75
|
+
* @license MIT
|
|
76
|
+
**/let we;class Er{constructor(t=!1){this.detached=t,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this.__v_skip=!0,this.parent=we,!t&&we&&(this.index=(we.scopes||(we.scopes=[])).push(this)-1)}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let t,s;if(this.scopes)for(t=0,s=this.scopes.length;t<s;t++)this.scopes[t].pause();for(t=0,s=this.effects.length;t<s;t++)this.effects[t].pause()}}resume(){if(this._active&&this._isPaused){this._isPaused=!1;let t,s;if(this.scopes)for(t=0,s=this.scopes.length;t<s;t++)this.scopes[t].resume();for(t=0,s=this.effects.length;t<s;t++)this.effects[t].resume()}}run(t){if(this._active){const s=we;try{return we=this,t()}finally{we=s}}}on(){++this._on===1&&(this.prevScope=we,we=this)}off(){this._on>0&&--this._on===0&&(we=this.prevScope,this.prevScope=void 0)}stop(t){if(this._active){this._active=!1;let s,n;for(s=0,n=this.effects.length;s<n;s++)this.effects[s].stop();for(this.effects.length=0,s=0,n=this.cleanups.length;s<n;s++)this.cleanups[s]();if(this.cleanups.length=0,this.scopes){for(s=0,n=this.scopes.length;s<n;s++)this.scopes[s].stop(!0);this.scopes.length=0}if(!this.detached&&this.parent&&!t){const o=this.parent.scopes.pop();o&&o!==this&&(this.parent.scopes[this.index]=o,o.index=this.index)}this.parent=void 0}}}function kr(){return we}let ne;const Is=new WeakSet;class mo{constructor(t){this.fn=t,this.deps=void 0,this.depsTail=void 0,this.flags=5,this.next=void 0,this.cleanup=void 0,this.scheduler=void 0,we&&we.active&&we.effects.push(this)}pause(){this.flags|=64}resume(){this.flags&64&&(this.flags&=-65,Is.has(this)&&(Is.delete(this),this.trigger()))}notify(){this.flags&2&&!(this.flags&32)||this.flags&8||xo(this)}run(){if(!(this.flags&1))return this.fn();this.flags|=2,$n(this),vo(this);const t=ne,s=Ae;ne=this,Ae=!0;try{return this.fn()}finally{yo(this),ne=t,Ae=s,this.flags&=-3}}stop(){if(this.flags&1){for(let t=this.deps;t;t=t.nextDep)rn(t);this.deps=this.depsTail=void 0,$n(this),this.onStop&&this.onStop(),this.flags&=-2}}trigger(){this.flags&64?Is.add(this):this.scheduler?this.scheduler():this.runIfDirty()}runIfDirty(){Vs(this)&&this.run()}get dirty(){return Vs(this)}}let go=0,Ft,Ht;function xo(e,t=!1){if(e.flags|=8,t){e.next=Ht,Ht=e;return}e.next=Ft,Ft=e}function nn(){go++}function on(){if(--go>0)return;if(Ht){let t=Ht;for(Ht=void 0;t;){const s=t.next;t.next=void 0,t.flags&=-9,t=s}}let e;for(;Ft;){let t=Ft;for(Ft=void 0;t;){const s=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(n){e||(e=n)}t=s}}if(e)throw e}function vo(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function yo(e){let t,s=e.depsTail,n=s;for(;n;){const o=n.prevDep;n.version===-1?(n===s&&(s=o),rn(n),Pr(n)):t=n,n.dep.activeLink=n.prevActiveLink,n.prevActiveLink=void 0,n=o}e.deps=t,e.depsTail=s}function Vs(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(bo(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function bo(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===Wt)||(e.globalVersion=Wt,!e.isSSR&&e.flags&128&&(!e.deps&&!e._dirty||!Vs(e))))return;e.flags|=2;const t=e.dep,s=ne,n=Ae;ne=e,Ae=!0;try{vo(e);const o=e.fn(e._value);(t.version===0||Ve(o,e._value))&&(e.flags|=128,e._value=o,t.version++)}catch(o){throw t.version++,o}finally{ne=s,Ae=n,yo(e),e.flags&=-3}}function rn(e,t=!1){const{dep:s,prevSub:n,nextSub:o}=e;if(n&&(n.nextSub=o,e.prevSub=void 0),o&&(o.prevSub=n,e.nextSub=void 0),s.subs===e&&(s.subs=n,!n&&s.computed)){s.computed.flags&=-5;for(let r=s.computed.deps;r;r=r.nextDep)rn(r,!0)}!t&&!--s.sc&&s.map&&s.map.delete(s.key)}function Pr(e){const{prevDep:t,nextDep:s}=e;t&&(t.nextDep=s,e.prevDep=void 0),s&&(s.prevDep=t,e.nextDep=void 0)}let Ae=!0;const _o=[];function et(){_o.push(Ae),Ae=!1}function tt(){const e=_o.pop();Ae=e===void 0?!0:e}function $n(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const s=ne;ne=void 0;try{t()}finally{ne=s}}}let Wt=0;class Ar{constructor(t,s){this.sub=t,this.dep=s,this.version=s.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class ln{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(t){if(!ne||!Ae||ne===this.computed)return;let s=this.activeLink;if(s===void 0||s.sub!==ne)s=this.activeLink=new Ar(ne,this),ne.deps?(s.prevDep=ne.depsTail,ne.depsTail.nextDep=s,ne.depsTail=s):ne.deps=ne.depsTail=s,wo(s);else if(s.version===-1&&(s.version=this.version,s.nextDep)){const n=s.nextDep;n.prevDep=s.prevDep,s.prevDep&&(s.prevDep.nextDep=n),s.prevDep=ne.depsTail,s.nextDep=void 0,ne.depsTail.nextDep=s,ne.depsTail=s,ne.deps===s&&(ne.deps=n)}return s}trigger(t){this.version++,Wt++,this.notify(t)}notify(t){nn();try{for(let s=this.subs;s;s=s.prevSub)s.sub.notify()&&s.sub.dep.notify()}finally{on()}}}function wo(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let n=t.deps;n;n=n.nextDep)wo(n)}const s=e.dep.subs;s!==e&&(e.prevSub=s,s&&(s.nextSub=e)),e.dep.subs=e}}const Us=new WeakMap,ht=Symbol(""),Bs=Symbol(""),zt=Symbol("");function he(e,t,s){if(Ae&&ne){let n=Us.get(e);n||Us.set(e,n=new Map);let o=n.get(s);o||(n.set(s,o=new ln),o.map=n,o.key=s),o.track()}}function Ze(e,t,s,n,o,r){const i=Us.get(e);if(!i){Wt++;return}const l=a=>{a&&a.trigger()};if(nn(),t==="clear")i.forEach(l);else{const a=j(e),p=a&&tn(s);if(a&&s==="length"){const u=Number(n);i.forEach((d,g)=>{(g==="length"||g===zt||!We(g)&&g>=u)&&l(d)})}else switch((s!==void 0||i.has(void 0))&&l(i.get(s)),p&&l(i.get(zt)),t){case"add":a?p&&l(i.get("length")):(l(i.get(ht)),wt(e)&&l(i.get(Bs)));break;case"delete":a||(l(i.get(ht)),wt(e)&&l(i.get(Bs)));break;case"set":wt(e)&&l(i.get(ht));break}}on()}function vt(e){const t=G(e);return t===e?t:(he(t,"iterate",zt),Pe(e)?t:t.map(Me))}function Cs(e){return he(e=G(e),"iterate",zt),e}function Fe(e,t){return st(e)?Tt(mt(e)?Me(t):t):Me(t)}const Mr={__proto__:null,[Symbol.iterator](){return Rs(this,Symbol.iterator,e=>Fe(this,e))},concat(...e){return vt(this).concat(...e.map(t=>j(t)?vt(t):t))},entries(){return Rs(this,"entries",e=>(e[1]=Fe(this,e[1]),e))},every(e,t){return Je(this,"every",e,t,void 0,arguments)},filter(e,t){return Je(this,"filter",e,t,s=>s.map(n=>Fe(this,n)),arguments)},find(e,t){return Je(this,"find",e,t,s=>Fe(this,s),arguments)},findIndex(e,t){return Je(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return Je(this,"findLast",e,t,s=>Fe(this,s),arguments)},findLastIndex(e,t){return Je(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return Je(this,"forEach",e,t,void 0,arguments)},includes(...e){return Ds(this,"includes",e)},indexOf(...e){return Ds(this,"indexOf",e)},join(e){return vt(this).join(e)},lastIndexOf(...e){return Ds(this,"lastIndexOf",e)},map(e,t){return Je(this,"map",e,t,void 0,arguments)},pop(){return Rt(this,"pop")},push(...e){return Rt(this,"push",e)},reduce(e,...t){return En(this,"reduce",e,t)},reduceRight(e,...t){return En(this,"reduceRight",e,t)},shift(){return Rt(this,"shift")},some(e,t){return Je(this,"some",e,t,void 0,arguments)},splice(...e){return Rt(this,"splice",e)},toReversed(){return vt(this).toReversed()},toSorted(e){return vt(this).toSorted(e)},toSpliced(...e){return vt(this).toSpliced(...e)},unshift(...e){return Rt(this,"unshift",e)},values(){return Rs(this,"values",e=>Fe(this,e))}};function Rs(e,t,s){const n=Cs(e),o=n[t]();return n!==e&&!Pe(e)&&(o._next=o.next,o.next=()=>{const r=o._next();return r.done||(r.value=s(r.value)),r}),o}const Or=Array.prototype;function Je(e,t,s,n,o,r){const i=Cs(e),l=i!==e&&!Pe(e),a=i[t];if(a!==Or[t]){const d=a.apply(e,r);return l?Me(d):d}let p=s;i!==e&&(l?p=function(d,g){return s.call(this,Fe(e,d),g,e)}:s.length>2&&(p=function(d,g){return s.call(this,d,g,e)}));const u=a.call(i,p,n);return l&&o?o(u):u}function En(e,t,s,n){const o=Cs(e),r=o!==e&&!Pe(e);let i=s,l=!1;o!==e&&(r?(l=n.length===0,i=function(p,u,d){return l&&(l=!1,p=Fe(e,p)),s.call(this,p,Fe(e,u),d,e)}):s.length>3&&(i=function(p,u,d){return s.call(this,p,u,d,e)}));const a=o[t](i,...n);return l?Fe(e,a):a}function Ds(e,t,s){const n=G(e);he(n,"iterate",zt);const o=n[t](...s);return(o===-1||o===!1)&&fn(s[0])?(s[0]=G(s[0]),n[t](...s)):o}function Rt(e,t,s=[]){et(),nn();const n=G(e)[t].apply(e,s);return on(),tt(),n}const Ir=Xs("__proto__,__v_isRef,__isVue"),So=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(We));function Rr(e){We(e)||(e=String(e));const t=G(this);return he(t,"has",e),t.hasOwnProperty(e)}class Co{constructor(t=!1,s=!1){this._isReadonly=t,this._isShallow=s}get(t,s,n){if(s==="__v_skip")return t.__v_skip;const o=this._isReadonly,r=this._isShallow;if(s==="__v_isReactive")return!o;if(s==="__v_isReadonly")return o;if(s==="__v_isShallow")return r;if(s==="__v_raw")return n===(o?r?Kr:ko:r?Eo:$o).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(n)?t:void 0;const i=j(t);if(!o){let a;if(i&&(a=Mr[s]))return a;if(s==="hasOwnProperty")return Rr}const l=Reflect.get(t,s,ge(t)?t:n);if((We(s)?So.has(s):Ir(s))||(o||he(t,"get",s),r))return l;if(ge(l)){const a=i&&tn(s)?l:l.value;return o&&Q(a)?Ws(a):a}return Q(l)?o?Ws(l):cn(l):l}}class To extends Co{constructor(t=!1){super(!1,t)}set(t,s,n,o){let r=t[s];const i=j(t)&&tn(s);if(!this._isShallow){const p=st(r);if(!Pe(n)&&!st(n)&&(r=G(r),n=G(n)),!i&&ge(r)&&!ge(n))return p||(r.value=n),!0}const l=i?Number(s)<t.length:Y(t,s),a=Reflect.set(t,s,n,ge(t)?t:o);return t===G(o)&&(l?Ve(n,r)&&Ze(t,"set",s,n):Ze(t,"add",s,n)),a}deleteProperty(t,s){const n=Y(t,s);t[s];const o=Reflect.deleteProperty(t,s);return o&&n&&Ze(t,"delete",s,void 0),o}has(t,s){const n=Reflect.has(t,s);return(!We(s)||!So.has(s))&&he(t,"has",s),n}ownKeys(t){return he(t,"iterate",j(t)?"length":ht),Reflect.ownKeys(t)}}class Dr extends Co{constructor(t=!1){super(!0,t)}set(t,s){return!0}deleteProperty(t,s){return!0}}const Lr=new To,Nr=new Dr,jr=new To(!0);const Ks=e=>e,ns=e=>Reflect.getPrototypeOf(e);function Fr(e,t,s){return function(...n){const o=this.__v_raw,r=G(o),i=wt(r),l=e==="entries"||e===Symbol.iterator&&i,a=e==="keys"&&i,p=o[e](...n),u=s?Ks:t?Tt:Me;return!t&&he(r,"iterate",a?Bs:ht),fe(Object.create(p),{next(){const{value:d,done:g}=p.next();return g?{value:d,done:g}:{value:l?[u(d[0]),u(d[1])]:u(d),done:g}}})}}function os(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function Hr(e,t){const s={get(o){const r=this.__v_raw,i=G(r),l=G(o);e||(Ve(o,l)&&he(i,"get",o),he(i,"get",l));const{has:a}=ns(i),p=t?Ks:e?Tt:Me;if(a.call(i,o))return p(r.get(o));if(a.call(i,l))return p(r.get(l));r!==i&&r.get(o)},get size(){const o=this.__v_raw;return!e&&he(G(o),"iterate",ht),o.size},has(o){const r=this.__v_raw,i=G(r),l=G(o);return e||(Ve(o,l)&&he(i,"has",o),he(i,"has",l)),o===l?r.has(o):r.has(o)||r.has(l)},forEach(o,r){const i=this,l=i.__v_raw,a=G(l),p=t?Ks:e?Tt:Me;return!e&&he(a,"iterate",ht),l.forEach((u,d)=>o.call(r,p(u),p(d),i))}};return fe(s,e?{add:os("add"),set:os("set"),delete:os("delete"),clear:os("clear")}:{add(o){const r=G(this),i=ns(r),l=G(o),a=!t&&!Pe(o)&&!st(o)?l:o;return i.has.call(r,a)||Ve(o,a)&&i.has.call(r,o)||Ve(l,a)&&i.has.call(r,l)||(r.add(a),Ze(r,"add",a,a)),this},set(o,r){!t&&!Pe(r)&&!st(r)&&(r=G(r));const i=G(this),{has:l,get:a}=ns(i);let p=l.call(i,o);p||(o=G(o),p=l.call(i,o));const u=a.call(i,o);return i.set(o,r),p?Ve(r,u)&&Ze(i,"set",o,r):Ze(i,"add",o,r),this},delete(o){const r=G(this),{has:i,get:l}=ns(r);let a=i.call(r,o);a||(o=G(o),a=i.call(r,o)),l&&l.call(r,o);const p=r.delete(o);return a&&Ze(r,"delete",o,void 0),p},clear(){const o=G(this),r=o.size!==0,i=o.clear();return r&&Ze(o,"clear",void 0,void 0),i}}),["keys","values","entries",Symbol.iterator].forEach(o=>{s[o]=Fr(o,e,t)}),s}function an(e,t){const s=Hr(e,t);return(n,o,r)=>o==="__v_isReactive"?!e:o==="__v_isReadonly"?e:o==="__v_raw"?n:Reflect.get(Y(s,o)&&o in n?s:n,o,r)}const Vr={get:an(!1,!1)},Ur={get:an(!1,!0)},Br={get:an(!0,!1)};const $o=new WeakMap,Eo=new WeakMap,ko=new WeakMap,Kr=new WeakMap;function Wr(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function zr(e){return e.__v_skip||!Object.isExtensible(e)?0:Wr(xr(e))}function cn(e){return st(e)?e:un(e,!1,Lr,Vr,$o)}function qr(e){return un(e,!1,jr,Ur,Eo)}function Ws(e){return un(e,!0,Nr,Br,ko)}function un(e,t,s,n,o){if(!Q(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const r=zr(e);if(r===0)return e;const i=o.get(e);if(i)return i;const l=new Proxy(e,r===2?n:s);return o.set(e,l),l}function mt(e){return st(e)?mt(e.__v_raw):!!(e&&e.__v_isReactive)}function st(e){return!!(e&&e.__v_isReadonly)}function Pe(e){return!!(e&&e.__v_isShallow)}function fn(e){return e?!!e.__v_raw:!1}function G(e){const t=e&&e.__v_raw;return t?G(t):e}function Jr(e){return!Y(e,"__v_skip")&&Object.isExtensible(e)&&uo(e,"__v_skip",!0),e}const Me=e=>Q(e)?cn(e):e,Tt=e=>Q(e)?Ws(e):e;function ge(e){return e?e.__v_isRef===!0:!1}function V(e){return Gr(e,!1)}function Gr(e,t){return ge(e)?e:new Yr(e,t)}class Yr{constructor(t,s){this.dep=new ln,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=s?t:G(t),this._value=s?t:Me(t),this.__v_isShallow=s}get value(){return this.dep.track(),this._value}set value(t){const s=this._rawValue,n=this.__v_isShallow||Pe(t)||st(t);t=n?t:G(t),Ve(t,s)&&(this._rawValue=t,this._value=n?t:Me(t),this.dep.trigger())}}function Zr(e){return ge(e)?e.value:e}const Qr={get:(e,t,s)=>t==="__v_raw"?e:Zr(Reflect.get(e,t,s)),set:(e,t,s,n)=>{const o=e[t];return ge(o)&&!ge(s)?(o.value=s,!0):Reflect.set(e,t,s,n)}};function Po(e){return mt(e)?e:new Proxy(e,Qr)}class Xr{constructor(t,s,n){this.fn=t,this.setter=s,this._value=void 0,this.dep=new ln(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=Wt-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!s,this.isSSR=n}notify(){if(this.flags|=16,!(this.flags&8)&&ne!==this)return xo(this,!0),!0}get value(){const t=this.dep.track();return bo(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function ei(e,t,s=!1){let n,o;return B(e)?n=e:(n=e.get,o=e.set),new Xr(n,o,s)}const rs={},ds=new WeakMap;let pt;function ti(e,t=!1,s=pt){if(s){let n=ds.get(s);n||ds.set(s,n=[]),n.push(e)}}function si(e,t,s=ee){const{immediate:n,deep:o,once:r,scheduler:i,augmentJob:l,call:a}=s,p=M=>o?M:Pe(M)||o===!1||o===0?Qe(M,1):Qe(M);let u,d,g,C,K=!1,I=!1;if(ge(e)?(d=()=>e.value,K=Pe(e)):mt(e)?(d=()=>p(e),K=!0):j(e)?(I=!0,K=e.some(M=>mt(M)||Pe(M)),d=()=>e.map(M=>{if(ge(M))return M.value;if(mt(M))return p(M);if(B(M))return a?a(M,2):M()})):B(e)?t?d=a?()=>a(e,2):e:d=()=>{if(g){et();try{g()}finally{tt()}}const M=pt;pt=u;try{return a?a(e,3,[C]):e(C)}finally{pt=M}}:d=Be,t&&o){const M=d,R=o===!0?1/0:o;d=()=>Qe(M(),R)}const W=kr(),A=()=>{u.stop(),W&&W.active&&en(W.effects,u)};if(r&&t){const M=t;t=(...R)=>{M(...R),A()}}let F=I?new Array(e.length).fill(rs):rs;const z=M=>{if(!(!(u.flags&1)||!u.dirty&&!M))if(t){const R=u.run();if(o||K||(I?R.some((P,L)=>Ve(P,F[L])):Ve(R,F))){g&&g();const P=pt;pt=u;try{const L=[R,F===rs?void 0:I&&F[0]===rs?[]:F,C];F=R,a?a(t,3,L):t(...L)}finally{pt=P}}}else u.run()};return l&&l(z),u=new mo(d),u.scheduler=i?()=>i(z,!1):z,C=M=>ti(M,!1,u),g=u.onStop=()=>{const M=ds.get(u);if(M){if(a)a(M,4);else for(const R of M)R();ds.delete(u)}},t?n?z(!0):F=u.run():i?i(z.bind(null,!0),!0):u.run(),A.pause=u.pause.bind(u),A.resume=u.resume.bind(u),A.stop=A,A}function Qe(e,t=1/0,s){if(t<=0||!Q(e)||e.__v_skip||(s=s||new Map,(s.get(e)||0)>=t))return e;if(s.set(e,t),t--,ge(e))Qe(e.value,t,s);else if(j(e))for(let n=0;n<e.length;n++)Qe(e[n],t,s);else if(Pt(e)||wt(e))e.forEach(n=>{Qe(n,t,s)});else if(co(e)){for(const n in e)Qe(e[n],t,s);for(const n of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,n)&&Qe(e[n],t,s)}return e}/**
|
|
77
|
+
* @vue/runtime-core v3.5.31
|
|
78
|
+
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
|
79
|
+
* @license MIT
|
|
80
|
+
**/function Xt(e,t,s,n){try{return n?e(...n):e()}catch(o){Ts(o,t,s)}}function ze(e,t,s,n){if(B(e)){const o=Xt(e,t,s,n);return o&&lo(o)&&o.catch(r=>{Ts(r,t,s)}),o}if(j(e)){const o=[];for(let r=0;r<e.length;r++)o.push(ze(e[r],t,s,n));return o}}function Ts(e,t,s,n=!0){const o=t?t.vnode:null,{errorHandler:r,throwUnhandledErrorInProduction:i}=t&&t.appContext.config||ee;if(t){let l=t.parent;const a=t.proxy,p=`https://vuejs.org/error-reference/#runtime-${s}`;for(;l;){const u=l.ec;if(u){for(let d=0;d<u.length;d++)if(u[d](e,a,p)===!1)return}l=l.parent}if(r){et(),Xt(r,null,10,[e,a,p]),tt();return}}ni(e,s,o,n,i)}function ni(e,t,s,n=!0,o=!1){if(o)throw e;console.error(e)}const ve=[];let Ne=-1;const St=[];let rt=null,yt=0;const Ao=Promise.resolve();let ps=null;function Mo(e){const t=ps||Ao;return e?t.then(this?e.bind(this):e):t}function oi(e){let t=Ne+1,s=ve.length;for(;t<s;){const n=t+s>>>1,o=ve[n],r=qt(o);r<e||r===e&&o.flags&2?t=n+1:s=n}return t}function dn(e){if(!(e.flags&1)){const t=qt(e),s=ve[ve.length-1];!s||!(e.flags&2)&&t>=qt(s)?ve.push(e):ve.splice(oi(t),0,e),e.flags|=1,Oo()}}function Oo(){ps||(ps=Ao.then(Ro))}function ri(e){j(e)?St.push(...e):rt&&e.id===-1?rt.splice(yt+1,0,e):e.flags&1||(St.push(e),e.flags|=1),Oo()}function kn(e,t,s=Ne+1){for(;s<ve.length;s++){const n=ve[s];if(n&&n.flags&2){if(e&&n.id!==e.uid)continue;ve.splice(s,1),s--,n.flags&4&&(n.flags&=-2),n(),n.flags&4||(n.flags&=-2)}}}function Io(e){if(St.length){const t=[...new Set(St)].sort((s,n)=>qt(s)-qt(n));if(St.length=0,rt){rt.push(...t);return}for(rt=t,yt=0;yt<rt.length;yt++){const s=rt[yt];s.flags&4&&(s.flags&=-2),s.flags&8||s(),s.flags&=-2}rt=null,yt=0}}const qt=e=>e.id==null?e.flags&2?-1:1/0:e.id;function Ro(e){try{for(Ne=0;Ne<ve.length;Ne++){const t=ve[Ne];t&&!(t.flags&8)&&(t.flags&4&&(t.flags&=-2),Xt(t,t.i,t.i?15:14),t.flags&4||(t.flags&=-2))}}finally{for(;Ne<ve.length;Ne++){const t=ve[Ne];t&&(t.flags&=-2)}Ne=-1,ve.length=0,Io(),ps=null,(ve.length||St.length)&&Ro()}}let $e=null,Do=null;function hs(e){const t=$e;return $e=e,Do=e&&e.type.__scopeId||null,t}function ii(e,t=$e,s){if(!t||e._n)return e;const n=(...o)=>{n._d&&Hn(-1);const r=hs(t);let i;try{i=e(...o)}finally{hs(r),n._d&&Hn(1)}return i};return n._n=!0,n._c=!0,n._d=!0,n}function ye(e,t){if($e===null)return e;const s=Ps($e),n=e.dirs||(e.dirs=[]);for(let o=0;o<t.length;o++){let[r,i,l,a=ee]=t[o];r&&(B(r)&&(r={mounted:r,updated:r}),r.deep&&Qe(i),n.push({dir:r,instance:s,value:i,oldValue:void 0,arg:l,modifiers:a}))}return e}function ft(e,t,s,n){const o=e.dirs,r=t&&t.dirs;for(let i=0;i<o.length;i++){const l=o[i];r&&(l.oldValue=r[i].value);let a=l.dir[n];a&&(et(),ze(a,s,8,[e.el,l,e,t]),tt())}}function li(e,t){if(me){let s=me.provides;const n=me.parent&&me.parent.provides;n===s&&(s=me.provides=Object.create(n)),s[e]=t}}function as(e,t,s=!1){const n=ll();if(n||Ct){let o=Ct?Ct._context.provides:n?n.parent==null||n.ce?n.vnode.appContext&&n.vnode.appContext.provides:n.parent.provides:void 0;if(o&&e in o)return o[e];if(arguments.length>1)return s&&B(t)?t.call(n&&n.proxy):t}}const ai=Symbol.for("v-scx"),ci=()=>as(ai);function Ls(e,t,s){return Lo(e,t,s)}function Lo(e,t,s=ee){const{immediate:n,deep:o,flush:r,once:i}=s,l=fe({},s),a=t&&n||!t&&r!=="post";let p;if(Gt){if(r==="sync"){const C=ci();p=C.__watcherHandles||(C.__watcherHandles=[])}else if(!a){const C=()=>{};return C.stop=Be,C.resume=Be,C.pause=Be,C}}const u=me;l.call=(C,K,I)=>ze(C,u,K,I);let d=!1;r==="post"?l.scheduler=C=>{_e(C,u&&u.suspense)}:r!=="sync"&&(d=!0,l.scheduler=(C,K)=>{K?C():dn(C)}),l.augmentJob=C=>{t&&(C.flags|=4),d&&(C.flags|=2,u&&(C.id=u.uid,C.i=u))};const g=si(e,t,l);return Gt&&(p?p.push(g):a&&g()),g}function ui(e,t,s){const n=this.proxy,o=ie(e)?e.includes(".")?No(n,e):()=>n[e]:e.bind(n,n);let r;B(t)?r=t:(r=t.handler,s=t);const i=es(this),l=Lo(o,r.bind(n),s);return i(),l}function No(e,t){const s=t.split(".");return()=>{let n=e;for(let o=0;o<s.length&&n;o++)n=n[s[o]];return n}}const fi=Symbol("_vte"),di=e=>e.__isTeleport,pi=Symbol("_leaveCb");function pn(e,t){e.shapeFlag&6&&e.component?(e.transition=t,pn(e.component.subTree,t)):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function gt(e,t){return B(e)?fe({name:e.name},t,{setup:e}):e}function jo(e){e.ids=[e.ids[0]+e.ids[2]+++"-",0,0]}function Pn(e,t){let s;return!!((s=Object.getOwnPropertyDescriptor(e,t))&&!s.configurable)}const ms=new WeakMap;function Vt(e,t,s,n,o=!1){if(j(e)){e.forEach((I,W)=>Vt(I,t&&(j(t)?t[W]:t),s,n,o));return}if(Ut(n)&&!o){n.shapeFlag&512&&n.type.__asyncResolved&&n.component.subTree.component&&Vt(e,t,s,n.component.subTree);return}const r=n.shapeFlag&4?Ps(n.component):n.el,i=o?null:r,{i:l,r:a}=e,p=t&&t.r,u=l.refs===ee?l.refs={}:l.refs,d=l.setupState,g=G(d),C=d===ee?io:I=>Pn(u,I)?!1:Y(g,I),K=(I,W)=>!(W&&Pn(u,W));if(p!=null&&p!==a){if(An(t),ie(p))u[p]=null,C(p)&&(d[p]=null);else if(ge(p)){const I=t;K(p,I.k)&&(p.value=null),I.k&&(u[I.k]=null)}}if(B(a))Xt(a,l,12,[i,u]);else{const I=ie(a),W=ge(a);if(I||W){const A=()=>{if(e.f){const F=I?C(a)?d[a]:u[a]:K()||!e.k?a.value:u[e.k];if(o)j(F)&&en(F,r);else if(j(F))F.includes(r)||F.push(r);else if(I)u[a]=[r],C(a)&&(d[a]=u[a]);else{const z=[r];K(a,e.k)&&(a.value=z),e.k&&(u[e.k]=z)}}else I?(u[a]=i,C(a)&&(d[a]=i)):W&&(K(a,e.k)&&(a.value=i),e.k&&(u[e.k]=i))};if(i){const F=()=>{A(),ms.delete(e)};F.id=-1,ms.set(e,F),_e(F,s)}else An(e),A()}}}function An(e){const t=ms.get(e);t&&(t.flags|=8,ms.delete(e))}Ss().requestIdleCallback;Ss().cancelIdleCallback;const Ut=e=>!!e.type.__asyncLoader,Fo=e=>e.type.__isKeepAlive;function hi(e,t){Ho(e,"a",t)}function mi(e,t){Ho(e,"da",t)}function Ho(e,t,s=me){const n=e.__wdc||(e.__wdc=()=>{let o=s;for(;o;){if(o.isDeactivated)return;o=o.parent}return e()});if($s(t,n,s),s){let o=s.parent;for(;o&&o.parent;)Fo(o.parent.vnode)&&gi(n,t,s,o),o=o.parent}}function gi(e,t,s,n){const o=$s(t,e,n,!0);hn(()=>{en(n[t],o)},s)}function $s(e,t,s=me,n=!1){if(s){const o=s[e]||(s[e]=[]),r=t.__weh||(t.__weh=(...i)=>{et();const l=es(s),a=ze(t,s,e,i);return l(),tt(),a});return n?o.unshift(r):o.push(r),r}}const ot=e=>(t,s=me)=>{(!Gt||e==="sp")&&$s(e,(...n)=>t(...n),s)},xi=ot("bm"),xt=ot("m"),vi=ot("bu"),yi=ot("u"),bi=ot("bum"),hn=ot("um"),_i=ot("sp"),wi=ot("rtg"),Si=ot("rtc");function Ci(e,t=me){$s("ec",e,t)}const Ti="components",Vo=Symbol.for("v-ndc");function $i(e){return ie(e)?Ei(Ti,e,!1)||e:e||Vo}function Ei(e,t,s=!0,n=!1){const o=$e||me;if(o){const r=o.type;{const l=dl(r,!1);if(l&&(l===t||l===be(t)||l===_s(be(t))))return r}const i=Mn(o[e]||r[e],t)||Mn(o.appContext[e],t);return!i&&n?r:i}}function Mn(e,t){return e&&(e[t]||e[be(t)]||e[_s(be(t))])}function nt(e,t,s,n){let o;const r=s,i=j(e);if(i||ie(e)){const l=i&&mt(e);let a=!1,p=!1;l&&(a=!Pe(e),p=st(e),e=Cs(e)),o=new Array(e.length);for(let u=0,d=e.length;u<d;u++)o[u]=t(a?p?Tt(Me(e[u])):Me(e[u]):e[u],u,void 0,r)}else if(typeof e=="number"){o=new Array(e);for(let l=0;l<e;l++)o[l]=t(l+1,l,void 0,r)}else if(Q(e))if(e[Symbol.iterator])o=Array.from(e,(l,a)=>t(l,a,void 0,r));else{const l=Object.keys(e);o=new Array(l.length);for(let a=0,p=l.length;a<p;a++){const u=l[a];o[a]=t(e[u],u,a,r)}}else o=[];return o}const zs=e=>e?ur(e)?Ps(e):zs(e.parent):null,Bt=fe(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>zs(e.parent),$root:e=>zs(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>Bo(e),$forceUpdate:e=>e.f||(e.f=()=>{dn(e.update)}),$nextTick:e=>e.n||(e.n=Mo.bind(e.proxy)),$watch:e=>ui.bind(e)}),Ns=(e,t)=>e!==ee&&!e.__isScriptSetup&&Y(e,t),ki={get({_:e},t){if(t==="__v_skip")return!0;const{ctx:s,setupState:n,data:o,props:r,accessCache:i,type:l,appContext:a}=e;if(t[0]!=="$"){const g=i[t];if(g!==void 0)switch(g){case 1:return n[t];case 2:return o[t];case 4:return s[t];case 3:return r[t]}else{if(Ns(n,t))return i[t]=1,n[t];if(o!==ee&&Y(o,t))return i[t]=2,o[t];if(Y(r,t))return i[t]=3,r[t];if(s!==ee&&Y(s,t))return i[t]=4,s[t];qs&&(i[t]=0)}}const p=Bt[t];let u,d;if(p)return t==="$attrs"&&he(e.attrs,"get",""),p(e);if((u=l.__cssModules)&&(u=u[t]))return u;if(s!==ee&&Y(s,t))return i[t]=4,s[t];if(d=a.config.globalProperties,Y(d,t))return d[t]},set({_:e},t,s){const{data:n,setupState:o,ctx:r}=e;return Ns(o,t)?(o[t]=s,!0):n!==ee&&Y(n,t)?(n[t]=s,!0):Y(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(r[t]=s,!0)},has({_:{data:e,setupState:t,accessCache:s,ctx:n,appContext:o,props:r,type:i}},l){let a;return!!(s[l]||e!==ee&&l[0]!=="$"&&Y(e,l)||Ns(t,l)||Y(r,l)||Y(n,l)||Y(Bt,l)||Y(o.config.globalProperties,l)||(a=i.__cssModules)&&a[l])},defineProperty(e,t,s){return s.get!=null?e._.accessCache[t]=0:Y(s,"value")&&this.set(e,t,s.value,null),Reflect.defineProperty(e,t,s)}};function On(e){return j(e)?e.reduce((t,s)=>(t[s]=null,t),{}):e}let qs=!0;function Pi(e){const t=Bo(e),s=e.proxy,n=e.ctx;qs=!1,t.beforeCreate&&In(t.beforeCreate,e,"bc");const{data:o,computed:r,methods:i,watch:l,provide:a,inject:p,created:u,beforeMount:d,mounted:g,beforeUpdate:C,updated:K,activated:I,deactivated:W,beforeDestroy:A,beforeUnmount:F,destroyed:z,unmounted:M,render:R,renderTracked:P,renderTriggered:L,errorCaptured:oe,serverPrefetch:Z,expose:ce,inheritAttrs:ke,components:qe,directives:Ce,filters:U}=t;if(p&&Ai(p,n,null),i)for(const re in i){const te=i[re];B(te)&&(n[re]=te.bind(s))}if(o){const re=o.call(s,s);Q(re)&&(e.data=cn(re))}if(qs=!0,r)for(const re in r){const te=r[re],ct=B(te)?te.bind(s,s):B(te.get)?te.get.bind(s,s):Be,ts=!B(te)&&B(te.set)?te.set.bind(s):Be,ut=Et({get:ct,set:ts});Object.defineProperty(n,re,{enumerable:!0,configurable:!0,get:()=>ut.value,set:Oe=>ut.value=Oe})}if(l)for(const re in l)Uo(l[re],n,s,re);if(a){const re=B(a)?a.call(s):a;Reflect.ownKeys(re).forEach(te=>{li(te,re[te])})}u&&In(u,e,"c");function J(re,te){j(te)?te.forEach(ct=>re(ct.bind(s))):te&&re(te.bind(s))}if(J(xi,d),J(xt,g),J(vi,C),J(yi,K),J(hi,I),J(mi,W),J(Ci,oe),J(Si,P),J(wi,L),J(bi,F),J(hn,M),J(_i,Z),j(ce))if(ce.length){const re=e.exposed||(e.exposed={});ce.forEach(te=>{Object.defineProperty(re,te,{get:()=>s[te],set:ct=>s[te]=ct,enumerable:!0})})}else e.exposed||(e.exposed={});R&&e.render===Be&&(e.render=R),ke!=null&&(e.inheritAttrs=ke),qe&&(e.components=qe),Ce&&(e.directives=Ce),Z&&jo(e)}function Ai(e,t,s=Be){j(e)&&(e=Js(e));for(const n in e){const o=e[n];let r;Q(o)?"default"in o?r=as(o.from||n,o.default,!0):r=as(o.from||n):r=as(o),ge(r)?Object.defineProperty(t,n,{enumerable:!0,configurable:!0,get:()=>r.value,set:i=>r.value=i}):t[n]=r}}function In(e,t,s){ze(j(e)?e.map(n=>n.bind(t.proxy)):e.bind(t.proxy),t,s)}function Uo(e,t,s,n){let o=n.includes(".")?No(s,n):()=>s[n];if(ie(e)){const r=t[e];B(r)&&Ls(o,r)}else if(B(e))Ls(o,e.bind(s));else if(Q(e))if(j(e))e.forEach(r=>Uo(r,t,s,n));else{const r=B(e.handler)?e.handler.bind(s):t[e.handler];B(r)&&Ls(o,r,e)}}function Bo(e){const t=e.type,{mixins:s,extends:n}=t,{mixins:o,optionsCache:r,config:{optionMergeStrategies:i}}=e.appContext,l=r.get(t);let a;return l?a=l:!o.length&&!s&&!n?a=t:(a={},o.length&&o.forEach(p=>gs(a,p,i,!0)),gs(a,t,i)),Q(t)&&r.set(t,a),a}function gs(e,t,s,n=!1){const{mixins:o,extends:r}=t;r&&gs(e,r,s,!0),o&&o.forEach(i=>gs(e,i,s,!0));for(const i in t)if(!(n&&i==="expose")){const l=Mi[i]||s&&s[i];e[i]=l?l(e[i],t[i]):t[i]}return e}const Mi={data:Rn,props:Dn,emits:Dn,methods:Nt,computed:Nt,beforeCreate:xe,created:xe,beforeMount:xe,mounted:xe,beforeUpdate:xe,updated:xe,beforeDestroy:xe,beforeUnmount:xe,destroyed:xe,unmounted:xe,activated:xe,deactivated:xe,errorCaptured:xe,serverPrefetch:xe,components:Nt,directives:Nt,watch:Ii,provide:Rn,inject:Oi};function Rn(e,t){return t?e?function(){return fe(B(e)?e.call(this,this):e,B(t)?t.call(this,this):t)}:t:e}function Oi(e,t){return Nt(Js(e),Js(t))}function Js(e){if(j(e)){const t={};for(let s=0;s<e.length;s++)t[e[s]]=e[s];return t}return e}function xe(e,t){return e?[...new Set([].concat(e,t))]:t}function Nt(e,t){return e?fe(Object.create(null),e,t):t}function Dn(e,t){return e?j(e)&&j(t)?[...new Set([...e,...t])]:fe(Object.create(null),On(e),On(t??{})):t}function Ii(e,t){if(!e)return t;if(!t)return e;const s=fe(Object.create(null),e);for(const n in t)s[n]=xe(e[n],t[n]);return s}function Ko(){return{app:null,config:{isNativeTag:io,performance:!1,globalProperties:{},optionMergeStrategies:{},errorHandler:void 0,warnHandler:void 0,compilerOptions:{}},mixins:[],components:{},directives:{},provides:Object.create(null),optionsCache:new WeakMap,propsCache:new WeakMap,emitsCache:new WeakMap}}let Ri=0;function Di(e,t){return function(n,o=null){B(n)||(n=fe({},n)),o!=null&&!Q(o)&&(o=null);const r=Ko(),i=new WeakSet,l=[];let a=!1;const p=r.app={_uid:Ri++,_component:n,_props:o,_container:null,_context:r,_instance:null,version:hl,get config(){return r.config},set config(u){},use(u,...d){return i.has(u)||(u&&B(u.install)?(i.add(u),u.install(p,...d)):B(u)&&(i.add(u),u(p,...d))),p},mixin(u){return r.mixins.includes(u)||r.mixins.push(u),p},component(u,d){return d?(r.components[u]=d,p):r.components[u]},directive(u,d){return d?(r.directives[u]=d,p):r.directives[u]},mount(u,d,g){if(!a){const C=p._ceVNode||Ke(n,o);return C.appContext=r,g===!0?g="svg":g===!1&&(g=void 0),e(C,u,g),a=!0,p._container=u,u.__vue_app__=p,Ps(C.component)}},onUnmount(u){l.push(u)},unmount(){a&&(ze(l,p._instance,16),e(null,p._container),delete p._container.__vue_app__)},provide(u,d){return r.provides[u]=d,p},runWithContext(u){const d=Ct;Ct=p;try{return u()}finally{Ct=d}}};return p}}let Ct=null;const Li=(e,t)=>t==="modelValue"||t==="model-value"?e.modelModifiers:e[`${t}Modifiers`]||e[`${be(t)}Modifiers`]||e[`${at(t)}Modifiers`];function Ni(e,t,...s){if(e.isUnmounted)return;const n=e.vnode.props||ee;let o=s;const r=t.startsWith("update:"),i=r&&Li(n,t.slice(7));i&&(i.trim&&(o=s.map(u=>ie(u)?u.trim():u)),i.number&&(o=s.map(ws)));let l,a=n[l=Ms(t)]||n[l=Ms(be(t))];!a&&r&&(a=n[l=Ms(at(t))]),a&&ze(a,e,6,o);const p=n[l+"Once"];if(p){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,ze(p,e,6,o)}}const ji=new WeakMap;function Wo(e,t,s=!1){const n=s?ji:t.emitsCache,o=n.get(e);if(o!==void 0)return o;const r=e.emits;let i={},l=!1;if(!B(e)){const a=p=>{const u=Wo(p,t,!0);u&&(l=!0,fe(i,u))};!s&&t.mixins.length&&t.mixins.forEach(a),e.extends&&a(e.extends),e.mixins&&e.mixins.forEach(a)}return!r&&!l?(Q(e)&&n.set(e,null),null):(j(r)?r.forEach(a=>i[a]=null):fe(i,r),Q(e)&&n.set(e,i),i)}function Es(e,t){return!e||!vs(t)?!1:(t=t.slice(2).replace(/Once$/,""),Y(e,t[0].toLowerCase()+t.slice(1))||Y(e,at(t))||Y(e,t))}function Ln(e){const{type:t,vnode:s,proxy:n,withProxy:o,propsOptions:[r],slots:i,attrs:l,emit:a,render:p,renderCache:u,props:d,data:g,setupState:C,ctx:K,inheritAttrs:I}=e,W=hs(e);let A,F;try{if(s.shapeFlag&4){const M=o||n,R=M;A=He(p.call(R,M,u,d,C,g,K)),F=l}else{const M=t;A=He(M.length>1?M(d,{attrs:l,slots:i,emit:a}):M(d,null)),F=t.props?l:Fi(l)}}catch(M){Kt.length=0,Ts(M,e,1),A=Ke(lt)}let z=A;if(F&&I!==!1){const M=Object.keys(F),{shapeFlag:R}=z;M.length&&R&7&&(r&&M.some(ys)&&(F=Hi(F,r)),z=$t(z,F,!1,!0))}return s.dirs&&(z=$t(z,null,!1,!0),z.dirs=z.dirs?z.dirs.concat(s.dirs):s.dirs),s.transition&&pn(z,s.transition),A=z,hs(W),A}const Fi=e=>{let t;for(const s in e)(s==="class"||s==="style"||vs(s))&&((t||(t={}))[s]=e[s]);return t},Hi=(e,t)=>{const s={};for(const n in e)(!ys(n)||!(n.slice(9)in t))&&(s[n]=e[n]);return s};function Vi(e,t,s){const{props:n,children:o,component:r}=e,{props:i,children:l,patchFlag:a}=t,p=r.emitsOptions;if(t.dirs||t.transition)return!0;if(s&&a>=0){if(a&1024)return!0;if(a&16)return n?Nn(n,i,p):!!i;if(a&8){const u=t.dynamicProps;for(let d=0;d<u.length;d++){const g=u[d];if(zo(i,n,g)&&!Es(p,g))return!0}}}else return(o||l)&&(!l||!l.$stable)?!0:n===i?!1:n?i?Nn(n,i,p):!0:!!i;return!1}function Nn(e,t,s){const n=Object.keys(t);if(n.length!==Object.keys(e).length)return!0;for(let o=0;o<n.length;o++){const r=n[o];if(zo(t,e,r)&&!Es(s,r))return!0}return!1}function zo(e,t,s){const n=e[s],o=t[s];return s==="style"&&Q(n)&&Q(o)?!At(n,o):n!==o}function Ui({vnode:e,parent:t,suspense:s},n){for(;t;){const o=t.subTree;if(o.suspense&&o.suspense.activeBranch===e&&(o.suspense.vnode.el=o.el=n,e=o),o===e)(e=t.vnode).el=n,t=t.parent;else break}s&&s.activeBranch===e&&(s.vnode.el=n)}const qo={},Jo=()=>Object.create(qo),Go=e=>Object.getPrototypeOf(e)===qo;function Bi(e,t,s,n=!1){const o={},r=Jo();e.propsDefaults=Object.create(null),Yo(e,t,o,r);for(const i in e.propsOptions[0])i in o||(o[i]=void 0);s?e.props=n?o:qr(o):e.type.props?e.props=o:e.props=r,e.attrs=r}function Ki(e,t,s,n){const{props:o,attrs:r,vnode:{patchFlag:i}}=e,l=G(o),[a]=e.propsOptions;let p=!1;if((n||i>0)&&!(i&16)){if(i&8){const u=e.vnode.dynamicProps;for(let d=0;d<u.length;d++){let g=u[d];if(Es(e.emitsOptions,g))continue;const C=t[g];if(a)if(Y(r,g))C!==r[g]&&(r[g]=C,p=!0);else{const K=be(g);o[K]=Gs(a,l,K,C,e,!1)}else C!==r[g]&&(r[g]=C,p=!0)}}}else{Yo(e,t,o,r)&&(p=!0);let u;for(const d in l)(!t||!Y(t,d)&&((u=at(d))===d||!Y(t,u)))&&(a?s&&(s[d]!==void 0||s[u]!==void 0)&&(o[d]=Gs(a,l,d,void 0,e,!0)):delete o[d]);if(r!==l)for(const d in r)(!t||!Y(t,d))&&(delete r[d],p=!0)}p&&Ze(e.attrs,"set","")}function Yo(e,t,s,n){const[o,r]=e.propsOptions;let i=!1,l;if(t)for(let a in t){if(jt(a))continue;const p=t[a];let u;o&&Y(o,u=be(a))?!r||!r.includes(u)?s[u]=p:(l||(l={}))[u]=p:Es(e.emitsOptions,a)||(!(a in n)||p!==n[a])&&(n[a]=p,i=!0)}if(r){const a=G(s),p=l||ee;for(let u=0;u<r.length;u++){const d=r[u];s[d]=Gs(o,a,d,p[d],e,!Y(p,d))}}return i}function Gs(e,t,s,n,o,r){const i=e[s];if(i!=null){const l=Y(i,"default");if(l&&n===void 0){const a=i.default;if(i.type!==Function&&!i.skipFactory&&B(a)){const{propsDefaults:p}=o;if(s in p)n=p[s];else{const u=es(o);n=p[s]=a.call(null,t),u()}}else n=a;o.ce&&o.ce._setProp(s,n)}i[0]&&(r&&!l?n=!1:i[1]&&(n===""||n===at(s))&&(n=!0))}return n}const Wi=new WeakMap;function Zo(e,t,s=!1){const n=s?Wi:t.propsCache,o=n.get(e);if(o)return o;const r=e.props,i={},l=[];let a=!1;if(!B(e)){const u=d=>{a=!0;const[g,C]=Zo(d,t,!0);fe(i,g),C&&l.push(...C)};!s&&t.mixins.length&&t.mixins.forEach(u),e.extends&&u(e.extends),e.mixins&&e.mixins.forEach(u)}if(!r&&!a)return Q(e)&&n.set(e,_t),_t;if(j(r))for(let u=0;u<r.length;u++){const d=be(r[u]);jn(d)&&(i[d]=ee)}else if(r)for(const u in r){const d=be(u);if(jn(d)){const g=r[u],C=i[d]=j(g)||B(g)?{type:g}:fe({},g),K=C.type;let I=!1,W=!0;if(j(K))for(let A=0;A<K.length;++A){const F=K[A],z=B(F)&&F.name;if(z==="Boolean"){I=!0;break}else z==="String"&&(W=!1)}else I=B(K)&&K.name==="Boolean";C[0]=I,C[1]=W,(I||Y(C,"default"))&&l.push(d)}}const p=[i,l];return Q(e)&&n.set(e,p),p}function jn(e){return e[0]!=="$"&&!jt(e)}const mn=e=>e==="_"||e==="_ctx"||e==="$stable",gn=e=>j(e)?e.map(He):[He(e)],zi=(e,t,s)=>{if(t._n)return t;const n=ii((...o)=>gn(t(...o)),s);return n._c=!1,n},Qo=(e,t,s)=>{const n=e._ctx;for(const o in e){if(mn(o))continue;const r=e[o];if(B(r))t[o]=zi(o,r,n);else if(r!=null){const i=gn(r);t[o]=()=>i}}},Xo=(e,t)=>{const s=gn(t);e.slots.default=()=>s},er=(e,t,s)=>{for(const n in t)(s||!mn(n))&&(e[n]=t[n])},qi=(e,t,s)=>{const n=e.slots=Jo();if(e.vnode.shapeFlag&32){const o=t._;o?(er(n,t,s),s&&uo(n,"_",o,!0)):Qo(t,n)}else t&&Xo(e,t)},Ji=(e,t,s)=>{const{vnode:n,slots:o}=e;let r=!0,i=ee;if(n.shapeFlag&32){const l=t._;l?s&&l===1?r=!1:er(o,t,s):(r=!t.$stable,Qo(t,o)),i=t}else t&&(Xo(e,t),i={default:1});if(r)for(const l in o)!mn(l)&&i[l]==null&&delete o[l]},_e=Xi;function Gi(e){return Yi(e)}function Yi(e,t){const s=Ss();s.__VUE__=!0;const{insert:n,remove:o,patchProp:r,createElement:i,createText:l,createComment:a,setText:p,setElementText:u,parentNode:d,nextSibling:g,setScopeId:C=Be,insertStaticContent:K}=e,I=(c,f,m,b=null,x=null,v=null,S=void 0,w=null,_=!!f.dynamicChildren)=>{if(c===f)return;c&&!Dt(c,f)&&(b=ss(c),Oe(c,x,v,!0),c=null),f.patchFlag===-2&&(_=!1,f.dynamicChildren=null);const{type:y,ref:D,shapeFlag:T}=f;switch(y){case ks:W(c,f,m,b);break;case lt:A(c,f,m,b);break;case cs:c==null&&F(f,m,b,S);break;case ae:qe(c,f,m,b,x,v,S,w,_);break;default:T&1?R(c,f,m,b,x,v,S,w,_):T&6?Ce(c,f,m,b,x,v,S,w,_):(T&64||T&128)&&y.process(c,f,m,b,x,v,S,w,_,Ot)}D!=null&&x?Vt(D,c&&c.ref,v,f||c,!f):D==null&&c&&c.ref!=null&&Vt(c.ref,null,v,c,!0)},W=(c,f,m,b)=>{if(c==null)n(f.el=l(f.children),m,b);else{const x=f.el=c.el;f.children!==c.children&&p(x,f.children)}},A=(c,f,m,b)=>{c==null?n(f.el=a(f.children||""),m,b):f.el=c.el},F=(c,f,m,b)=>{[c.el,c.anchor]=K(c.children,f,m,b,c.el,c.anchor)},z=({el:c,anchor:f},m,b)=>{let x;for(;c&&c!==f;)x=g(c),n(c,m,b),c=x;n(f,m,b)},M=({el:c,anchor:f})=>{let m;for(;c&&c!==f;)m=g(c),o(c),c=m;o(f)},R=(c,f,m,b,x,v,S,w,_)=>{if(f.type==="svg"?S="svg":f.type==="math"&&(S="mathml"),c==null)P(f,m,b,x,v,S,w,_);else{const y=c.el&&c.el._isVueCE?c.el:null;try{y&&y._beginPatch(),Z(c,f,x,v,S,w,_)}finally{y&&y._endPatch()}}},P=(c,f,m,b,x,v,S,w)=>{let _,y;const{props:D,shapeFlag:T,transition:O,dirs:H}=c;if(_=c.el=i(c.type,v,D&&D.is,D),T&8?u(_,c.children):T&16&&oe(c.children,_,null,b,x,js(c,v),S,w),H&&ft(c,null,b,"created"),L(_,c,c.scopeId,S,b),D){for(const X in D)X!=="value"&&!jt(X)&&r(_,X,null,D[X],v,b);"value"in D&&r(_,"value",null,D.value,v),(y=D.onVnodeBeforeMount)&&Le(y,b,c)}H&&ft(c,null,b,"beforeMount");const q=Zi(x,O);q&&O.beforeEnter(_),n(_,f,m),((y=D&&D.onVnodeMounted)||q||H)&&_e(()=>{try{y&&Le(y,b,c),q&&O.enter(_),H&&ft(c,null,b,"mounted")}finally{}},x)},L=(c,f,m,b,x)=>{if(m&&C(c,m),b)for(let v=0;v<b.length;v++)C(c,b[v]);if(x){let v=x.subTree;if(f===v||or(v.type)&&(v.ssContent===f||v.ssFallback===f)){const S=x.vnode;L(c,S,S.scopeId,S.slotScopeIds,x.parent)}}},oe=(c,f,m,b,x,v,S,w,_=0)=>{for(let y=_;y<c.length;y++){const D=c[y]=w?Ye(c[y]):He(c[y]);I(null,D,f,m,b,x,v,S,w)}},Z=(c,f,m,b,x,v,S)=>{const w=f.el=c.el;let{patchFlag:_,dynamicChildren:y,dirs:D}=f;_|=c.patchFlag&16;const T=c.props||ee,O=f.props||ee;let H;if(m&&dt(m,!1),(H=O.onVnodeBeforeUpdate)&&Le(H,m,f,c),D&&ft(f,c,m,"beforeUpdate"),m&&dt(m,!0),(T.innerHTML&&O.innerHTML==null||T.textContent&&O.textContent==null)&&u(w,""),y?ce(c.dynamicChildren,y,w,m,b,js(f,x),v):S||te(c,f,w,null,m,b,js(f,x),v,!1),_>0){if(_&16)ke(w,T,O,m,x);else if(_&2&&T.class!==O.class&&r(w,"class",null,O.class,x),_&4&&r(w,"style",T.style,O.style,x),_&8){const q=f.dynamicProps;for(let X=0;X<q.length;X++){const se=q[X],le=T[se],ue=O[se];(ue!==le||se==="value")&&r(w,se,le,ue,x,m)}}_&1&&c.children!==f.children&&u(w,f.children)}else!S&&y==null&&ke(w,T,O,m,x);((H=O.onVnodeUpdated)||D)&&_e(()=>{H&&Le(H,m,f,c),D&&ft(f,c,m,"updated")},b)},ce=(c,f,m,b,x,v,S)=>{for(let w=0;w<f.length;w++){const _=c[w],y=f[w],D=_.el&&(_.type===ae||!Dt(_,y)||_.shapeFlag&198)?d(_.el):m;I(_,y,D,null,b,x,v,S,!0)}},ke=(c,f,m,b,x)=>{if(f!==m){if(f!==ee)for(const v in f)!jt(v)&&!(v in m)&&r(c,v,f[v],null,x,b);for(const v in m){if(jt(v))continue;const S=m[v],w=f[v];S!==w&&v!=="value"&&r(c,v,w,S,x,b)}"value"in m&&r(c,"value",f.value,m.value,x)}},qe=(c,f,m,b,x,v,S,w,_)=>{const y=f.el=c?c.el:l(""),D=f.anchor=c?c.anchor:l("");let{patchFlag:T,dynamicChildren:O,slotScopeIds:H}=f;H&&(w=w?w.concat(H):H),c==null?(n(y,m,b),n(D,m,b),oe(f.children||[],m,D,x,v,S,w,_)):T>0&&T&64&&O&&c.dynamicChildren&&c.dynamicChildren.length===O.length?(ce(c.dynamicChildren,O,m,x,v,S,w),(f.key!=null||x&&f===x.subTree)&&tr(c,f,!0)):te(c,f,m,D,x,v,S,w,_)},Ce=(c,f,m,b,x,v,S,w,_)=>{f.slotScopeIds=w,c==null?f.shapeFlag&512?x.ctx.activate(f,m,b,S,_):U(f,m,b,x,v,S,_):E(c,f,_)},U=(c,f,m,b,x,v,S)=>{const w=c.component=il(c,b,x);if(Fo(c)&&(w.ctx.renderer=Ot),al(w,!1,S),w.asyncDep){if(x&&x.registerDep(w,J,S),!c.el){const _=w.subTree=Ke(lt);A(null,_,f,m),c.placeholder=_.el}}else J(w,c,f,m,x,v,S)},E=(c,f,m)=>{const b=f.component=c.component;if(Vi(c,f,m))if(b.asyncDep&&!b.asyncResolved){re(b,f,m);return}else b.next=f,b.update();else f.el=c.el,b.vnode=f},J=(c,f,m,b,x,v,S)=>{const w=()=>{if(c.isMounted){let{next:T,bu:O,u:H,parent:q,vnode:X}=c;{const Re=sr(c);if(Re){T&&(T.el=X.el,re(c,T,S)),Re.asyncDep.then(()=>{_e(()=>{c.isUnmounted||y()},x)});return}}let se=T,le;dt(c,!1),T?(T.el=X.el,re(c,T,S)):T=X,O&&ls(O),(le=T.props&&T.props.onVnodeBeforeUpdate)&&Le(le,q,T,X),dt(c,!0);const ue=Ln(c),Ie=c.subTree;c.subTree=ue,I(Ie,ue,d(Ie.el),ss(Ie),c,x,v),T.el=ue.el,se===null&&Ui(c,ue.el),H&&_e(H,x),(le=T.props&&T.props.onVnodeUpdated)&&_e(()=>Le(le,q,T,X),x)}else{let T;const{el:O,props:H}=f,{bm:q,m:X,parent:se,root:le,type:ue}=c,Ie=Ut(f);dt(c,!1),q&&ls(q),!Ie&&(T=H&&H.onVnodeBeforeMount)&&Le(T,se,f),dt(c,!0);{le.ce&&le.ce._hasShadowRoot()&&le.ce._injectChildStyle(ue,c.parent?c.parent.type:void 0);const Re=c.subTree=Ln(c);I(null,Re,m,b,c,x,v),f.el=Re.el}if(X&&_e(X,x),!Ie&&(T=H&&H.onVnodeMounted)){const Re=f;_e(()=>Le(T,se,Re),x)}(f.shapeFlag&256||se&&Ut(se.vnode)&&se.vnode.shapeFlag&256)&&c.a&&_e(c.a,x),c.isMounted=!0,f=m=b=null}};c.scope.on();const _=c.effect=new mo(w);c.scope.off();const y=c.update=_.run.bind(_),D=c.job=_.runIfDirty.bind(_);D.i=c,D.id=c.uid,_.scheduler=()=>dn(D),dt(c,!0),y()},re=(c,f,m)=>{f.component=c;const b=c.vnode.props;c.vnode=f,c.next=null,Ki(c,f.props,b,m),Ji(c,f.children,m),et(),kn(c),tt()},te=(c,f,m,b,x,v,S,w,_=!1)=>{const y=c&&c.children,D=c?c.shapeFlag:0,T=f.children,{patchFlag:O,shapeFlag:H}=f;if(O>0){if(O&128){ts(y,T,m,b,x,v,S,w,_);return}else if(O&256){ct(y,T,m,b,x,v,S,w,_);return}}H&8?(D&16&&Mt(y,x,v),T!==y&&u(m,T)):D&16?H&16?ts(y,T,m,b,x,v,S,w,_):Mt(y,x,v,!0):(D&8&&u(m,""),H&16&&oe(T,m,b,x,v,S,w,_))},ct=(c,f,m,b,x,v,S,w,_)=>{c=c||_t,f=f||_t;const y=c.length,D=f.length,T=Math.min(y,D);let O;for(O=0;O<T;O++){const H=f[O]=_?Ye(f[O]):He(f[O]);I(c[O],H,m,null,x,v,S,w,_)}y>D?Mt(c,x,v,!0,!1,T):oe(f,m,b,x,v,S,w,_,T)},ts=(c,f,m,b,x,v,S,w,_)=>{let y=0;const D=f.length;let T=c.length-1,O=D-1;for(;y<=T&&y<=O;){const H=c[y],q=f[y]=_?Ye(f[y]):He(f[y]);if(Dt(H,q))I(H,q,m,null,x,v,S,w,_);else break;y++}for(;y<=T&&y<=O;){const H=c[T],q=f[O]=_?Ye(f[O]):He(f[O]);if(Dt(H,q))I(H,q,m,null,x,v,S,w,_);else break;T--,O--}if(y>T){if(y<=O){const H=O+1,q=H<D?f[H].el:b;for(;y<=O;)I(null,f[y]=_?Ye(f[y]):He(f[y]),m,q,x,v,S,w,_),y++}}else if(y>O)for(;y<=T;)Oe(c[y],x,v,!0),y++;else{const H=y,q=y,X=new Map;for(y=q;y<=O;y++){const Te=f[y]=_?Ye(f[y]):He(f[y]);Te.key!=null&&X.set(Te.key,y)}let se,le=0;const ue=O-q+1;let Ie=!1,Re=0;const It=new Array(ue);for(y=0;y<ue;y++)It[y]=0;for(y=H;y<=T;y++){const Te=c[y];if(le>=ue){Oe(Te,x,v,!0);continue}let De;if(Te.key!=null)De=X.get(Te.key);else for(se=q;se<=O;se++)if(It[se-q]===0&&Dt(Te,f[se])){De=se;break}De===void 0?Oe(Te,x,v,!0):(It[De-q]=y+1,De>=Re?Re=De:Ie=!0,I(Te,f[De],m,null,x,v,S,w,_),le++)}const _n=Ie?Qi(It):_t;for(se=_n.length-1,y=ue-1;y>=0;y--){const Te=q+y,De=f[Te],wn=f[Te+1],Sn=Te+1<D?wn.el||nr(wn):b;It[y]===0?I(null,De,m,Sn,x,v,S,w,_):Ie&&(se<0||y!==_n[se]?ut(De,m,Sn,2):se--)}}},ut=(c,f,m,b,x=null)=>{const{el:v,type:S,transition:w,children:_,shapeFlag:y}=c;if(y&6){ut(c.component.subTree,f,m,b);return}if(y&128){c.suspense.move(f,m,b);return}if(y&64){S.move(c,f,m,Ot);return}if(S===ae){n(v,f,m);for(let T=0;T<_.length;T++)ut(_[T],f,m,b);n(c.anchor,f,m);return}if(S===cs){z(c,f,m);return}if(b!==2&&y&1&&w)if(b===0)w.beforeEnter(v),n(v,f,m),_e(()=>w.enter(v),x);else{const{leave:T,delayLeave:O,afterLeave:H}=w,q=()=>{c.ctx.isUnmounted?o(v):n(v,f,m)},X=()=>{v._isLeaving&&v[pi](!0),T(v,()=>{q(),H&&H()})};O?O(v,q,X):X()}else n(v,f,m)},Oe=(c,f,m,b=!1,x=!1)=>{const{type:v,props:S,ref:w,children:_,dynamicChildren:y,shapeFlag:D,patchFlag:T,dirs:O,cacheIndex:H,memo:q}=c;if(T===-2&&(x=!1),w!=null&&(et(),Vt(w,null,m,c,!0),tt()),H!=null&&(f.renderCache[H]=void 0),D&256){f.ctx.deactivate(c);return}const X=D&1&&O,se=!Ut(c);let le;if(se&&(le=S&&S.onVnodeBeforeUnmount)&&Le(le,f,c),D&6)mr(c.component,m,b);else{if(D&128){c.suspense.unmount(m,b);return}X&&ft(c,null,f,"beforeUnmount"),D&64?c.type.remove(c,f,m,Ot,b):y&&!y.hasOnce&&(v!==ae||T>0&&T&64)?Mt(y,f,m,!1,!0):(v===ae&&T&384||!x&&D&16)&&Mt(_,f,m),b&&yn(c)}const ue=q!=null&&H==null;(se&&(le=S&&S.onVnodeUnmounted)||X||ue)&&_e(()=>{le&&Le(le,f,c),X&&ft(c,null,f,"unmounted"),ue&&(c.el=null)},m)},yn=c=>{const{type:f,el:m,anchor:b,transition:x}=c;if(f===ae){hr(m,b);return}if(f===cs){M(c);return}const v=()=>{o(m),x&&!x.persisted&&x.afterLeave&&x.afterLeave()};if(c.shapeFlag&1&&x&&!x.persisted){const{leave:S,delayLeave:w}=x,_=()=>S(m,v);w?w(c.el,v,_):_()}else v()},hr=(c,f)=>{let m;for(;c!==f;)m=g(c),o(c),c=m;o(f)},mr=(c,f,m)=>{const{bum:b,scope:x,job:v,subTree:S,um:w,m:_,a:y}=c;Fn(_),Fn(y),b&&ls(b),x.stop(),v&&(v.flags|=8,Oe(S,c,f,m)),w&&_e(w,f),_e(()=>{c.isUnmounted=!0},f)},Mt=(c,f,m,b=!1,x=!1,v=0)=>{for(let S=v;S<c.length;S++)Oe(c[S],f,m,b,x)},ss=c=>{if(c.shapeFlag&6)return ss(c.component.subTree);if(c.shapeFlag&128)return c.suspense.next();const f=g(c.anchor||c.el),m=f&&f[fi];return m?g(m):f};let As=!1;const bn=(c,f,m)=>{let b;c==null?f._vnode&&(Oe(f._vnode,null,null,!0),b=f._vnode.component):I(f._vnode||null,c,f,null,null,null,m),f._vnode=c,As||(As=!0,kn(b),Io(),As=!1)},Ot={p:I,um:Oe,m:ut,r:yn,mt:U,mc:oe,pc:te,pbc:ce,n:ss,o:e};return{render:bn,hydrate:void 0,createApp:Di(bn)}}function js({type:e,props:t},s){return s==="svg"&&e==="foreignObject"||s==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:s}function dt({effect:e,job:t},s){s?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function Zi(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function tr(e,t,s=!1){const n=e.children,o=t.children;if(j(n)&&j(o))for(let r=0;r<n.length;r++){const i=n[r];let l=o[r];l.shapeFlag&1&&!l.dynamicChildren&&((l.patchFlag<=0||l.patchFlag===32)&&(l=o[r]=Ye(o[r]),l.el=i.el),!s&&l.patchFlag!==-2&&tr(i,l)),l.type===ks&&(l.patchFlag===-1&&(l=o[r]=Ye(l)),l.el=i.el),l.type===lt&&!l.el&&(l.el=i.el)}}function Qi(e){const t=e.slice(),s=[0];let n,o,r,i,l;const a=e.length;for(n=0;n<a;n++){const p=e[n];if(p!==0){if(o=s[s.length-1],e[o]<p){t[n]=o,s.push(n);continue}for(r=0,i=s.length-1;r<i;)l=r+i>>1,e[s[l]]<p?r=l+1:i=l;p<e[s[r]]&&(r>0&&(t[n]=s[r-1]),s[r]=n)}}for(r=s.length,i=s[r-1];r-- >0;)s[r]=i,i=t[i];return s}function sr(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:sr(t)}function Fn(e){if(e)for(let t=0;t<e.length;t++)e[t].flags|=8}function nr(e){if(e.placeholder)return e.placeholder;const t=e.component;return t?nr(t.subTree):null}const or=e=>e.__isSuspense;function Xi(e,t){t&&t.pendingBranch?j(e)?t.effects.push(...e):t.effects.push(e):ri(e)}const ae=Symbol.for("v-fgt"),ks=Symbol.for("v-txt"),lt=Symbol.for("v-cmt"),cs=Symbol.for("v-stc"),Kt=[];let Ee=null;function $(e=!1){Kt.push(Ee=e?null:[])}function el(){Kt.pop(),Ee=Kt[Kt.length-1]||null}let Jt=1;function Hn(e,t=!1){Jt+=e,e<0&&Ee&&t&&(Ee.hasOnce=!0)}function rr(e){return e.dynamicChildren=Jt>0?Ee||_t:null,el(),Jt>0&&Ee&&Ee.push(e),e}function k(e,t,s,n,o,r){return rr(h(e,t,s,n,o,r,!0))}function ir(e,t,s,n,o){return rr(Ke(e,t,s,n,o,!0))}function lr(e){return e?e.__v_isVNode===!0:!1}function Dt(e,t){return e.type===t.type&&e.key===t.key}const ar=({key:e})=>e??null,us=({ref:e,ref_key:t,ref_for:s})=>(typeof e=="number"&&(e=""+e),e!=null?ie(e)||ge(e)||B(e)?{i:$e,r:e,k:t,f:!!s}:e:null);function h(e,t=null,s=null,n=0,o=null,r=e===ae?0:1,i=!1,l=!1){const a={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&ar(t),ref:t&&us(t),scopeId:Do,slotScopeIds:null,children:s,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:r,patchFlag:n,dynamicProps:o,dynamicChildren:null,appContext:null,ctx:$e};return l?(xn(a,s),r&128&&e.normalize(a)):s&&(a.shapeFlag|=ie(s)?8:16),Jt>0&&!i&&Ee&&(a.patchFlag>0||r&6)&&a.patchFlag!==32&&Ee.push(a),a}const Ke=tl;function tl(e,t=null,s=null,n=0,o=null,r=!1){if((!e||e===Vo)&&(e=lt),lr(e)){const l=$t(e,t,!0);return s&&xn(l,s),Jt>0&&!r&&Ee&&(l.shapeFlag&6?Ee[Ee.indexOf(e)]=l:Ee.push(l)),l.patchFlag=-2,l}if(pl(e)&&(e=e.__vccOpts),t){t=sl(t);let{class:l,style:a}=t;l&&!ie(l)&&(t.class=Se(l)),Q(a)&&(fn(a)&&!j(a)&&(a=fe({},a)),t.style=Qt(a))}const i=ie(e)?1:or(e)?128:di(e)?64:Q(e)?4:B(e)?2:0;return h(e,t,s,n,o,i,r,!0)}function sl(e){return e?fn(e)||Go(e)?fe({},e):e:null}function $t(e,t,s=!1,n=!1){const{props:o,ref:r,patchFlag:i,children:l,transition:a}=e,p=t?nl(o||{},t):o,u={__v_isVNode:!0,__v_skip:!0,type:e.type,props:p,key:p&&ar(p),ref:t&&t.ref?s&&r?j(r)?r.concat(us(t)):[r,us(t)]:us(t):r,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:l,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==ae?i===-1?16:i|16:i,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:a,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&$t(e.ssContent),ssFallback:e.ssFallback&&$t(e.ssFallback),placeholder:e.placeholder,el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return a&&n&&pn(u,a.clone(u)),u}function cr(e=" ",t=0){return Ke(ks,null,e,t)}function je(e,t){const s=Ke(cs,null,e);return s.staticCount=t,s}function pe(e="",t=!1){return t?($(),ir(lt,null,e)):Ke(lt,null,e)}function He(e){return e==null||typeof e=="boolean"?Ke(lt):j(e)?Ke(ae,null,e.slice()):lr(e)?Ye(e):Ke(ks,null,String(e))}function Ye(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:$t(e)}function xn(e,t){let s=0;const{shapeFlag:n}=e;if(t==null)t=null;else if(j(t))s=16;else if(typeof t=="object")if(n&65){const o=t.default;o&&(o._c&&(o._d=!1),xn(e,o()),o._c&&(o._d=!0));return}else{s=32;const o=t._;!o&&!Go(t)?t._ctx=$e:o===3&&$e&&($e.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else B(t)?(t={default:t,_ctx:$e},s=32):(t=String(t),n&64?(s=16,t=[cr(t)]):s=8);e.children=t,e.shapeFlag|=s}function nl(...e){const t={};for(let s=0;s<e.length;s++){const n=e[s];for(const o in n)if(o==="class")t.class!==n.class&&(t.class=Se([t.class,n.class]));else if(o==="style")t.style=Qt([t.style,n.style]);else if(vs(o)){const r=t[o],i=n[o];i&&r!==i&&!(j(r)&&r.includes(i))?t[o]=r?[].concat(r,i):i:i==null&&r==null&&!ys(o)&&(t[o]=i)}else o!==""&&(t[o]=n[o])}return t}function Le(e,t,s,n=null){ze(e,t,7,[s,n])}const ol=Ko();let rl=0;function il(e,t,s){const n=e.type,o=(t?t.appContext:e.appContext)||ol,r={uid:rl++,vnode:e,type:n,parent:t,appContext:o,root:null,next:null,subTree:null,effect:null,update:null,job:null,scope:new Er(!0),render:null,proxy:null,exposed:null,exposeProxy:null,withProxy:null,provides:t?t.provides:Object.create(o.provides),ids:t?t.ids:["",0,0],accessCache:null,renderCache:[],components:null,directives:null,propsOptions:Zo(n,o),emitsOptions:Wo(n,o),emit:null,emitted:null,propsDefaults:ee,inheritAttrs:n.inheritAttrs,ctx:ee,data:ee,props:ee,attrs:ee,slots:ee,refs:ee,setupState:ee,setupContext:null,suspense:s,suspenseId:s?s.pendingId:0,asyncDep:null,asyncResolved:!1,isMounted:!1,isUnmounted:!1,isDeactivated:!1,bc:null,c:null,bm:null,m:null,bu:null,u:null,um:null,bum:null,da:null,a:null,rtg:null,rtc:null,ec:null,sp:null};return r.ctx={_:r},r.root=t?t.root:r,r.emit=Ni.bind(null,r),e.ce&&e.ce(r),r}let me=null;const ll=()=>me||$e;let xs,Ys;{const e=Ss(),t=(s,n)=>{let o;return(o=e[s])||(o=e[s]=[]),o.push(n),r=>{o.length>1?o.forEach(i=>i(r)):o[0](r)}};xs=t("__VUE_INSTANCE_SETTERS__",s=>me=s),Ys=t("__VUE_SSR_SETTERS__",s=>Gt=s)}const es=e=>{const t=me;return xs(e),e.scope.on(),()=>{e.scope.off(),xs(t)}},Vn=()=>{me&&me.scope.off(),xs(null)};function ur(e){return e.vnode.shapeFlag&4}let Gt=!1;function al(e,t=!1,s=!1){t&&Ys(t);const{props:n,children:o}=e.vnode,r=ur(e);Bi(e,n,r,t),qi(e,o,s||t);const i=r?cl(e,t):void 0;return t&&Ys(!1),i}function cl(e,t){const s=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,ki);const{setup:n}=s;if(n){et();const o=e.setupContext=n.length>1?fl(e):null,r=es(e),i=Xt(n,e,0,[e.props,o]),l=lo(i);if(tt(),r(),(l||e.sp)&&!Ut(e)&&jo(e),l){if(i.then(Vn,Vn),t)return i.then(a=>{Un(e,a)}).catch(a=>{Ts(a,e,0)});e.asyncDep=i}else Un(e,i)}else fr(e)}function Un(e,t,s){B(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:Q(t)&&(e.setupState=Po(t)),fr(e)}function fr(e,t,s){const n=e.type;e.render||(e.render=n.render||Be);{const o=es(e);et();try{Pi(e)}finally{tt(),o()}}}const ul={get(e,t){return he(e,"get",""),e[t]}};function fl(e){const t=s=>{e.exposed=s||{}};return{attrs:new Proxy(e.attrs,ul),slots:e.slots,emit:e.emit,expose:t}}function Ps(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(Po(Jr(e.exposed)),{get(t,s){if(s in t)return t[s];if(s in Bt)return Bt[s](e)},has(t,s){return s in t||s in Bt}})):e.proxy}function dl(e,t=!0){return B(e)?e.displayName||e.name:e.name||t&&e.__name}function pl(e){return B(e)&&"__vccOpts"in e}const Et=(e,t)=>ei(e,t,Gt),hl="3.5.31";/**
|
|
81
|
+
* @vue/runtime-dom v3.5.31
|
|
82
|
+
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
|
83
|
+
* @license MIT
|
|
84
|
+
**/let Zs;const Bn=typeof window<"u"&&window.trustedTypes;if(Bn)try{Zs=Bn.createPolicy("vue",{createHTML:e=>e})}catch{}const dr=Zs?e=>Zs.createHTML(e):e=>e,ml="http://www.w3.org/2000/svg",gl="http://www.w3.org/1998/Math/MathML",Ge=typeof document<"u"?document:null,Kn=Ge&&Ge.createElement("template"),xl={insert:(e,t,s)=>{t.insertBefore(e,s||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,s,n)=>{const o=t==="svg"?Ge.createElementNS(ml,e):t==="mathml"?Ge.createElementNS(gl,e):s?Ge.createElement(e,{is:s}):Ge.createElement(e);return e==="select"&&n&&n.multiple!=null&&o.setAttribute("multiple",n.multiple),o},createText:e=>Ge.createTextNode(e),createComment:e=>Ge.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Ge.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,s,n,o,r){const i=s?s.previousSibling:t.lastChild;if(o&&(o===r||o.nextSibling))for(;t.insertBefore(o.cloneNode(!0),s),!(o===r||!(o=o.nextSibling)););else{Kn.innerHTML=dr(n==="svg"?`<svg>${e}</svg>`:n==="mathml"?`<math>${e}</math>`:e);const l=Kn.content;if(n==="svg"||n==="mathml"){const a=l.firstChild;for(;a.firstChild;)l.appendChild(a.firstChild);l.removeChild(a)}t.insertBefore(l,s)}return[i?i.nextSibling:t.firstChild,s?s.previousSibling:t.lastChild]}},vl=Symbol("_vtc");function yl(e,t,s){const n=e[vl];n&&(t=(t?[t,...n]:[...n]).join(" ")),t==null?e.removeAttribute("class"):s?e.setAttribute("class",t):e.className=t}const Wn=Symbol("_vod"),bl=Symbol("_vsh"),_l=Symbol(""),wl=/(?:^|;)\s*display\s*:/;function Sl(e,t,s){const n=e.style,o=ie(s);let r=!1;if(s&&!o){if(t)if(ie(t))for(const i of t.split(";")){const l=i.slice(0,i.indexOf(":")).trim();s[l]==null&&fs(n,l,"")}else for(const i in t)s[i]==null&&fs(n,i,"");for(const i in s)i==="display"&&(r=!0),fs(n,i,s[i])}else if(o){if(t!==s){const i=n[_l];i&&(s+=";"+i),n.cssText=s,r=wl.test(s)}}else t&&e.removeAttribute("style");Wn in e&&(e[Wn]=r?n.display:"",e[bl]&&(n.display="none"))}const zn=/\s*!important$/;function fs(e,t,s){if(j(s))s.forEach(n=>fs(e,t,n));else if(s==null&&(s=""),t.startsWith("--"))e.setProperty(t,s);else{const n=Cl(e,t);zn.test(s)?e.setProperty(at(n),s.replace(zn,""),"important"):e[n]=s}}const qn=["Webkit","Moz","ms"],Fs={};function Cl(e,t){const s=Fs[t];if(s)return s;let n=be(t);if(n!=="filter"&&n in e)return Fs[t]=n;n=_s(n);for(let o=0;o<qn.length;o++){const r=qn[o]+n;if(r in e)return Fs[t]=r}return t}const Jn="http://www.w3.org/1999/xlink";function Gn(e,t,s,n,o,r=Tr(t)){n&&t.startsWith("xlink:")?s==null?e.removeAttributeNS(Jn,t.slice(6,t.length)):e.setAttributeNS(Jn,t,s):s==null||r&&!fo(s)?e.removeAttribute(t):e.setAttribute(t,r?"":We(s)?String(s):s)}function Yn(e,t,s,n,o){if(t==="innerHTML"||t==="textContent"){s!=null&&(e[t]=t==="innerHTML"?dr(s):s);return}const r=e.tagName;if(t==="value"&&r!=="PROGRESS"&&!r.includes("-")){const l=r==="OPTION"?e.getAttribute("value")||"":e.value,a=s==null?e.type==="checkbox"?"on":"":String(s);(l!==a||!("_value"in e))&&(e.value=a),s==null&&e.removeAttribute(t),e._value=s;return}let i=!1;if(s===""||s==null){const l=typeof e[t];l==="boolean"?s=fo(s):s==null&&l==="string"?(s="",i=!0):l==="number"&&(s=0,i=!0)}try{e[t]=s}catch{}i&&e.removeAttribute(o||t)}function it(e,t,s,n){e.addEventListener(t,s,n)}function Tl(e,t,s,n){e.removeEventListener(t,s,n)}const Zn=Symbol("_vei");function $l(e,t,s,n,o=null){const r=e[Zn]||(e[Zn]={}),i=r[t];if(n&&i)i.value=n;else{const[l,a]=El(t);if(n){const p=r[t]=Al(n,o);it(e,l,p,a)}else i&&(Tl(e,l,i,a),r[t]=void 0)}}const Qn=/(?:Once|Passive|Capture)$/;function El(e){let t;if(Qn.test(e)){t={};let n;for(;n=e.match(Qn);)e=e.slice(0,e.length-n[0].length),t[n[0].toLowerCase()]=!0}return[e[2]===":"?e.slice(3):at(e.slice(2)),t]}let Hs=0;const kl=Promise.resolve(),Pl=()=>Hs||(kl.then(()=>Hs=0),Hs=Date.now());function Al(e,t){const s=n=>{if(!n._vts)n._vts=Date.now();else if(n._vts<=s.attached)return;ze(Ml(n,s.value),t,5,[n])};return s.value=e,s.attached=Pl(),s}function Ml(e,t){if(j(t)){const s=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{s.call(e),e._stopped=!0},t.map(n=>o=>!o._stopped&&n&&n(o))}else return t}const Xn=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,Ol=(e,t,s,n,o,r)=>{const i=o==="svg";t==="class"?yl(e,n,i):t==="style"?Sl(e,s,n):vs(t)?ys(t)||$l(e,t,s,n,r):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):Il(e,t,n,i))?(Yn(e,t,n),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&Gn(e,t,n,i,r,t!=="value")):e._isVueCE&&(Rl(e,t)||e._def.__asyncLoader&&(/[A-Z]/.test(t)||!ie(n)))?Yn(e,be(t),n,r,t):(t==="true-value"?e._trueValue=n:t==="false-value"&&(e._falseValue=n),Gn(e,t,n,i))};function Il(e,t,s,n){if(n)return!!(t==="innerHTML"||t==="textContent"||t in e&&Xn(t)&&B(s));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="autocorrect"||t==="sandbox"&&e.tagName==="IFRAME"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const o=e.tagName;if(o==="IMG"||o==="VIDEO"||o==="CANVAS"||o==="SOURCE")return!1}return Xn(t)&&ie(s)?!1:t in e}function Rl(e,t){const s=e._def.props;if(!s)return!1;const n=be(t);return Array.isArray(s)?s.some(o=>be(o)===n):Object.keys(s).some(o=>be(o)===n)}const kt=e=>{const t=e.props["onUpdate:modelValue"]||!1;return j(t)?s=>ls(t,s):t};function Dl(e){e.target.composing=!0}function eo(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const Xe=Symbol("_assign");function to(e,t,s){return t&&(e=e.trim()),s&&(e=ws(e)),e}const Ue={created(e,{modifiers:{lazy:t,trim:s,number:n}},o){e[Xe]=kt(o);const r=n||o.props&&o.props.type==="number";it(e,t?"change":"input",i=>{i.target.composing||e[Xe](to(e.value,s,r))}),(s||r)&&it(e,"change",()=>{e.value=to(e.value,s,r)}),t||(it(e,"compositionstart",Dl),it(e,"compositionend",eo),it(e,"change",eo))},mounted(e,{value:t}){e.value=t??""},beforeUpdate(e,{value:t,oldValue:s,modifiers:{lazy:n,trim:o,number:r}},i){if(e[Xe]=kt(i),e.composing)return;const l=(r||e.type==="number")&&!/^0\d/.test(e.value)?ws(e.value):e.value,a=t??"";if(l===a)return;const p=e.getRootNode();(p instanceof Document||p instanceof ShadowRoot)&&p.activeElement===e&&e.type!=="range"&&(n&&t===s||o&&e.value.trim()===a)||(e.value=a)}},so={deep:!0,created(e,t,s){e[Xe]=kt(s),it(e,"change",()=>{const n=e._modelValue,o=Yt(e),r=e.checked,i=e[Xe];if(j(n)){const l=sn(n,o),a=l!==-1;if(r&&!a)i(n.concat(o));else if(!r&&a){const p=[...n];p.splice(l,1),i(p)}}else if(Pt(n)){const l=new Set(n);r?l.add(o):l.delete(o),i(l)}else i(pr(e,r))})},mounted:no,beforeUpdate(e,t,s){e[Xe]=kt(s),no(e,t,s)}};function no(e,{value:t,oldValue:s},n){e._modelValue=t;let o;if(j(t))o=sn(t,n.props.value)>-1;else if(Pt(t))o=t.has(n.props.value);else{if(t===s)return;o=At(t,pr(e,!0))}e.checked!==o&&(e.checked=o)}const Qs={deep:!0,created(e,{value:t,modifiers:{number:s}},n){const o=Pt(t);it(e,"change",()=>{const r=Array.prototype.filter.call(e.options,i=>i.selected).map(i=>s?ws(Yt(i)):Yt(i));e[Xe](e.multiple?o?new Set(r):r:r[0]),e._assigning=!0,Mo(()=>{e._assigning=!1})}),e[Xe]=kt(n)},mounted(e,{value:t}){oo(e,t)},beforeUpdate(e,t,s){e[Xe]=kt(s)},updated(e,{value:t}){e._assigning||oo(e,t)}};function oo(e,t){const s=e.multiple,n=j(t);if(!(s&&!n&&!Pt(t))){for(let o=0,r=e.options.length;o<r;o++){const i=e.options[o],l=Yt(i);if(s)if(n){const a=typeof l;a==="string"||a==="number"?i.selected=t.some(p=>String(p)===String(l)):i.selected=sn(t,l)>-1}else i.selected=t.has(l);else if(At(Yt(i),t)){e.selectedIndex!==o&&(e.selectedIndex=o);return}}!s&&e.selectedIndex!==-1&&(e.selectedIndex=-1)}}function Yt(e){return"_value"in e?e._value:e.value}function pr(e,t){const s=t?"_trueValue":"_falseValue";return s in e?e[s]:t}const Ll={esc:"escape",space:" ",up:"arrow-up",left:"arrow-left",right:"arrow-right",down:"arrow-down",delete:"backspace"},Nl=(e,t)=>{const s=e._withKeys||(e._withKeys={}),n=t.join(".");return s[n]||(s[n]=(o=>{if(!("key"in o))return;const r=at(o.key);if(t.some(i=>i===r||Ll[i]===r))return e(o)}))},jl=fe({patchProp:Ol},xl);let ro;function Fl(){return ro||(ro=Gi(jl))}const Hl=((...e)=>{const t=Fl().createApp(...e),{mount:s}=t;return t.mount=n=>{const o=Ul(n);if(!o)return;const r=t._component;!B(r)&&!r.render&&!r.template&&(r.template=o.innerHTML),o.nodeType===1&&(o.textContent="");const i=s(o,!1,Vl(o));return o instanceof Element&&(o.removeAttribute("v-cloak"),o.setAttribute("data-v-app","")),i},t});function Vl(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function Ul(e){return ie(e)?document.querySelector(e):e}let vn="";function Lt(e){vn=e}function bt(){return vn}async function de(e,t){const s=await fetch(e,{...t,headers:{Authorization:`Bearer ${vn}`,"Content-Type":"application/json",...(t==null?void 0:t.headers)??{}}});if(!s.ok){const n=new Error(s.statusText);throw n.status=s.status,n}return s.json()}const Bl={class:"animate-fade-in"},Kl={key:0,class:"text-center py-12 text-textSecondary"},Wl={key:1,class:"text-center text-textSecondary py-12"},zl={key:2,class:"space-y-3"},ql={class:"flex items-center justify-between"},Jl={class:"flex items-center gap-3"},Gl={class:"font-medium"},Yl={class:"text-accentLight"},Zl={class:"text-textSecondary text-xs"},Ql={key:2,class:"text-muted italic"},Xl={class:"text-xs text-textSecondary font-mono"},ea={class:"text-right"},ta={class:"flex items-center gap-2 justify-end"},sa={class:"text-xs text-textSecondary"},na=gt({__name:"SessionsTab",props:{status:{}},setup(e){const t=e,s=V([]),n=V(!0);async function o(){n.value=!0;try{const p=await de("/api/status");s.value=(p.sessions||[]).slice().sort((u,d)=>u.status==="active"&&d.status!=="active"?-1:u.status!=="active"&&d.status==="active"?1:d.lastActivity-u.lastActivity)}finally{n.value=!1}}const r=Et(()=>{var u;return(((u=t.status)==null?void 0:u.sessions)??s.value).slice().sort((d,g)=>d.status==="active"&&g.status!=="active"?-1:d.status!=="active"&&g.status==="active"?1:g.lastActivity-d.lastActivity)});function i(p){const u=Math.floor((Date.now()-p.lastActivity)/6e4);return p.status==="disconnected"?{label:`Disconnected${u>0?` — ${u}m ago`:""}`,color:"text-muted"}:u<5?{label:"Active",color:"text-success"}:u<30?{label:`Idle ${u}m`,color:"text-warn"}:{label:`Dormant ${u}m`,color:"text-danger"}}function l(p){if(!p.lastWaitCallAt)return"";const u=Math.floor((Date.now()-p.lastWaitCallAt)/6e4);return u<5?`Polling — ${u===0?"just now":u+"m ago"}`:`Last poll — ${u}m ago`}function a(p){return p.lastWaitCallAt?Math.floor((Date.now()-p.lastWaitCallAt)/6e4)<5?"text-success":"text-warn":""}return xt(o),(p,u)=>($(),k("div",Bl,[n.value&&r.value.length===0?($(),k("div",Kl,"Loading sessions...")):r.value.length===0?($(),k("div",Wl,"No sessions")):($(),k("div",zl,[($(!0),k(ae,null,nt(r.value,d=>($(),k("div",{key:d.mcpSessionId,class:Se(["glass rounded-xl p-4 animate-slide-up",d.status==="disconnected"?"opacity-60":""])},[h("div",ql,[h("div",Jl,[h("span",{class:Se(["w-2.5 h-2.5 rounded-full",d.status==="disconnected"?"bg-muted":Math.floor((Date.now()-d.lastActivity)/6e4)<5?"bg-success":Math.floor((Date.now()-d.lastActivity)/6e4)<30?"bg-warn":"bg-danger"])},null,2),h("div",null,[h("div",Gl,[d.topicName?($(),k(ae,{key:0},[h("span",Yl,N(d.topicName),1),h("span",Zl," (thread "+N(d.threadId)+")",1)],64)):d.threadId!=null?($(),k(ae,{key:1},[cr("Thread "+N(d.threadId),1)],64)):($(),k("span",Ql,"Awaiting start_session…"))]),h("div",Xl,N(d.mcpSessionId.slice(0,12))+"...",1)])]),h("div",ea,[h("div",ta,[h("span",{class:Se(["text-sm font-medium",i(d).color])},N(i(d).label),3),l(d)?($(),k("span",{key:0,class:Se(["text-xs ml-2",a(d)])},N(l(d)),3)):pe("",!0)]),h("div",sa,N(d.transportType),1)])])],2))),128))]))]))}}),oa={class:"animate-fade-in"},ra={class:"flex flex-wrap items-center gap-3 mb-4"},ia={key:0,class:"text-center py-12 text-textSecondary"},la={key:1,class:"text-center py-12 text-textSecondary"},aa={key:2,class:"space-y-2"},ca={class:"flex items-start justify-between gap-3"},ua={class:"flex-1 min-w-0"},fa={class:"flex items-center gap-2 mb-1"},da={key:0,class:"type-badge",style:{background:"rgba(239,68,68,0.15)",color:"#f87171"}},pa={key:1,class:"type-badge",style:{background:"rgba(245,158,11,0.15)",color:"#fbbf24"}},ha={class:"text-xs text-textSecondary"},ma={class:"text-sm text-textPrimary leading-relaxed"},ga={class:"flex flex-wrap gap-1.5 mt-2"},xa={class:"text-right shrink-0"},va={class:"text-sm font-mono text-textSecondary"},ya={class:"text-xs text-muted"},ba={class:"text-xs text-muted"},_a=gt({__name:"MemoryNotesTab",setup(e){const t=V([]),s=V(!1),n=V(""),o=V("created_at"),r=V("");let i=null;async function l(){s.value=!0;try{const u=r.value.trim();let d;if(u)d=await de(`/api/search?q=${encodeURIComponent(u)}&limit=50`);else{const g=new URLSearchParams({limit:"50",sort:o.value});n.value&&g.set("type",n.value),d=await de(`/api/notes?${g}`)}t.value=d}finally{s.value=!1}}function a(){i&&clearTimeout(i),i=setTimeout(l,300)}function p(u){if(!u)return"never";const d=Date.now()-new Date(u).getTime(),g=Math.floor(d/6e4);if(g<1)return"just now";if(g<60)return`${g}m ago`;const C=Math.floor(g/60);return C<24?`${C}h ago`:`${Math.floor(C/24)}d ago`}return xt(l),(u,d)=>($(),k("div",oa,[h("div",ra,[ye(h("input",{"onUpdate:modelValue":d[0]||(d[0]=g=>r.value=g),onInput:a,type:"text",placeholder:"Search notes...",class:"flex-1 min-w-[200px] px-4 py-2 rounded-xl bg-card border border-gray-700 text-sm text-textPrimary placeholder-muted focus:outline-none focus:border-accent transition"},null,544),[[Ue,r.value]]),ye(h("select",{"onUpdate:modelValue":d[1]||(d[1]=g=>n.value=g),onChange:l,class:"px-3 py-2 rounded-xl bg-card border border-gray-700 text-sm text-textPrimary focus:outline-none"},[...d[3]||(d[3]=[je('<option value="">All types</option><option value="fact">Facts</option><option value="preference">Preferences</option><option value="pattern">Patterns</option><option value="entity">Entities</option><option value="relationship">Relationships</option>',6)])],544),[[Qs,n.value]]),ye(h("select",{"onUpdate:modelValue":d[2]||(d[2]=g=>o.value=g),onChange:l,class:"px-3 py-2 rounded-xl bg-card border border-gray-700 text-sm text-textPrimary focus:outline-none"},[...d[4]||(d[4]=[h("option",{value:"created_at"},"Newest",-1),h("option",{value:"confidence"},"Confidence",-1),h("option",{value:"access_count"},"Most accessed",-1)])],544),[[Qs,o.value]])]),s.value?($(),k("div",ia,"Loading notes...")):t.value.length===0?($(),k("div",la,"No notes found")):($(),k("div",aa,[($(!0),k(ae,null,nt(t.value,g=>($(),k("div",{key:g.noteId,class:Se(["glass rounded-xl p-4 animate-fade-in",`priority-${g.priority||0}`])},[h("div",ca,[h("div",ua,[h("div",fa,[h("span",{class:Se(["type-badge",`type-${g.type}`])},N(g.type),3),g.priority>=2?($(),k("span",da,"HIGH IMPORTANCE")):g.priority===1?($(),k("span",pa,"NOTABLE")):pe("",!0),h("span",ha,N(g.noteId),1)]),h("p",ma,N(g.content),1),h("div",ga,[($(!0),k(ae,null,nt(g.keywords||[],C=>($(),k("span",{key:C,class:"text-xs px-2 py-0.5 rounded-full bg-accent/10 text-accentLight"},N(C),1))),128))])]),h("div",xa,[h("div",va,N(((Number(g.confidence)||0)*100).toFixed(0))+"%",1),h("div",ya,N(p(g.createdAt)),1),h("div",ba,N(g.accessCount??0)+" hits",1)])])],2))),128))]))]))}}),wa={class:"animate-fade-in"},Sa={class:"flex items-center gap-3 mb-4"},Ca=["disabled"],Ta={key:0,class:"text-center py-12 text-textSecondary text-sm"},$a={key:1,class:"text-center py-12 text-textSecondary"},Ea={key:2,class:"space-y-2"},ka={class:"flex items-start gap-3"},Pa={class:"text-lg"},Aa={class:"flex-1 min-w-0"},Ma={class:"flex items-center gap-2 mb-1"},Oa={class:"type-badge type-fact"},Ia={class:"text-xs text-textSecondary font-mono"},Ra={class:"text-xs text-muted"},Da={class:"text-sm text-textSecondary leading-relaxed break-words"},La={class:"text-xs text-muted shrink-0"},Na=gt({__name:"EpisodesTab",setup(e){const t=V([]),s=V(!1),n=V(""),o=V(!1),r={text:"💬",voice:"🎤",image:"🖼️",file:"📎",system:"⚙️"};async function i(){s.value=!0;try{let p="/api/episodes?limit=30";n.value&&(p+=`&threadId=${n.value}`),t.value=await de(p),o.value=!0}finally{s.value=!1}}function l(p){if(!p)return"never";const u=Date.now()-new Date(p).getTime(),d=Math.floor(u/6e4);if(d<1)return"just now";if(d<60)return`${d}m ago`;const g=Math.floor(d/60);return g<24?`${g}h ago`:`${Math.floor(g/24)}d ago`}function a(p){return p?typeof p=="object"?JSON.stringify(p).slice(0,300):String(p).slice(0,300):"(no content)"}return(p,u)=>($(),k("div",wa,[h("div",Sa,[ye(h("input",{"onUpdate:modelValue":u[0]||(u[0]=d=>n.value=d),type:"number",placeholder:"Thread ID (optional)",class:"w-48 px-4 py-2 rounded-xl bg-card border border-gray-700 text-sm text-textPrimary placeholder-muted focus:outline-none focus:border-accent transition"},null,512),[[Ue,n.value]]),h("button",{onClick:i,disabled:s.value,class:"px-4 py-2 rounded-xl bg-accent hover:bg-accentLight disabled:opacity-50 text-white text-sm font-medium transition"},N(s.value?"Loading...":"Load"),9,Ca)]),o.value?t.value.length===0?($(),k("div",$a,"No episodes")):($(),k("div",Ea,[($(!0),k(ae,null,nt(t.value,d=>($(),k("div",{key:d.episodeId,class:"glass rounded-xl p-4 animate-fade-in"},[h("div",ka,[h("span",Pa,N(r[d.modality]||"📝"),1),h("div",Aa,[h("div",Ma,[h("span",Oa,N(d.type||"unknown"),1),h("span",Ia,N(d.episodeId||"-"),1),h("span",Ra,N(l(d.createdAt)),1)]),h("p",Da,N(a(d.content)),1)]),h("div",La,"imp: "+N(((Number(d.importance)||0)*100).toFixed(0))+"%",1)])]))),128))])):($(),k("div",Ta,'Click "Load" to fetch episodes'))]))}}),ja={class:"animate-fade-in"},Fa={key:0,class:"text-center py-12 text-textSecondary"},Ha={key:1,class:"text-center py-12 text-textSecondary"},Va={key:2,class:"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-3"},Ua={class:"font-medium text-sm"},Ba={class:"flex items-center justify-between mt-2"},Ka={class:"text-lg font-bold font-mono text-accent"},Wa={class:"text-xs text-muted"},za=gt({__name:"TopicsTab",setup(e){const t=V([]),s=V(!0);async function n(){s.value=!0;try{t.value=await de("/api/topics")}finally{s.value=!1}}function o(a){return(a.semanticCount||0)+(a.proceduralCount||0)}function r(a){if(!a)return"never";const p=Date.now()-new Date(a).getTime(),u=Math.floor(p/6e4);if(u<1)return"just now";if(u<60)return`${u}m ago`;const d=Math.floor(u/60);return d<24?`${d}h ago`:`${Math.floor(d/24)}d ago`}const i=()=>t.value.slice().sort((a,p)=>o(p)-o(a)),l=()=>{const a=t.value.map(p=>o(p));return Math.max(...a,1)};return xt(n),(a,p)=>($(),k("div",ja,[s.value?($(),k("div",Fa,"Loading topics...")):t.value.length===0?($(),k("div",Ha,"No topics yet")):($(),k("div",Va,[($(!0),k(ae,null,nt(i(),u=>($(),k("div",{key:u.topic,class:"glass rounded-xl p-4 animate-slide-up",style:Qt({borderLeft:`3px solid rgba(99,102,241,${Math.max(.15,o(u)/l())})`})},[h("div",Ua,N(u.topic||"Unknown"),1),h("div",Ba,[h("span",Ka,N(o(u)),1),h("span",Wa,N(r(u.lastUpdated)),1)])],4))),128))]))]))}}),qa={class:"animate-fade-in space-y-6"},Ja={class:"glass rounded-xl p-4"},Ga={class:"flex flex-wrap items-center gap-4 mb-4"},Ya={key:0,class:"text-sm text-success"},Za={class:"flex flex-wrap items-center gap-3"},Qa={key:0,class:"text-sm text-success"},Xa={class:"glass rounded-xl p-6"},ec={class:"flex flex-wrap items-center justify-between gap-4 mb-4"},tc={class:"flex items-center gap-2"},sc={key:0,class:"text-sm text-success"},nc={key:0,class:"mb-3"},oc={class:"mt-4"},rc=["innerHTML"],ic={class:"glass rounded-xl p-6"},lc={class:"flex flex-wrap items-center justify-between gap-4 mb-4"},ac={class:"flex items-center gap-2"},cc={key:0,class:"text-sm text-success"},uc={class:"mb-4 flex flex-wrap items-center gap-3"},fc={class:"flex items-center gap-2"},dc={class:"font-mono text-sm text-textPrimary"},pc={key:0,class:"mb-3"},hc={class:"flex flex-wrap gap-2 mb-3"},mc=["onClick"],gc={class:"mt-4"},xc=["innerHTML"],vc=gt({__name:"TemplatesTab",setup(e){function t(U){return U.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/\{\{([A-Z_]+)\}\}/g,'<span class="text-accentLight" style="background:rgba(99,102,241,0.1);padding:0 2px;border-radius:3px">{{$1}}</span>')}const s=V("copilot"),n=V(""),o=V(""),r=V(""),i=V(""),l=V(!0),a=V(""),p=V(!1),u=V(""),d=V(!0),g=V(""),C=V(!1),K=V([]),I=V("");async function W(){await Promise.all([A(),F(),z(),M()])}async function A(){try{const U=await de("/api/settings/agent-type");s.value=U.agentType||"copilot"}catch{}}async function F(){try{const U=await de("/api/settings/claude-mcp-config");o.value=U.path||""}catch{}}async function z(){try{const U=await de("/api/templates");if(U.templates&&U.templates.length>0){const E=U.templates[0];i.value=E.content||"",l.value=E.isDefault??!0}}catch{}}async function M(){try{const[U,E,J]=await Promise.all([de("/api/templates/drive"),de("/api/templates/drive-presets"),de("/api/settings/dmn-activation-hours")]);K.value=E.presets||[],I.value=String(J.value??"not set"),U.custom?(u.value=U.custom,d.value=!1):(u.value=U.default||"",d.value=!0)}catch{}}async function R(){try{await de("/api/settings/agent-type",{method:"POST",body:JSON.stringify({agentType:s.value})}),await de("/api/templates/reminders",{method:"DELETE"}),n.value="Saved ✓",setTimeout(()=>{n.value=""},3e3),await z()}catch(U){n.value="Error: "+U.message}}async function P(){const U=o.value.trim();if(!U){r.value="Path is empty",setTimeout(()=>{r.value=""},3e3);return}try{await de("/api/settings/claude-mcp-config",{method:"POST",body:JSON.stringify({path:U})}),r.value="Saved ✓",setTimeout(()=>{r.value=""},3e3)}catch(E){r.value="Error: "+E.message}}async function L(){try{const U=await fetch("/api/templates/reminders",{method:"POST",headers:{Authorization:`Bearer ${bt()}`,"Content-Type":"application/json"},body:JSON.stringify({content:i.value})});if(!U.ok)throw new Error(U.statusText);l.value=!1,a.value="Saved ✓",setTimeout(()=>{a.value=""},3e3)}catch(U){a.value="Error: "+U.message}}async function oe(){if(confirm("Reset to default template? Your customizations will be lost."))try{const U=await fetch("/api/templates/reminders",{method:"DELETE",headers:{Authorization:`Bearer ${bt()}`}});if(!U.ok)throw new Error(U.statusText);await z(),a.value="Reset to default ✓",setTimeout(()=>{a.value=""},3e3)}catch(U){a.value="Error: "+U.message}}async function Z(){const U=u.value;if(!U.trim()){g.value="Template is empty — load a preset first",setTimeout(()=>{g.value=""},3e3);return}try{const E=await fetch("/api/templates/drive",{method:"POST",headers:{Authorization:`Bearer ${bt()}`,"Content-Type":"application/json"},body:JSON.stringify({content:U})});if(!E.ok)throw new Error(E.statusText);d.value=!1,g.value="Saved ✓",setTimeout(()=>{g.value=""},3e3)}catch(E){g.value="Error: "+E.message}}async function ce(){if(confirm("Reset drive template? The custom template will be removed."))try{const U=await fetch("/api/templates/drive",{method:"DELETE",headers:{Authorization:`Bearer ${bt()}`}});if(!U.ok)throw new Error(U.statusText);await M(),g.value="Reset to default ✓",setTimeout(()=>{g.value=""},3e3)}catch(U){g.value="Error: "+U.message}}function ke(U){u.value=U.content,d.value=!1}const qe=Et(()=>t(i.value)),Ce=Et(()=>u.value?t(u.value):'<span style="color:#6b7280">(no template loaded)</span>');return xt(W),(U,E)=>($(),k("div",qa,[h("div",Ja,[h("div",Ga,[E[7]||(E[7]=h("label",{class:"text-sm font-medium text-textSecondary"},"Agent Type",-1)),ye(h("select",{"onUpdate:modelValue":E[0]||(E[0]=J=>s.value=J),onChange:R,class:"px-3 py-2 rounded-xl bg-card border border-gray-700 text-sm text-textPrimary focus:outline-none focus:border-accent transition"},[...E[6]||(E[6]=[h("option",{value:"copilot"},"Copilot",-1),h("option",{value:"claude"},"Claude",-1),h("option",{value:"cursor"},"Cursor",-1)])],544),[[Qs,s.value]]),n.value?($(),k("span",Ya,N(n.value),1)):pe("",!0),E[8]||(E[8]=h("span",{class:"text-xs text-muted"},"Changes which default reminders template is used",-1))]),h("div",Za,[E[9]||(E[9]=h("label",{class:"text-sm font-medium text-textSecondary"},"Claude MCP Config Path",-1)),ye(h("input",{"onUpdate:modelValue":E[1]||(E[1]=J=>o.value=J),type:"text",placeholder:"~/.claude/settings.json",class:"flex-1 min-w-[260px] px-3 py-2 rounded-xl bg-card border border-gray-700 text-sm text-textPrimary placeholder-muted font-mono focus:outline-none focus:border-accent transition"},null,512),[[Ue,o.value]]),h("button",{onClick:P,class:"px-4 py-2 rounded-xl bg-accent hover:bg-accentLight text-white text-sm font-medium transition"},"Save"),r.value?($(),k("span",Qa,N(r.value),1)):pe("",!0)])]),h("div",Xa,[h("div",ec,[E[10]||(E[10]=h("div",null,[h("h3",{class:"text-lg font-semibold"},"Reminders Template"),h("p",{class:"text-sm text-textSecondary mt-1"},"Edit the system prompt template sent with every reminder")],-1)),h("div",tc,[a.value?($(),k("span",sc,N(a.value),1)):pe("",!0),h("button",{onClick:oe,class:"px-4 py-2 rounded-xl bg-card hover:bg-cardHover border border-gray-700 text-sm text-textSecondary hover:text-textPrimary transition"},"Reset to Default"),h("button",{onClick:L,class:"px-4 py-2 rounded-xl bg-accent hover:bg-accentLight text-white text-sm font-medium transition"},"Save")])]),l.value?($(),k("div",nc,[...E[11]||(E[11]=[h("span",{class:"type-badge",style:{background:"rgba(245,158,11,0.15)",color:"#fbbf24"}},"USING DEFAULT — edit and save to customize",-1)])])):pe("",!0),ye(h("textarea",{"onUpdate:modelValue":E[2]||(E[2]=J=>i.value=J),rows:"20",spellcheck:"false",class:"w-full px-4 py-3 rounded-xl bg-surface border border-gray-700 text-textPrimary font-mono text-sm leading-relaxed focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent transition resize-y",placeholder:"Loading..."},null,512),[[Ue,i.value]]),h("div",oc,[h("div",{class:"flex items-center gap-2 mb-2 cursor-pointer select-none",onClick:E[3]||(E[3]=J=>p.value=!p.value)},[($(),k("svg",{class:Se(["w-4 h-4 text-textSecondary transition-transform",p.value?"rotate-90":""]),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[...E[12]||(E[12]=[h("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M9 5l7 7-7 7"},null,-1)])],2)),E[13]||(E[13]=h("span",{class:"text-sm font-medium text-textSecondary"},"Preview with highlighted variables",-1))]),p.value?($(),k("div",{key:0,class:"glass rounded-xl p-4 font-mono text-sm leading-relaxed whitespace-pre-wrap break-words",innerHTML:qe.value},null,8,rc)):pe("",!0)]),E[14]||(E[14]=je('<details class="mt-4"><summary class="text-sm font-medium text-textSecondary cursor-pointer hover:text-textPrimary transition">Available Variables</summary><div class="mt-2 glass rounded-xl p-4 grid grid-cols-1 sm:grid-cols-2 gap-2 text-sm"><div><code class="text-accentLight">{{OPERATOR_MESSAGE}}</code> <span class="text-textSecondary">— latest operator message</span></div><div><code class="text-accentLight">{{THREAD_ID}}</code> <span class="text-textSecondary">— Telegram thread ID</span></div><div><code class="text-accentLight">{{TIME}}</code> <span class="text-textSecondary">— formatted timestamp</span></div><div><code class="text-accentLight">{{UPTIME}}</code> <span class="text-textSecondary">— session uptime</span></div><div><code class="text-accentLight">{{VERSION}}</code> <span class="text-textSecondary">— package version</span></div><div><code class="text-accentLight">{{MODE}}</code> <span class="text-textSecondary">— "autonomous" or "standard"</span></div></div></details>',1))]),h("div",ic,[h("div",lc,[E[15]||(E[15]=h("div",null,[h("h3",{class:"text-lg font-semibold"},"Drive Framing Template"),h("p",{class:"text-sm text-textSecondary mt-1"},"Customize the autonomous drive prompt sent when the operator is away")],-1)),h("div",ac,[g.value?($(),k("span",cc,N(g.value),1)):pe("",!0),h("button",{onClick:ce,class:"px-4 py-2 rounded-xl bg-card hover:bg-cardHover border border-gray-700 text-sm text-textSecondary hover:text-textPrimary transition"},"Reset to Default"),h("button",{onClick:Z,class:"px-4 py-2 rounded-xl bg-accent hover:bg-accentLight text-white text-sm font-medium transition"},"Save")])]),h("div",uc,[E[17]||(E[17]=h("label",{class:"text-sm text-textSecondary"},"Drive Activation Period:",-1)),h("div",fc,[h("span",dc,N(I.value),1),E[16]||(E[16]=h("span",{class:"text-sm text-textSecondary"},"hours",-1))]),E[18]||(E[18]=h("span",{class:"text-xs text-muted"},"(informational — set via DMN_ACTIVATION_HOURS env var)",-1))]),d.value?($(),k("div",pc,[...E[19]||(E[19]=[h("span",{class:"type-badge",style:{background:"rgba(245,158,11,0.15)",color:"#fbbf24"}},"(Default — edit to override)",-1)])])):pe("",!0),h("div",hc,[E[20]||(E[20]=h("span",{class:"text-sm text-textSecondary self-center"},"Presets:",-1)),($(!0),k(ae,null,nt(K.value,J=>($(),k("button",{key:J.key,onClick:re=>ke(J),class:"px-3 py-1.5 rounded-lg bg-card hover:bg-cardHover border border-gray-700 text-xs text-textSecondary hover:text-textPrimary transition"},N(J.label),9,mc))),128))]),ye(h("textarea",{"onUpdate:modelValue":E[4]||(E[4]=J=>u.value=J),rows:"15",spellcheck:"false",class:"w-full px-4 py-3 rounded-xl bg-surface border border-gray-700 text-textPrimary font-mono text-sm leading-relaxed focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent transition resize-y",placeholder:"Load a preset or type a custom drive template..."},null,512),[[Ue,u.value]]),h("div",gc,[h("div",{class:"flex items-center gap-2 mb-2 cursor-pointer select-none",onClick:E[5]||(E[5]=J=>C.value=!C.value)},[($(),k("svg",{class:Se(["w-4 h-4 text-textSecondary transition-transform",C.value?"rotate-90":""]),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[...E[21]||(E[21]=[h("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M9 5l7 7-7 7"},null,-1)])],2)),E[22]||(E[22]=h("span",{class:"text-sm font-medium text-textSecondary"},"Preview with sample values",-1))]),C.value?($(),k("div",{key:0,class:"glass rounded-xl p-4 font-mono text-sm leading-relaxed whitespace-pre-wrap break-words",innerHTML:Ce.value},null,8,xc)):pe("",!0)]),E[23]||(E[23]=je('<details class="mt-4"><summary class="text-sm font-medium text-textSecondary cursor-pointer hover:text-textPrimary transition">Available Variables</summary><div class="mt-2 glass rounded-xl p-4 grid grid-cols-1 sm:grid-cols-2 gap-2 text-sm"><div><code class="text-accentLight">{{IDLE_HOURS}}</code> <span class="text-textSecondary">— hours since last operator interaction</span></div><div><code class="text-accentLight">{{TIME}}</code> <span class="text-textSecondary">— ISO timestamp</span></div><div><code class="text-accentLight">{{PROBABILITY}}</code> <span class="text-textSecondary">— drive activation probability (0.2–1.0)</span></div></div></details>',1))])]))}}),yc={class:"animate-fade-in"},bc={class:"glass rounded-xl p-6 mb-6"},_c={class:"flex flex-wrap items-center justify-between gap-4 mb-4"},wc={key:0,class:"glass rounded-xl p-4 mb-4 border border-accent/30"},Sc={class:"grid grid-cols-1 sm:grid-cols-2 gap-3 mb-3"},Cc={class:"flex items-center gap-4 mb-3"},Tc={class:"flex items-center gap-2 text-sm text-textSecondary cursor-pointer"},$c={class:"flex items-center gap-2"},Ec={key:0,class:"text-sm text-warn"},kc={key:1,class:"text-center py-8 text-textSecondary text-sm"},Pc={key:2,class:"text-center text-textSecondary py-12"},Ac={key:3,class:"space-y-2"},Mc=["onClick"],Oc={class:"flex items-start justify-between gap-3"},Ic={class:"flex-1 min-w-0"},Rc={class:"flex items-center gap-2 mb-1"},Dc={class:"font-medium text-sm"},Lc={key:0,class:"type-badge",style:{background:"rgba(245,158,11,0.15)",color:"#fbbf24"}},Nc={class:"flex flex-wrap gap-1.5 mt-1"},jc=["title"],Fc={key:0,class:"glass rounded-xl p-6"},Hc={class:"flex flex-wrap items-center justify-between gap-4 mb-4"},Vc={class:"text-lg font-semibold"},Uc={class:"text-sm text-textSecondary mt-1"},Bc={class:"flex items-center gap-2"},Kc={key:0,class:"text-sm text-success"},Wc={class:"grid grid-cols-1 sm:grid-cols-3 gap-3 mb-4"},zc=["value"],qc={class:"flex items-end"},Jc={class:"flex items-center gap-2 text-sm text-textSecondary cursor-pointer pb-2"},Gc=gt({__name:"SkillsTab",setup(e){const t=V([]),s=V(!0),n=V(null),o=V(""),r=V(""),i=V(!1),l=V(""),a=V(!1),p=V(""),u=V(""),d=V(!1),g=V("");async function C(){s.value=!0;try{const R=await de("/api/skills");t.value=R.skills||[]}finally{s.value=!1}}function K(R){return R?R.includes(".remote-copilot-mcp")&&R.includes("skills")?"user":R.endsWith(".default.md")?"default":R.endsWith(".skill.md")?"project":"unknown":"unknown"}function I(R){const P={user:"background:rgba(99,102,241,0.15);color:#818cf8",default:"background:rgba(107,114,128,0.15);color:#9ca3af",project:"background:rgba(34,197,94,0.15);color:#4ade80",unknown:"background:rgba(107,114,128,0.15);color:#9ca3af"};return P[R]||P.unknown}function W(R){n.value=R,o.value=R.content,r.value=(R.triggers||[]).join(", "),i.value=!!R.replacesOrchestrator,a.value=!1}function A(){n.value=null}function F(R,P,L,oe){let Z=`---
|
|
85
|
+
name: ${R}
|
|
86
|
+
triggers:
|
|
87
|
+
`;return P.forEach(ce=>{Z+=` - ${ce.trim()}
|
|
88
|
+
`}),L&&(Z+=`replaces_orchestrator: true
|
|
89
|
+
`),Z+=`---
|
|
90
|
+
|
|
91
|
+
`,Z+oe}async function z(){if(!n.value)return;const R=n.value.name;try{const P=r.value.split(",").map(ce=>ce.trim()).filter(Boolean),L=o.value;let oe;L.trimStart().startsWith("---")?oe=L:oe=F(R,P,i.value,L);const Z=await fetch(`/api/skills/${encodeURIComponent(R)}`,{method:"PUT",headers:{Authorization:`Bearer ${bt()}`,"Content-Type":"application/json"},body:JSON.stringify({content:oe})});if(!Z.ok)throw new Error(Z.statusText);l.value="Saved ✓",setTimeout(()=>{l.value=""},3e3),await C()}catch(P){l.value="Error: "+P.message}}async function M(){const R=p.value.trim(),P=u.value;if(!R){g.value="Name is required";return}const L=P.split(",").map(Z=>Z.trim()).filter(Boolean);if(!L.length){g.value="At least one trigger is required";return}const oe=F(R,L,d.value,`\x3C!-- Write your skill instructions here -->
|
|
92
|
+
`);try{const Z=await fetch(`/api/skills/${encodeURIComponent(R)}`,{method:"PUT",headers:{Authorization:`Bearer ${bt()}`,"Content-Type":"application/json"},body:JSON.stringify({content:oe})});if(!Z.ok)throw new Error(Z.statusText);g.value="Created ✓",a.value=!1,await C();const ce=t.value.find(ke=>ke.name===R);ce&&W(ce)}catch(Z){g.value="Error: "+Z.message}}return xt(C),(R,P)=>($(),k("div",yc,[h("div",bc,[h("div",_c,[P[8]||(P[8]=h("div",null,[h("h3",{class:"text-lg font-semibold"},"Skill Library"),h("p",{class:"text-sm text-textSecondary mt-1"},"Manage intent-routing skills — user overrides, defaults, and project skills")],-1)),h("button",{onClick:P[0]||(P[0]=L=>{a.value=!a.value,n.value=null}),class:"px-4 py-2 rounded-xl bg-accent hover:bg-accentLight text-white text-sm font-medium transition"}," + New Skill ")]),a.value?($(),k("div",wc,[P[12]||(P[12]=h("h4",{class:"text-sm font-semibold mb-3"},"Create New Skill",-1)),h("div",Sc,[h("div",null,[P[9]||(P[9]=h("label",{class:"text-xs text-textSecondary block mb-1"},"Name",-1)),ye(h("input",{"onUpdate:modelValue":P[1]||(P[1]=L=>p.value=L),type:"text",placeholder:"my-skill",class:"w-full px-3 py-2 rounded-lg bg-surface border border-gray-700 text-sm text-textPrimary font-mono focus:outline-none focus:border-accent transition"},null,512),[[Ue,p.value]])]),h("div",null,[P[10]||(P[10]=h("label",{class:"text-xs text-textSecondary block mb-1"},"Triggers (comma-separated)",-1)),ye(h("input",{"onUpdate:modelValue":P[2]||(P[2]=L=>u.value=L),type:"text",placeholder:"trigger1, trigger2",class:"w-full px-3 py-2 rounded-lg bg-surface border border-gray-700 text-sm text-textPrimary focus:outline-none focus:border-accent transition"},null,512),[[Ue,u.value]])])]),h("div",Cc,[h("label",Tc,[ye(h("input",{"onUpdate:modelValue":P[3]||(P[3]=L=>d.value=L),type:"checkbox",class:"rounded"},null,512),[[so,d.value]]),P[11]||(P[11]=h("span",null,"Replaces orchestrator",-1))])]),h("div",$c,[h("button",{onClick:M,class:"px-4 py-2 rounded-xl bg-accent hover:bg-accentLight text-white text-sm font-medium transition"},"Create"),h("button",{onClick:P[4]||(P[4]=L=>a.value=!1),class:"px-4 py-2 rounded-xl bg-card hover:bg-cardHover border border-gray-700 text-sm text-textSecondary hover:text-textPrimary transition"},"Cancel"),g.value?($(),k("span",Ec,N(g.value),1)):pe("",!0)])])):pe("",!0),s.value?($(),k("div",kc,"Loading...")):t.value.length===0?($(),k("div",Pc,"No skills loaded")):($(),k("div",Ac,[($(!0),k(ae,null,nt(t.value,L=>{var oe;return $(),k("div",{key:L.name,onClick:Z=>W(L),class:Se(["glass rounded-xl p-4 cursor-pointer hover:bg-cardHover transition border",((oe=n.value)==null?void 0:oe.name)===L.name?"border-accent":"border-transparent"])},[h("div",Oc,[h("div",Ic,[h("div",Rc,[h("span",Dc,N(L.name),1),h("span",{class:"type-badge",style:Qt(I(K(L.source)))},N(K(L.source)),5),L.replacesOrchestrator?($(),k("span",Lc,"REPLACES ORCH")):pe("",!0)]),h("div",Nc,[($(!0),k(ae,null,nt(L.triggers||[],Z=>($(),k("span",{key:Z,class:"text-xs px-2 py-0.5 rounded-full bg-accent/10 text-accentLight"},N(Z),1))),128))])]),h("div",{class:"text-xs text-muted font-mono shrink-0 max-w-[200px] truncate",title:L.source||""},N((L.source||"").split(/[\\/]/).pop()||""),9,jc)])],10,Mc)}),128))]))]),n.value?($(),k("div",Fc,[h("div",Hc,[h("div",null,[h("h3",Vc,"Edit: "+N(n.value.name),1),h("p",Uc,N(n.value.source||"(unknown source)"),1)]),h("div",Bc,[l.value?($(),k("span",Kc,N(l.value),1)):pe("",!0),h("button",{onClick:A,class:"px-4 py-2 rounded-xl bg-card hover:bg-cardHover border border-gray-700 text-sm text-textSecondary hover:text-textPrimary transition"},"Close"),h("button",{onClick:z,class:"px-4 py-2 rounded-xl bg-accent hover:bg-accentLight text-white text-sm font-medium transition"},"Save")])]),h("div",Wc,[h("div",null,[P[13]||(P[13]=h("label",{class:"text-xs text-textSecondary block mb-1"},"Name",-1)),h("input",{value:n.value.name,type:"text",readonly:"",class:"w-full px-3 py-2 rounded-lg bg-surface border border-gray-700 text-sm text-textPrimary font-mono opacity-60 cursor-not-allowed"},null,8,zc)]),h("div",null,[P[14]||(P[14]=h("label",{class:"text-xs text-textSecondary block mb-1"},"Triggers (comma-separated)",-1)),ye(h("input",{"onUpdate:modelValue":P[5]||(P[5]=L=>r.value=L),type:"text",class:"w-full px-3 py-2 rounded-lg bg-surface border border-gray-700 text-sm text-textPrimary focus:outline-none focus:border-accent transition"},null,512),[[Ue,r.value]])]),h("div",qc,[h("label",Jc,[ye(h("input",{"onUpdate:modelValue":P[6]||(P[6]=L=>i.value=L),type:"checkbox",class:"rounded"},null,512),[[so,i.value]]),P[15]||(P[15]=h("span",null,"Replaces orchestrator",-1))])])]),ye(h("textarea",{"onUpdate:modelValue":P[7]||(P[7]=L=>o.value=L),rows:"20",spellcheck:"false",class:"w-full px-4 py-3 rounded-xl bg-surface border border-gray-700 text-textPrimary font-mono text-sm leading-relaxed focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent transition resize-y",placeholder:"Skill body (markdown)..."},null,512),[[Ue,o.value]])])):pe("",!0)]))}}),Yc={key:0,class:"fixed inset-0 z-50 flex items-center justify-center bg-surface/95 backdrop-blur-sm"},Zc={class:"glass rounded-2xl p-8 max-w-md w-full mx-4 animate-slide-up"},Qc=["disabled"],Xc={key:0,class:"mt-3 text-sm text-danger"},eu={key:1,class:"min-h-screen font-sans text-textPrimary animate-fade-in"},tu={class:"glass sticky top-0 z-40 border-b border-gray-800/50"},su={class:"max-w-7xl mx-auto px-4 sm:px-6 py-4 flex items-center justify-between"},nu={class:"flex items-center gap-4"},ou={class:"text-sm text-textSecondary font-mono"},ru={class:"max-w-7xl mx-auto px-4 sm:px-6 py-6"},iu={class:"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-3"},lu={class:"glass rounded-xl p-4 stat-glow animate-slide-up"},au={class:"text-2xl font-bold font-mono"},cu={class:"glass rounded-xl p-4 stat-glow animate-slide-up"},uu={class:"text-2xl font-bold font-mono"},fu={class:"glass rounded-xl p-4 stat-glow animate-slide-up"},du={class:"text-2xl font-bold font-mono"},pu={class:"glass rounded-xl p-4 stat-glow animate-slide-up"},hu={class:"flex items-center gap-2 mb-2"},mu={class:"text-2xl font-bold font-mono"},gu={class:"glass rounded-xl p-4 stat-glow animate-slide-up"},xu={class:"text-2xl font-bold font-mono"},vu={class:"glass rounded-xl p-4 stat-glow animate-slide-up"},yu={class:"text-2xl font-bold font-mono"},bu={class:"max-w-7xl mx-auto px-4 sm:px-6"},_u={class:"flex gap-6 border-b border-gray-800/50 mb-6"},wu=["onClick"],Su={class:"max-w-7xl mx-auto px-4 sm:px-6 pb-12"},is="sensorium_token",Cu=gt({__name:"App",setup(e){const t=V(!1),s=V(""),n=V(""),o=V(!1),r=V(null),i=V("sessions");let l=null;const a=[{id:"sessions",label:"Sessions"},{id:"notes",label:"Memory Notes"},{id:"episodes",label:"Episodes"},{id:"topics",label:"Topics"},{id:"templates",label:"Templates"},{id:"skills",label:"Skills"}],p={sessions:na,notes:_a,episodes:Na,topics:za,templates:vc,skills:Gc},u=Et(()=>p[i.value]),d=Et(()=>{if(!r.value)return"—";const W=Math.floor(r.value.uptime),A=Math.floor(W/86400),F=Math.floor(W%86400/3600),z=Math.floor(W%3600/60);return A>0?`${A}d ${F}h`:F>0?`${F}h ${z}m`:`${z}m`});async function g(){const W=s.value.trim()||"no-auth";o.value=!0,n.value="";try{Lt(W),await K(),localStorage.setItem(is,W),t.value=!0,I()}catch(A){const F=A;F.status===401?n.value="Invalid token":n.value=F.message??"Connection failed",Lt("")}finally{o.value=!1}}function C(){localStorage.removeItem(is),t.value=!1,s.value="",r.value=null,l&&clearInterval(l),Lt("")}async function K(){r.value=await de("/api/status")}function I(){l&&clearInterval(l),l=setInterval(K,3e4)}return xt(async()=>{const W=localStorage.getItem(is);if(W){s.value=W;try{Lt(W),await K(),t.value=!0,I()}catch{localStorage.removeItem(is),Lt("")}}}),hn(()=>{l&&clearInterval(l)}),(W,A)=>{var F,z,M,R,P,L,oe,Z,ce,ke,qe;return t.value?($(),k("div",eu,[h("header",tu,[h("div",su,[A[3]||(A[3]=je('<div class="flex items-center gap-3"><div class="w-8 h-8 rounded-lg bg-gradient-to-br from-accent to-purple-500 flex items-center justify-center"><span class="text-white text-sm font-bold">S</span></div><div><h1 class="text-lg font-semibold tracking-tight">Sensorium MCP</h1><p class="text-xs text-textSecondary">Agent Dashboard</p></div></div>',1)),h("div",nu,[A[2]||(A[2]=h("div",{class:"flex items-center gap-2 text-sm"},[h("span",{class:"w-2 h-2 rounded-full bg-success animate-pulse-slow"}),h("span",{class:"text-textSecondary"},"Connected")],-1)),h("div",ou,N(d.value),1),h("button",{onClick:C,class:"text-sm text-muted hover:text-textSecondary transition"},"Disconnect")])])]),h("div",ru,[h("div",iu,[h("div",lu,[A[4]||(A[4]=je('<div class="flex items-center gap-2 mb-2"><span class="text-success"><svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z"></path></svg></span><span class="text-xs text-textSecondary font-medium uppercase tracking-wider">Sessions</span></div>',1)),h("div",au,N(((F=r.value)==null?void 0:F.activeSessions)??0),1)]),h("div",cu,[A[5]||(A[5]=je('<div class="flex items-center gap-2 mb-2"><span class="text-accentLight"><svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path></svg></span><span class="text-xs text-textSecondary font-medium uppercase tracking-wider">Notes</span></div>',1)),h("div",uu,N(((M=(z=r.value)==null?void 0:z.memory)==null?void 0:M.totalSemanticNotes)??0),1)]),h("div",fu,[A[6]||(A[6]=je('<div class="flex items-center gap-2 mb-2"><span class="text-warn"><svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path></svg></span><span class="text-xs text-textSecondary font-medium uppercase tracking-wider">Episodes</span></div>',1)),h("div",du,N(((P=(R=r.value)==null?void 0:R.memory)==null?void 0:P.totalEpisodes)??0),1)]),h("div",pu,[h("div",hu,[h("span",{class:Se((((oe=(L=r.value)==null?void 0:L.memory)==null?void 0:oe.unconsolidatedEpisodes)??0)>10?"text-danger":"text-success")},[...A[7]||(A[7]=[h("svg",{class:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[h("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"})],-1)])],2),A[8]||(A[8]=h("span",{class:"text-xs text-textSecondary font-medium uppercase tracking-wider"},"Unconsolidated",-1))]),h("div",mu,N(((ce=(Z=r.value)==null?void 0:Z.memory)==null?void 0:ce.unconsolidatedEpisodes)??0),1)]),h("div",gu,[A[9]||(A[9]=je('<div class="flex items-center gap-2 mb-2"><span class="text-accent"><svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.066 2.573c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.573 1.066c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.066-2.573c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path></svg></span><span class="text-xs text-textSecondary font-medium uppercase tracking-wider">Procedures</span></div>',1)),h("div",xu,N(((qe=(ke=r.value)==null?void 0:ke.memory)==null?void 0:qe.totalProcedures)??0),1)]),h("div",vu,[A[10]||(A[10]=je('<div class="flex items-center gap-2 mb-2"><span class="text-success"><svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14M12 5l7 7-7 7"></path></svg></span><span class="text-xs text-textSecondary font-medium uppercase tracking-wider">Uptime</span></div>',1)),h("div",yu,N(d.value),1)])])]),h("div",bu,[h("nav",_u,[($(),k(ae,null,nt(a,Ce=>h("button",{key:Ce.id,onClick:U=>i.value=Ce.id,class:Se(["pb-3 text-sm font-medium transition",i.value===Ce.id?"tab-active":"tab-inactive"])},N(Ce.label),11,wu)),64))])]),h("div",Su,[($(),ir($i(u.value),{status:r.value},null,8,["status"]))])])):($(),k("div",Yc,[h("div",Zc,[A[1]||(A[1]=je('<div class="flex items-center gap-3 mb-6"><div class="w-10 h-10 rounded-xl bg-accent/20 flex items-center justify-center"><svg class="w-5 h-5 text-accent" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"></path></svg></div><div><h2 class="text-lg font-semibold">Sensorium MCP</h2><p class="text-sm text-textSecondary">Enter your API token</p></div></div>',1)),ye(h("input",{"onUpdate:modelValue":A[0]||(A[0]=Ce=>s.value=Ce),type:"password",placeholder:"MCP_HTTP_SECRET",class:"w-full px-4 py-3 rounded-xl bg-surface border border-gray-700 text-textPrimary placeholder-muted focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent transition font-mono text-sm",onKeydown:Nl(g,["enter"])},null,544),[[Ue,s.value]]),h("button",{onClick:g,disabled:o.value,class:"w-full mt-4 px-4 py-3 rounded-xl bg-accent hover:bg-accentLight disabled:opacity-50 text-white font-medium transition"},N(o.value?"Connecting...":"Connect"),9,Qc),n.value?($(),k("p",Xc,N(n.value),1)):pe("",!0)])]))}}});Hl(Cu).mount("#app");</script>
|
|
93
|
+
</head>
|
|
94
|
+
<body class="font-sans text-textPrimary min-h-screen">
|
|
95
|
+
<div id="app"></div>
|
|
96
|
+
</body>
|
|
97
|
+
</html>
|