aegis-desktop 1.0.0 → 1.0.2
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 +5 -0
- package/lib/auto.js +5 -0
- package/lib/avatar/companion.js +5 -0
- package/lib/avatar/cosmetics.js +5 -0
- package/lib/avatar/events.js +5 -0
- package/lib/avatar/holder-turn.js +5 -0
- package/lib/avatar/holders.js +5 -0
- package/lib/avatar/identity.js +5 -0
- package/lib/avatar/level.js +5 -0
- package/lib/avatar/mirror.js +5 -0
- package/lib/avatar/persona.js +5 -0
- package/lib/avatar/profile.js +5 -0
- package/lib/avatar/register.js +5 -0
- package/lib/avatar/store.js +5 -0
- package/lib/avatar/tiers.js +5 -0
- package/lib/avatar/transfer.js +5 -0
- package/lib/avatar/turn.js +5 -0
- package/lib/avatar/voice.js +5 -0
- package/lib/avatar/xp.js +5 -0
- package/lib/deep-link.js +5 -0
- package/lib/fingerprint.js +5 -0
- package/lib/local/aegis-seal.mjs +5 -0
- package/lib/local/agents.js +5 -0
- package/lib/local/autonomous.js +5 -0
- package/lib/local/context.js +5 -0
- package/lib/local/covenant.js +5 -0
- package/lib/local/engine.js +129 -0
- package/lib/local/entitlement.js +5 -0
- package/lib/local/git-scope.js +5 -0
- package/lib/local/local.js +5 -0
- package/lib/local/prompt.js +5 -0
- package/lib/local/queue.js +5 -0
- package/lib/local/session-rounds.js +5 -0
- package/lib/local/shell.js +88 -9
- package/lib/local/telemetry.js +5 -0
- package/lib/local/tools.js +13 -6
- package/lib/local/turn-guard.js +5 -0
- package/lib/local/worktree-lock.js +5 -0
- package/lib/provider-key-mirror.js +5 -0
- package/lib/quick-launcher.js +5 -0
- package/lib/settings.js +5 -0
- package/lib/sync/memory-queue.js +5 -0
- package/lib/sync/persist-gate.js +5 -0
- package/lib/sync/sessions.js +5 -0
- package/lib/window-state.js +5 -0
- package/main.js +34 -0
- package/package.json +1 -1
- package/preload.js +14 -0
- package/renderer/app.js +111 -0
- package/renderer/avatar/assemble.js +5 -0
- package/renderer/avatar/avatar.css +7 -0
- package/renderer/avatar/avatar.js +5 -0
- package/renderer/avatar/cards.js +5 -0
- package/renderer/avatar/hud.js +5 -0
- package/renderer/avatar/machine.js +5 -0
- package/renderer/avatar/pane.js +5 -0
- package/renderer/avatar/parts.js +5 -0
- package/renderer/budget.js +5 -0
- package/renderer/diff.js +5 -0
- package/renderer/diffview.js +5 -0
- package/renderer/fingerprint.css +7 -0
- package/renderer/fingerprint.js +5 -0
- package/renderer/fonts/fonts.css +7 -0
- package/renderer/index.html +7 -0
- package/renderer/markdown.js +5 -0
- package/renderer/quick.css +7 -0
- package/renderer/quick.html +7 -0
- package/renderer/quick.js +5 -0
- package/renderer/stream-policy.js +5 -0
- package/renderer/style.css +7 -0
- package/renderer/transcript-view.js +5 -0
- package/renderer/usage.js +5 -0
- package/vendor/aegis.js +5 -0
- package/vendor/agent-gate.mjs +23 -0
- package/vendor/attest.js +5 -0
- package/vendor/authorship-key.js +5 -0
- package/vendor/auto-provision.js +5 -0
- package/vendor/brain-catalog.js +5 -0
- package/vendor/byok-catalog.js +5 -0
- package/vendor/credentials.js +5 -0
- package/vendor/device-fingerprint.js +5 -0
- package/vendor/env-file.js +5 -0
- package/vendor/fingerprint.js +5 -0
- package/vendor/foreign-memory.js +5 -0
- package/vendor/hooks.js +5 -0
- package/vendor/model-discovery.js +332 -0
- package/vendor/platform.js +5 -0
- package/vendor/prefs.js +5 -0
- package/vendor/presence-constants.js +5 -0
- package/vendor/presence.js +5 -0
- package/vendor/record-vault.js +5 -0
- package/vendor/session-store.js +5 -0
- package/vendor/topup.js +5 -0
- package/vendor/touch.js +5 -0
- package/vendor/update.js +5 -0
- package/vendor/user-models.js +5 -0
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
|
/**
|
package/lib/avatar/companion.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/avatar/cosmetics.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/avatar/events.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
|
/**
|
package/lib/avatar/holders.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/avatar/identity.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/avatar/level.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/avatar/mirror.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/avatar/persona.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/avatar/profile.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/avatar/register.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/avatar/store.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/avatar/tiers.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/avatar/transfer.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/avatar/turn.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/avatar/voice.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/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
|
/**
|
package/lib/fingerprint.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/local/aegis-seal.mjs
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
|
/**
|
|
3
8
|
* aegis-seal.mjs — codec for ÆL/1 (AEGIS Encoded Language)
|
|
4
9
|
*
|
package/lib/local/agents.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/local/autonomous.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/local/context.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/local/covenant.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/local/engine.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
|
/**
|
|
@@ -335,6 +340,33 @@ function requireSharedUserModels() {
|
|
|
335
340
|
throw last;
|
|
336
341
|
}
|
|
337
342
|
|
|
343
|
+
/**
|
|
344
|
+
* The vendor-list helper (`client/model-discovery.js`) — the module that asks a
|
|
345
|
+
* provider's OWN API which model ids exist, so a desktop user is not asked to
|
|
346
|
+
* recall an id the vendor publishes at a URL. Same resolution rule as the two
|
|
347
|
+
* catalog modules above, for the same reason: the CLI's `/model-discover` reads
|
|
348
|
+
* this one module too, so the terminal and the window cannot answer "what does
|
|
349
|
+
* this key reach" differently.
|
|
350
|
+
*
|
|
351
|
+
* It does no I/O at load time (no key store, no network), so requiring it here
|
|
352
|
+
* costs the window nothing until a user asks for a list.
|
|
353
|
+
*/
|
|
354
|
+
function requireSharedModelDiscovery() {
|
|
355
|
+
const candidates = [
|
|
356
|
+
() => require('../../../client/model-discovery.js'),
|
|
357
|
+
() => require('../../vendor/model-discovery.js'),
|
|
358
|
+
];
|
|
359
|
+
let last = null;
|
|
360
|
+
for (const load of candidates) {
|
|
361
|
+
try {
|
|
362
|
+
return load();
|
|
363
|
+
} catch (err) {
|
|
364
|
+
last = err;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
throw last;
|
|
368
|
+
}
|
|
369
|
+
|
|
338
370
|
/**
|
|
339
371
|
* How long a turn waits for the working-tree lock before running anyway.
|
|
340
372
|
*
|
|
@@ -614,6 +646,12 @@ const {
|
|
|
614
646
|
addUserModel,
|
|
615
647
|
removeUserModel,
|
|
616
648
|
} = requireSharedUserModels();
|
|
649
|
+
const {
|
|
650
|
+
discoverModels: discoverVendorModels,
|
|
651
|
+
canDiscover: canDiscoverVendorModels,
|
|
652
|
+
endpointFor: vendorEndpointFor,
|
|
653
|
+
discoverableProviders,
|
|
654
|
+
} = requireSharedModelDiscovery();
|
|
617
655
|
|
|
618
656
|
// ── Agent-loop helpers ──────────────────────────────────────────────────────
|
|
619
657
|
|
|
@@ -941,6 +979,12 @@ function createLocalEngine({
|
|
|
941
979
|
// caller (desktop/main.js, the CLI's deps.js) wires the local class by
|
|
942
980
|
// simply existing.
|
|
943
981
|
localTransport: localT = localTransport,
|
|
982
|
+
// Injectable for tests (and for a host that fronts the network itself): the
|
|
983
|
+
// fetch used ONLY by `discoverModels`, which asks a vendor's list API. Every
|
|
984
|
+
// other request in this file goes through `localT`, so this is deliberately
|
|
985
|
+
// not the transport — discovery is an outbound call to api.<vendor>, not to
|
|
986
|
+
// the AEGIS relay. Undefined in production, which means the global fetch.
|
|
987
|
+
fetchImpl,
|
|
944
988
|
}) {
|
|
945
989
|
const controllers = new Map(); // sessionId -> AbortController
|
|
946
990
|
const T = tools || toolsModule;
|
|
@@ -2556,6 +2600,28 @@ function createLocalEngine({
|
|
|
2556
2600
|
return localT.unloadAll();
|
|
2557
2601
|
}
|
|
2558
2602
|
|
|
2603
|
+
/**
|
|
2604
|
+
* The vendor key for a provider, resolved in the order the NEXT TURN will
|
|
2605
|
+
* resolve it: the saved `byok:<provider>` row first, then `~/.aegiscode/.env`
|
|
2606
|
+
* (loaded into the environment at host start-up by `client/env-file.js`) and
|
|
2607
|
+
* the shell. Discovery must ask with the key the call will run on — a list
|
|
2608
|
+
* fetched with a different one describes a catalog this machine cannot reach.
|
|
2609
|
+
*
|
|
2610
|
+
* Read-only by construction: it never writes a key, never hands the value to
|
|
2611
|
+
* a renderer and never logs it.
|
|
2612
|
+
*/
|
|
2613
|
+
function byokKeyForProviderLookup(providerId) {
|
|
2614
|
+
const id = String(providerId == null ? '' : providerId).trim().toLowerCase();
|
|
2615
|
+
if (!id) return '';
|
|
2616
|
+
try {
|
|
2617
|
+
if (settings && typeof settings.rawKey === 'function') {
|
|
2618
|
+
const stored = settings.rawKey(byokNamespace(id));
|
|
2619
|
+
if (typeof stored === 'string' && stored.trim()) return stored.trim();
|
|
2620
|
+
}
|
|
2621
|
+
} catch { /* a store that throws has no key, and that is a reportable state */ }
|
|
2622
|
+
return providerKeyFromEnv(id);
|
|
2623
|
+
}
|
|
2624
|
+
|
|
2559
2625
|
return {
|
|
2560
2626
|
CLASSES,
|
|
2561
2627
|
listClasses,
|
|
@@ -2582,6 +2648,69 @@ function createLocalEngine({
|
|
|
2582
2648
|
userModels: () => loadUserModels(),
|
|
2583
2649
|
addUserModel: (provider, model) => addUserModel(provider, model),
|
|
2584
2650
|
removeUserModel: (provider, model) => removeUserModel(provider, model),
|
|
2651
|
+
// ── asking the vendor, so the user does not have to remember ids ───────
|
|
2652
|
+
//
|
|
2653
|
+
// `discoverModels(provider)` resolves and returns the ids the provider's own
|
|
2654
|
+
// list API serves RIGHT NOW, which is the fix for the chore that produced
|
|
2655
|
+
// `client/byok-catalog.js`'s hand-copied Anthropic table. It never throws:
|
|
2656
|
+
// the shape is the discovery module's own
|
|
2657
|
+
// `{ ok, provider, ids, others, count }` / `{ ok:false, error }`, and the
|
|
2658
|
+
// renderer prints `error` verbatim. A window that guessed at an id and
|
|
2659
|
+
// silently pinned a 404 is the outcome this exists to prevent.
|
|
2660
|
+
//
|
|
2661
|
+
// The key comes from the SAME chain the next turn will use (the saved
|
|
2662
|
+
// `byok:<provider>` row, then `~/.aegiscode/.env`, then the shell), because
|
|
2663
|
+
// a list fetched with a different key than the call runs on would describe
|
|
2664
|
+
// somebody else's catalog.
|
|
2665
|
+
discoverModels: async (provider) => {
|
|
2666
|
+
const id = String(provider == null ? '' : provider).trim().toLowerCase();
|
|
2667
|
+
const key = byokKeyForProviderLookup(id);
|
|
2668
|
+
const res = await discoverVendorModels(id, { key, fetchImpl });
|
|
2669
|
+
// Say what the caller needs to offer the next step: which of these the
|
|
2670
|
+
// relay itself already lists, and which this machine has declared, so the
|
|
2671
|
+
// UI can mark a row instead of the user diffing two lists by eye.
|
|
2672
|
+
if (!res || !res.ok) return res;
|
|
2673
|
+
const declared = [];
|
|
2674
|
+
try {
|
|
2675
|
+
const map = loadUserModels().map;
|
|
2676
|
+
for (const m of Array.isArray(map[id]) ? map[id] : []) declared.push(m);
|
|
2677
|
+
} catch { /* a store that cannot be read marks nothing */ }
|
|
2678
|
+
return { ...res, declared, endpoint: (vendorEndpointFor(id) || {}).url || '' };
|
|
2679
|
+
},
|
|
2680
|
+
// The bulk write (`/model-add <provider> '*'` and the desktop's "Add all"
|
|
2681
|
+
// button): declare every id in one pass, skipping what is already there and
|
|
2682
|
+
// NAMING what was refused rather than aborting the whole batch on one bad
|
|
2683
|
+
// row. Returns counts, never a bare boolean, so both faces can report
|
|
2684
|
+
// "3 added, 2 already declared" instead of claiming work they did not do.
|
|
2685
|
+
addUserModels: (provider, ids) => {
|
|
2686
|
+
const list = Array.isArray(ids) ? ids : [];
|
|
2687
|
+
const out = { provider, added: 0, already: [], failed: [], capped: 0, file: '' };
|
|
2688
|
+
for (const raw of list) {
|
|
2689
|
+
try {
|
|
2690
|
+
const res = addUserModel(provider, raw);
|
|
2691
|
+
out.file = res.file || out.file;
|
|
2692
|
+
if (res.added) out.added += 1;
|
|
2693
|
+
else out.already.push(res.model);
|
|
2694
|
+
} catch (err) {
|
|
2695
|
+
const message = (err && err.message) || String(err);
|
|
2696
|
+
// The store's per-provider ceiling ends the batch as a CEILING. A
|
|
2697
|
+
// vendor serves a hundred ids and the store holds 32, so reporting
|
|
2698
|
+
// that as sixty-eight refused models would describe one deliberate
|
|
2699
|
+
// limit as sixty-eight broken ids.
|
|
2700
|
+
if (/the cap/.test(message)) {
|
|
2701
|
+
out.capped = list.length - out.added - out.already.length - out.failed.length;
|
|
2702
|
+
break;
|
|
2703
|
+
}
|
|
2704
|
+
out.failed.push({ id: String(raw), reason: message });
|
|
2705
|
+
}
|
|
2706
|
+
}
|
|
2707
|
+
return out;
|
|
2708
|
+
},
|
|
2709
|
+
// What the Settings row uses to decide whether to OFFER a list at all: a
|
|
2710
|
+
// provider this client cannot ask (or has no key for) falls back to the
|
|
2711
|
+
// free-form input, which is the path that always works.
|
|
2712
|
+
canDiscoverModels: (provider) => canDiscoverVendorModels(provider),
|
|
2713
|
+
discoverableProviders: () => discoverableProviders(),
|
|
2585
2714
|
};
|
|
2586
2715
|
}
|
|
2587
2716
|
|
package/lib/local/entitlement.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/local/git-scope.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/local/local.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/local/prompt.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/local/queue.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
|
/**
|
package/lib/local/shell.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
|
/**
|
|
@@ -280,10 +285,34 @@ const SHELL_CACHE = new Map();
|
|
|
280
285
|
function resolveSessionShell(options = {}) {
|
|
281
286
|
const o = shellSeams(options);
|
|
282
287
|
if (o.platform === 'win32') {
|
|
283
|
-
const
|
|
288
|
+
const cmdSpec = platform.shellSpec({ platform: 'win32', env: o.env });
|
|
284
289
|
const powershell =
|
|
285
290
|
platform.resolveExecutable('powershell', { platform: 'win32', env: o.env, exists: o.exists }) ||
|
|
286
291
|
'powershell.exe';
|
|
292
|
+
// ONE-SHOT NOW SPEAKS THE SESSION'S DIALECT TOO (2026-02-14 report, item 1).
|
|
293
|
+
//
|
|
294
|
+
// This used to be `oneShot: cmdSpec` — PowerShell for the session, cmd.exe
|
|
295
|
+
// for every one-shot — and that mismatch is what made `exec` silently wrong
|
|
296
|
+
// mid-turn. When the live session died (sentinel timeout, killed child, a
|
|
297
|
+
// rejected stdin write) the degrade paths below run one-shot, so from that
|
|
298
|
+
// moment on every remaining command in the turn was parsed by cmd.exe while
|
|
299
|
+
// the model kept emitting PowerShell quoting. cmd.exe answers
|
|
300
|
+
// `'"Write-Output \"' is not recognized as an internal or external command`
|
|
301
|
+
// — localized, so on sv-SE it reads `Felaktig syntax för filnamn, katalognamn
|
|
302
|
+
// eller volymetikett`, which looks like a filesystem fault and not a shell
|
|
303
|
+
// change — and nothing in the tool result said the shell had switched.
|
|
304
|
+
//
|
|
305
|
+
// `-Command` accepts exactly the quoting the session accepts, so a
|
|
306
|
+
// degradation is now a transport change and not a language change. cmd.exe
|
|
307
|
+
// is no longer reachable from this path at all: if PowerShell cannot be
|
|
308
|
+
// resolved the spawn fails loudly (oneShotShell reports `error: …`) instead
|
|
309
|
+
// of quietly running the command in a shell that cannot read it.
|
|
310
|
+
const oneShot = {
|
|
311
|
+
cmd: powershell,
|
|
312
|
+
arg: '-Command',
|
|
313
|
+
kind: 'powershell',
|
|
314
|
+
source: 'powershell.exe',
|
|
315
|
+
};
|
|
287
316
|
return {
|
|
288
317
|
ok: true,
|
|
289
318
|
cmd: powershell,
|
|
@@ -294,11 +323,16 @@ function resolveSessionShell(options = {}) {
|
|
|
294
323
|
unsupported: null,
|
|
295
324
|
caveat: null,
|
|
296
325
|
error: null,
|
|
297
|
-
|
|
298
|
-
// `exec` always used, and PowerShell is only the session's dialect.
|
|
299
|
-
oneShot: spec,
|
|
326
|
+
oneShot,
|
|
300
327
|
executed: [],
|
|
301
|
-
tried: [
|
|
328
|
+
tried: [
|
|
329
|
+
{ candidate: powershell, ok: true, reason: 'the Windows default (PowerShell session AND one-shot)' },
|
|
330
|
+
{
|
|
331
|
+
candidate: cmdSpec.cmd,
|
|
332
|
+
ok: false,
|
|
333
|
+
reason: 'cmd.exe is never used for one-shot: it cannot parse the PowerShell quoting the session teaches',
|
|
334
|
+
},
|
|
335
|
+
],
|
|
302
336
|
};
|
|
303
337
|
}
|
|
304
338
|
|
|
@@ -363,8 +397,11 @@ function oneShotShellSpec(options = {}) {
|
|
|
363
397
|
return { ok: false, cmd: null, arg: null, kind: null, error: spec.error, spec };
|
|
364
398
|
}
|
|
365
399
|
if (spec.kind === 'powershell') {
|
|
366
|
-
|
|
367
|
-
|
|
400
|
+
// The session's own one-shot spec (PowerShell `-Command`), so the `exec`
|
|
401
|
+
// tool's no-session path and this module's fallback cannot disagree about
|
|
402
|
+
// the dialect — which is exactly how cmd.exe used to sneak back in.
|
|
403
|
+
const shot = spec.oneShot || platform.shellSpec({ platform: 'win32', env: shellSeams(options).env });
|
|
404
|
+
return { ok: true, cmd: shot.cmd, arg: shot.arg, kind: shot.kind || 'powershell', error: null, spec };
|
|
368
405
|
}
|
|
369
406
|
return { ok: true, cmd: spec.cmd, arg: spec.arg, kind: 'posix-sh', error: null, spec };
|
|
370
407
|
}
|
|
@@ -412,6 +449,10 @@ class ShellSession {
|
|
|
412
449
|
this.buf = '';
|
|
413
450
|
this.alive = false;
|
|
414
451
|
this._pending = null; // resolver-scan for the in-flight command
|
|
452
|
+
this.cwd = cwd || process.cwd();
|
|
453
|
+
this.disposed = false; // an explicit dispose() must NOT be self-healed
|
|
454
|
+
this._respawns = 0; // one self-heal attempt per session, never a loop
|
|
455
|
+
this._degradedNoted = false; // the degrade marker is emitted once per session
|
|
415
456
|
this.shellOptions = shellOptions || {};
|
|
416
457
|
// Resolved BEFORE anything is spawned or written: `shell.kind` is what the
|
|
417
458
|
// command framing below branches on, so an unverified `$SHELL` can never
|
|
@@ -485,7 +526,21 @@ class ShellSession {
|
|
|
485
526
|
if (!this.alive && this.shellError) {
|
|
486
527
|
return Promise.resolve({ content: this.shellError, isError: true });
|
|
487
528
|
}
|
|
488
|
-
|
|
529
|
+
// SELF-HEAL BEFORE DEGRADING. The old path latched: once the live session
|
|
530
|
+
// died (a timeout kill, a child exit, a spawn error) every remaining
|
|
531
|
+
// command in the turn ran one-shot, and on Windows that one-shot used to
|
|
532
|
+
// be cmd.exe — so the agent stayed silently wrong for the rest of the
|
|
533
|
+
// turn. Re-probe and re-spawn ONCE instead, and only then fall through.
|
|
534
|
+
if (!this.alive && !this.disposed && this._respawns < 1) {
|
|
535
|
+
this._respawns += 1;
|
|
536
|
+
this.buf = '';
|
|
537
|
+
this.shell = resolveSessionShell(this.shellOptions);
|
|
538
|
+
this.shellError = this.shell.ok ? null : this.shell.error;
|
|
539
|
+
this._start(this.cwd);
|
|
540
|
+
if (this.alive) return this.run(command, { timeout, working_directory });
|
|
541
|
+
}
|
|
542
|
+
return oneShotShell({ command, timeout, working_directory, shellOptions: this.shellOptions })
|
|
543
|
+
.then((result) => this._noteDegraded(result, !this.alive ? 'the persistent session is not running' : 'no usable session dialect'));
|
|
489
544
|
}
|
|
490
545
|
let cmd = String(command || '');
|
|
491
546
|
|
|
@@ -557,7 +612,8 @@ class ShellSession {
|
|
|
557
612
|
this.child.stdin.write(script);
|
|
558
613
|
} catch {
|
|
559
614
|
this.alive = false;
|
|
560
|
-
oneShotShell({ command, timeout, working_directory, shellOptions: this.shellOptions })
|
|
615
|
+
oneShotShell({ command, timeout, working_directory, shellOptions: this.shellOptions })
|
|
616
|
+
.then((r) => finish(this._noteDegraded(r, 'the session stdin rejected the command')));
|
|
561
617
|
return;
|
|
562
618
|
}
|
|
563
619
|
// Data may already be buffered (fast commands) — scan once now.
|
|
@@ -565,7 +621,30 @@ class ShellSession {
|
|
|
565
621
|
});
|
|
566
622
|
}
|
|
567
623
|
|
|
624
|
+
/**
|
|
625
|
+
* Mark a result that came from the one-shot fallback rather than the live
|
|
626
|
+
* session, so the model is TOLD the shell changed and can stop trusting its
|
|
627
|
+
* quoting contract.
|
|
628
|
+
*
|
|
629
|
+
* The 2026-02-14 report's worst finding was precisely that this happened
|
|
630
|
+
* silently: "nothing in the result tells the agent the shell changed" while
|
|
631
|
+
* the agent "degrades to a one-shot cmd.exe — and stays there for the
|
|
632
|
+
* remainder of the turn", so it kept emitting PowerShell quoting, got
|
|
633
|
+
* localized cmd.exe syntax errors, and finally blamed the user's machine.
|
|
634
|
+
* Emitted ONCE per session so a degraded turn stays readable.
|
|
635
|
+
*/
|
|
636
|
+
_noteDegraded(result, reason) {
|
|
637
|
+
const r = result && typeof result === 'object' ? result : { content: String(result == null ? '' : result), isError: true };
|
|
638
|
+
if (this._degradedNoted) return r;
|
|
639
|
+
this._degradedNoted = true;
|
|
640
|
+
const via = this.shell && this.shell.cmd ? this.shell.cmd : 'unknown shell';
|
|
641
|
+
const was = this.shell && this.shell.kind ? this.shell.kind : 'none';
|
|
642
|
+
const marker = `[shell_degraded] ran one-shot via ${via} (${reason}); session dialect was ${was} — quoting contracts may differ`;
|
|
643
|
+
return { ...r, content: `${marker}\n${r.content || ''}` };
|
|
644
|
+
}
|
|
645
|
+
|
|
568
646
|
dispose() {
|
|
647
|
+
this.disposed = true;
|
|
569
648
|
this.alive = false;
|
|
570
649
|
if (this.child) {
|
|
571
650
|
try { this.child.stdin.end(); } catch { /* already gone */ }
|