@newsails/veil-cli 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.veil/agents/analyst/AGENT.md +21 -0
- package/.veil/agents/analyst/agent.json +23 -0
- package/.veil/agents/assistant/AGENT.md +15 -0
- package/.veil/agents/assistant/agent.json +19 -0
- package/.veil/agents/coder/AGENT.md +18 -0
- package/.veil/agents/coder/agent.json +19 -0
- package/.veil/agents/hello/AGENT.md +5 -0
- package/.veil/agents/hello/agent.json +13 -0
- package/.veil/agents/writer/AGENT.md +12 -0
- package/.veil/agents/writer/agent.json +17 -0
- package/.veil/memory/MEMORY.md +343 -0
- package/.veil/memory/agents/analyst/MEMORY.md +55 -0
- package/.veil/memory/agents/hello/MEMORY.md +12 -0
- package/.veil/runtime.pid +1 -0
- package/.veil/settings.json +10 -0
- package/.veil-studio/studio.db +0 -0
- package/.veil-studio/studio.db-shm +0 -0
- package/.veil-studio/studio.db-wal +0 -0
- package/PLAN/01-vision.md +26 -0
- package/PLAN/02-tech-stack.md +94 -0
- package/PLAN/03-agents.md +232 -0
- package/PLAN/04-runtime.md +171 -0
- package/PLAN/05-tools.md +211 -0
- package/PLAN/06-communication.md +243 -0
- package/PLAN/07-storage.md +218 -0
- package/PLAN/08-api-cli.md +153 -0
- package/PLAN/09-permissions.md +108 -0
- package/PLAN/10-ably.md +105 -0
- package/PLAN/11-file-formats.md +442 -0
- package/PLAN/12-folder-structure.md +205 -0
- package/PLAN/13-operations.md +212 -0
- package/PLAN/README.md +23 -0
- package/README.md +128 -0
- package/REPORT.md +174 -0
- package/TODO.md +45 -0
- package/ai-tests/FRONTEND_PROMPT.md +220 -0
- package/ai-tests/Research & Planning.md +814 -0
- package/ai-tests/prompt-001-basic-api.md +230 -0
- package/ai-tests/prompt-002-basic-flows.md +230 -0
- package/ai-tests/prompt-003-agent-behaviors.md +220 -0
- package/api/middleware.js +60 -0
- package/api/routes/agents.js +193 -0
- package/api/routes/chat.js +93 -0
- package/api/routes/completions.js +122 -0
- package/api/routes/daemons.js +80 -0
- package/api/routes/memory.js +169 -0
- package/api/routes/models.js +40 -0
- package/api/routes/remote-methods.js +74 -0
- package/api/routes/sessions.js +208 -0
- package/api/routes/settings.js +108 -0
- package/api/routes/system.js +50 -0
- package/api/routes/tasks.js +270 -0
- package/api/server.js +120 -0
- package/cli/formatter.js +70 -0
- package/cli/index.js +443 -0
- package/cli/parser.js +113 -0
- package/config/config.json +10 -0
- package/config/models.json +6826 -0
- package/core/agent.js +329 -0
- package/core/cancel.js +38 -0
- package/core/compaction.js +176 -0
- package/core/events.js +13 -0
- package/core/loop.js +564 -0
- package/core/memory.js +51 -0
- package/core/prompt.js +185 -0
- package/core/queue.js +96 -0
- package/core/registry.js +291 -0
- package/core/remote-methods.js +124 -0
- package/core/router.js +386 -0
- package/core/running-sessions.js +18 -0
- package/docs/api/01-system.md +84 -0
- package/docs/api/02-agents.md +374 -0
- package/docs/api/03-chat.md +269 -0
- package/docs/api/04-tasks.md +470 -0
- package/docs/api/05-sessions.md +444 -0
- package/docs/api/06-daemons.md +142 -0
- package/docs/api/07-memory.md +186 -0
- package/docs/api/08-settings.md +133 -0
- package/docs/api/09-models.md +119 -0
- package/docs/api/09-websocket.md +350 -0
- package/docs/api/10-completions.md +134 -0
- package/docs/api/README.md +116 -0
- package/docs/guide/01-quickstart.md +220 -0
- package/docs/guide/02-folder-structure.md +185 -0
- package/docs/guide/03-configuration.md +252 -0
- package/docs/guide/04-agents.md +267 -0
- package/docs/guide/05-cli.md +290 -0
- package/docs/guide/06-tools.md +643 -0
- package/docs/guide/07-permissions.md +236 -0
- package/docs/guide/08-memory.md +139 -0
- package/docs/guide/09-multi-agent.md +271 -0
- package/docs/guide/10-daemons.md +226 -0
- package/docs/guide/README.md +53 -0
- package/docs/index.html +623 -0
- package/examples/README.md +151 -0
- package/examples/agents/assistant/AGENT.md +31 -0
- package/examples/agents/assistant/SOUL.md +9 -0
- package/examples/agents/assistant/agent.json +74 -0
- package/examples/agents/hello/AGENT.md +15 -0
- package/examples/agents/hello/agent.json +14 -0
- package/examples/agents/monitor/AGENT.md +51 -0
- package/examples/agents/monitor/agent.json +33 -0
- package/examples/agents/monitor/heartbeats/monitor.md +24 -0
- package/examples/agents/orchestrator/AGENT.md +70 -0
- package/examples/agents/orchestrator/agent.json +30 -0
- package/examples/agents/researcher/AGENT.md +52 -0
- package/examples/agents/researcher/agent.json +49 -0
- package/examples/agents/researcher/skills/web-research.md +28 -0
- package/examples/skills/code-review.md +72 -0
- package/examples/skills/summarise.md +59 -0
- package/examples/skills/web-research.md +42 -0
- package/examples/tools/word-count/index.js +27 -0
- package/examples/tools/word-count/tool.json +18 -0
- package/infrastructure/database.js +563 -0
- package/infrastructure/scheduler.js +122 -0
- package/llm/client.js +206 -0
- package/migrations/001-initial.sql +121 -0
- package/migrations/002-debuggability.sql +13 -0
- package/migrations/003-drop-orphaned-columns.sql +72 -0
- package/migrations/004-session-message-token-fields.sql +78 -0
- package/migrations/005-session-thinking.sql +5 -0
- package/package.json +30 -0
- package/schemas/agent.json +143 -0
- package/schemas/settings.json +111 -0
- package/scripts/fetch-models.js +93 -0
- package/session-debug-scenario.md +248 -0
- package/settings/fields.js +52 -0
- package/system-prompts/base-core.md +7 -0
- package/system-prompts/environment.md +13 -0
- package/system-prompts/reminders/anti-drift.md +6 -0
- package/system-prompts/reminders/stall-recovery.md +10 -0
- package/system-prompts/safety-rules.md +25 -0
- package/system-prompts/task-heuristics.md +27 -0
- package/test/client.js +71 -0
- package/test/integration/01-health.test.js +25 -0
- package/test/integration/02-agents.test.js +80 -0
- package/test/integration/03-chat-hello.test.js +48 -0
- package/test/integration/04-chat-multiturn.test.js +61 -0
- package/test/integration/05-chat-writer.test.js +48 -0
- package/test/integration/06-task-basic.test.js +68 -0
- package/test/integration/07-task-tools.test.js +74 -0
- package/test/integration/08-task-code-analysis.test.js +69 -0
- package/test/integration/09-memory-analyst.test.js +63 -0
- package/test/integration/10-task-advanced.test.js +85 -0
- package/test/integration/11-sessions-advanced.test.js +84 -0
- package/test/integration/12-assistant-chat-tools.test.js +75 -0
- package/test/integration/13-edge-cases.test.js +99 -0
- package/test/integration/14-cancel.test.js +62 -0
- package/test/integration/15-debug.test.js +106 -0
- package/test/integration/16-memory-api.test.js +83 -0
- package/test/integration/17-settings-api.test.js +41 -0
- package/test/integration/18-tool-search-activation.test.js +119 -0
- package/test/results/.gitkeep +0 -0
- package/test/runner.js +206 -0
- package/test/smoke.js +216 -0
- package/tools/agent_message.js +85 -0
- package/tools/agent_send.js +80 -0
- package/tools/agent_spawn.js +44 -0
- package/tools/bash.js +49 -0
- package/tools/edit_file.js +41 -0
- package/tools/glob.js +64 -0
- package/tools/grep.js +82 -0
- package/tools/list_dir.js +63 -0
- package/tools/log_write.js +31 -0
- package/tools/memory_read.js +38 -0
- package/tools/memory_search.js +65 -0
- package/tools/memory_write.js +42 -0
- package/tools/read_file.js +48 -0
- package/tools/sleep.js +22 -0
- package/tools/task_create.js +41 -0
- package/tools/task_respond.js +37 -0
- package/tools/task_spawn.js +64 -0
- package/tools/task_status.js +39 -0
- package/tools/task_subscribe.js +37 -0
- package/tools/todo_read.js +26 -0
- package/tools/todo_write.js +38 -0
- package/tools/tool_activate.js +24 -0
- package/tools/tool_search.js +24 -0
- package/tools/web_fetch.js +50 -0
- package/tools/web_search.js +52 -0
- package/tools/write_file.js +28 -0
- package/ui/api.js +190 -0
- package/ui/app.js +281 -0
- package/ui/index.html +382 -0
- package/ui/views/agents.js +377 -0
- package/ui/views/chat.js +610 -0
- package/ui/views/connection.js +96 -0
- package/ui/views/daemons.js +129 -0
- package/ui/views/feed.js +194 -0
- package/ui/views/memory.js +263 -0
- package/ui/views/models.js +146 -0
- package/ui/views/sessions.js +314 -0
- package/ui/views/settings.js +142 -0
- package/ui/views/tasks.js +415 -0
- package/utils/context.js +49 -0
- package/utils/id.js +16 -0
- package/utils/models.js +88 -0
- package/utils/paths.js +213 -0
- package/utils/settings.js +172 -0
package/ui/app.js
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
window.Veil = window.Veil || {};
|
|
4
|
+
const KB = window.Veil;
|
|
5
|
+
|
|
6
|
+
KB.state = {
|
|
7
|
+
connected: false,
|
|
8
|
+
serverUrl: '',
|
|
9
|
+
secret: '',
|
|
10
|
+
api: null,
|
|
11
|
+
currentAgent: null,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/* ── Utilities ──────────────────────────────────────────────────────── */
|
|
15
|
+
KB.utils = {
|
|
16
|
+
esc(s) {
|
|
17
|
+
if (s == null) return '';
|
|
18
|
+
return String(s)
|
|
19
|
+
.replace(/&/g,'&').replace(/</g,'<')
|
|
20
|
+
.replace(/>/g,'>').replace(/"/g,'"');
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
relTime(dateStr) {
|
|
24
|
+
if (!dateStr) return '—';
|
|
25
|
+
const diff = Date.now() - new Date(dateStr).getTime();
|
|
26
|
+
if (isNaN(diff)) return dateStr;
|
|
27
|
+
const s = Math.floor(diff / 1000);
|
|
28
|
+
if (s < 5) return 'just now';
|
|
29
|
+
if (s < 60) return s + 's ago';
|
|
30
|
+
const m = Math.floor(s / 60);
|
|
31
|
+
if (m < 60) return m + 'm ago';
|
|
32
|
+
const h = Math.floor(m / 60);
|
|
33
|
+
if (h < 24) return h + 'h ago';
|
|
34
|
+
const d = Math.floor(h / 24);
|
|
35
|
+
return d + 'd ago';
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
formatMs(ms) {
|
|
39
|
+
if (ms == null || ms < 0) return '—';
|
|
40
|
+
if (ms < 1000) return ms + 'ms';
|
|
41
|
+
if (ms < 60000) return (ms / 1000).toFixed(1) + 's';
|
|
42
|
+
return Math.floor(ms / 60000) + 'm ' + Math.floor((ms % 60000) / 1000) + 's';
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
formatCost(cost) {
|
|
46
|
+
if (cost == null || cost === 0) return '';
|
|
47
|
+
if (cost < 0.001) return '$' + cost.toFixed(6);
|
|
48
|
+
return '$' + cost.toFixed(4);
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
badge(status) {
|
|
52
|
+
return `<span class="badge badge-${KB.utils.esc(status)}">${KB.utils.esc(status)}</span>`;
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
spinner() {
|
|
56
|
+
return `<span class="spin" style="display:inline-block;width:13px;height:13px;border:2px solid var(--border2);border-top-color:var(--accent);border-radius:50%;"></span>`;
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
shortId(id) {
|
|
60
|
+
if (!id) return '—';
|
|
61
|
+
return id.length > 18 ? id.slice(0, 18) + '…' : id;
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
truncate(s, n) {
|
|
65
|
+
if (!s) return '';
|
|
66
|
+
s = String(s);
|
|
67
|
+
return s.length > n ? s.slice(0, n) + '…' : s;
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
toast(msg, type) {
|
|
71
|
+
const c = document.getElementById('toast-container');
|
|
72
|
+
if (!c) return;
|
|
73
|
+
const el = document.createElement('div');
|
|
74
|
+
const [bg, col, bc] =
|
|
75
|
+
type === 'error' ? ['var(--surface)', 'var(--red)', 'rgba(239,68,68,0.3)'] :
|
|
76
|
+
type === 'warn' ? ['var(--surface)', 'var(--yellow)', 'rgba(234,179,8,0.3)'] :
|
|
77
|
+
['var(--surface)', 'var(--green)', 'rgba(34,197,94,0.3)'];
|
|
78
|
+
el.style.cssText = `background:${bg};color:${col};border:1px solid ${bc};padding:10px 16px;border-radius:10px;font-size:13px;font-weight:500;pointer-events:auto;box-shadow:0 8px 24px rgba(0,0,0,0.5);animation:fadeIn 0.18s ease both;max-width:320px;`;
|
|
79
|
+
el.textContent = msg;
|
|
80
|
+
c.appendChild(el);
|
|
81
|
+
setTimeout(() => { if (el.parentNode) el.parentNode.removeChild(el); }, 3500);
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
fmtDate(d) {
|
|
85
|
+
if (!d) return '—';
|
|
86
|
+
return new Date(d).toLocaleString();
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
fmtTokens(inp, out, cost) {
|
|
90
|
+
const parts = [];
|
|
91
|
+
if (inp) parts.push(inp.toLocaleString() + ' in');
|
|
92
|
+
if (out) parts.push(out.toLocaleString() + ' out');
|
|
93
|
+
if (cost) parts.push(KB.utils.formatCost(cost));
|
|
94
|
+
return parts.join(' / ');
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
/* SVG circular context-window ring.
|
|
98
|
+
size = current context tokens, limit = model max (0/null = unknown).
|
|
99
|
+
tooltipLines = array of {label, value} for the hover tooltip. */
|
|
100
|
+
contextRing(size, limit, tooltipLines) {
|
|
101
|
+
if (!size) return '';
|
|
102
|
+
const R = 14, STROKE = 3, C = 2 * Math.PI * R;
|
|
103
|
+
const pct = limit ? Math.min(size / limit, 1) : 0;
|
|
104
|
+
const color = pct > 0.85 ? 'var(--red)' : pct > 0.60 ? 'var(--yellow)' : 'var(--green)';
|
|
105
|
+
const used = limit ? Math.round(pct * 100) + '%' : '?';
|
|
106
|
+
const dash = C * (1 - pct);
|
|
107
|
+
const dim = (R + STROKE) * 2;
|
|
108
|
+
const lines = (tooltipLines || []).map(l =>
|
|
109
|
+
`<div><strong>${KB.utils.esc(l.label)}:</strong> ${KB.utils.esc(String(l.value))}</div>`
|
|
110
|
+
).join('');
|
|
111
|
+
return `<span class="ctx-ring-wrap">
|
|
112
|
+
<svg width="${dim}" height="${dim}" viewBox="0 0 ${dim} ${dim}" style="transform:rotate(-90deg);">
|
|
113
|
+
<circle cx="${R+STROKE}" cy="${R+STROKE}" r="${R}" fill="none"
|
|
114
|
+
stroke="var(--border2)" stroke-width="${STROKE}"/>
|
|
115
|
+
<circle cx="${R+STROKE}" cy="${R+STROKE}" r="${R}" fill="none"
|
|
116
|
+
stroke="${color}" stroke-width="${STROKE}"
|
|
117
|
+
stroke-dasharray="${C}" stroke-dashoffset="${dash}"
|
|
118
|
+
stroke-linecap="round" style="transition:stroke-dashoffset 0.4s ease,stroke 0.4s ease;"/>
|
|
119
|
+
</svg>
|
|
120
|
+
<span style="position:absolute;font-size:8px;font-weight:700;color:${color};pointer-events:none;">${used}</span>
|
|
121
|
+
<span class="ctx-tooltip">${lines || '<div>No data</div>'}</span>
|
|
122
|
+
</span>`;
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/* ── Modal ──────────────────────────────────────────────────────────── */
|
|
127
|
+
KB.modal = {
|
|
128
|
+
show(html) {
|
|
129
|
+
document.getElementById('modal-box').innerHTML = html;
|
|
130
|
+
const o = document.getElementById('modal-overlay');
|
|
131
|
+
o.style.display = 'flex';
|
|
132
|
+
},
|
|
133
|
+
hide() {
|
|
134
|
+
document.getElementById('modal-overlay').style.display = 'none';
|
|
135
|
+
document.getElementById('modal-box').innerHTML = '';
|
|
136
|
+
},
|
|
137
|
+
onOverlayClick(e) {
|
|
138
|
+
if (e.target === document.getElementById('modal-overlay')) KB.modal.hide();
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
/* ── Connection management ──────────────────────────────────────────── */
|
|
143
|
+
KB.loadConnection = function() {
|
|
144
|
+
KB.state.serverUrl = window.__VEIL_API__ || localStorage.getItem('veil_url') || '';
|
|
145
|
+
KB.state.secret = window.__VEIL_SECRET__ || localStorage.getItem('veil_secret') || '';
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
KB.saveConnection = function(url, secret) {
|
|
149
|
+
KB.state.serverUrl = url;
|
|
150
|
+
KB.state.secret = secret;
|
|
151
|
+
localStorage.setItem('veil_url', url);
|
|
152
|
+
localStorage.setItem('veil_secret', secret);
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
KB.clearConnection = function() {
|
|
156
|
+
KB.state.connected = false;
|
|
157
|
+
KB.state.serverUrl = '';
|
|
158
|
+
KB.state.secret = '';
|
|
159
|
+
KB.state.api = null;
|
|
160
|
+
KB.state.currentAgent = null;
|
|
161
|
+
localStorage.removeItem('veil_url');
|
|
162
|
+
localStorage.removeItem('veil_secret');
|
|
163
|
+
KB._updateIndicator();
|
|
164
|
+
document.getElementById('sidebar').style.display = 'none';
|
|
165
|
+
KB.navigate('connection');
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
KB._updateIndicator = function() {
|
|
169
|
+
const dot = document.getElementById('conn-dot');
|
|
170
|
+
const text = document.getElementById('conn-text');
|
|
171
|
+
if (!dot || !text) return;
|
|
172
|
+
if (KB.state.connected) {
|
|
173
|
+
dot.style.background = 'var(--green)';
|
|
174
|
+
dot.style.boxShadow = '0 0 6px var(--green)';
|
|
175
|
+
const short = KB.state.serverUrl.replace(/^https?:\/\//, '');
|
|
176
|
+
text.style.display = 'flex';
|
|
177
|
+
text.style.alignItems = 'center';
|
|
178
|
+
text.style.gap = '4px';
|
|
179
|
+
text.innerHTML = `<span style="color:var(--text2);font-size:11.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;">${KB.utils.esc(short)}</span>`
|
|
180
|
+
+ `<button onclick="window.Veil.clearConnection()" style="flex-shrink:0;background:none;border:none;cursor:pointer;color:var(--text3);font-size:14px;line-height:1;padding:0 2px;font-family:inherit;" title="Disconnect" onmouseover="this.style.color='var(--red)'" onmouseout="this.style.color='var(--text3)'">⎋</button>`;
|
|
181
|
+
} else {
|
|
182
|
+
dot.style.background = 'var(--border2)';
|
|
183
|
+
dot.style.boxShadow = 'none';
|
|
184
|
+
text.style.display = '';
|
|
185
|
+
text.textContent = 'Not connected';
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
/* ── Router ─────────────────────────────────────────────────────────── */
|
|
190
|
+
let _currentView = null;
|
|
191
|
+
|
|
192
|
+
KB.navigate = function(route, params) {
|
|
193
|
+
params = params || {};
|
|
194
|
+
if (_currentView && _currentView.unmount) {
|
|
195
|
+
try { _currentView.unmount(); } catch {}
|
|
196
|
+
}
|
|
197
|
+
const view = KB.views[route];
|
|
198
|
+
if (!view) {
|
|
199
|
+
KB.navigate('connection');
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
/* update nav highlight */
|
|
203
|
+
document.querySelectorAll('.nav-link').forEach(el => {
|
|
204
|
+
if (el.getAttribute('data-route') === route) {
|
|
205
|
+
el.classList.add('nav-active');
|
|
206
|
+
} else {
|
|
207
|
+
el.classList.remove('nav-active');
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
const main = document.getElementById('main-content');
|
|
211
|
+
main.innerHTML = view.render(params);
|
|
212
|
+
if (view.mount) view.mount(params);
|
|
213
|
+
_currentView = view;
|
|
214
|
+
/* update hash without triggering another hashchange */
|
|
215
|
+
if (route !== 'connection') {
|
|
216
|
+
history.replaceState(null, '', '#' + route);
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
window.addEventListener('hashchange', () => {
|
|
221
|
+
if (!KB.state.connected) return;
|
|
222
|
+
const route = location.hash.slice(1) || 'agents';
|
|
223
|
+
if (KB.views[route]) KB.navigate(route);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
/* ── Bootstrap ──────────────────────────────────────────────────────── */
|
|
227
|
+
KB.loadConnection();
|
|
228
|
+
|
|
229
|
+
if (KB.state.serverUrl) {
|
|
230
|
+
KB.state.api = new KB.API(KB.state.serverUrl, KB.state.secret);
|
|
231
|
+
KB.state.api.health()
|
|
232
|
+
.then(() => {
|
|
233
|
+
KB.state.connected = true;
|
|
234
|
+
KB._updateIndicator();
|
|
235
|
+
document.getElementById('sidebar').style.display = 'flex';
|
|
236
|
+
const route = location.hash.slice(1) || 'agents';
|
|
237
|
+
KB.navigate(KB.views[route] ? route : 'agents');
|
|
238
|
+
})
|
|
239
|
+
.catch(() => {
|
|
240
|
+
KB.state.connected = false;
|
|
241
|
+
KB.navigate('connection');
|
|
242
|
+
});
|
|
243
|
+
} else {
|
|
244
|
+
KB.navigate('connection');
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/* ── Electron embedded titlebar ─────────────────────────────────────── */
|
|
248
|
+
(function () {
|
|
249
|
+
if (typeof window === 'undefined' || !window.electronWin) return;
|
|
250
|
+
|
|
251
|
+
const bar = document.getElementById('electron-titlebar');
|
|
252
|
+
if (!bar) return;
|
|
253
|
+
|
|
254
|
+
bar.style.display = 'flex';
|
|
255
|
+
document.body.style.paddingTop = '34px';
|
|
256
|
+
|
|
257
|
+
const logo = document.getElementById('sidebar-logo');
|
|
258
|
+
if (logo) logo.style.display = 'none';
|
|
259
|
+
|
|
260
|
+
const titleEl = document.getElementById('tb-title');
|
|
261
|
+
const apiUrl = window.__VEIL_API__ || KB.state.serverUrl;
|
|
262
|
+
if (titleEl && apiUrl) {
|
|
263
|
+
const secret = window.__VEIL_SECRET__ || KB.state.secret || '';
|
|
264
|
+
fetch(apiUrl.replace(/\/$/, '') + '/status', {
|
|
265
|
+
headers: secret ? { 'X-Veil-Secret': secret } : {},
|
|
266
|
+
})
|
|
267
|
+
.then(r => r.json())
|
|
268
|
+
.then(data => {
|
|
269
|
+
if (data.cwd) {
|
|
270
|
+
const parts = data.cwd.replace(/\\/g, '/').split('/').filter(Boolean);
|
|
271
|
+
const name = parts[parts.length - 1] || data.cwd;
|
|
272
|
+
titleEl.textContent = 'VeilCLI\u2002|\u2002' + name;
|
|
273
|
+
}
|
|
274
|
+
})
|
|
275
|
+
.catch(() => {});
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
document.getElementById('tb-min').onclick = () => window.electronWin.minimize();
|
|
279
|
+
document.getElementById('tb-max').onclick = () => window.electronWin.maximize();
|
|
280
|
+
document.getElementById('tb-close').onclick = () => window.electronWin.close();
|
|
281
|
+
}());
|
package/ui/index.html
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>VeilCLI</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
|
+
<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">
|
|
10
|
+
<script src="https://cdn.jsdelivr.net/npm/marked@9/marked.min.js"></script>
|
|
11
|
+
<script src="https://cdn.jsdelivr.net/npm/dompurify@3/dist/purify.min.js"></script>
|
|
12
|
+
<style>
|
|
13
|
+
:root {
|
|
14
|
+
--bg: #0C0C10;
|
|
15
|
+
--surface: #13131A;
|
|
16
|
+
--surface2: #1A1A23;
|
|
17
|
+
--surface3: #22222E;
|
|
18
|
+
--border: #24242F;
|
|
19
|
+
--border2: #2E2E3C;
|
|
20
|
+
--text: #E2E2EE;
|
|
21
|
+
--text2: #8080A0;
|
|
22
|
+
--text3: #44445A;
|
|
23
|
+
--accent: #7C6AF0;
|
|
24
|
+
--accent-h: #6B5ADF;
|
|
25
|
+
--accent-glow: rgba(124,106,240,0.18);
|
|
26
|
+
--green: #22C55E;
|
|
27
|
+
--green-dim: rgba(34,197,94,0.12);
|
|
28
|
+
--red: #EF4444;
|
|
29
|
+
--red-dim: rgba(239,68,68,0.12);
|
|
30
|
+
--yellow: #EAB308;
|
|
31
|
+
--yellow-dim: rgba(234,179,8,0.12);
|
|
32
|
+
--blue: #3B82F6;
|
|
33
|
+
--blue-dim: rgba(59,130,246,0.12);
|
|
34
|
+
--radius: 10px;
|
|
35
|
+
--radius-sm: 7px;
|
|
36
|
+
--radius-lg: 14px;
|
|
37
|
+
--bg-alt: #09090D;
|
|
38
|
+
--bg-task: rgba(59,130,246,0.08);
|
|
39
|
+
--bg-chat: rgba(34,197,94,0.08);
|
|
40
|
+
--bg-daemon: rgba(234,179,8,0.08);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
44
|
+
|
|
45
|
+
body {
|
|
46
|
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
47
|
+
background: var(--bg);
|
|
48
|
+
color: var(--text);
|
|
49
|
+
font-size: 13.5px;
|
|
50
|
+
line-height: 1.55;
|
|
51
|
+
-webkit-font-smoothing: antialiased;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* ── Scrollbars ───────────────────────────────────── */
|
|
55
|
+
::-webkit-scrollbar { width: 4px; height: 4px; }
|
|
56
|
+
::-webkit-scrollbar-track { background: transparent; }
|
|
57
|
+
::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 4px; }
|
|
58
|
+
::-webkit-scrollbar-thumb:hover { background: var(--text3); }
|
|
59
|
+
|
|
60
|
+
/* ── Streaming cursor ─────────────────────────────── */
|
|
61
|
+
.streaming::after {
|
|
62
|
+
content: '│';
|
|
63
|
+
animation: cur-blink 1s step-start infinite;
|
|
64
|
+
color: var(--accent);
|
|
65
|
+
font-weight: 300;
|
|
66
|
+
}
|
|
67
|
+
@keyframes cur-blink { 50% { opacity: 0; } }
|
|
68
|
+
|
|
69
|
+
/* ── Nav ──────────────────────────────────────────── */
|
|
70
|
+
.nav-link {
|
|
71
|
+
display: flex; align-items: center; gap: 9px;
|
|
72
|
+
padding: 8px 10px; border-radius: var(--radius-sm);
|
|
73
|
+
font-size: 13px; font-weight: 450; color: var(--text2);
|
|
74
|
+
text-decoration: none; cursor: pointer;
|
|
75
|
+
transition: background 0.12s, color 0.12s;
|
|
76
|
+
user-select: none; margin: 1px 0;
|
|
77
|
+
}
|
|
78
|
+
.nav-link:hover { background: var(--surface2); color: var(--text); }
|
|
79
|
+
.nav-active { background: var(--accent-glow) !important; color: var(--text) !important; }
|
|
80
|
+
.nav-active .ni { color: var(--accent); }
|
|
81
|
+
|
|
82
|
+
/* ── Buttons ──────────────────────────────────────── */
|
|
83
|
+
.btn {
|
|
84
|
+
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
|
|
85
|
+
padding: 7px 14px; border-radius: var(--radius-sm);
|
|
86
|
+
font-size: 13px; font-weight: 500; font-family: inherit;
|
|
87
|
+
cursor: pointer; border: 1px solid transparent;
|
|
88
|
+
transition: background 0.12s, border-color 0.12s, opacity 0.12s, box-shadow 0.12s;
|
|
89
|
+
white-space: nowrap; user-select: none; outline: none;
|
|
90
|
+
}
|
|
91
|
+
.btn:disabled { opacity: 0.38; cursor: not-allowed; pointer-events: none; }
|
|
92
|
+
.btn-primary { background: var(--accent); color: #fff; border-color: var(--accent); }
|
|
93
|
+
.btn-primary:hover { background: var(--accent-h); border-color: var(--accent-h); box-shadow: 0 0 0 3px var(--accent-glow); }
|
|
94
|
+
.btn-secondary { background: var(--surface2); color: var(--text); border-color: var(--border2); }
|
|
95
|
+
.btn-secondary:hover { background: var(--surface3); border-color: var(--border2); }
|
|
96
|
+
.btn-ghost { background: transparent; color: var(--text2); border-color: transparent; }
|
|
97
|
+
.btn-ghost:hover { background: var(--surface2); color: var(--text); }
|
|
98
|
+
.btn-danger { background: var(--red-dim); color: var(--red); border-color: rgba(239,68,68,0.25); }
|
|
99
|
+
.btn-danger:hover { background: rgba(239,68,68,0.2); }
|
|
100
|
+
.btn-success { background: var(--green-dim); color: var(--green); border-color: rgba(34,197,94,0.25); }
|
|
101
|
+
.btn-success:hover { background: rgba(34,197,94,0.2); }
|
|
102
|
+
.btn-sm { padding: 4px 10px; font-size: 12px; border-radius: 6px; }
|
|
103
|
+
.btn-xs { padding: 2px 7px; font-size: 11px; border-radius: 5px; }
|
|
104
|
+
|
|
105
|
+
/* ── Inputs ───────────────────────────────────────── */
|
|
106
|
+
.input {
|
|
107
|
+
background: var(--surface2); border: 1px solid var(--border2);
|
|
108
|
+
border-radius: var(--radius-sm); padding: 8px 12px;
|
|
109
|
+
font-size: 13.5px; color: var(--text); font-family: inherit;
|
|
110
|
+
width: 100%; outline: none;
|
|
111
|
+
transition: border-color 0.15s, box-shadow 0.15s;
|
|
112
|
+
}
|
|
113
|
+
.input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); }
|
|
114
|
+
.input::placeholder { color: var(--text3); }
|
|
115
|
+
select.input { cursor: pointer; }
|
|
116
|
+
textarea.input { resize: vertical; }
|
|
117
|
+
textarea.mono { font-family: 'JetBrains Mono', 'Courier New', monospace; font-size: 12.5px; line-height: 1.6; }
|
|
118
|
+
|
|
119
|
+
/* ── Cards ────────────────────────────────────────── */
|
|
120
|
+
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; }
|
|
121
|
+
.card2 { background: var(--surface2); border: 1px solid var(--border2); border-radius: var(--radius); }
|
|
122
|
+
|
|
123
|
+
/* ── Badges ───────────────────────────────────────── */
|
|
124
|
+
.badge {
|
|
125
|
+
display: inline-flex; align-items: center;
|
|
126
|
+
padding: 2px 8px; border-radius: 999px;
|
|
127
|
+
font-size: 11px; font-weight: 600; letter-spacing: 0.02em;
|
|
128
|
+
}
|
|
129
|
+
.badge-pending { background: rgba(128,128,160,0.14); color: #9090B8; }
|
|
130
|
+
.badge-processing { background: var(--blue-dim); color: #60A5FA; }
|
|
131
|
+
.badge-finished { background: var(--green-dim); color: #4ADE80; }
|
|
132
|
+
.badge-failed { background: var(--red-dim); color: #F87171; }
|
|
133
|
+
.badge-waiting { background: var(--yellow-dim); color: #FCD34D; }
|
|
134
|
+
.badge-canceled { background: rgba(68,68,90,0.18); color: #6868A0; }
|
|
135
|
+
.badge-active { background: var(--green-dim); color: #4ADE80; }
|
|
136
|
+
.badge-closed { background: rgba(68,68,90,0.18); color: #6868A0; }
|
|
137
|
+
|
|
138
|
+
/* ── Messages ─────────────────────────────────────── */
|
|
139
|
+
.msg-user { background: var(--surface3); border-radius: 16px 16px 4px 16px; }
|
|
140
|
+
.msg-system { background: rgba(68,68,90,0.12); border: 1px solid var(--border); border-radius: 8px; color: var(--text2); font-size: 12px; }
|
|
141
|
+
.msg-tool { background: var(--bg); border: 1px solid var(--border2); border-radius: 8px; font-family: 'JetBrains Mono', monospace; font-size: 12px; }
|
|
142
|
+
|
|
143
|
+
/* ── Tool block ───────────────────────────────────── */
|
|
144
|
+
.tool-block { background: var(--bg); border: 1px solid var(--border2); border-radius: 8px; overflow: hidden; }
|
|
145
|
+
|
|
146
|
+
/* ── List items ───────────────────────────────────── */
|
|
147
|
+
.list-item { padding: 9px 12px; border-radius: var(--radius-sm); margin: 1px 4px; cursor: pointer; transition: background 0.1s; }
|
|
148
|
+
.list-item:hover { background: var(--surface2); }
|
|
149
|
+
.list-item.selected { background: var(--accent-glow); }
|
|
150
|
+
|
|
151
|
+
/* ── Panel header ─────────────────────────────────── */
|
|
152
|
+
.panel-header { padding: 10px 16px; border-bottom: 1px solid var(--border); font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text3); }
|
|
153
|
+
|
|
154
|
+
/* ── Timeline dot ──────────────────────────────────── */
|
|
155
|
+
.timeline-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; margin-top: 6px; }
|
|
156
|
+
|
|
157
|
+
/* ── Divider ──────────────────────────────────────── */
|
|
158
|
+
hr, .divider { border: none; border-top: 1px solid var(--border); }
|
|
159
|
+
|
|
160
|
+
/* ── Spinner ──────────────────────────────────────── */
|
|
161
|
+
.spin { animation: spin 0.7s linear infinite; display: inline-block; }
|
|
162
|
+
@keyframes spin { to { transform: rotate(360deg); } }
|
|
163
|
+
|
|
164
|
+
/* ── Animations ───────────────────────────────────── */
|
|
165
|
+
.fade-in { animation: fadeIn 0.18s ease both; }
|
|
166
|
+
@keyframes fadeIn { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; } }
|
|
167
|
+
|
|
168
|
+
/* ── Code / pre ───────────────────────────────────── */
|
|
169
|
+
pre { white-space: pre-wrap; word-break: break-all; font-family: 'JetBrains Mono', monospace; font-size: 12px; }
|
|
170
|
+
|
|
171
|
+
/* ── Markdown prose ────────────────────────────────── */
|
|
172
|
+
.msg-md { font-size: 14px; line-height: 1.65; color: var(--text); word-break: break-word; }
|
|
173
|
+
.msg-md p { margin: 0 0 10px; }
|
|
174
|
+
.msg-md p:last-child { margin-bottom: 0; }
|
|
175
|
+
.msg-md h1,.msg-md h2,.msg-md h3,.msg-md h4 { font-weight: 700; margin: 16px 0 8px; color: var(--text); line-height: 1.3; }
|
|
176
|
+
.msg-md h1 { font-size: 18px; } .msg-md h2 { font-size: 16px; } .msg-md h3 { font-size: 14.5px; } .msg-md h4 { font-size: 13.5px; }
|
|
177
|
+
.msg-md ul,.msg-md ol { margin: 6px 0 10px 20px; padding: 0; }
|
|
178
|
+
.msg-md li { margin: 3px 0; }
|
|
179
|
+
.msg-md code { font-family: 'JetBrains Mono', monospace; font-size: 12.5px; background: var(--surface2); border: 1px solid var(--border2); border-radius: 4px; padding: 1px 5px; color: var(--accent); }
|
|
180
|
+
.msg-md pre { background: var(--bg); border: 1px solid var(--border2); border-radius: 8px; padding: 12px 14px; overflow-x: auto; margin: 8px 0; }
|
|
181
|
+
.msg-md pre code { background: none; border: none; padding: 0; color: var(--text2); font-size: 12.5px; }
|
|
182
|
+
.msg-md blockquote { border-left: 3px solid var(--border2); margin: 8px 0; padding: 4px 12px; color: var(--text2); }
|
|
183
|
+
.msg-md table { border-collapse: collapse; width: 100%; margin: 8px 0; font-size: 13px; }
|
|
184
|
+
.msg-md th { background: var(--surface2); font-weight: 600; }
|
|
185
|
+
.msg-md th, .msg-md td { border: 1px solid var(--border); padding: 6px 10px; text-align: left; }
|
|
186
|
+
.msg-md a { color: var(--accent); text-decoration: none; } .msg-md a:hover { text-decoration: underline; }
|
|
187
|
+
.msg-md hr { border: none; border-top: 1px solid var(--border); margin: 12px 0; }
|
|
188
|
+
.msg-md strong { color: var(--text); font-weight: 600; }
|
|
189
|
+
|
|
190
|
+
/* ── Copy button ────────────────────────────────────── */
|
|
191
|
+
.msg-bubble-wrap { position: relative; }
|
|
192
|
+
.msg-copy-btn {
|
|
193
|
+
position: absolute; bottom: -10px; left: 65px;
|
|
194
|
+
opacity: 0; transition: opacity 0.15s;
|
|
195
|
+
background: var(--surface2); border: 1px solid var(--border2);
|
|
196
|
+
color: var(--text3); border-radius: 6px;
|
|
197
|
+
padding: 3px 8px; font-size: 11.5px; cursor: pointer;
|
|
198
|
+
font-family: inherit;
|
|
199
|
+
}
|
|
200
|
+
.msg-bubble-wrap:hover .msg-copy-btn { opacity: 1; }
|
|
201
|
+
.msg-copy-btn:hover { background: var(--surface3); color: var(--text); }
|
|
202
|
+
|
|
203
|
+
/* ── Context ring ───────────────────────────────────── */
|
|
204
|
+
.ctx-ring-wrap {
|
|
205
|
+
position: relative; display: inline-flex; align-items: center; justify-content: center;
|
|
206
|
+
cursor: default; flex-shrink: 0;
|
|
207
|
+
}
|
|
208
|
+
.ctx-ring-wrap svg { display: block; }
|
|
209
|
+
.ctx-tooltip {
|
|
210
|
+
display: none; position: absolute; top: calc(100% + 8px); right: 0;
|
|
211
|
+
background: var(--surface2); border: 1px solid var(--border2);
|
|
212
|
+
border-radius: 8px; padding: 10px 13px; min-width: 200px;
|
|
213
|
+
font-size: 12px; color: var(--text2); line-height: 1.7;
|
|
214
|
+
box-shadow: 0 8px 24px rgba(0,0,0,0.45); z-index: 200; white-space: nowrap;
|
|
215
|
+
}
|
|
216
|
+
.ctx-tooltip strong { color: var(--text); }
|
|
217
|
+
.ctx-ring-wrap:hover .ctx-tooltip { display: block; }
|
|
218
|
+
|
|
219
|
+
/* ── Thinking dots ──────────────────────────────────── */
|
|
220
|
+
.thinking-dots { color: var(--text3); font-size: 13.5px; font-style: italic; }
|
|
221
|
+
.thinking-dots::after {
|
|
222
|
+
content: '';
|
|
223
|
+
animation: thinkDots 1.2s steps(4, end) infinite;
|
|
224
|
+
}
|
|
225
|
+
@keyframes thinkDots {
|
|
226
|
+
0% { content: ''; }
|
|
227
|
+
25% { content: '.'; }
|
|
228
|
+
50% { content: '..'; }
|
|
229
|
+
75% { content: '...'; }
|
|
230
|
+
100% { content: ''; }
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/* ── Avatar ───────────────────────────────────────── */
|
|
234
|
+
.avatar {
|
|
235
|
+
width: 28px; height: 28px; border-radius: 50%;
|
|
236
|
+
display: flex; align-items: center; justify-content: center;
|
|
237
|
+
font-size: 11px; font-weight: 700; flex-shrink: 0;
|
|
238
|
+
text-transform: uppercase; letter-spacing: 0;
|
|
239
|
+
}
|
|
240
|
+
.avatar-accent { background: var(--accent-glow); color: var(--accent); }
|
|
241
|
+
.avatar-surface { background: var(--surface3); color: var(--text2); }
|
|
242
|
+
|
|
243
|
+
/* ── Info row ─────────────────────────────────────── */
|
|
244
|
+
.info-label { font-size: 10.5px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text3); margin-bottom: 3px; }
|
|
245
|
+
.info-value { font-size: 13.5px; color: var(--text); }
|
|
246
|
+
|
|
247
|
+
/* ── Electron embedded titlebar ─────────────────────── */
|
|
248
|
+
#electron-titlebar {
|
|
249
|
+
display: none;
|
|
250
|
+
position: fixed;
|
|
251
|
+
top: 0; left: 0; right: 0;
|
|
252
|
+
height: 34px;
|
|
253
|
+
background: var(--surface);
|
|
254
|
+
border-bottom: 1px solid var(--border);
|
|
255
|
+
-webkit-app-region: drag;
|
|
256
|
+
user-select: none;
|
|
257
|
+
z-index: 10000;
|
|
258
|
+
align-items: center;
|
|
259
|
+
padding: 0 6px 0 0;
|
|
260
|
+
}
|
|
261
|
+
.tb-win-btn {
|
|
262
|
+
-webkit-app-region: no-drag;
|
|
263
|
+
width: 28px; height: 28px;
|
|
264
|
+
border-radius: 6px;
|
|
265
|
+
border: none; cursor: pointer;
|
|
266
|
+
font-size: 14px; line-height: 1;
|
|
267
|
+
display: flex; align-items: center; justify-content: center;
|
|
268
|
+
background: transparent; color: var(--text3);
|
|
269
|
+
transition: background 0.12s, color 0.12s;
|
|
270
|
+
font-family: inherit;
|
|
271
|
+
}
|
|
272
|
+
.tb-win-btn:hover { background: var(--surface2); color: var(--text); }
|
|
273
|
+
#tb-close:hover { background: var(--red-dim); color: var(--red); }
|
|
274
|
+
|
|
275
|
+
/* ── Tab bar ──────────────────────────────────────── */
|
|
276
|
+
.tab-btn {
|
|
277
|
+
padding: 8px 14px; font-size: 13px; font-weight: 500;
|
|
278
|
+
color: var(--text2); background: none; border: none;
|
|
279
|
+
border-bottom: 2px solid transparent; cursor: pointer;
|
|
280
|
+
transition: color 0.12s, border-color 0.12s; font-family: inherit;
|
|
281
|
+
}
|
|
282
|
+
.tab-btn:hover { color: var(--text); }
|
|
283
|
+
.tab-active { color: var(--text) !important; border-bottom-color: var(--accent) !important; }
|
|
284
|
+
</style>
|
|
285
|
+
</head>
|
|
286
|
+
<body style="height:100vh;overflow:hidden;display:flex;">
|
|
287
|
+
|
|
288
|
+
<!-- Electron embedded titlebar — hidden in browser, shown when inside Veil Desktop -->
|
|
289
|
+
<div id="electron-titlebar">
|
|
290
|
+
<div style="flex:1;padding-left:10px;display:flex;align-items:center;gap:7px;-webkit-app-region:drag;pointer-events:none;">
|
|
291
|
+
<div style="width:20px;height:20px;background:linear-gradient(135deg,var(--accent),#5B8AF0);border-radius:5px;display:flex;align-items:center;justify-content:center;flex-shrink:0;">
|
|
292
|
+
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon></svg>
|
|
293
|
+
</div>
|
|
294
|
+
<span id="tb-title" style="font-size:13px;font-weight:600;color:var(--text);letter-spacing:-0.01em;">VeilCLI</span>
|
|
295
|
+
</div>
|
|
296
|
+
<div style="-webkit-app-region:no-drag;display:flex;gap:2px;align-items:center;">
|
|
297
|
+
<button id="tb-min" class="tb-win-btn" title="Minimize">–</button>
|
|
298
|
+
<button id="tb-max" class="tb-win-btn" title="Maximize">□</button>
|
|
299
|
+
<button id="tb-close" class="tb-win-btn" title="Close">✕</button>
|
|
300
|
+
</div>
|
|
301
|
+
</div>
|
|
302
|
+
|
|
303
|
+
<!-- Sidebar -->
|
|
304
|
+
<nav id="sidebar" style="display:none;width:210px;background:var(--surface);border-right:1px solid var(--border);flex-shrink:0;flex-direction:column;overflow:hidden;">
|
|
305
|
+
<!-- Logo -->
|
|
306
|
+
<div id="sidebar-logo" style="padding:13px 12px 11px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:9px;flex-shrink:0;">
|
|
307
|
+
<div style="width:28px;height:28px;background:linear-gradient(135deg,var(--accent),#5B8AF0);border-radius:8px;display:flex;align-items:center;justify-content:center;flex-shrink:0;box-shadow:0 2px 8px var(--accent-glow);">
|
|
308
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon></svg>
|
|
309
|
+
</div>
|
|
310
|
+
<span style="font-weight:700;font-size:14px;letter-spacing:-0.02em;">Veil DashBoard</span>
|
|
311
|
+
</div>
|
|
312
|
+
<!-- Nav links -->
|
|
313
|
+
<div style="flex:1;overflow-y:auto;padding:8px;">
|
|
314
|
+
<a href="#chat" data-route="chat" class="nav-link">
|
|
315
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>
|
|
316
|
+
Chat
|
|
317
|
+
</a>
|
|
318
|
+
<a href="#sessions" data-route="sessions" class="nav-link">
|
|
319
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>
|
|
320
|
+
Sessions
|
|
321
|
+
</a>
|
|
322
|
+
<a href="#agents" data-route="agents" class="nav-link">
|
|
323
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"></rect><circle cx="12" cy="5" r="2"></circle><path d="M12 7v4"></path><line x1="8" y1="16" x2="8" y2="16"></line><line x1="16" y1="16" x2="16" y2="16"></line></svg>
|
|
324
|
+
Agents
|
|
325
|
+
</a>
|
|
326
|
+
<a href="#tasks" data-route="tasks" class="nav-link">
|
|
327
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 11l3 3L22 4"></path><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"></path></svg>
|
|
328
|
+
Tasks
|
|
329
|
+
</a>
|
|
330
|
+
<a href="#daemons" data-route="daemons" class="nav-link">
|
|
331
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg>
|
|
332
|
+
Daemons
|
|
333
|
+
</a>
|
|
334
|
+
<a href="#memory" data-route="memory" class="nav-link">
|
|
335
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="16" height="16" rx="2"></rect><line x1="4" y1="9" x2="20" y2="9"></line><line x1="4" y1="14" x2="20" y2="14"></line><line x1="9" y1="4" x2="9" y2="20"></line><line x1="15" y1="4" x2="15" y2="20"></line></svg>
|
|
336
|
+
Memory
|
|
337
|
+
</a>
|
|
338
|
+
<a href="#settings" data-route="settings" class="nav-link">
|
|
339
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
|
|
340
|
+
Settings
|
|
341
|
+
</a>
|
|
342
|
+
<a href="#models" data-route="models" class="nav-link">
|
|
343
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 2 7 12 12 22 7 12 2"></polygon><polyline points="2 17 12 22 22 17"></polyline><polyline points="2 12 12 17 22 12"></polyline></svg>
|
|
344
|
+
Models
|
|
345
|
+
</a>
|
|
346
|
+
<a href="#feed" data-route="feed" class="nav-link">
|
|
347
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4.9 19.1C1 15.2 1 8.8 4.9 4.9"></path><path d="M7.8 16.2c-2.3-2.3-2.3-6.1 0-8.5"></path><circle cx="12" cy="12" r="2"></circle><path d="M16.2 7.8c2.3 2.3 2.3 6.1 0 8.5"></path><path d="M19.1 4.9C23 8.8 23 15.1 19.1 19"></path></svg>
|
|
348
|
+
Live Feed
|
|
349
|
+
</a>
|
|
350
|
+
</div>
|
|
351
|
+
<!-- Connection status -->
|
|
352
|
+
<div id="connection-indicator" style="padding:10px 12px;border-top:1px solid var(--border);display:flex;align-items:center;gap:7px;flex-shrink:0;">
|
|
353
|
+
<span id="conn-dot" style="display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--border2);transition:background 0.3s;flex-shrink:0;"></span>
|
|
354
|
+
<span id="conn-text" style="font-size:12px;color:var(--text3);flex:1;min-width:0;">Not connected</span>
|
|
355
|
+
</div>
|
|
356
|
+
</nav>
|
|
357
|
+
|
|
358
|
+
<!-- Main -->
|
|
359
|
+
<main id="main-content" style="flex:1;overflow:auto;background:var(--bg);"></main>
|
|
360
|
+
|
|
361
|
+
<!-- Toasts -->
|
|
362
|
+
<div id="toast-container" style="position:fixed;bottom:20px;right:20px;z-index:9999;display:flex;flex-direction:column;gap:8px;pointer-events:none;"></div>
|
|
363
|
+
|
|
364
|
+
<!-- Modal -->
|
|
365
|
+
<div id="modal-overlay" style="display:none;position:fixed;inset:0;z-index:9000;background:rgba(0,0,0,0.65);backdrop-filter:blur(6px);align-items:center;justify-content:center;" onclick="window.Veil.modal.onOverlayClick(event)">
|
|
366
|
+
<div id="modal-box" class="card fade-in" style="max-width:600px;width:90%;max-height:88vh;overflow:auto;padding:28px;border-radius:16px;border-color:var(--border2);"></div>
|
|
367
|
+
</div>
|
|
368
|
+
|
|
369
|
+
<script src="api.js"></script>
|
|
370
|
+
<script src="views/connection.js"></script>
|
|
371
|
+
<script src="views/agents.js"></script>
|
|
372
|
+
<script src="views/chat.js"></script>
|
|
373
|
+
<script src="views/tasks.js"></script>
|
|
374
|
+
<script src="views/sessions.js"></script>
|
|
375
|
+
<script src="views/daemons.js"></script>
|
|
376
|
+
<script src="views/memory.js"></script>
|
|
377
|
+
<script src="views/settings.js"></script>
|
|
378
|
+
<script src="views/models.js"></script>
|
|
379
|
+
<script src="views/feed.js"></script>
|
|
380
|
+
<script src="app.js"></script>
|
|
381
|
+
</body>
|
|
382
|
+
</html>
|