super-dsh 0.1.6 → 0.1.10-e
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/README.md +25 -3
- package/agent-agy/cordis.patch.yml +7 -4
- package/agent-agy/dist/agent.d.ts +12 -11
- package/agent-agy/dist/agy-auth-gateway.d.ts +124 -0
- package/agent-agy/dist/agy-auth-gateway.js +233 -0
- package/agent-agy/dist/agy-auth.d.ts +153 -0
- package/agent-agy/dist/agy-auth.js +179 -0
- package/agent-agy/dist/agy-cli-client.d.ts +39 -9
- package/agent-agy/dist/agy-cli-client.js +82 -18
- package/agent-agy/dist/agy-store.d.ts +8 -0
- package/agent-agy/dist/index.d.ts +46 -16
- package/agent-agy/dist/index.js +82 -56
- package/agent-agy/dist/models.d.ts +70 -0
- package/agent-agy/dist/models.js +102 -3
- package/agent-agy/package.json +7 -5
- package/agent-agy-sdk/cordis.patch.yml +58 -0
- package/agent-agy-sdk/dist/adapter.d.ts +15 -0
- package/agent-agy-sdk/dist/adapter.js +42 -0
- package/agent-agy-sdk/dist/agent-preset-agy.d.ts +27 -0
- package/agent-agy-sdk/dist/agent-preset-agy.js +32 -0
- package/agent-agy-sdk/dist/agent.d.ts +138 -0
- package/agent-agy-sdk/dist/agent.js +494 -0
- package/{agent-agy → agent-agy-sdk}/dist/agy-client.d.ts +26 -6
- package/{agent-agy → agent-agy-sdk}/dist/agy-client.js +43 -25
- package/agent-agy-sdk/dist/agy-sessions.d.ts +25 -0
- package/agent-agy-sdk/dist/agy-sessions.js +107 -0
- package/agent-agy-sdk/dist/agy-store.d.ts +39 -0
- package/agent-agy-sdk/dist/agy-store.js +83 -0
- package/agent-agy-sdk/dist/inbox.d.ts +26 -0
- package/agent-agy-sdk/dist/inbox.js +53 -0
- package/agent-agy-sdk/dist/index.d.ts +93 -0
- package/agent-agy-sdk/dist/index.js +476 -0
- package/agent-agy-sdk/dist/models.d.ts +41 -0
- package/agent-agy-sdk/dist/models.js +74 -0
- package/agent-agy-sdk/dist/sdk-venv.d.ts +76 -0
- package/agent-agy-sdk/dist/sdk-venv.js +173 -0
- package/agent-agy-sdk/dist/world-plugin.d.ts +10 -0
- package/agent-agy-sdk/dist/world-plugin.js +82 -0
- package/agent-agy-sdk/package.json +64 -0
- package/agent-claude/dist/adapter.js +106 -31
- package/agent-claude/dist/agent.js +154 -17
- package/agent-claude/dist/claude-client.js +84 -43
- package/agent-claude/dist/claude-launch.js +101 -0
- package/agent-claude/dist/claude-native-config.js +169 -0
- package/agent-claude/dist/claude-provider-gateway.js +340 -0
- package/agent-claude/dist/claude-providers.js +391 -0
- package/agent-claude/dist/claude-route.js +152 -0
- package/agent-claude/dist/index.js +214 -37
- package/agent-claude/dist/models.js +14 -0
- package/agent-claude/dist/sdk-runtime.js +320 -0
- package/agent-claude/package.json +6 -4
- package/agent-codex/README.md +141 -36
- package/agent-codex/cordis.patch.yml +14 -10
- package/agent-codex/dist/adapter.js +64 -28
- package/agent-codex/dist/agent.js +255 -81
- package/agent-codex/dist/app-server-approvals.js +165 -0
- package/agent-codex/dist/app-server-client.js +723 -0
- package/agent-codex/dist/app-server-events.js +432 -0
- package/agent-codex/dist/app-server-protocol.js +95 -0
- package/agent-codex/dist/app-server-wire.js +299 -0
- package/agent-codex/dist/codex-launch.js +78 -0
- package/agent-codex/dist/codex-native-config.js +392 -0
- package/agent-codex/dist/codex-provider-gateway.js +402 -0
- package/agent-codex/dist/codex-providers.js +376 -0
- package/agent-codex/dist/codex-route.js +86 -0
- package/agent-codex/dist/index.js +256 -115
- package/agent-codex/dist/permission.js +75 -1
- package/agent-codex/package.json +1 -2
- package/agent-codex-sdk/README.md +79 -0
- package/agent-codex-sdk/cordis.patch.yml +81 -0
- package/agent-codex-sdk/dist/adapter.js +91 -0
- package/agent-codex-sdk/dist/agent-preset-codex.js +32 -0
- package/agent-codex-sdk/dist/agent.js +1085 -0
- package/agent-codex-sdk/dist/codex-native-config.js +392 -0
- package/agent-codex-sdk/dist/codex-provider-gateway.js +402 -0
- package/agent-codex-sdk/dist/codex-providers.js +376 -0
- package/agent-codex-sdk/dist/codex-route.js +86 -0
- package/{agent-codex/dist/codex-client.js → agent-codex-sdk/dist/codex-sdk-client.js} +253 -32
- package/agent-codex-sdk/dist/codex-sdk-launch.js +92 -0
- package/agent-codex-sdk/dist/codex-store.js +180 -0
- package/agent-codex-sdk/dist/inbox.js +53 -0
- package/agent-codex-sdk/dist/index.js +739 -0
- package/agent-codex-sdk/dist/permission.js +71 -0
- package/agent-codex-sdk/dist/sdk-runtime.js +307 -0
- package/agent-codex-sdk/dist/session-map.js +167 -0
- package/agent-codex-sdk/dist/world-plugin.js +93 -0
- package/agent-codex-sdk/package.json +79 -0
- package/agent-codex-sdk/scripts/fetch-sdk-runtime.mjs +57 -0
- package/agent-omp/README.md +72 -55
- package/agent-omp/dist/agent.js +36 -11
- package/agent-omp/dist/index.js +92 -52
- package/agent-omp/dist/lazy-rpc.js +11 -4
- package/agent-omp/dist/omp-cli.js +114 -97
- package/agent-omp/dist/omp-store.js +12 -4
- package/agent-omp/dist/permission.js +70 -5
- package/agent-omp/dist/rpc-client.js +409 -0
- package/agent-omp/dist/world-plugin.js +36 -3
- package/agent-omp/package.json +2 -6
- package/agent-omp-sdk/README.md +103 -0
- package/agent-omp-sdk/cordis.patch.yml +108 -0
- package/agent-omp-sdk/dist/adapter.d.ts +21 -0
- package/agent-omp-sdk/dist/adapter.js +36 -0
- package/agent-omp-sdk/dist/agent-preset-omp.d.ts +31 -0
- package/agent-omp-sdk/dist/agent-preset-omp.js +32 -0
- package/agent-omp-sdk/dist/agent.d.ts +64 -0
- package/agent-omp-sdk/dist/agent.js +1178 -0
- package/agent-omp-sdk/dist/discovery.d.ts +57 -0
- package/agent-omp-sdk/dist/discovery.js +116 -0
- package/agent-omp-sdk/dist/inbox.d.ts +28 -0
- package/agent-omp-sdk/dist/inbox.js +53 -0
- package/agent-omp-sdk/dist/index.d.ts +60 -0
- package/agent-omp-sdk/dist/index.js +632 -0
- package/agent-omp-sdk/dist/knobs.d.ts +34 -0
- package/agent-omp-sdk/dist/knobs.js +50 -0
- package/agent-omp-sdk/dist/lazy-rpc.d.ts +98 -0
- package/agent-omp-sdk/dist/lazy-rpc.js +178 -0
- package/agent-omp-sdk/dist/mobile/zoom-guard.d.ts +187 -0
- package/agent-omp-sdk/dist/mobile/zoom-guard.js +294 -0
- package/agent-omp-sdk/dist/mobile-boot.d.ts +49 -0
- package/agent-omp-sdk/dist/mobile-boot.js +38 -0
- package/agent-omp-sdk/dist/models.d.ts +39 -0
- package/agent-omp-sdk/dist/models.js +299 -0
- package/agent-omp-sdk/dist/omp-cli.d.ts +67 -0
- package/agent-omp-sdk/dist/omp-cli.js +164 -0
- package/agent-omp-sdk/dist/omp-disk-discovery.d.ts +27 -0
- package/agent-omp-sdk/dist/omp-disk-discovery.js +178 -0
- package/agent-omp-sdk/dist/omp-executable.d.ts +2 -0
- package/agent-omp-sdk/dist/omp-executable.js +30 -0
- package/agent-omp-sdk/dist/omp-store.d.ts +134 -0
- package/agent-omp-sdk/dist/omp-store.js +526 -0
- package/agent-omp-sdk/dist/pairing.d.ts +7 -0
- package/agent-omp-sdk/dist/pairing.js +45 -0
- package/agent-omp-sdk/dist/permission.d.ts +138 -0
- package/agent-omp-sdk/dist/permission.js +161 -0
- package/agent-omp-sdk/dist/protocol.d.ts +189 -0
- package/agent-omp-sdk/dist/rpc-types.d.ts +77 -0
- package/agent-omp-sdk/dist/rpc-types.js +1 -0
- package/agent-omp-sdk/dist/sdk-client.d.ts +160 -0
- package/{agent-omp → agent-omp-sdk}/dist/sdk-client.js +108 -56
- package/agent-omp-sdk/dist/sdk-runtime.d.ts +211 -0
- package/agent-omp-sdk/dist/sdk-runtime.js +418 -0
- package/agent-omp-sdk/dist/sidecar-client.d.ts +87 -0
- package/agent-omp-sdk/dist/sidecar-client.js +197 -0
- package/agent-omp-sdk/dist/store/adapter.d.ts +17 -0
- package/agent-omp-sdk/dist/store/adapter.js +47 -0
- package/agent-omp-sdk/dist/store/db.d.ts +70 -0
- package/agent-omp-sdk/dist/store/db.js +210 -0
- package/agent-omp-sdk/dist/store/index.d.ts +23 -0
- package/agent-omp-sdk/dist/store/index.js +59 -0
- package/agent-omp-sdk/dist/store/reconcile.d.ts +15 -0
- package/agent-omp-sdk/dist/store/reconcile.js +51 -0
- package/agent-omp-sdk/dist/store/schema.d.ts +8 -0
- package/agent-omp-sdk/dist/store/schema.js +40 -0
- package/agent-omp-sdk/dist/transport.d.ts +49 -0
- package/agent-omp-sdk/dist/transport.js +35 -0
- package/agent-omp-sdk/dist/world-home.d.ts +4 -0
- package/agent-omp-sdk/dist/world-home.js +23 -0
- package/agent-omp-sdk/dist/world-plugin.d.ts +10 -0
- package/agent-omp-sdk/dist/world-plugin.js +137 -0
- package/agent-omp-sdk/package.json +87 -0
- package/client/index.js +1883 -287
- package/cordis.patch.yml +80 -0
- package/package.json +23 -9
- package/superd-hub/dist/a2a-delivery.d.ts +189 -0
- package/superd-hub/dist/a2a-delivery.js +240 -0
- package/superd-hub/dist/a2a-host.d.ts +76 -0
- package/superd-hub/dist/a2a-host.js +145 -0
- package/superd-hub/dist/a2a-ingest.d.ts +31 -0
- package/superd-hub/dist/a2a-ingest.js +636 -0
- package/superd-hub/dist/a2a-log.d.ts +17 -0
- package/superd-hub/dist/a2a-log.js +42 -0
- package/superd-hub/dist/a2a-row.d.ts +65 -0
- package/superd-hub/dist/a2a-row.js +162 -0
- package/superd-hub/dist/a2a-service.d.ts +357 -0
- package/superd-hub/dist/a2a-service.js +980 -0
- package/superd-hub/dist/a2a-wire.d.ts +220 -0
- package/superd-hub/dist/a2a-wire.js +305 -0
- package/superd-hub/dist/agent-ids.d.ts +10 -0
- package/superd-hub/dist/agent-ids.js +68 -0
- package/superd-hub/dist/agent-roster.d.ts +29 -18
- package/superd-hub/dist/agent-roster.js +54 -15
- package/superd-hub/dist/agent-status.d.ts +119 -0
- package/superd-hub/dist/agent-status.js +386 -0
- package/superd-hub/dist/client/agent-settings.d.ts +210 -0
- package/superd-hub/dist/client/agent-settings.js +300 -0
- package/superd-hub/dist/client/mesh-api.d.ts +134 -0
- package/superd-hub/dist/client/mesh-api.js +219 -0
- package/superd-hub/dist/client/mesh-groups.d.ts +63 -0
- package/superd-hub/dist/client/mesh-groups.js +66 -0
- package/superd-hub/dist/client/roster.d.ts +48 -0
- package/superd-hub/dist/client/roster.js +102 -0
- package/superd-hub/dist/client/runtime-settings-api.d.ts +76 -0
- package/superd-hub/dist/client/runtime-settings-api.js +137 -0
- package/superd-hub/dist/client/switch.d.ts +165 -0
- package/superd-hub/dist/client/switch.js +295 -0
- package/superd-hub/dist/exec-pty-channel.d.ts +58 -0
- package/superd-hub/dist/exec-pty-channel.js +162 -0
- package/superd-hub/dist/exec-pty-framing.d.ts +32 -0
- package/superd-hub/dist/exec-pty-framing.js +81 -0
- package/superd-hub/dist/exec-pty-rpc.d.ts +21 -0
- package/superd-hub/dist/exec-pty-rpc.js +128 -0
- package/superd-hub/dist/exec-pty-session.d.ts +76 -0
- package/superd-hub/dist/exec-pty-session.js +234 -0
- package/superd-hub/dist/exec.d.ts +56 -0
- package/superd-hub/dist/exec.js +225 -0
- package/superd-hub/dist/gateway.d.ts +39 -2
- package/superd-hub/dist/gateway.js +62 -3
- package/superd-hub/dist/hub-tool.d.ts +174 -0
- package/superd-hub/dist/hub-tool.js +464 -0
- package/superd-hub/dist/index.d.ts +15 -1
- package/superd-hub/dist/index.js +16 -0
- package/superd-hub/dist/machines.d.ts +45 -0
- package/superd-hub/dist/machines.js +125 -0
- package/superd-hub/dist/mesh-federate.d.ts +138 -0
- package/superd-hub/dist/mesh-federate.js +223 -0
- package/superd-hub/dist/mesh-gateway.d.ts +67 -0
- package/superd-hub/dist/mesh-gateway.js +408 -0
- package/superd-hub/dist/mesh-link.d.ts +274 -0
- package/superd-hub/dist/mesh-link.js +441 -0
- package/superd-hub/dist/mesh-rpc.d.ts +123 -0
- package/superd-hub/dist/mesh-rpc.js +250 -0
- package/superd-hub/dist/mux-client.d.ts +71 -0
- package/superd-hub/dist/mux-client.js +281 -0
- package/superd-hub/dist/pack-version.d.ts +2 -0
- package/superd-hub/dist/pack-version.js +30 -0
- package/superd-hub/dist/roster.d.ts +6 -0
- package/superd-hub/dist/rpc.d.ts +18 -2
- package/superd-hub/dist/rpc.js +34 -4
- package/superd-hub/dist/spawn-world.js +3 -1
- package/superd-hub/dist/switch-core.d.ts +62 -25
- package/superd-hub/dist/switch-core.js +53 -30
- package/superd-hub/dist/system-head.d.ts +22 -12
- package/superd-hub/dist/system-head.js +100 -84
- package/superd-hub/dist/wire-endpoints.d.ts +264 -0
- package/superd-hub/dist/wire-endpoints.js +180 -0
- package/superd-hub/lib/client/index.js +1883 -287
- package/superd-hub/package.json +11 -2
- package/agent-agy/dist/agent-preset-projection.d.ts +0 -31
- package/agent-agy/dist/agent-preset-projection.js +0 -33
- package/agent-claude/dist/agent-preset-projection.js +0 -30
- package/agent-codex/dist/agent-preset-projection.js +0 -37
- package/agent-codex/dist/app-home.js +0 -65
- package/agent-codex/dist/models.js +0 -152
- package/agent-codex/dist/spike.js +0 -46
- package/agent-hermes/dist/agent-preset-projection.js +0 -34
- package/agent-omp/dist/agent-preset-projection.js +0 -36
- package/agent-omp/dist/app-home.js +0 -86
- package/agent-omp/dist/sidecar-client.js +0 -195
- package/agent-pi/dist/agent-preset-projection.js +0 -29
- package/superd-hub/dist/client-shim.d.ts +0 -28
- package/superd-hub/dist/client-shim.js +0 -251
- package/superd-hub/dist/index-pass.d.ts +0 -22
- package/superd-hub/dist/index-pass.js +0 -47
- package/superd-hub/dist/labels.d.ts +0 -45
- package/superd-hub/dist/labels.js +0 -83
- /package/{agent-agy → agent-agy-sdk}/bridge/agy_bridge.py +0 -0
- /package/{agent-agy → agent-agy-sdk}/bridge/gemini_openai_server.mjs +0 -0
- /package/{agent-codex/dist/codex-events.js → agent-codex-sdk/dist/codex-sdk-events.js} +0 -0
- /package/{agent-omp → agent-omp-sdk}/dist/protocol.js +0 -0
- /package/{agent-omp → agent-omp-sdk}/sidecar/main.ts +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* agent-codex provider — Codex provider plugin for DeepSeek Harness
|
|
3
|
-
* (Super D,
|
|
3
|
+
* (Super D, app-server line).
|
|
4
4
|
*
|
|
5
5
|
* Replaces the built-in agent loop with an `AgentFactory` that drives
|
|
6
|
-
*
|
|
6
|
+
* `codex app-server` threads (one `CodexAppServerClient` per session) and bridges
|
|
7
7
|
* the projected wire stream into the Dash Agent/Session contracts. Mirrors
|
|
8
8
|
* `@deepseek-ai/dsh-agent-loop`'s creation transaction (prepare → owned
|
|
9
9
|
* storage handle → setup → publish) so the session + agent publish as one
|
|
@@ -22,16 +22,19 @@
|
|
|
22
22
|
import { existsSync, realpathSync, statSync } from "node:fs";
|
|
23
23
|
import { join } from "node:path";
|
|
24
24
|
import { Service } from "@deepseek-ai/cordis";
|
|
25
|
-
import { installModelSelection } from "@deepseek-ai/dsh-agent";
|
|
26
25
|
import { SessionLogOffset, SessionPreparation, interruptedTurnClosers, } from "@deepseek-ai/dsh-session";
|
|
27
|
-
import {
|
|
26
|
+
import { CodexAppServerClient } from "./app-server-client.js";
|
|
28
27
|
import { CodexAgent } from "./agent.js";
|
|
29
|
-
import { CodexLlmAdapter,
|
|
28
|
+
import { CodexLlmAdapter, routeIds } from "./adapter.js";
|
|
30
29
|
import { registerCodexPreset } from "./agent-preset-codex.js";
|
|
31
30
|
import { readRolloutHead, resolveCodexHome } from "./codex-store.js";
|
|
31
|
+
import { CodexProvidersGateway, syncFromNative } from "./codex-provider-gateway.js";
|
|
32
|
+
import { readProviderStore } from "./codex-providers.js";
|
|
33
|
+
import { readNativeSelection } from "./codex-native-config.js";
|
|
34
|
+
import { seedRoute } from "./codex-route.js";
|
|
35
|
+
import { providerLaunch } from "./codex-launch.js";
|
|
32
36
|
import { CodexResumeError, sessionRecord, upsertSession } from "./session-map.js";
|
|
33
|
-
import {
|
|
34
|
-
import { codexApprovalMode, defaultPermissionPreset, envApprovalMode, presetFromEvents } from "./permission.js";
|
|
37
|
+
import { codexApprovalMode, defaultPermissionPreset, envApprovalMode, presetFromEvents, sandboxModeForPreset } from "./permission.js";
|
|
35
38
|
/** Realpath of a recorded cwd, accepted only when it names an existing directory. */
|
|
36
39
|
function validatedCwd(cwd) {
|
|
37
40
|
if (cwd === undefined)
|
|
@@ -49,6 +52,13 @@ const trace = (...parts) => {
|
|
|
49
52
|
if (process.env.CODEX_TRACE === "1")
|
|
50
53
|
process.stderr.write(`[codex-provider ${Date.now() % 1_000_000}] ${parts.join(" ")}\n`);
|
|
51
54
|
};
|
|
55
|
+
/**
|
|
56
|
+
* How often the canonical store is reconciled with the user's `config.toml`
|
|
57
|
+
* (2026-10-04 user ruling: startup + every ten minutes). The file is the user's
|
|
58
|
+
* own and edits it with their own tools, so the sync is a poll rather than an
|
|
59
|
+
* event subscription — ten minutes is the granularity the ruling asked for.
|
|
60
|
+
*/
|
|
61
|
+
const SYNC_INTERVAL_MS = 600_000;
|
|
52
62
|
/** Open a read handle, pull the complete stored log, close. */
|
|
53
63
|
async function readStoredEvents(persistence, id, signal) {
|
|
54
64
|
const handle = await persistence.open(id, "read", signal === undefined ? {} : { signal });
|
|
@@ -82,6 +92,15 @@ export class CodexProvider extends Service {
|
|
|
82
92
|
home;
|
|
83
93
|
/** Echo/staleness guard for the app-wide default-model push. */
|
|
84
94
|
defaultModelKey = "";
|
|
95
|
+
/**
|
|
96
|
+
* The live `ctx.llm` registration for the codex routes, when one exists.
|
|
97
|
+
* Its `replace()` is how the route SET follows the store: a provider gaining
|
|
98
|
+
* or losing its first model changes which routes exist, which re-registration
|
|
99
|
+
* alone can express.
|
|
100
|
+
*/
|
|
101
|
+
routes;
|
|
102
|
+
/** Epoch ms of the last reconcile with the user's `config.toml`. */
|
|
103
|
+
syncedAt;
|
|
85
104
|
constructor(ctx) {
|
|
86
105
|
super(ctx, "codexProvider");
|
|
87
106
|
this.runtime = { ctx };
|
|
@@ -93,7 +112,15 @@ export class CodexProvider extends Service {
|
|
|
93
112
|
const codexHome = resolveCodexHome();
|
|
94
113
|
trace(`home: worldHome=${this.home} codexHome=${codexHome} configExists=${existsSync(join(codexHome, "config.toml"))}`);
|
|
95
114
|
ctx.effect(() => ctx.agents.setFactory(this), "codexProvider.setFactory()");
|
|
115
|
+
// The store is canonical and the native file is a source (2026-10-04).
|
|
116
|
+
// Register the routes the store already implies FIRST, so a malformed
|
|
117
|
+
// config.toml costs the world a reconcile, never its provider list; then
|
|
118
|
+
// reconcile, then keep reconciling on a timer.
|
|
96
119
|
this.#registerModelCatalog();
|
|
120
|
+
this.syncNow();
|
|
121
|
+
const timer = setInterval(() => this.syncNow(), SYNC_INTERVAL_MS);
|
|
122
|
+
timer.unref?.();
|
|
123
|
+
ctx.effect(() => () => clearInterval(timer), "codexProvider.syncTimer()");
|
|
97
124
|
this.#registerDefaultModel();
|
|
98
125
|
// The roster must be visible to the API gateway's root-level remote
|
|
99
126
|
// enumeration (dsh-host-apiproxy read it from the root service table);
|
|
@@ -107,23 +134,100 @@ export class CodexProvider extends Service {
|
|
|
107
134
|
// pins its `default` to the Codex preset). The adapter only registers
|
|
108
135
|
// its one fixed preset into the registry.
|
|
109
136
|
registerCodexPreset(ctx);
|
|
137
|
+
// The Hub settings panel's data plane (2026-10-03 multi-provider ruling): an
|
|
138
|
+
// adapter-owned Typert Remote (`codexProviders/get|save|remove`) on this
|
|
139
|
+
// world's context. The hub's carrier forwards `envelope.method` verbatim,
|
|
140
|
+
// so the panel reaches it through the existing `/hub/api?agent=codex`
|
|
141
|
+
// family — no new hub route, and no provider knowledge leaks out of the
|
|
142
|
+
// adapter (dev-rules §12). Cordis keeps the instance alive as this
|
|
143
|
+
// context's `codexProviders` service. There is no `select`: which provider a
|
|
144
|
+
// session runs on is DSH's per-session `model/selection`.
|
|
145
|
+
//
|
|
146
|
+
// `resolveCodexHome` is passed as a THUNK on purpose: the native home is
|
|
147
|
+
// re-resolved per call (so a test's `CODEX_HOME` and an operator's override
|
|
148
|
+
// are both honored) and construction stays read-free — the panel's first
|
|
149
|
+
// `get` is what touches disk.
|
|
150
|
+
new CodexProvidersGateway(ctx, this.home, () => resolveCodexHome(), () => this.refreshRoutes());
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Reconcile the canonical provider store with the user's `config.toml` and
|
|
154
|
+
* re-register the `ctx.llm` routes if either moved.
|
|
155
|
+
*
|
|
156
|
+
* Called once at startup and every {@link SYNC_INTERVAL_MS} (2026-10-04 user
|
|
157
|
+
* ruling), plus after every panel mutation through the gateway's `onChange`.
|
|
158
|
+
* Never throws: a provider list is not worth a boot.
|
|
159
|
+
*/
|
|
160
|
+
syncNow() {
|
|
161
|
+
try {
|
|
162
|
+
const { store, added, updated } = syncFromNative(this.home, resolveCodexHome());
|
|
163
|
+
if (added.length > 0 || updated.length > 0) {
|
|
164
|
+
this.runtime.ctx.logger.info(`codex-provider: config.toml sync — added ${added.join(", ") || "none"}, refreshed ${updated.join(", ") || "none"}`);
|
|
165
|
+
}
|
|
166
|
+
this.syncedAt = Date.now();
|
|
167
|
+
this.#applyRoutes(store.providers);
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
this.runtime.ctx.logger.warn(`codex-provider: provider sync failed: ${String(error)}`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/** Re-register the `ctx.llm` routes from the current store (panel mutation path). */
|
|
174
|
+
refreshRoutes() {
|
|
175
|
+
try {
|
|
176
|
+
this.#applyRoutes(readProviderStore(this.home).providers);
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
this.runtime.ctx.logger.warn(`codex-provider: route refresh failed: ${String(error)}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* The provider id the user's own `config.toml` names, mapped into the store.
|
|
184
|
+
* It is the app-wide default's provider and the fallback for a session whose
|
|
185
|
+
* logged selection predates the multi-provider rework. `undefined` when the
|
|
186
|
+
* native file names nothing this world can serve.
|
|
187
|
+
*/
|
|
188
|
+
nativeProviderId() {
|
|
189
|
+
const native = readNativeSelection(resolveCodexHome());
|
|
190
|
+
const wanted = native.providerId;
|
|
191
|
+
if (wanted === undefined)
|
|
192
|
+
return undefined;
|
|
193
|
+
const providers = readProviderStore(this.home).providers;
|
|
194
|
+
return providers.find((entry) => entry.id === wanted)?.id ?? undefined;
|
|
195
|
+
}
|
|
196
|
+
/** The store entry a DSH route id names. */
|
|
197
|
+
providerEntry(providerId) {
|
|
198
|
+
return readProviderStore(this.home).providers.find((entry) => entry.id === providerId);
|
|
110
199
|
}
|
|
111
200
|
/**
|
|
112
|
-
* The factory
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* options
|
|
118
|
-
*
|
|
201
|
+
* The factory's session-level route fallback — always ONE coherent pair.
|
|
202
|
+
*
|
|
203
|
+
* The ambient `agentDefaultModel` selection is not authoritative here (user
|
|
204
|
+
* directive 2026-09-15), and neither is a global "active" provider any more:
|
|
205
|
+
* the session's OWN `model/selection` decides, resolved by the agent at each
|
|
206
|
+
* turn. These options are what a session with no selection of its own starts
|
|
207
|
+
* from.
|
|
208
|
+
*
|
|
209
|
+
* The one trap this method exists to close: a cached default can outlive the
|
|
210
|
+
* model list it named, because the panel may have removed that model since
|
|
211
|
+
* (upstream persists the last pick as the deployment default). Honouring a pair
|
|
212
|
+
* the provider no longer serves would seed a route nobody can run, so a request
|
|
213
|
+
* wins only when BOTH halves are still servable; otherwise the user's own
|
|
214
|
+
* `config.toml` pair takes over, which is authoritative for exactly the provider
|
|
215
|
+
* it is in force for.
|
|
119
216
|
*/
|
|
120
217
|
sessionAgentOptions(requested) {
|
|
121
|
-
const
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
218
|
+
const native = readNativeSelection(resolveCodexHome());
|
|
219
|
+
const wanted = requested?.provider !== undefined && typeof requested.model === "string" ? requested : undefined;
|
|
220
|
+
const serves = wanted !== undefined
|
|
221
|
+
&& this.providerEntry(wanted.provider)?.models.some((model) => model.id === wanted.model) === true;
|
|
222
|
+
if (wanted !== undefined && serves)
|
|
223
|
+
return { ...wanted, provider: wanted.provider, model: wanted.model };
|
|
224
|
+
const provider = this.nativeProviderId();
|
|
225
|
+
const model = native.model !== undefined && native.model !== "" ? native.model : undefined;
|
|
226
|
+
return {
|
|
227
|
+
...(requested ?? {}),
|
|
228
|
+
...(provider === undefined ? {} : { provider }),
|
|
229
|
+
...(model === undefined ? {} : { model }),
|
|
230
|
+
};
|
|
127
231
|
}
|
|
128
232
|
/**
|
|
129
233
|
* The write path is mandatory now (2026-09-16): this factory owns the DSH
|
|
@@ -151,12 +255,12 @@ export class CodexProvider extends Service {
|
|
|
151
255
|
return { handle, storedCount: 0 };
|
|
152
256
|
}
|
|
153
257
|
/**
|
|
154
|
-
* Runtime facts the agent stamps into the log
|
|
155
|
-
* (rollout HEAD `base_instructions`, readable once
|
|
156
|
-
* the
|
|
157
|
-
*
|
|
258
|
+
* Runtime facts the agent stamps into the log and needs to launch a child:
|
|
259
|
+
* Codex's own system prompt (rollout HEAD `base_instructions`, readable once
|
|
260
|
+
* the thread exists), the launch that pins a provider, and the provider's own
|
|
261
|
+
* context window for one of its models.
|
|
158
262
|
*/
|
|
159
|
-
agentRuntime(client, id) {
|
|
263
|
+
agentRuntime(client, id, cwd) {
|
|
160
264
|
const codexHome = resolveCodexHome();
|
|
161
265
|
return {
|
|
162
266
|
systemPrompt: () => {
|
|
@@ -165,25 +269,24 @@ export class CodexProvider extends Service {
|
|
|
165
269
|
return undefined;
|
|
166
270
|
return readRolloutHead(codexHome, threadId)?.baseInstructions;
|
|
167
271
|
},
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
const
|
|
178
|
-
return
|
|
179
|
-
provider: CODEX_PROVIDER_ID,
|
|
180
|
-
model,
|
|
181
|
-
...(entry?.contextWindow !== undefined && entry.contextWindow > 0 ? { contextWindow: entry.contextWindow } : {}),
|
|
182
|
-
};
|
|
272
|
+
// The whole on-the-fly mechanism in one call: the agent asks for the
|
|
273
|
+
// argv/env that pin a provider, and gets them without a single write to
|
|
274
|
+
// the user's home (the per-provider model catalog is ours).
|
|
275
|
+
launchFor: (providerId) => {
|
|
276
|
+
const entry = this.providerEntry(providerId);
|
|
277
|
+
return entry === undefined ? undefined : providerLaunch(this.home, codexHome, entry);
|
|
278
|
+
},
|
|
279
|
+
contextWindowFor: (providerId, model) => {
|
|
280
|
+
const entry = this.providerEntry(providerId);
|
|
281
|
+
const found = entry?.models.find((candidate) => candidate.id === model);
|
|
282
|
+
return found?.contextWindow;
|
|
183
283
|
},
|
|
184
284
|
// RC-4: turn-time native rejections mark the map so the next resume
|
|
185
285
|
// fails fast (CodexResumeError NATIVE_REJECTED) instead of burning
|
|
186
286
|
// another turn on a dead thread.
|
|
287
|
+
// The session workspace: the per-turn permission fold needs it for
|
|
288
|
+
// `workspaceWrite.writableRoots` (never a home — the user's workspace).
|
|
289
|
+
cwd: () => cwd,
|
|
187
290
|
markNotResumable: () => {
|
|
188
291
|
try {
|
|
189
292
|
upsertSession(this.home, String(id), { resumable: false });
|
|
@@ -230,12 +333,17 @@ export class CodexProvider extends Service {
|
|
|
230
333
|
const service = mCtx.get("agentDefaultModel");
|
|
231
334
|
if (service === undefined)
|
|
232
335
|
return;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
336
|
+
// The default is whatever the user's own codex config runs, expressed in
|
|
337
|
+
// the store's own route id so the harness can resolve it. A config naming
|
|
338
|
+
// a provider this world has no route for is not a default we can push.
|
|
339
|
+
const native = readNativeSelection(resolveCodexHome());
|
|
340
|
+
const provider = this.nativeProviderId();
|
|
341
|
+
const model = native.model;
|
|
342
|
+
if (provider === undefined || model === undefined || model === "") {
|
|
343
|
+
trace("default model push skipped: config.toml names no servable provider/model");
|
|
236
344
|
return;
|
|
237
345
|
}
|
|
238
|
-
const target = { provider
|
|
346
|
+
const target = { provider, model };
|
|
239
347
|
const targetKey = `${target.provider}/${target.model}`;
|
|
240
348
|
const current = service.currentSelection?.();
|
|
241
349
|
const currentKey = current === undefined ? undefined : `${current.provider}/${current.model}`;
|
|
@@ -256,14 +364,45 @@ export class CodexProvider extends Service {
|
|
|
256
364
|
});
|
|
257
365
|
});
|
|
258
366
|
}
|
|
367
|
+
/**
|
|
368
|
+
* Register the codex routes on `ctx.llm` — ONE ROUTE PER PROVIDER with
|
|
369
|
+
* models (2026-10-04 rework).
|
|
370
|
+
*
|
|
371
|
+
* The harness's model selector is provider-grouped, and its per-session
|
|
372
|
+
* choice is durable (`model/selection` + the `modelSelection` projection), so
|
|
373
|
+
* expressing the Codex provider list as real routes is what makes the whole
|
|
374
|
+
* feature DSH-native: nothing in Super D has to model "the active provider" or
|
|
375
|
+
* remember which route a session last used.
|
|
376
|
+
*
|
|
377
|
+
* A provider with no models yet registers no route — codex itself cannot run
|
|
378
|
+
* it until the user says which model to ask for, and an empty group in the
|
|
379
|
+
* picker would be noise.
|
|
380
|
+
*/
|
|
259
381
|
#registerModelCatalog() {
|
|
382
|
+
this.#applyRoutes(readProviderStore(this.home).providers);
|
|
383
|
+
}
|
|
384
|
+
/** Register or atomically re-point the codex routes at the given providers. */
|
|
385
|
+
#applyRoutes(providers) {
|
|
260
386
|
const llm = this.runtime.ctx.get("llm");
|
|
261
387
|
if (llm === undefined)
|
|
262
388
|
return;
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
389
|
+
const ids = routeIds({ version: 1, providers });
|
|
390
|
+
if (this.routes === undefined) {
|
|
391
|
+
if (ids.length === 0) {
|
|
392
|
+
// `registerAdapter` refuses an empty initial set, and there is nothing
|
|
393
|
+
// to serve yet; the next sync or panel save will register the routes.
|
|
394
|
+
trace("route registration deferred: no provider with models yet");
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
this.routes = llm.registerAdapter([...ids], new CodexLlmAdapter(this.home));
|
|
398
|
+
trace(`routes registered: ${ids.join(", ")}`);
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
// `replace` validates the whole candidate set before swapping, so a bad id
|
|
402
|
+
// cannot leave the registry half-updated — but a throw here must not take
|
|
403
|
+
// the caller (a timer, or a panel save) down with it.
|
|
404
|
+
this.routes.replace([...ids]);
|
|
405
|
+
trace(`routes replaced: ${ids.join(", ") || "none"}`);
|
|
267
406
|
}
|
|
268
407
|
async createAgent(ownerCtx, options) {
|
|
269
408
|
const loopCtx = this.runtime.ctx;
|
|
@@ -281,30 +420,29 @@ export class CodexProvider extends Service {
|
|
|
281
420
|
// the upstream persistence service a created session would persist
|
|
282
421
|
// nothing, so require it up front.
|
|
283
422
|
const persistence = this.requirePersistence("create");
|
|
284
|
-
//
|
|
285
|
-
// session does not exist yet
|
|
286
|
-
// which is what stamps `permission/preset` via
|
|
287
|
-
// only inside setupAndPublish
|
|
288
|
-
//
|
|
289
|
-
//
|
|
290
|
-
//
|
|
423
|
+
// App-server line (2026-10-03): the thread's LAUNCH posture still needs a
|
|
424
|
+
// decision here — the Dash session does not exist yet (it is prepared +
|
|
425
|
+
// announced, which is what stamps `permission/preset` via
|
|
426
|
+
// pinInitialPermission, only inside setupAndPublish AFTER this call) — so
|
|
427
|
+
// the env override (CODEX_APPROVAL_MODE, headless runs) wins, else the
|
|
428
|
+
// permission service's default. From the first turn on, `agent.ts` folds
|
|
429
|
+
// the LIVE session log per turn (`turnPolicyFromEvents`) and overrides both
|
|
430
|
+
// fields on every `turn/start`, which is what makes `/permission` real.
|
|
291
431
|
const preset = envApprovalMode() ?? defaultPermissionPreset(loopCtx);
|
|
292
432
|
const approvalPolicy = codexApprovalMode(preset);
|
|
433
|
+
const sandboxMode = sandboxModeForPreset(preset);
|
|
293
434
|
const spawnCwd = validatedCwd(cwd) ?? process.cwd();
|
|
294
|
-
trace(`create id=${id} preset=${preset ?? "none"} approval=${approvalPolicy} spawnCwd=${spawnCwd}${envApprovalMode() === undefined ? "" : " (env override)"}`);
|
|
295
|
-
// Backend takes ZERO part in the UI's browser-local new-session draft
|
|
296
|
-
//
|
|
297
|
-
//
|
|
298
|
-
//
|
|
299
|
-
const client =
|
|
300
|
-
//
|
|
301
|
-
//
|
|
302
|
-
//
|
|
303
|
-
//
|
|
304
|
-
|
|
305
|
-
if (createCatalog.defaultModel !== CODEX_DEFAULT_MODEL_PLACEHOLDER) {
|
|
306
|
-
void client.setModel(CODEX_PROVIDER_ID, createCatalog.defaultModel).catch(() => { });
|
|
307
|
-
}
|
|
435
|
+
trace(`create id=${id} preset=${preset ?? "none"} approval=${approvalPolicy} sandbox=${sandboxMode} spawnCwd=${spawnCwd}${envApprovalMode() === undefined ? "" : " (env override)"}`);
|
|
436
|
+
// Backend takes ZERO part in the UI's browser-local new-session draft: the
|
|
437
|
+
// app-server child is NOT spawned here (lazy-spawn gate, rules §14-i) —
|
|
438
|
+
// create() is pure construction, and the process materializes on the first
|
|
439
|
+
// real prompt.
|
|
440
|
+
const client = CodexAppServerClient.create({ cwd: spawnCwd, approvalPolicy, sandboxMode });
|
|
441
|
+
// The session's route is NOT pinned here any more (2026-10-04): the agent
|
|
442
|
+
// resolves it per turn from DSH's own model-selection state, and a launch
|
|
443
|
+
// costs nothing until the first real prompt. `setupAndPublish` still seeds a
|
|
444
|
+
// `model/selection` for a session that has none, so the transcript can name
|
|
445
|
+
// its route from turn one.
|
|
308
446
|
const preparation = SessionPreparation.create(loopCtx.sessions.prepare(id, {
|
|
309
447
|
...(options.seed === undefined ? {} : { seed: options.seed }),
|
|
310
448
|
...(meta === undefined ? {} : { meta }),
|
|
@@ -324,7 +462,7 @@ export class CodexProvider extends Service {
|
|
|
324
462
|
});
|
|
325
463
|
this.followThreadId(id, client);
|
|
326
464
|
handedOff = true;
|
|
327
|
-
return await setupAndPublish(loopCtx, ownerCtx, id, this.sessionAgentOptions(options.agentOptions), options.setup, preparation.session, client, options.parentAgent, "startup", { enterSession: true, preparation }, stored, this.agentRuntime(client, id));
|
|
465
|
+
return await setupAndPublish(loopCtx, ownerCtx, id, this.sessionAgentOptions(options.agentOptions), options.setup, preparation.session, client, options.parentAgent, "startup", { enterSession: true, preparation }, stored, this.agentRuntime(client, id, spawnCwd));
|
|
328
466
|
}
|
|
329
467
|
catch (error) {
|
|
330
468
|
trace(`create ${id} THREW: ${String(error)}`);
|
|
@@ -378,10 +516,10 @@ export class CodexProvider extends Service {
|
|
|
378
516
|
if (spawnCwd === undefined) {
|
|
379
517
|
throw new Error(`cannot resume session "${id}": its recorded working directory no longer exists`);
|
|
380
518
|
}
|
|
381
|
-
// Approval policy for the re-attached thread:
|
|
382
|
-
// decided
|
|
383
|
-
//
|
|
384
|
-
//
|
|
519
|
+
// Approval policy / sandbox mode for the re-attached thread: the LAUNCH
|
|
520
|
+
// posture, decided from the recorded preset, else the persisted session log,
|
|
521
|
+
// else the permission service's default. CODEX_APPROVAL_MODE (headless
|
|
522
|
+
// runs) overrides. The per-turn fold in agent.ts takes over from turn one.
|
|
385
523
|
const envMode = envApprovalMode();
|
|
386
524
|
const preset = envMode !== undefined
|
|
387
525
|
? envMode
|
|
@@ -389,11 +527,17 @@ export class CodexProvider extends Service {
|
|
|
389
527
|
presetFromEvents(await readStoredEvents(persistence, id, options.signal)) ??
|
|
390
528
|
defaultPermissionPreset(loopCtx);
|
|
391
529
|
const approvalPolicy = codexApprovalMode(preset);
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
//
|
|
395
|
-
//
|
|
396
|
-
|
|
530
|
+
const sandboxMode = sandboxModeForPreset(preset);
|
|
531
|
+
trace(`resume id=${id} spawnCwd=${spawnCwd} preset=${preset ?? "none"} approval=${approvalPolicy} sandbox=${sandboxMode}`);
|
|
532
|
+
// Re-attach to the Codex thread by its id on the first real prompt (Codex
|
|
533
|
+
// owns the live agent context and restores the model context from its
|
|
534
|
+
// rollout). No process is spawned here — lazy-spawn gate, rules §14-i.
|
|
535
|
+
const client = CodexAppServerClient.create({
|
|
536
|
+
cwd: spawnCwd,
|
|
537
|
+
resumeThreadId: record.threadId,
|
|
538
|
+
approvalPolicy,
|
|
539
|
+
sandboxMode,
|
|
540
|
+
});
|
|
397
541
|
let handle;
|
|
398
542
|
let stored;
|
|
399
543
|
let preparation;
|
|
@@ -419,7 +563,7 @@ export class CodexProvider extends Service {
|
|
|
419
563
|
handle = undefined; // ownership passes to setupAndPublish
|
|
420
564
|
this.followThreadId(id, client);
|
|
421
565
|
handedOff = true;
|
|
422
|
-
return await setupAndPublish(loopCtx, ownerCtx, id, this.sessionAgentOptions(options.agentOptions), options.setup, preparation.session, client, options.parentAgent, "resume", { enterSession: true, preparation }, stored, this.agentRuntime(client, id));
|
|
566
|
+
return await setupAndPublish(loopCtx, ownerCtx, id, this.sessionAgentOptions(options.agentOptions), options.setup, preparation.session, client, options.parentAgent, "resume", { enterSession: true, preparation }, stored, this.agentRuntime(client, id, spawnCwd));
|
|
423
567
|
}
|
|
424
568
|
catch (error) {
|
|
425
569
|
trace(`resume ${id} THREW: ${String(error)} | stack=${error instanceof Error ? error.stack?.slice(0, 400) : "n/a"}`);
|
|
@@ -444,13 +588,15 @@ export class CodexProvider extends Service {
|
|
|
444
588
|
* the client's event stream.
|
|
445
589
|
*/
|
|
446
590
|
followThreadId = (id, client) => {
|
|
447
|
-
// RE-ARMING observer
|
|
448
|
-
//
|
|
449
|
-
//
|
|
450
|
-
//
|
|
451
|
-
//
|
|
591
|
+
// RE-ARMING observer: newSession() swaps threads mid-session, so the pairing
|
|
592
|
+
// must be re-upserted whenever the client ATTACHES a new thread, not just
|
|
593
|
+
// once. Unsubscribing after the first capture would leave the map pointing
|
|
594
|
+
// at the discarded thread, and the next resume would re-attach to a thread
|
|
595
|
+
// the session no longer runs on.
|
|
452
596
|
let lastRecorded = client.threadId;
|
|
453
597
|
const observe = (threadId) => {
|
|
598
|
+
if (threadId === lastRecorded)
|
|
599
|
+
return;
|
|
454
600
|
lastRecorded = threadId;
|
|
455
601
|
try {
|
|
456
602
|
upsertSession(this.home, String(id), { threadId });
|
|
@@ -460,14 +606,9 @@ export class CodexProvider extends Service {
|
|
|
460
606
|
this.runtime.ctx.logger.warn(`codex-provider: failed to persist the Codex thread id for ${String(id)}: ${String(error)}`);
|
|
461
607
|
}
|
|
462
608
|
};
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
client.
|
|
466
|
-
const observed = client.threadId;
|
|
467
|
-
if (observed === null || observed === lastRecorded)
|
|
468
|
-
return;
|
|
469
|
-
observe(observed);
|
|
470
|
-
});
|
|
609
|
+
// App-server line: the thread attaches lazily (first prompt), and
|
|
610
|
+
// `onThreadAttached` fires synchronously when one already exists.
|
|
611
|
+
client.onThreadAttached(observe);
|
|
471
612
|
};
|
|
472
613
|
}
|
|
473
614
|
/**
|
|
@@ -500,37 +641,37 @@ async function setupAndPublish(loopCtx, ownerCtx, id, agentOptions, setup, sessi
|
|
|
500
641
|
try {
|
|
501
642
|
// Build the agent shim over the session and the live client.
|
|
502
643
|
agent = new CodexAgent(loopCtx, id, agentOptions, session, client, () => idleExit?.(), runtimeInfo);
|
|
503
|
-
//
|
|
504
|
-
//
|
|
505
|
-
//
|
|
506
|
-
// the
|
|
507
|
-
//
|
|
508
|
-
//
|
|
644
|
+
// Seed THIS session's route only when its log has none (2026-10-04).
|
|
645
|
+
//
|
|
646
|
+
// The pin used to run on every create AND resume, which would now stomp a
|
|
647
|
+
// choice the user made in the model selector: `model/selection` IS the
|
|
648
|
+
// session's durable route, so an existing one is the authority and only a
|
|
649
|
+
// session that has never named a route gets the boot default. The append is
|
|
650
|
+
// log-only — the agent resolves it at each turn (`#resolveRoute`).
|
|
509
651
|
try {
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
});
|
|
652
|
+
// A narrow local cast for the same reason the append below uses one:
|
|
653
|
+
// `model/selection` is declared by the session-controller package's
|
|
654
|
+
// `SessionEventMap` augmentation, which this adapter deliberately does not
|
|
655
|
+
// depend on. The event name is the contract; its payload is not read here.
|
|
656
|
+
const events = session.snapshotEvents();
|
|
657
|
+
const alreadyRouted = events.some((event) => event.type === "model/selection");
|
|
658
|
+
// ONE source, on purpose: `agentOptions` is already the reconciled pair
|
|
659
|
+
// (`sessionAgentOptions`). Building the seed from the native provider id
|
|
660
|
+
// and the default model independently produced `zhipu-cn/deepseek-flash`,
|
|
661
|
+
// which no provider serves — see `seedRoute`.
|
|
662
|
+
const seed = seedRoute(agentOptions);
|
|
663
|
+
if (!alreadyRouted && seed !== undefined) {
|
|
664
|
+
const selection = { provider: seed.provider, model: seed.model };
|
|
524
665
|
// `model/selection` is contributed to `SessionEventMap` by the upstream
|
|
525
666
|
// session-controller package (declaration merging); this adapter does
|
|
526
667
|
// not depend on it, so the append goes through a narrow local cast.
|
|
527
668
|
session.append("model/selection", selection);
|
|
528
|
-
trace(`session route
|
|
669
|
+
trace(`session route seeded: ${seed.provider}/${seed.model}`);
|
|
529
670
|
}
|
|
530
671
|
}
|
|
531
672
|
catch (error) {
|
|
532
673
|
// Fail-soft: the boot-time default-model push remains the fallback.
|
|
533
|
-
trace(`session route
|
|
674
|
+
trace(`session route seed failed: ${String(error)}`);
|
|
534
675
|
}
|
|
535
676
|
// Session identity (the preset stamp) and the Codex system prompt commit
|
|
536
677
|
// on the first turn via CodexAgent's #bootstrapSessionIdentity /
|