aegis-desktop 0.8.35 → 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.
Files changed (97) hide show
  1. package/README.md +11 -0
  2. package/bin/aegis.js +5 -0
  3. package/lib/auto.js +5 -0
  4. package/lib/avatar/companion.js +5 -0
  5. package/lib/avatar/cosmetics.js +5 -0
  6. package/lib/avatar/events.js +5 -0
  7. package/lib/avatar/holder-turn.js +5 -0
  8. package/lib/avatar/holders.js +5 -0
  9. package/lib/avatar/identity.js +5 -0
  10. package/lib/avatar/level.js +5 -0
  11. package/lib/avatar/mirror.js +5 -0
  12. package/lib/avatar/persona.js +5 -0
  13. package/lib/avatar/profile.js +5 -0
  14. package/lib/avatar/register.js +5 -0
  15. package/lib/avatar/store.js +5 -0
  16. package/lib/avatar/tiers.js +5 -0
  17. package/lib/avatar/transfer.js +5 -0
  18. package/lib/avatar/turn.js +5 -0
  19. package/lib/avatar/voice.js +5 -0
  20. package/lib/avatar/xp.js +5 -0
  21. package/lib/deep-link.js +40 -1
  22. package/lib/fingerprint.js +5 -0
  23. package/lib/local/aegis-seal.mjs +5 -0
  24. package/lib/local/agents.js +5 -0
  25. package/lib/local/autonomous.js +86 -0
  26. package/lib/local/context.js +5 -0
  27. package/lib/local/covenant.js +5 -0
  28. package/lib/local/engine.js +463 -12
  29. package/lib/local/entitlement.js +5 -0
  30. package/lib/local/git-scope.js +5 -0
  31. package/lib/local/local.js +5 -0
  32. package/lib/local/prompt.js +5 -0
  33. package/lib/local/queue.js +5 -0
  34. package/lib/local/session-rounds.js +5 -0
  35. package/lib/local/shell.js +88 -9
  36. package/lib/local/telemetry.js +5 -0
  37. package/lib/local/tools.js +13 -6
  38. package/lib/local/turn-guard.js +5 -0
  39. package/lib/local/worktree-lock.js +5 -0
  40. package/lib/provider-key-mirror.js +5 -0
  41. package/lib/quick-launcher.js +5 -0
  42. package/lib/settings.js +5 -0
  43. package/lib/sync/memory-queue.js +5 -0
  44. package/lib/sync/persist-gate.js +5 -0
  45. package/lib/sync/sessions.js +5 -0
  46. package/lib/window-state.js +5 -0
  47. package/main.js +258 -6
  48. package/package.json +1 -1
  49. package/preload.js +26 -0
  50. package/renderer/app.js +344 -0
  51. package/renderer/avatar/assemble.js +5 -0
  52. package/renderer/avatar/avatar.css +7 -0
  53. package/renderer/avatar/avatar.js +5 -0
  54. package/renderer/avatar/cards.js +5 -0
  55. package/renderer/avatar/hud.js +5 -0
  56. package/renderer/avatar/machine.js +5 -0
  57. package/renderer/avatar/pane.js +5 -0
  58. package/renderer/avatar/parts.js +5 -0
  59. package/renderer/budget.js +5 -0
  60. package/renderer/diff.js +5 -0
  61. package/renderer/diffview.js +5 -0
  62. package/renderer/fingerprint.css +7 -0
  63. package/renderer/fingerprint.js +5 -0
  64. package/renderer/fonts/fonts.css +7 -0
  65. package/renderer/index.html +7 -0
  66. package/renderer/markdown.js +5 -0
  67. package/renderer/quick.css +7 -0
  68. package/renderer/quick.html +7 -0
  69. package/renderer/quick.js +5 -0
  70. package/renderer/stream-policy.js +5 -0
  71. package/renderer/style.css +21 -0
  72. package/renderer/transcript-view.js +5 -0
  73. package/renderer/usage.js +73 -1
  74. package/vendor/aegis.js +27 -0
  75. package/vendor/agent-gate.mjs +23 -0
  76. package/vendor/attest.js +5 -0
  77. package/vendor/authorship-key.js +5 -0
  78. package/vendor/auto-provision.js +5 -0
  79. package/vendor/brain-catalog.js +5 -0
  80. package/vendor/byok-catalog.js +48 -8
  81. package/vendor/credentials.js +5 -0
  82. package/vendor/device-fingerprint.js +5 -0
  83. package/vendor/env-file.js +5 -0
  84. package/vendor/fingerprint.js +5 -0
  85. package/vendor/foreign-memory.js +5 -0
  86. package/vendor/hooks.js +5 -0
  87. package/vendor/model-discovery.js +332 -0
  88. package/vendor/platform.js +5 -0
  89. package/vendor/prefs.js +5 -0
  90. package/vendor/presence-constants.js +5 -0
  91. package/vendor/presence.js +5 -0
  92. package/vendor/record-vault.js +5 -0
  93. package/vendor/session-store.js +5 -0
  94. package/vendor/topup.js +5 -0
  95. package/vendor/touch.js +5 -0
  96. package/vendor/update.js +5 -0
  97. package/vendor/user-models.js +383 -0
package/README.md CHANGED
@@ -101,6 +101,17 @@ the models that key unlocks appear as their own entries, one per provider.
101
101
  startup, and a provider with no key saved in Settings is resolved from it.
102
102
  3. Select the **Bring your own key** class and pick a model.
103
103
 
104
+ **A model the catalogue does not name yet.** Vendors ship models faster than any
105
+ client release, and the relay forwards whatever model string it is handed — so
106
+ Settings ends with an **Add model** row (provider + model id + *Add model*). It
107
+ writes the same `~/.aegiscode/models.json` the CLI's `/model-add` writes, so a
108
+ model added here appears in the terminal's `/models` immediately and one added
109
+ there appears in this picker on its next refresh; the row prints the file path,
110
+ which is also the bulk-edit path. The provider id is offered from the live
111
+ catalogue but you may type one, and a provider the relay takes no key for is
112
+ refused rather than stored (a declaration nothing can attach a key to would show
113
+ up in no picker at all). Each declared model gets a **Remove** row.
114
+
104
115
  **What it costs.** AEGIS pays your provider nothing on this lane, so there is no
105
116
  provider cost to take a margin on — instead your AEGIS account is charged a flat
106
117
  **handling fee** per 1k tokens, for the routing, prompt assembly, caching, tool
package/bin/aegis.js CHANGED
@@ -1,4 +1,9 @@
1
1
  #!/usr/bin/env node
2
+ // SPDX-License-Identifier: AGPL-3.0-or-later
3
+ // Copyright (C) 2026 Niklas Borneklint — AEGIS Code (aegiscode) / Aegiscloud.
4
+ // AEGIS Code (aegiscode) — source: https://github.com/aegisinfo/aegiscode-plugin
5
+ // Conveying a modified copy, or running one as a network service, owes the
6
+ // corresponding source under this licence (§5/§13) — see LICENSING.md.
2
7
  'use strict';
3
8
 
4
9
  /**
package/lib/auto.js CHANGED
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
package/lib/avatar/xp.js CHANGED
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
package/lib/deep-link.js CHANGED
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -14,6 +19,36 @@
14
19
  const PROTOCOL = 'aegis';
15
20
  const SCHEME_PREFIX = `${PROTOCOL}://`;
16
21
 
22
+ /**
23
+ * Ceilings on the two values a *remote* caller controls.
24
+ *
25
+ * Any web page or any other app on the machine can hand the OS an `aegis://`
26
+ * URL, so both fields are attacker-chosen input on a channel nobody authenticates
27
+ * (there is no "is this link from the user?" check, and there cannot be one for
28
+ * a custom scheme). Bounding them keeps a hostile link from parking megabytes of
29
+ * text in the composer, from filling the window with a wall of pre-filled prompt,
30
+ * or from using the deep link as a bulk data channel into a session that can run
31
+ * tools. The renderer pre-fills rather than auto-sends (renderer/app.js
32
+ * handleDeepLink), so the cost is bounded, but a pre-filled prompt is still the
33
+ * most direct route from "a page I visited" to "text the user is invited to send
34
+ * to a model with tools on".
35
+ *
36
+ * These are generous on purpose: a real hand-written link is a sentence or two.
37
+ */
38
+ const MAX_PROMPT_LENGTH = 2000;
39
+ /** Session ids are uuids (36 chars); the slack is for a future format, not a payload. */
40
+ const MAX_SESSION_ID_LENGTH = 128;
41
+ /**
42
+ * …and the charset is pinned too, because this id does not stay a string: the
43
+ * renderer's `open` handler hands it to openSession(), which loads the session
44
+ * by name. A hostile link could otherwise offer `../../…` or an absolute path
45
+ * and have the *renderer* ask main to open whatever that resolves to. Ids this
46
+ * app mints are `[0-9a-f-]`; anything outside a conservative id alphabet is not
47
+ * one of ours, so it is rejected rather than escaped or repaired.
48
+ */
49
+ const SESSION_ID_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;
50
+
51
+
17
52
  /** True for any string that looks like our protocol, cheap enough to filter
18
53
  * argv with before the full URL parse (which throws on most argv entries —
19
54
  * flags, file paths — so callers should not run it against every arg). */
@@ -44,11 +79,15 @@ function parseDeepLinkUrl(url) {
44
79
  if (action === 'open') {
45
80
  const sessionId = parsed.searchParams.get('session');
46
81
  if (!sessionId) return null;
82
+ if (sessionId.length > MAX_SESSION_ID_LENGTH) return null;
83
+ if (!SESSION_ID_PATTERN.test(sessionId)) return null;
47
84
  return { action: 'open', sessionId };
48
85
  }
49
86
 
50
87
  if (action === 'new') {
51
- return { action: 'new', prompt: parsed.searchParams.get('prompt') || '' };
88
+ const prompt = parsed.searchParams.get('prompt') || '';
89
+ if (prompt.length > MAX_PROMPT_LENGTH) return null;
90
+ return { action: 'new', prompt };
52
91
  }
53
92
 
54
93
  return null;
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -1,4 +1,9 @@
1
1
  #!/usr/bin/env node
2
+ // SPDX-License-Identifier: AGPL-3.0-or-later
3
+ // Copyright (C) 2026 Niklas Borneklint — AEGIS Code (aegiscode) / Aegiscloud.
4
+ // AEGIS Code (aegiscode) — source: https://github.com/aegisinfo/aegiscode-plugin
5
+ // Conveying a modified copy, or running one as a network service, owes the
6
+ // corresponding source under this licence (§5/§13) — see LICENSING.md.
2
7
  /**
3
8
  * aegis-seal.mjs — codec for ÆL/1 (AEGIS Encoded Language)
4
9
  *
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -73,6 +78,83 @@ const MAX_ROUND_STOPS = 3;
73
78
  */
74
79
  const WRITE_TOOLS = new Set(['writeFile', 'editFile']);
75
80
 
81
+ // ── Auto mode and the round horizon ─────────────────────────────────────────
82
+ //
83
+ // The two halves of "auto mode" the upstream engine (aegiscodex-dev) defines
84
+ // are independent, and a host that wires only one of them is *not* running auto
85
+ // mode — it is running "no approval cards", which is half the feature and all
86
+ // the friction:
87
+ //
88
+ // 1. no approval keystroke per mutating tool call;
89
+ // 2. a turn that hits its round horizon is EXTENDED silently a few times
90
+ // before a human is asked.
91
+ //
92
+ // (1) is the posture (the desktop's Tool-approvals switch, the CLI's
93
+ // /automode); (2) needs the arithmetic below, and the plugin's Electron host
94
+ // had none of it — with auto mode ON, every horizon hit still raised the
95
+ // blocking round card, which is precisely the question auto mode exists to stop
96
+ // asking ("12 rounds — keep going?" answered the same way every time).
97
+ //
98
+ // Ported verbatim from the engine's src/autonomous.js (DEFAULT_AUTO_CONTINUES,
99
+ // autoContinueLimit, autoRoundsDefault, autoContinuePlan) rather than vendored,
100
+ // because this repo hosts no build of that ESM module — but with the SAME
101
+ // numbers and the SAME env knobs, so a turn behaves identically in either
102
+ // client. cli/src/chatflow.js carries the third copy, which is what the CLI
103
+ // presenter uses to answer the ask.
104
+
105
+ /** Automatic continuations an attended turn may take while auto mode is on. */
106
+ const DEFAULT_AUTO_CONTINUES = 3;
107
+
108
+ /**
109
+ * The auto-continue allowance, honouring AEGIS_AUTO_CONTINUE_MAX.
110
+ *
111
+ * Bounded and pure, and a garbage value falls back to the default rather than
112
+ * to 0: an unparseable env var must not silently switch auto mode off, because
113
+ * the visible symptom of that ("why is it asking me again?") points nowhere
114
+ * near the environment.
115
+ */
116
+ function autoContinueLimit(env = process.env) {
117
+ const n = Number.parseInt(env && env.AEGIS_AUTO_CONTINUE_MAX, 10);
118
+ return Number.isFinite(n) && n > 0 ? n : DEFAULT_AUTO_CONTINUES;
119
+ }
120
+
121
+ /**
122
+ * Values of AEGIS_AUTO_ROUNDS that mean "start in manual mode". Anything else —
123
+ * unset, empty, a typo like `flase` — leaves auto mode's default in place, so a
124
+ * misspelt opt-out cannot silently disable the mode the operator asked for.
125
+ * Same set, same reasoning, as the engine's AUTO_ROUNDS_OFF.
126
+ */
127
+ const AUTO_ROUNDS_OFF = new Set(['0', 'false', 'off', 'no']);
128
+
129
+ /** False only when AEGIS_AUTO_ROUNDS explicitly says so. */
130
+ function autoRoundsDefault(env = process.env) {
131
+ const raw = env && env.AEGIS_AUTO_ROUNDS;
132
+ if (raw === undefined || raw === null) return true;
133
+ const val = String(raw).trim().toLowerCase();
134
+ if (!val) return true;
135
+ return !AUTO_ROUNDS_OFF.has(val);
136
+ }
137
+
138
+ /**
139
+ * Decide what one round-horizon ask becomes while auto mode is on.
140
+ *
141
+ * Pure, because this is budget arithmetic on a keystroke-less path: the caller
142
+ * only renders the answer and must not be trusted to keep the count. `used` is
143
+ * the running tally the caller holds and echoes back, so an ask that IS shown
144
+ * to the human resets it — the human was asked, so the next block of automatic
145
+ * continuations starts clean.
146
+ *
147
+ * { auto: true, used: n } → answer the ask "yes" without a dialog
148
+ * { auto: false, used: n } → show the real ask (allowance spent, or off)
149
+ */
150
+ function autoContinuePlan({ on = false, used = 0, limit = DEFAULT_AUTO_CONTINUES } = {}) {
151
+ const cap = Number.isFinite(limit) && limit > 0 ? Math.floor(limit) : DEFAULT_AUTO_CONTINUES;
152
+ const spent = Number.isFinite(used) && used > 0 ? Math.floor(used) : 0;
153
+ if (!on) return { auto: false, used: spent, cap };
154
+ if (spent >= cap) return { auto: false, used: 0, cap };
155
+ return { auto: true, used: spent + 1, cap };
156
+ }
157
+
76
158
  /** The path a file-writing tool call names, in either spelling the engine uses. */
77
159
  function writtenPath(tool) {
78
160
  const args = (tool && tool.args) || {};
@@ -906,6 +988,10 @@ module.exports = {
906
988
  isAutonomousRequest,
907
989
  maxRounds,
908
990
  withRoundHorizon,
991
+ DEFAULT_AUTO_CONTINUES,
992
+ autoContinueLimit,
993
+ autoRoundsDefault,
994
+ autoContinuePlan,
909
995
  resolveModel,
910
996
  ignoredEnvModel,
911
997
  resolveEffort,
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**
@@ -1,3 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
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.
1
6
  'use strict';
2
7
 
3
8
  /**