aegis-desktop 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/aegis.js +30 -0
- package/build/icon.png +0 -0
- package/lib/local/agents.js +102 -0
- package/lib/local/context.js +81 -0
- package/lib/local/engine.js +460 -0
- package/lib/local/ollama.js +77 -0
- package/lib/local/prompt.js +91 -0
- package/lib/local/providers.js +536 -0
- package/lib/local/shell.js +208 -0
- package/lib/local/tools.js +638 -0
- package/lib/settings.js +225 -0
- package/lib/sync/memory-queue.js +57 -0
- package/lib/sync/sessions.js +199 -0
- package/main.js +715 -0
- package/package.json +46 -0
- package/preload.js +168 -0
- package/renderer/app.js +1990 -0
- package/renderer/index.html +289 -0
- package/renderer/max-tokens.js +18 -0
- package/renderer/style.css +1454 -0
- package/vendor/aegis.js +694 -0
- package/vendor/foreign-memory.js +666 -0
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta
|
|
6
|
+
http-equiv="Content-Security-Policy"
|
|
7
|
+
content="default-src 'none'; script-src 'self'; style-src 'self' https://fonts.googleapis.com; font-src https://fonts.gstatic.com; img-src 'self' data:"
|
|
8
|
+
/>
|
|
9
|
+
<title>AEGIS Desktop</title>
|
|
10
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
11
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
12
|
+
<link
|
|
13
|
+
href="https://fonts.googleapis.com/css2?family=DM+Mono:ital,wght@0,300;0,400;0,500;1,400&family=Syne:wght@400;600;700;800&family=Ubuntu:ital,wght@0,400;0,500;0,700;1,400&display=swap"
|
|
14
|
+
rel="stylesheet"
|
|
15
|
+
/>
|
|
16
|
+
<link rel="stylesheet" href="style.css" />
|
|
17
|
+
</head>
|
|
18
|
+
<body>
|
|
19
|
+
<header class="topbar">
|
|
20
|
+
<h1>AEGIS <span class="accent">Desktop</span></h1>
|
|
21
|
+
<div class="conn">
|
|
22
|
+
<span class="dot" id="conn-dot"></span>
|
|
23
|
+
<span id="conn-text">connecting…</span>
|
|
24
|
+
</div>
|
|
25
|
+
<div class="spacer"></div>
|
|
26
|
+
<button type="button" id="new-chat" class="ghost-btn">New chat</button>
|
|
27
|
+
</header>
|
|
28
|
+
|
|
29
|
+
<main>
|
|
30
|
+
<aside class="side">
|
|
31
|
+
<section class="card">
|
|
32
|
+
<h2>Status</h2>
|
|
33
|
+
<dl>
|
|
34
|
+
<dt>app</dt><dd id="st-app">–</dd>
|
|
35
|
+
<dt>client</dt><dd id="st-client">–</dd>
|
|
36
|
+
<dt>endpoint</dt><dd id="st-base">–</dd>
|
|
37
|
+
<dt>key</dt><dd id="st-key">–</dd>
|
|
38
|
+
<dt>plan</dt><dd id="st-plan">–</dd>
|
|
39
|
+
<dt>balance</dt><dd id="st-balance">–</dd>
|
|
40
|
+
</dl>
|
|
41
|
+
<div class="api-key-row">
|
|
42
|
+
<input
|
|
43
|
+
type="password"
|
|
44
|
+
id="api-key-input"
|
|
45
|
+
placeholder="AEGIS API key"
|
|
46
|
+
autocomplete="off"
|
|
47
|
+
/>
|
|
48
|
+
<button type="button" id="api-key-save" class="ghost-btn">Save</button>
|
|
49
|
+
<button type="button" id="api-key-verify" class="ghost-btn">Verify</button>
|
|
50
|
+
</div>
|
|
51
|
+
<p class="hint" id="api-key-hint"></p>
|
|
52
|
+
</section>
|
|
53
|
+
|
|
54
|
+
<section class="card">
|
|
55
|
+
<h2>Model</h2>
|
|
56
|
+
<label for="class-select">Provider class</label>
|
|
57
|
+
<select id="class-select"></select>
|
|
58
|
+
|
|
59
|
+
<label for="model-select">Model</label>
|
|
60
|
+
<select id="model-select"></select>
|
|
61
|
+
<select id="model-preset" hidden title="Quick-fill a known model + base URL"></select>
|
|
62
|
+
<input
|
|
63
|
+
type="text"
|
|
64
|
+
id="model-input"
|
|
65
|
+
placeholder="type a model id — e.g. gpt-4o-mini"
|
|
66
|
+
autocomplete="off"
|
|
67
|
+
hidden
|
|
68
|
+
/>
|
|
69
|
+
|
|
70
|
+
<label for="max-tokens">Max tokens</label>
|
|
71
|
+
<div class="max-tokens-row">
|
|
72
|
+
<select id="max-tokens">
|
|
73
|
+
<option value="1024">1k</option>
|
|
74
|
+
<option value="4096" selected>4k</option>
|
|
75
|
+
<option value="16384">16k</option>
|
|
76
|
+
<option value="64000">64k</option>
|
|
77
|
+
<option value="300000">300k</option>
|
|
78
|
+
</select>
|
|
79
|
+
<label
|
|
80
|
+
class="flow-toggle"
|
|
81
|
+
for="max-tokens-adaptive"
|
|
82
|
+
title="Automatically use the highest output ceiling the selected model supports, up to 300k tokens, instead of the fixed choice above."
|
|
83
|
+
>
|
|
84
|
+
<input type="checkbox" id="max-tokens-adaptive" />
|
|
85
|
+
<span>adaptive</span>
|
|
86
|
+
</label>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<label
|
|
90
|
+
class="flow-toggle"
|
|
91
|
+
for="autonomous-toggle"
|
|
92
|
+
id="autonomous-toggle-wrap"
|
|
93
|
+
hidden
|
|
94
|
+
title="Let the model work autonomously: fan out to multiple reasoning workers and synthesize their findings into one answer. Aegis Cloud models only."
|
|
95
|
+
>
|
|
96
|
+
<input type="checkbox" id="autonomous-toggle" />
|
|
97
|
+
<span>work autonomously</span>
|
|
98
|
+
</label>
|
|
99
|
+
<div id="autonomous-controls" class="autonomous-controls" hidden>
|
|
100
|
+
<label for="autonomous-effort">Effort</label>
|
|
101
|
+
<select id="autonomous-effort">
|
|
102
|
+
<option value="low">low</option>
|
|
103
|
+
<option value="medium">medium</option>
|
|
104
|
+
<option value="high" selected>high</option>
|
|
105
|
+
</select>
|
|
106
|
+
<label for="autonomous-workers">Workers</label>
|
|
107
|
+
<input type="number" id="autonomous-workers" min="1" max="8" step="1" value="3" />
|
|
108
|
+
</div>
|
|
109
|
+
<p class="hint" id="model-hint"></p>
|
|
110
|
+
</section>
|
|
111
|
+
|
|
112
|
+
<section class="card">
|
|
113
|
+
<h2>Provider settings</h2>
|
|
114
|
+
<div id="settings-list"></div>
|
|
115
|
+
<p class="hint" id="settings-hint"></p>
|
|
116
|
+
</section>
|
|
117
|
+
|
|
118
|
+
<section class="card">
|
|
119
|
+
<h2>Sessions</h2>
|
|
120
|
+
<button type="button" id="sessions-refresh" class="ghost-btn">Refresh</button>
|
|
121
|
+
<button type="button" id="sync-now" class="ghost-btn">Sync now</button>
|
|
122
|
+
<ul class="sessions-list" id="sessions-list"></ul>
|
|
123
|
+
<p class="hint" id="sessions-hint"></p>
|
|
124
|
+
<p class="hint" id="sync-status"></p>
|
|
125
|
+
</section>
|
|
126
|
+
|
|
127
|
+
<section class="card">
|
|
128
|
+
<!-- The heading is the click target for the full memory inspector.
|
|
129
|
+
The button lives *inside* the h2 (not the reverse) because a
|
|
130
|
+
<button> may only contain phrasing content, and <h2> is not. -->
|
|
131
|
+
<h2>
|
|
132
|
+
<button
|
|
133
|
+
type="button"
|
|
134
|
+
class="card-title-btn"
|
|
135
|
+
id="memory-open"
|
|
136
|
+
title="Open the memory inspector — every entry with its source, tags and topics"
|
|
137
|
+
>
|
|
138
|
+
<span>Memory</span>
|
|
139
|
+
<span class="ctb-expand" aria-hidden="true">⤢</span>
|
|
140
|
+
</button>
|
|
141
|
+
</h2>
|
|
142
|
+
<form id="memory-search-form" class="memory-search">
|
|
143
|
+
<input
|
|
144
|
+
type="text"
|
|
145
|
+
id="memory-query"
|
|
146
|
+
placeholder="Search memory…"
|
|
147
|
+
autocomplete="off"
|
|
148
|
+
/>
|
|
149
|
+
<button type="submit" id="memory-search-btn">Search</button>
|
|
150
|
+
</form>
|
|
151
|
+
<ul class="memory-results" id="memory-results"></ul>
|
|
152
|
+
<textarea
|
|
153
|
+
id="memory-entry"
|
|
154
|
+
rows="2"
|
|
155
|
+
placeholder="Save a note to memory…"
|
|
156
|
+
></textarea>
|
|
157
|
+
<button type="button" id="memory-save-btn" class="btn-block">Save to memory</button>
|
|
158
|
+
<button type="button" id="memory-import-btn" class="btn-block">
|
|
159
|
+
Import from other AI tools…
|
|
160
|
+
</button>
|
|
161
|
+
<p class="hint" id="memory-hint"></p>
|
|
162
|
+
</section>
|
|
163
|
+
</aside>
|
|
164
|
+
|
|
165
|
+
<section class="chat">
|
|
166
|
+
<!-- Inert template: cloned into #messages by renderWelcome() so the
|
|
167
|
+
welcome markup lives in exactly one place and survives the
|
|
168
|
+
innerHTML clears in newChat()/openSession(). -->
|
|
169
|
+
<template id="welcome-template">
|
|
170
|
+
<div class="chat-welcome" id="chat-welcome">
|
|
171
|
+
<div class="chat-greeting-row">
|
|
172
|
+
<div class="glyph">✦</div>
|
|
173
|
+
<div class="title" id="chat-greeting">Hello</div>
|
|
174
|
+
</div>
|
|
175
|
+
<div class="sub">
|
|
176
|
+
Ask anything — or start with one of these.
|
|
177
|
+
</div>
|
|
178
|
+
<div class="chat-quick-actions">
|
|
179
|
+
<button class="chat-quick-pill" type="button" data-quick="Write a ">
|
|
180
|
+
<span class="qp-ic">✎</span>Write code
|
|
181
|
+
</button>
|
|
182
|
+
<button class="chat-quick-pill" type="button" data-quick="Explain how ">
|
|
183
|
+
<span class="qp-ic">✦</span>Explain a concept
|
|
184
|
+
</button>
|
|
185
|
+
<button
|
|
186
|
+
class="chat-quick-pill"
|
|
187
|
+
type="button"
|
|
188
|
+
data-quick="Help me debug this error: "
|
|
189
|
+
>
|
|
190
|
+
<span class="qp-ic">🐛</span>Debug an error
|
|
191
|
+
</button>
|
|
192
|
+
<button
|
|
193
|
+
class="chat-quick-pill"
|
|
194
|
+
type="button"
|
|
195
|
+
data-quick="Compare two approaches to "
|
|
196
|
+
>
|
|
197
|
+
<span class="qp-ic">⇄</span>Weigh two options
|
|
198
|
+
</button>
|
|
199
|
+
<button
|
|
200
|
+
class="chat-quick-pill"
|
|
201
|
+
type="button"
|
|
202
|
+
data-quick="Help me plan "
|
|
203
|
+
>
|
|
204
|
+
<span class="qp-ic">⊞</span>Plan a project
|
|
205
|
+
</button>
|
|
206
|
+
</div>
|
|
207
|
+
<div class="hints">
|
|
208
|
+
Enter to send · Shift+Enter for a newline · the discovery lane adds
|
|
209
|
+
two extra paths to every answer
|
|
210
|
+
</div>
|
|
211
|
+
</div>
|
|
212
|
+
</template>
|
|
213
|
+
<div class="messages" id="messages" aria-live="polite"></div>
|
|
214
|
+
<form class="composer" id="composer">
|
|
215
|
+
<textarea
|
|
216
|
+
id="prompt"
|
|
217
|
+
rows="2"
|
|
218
|
+
placeholder="Message AEGIS… (Enter to send, Shift+Enter for a newline)"
|
|
219
|
+
></textarea>
|
|
220
|
+
<div class="composer-side">
|
|
221
|
+
<label
|
|
222
|
+
class="flow-toggle"
|
|
223
|
+
for="explore-toggle"
|
|
224
|
+
title="After every answer, send the AI down two extra paths — an alternative angle and an unexpected discovery — shown as a horizontal discovery lane."
|
|
225
|
+
>
|
|
226
|
+
<input type="checkbox" id="explore-toggle" checked />
|
|
227
|
+
<span>discovery lane</span>
|
|
228
|
+
</label>
|
|
229
|
+
<button type="submit" id="send">Send</button>
|
|
230
|
+
</div>
|
|
231
|
+
</form>
|
|
232
|
+
</section>
|
|
233
|
+
</main>
|
|
234
|
+
|
|
235
|
+
<!-- Memory inspector: full-viewport translucent overlay opened from the
|
|
236
|
+
sidebar Memory heading. Markup is static and populated by
|
|
237
|
+
renderMemoryOverlay() — this renderer runs under CSP `script-src 'self'`,
|
|
238
|
+
so inline handlers would be dropped silently. -->
|
|
239
|
+
<div class="memory-overlay" id="memory-overlay" hidden>
|
|
240
|
+
<div class="memory-backdrop" id="memory-backdrop"></div>
|
|
241
|
+
<div
|
|
242
|
+
class="memory-panel"
|
|
243
|
+
role="dialog"
|
|
244
|
+
aria-modal="true"
|
|
245
|
+
aria-labelledby="memory-panel-title"
|
|
246
|
+
>
|
|
247
|
+
<header class="memory-panel-head">
|
|
248
|
+
<h2 id="memory-panel-title">Memory</h2>
|
|
249
|
+
<span class="memory-count" id="memory-count"></span>
|
|
250
|
+
<div class="spacer"></div>
|
|
251
|
+
<button type="button" id="memory-close" class="ghost-btn" title="Close (Esc)">
|
|
252
|
+
Close
|
|
253
|
+
</button>
|
|
254
|
+
</header>
|
|
255
|
+
|
|
256
|
+
<form class="memory-filters" id="memory-filters">
|
|
257
|
+
<input
|
|
258
|
+
type="text"
|
|
259
|
+
id="memory-overlay-query"
|
|
260
|
+
placeholder="Filter by text, tag, topic or source…"
|
|
261
|
+
autocomplete="off"
|
|
262
|
+
/>
|
|
263
|
+
<button type="submit">Filter</button>
|
|
264
|
+
<button type="button" id="memory-filters-clear" class="ghost-btn">Clear</button>
|
|
265
|
+
</form>
|
|
266
|
+
|
|
267
|
+
<div class="memory-chips" id="memory-chips"></div>
|
|
268
|
+
|
|
269
|
+
<div class="memory-scroll">
|
|
270
|
+
<ul class="memory-list" id="memory-list"></ul>
|
|
271
|
+
</div>
|
|
272
|
+
|
|
273
|
+
<div class="memory-actions">
|
|
274
|
+
<textarea
|
|
275
|
+
id="memory-overlay-entry"
|
|
276
|
+
rows="2"
|
|
277
|
+
placeholder="Save a note to memory…"
|
|
278
|
+
></textarea>
|
|
279
|
+
<button type="button" id="memory-overlay-save" class="btn-block">
|
|
280
|
+
Save to memory
|
|
281
|
+
</button>
|
|
282
|
+
</div>
|
|
283
|
+
</div>
|
|
284
|
+
</div>
|
|
285
|
+
|
|
286
|
+
<script src="max-tokens.js"></script>
|
|
287
|
+
<script src="app.js"></script>
|
|
288
|
+
</body>
|
|
289
|
+
</html>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pure per-model max-tokens ceiling math (plan Phase 5, product-plan §6.3).
|
|
5
|
+
* Standalone from app.js so it's requireable from a plain Node test without
|
|
6
|
+
* pulling in DOM/window.aegis — app.js only calls into it.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const FLAT_CEILING = 300000;
|
|
10
|
+
|
|
11
|
+
function maxTokensCeiling(meta) {
|
|
12
|
+
const raw = meta && Number(meta.max_output);
|
|
13
|
+
return Number.isFinite(raw) && raw > 0 ? Math.min(FLAT_CEILING, raw) : FLAT_CEILING;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
17
|
+
module.exports = { maxTokensCeiling, FLAT_CEILING };
|
|
18
|
+
}
|