aegis-desktop 1.0.13 → 1.0.15

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.
Files changed (96) hide show
  1. package/SOURCE-OFFER.txt +9 -0
  2. package/bin/aegis.js +1 -32
  3. package/lib/account-key.js +1 -56
  4. package/lib/auto.js +1 -430
  5. package/lib/avatar/companion.js +1 -698
  6. package/lib/avatar/cosmetics.js +1 -532
  7. package/lib/avatar/events.js +1 -344
  8. package/lib/avatar/holder-turn.js +1 -350
  9. package/lib/avatar/holders.js +1 -612
  10. package/lib/avatar/identity.js +1 -641
  11. package/lib/avatar/level.js +1 -368
  12. package/lib/avatar/mirror.js +1 -524
  13. package/lib/avatar/persona.js +1 -388
  14. package/lib/avatar/profile.js +1 -977
  15. package/lib/avatar/register.js +1 -307
  16. package/lib/avatar/store.js +1 -472
  17. package/lib/avatar/tiers.js +1 -38
  18. package/lib/avatar/transfer.js +1 -415
  19. package/lib/avatar/turn.js +1 -216
  20. package/lib/avatar/voice.js +1 -328
  21. package/lib/avatar/xp.js +1 -404
  22. package/lib/deep-link.js +1 -120
  23. package/lib/fingerprint.js +2 -347
  24. package/lib/google-connect.js +1 -169
  25. package/lib/local/agents.js +1 -105
  26. package/lib/local/autonomous.js +1 -1045
  27. package/lib/local/claude-pro.js +1 -993
  28. package/lib/local/context.js +1 -95
  29. package/lib/local/engine.js +1 -3228
  30. package/lib/local/entitlement.js +1 -654
  31. package/lib/local/git-scope.js +1 -228
  32. package/lib/local/local.js +1 -2135
  33. package/lib/local/prompt.js +1 -275
  34. package/lib/local/queue.js +1 -560
  35. package/lib/local/session-rounds.js +1 -208
  36. package/lib/local/shell.js +1 -680
  37. package/lib/local/telemetry.js +1 -470
  38. package/lib/local/tools.js +1 -1238
  39. package/lib/local/turn-guard.js +1 -300
  40. package/lib/local/worktree-lock.js +1 -235
  41. package/lib/provider-key-mirror.js +1 -252
  42. package/lib/quick-launcher.js +1 -84
  43. package/lib/settings.js +1 -890
  44. package/lib/sync/memory-queue.js +1 -60
  45. package/lib/sync/persist-gate.js +1 -148
  46. package/lib/sync/sessions.js +1 -106
  47. package/lib/window-state.js +1 -66
  48. package/main.js +3 -4390
  49. package/package.json +3 -5
  50. package/preload.js +3 -628
  51. package/renderer/app.js +1 -6560
  52. package/renderer/avatar/assemble.js +1 -335
  53. package/renderer/avatar/avatar.js +1 -380
  54. package/renderer/avatar/cards.js +1 -141
  55. package/renderer/avatar/hud.js +1 -206
  56. package/renderer/avatar/machine.js +1 -213
  57. package/renderer/avatar/pane.js +1 -439
  58. package/renderer/avatar/parts.js +1 -437
  59. package/renderer/budget.js +1 -168
  60. package/renderer/companion.js +1 -223
  61. package/renderer/diff.js +1 -359
  62. package/renderer/diffview.js +1 -336
  63. package/renderer/fingerprint.js +3 -720
  64. package/renderer/markdown.js +1 -168
  65. package/renderer/provider-toolbar.js +1 -134
  66. package/renderer/providers.js +1 -259
  67. package/renderer/quick.js +1 -191
  68. package/renderer/stream-policy.js +1 -306
  69. package/renderer/transcript-view.js +1 -323
  70. package/renderer/usage.js +1 -1239
  71. package/vendor/aegis.js +1 -2054
  72. package/vendor/attest.js +1 -442
  73. package/vendor/authorship-key.js +1 -410
  74. package/vendor/auto-provision.js +1 -134
  75. package/vendor/brain-catalog.js +1 -268
  76. package/vendor/byok-catalog.js +1 -230
  77. package/vendor/credentials.js +1 -494
  78. package/vendor/device-fingerprint.js +1 -141
  79. package/vendor/drive-connect.js +1 -85
  80. package/vendor/drive-upload.js +1 -174
  81. package/vendor/env-file.js +1 -1273
  82. package/vendor/fingerprint.js +1 -1064
  83. package/vendor/foreign-memory.js +1 -669
  84. package/vendor/google-signin.js +1 -125
  85. package/vendor/hooks.js +1 -430
  86. package/vendor/model-discovery.js +1 -330
  87. package/vendor/platform.js +1 -937
  88. package/vendor/prefs.js +1 -351
  89. package/vendor/presence-constants.js +1 -107
  90. package/vendor/presence.js +1 -438
  91. package/vendor/record-vault.js +3 -1055
  92. package/vendor/session-store.js +1 -548
  93. package/vendor/topup.js +1 -297
  94. package/vendor/touch.js +1 -458
  95. package/vendor/update.js +1 -704
  96. package/vendor/user-models.js +1 -381
@@ -1,346 +1,3 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-or-later
2
2
  // Copyright (C) 2026 Niklas Borneklint — AEGIS Code (aegiscode) / Aegiscloud.
3
- // AEGIS Code (aegiscode) — source: https://github.com/aegisinfo/aegiscode-plugin
4
- // Conveying a modified copy, or running one as a network service, owes the
5
- // corresponding source under this licence (§5/§13) — see LICENSING.md.
6
- 'use strict';
7
-
8
- /**
9
- * events.js — the avatar's state machine, driven by real engine signals.
10
- *
11
- * Two decisions shape this file:
12
- *
13
- * 1. NO TIMERS INSIDE. A machine that owns a `setTimeout` is a machine that
14
- * leaks one, keeps the Electron process alive at quit, and cannot be tested
15
- * without sleeping. The caller passes `tick(now)` — main already has a clock
16
- * and the renderer already runs a frame loop — so idle-timeout behaviour is
17
- * deterministic and instant in tests.
18
- *
19
- * 2. UNKNOWN SIGNALS ARE NO-OPS, NEVER THROWS. The signals come from turn
20
- * assembly, the approval card, the queue progress renderer and the sync
21
- * status line — four places that will grow new events over time. A machine
22
- * that throws on an unrecognised signal turns every future feature into a
23
- * crash in the avatar, so the default transition is "stay put".
24
- *
25
- * The states are wired to signals that
26
- * already exist: turn start/stream/end, `tool.*` from the tool host, the
27
- * approval card, queue progress, and sync status. No new event bus.
28
- *
29
- * Pure: no DOM, no Electron, no fs.
30
- */
31
-
32
- const STATES = Object.freeze([
33
- 'idle',
34
- 'listening',
35
- 'thinking',
36
- 'reading',
37
- 'writing',
38
- 'running',
39
- 'awaiting-you',
40
- 'celebrating',
41
- 'dozing',
42
- 'error',
43
- ]);
44
-
45
- const SIGNALS = Object.freeze([
46
- 'turn.start',
47
- 'turn.stream',
48
- 'turn.end',
49
- 'tool.read',
50
- 'tool.write',
51
- 'tool.run',
52
- 'approval.card',
53
- 'approval.decided',
54
- 'queue.progress',
55
- 'sync.error',
56
- 'sync.ok',
57
- 'celebrate.done',
58
- 'poke',
59
- 'reset',
60
- 'idle.timeout',
61
- ]);
62
-
63
- /** Signals that mean "the user or the engine is doing something". */
64
- const ACTIVITY_SIGNALS = Object.freeze([
65
- 'turn.start',
66
- 'turn.stream',
67
- 'tool.read',
68
- 'tool.write',
69
- 'tool.run',
70
- 'approval.card',
71
- 'approval.decided',
72
- 'queue.progress',
73
- 'poke',
74
- ]);
75
-
76
- const DEFAULT_IDLE_TIMEOUT_MS = 5 * 60 * 1000;
77
-
78
- /** turn.end celebrates only when the turn actually produced something green. */
79
- function afterTurnEnd(meta) {
80
- return meta && meta.green ? 'celebrating' : 'idle';
81
- }
82
-
83
- /**
84
- * Transition table: state → signal → next state.
85
- *
86
- * A value may be a state name or a `(meta) => state` function. A missing entry
87
- * means no transition (state unchanged, `changed: false`).
88
- *
89
- * `sync.error` is listed on every non-error state rather than special-cased in
90
- * code, so reading the table tells you the whole machine.
91
- */
92
- const TABLE = Object.freeze({
93
- idle: {
94
- 'turn.start': 'listening',
95
- 'approval.card': 'awaiting-you',
96
- 'queue.progress': 'running',
97
- 'idle.timeout': 'dozing',
98
- 'sync.error': 'error',
99
- reset: 'idle',
100
- },
101
- listening: {
102
- 'turn.start': 'listening',
103
- 'turn.stream': 'thinking',
104
- 'tool.read': 'reading',
105
- 'tool.write': 'writing',
106
- 'tool.run': 'running',
107
- 'approval.card': 'awaiting-you',
108
- 'turn.end': afterTurnEnd,
109
- 'sync.error': 'error',
110
- reset: 'idle',
111
- },
112
- thinking: {
113
- 'turn.stream': 'thinking',
114
- 'tool.read': 'reading',
115
- 'tool.write': 'writing',
116
- 'tool.run': 'running',
117
- 'approval.card': 'awaiting-you',
118
- 'turn.end': afterTurnEnd,
119
- 'sync.error': 'error',
120
- reset: 'idle',
121
- },
122
- reading: {
123
- 'tool.read': 'reading',
124
- 'tool.write': 'writing',
125
- 'tool.run': 'running',
126
- 'turn.stream': 'thinking',
127
- 'approval.card': 'awaiting-you',
128
- 'turn.end': afterTurnEnd,
129
- 'sync.error': 'error',
130
- reset: 'idle',
131
- },
132
- writing: {
133
- 'tool.write': 'writing',
134
- 'tool.read': 'reading',
135
- 'tool.run': 'running',
136
- 'turn.stream': 'thinking',
137
- 'approval.card': 'awaiting-you',
138
- 'turn.end': afterTurnEnd,
139
- 'sync.error': 'error',
140
- reset: 'idle',
141
- },
142
- running: {
143
- 'tool.run': 'running',
144
- 'tool.read': 'reading',
145
- 'tool.write': 'writing',
146
- 'queue.progress': 'running',
147
- 'turn.stream': 'thinking',
148
- 'approval.card': 'awaiting-you',
149
- 'turn.end': afterTurnEnd,
150
- 'sync.error': 'error',
151
- reset: 'idle',
152
- },
153
- 'awaiting-you': {
154
- 'approval.card': 'awaiting-you',
155
- 'approval.decided': 'thinking',
156
- 'turn.end': afterTurnEnd,
157
- 'sync.error': 'error',
158
- reset: 'idle',
159
- },
160
- celebrating: {
161
- 'celebrate.done': 'idle',
162
- 'turn.start': 'listening',
163
- 'sync.error': 'error',
164
- reset: 'idle',
165
- },
166
- dozing: {
167
- poke: 'idle',
168
- 'turn.start': 'listening',
169
- 'approval.card': 'awaiting-you',
170
- 'sync.error': 'error',
171
- reset: 'idle',
172
- },
173
- error: {
174
- reset: 'idle',
175
- 'sync.ok': 'idle',
176
- 'turn.start': 'listening',
177
- 'sync.error': 'error',
178
- },
179
- });
180
-
181
- /**
182
- * Expression id per state. The renderer maps these to the persona's expression
183
- * pack; keeping the mapping here means the renderer needs no state knowledge.
184
- */
185
- const EXPRESSIONS = Object.freeze({
186
- idle: 'neutral',
187
- listening: 'attentive',
188
- thinking: 'focused',
189
- reading: 'focused',
190
- writing: 'focused',
191
- running: 'focused',
192
- 'awaiting-you': 'waiting',
193
- celebrating: 'happy',
194
- dozing: 'sleepy',
195
- error: 'concerned',
196
- });
197
-
198
- /** Is this a state we know how to draw / reason about? */
199
- function isState(state) {
200
- return STATES.includes(state);
201
- }
202
-
203
- function expressionFor(state) {
204
- return EXPRESSIONS[state] || 'neutral';
205
- }
206
-
207
- /**
208
- * Build a machine.
209
- *
210
- * @param {object} [opts]
211
- * @param {string} [opts.state] starting state (default 'idle')
212
- * @param {number} [opts.now] starting clock, ms
213
- * @param {number} [opts.idleTimeoutMs] silence before `idle` → `dozing`
214
- * @param {number} [opts.historyLimit] transition log length (default 64)
215
- */
216
- function createMachine(opts) {
217
- // A default parameter only covers `undefined`; `createMachine(null)` would
218
- // throw on property access. Construction is total on purpose — main builds
219
- // this from whatever the config file happened to contain.
220
- const o = opts && typeof opts === 'object' ? opts : {};
221
- const idleTimeoutMs = Number.isFinite(o.idleTimeoutMs) && o.idleTimeoutMs > 0
222
- ? o.idleTimeoutMs
223
- : DEFAULT_IDLE_TIMEOUT_MS;
224
- let state = isState(o.state) ? o.state : 'idle';
225
- let clock = Number.isFinite(o.now) ? o.now : 0;
226
- let lastActivity = clock;
227
- let tickCount = 0;
228
- const historyLimit = Number.isFinite(o.historyLimit) && o.historyLimit > 0 ? o.historyLimit : 64;
229
- const history = [];
230
- const listeners = new Set();
231
-
232
- function emit(event) {
233
- history.push(event);
234
- if (history.length > historyLimit) history.shift();
235
- for (const fn of listeners) {
236
- try {
237
- fn(event);
238
- } catch {
239
- // A subscriber that throws must not take the machine (or the turn) with
240
- // it — the state is already updated by the time listeners run.
241
- }
242
- }
243
- }
244
-
245
- /**
246
- * Send a signal.
247
- * @param {string} signal
248
- * @param {object} [meta] e.g. { green: true } on turn.end
249
- * @returns {{ changed: boolean, state: string, prev: string, signal: string }}
250
- */
251
- function send(signal, meta) {
252
- const prev = state;
253
- const row = TABLE[state] || {};
254
- const target = row[String(signal)];
255
- let next = state;
256
- if (typeof target === 'function') next = target(meta || {});
257
- else if (typeof target === 'string') next = target;
258
-
259
- if (!isState(next)) next = state;
260
- const changed = next !== prev;
261
- if (changed) {
262
- state = next;
263
- }
264
- if (ACTIVITY_SIGNALS.includes(String(signal))) {
265
- lastActivity = clock;
266
- }
267
- emit({ signal: String(signal), prev, state, changed, meta: meta || null, t: clock });
268
- return { changed, state, prev, signal: String(signal) };
269
- }
270
-
271
- /**
272
- * Advance the clock and let the machine decide whether silence has become
273
- * `dozing`. Returns the same shape as `send`, with `signal: null` when the
274
- * clock moved but nothing transitioned — the common case.
275
- *
276
- * Deliberately conservative: only `idle` dozes. A long-running turn, an open
277
- * approval card, or a stream that is thinking must never be interrupted by
278
- * the avatar falling asleep.
279
- */
280
- function tick(now) {
281
- if (Number.isFinite(now)) clock = Math.max(clock, now);
282
- tickCount += 1;
283
- if (state !== 'idle') return { changed: false, state, prev: state, signal: null };
284
- if (clock - lastActivity < idleTimeoutMs) return { changed: false, state, prev: state, signal: null };
285
- return send('idle.timeout');
286
- }
287
-
288
- return {
289
- get state() {
290
- return state;
291
- },
292
- get expression() {
293
- return expressionFor(state);
294
- },
295
- get lastActivity() {
296
- return lastActivity;
297
- },
298
- get ticks() {
299
- return tickCount;
300
- },
301
- history,
302
- send,
303
- tick,
304
- /** Set the clock without evaluating an idle timeout. */
305
- setNow(now) {
306
- if (Number.isFinite(now)) clock = Math.max(clock, now);
307
- return clock;
308
- },
309
- on(fn) {
310
- if (typeof fn !== 'function') throw new TypeError('listener must be a function');
311
- listeners.add(fn);
312
- return () => listeners.delete(fn);
313
- },
314
- reset(now) {
315
- listeners.clear();
316
- history.length = 0;
317
- state = 'idle';
318
- lastActivity = Number.isFinite(now) ? now : clock;
319
- return state;
320
- },
321
- };
322
- }
323
-
324
- /** Every (state, signal) pair the machine can act on. Used to fuzz the table. */
325
- function transitions() {
326
- const out = [];
327
- for (const state of STATES) {
328
- for (const signal of Object.keys(TABLE[state] || {})) {
329
- out.push({ state, signal });
330
- }
331
- }
332
- return out;
333
- }
334
-
335
- module.exports = {
336
- STATES,
337
- SIGNALS,
338
- ACTIVITY_SIGNALS,
339
- EXPRESSIONS,
340
- TABLE,
341
- DEFAULT_IDLE_TIMEOUT_MS,
342
- isState,
343
- expressionFor,
344
- createMachine,
345
- transitions,
346
- };
3
+ "use strict";const STATES=Object.freeze(["idle","listening","thinking","reading","writing","running","awaiting-you","celebrating","dozing","error"]),SIGNALS=Object.freeze(["turn.start","turn.stream","turn.end","tool.read","tool.write","tool.run","approval.card","approval.decided","queue.progress","sync.error","sync.ok","celebrate.done","poke","reset","idle.timeout"]),ACTIVITY_SIGNALS=Object.freeze(["turn.start","turn.stream","tool.read","tool.write","tool.run","approval.card","approval.decided","queue.progress","poke"]),DEFAULT_IDLE_TIMEOUT_MS=3e5;function afterTurnEnd(e){return e&&e.green?"celebrating":"idle"}const TABLE=Object.freeze({idle:{"turn.start":"listening","approval.card":"awaiting-you","queue.progress":"running","idle.timeout":"dozing","sync.error":"error",reset:"idle"},listening:{"turn.start":"listening","turn.stream":"thinking","tool.read":"reading","tool.write":"writing","tool.run":"running","approval.card":"awaiting-you","turn.end":afterTurnEnd,"sync.error":"error",reset:"idle"},thinking:{"turn.stream":"thinking","tool.read":"reading","tool.write":"writing","tool.run":"running","approval.card":"awaiting-you","turn.end":afterTurnEnd,"sync.error":"error",reset:"idle"},reading:{"tool.read":"reading","tool.write":"writing","tool.run":"running","turn.stream":"thinking","approval.card":"awaiting-you","turn.end":afterTurnEnd,"sync.error":"error",reset:"idle"},writing:{"tool.write":"writing","tool.read":"reading","tool.run":"running","turn.stream":"thinking","approval.card":"awaiting-you","turn.end":afterTurnEnd,"sync.error":"error",reset:"idle"},running:{"tool.run":"running","tool.read":"reading","tool.write":"writing","queue.progress":"running","turn.stream":"thinking","approval.card":"awaiting-you","turn.end":afterTurnEnd,"sync.error":"error",reset:"idle"},"awaiting-you":{"approval.card":"awaiting-you","approval.decided":"thinking","turn.end":afterTurnEnd,"sync.error":"error",reset:"idle"},celebrating:{"celebrate.done":"idle","turn.start":"listening","sync.error":"error",reset:"idle"},dozing:{poke:"idle","turn.start":"listening","approval.card":"awaiting-you","sync.error":"error",reset:"idle"},error:{reset:"idle","sync.ok":"idle","turn.start":"listening","sync.error":"error"}}),EXPRESSIONS=Object.freeze({idle:"neutral",listening:"attentive",thinking:"focused",reading:"focused",writing:"focused",running:"focused","awaiting-you":"waiting",celebrating:"happy",dozing:"sleepy",error:"concerned"});function isState(e){return STATES.includes(e)}function expressionFor(e){return EXPRESSIONS[e]||"neutral"}function createMachine(e){const r=e&&"object"==typeof e?e:{},t=Number.isFinite(r.idleTimeoutMs)&&r.idleTimeoutMs>0?r.idleTimeoutMs:3e5;let n=isState(r.state)?r.state:"idle",i=Number.isFinite(r.now)?r.now:0,o=i,a=0;const s=Number.isFinite(r.historyLimit)&&r.historyLimit>0?r.historyLimit:64,u=[],l=new Set;function d(e,r){const t=n,a=(TABLE[n]||{})[String(e)];let d=n;"function"==typeof a?d=a(r||{}):"string"==typeof a&&(d=a),isState(d)||(d=n);const g=d!==t;return g&&(n=d),ACTIVITY_SIGNALS.includes(String(e))&&(o=i),function(e){u.push(e),u.length>s&&u.shift();for(const r of l)try{r(e)}catch{}}({signal:String(e),prev:t,state:n,changed:g,meta:r||null,t:i}),{changed:g,state:n,prev:t,signal:String(e)}}return{get state(){return n},get expression(){return expressionFor(n)},get lastActivity(){return o},get ticks(){return a},history:u,send:d,tick:function(e){return Number.isFinite(e)&&(i=Math.max(i,e)),a+=1,"idle"!==n||i-o<t?{changed:!1,state:n,prev:n,signal:null}:d("idle.timeout")},setNow:e=>(Number.isFinite(e)&&(i=Math.max(i,e)),i),on(e){if("function"!=typeof e)throw new TypeError("listener must be a function");return l.add(e),()=>l.delete(e)},reset:e=>(l.clear(),u.length=0,n="idle",o=Number.isFinite(e)?e:i,n)}}function transitions(){const e=[];for(const r of STATES)for(const t of Object.keys(TABLE[r]||{}))e.push({state:r,signal:t});return e}module.exports={STATES:STATES,SIGNALS:SIGNALS,ACTIVITY_SIGNALS:ACTIVITY_SIGNALS,EXPRESSIONS:EXPRESSIONS,TABLE:TABLE,DEFAULT_IDLE_TIMEOUT_MS:3e5,isState:isState,expressionFor:expressionFor,createMachine:createMachine,transitions:transitions};