@gajae-code/coding-agent 0.18.7 → 0.18.8
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/CHANGELOG.md +279 -1
- package/dist/types/async/job-manager.d.ts +1 -1
- package/dist/types/capability/mcp.d.ts +2 -0
- package/dist/types/capability/skill.d.ts +2 -0
- package/dist/types/capability/types.d.ts +2 -0
- package/dist/types/cli/public-command-errors.d.ts +3 -1
- package/dist/types/cli/setup-cli.d.ts +1 -1
- package/dist/types/commands/deep-interview.d.ts +3 -0
- package/dist/types/config/autorouting-tier-map.d.ts +348 -9
- package/dist/types/config/file-lock.d.ts +1 -0
- package/dist/types/config/model-bindings-applier.d.ts +2 -0
- package/dist/types/config/model-profile-activation.d.ts +11 -3
- package/dist/types/config/model-registry.d.ts +4 -9
- package/dist/types/config/skill-settings-defaults.d.ts +2 -0
- package/dist/types/cursor-delete-path.d.ts +1 -0
- package/dist/types/cursor-mcp-name.d.ts +8 -0
- package/dist/types/customization/inventory.d.ts +2 -0
- package/dist/types/debug/report-bundle-parent.d.ts +2 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.d.ts +1 -0
- package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/version-manager.d.ts +31 -0
- package/dist/types/defaults/gjc-skills.generated.d.ts +5 -6
- package/dist/types/discovery/helpers.d.ts +6 -1
- package/dist/types/export/html/css-color.d.ts +2 -0
- package/dist/types/export/html/template.generated.d.ts +1 -1
- package/dist/types/extensibility/extensions/types.d.ts +7 -0
- package/dist/types/extensibility/gjc-plugins/runtime-adapters.d.ts +14 -1
- package/dist/types/extensibility/plugins/marketplace/cache.d.ts +2 -0
- package/dist/types/extensibility/plugins/plugin-link-path.d.ts +2 -0
- package/dist/types/extensibility/runtime-skill-discovery.d.ts +3 -1
- package/dist/types/extensibility/skill-management.d.ts +3 -1
- package/dist/types/extensibility/skills.d.ts +2 -0
- package/dist/types/gjc-runtime/deep-interview-crystallize.d.ts +74 -0
- package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +11 -0
- package/dist/types/gjc-runtime/gc-runtime.d.ts +5 -0
- package/dist/types/gjc-runtime/ralplan-runtime.d.ts +0 -5
- package/dist/types/gjc-runtime/state-argv.d.ts +1 -1
- package/dist/types/gjc-runtime/state-migrations.d.ts +8 -0
- package/dist/types/gjc-runtime/state-runtime.d.ts +95 -0
- package/dist/types/gjc-runtime/state-writer.d.ts +11 -1
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +8 -0
- package/dist/types/internal-urls/skill-path.d.ts +1 -0
- package/dist/types/lsp/workspace-path.d.ts +1 -0
- package/dist/types/modes/acp/acp-agent.d.ts +7 -0
- package/dist/types/modes/components/custom-editor.d.ts +6 -0
- package/dist/types/modes/components/customization/customization-dashboard.d.ts +1 -0
- package/dist/types/modes/components/extensions/state-manager.d.ts +4 -3
- package/dist/types/modes/controllers/input-controller.d.ts +9 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -0
- package/dist/types/modes/utils/interrupt-ownership.d.ts +3 -0
- package/dist/types/modes/utils/keybinding-matchers.d.ts +1 -0
- package/dist/types/modes/utils/macos-option-forwarding.d.ts +17 -0
- package/dist/types/progress/collect-project-progress.d.ts +38 -0
- package/dist/types/progress/progress-contract.d.ts +154 -0
- package/dist/types/progress/progress-snapshot.d.ts +11 -0
- package/dist/types/progress/project-progress.d.ts +141 -0
- package/dist/types/progress/render-progress.d.ts +28 -0
- package/dist/types/runtime-mcp/oauth-public-url.d.ts +1 -0
- package/dist/types/runtime-mcp/plugin-network-boundary.d.ts +1 -0
- package/dist/types/runtime-mcp/smithery-registry.d.ts +24 -0
- package/dist/types/runtime-mcp/types.d.ts +6 -0
- package/dist/types/sdk/acp/adapter.d.ts +1 -1
- package/dist/types/sdk/broker/broker-exit.d.ts +6 -2
- package/dist/types/sdk/broker/broker.d.ts +18 -1
- package/dist/types/sdk/broker/session-index.d.ts +12 -6
- package/dist/types/sdk/bus/index.d.ts +12 -1
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +6 -1
- package/dist/types/sdk/client/client.d.ts +2 -0
- package/dist/types/sdk/host/query/handlers.d.ts +3 -0
- package/dist/types/sdk/index.d.ts +1 -0
- package/dist/types/sdk/router/session-router.d.ts +2 -0
- package/dist/types/sdk/session-list.d.ts +1 -1
- package/dist/types/sdk/session.d.ts +8 -0
- package/dist/types/session/agent-session.d.ts +38 -9
- package/dist/types/session/artifacts.d.ts +2 -2
- package/dist/types/session/internal/managed-gc-retirement-codec.d.ts +32 -0
- package/dist/types/session/internal/managed-session-scope.d.ts +79 -2
- package/dist/types/session/internal/managed-session-storage.d.ts +26 -1
- package/dist/types/session/internal/managed-task-owner-cleanup.d.ts +62 -0
- package/dist/types/session/internal/task-artifact-owner-access.d.ts +2 -0
- package/dist/types/session/internal/task-artifact-owner-transcript.d.ts +9 -1
- package/dist/types/session/session-manager.d.ts +31 -5
- package/dist/types/session/session-retirement.d.ts +31 -7
- package/dist/types/session/session-storage.d.ts +62 -2
- package/dist/types/session/task-artifact-owner-codec.d.ts +2 -0
- package/dist/types/setup/credential-auto-import.d.ts +1 -1
- package/dist/types/setup/credential-import.d.ts +6 -4
- package/dist/types/skill-state/active-state.d.ts +38 -0
- package/dist/types/slash-commands/helpers/progress-report.d.ts +8 -0
- package/dist/types/task/executor.d.ts +3 -0
- package/dist/types/tools/bash-skill-urls.d.ts +1 -1
- package/dist/types/tools/index.d.ts +3 -0
- package/dist/types/tools/python.d.ts +9 -1
- package/dist/types/tools/recipe/recipe-guard.d.ts +7 -0
- package/dist/types/tools/restricted-cwd.d.ts +1 -0
- package/dist/types/tools/todo-write.d.ts +6 -0
- package/dist/types/utils/tools-checksum.d.ts +7 -0
- package/package.json +7 -7
- package/scripts/generate-sdk-operation-inventory.ts +21 -0
- package/scripts/verify-managed-empty-stop.ts +28 -0
- package/src/async/job-manager.ts +228 -122
- package/src/capability/index.ts +17 -0
- package/src/capability/mcp.ts +2 -0
- package/src/capability/skill.ts +2 -0
- package/src/capability/types.ts +2 -0
- package/src/cli/auth-broker-cli.ts +1 -1
- package/src/cli/customize-doctor.ts +15 -2
- package/src/cli/public-command-errors.ts +21 -1
- package/src/cli/setup-cli.ts +4 -4
- package/src/cli/skills-cli.ts +5 -0
- package/src/commands/deep-interview.ts +47 -8
- package/src/commands/sdk.ts +28 -8
- package/src/config/autorouting-tier-map.ts +117 -7
- package/src/config/file-lock.ts +307 -68
- package/src/config/mcp-schema.json +4 -0
- package/src/config/model-bindings-applier.ts +20 -0
- package/src/config/model-profile-activation.ts +240 -46
- package/src/config/model-registry.ts +47 -153
- package/src/config/skill-settings-defaults.ts +7 -0
- package/src/coordinator-mcp/policy.ts +3 -2
- package/src/cursor-delete-path.ts +10 -0
- package/src/cursor-mcp-name.ts +15 -0
- package/src/cursor.ts +13 -2
- package/src/customization/inventory.ts +3 -0
- package/src/debug/report-bundle-parent.ts +22 -0
- package/src/debug/report-bundle.ts +3 -0
- package/src/debug/system-info.ts +13 -1
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.ts +67 -4
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/version-manager.ts +80 -0
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +105 -10
- package/src/defaults/gjc/skills/ralplan/SKILL.md +6 -4
- package/src/defaults/gjc-defaults.test.ts +18 -1
- package/src/defaults/gjc-defaults.ts +3 -0
- package/src/defaults/gjc-skills.generated.ts +58 -36
- package/src/discovery/agents.ts +6 -1
- package/src/discovery/builtin.ts +10 -0
- package/src/discovery/helpers.ts +159 -20
- package/src/discovery/mcp-json.ts +6 -0
- package/src/discovery/ssh.ts +1 -1
- package/src/discovery/substitute-plugin-root.ts +3 -1
- package/src/edit/file-read-cache.ts +1 -1
- package/src/eval/py/executor.ts +380 -120
- package/src/export/html/css-color.ts +9 -0
- package/src/export/html/index.ts +5 -4
- package/src/export/html/template.generated.ts +1 -1
- package/src/extensibility/extensions/runner.ts +4 -0
- package/src/extensibility/extensions/types.ts +7 -0
- package/src/extensibility/gjc-plugins/runtime-adapters.ts +73 -8
- package/src/extensibility/plugins/manager.ts +3 -2
- package/src/extensibility/plugins/marketplace/cache.ts +15 -0
- package/src/extensibility/plugins/marketplace/manager.ts +11 -3
- package/src/extensibility/plugins/plugin-link-path.ts +12 -0
- package/src/extensibility/runtime-skill-discovery.ts +20 -2
- package/src/extensibility/skill-management.ts +6 -2
- package/src/extensibility/skills.ts +6 -1
- package/src/gjc-runtime/deep-interview-crystallize.ts +1814 -0
- package/src/gjc-runtime/deep-interview-recorder.ts +20 -2
- package/src/gjc-runtime/deep-interview-runtime.ts +1415 -13
- package/src/gjc-runtime/deep-interview-stage.ts +98 -21
- package/src/gjc-runtime/gc-runtime.ts +206 -9
- package/src/gjc-runtime/launch-worktree.ts +14 -4
- package/src/gjc-runtime/ralplan-runtime.ts +447 -52
- package/src/gjc-runtime/state-argv.ts +2 -0
- package/src/gjc-runtime/state-migrations.ts +91 -29
- package/src/gjc-runtime/state-runtime.ts +3716 -135
- package/src/gjc-runtime/state-writer.ts +83 -8
- package/src/gjc-runtime/ultragoal-runtime.ts +16 -4
- package/src/gjc-runtime/workflow-manifest.generated.json +70 -42
- package/src/gjc-runtime/workflow-manifest.ts +54 -21
- package/src/harness-control-plane/operate.ts +12 -4
- package/src/harness-control-plane/owner.ts +5 -1
- package/src/hashline/parser.ts +48 -9
- package/src/hashline/recovery.ts +13 -4
- package/src/internal-urls/docs-index.generated.ts +18 -17
- package/src/internal-urls/skill-path.ts +19 -0
- package/src/internal-urls/skill-protocol.ts +2 -0
- package/src/lsp/edits.ts +6 -0
- package/src/lsp/workspace-path.ts +51 -0
- package/src/main.ts +195 -31
- package/src/modes/acp/acp-agent.ts +88 -4
- package/src/modes/components/custom-editor.ts +14 -0
- package/src/modes/components/customization/customization-dashboard.ts +12 -0
- package/src/modes/components/extensions/extension-dashboard.ts +2 -2
- package/src/modes/components/extensions/state-manager.ts +15 -5
- package/src/modes/components/model-selector.ts +1 -4
- package/src/modes/components/provider-onboarding-selector.ts +1 -1
- package/src/modes/components/status-line/segments.ts +4 -0
- package/src/modes/controllers/event-controller.ts +11 -4
- package/src/modes/controllers/input-controller.ts +74 -29
- package/src/modes/controllers/runtime-mcp-command-controller.ts +8 -3
- package/src/modes/controllers/selector-controller.ts +28 -15
- package/src/modes/interactive-mode.ts +4 -0
- package/src/modes/runtime-init.ts +4 -0
- package/src/modes/utils/abort-message.ts +3 -1
- package/src/modes/utils/interrupt-ownership.ts +12 -0
- package/src/modes/utils/keybinding-matchers.ts +4 -0
- package/src/modes/utils/macos-option-forwarding.ts +80 -0
- package/src/progress/collect-project-progress.ts +153 -0
- package/src/progress/progress-contract.ts +172 -0
- package/src/progress/progress-snapshot.ts +140 -0
- package/src/progress/project-progress.ts +446 -0
- package/src/progress/render-progress.ts +209 -0
- package/src/prompts/system/master-mode.md +1 -0
- package/src/prompts/tools/skill-discovery.md +1 -1
- package/src/runtime-mcp/config-writer.ts +10 -6
- package/src/runtime-mcp/config.ts +1 -0
- package/src/runtime-mcp/oauth-flow.ts +5 -0
- package/src/runtime-mcp/oauth-public-url.ts +8 -0
- package/src/runtime-mcp/plugin-network-boundary.ts +4 -0
- package/src/runtime-mcp/smithery-registry.ts +22 -3
- package/src/runtime-mcp/transports/http.ts +2 -2
- package/src/runtime-mcp/types.ts +6 -0
- package/src/sdk/acp/adapter.ts +93 -8
- package/src/sdk/broker/broker-exit.ts +52 -23
- package/src/sdk/broker/broker.ts +75 -6
- package/src/sdk/broker/ensure.ts +2 -0
- package/src/sdk/broker/lifecycle.ts +711 -66
- package/src/sdk/broker/session-index.ts +191 -81
- package/src/sdk/bus/chat-daemon-cli.ts +38 -1
- package/src/sdk/bus/chat-daemon-control.ts +2 -2
- package/src/sdk/bus/index.ts +238 -43
- package/src/sdk/bus/telegram-daemon-contract.ts +6 -1
- package/src/sdk/cli/session-cli.ts +17 -3
- package/src/sdk/client/client.ts +28 -8
- package/src/sdk/host/query/handlers.ts +9 -1
- package/src/sdk/host/session-runtime.test.ts +2647 -294
- package/src/sdk/host/session-runtime.ts +426 -109
- package/src/sdk/host/surface-policy.ts +1 -0
- package/src/sdk/index.ts +8 -0
- package/src/sdk/lifecycle-session.ts +3 -1
- package/src/sdk/prompt-deadline-manager.ts +15 -0
- package/src/sdk/protocol/operation-inventory.generated.json +146 -0
- package/src/sdk/protocol/operation-registry.ts +9 -2
- package/src/sdk/router/session-router.ts +75 -12
- package/src/sdk/session-list.ts +1 -0
- package/src/sdk/session.ts +67 -38
- package/src/session/agent-session.ts +623 -224
- package/src/session/artifacts.ts +174 -70
- package/src/session/internal/managed-gc-retirement-codec.ts +319 -0
- package/src/session/internal/managed-session-scope.ts +3457 -462
- package/src/session/internal/managed-session-storage.ts +376 -61
- package/src/session/internal/managed-task-owner-cleanup.ts +473 -0
- package/src/session/internal/task-artifact-owner-access.ts +19 -3
- package/src/session/internal/task-artifact-owner-transcript.ts +547 -1
- package/src/session/session-manager.ts +939 -133
- package/src/session/session-retirement.ts +573 -14
- package/src/session/session-storage.ts +417 -14
- package/src/session/task-artifact-owner-codec.ts +71 -8
- package/src/session/task-artifact-owner-retirement.ts +21 -19
- package/src/setup/credential-auto-import.ts +12 -3
- package/src/setup/credential-import.ts +176 -5
- package/src/setup/paseo/announce.ts +6 -1
- package/src/skill-state/active-state.ts +132 -2
- package/src/slash-commands/builtin-registry.ts +39 -9
- package/src/slash-commands/helpers/progress-report.ts +23 -0
- package/src/stt/setup.ts +3 -5
- package/src/task/commands.ts +3 -1
- package/src/task/executor.ts +4 -0
- package/src/task/index.ts +6 -0
- package/src/tools/ask.ts +205 -6
- package/src/tools/ast-edit.ts +4 -0
- package/src/tools/bash-allowed-prefixes.ts +15 -0
- package/src/tools/bash-skill-urls.ts +56 -3
- package/src/tools/bash.ts +48 -79
- package/src/tools/descriptors.ts +5 -1
- package/src/tools/eval.ts +56 -36
- package/src/tools/image-gen.ts +1 -1
- package/src/tools/index.ts +3 -0
- package/src/tools/python.ts +187 -66
- package/src/tools/recipe/index.ts +9 -0
- package/src/tools/recipe/recipe-guard.ts +19 -0
- package/src/tools/restricted-cwd.ts +10 -0
- package/src/tools/skill-discovery.ts +5 -0
- package/src/tools/skill.ts +28 -1
- package/src/tools/todo-write.ts +10 -1
- package/src/tools/tool-catalog.generated.ts +1 -1
- package/src/tools/write.ts +1 -0
- package/src/utils/tools-checksum.ts +34 -0
- package/src/utils/tools-manager.ts +24 -6
- package/src/web/search/providers/codex.ts +3 -2
|
@@ -34,6 +34,20 @@ export class ModelBindingsApplier {
|
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
/** Fork configured bindings and their applied lifecycle onto independent settings. */
|
|
38
|
+
snapshotForSettings(targetSettings: Settings): ModelBindingsApplier {
|
|
39
|
+
const snapshot = new ModelBindingsApplier();
|
|
40
|
+
snapshot.#targetSettings = targetSettings;
|
|
41
|
+
snapshot.#bindings = this.getBindings();
|
|
42
|
+
snapshot.#appliedRoles = new Set(this.#appliedRoles);
|
|
43
|
+
snapshot.#appliedAgentOverrides = new Set(this.#appliedAgentOverrides);
|
|
44
|
+
snapshot.#roleBaselines = this.#cloneSelectorMap(this.#roleBaselines);
|
|
45
|
+
snapshot.#agentBaselines = this.#cloneSelectorMap(this.#agentBaselines);
|
|
46
|
+
snapshot.#lastAppliedRoles = this.#cloneSelectorMap(this.#lastAppliedRoles);
|
|
47
|
+
snapshot.#lastAppliedAgentOverrides = this.#cloneSelectorMap(this.#lastAppliedAgentOverrides);
|
|
48
|
+
return snapshot;
|
|
49
|
+
}
|
|
50
|
+
|
|
37
51
|
applyTo(targetSettings: Settings): void {
|
|
38
52
|
if (this.#targetSettings && this.#targetSettings !== targetSettings) {
|
|
39
53
|
this.#restoreTarget(this.#targetSettings);
|
|
@@ -184,6 +198,12 @@ export class ModelBindingsApplier {
|
|
|
184
198
|
return copy;
|
|
185
199
|
}
|
|
186
200
|
|
|
201
|
+
#cloneSelectorMap<T extends ModelSelectorValue | undefined>(source: Map<string, T>): Map<string, T> {
|
|
202
|
+
const copy = new Map<string, T>();
|
|
203
|
+
for (const [key, value] of source) copy.set(key, this.#clone(value) as T);
|
|
204
|
+
return copy;
|
|
205
|
+
}
|
|
206
|
+
|
|
187
207
|
#clone(value: ModelSelectorValue | undefined): ModelSelectorValue | undefined {
|
|
188
208
|
return Array.isArray(value) ? [...value] : value;
|
|
189
209
|
}
|
|
@@ -37,6 +37,11 @@ import {
|
|
|
37
37
|
import { type ModelSelectorValue, normalizeModelSelectorValue } from "./model-selector-value";
|
|
38
38
|
import type { Settings } from "./settings";
|
|
39
39
|
|
|
40
|
+
type UserCanonicalVariantSelection = {
|
|
41
|
+
revision: number;
|
|
42
|
+
canonicalVariant: string | undefined;
|
|
43
|
+
};
|
|
44
|
+
|
|
40
45
|
type ModelProfileActivationSession = Pick<
|
|
41
46
|
AgentSession,
|
|
42
47
|
"model" | "thinkingLevel" | "sessionId" | "getConfiguredModelChain" | "setConfiguredModelChain"
|
|
@@ -59,6 +64,7 @@ type ModelProfileActivationSession = Pick<
|
|
|
59
64
|
syncEagerDelegation?: () => Promise<void>;
|
|
60
65
|
getSessionDefaultModelSelector?: () => string | undefined;
|
|
61
66
|
recordResumeDefaultModel?: (selector: string | undefined) => void;
|
|
67
|
+
getUserCanonicalVariantSelection?: () => UserCanonicalVariantSelection;
|
|
62
68
|
seedDefaultFallbackResolution?: (activeIndex: number, skips: Array<{ selector: string; reason: string }>) => void;
|
|
63
69
|
getDefaultFallbackRuntimeState?: () => DefaultFallbackRuntimeState;
|
|
64
70
|
restoreDefaultFallbackRuntimeState?: (state: DefaultFallbackRuntimeState) => void;
|
|
@@ -73,8 +79,7 @@ type ModelProfileActivationSession = Pick<
|
|
|
73
79
|
| "resolveModelByLookupAlias"
|
|
74
80
|
| "authStorage"
|
|
75
81
|
| "isCredentiallessProvider"
|
|
76
|
-
|
|
77
|
-
Partial<Pick<ModelRegistry, "getAvailableForProfileActivation">>;
|
|
82
|
+
>;
|
|
78
83
|
getConfiguredModelChainState?: (role: string) => ConfiguredModelChainState | undefined;
|
|
79
84
|
};
|
|
80
85
|
|
|
@@ -103,7 +108,6 @@ export interface PrepareModelProfileActivationOptions {
|
|
|
103
108
|
Pick<
|
|
104
109
|
ModelRegistry,
|
|
105
110
|
| "getAvailable"
|
|
106
|
-
| "getAvailableForProfileActivation"
|
|
107
111
|
| "resolveModelByLookupAlias"
|
|
108
112
|
| "lookupAliasExists"
|
|
109
113
|
| "clearCanonicalVariant"
|
|
@@ -123,6 +127,8 @@ export interface PrepareModelProfileActivationOptions {
|
|
|
123
127
|
export interface ApplyModelProfileActivationOptions {
|
|
124
128
|
persistDefault?: boolean;
|
|
125
129
|
thinkingLevelOverride?: ThinkingLevel;
|
|
130
|
+
/** Cancels deferred activation if a newer user model selection exists. */
|
|
131
|
+
isCurrent?: () => boolean;
|
|
126
132
|
}
|
|
127
133
|
export interface PreparedModelProfileActivation {
|
|
128
134
|
profileName: string;
|
|
@@ -176,6 +182,7 @@ export interface PreparedModelProfileActivation {
|
|
|
176
182
|
* so a stale provider cannot silently resurrect.
|
|
177
183
|
*/
|
|
178
184
|
previousCanonicalVariant: string | undefined;
|
|
185
|
+
previousUserCanonicalVariantSelection: UserCanonicalVariantSelection | undefined;
|
|
179
186
|
/** Registry used to resolve and restore the session sticky canonical variant. */
|
|
180
187
|
modelRegistry: PrepareModelProfileActivationOptions["modelRegistry"];
|
|
181
188
|
}
|
|
@@ -258,10 +265,8 @@ function concretizeMaterializedAssignmentValues(
|
|
|
258
265
|
if (!modelRegistry || !sessionId) return assignments;
|
|
259
266
|
// Materialized assignments are persisted into `modelRoles` and
|
|
260
267
|
// `task.agentModelOverrides` and later consumed by profile execution, so they
|
|
261
|
-
//
|
|
262
|
-
|
|
263
|
-
// bundled model that fresh live profile evidence excludes.
|
|
264
|
-
const availableModels = modelRegistry.getAvailableForProfileActivation?.() ?? modelRegistry.getAvailable();
|
|
268
|
+
// resolve against the same catalog profile activation uses.
|
|
269
|
+
const availableModels = modelRegistry.getAvailable();
|
|
265
270
|
const authenticatedModels = availableModels.filter(model => {
|
|
266
271
|
const isCredentiallessProvider = modelRegistry.isCredentiallessProvider?.bind(modelRegistry);
|
|
267
272
|
const hasUsableAuth = modelRegistry.authStorage?.hasUsableAuth?.bind(modelRegistry.authStorage);
|
|
@@ -879,10 +884,7 @@ export async function resolveModelProfileDefaultChain(options: {
|
|
|
879
884
|
allRoutable && proxyProvider !== undefined ? [proxyProvider] : [...group],
|
|
880
885
|
);
|
|
881
886
|
}
|
|
882
|
-
const availableModels =
|
|
883
|
-
options.modelRegistry.getAvailableForProfileActivation?.() ??
|
|
884
|
-
options.modelRegistry.getAvailable?.() ??
|
|
885
|
-
options.modelRegistry.getAll();
|
|
887
|
+
const availableModels = options.modelRegistry.getAvailable?.() ?? options.modelRegistry.getAll();
|
|
886
888
|
let bindings = resolveProfileBindings(profile);
|
|
887
889
|
if (alternativeGroups.length > 0)
|
|
888
890
|
bindings = rewriteBindingsProviders(bindings, authenticatedProviders, alternativeGroups);
|
|
@@ -1323,6 +1325,25 @@ function restoreCanonicalVariant(
|
|
|
1323
1325
|
modelRegistry.clearCanonicalVariant?.(sessionId);
|
|
1324
1326
|
}
|
|
1325
1327
|
}
|
|
1328
|
+
|
|
1329
|
+
function restoreCanonicalVariantAfterPreparation(
|
|
1330
|
+
modelRegistry: PrepareModelProfileActivationOptions["modelRegistry"],
|
|
1331
|
+
session: ModelProfileActivationSession,
|
|
1332
|
+
previousCanonicalVariant: string | undefined,
|
|
1333
|
+
previousUserSelection: UserCanonicalVariantSelection | undefined,
|
|
1334
|
+
): void {
|
|
1335
|
+
const currentUserSelection = session.getUserCanonicalVariantSelection?.();
|
|
1336
|
+
const userSelectionChanged =
|
|
1337
|
+
previousUserSelection !== undefined &&
|
|
1338
|
+
currentUserSelection !== undefined &&
|
|
1339
|
+
currentUserSelection.revision !== previousUserSelection.revision;
|
|
1340
|
+
restoreCanonicalVariant(
|
|
1341
|
+
modelRegistry,
|
|
1342
|
+
session.sessionId,
|
|
1343
|
+
userSelectionChanged ? currentUserSelection.canonicalVariant : previousCanonicalVariant,
|
|
1344
|
+
);
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1326
1347
|
export async function prepareModelProfileActivation(
|
|
1327
1348
|
options: PrepareModelProfileActivationOptions,
|
|
1328
1349
|
): Promise<PreparedModelProfileActivation> {
|
|
@@ -1337,6 +1358,7 @@ export async function prepareModelProfileActivation(
|
|
|
1337
1358
|
// genuinely-sticky provider even when the live model is a transient switch.
|
|
1338
1359
|
const credentialSessionId = options.session.credentialSessionId ?? options.session.sessionId;
|
|
1339
1360
|
const previousCanonicalVariant = options.modelRegistry.getSessionCanonicalVariant?.(options.session.sessionId);
|
|
1361
|
+
const previousUserCanonicalVariantSelection = options.session.getUserCanonicalVariantSelection?.();
|
|
1340
1362
|
|
|
1341
1363
|
// Explicit profile activation/reselection invalidates the session's sticky
|
|
1342
1364
|
// canonical variant BEFORE the new profile's aliases resolve, so the old
|
|
@@ -1464,10 +1486,7 @@ export async function prepareModelProfileActivation(
|
|
|
1464
1486
|
);
|
|
1465
1487
|
}
|
|
1466
1488
|
|
|
1467
|
-
const availableModels =
|
|
1468
|
-
options.modelRegistry.getAvailableForProfileActivation?.() ??
|
|
1469
|
-
options.modelRegistry.getAvailable?.() ??
|
|
1470
|
-
options.modelRegistry.getAll();
|
|
1489
|
+
const availableModels = options.modelRegistry.getAvailable?.() ?? options.modelRegistry.getAll();
|
|
1471
1490
|
const roleCatalogModels = options.modelRegistry.getAll();
|
|
1472
1491
|
let bindings = resolveProfileBindings(profile);
|
|
1473
1492
|
if (alternativeGroups.length > 0) {
|
|
@@ -1562,6 +1581,7 @@ export async function prepareModelProfileActivation(
|
|
|
1562
1581
|
modelRegistry: options.modelRegistry,
|
|
1563
1582
|
previousModel,
|
|
1564
1583
|
previousCanonicalVariant,
|
|
1584
|
+
previousUserCanonicalVariantSelection,
|
|
1565
1585
|
previousThinkingLevel: options.session.thinkingLevel,
|
|
1566
1586
|
previousAgentModelOverrides: { ...options.settings.get("task.agentModelOverrides") },
|
|
1567
1587
|
previousModelRoles: { ...options.settings.get("modelRoles") },
|
|
@@ -1602,7 +1622,12 @@ export async function prepareModelProfileActivation(
|
|
|
1602
1622
|
};
|
|
1603
1623
|
} catch (error) {
|
|
1604
1624
|
try {
|
|
1605
|
-
|
|
1625
|
+
restoreCanonicalVariantAfterPreparation(
|
|
1626
|
+
options.modelRegistry,
|
|
1627
|
+
options.session,
|
|
1628
|
+
previousCanonicalVariant,
|
|
1629
|
+
previousUserCanonicalVariantSelection,
|
|
1630
|
+
);
|
|
1606
1631
|
} catch (rollbackError) {
|
|
1607
1632
|
throw incompleteModelProfileRollbackError("preparation", "profile preflight", error, [
|
|
1608
1633
|
{ stage: "restore canonical model variant", error: rollbackError },
|
|
@@ -1648,10 +1673,45 @@ function incompleteModelProfileRollbackError(
|
|
|
1648
1673
|
);
|
|
1649
1674
|
}
|
|
1650
1675
|
|
|
1676
|
+
class ModelProfileActivationSupersededError extends Error {
|
|
1677
|
+
constructor() {
|
|
1678
|
+
super("Model profile activation superseded by a newer user model selection");
|
|
1679
|
+
this.name = "ModelProfileActivationSupersededError";
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
function sameSerializedValue(left: unknown, right: unknown): boolean {
|
|
1684
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
function restoreConcurrentProfileOverrides(
|
|
1688
|
+
previous: Readonly<Record<string, ModelSelectorValue>> | undefined,
|
|
1689
|
+
activated: Readonly<Record<string, ModelSelectorValue>> | undefined,
|
|
1690
|
+
current: Readonly<Record<string, ModelSelectorValue>> | undefined,
|
|
1691
|
+
): Readonly<Record<string, ModelSelectorValue>> | undefined {
|
|
1692
|
+
if (sameSerializedValue(current, activated)) return previous;
|
|
1693
|
+
const restored = { ...(previous ?? {}) };
|
|
1694
|
+
const keys = new Set([
|
|
1695
|
+
...Object.keys(previous ?? {}),
|
|
1696
|
+
...Object.keys(activated ?? {}),
|
|
1697
|
+
...Object.keys(current ?? {}),
|
|
1698
|
+
]);
|
|
1699
|
+
for (const key of keys) {
|
|
1700
|
+
const wasActivated = activated !== undefined && Object.hasOwn(activated, key);
|
|
1701
|
+
const isCurrent = current !== undefined && Object.hasOwn(current, key);
|
|
1702
|
+
if (wasActivated === isCurrent && sameSerializedValue(activated?.[key], current?.[key])) continue;
|
|
1703
|
+
const currentValue = current?.[key];
|
|
1704
|
+
if (isCurrent && currentValue !== undefined) restored[key] = currentValue;
|
|
1705
|
+
else delete restored[key];
|
|
1706
|
+
}
|
|
1707
|
+
return Object.keys(restored).length > 0 || previous !== undefined ? restored : undefined;
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1651
1710
|
export async function applyPreparedModelProfileActivation(
|
|
1652
1711
|
prepared: PreparedModelProfileActivation,
|
|
1653
1712
|
options: ApplyModelProfileActivationOptions = {},
|
|
1654
1713
|
): Promise<void> {
|
|
1714
|
+
if (options.isCurrent && !options.isCurrent()) return;
|
|
1655
1715
|
let activationStage = "default chain";
|
|
1656
1716
|
let modelMutationStarted = false;
|
|
1657
1717
|
let overridesChanged = false;
|
|
@@ -1659,8 +1719,15 @@ export async function applyPreparedModelProfileActivation(
|
|
|
1659
1719
|
let persistentMutationStarted = false;
|
|
1660
1720
|
let defaultChainChanged = false;
|
|
1661
1721
|
let resumeDefaultChanged = false;
|
|
1722
|
+
let activatedDefaultChainState: ConfiguredModelChainState | undefined;
|
|
1723
|
+
let activatedFallbackRuntimeState: DefaultFallbackRuntimeState | undefined;
|
|
1724
|
+
let activatedModelRolesOverride: unknown;
|
|
1725
|
+
let activatedAgentModelOverridesOverride: unknown;
|
|
1662
1726
|
|
|
1663
1727
|
try {
|
|
1728
|
+
// Set the fallback chain before yielding to setModelTemporary, so a user
|
|
1729
|
+
// selection during async mutation uses the fallback chain as-is rather than
|
|
1730
|
+
// having the profile's chain written over a concurrent user choice.
|
|
1664
1731
|
const ownedDefaultChain =
|
|
1665
1732
|
prepared.defaultChain.length > 0
|
|
1666
1733
|
? prepared.defaultChain
|
|
@@ -1681,6 +1748,8 @@ export async function applyPreparedModelProfileActivation(
|
|
|
1681
1748
|
prepared.defaultResolutionSkips,
|
|
1682
1749
|
);
|
|
1683
1750
|
}
|
|
1751
|
+
activatedDefaultChainState = prepared.session.getConfiguredModelChainState?.("default");
|
|
1752
|
+
activatedFallbackRuntimeState = prepared.session.getDefaultFallbackRuntimeState?.();
|
|
1684
1753
|
}
|
|
1685
1754
|
if (prepared.defaultModel) {
|
|
1686
1755
|
activationStage = "model selection";
|
|
@@ -1689,11 +1758,14 @@ export async function applyPreparedModelProfileActivation(
|
|
|
1689
1758
|
options.thinkingLevelOverride ?? prepared.defaultThinkingLevel,
|
|
1690
1759
|
{
|
|
1691
1760
|
cause: "profile-activation",
|
|
1761
|
+
shouldMutate: options.isCurrent,
|
|
1692
1762
|
onMutationStarted: () => {
|
|
1693
1763
|
modelMutationStarted = true;
|
|
1694
1764
|
},
|
|
1695
1765
|
},
|
|
1696
1766
|
);
|
|
1767
|
+
if (options.isCurrent && !modelMutationStarted) throw new ModelProfileActivationSupersededError();
|
|
1768
|
+
if (options.isCurrent && !options.isCurrent()) throw new ModelProfileActivationSupersededError();
|
|
1697
1769
|
}
|
|
1698
1770
|
// Always reinstall the model role layer from the durable base plus the
|
|
1699
1771
|
// new profile's roles so omitted roles from the previous profile are dropped.
|
|
@@ -1702,6 +1774,7 @@ export async function applyPreparedModelProfileActivation(
|
|
|
1702
1774
|
...prepared.baseModelRoles,
|
|
1703
1775
|
...prepared.modelRoles,
|
|
1704
1776
|
});
|
|
1777
|
+
activatedModelRolesOverride = prepared.settings.getOverride("modelRoles");
|
|
1705
1778
|
modelRolesChanged = true;
|
|
1706
1779
|
// Always reinstall the agent role layer from the durable base plus the
|
|
1707
1780
|
// new profile's roles: a default-only or role-free successor must drop
|
|
@@ -1711,6 +1784,7 @@ export async function applyPreparedModelProfileActivation(
|
|
|
1711
1784
|
...prepared.baseAgentModelOverrides,
|
|
1712
1785
|
...prepared.agentModelOverrides,
|
|
1713
1786
|
});
|
|
1787
|
+
activatedAgentModelOverridesOverride = prepared.settings.getOverride("task.agentModelOverrides");
|
|
1714
1788
|
overridesChanged = true;
|
|
1715
1789
|
if (options.persistDefault) {
|
|
1716
1790
|
persistentMutationStarted = true;
|
|
@@ -1727,6 +1801,7 @@ export async function applyPreparedModelProfileActivation(
|
|
|
1727
1801
|
activationStage = "forward settings flush";
|
|
1728
1802
|
await prepared.settings.flushOrThrow();
|
|
1729
1803
|
}
|
|
1804
|
+
if (options.isCurrent && !options.isCurrent()) throw new ModelProfileActivationSupersededError();
|
|
1730
1805
|
activationStage = "active profile marker";
|
|
1731
1806
|
prepared.session.setActiveModelProfile?.(prepared.profileName);
|
|
1732
1807
|
if (prepared.defaultModel) {
|
|
@@ -1743,6 +1818,8 @@ export async function applyPreparedModelProfileActivation(
|
|
|
1743
1818
|
prepared.previousModel,
|
|
1744
1819
|
);
|
|
1745
1820
|
} catch (error) {
|
|
1821
|
+
const activationWasCancelled = error instanceof ModelProfileActivationSupersededError;
|
|
1822
|
+
const selectionSuperseded = options.isCurrent?.() === false;
|
|
1746
1823
|
const rollbackErrors: Array<{ stage: string; error: unknown }> = [];
|
|
1747
1824
|
const restore = (stage: string, action: () => void): void => {
|
|
1748
1825
|
try {
|
|
@@ -1752,42 +1829,82 @@ export async function applyPreparedModelProfileActivation(
|
|
|
1752
1829
|
}
|
|
1753
1830
|
};
|
|
1754
1831
|
if (persistentMutationStarted) {
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1832
|
+
if (
|
|
1833
|
+
!selectionSuperseded ||
|
|
1834
|
+
sameSerializedValue(prepared.settings.getGlobal("modelProfile.default"), prepared.profileName)
|
|
1835
|
+
) {
|
|
1836
|
+
restore("restore default profile setting", () =>
|
|
1837
|
+
prepared.previousPersistedDefaultProfile === undefined
|
|
1838
|
+
? prepared.settings.unset("modelProfile.default")
|
|
1839
|
+
: prepared.settings.set("modelProfile.default", prepared.previousPersistedDefaultProfile),
|
|
1840
|
+
);
|
|
1841
|
+
}
|
|
1842
|
+
const currentPersistedModelRoles = prepared.settings.getGlobal("modelRoles");
|
|
1843
|
+
const restoredModelRoles =
|
|
1844
|
+
selectionSuperseded && currentPersistedModelRoles && !sameSerializedValue(currentPersistedModelRoles, {})
|
|
1845
|
+
? { ...(prepared.previousPersistedModelRoles ?? {}), ...currentPersistedModelRoles }
|
|
1846
|
+
: prepared.previousPersistedModelRoles;
|
|
1760
1847
|
restore("restore model role setting", () =>
|
|
1761
|
-
|
|
1848
|
+
restoredModelRoles === undefined
|
|
1762
1849
|
? prepared.settings.unset("modelRoles")
|
|
1763
|
-
: prepared.settings.set("modelRoles",
|
|
1850
|
+
: prepared.settings.set("modelRoles", restoredModelRoles),
|
|
1764
1851
|
);
|
|
1852
|
+
const currentPersistedAgentModelOverrides = prepared.settings.getGlobal("task.agentModelOverrides");
|
|
1853
|
+
const restoredPersistedAgentModelOverrides =
|
|
1854
|
+
selectionSuperseded &&
|
|
1855
|
+
currentPersistedAgentModelOverrides &&
|
|
1856
|
+
!sameSerializedValue(currentPersistedAgentModelOverrides, {})
|
|
1857
|
+
? {
|
|
1858
|
+
...(prepared.previousPersistedAgentModelOverrides ?? {}),
|
|
1859
|
+
...currentPersistedAgentModelOverrides,
|
|
1860
|
+
}
|
|
1861
|
+
: prepared.previousPersistedAgentModelOverrides;
|
|
1765
1862
|
restore("restore agent role setting", () =>
|
|
1766
|
-
|
|
1863
|
+
restoredPersistedAgentModelOverrides === undefined
|
|
1767
1864
|
? prepared.settings.unset("task.agentModelOverrides")
|
|
1768
|
-
: prepared.settings.set("task.agentModelOverrides",
|
|
1769
|
-
);
|
|
1770
|
-
restore("restore thinking level setting", () =>
|
|
1771
|
-
prepared.previousPersistedDefaultThinkingLevel === undefined
|
|
1772
|
-
? prepared.settings.unset("defaultThinkingLevel")
|
|
1773
|
-
: prepared.settings.set("defaultThinkingLevel", prepared.previousPersistedDefaultThinkingLevel),
|
|
1865
|
+
: prepared.settings.set("task.agentModelOverrides", restoredPersistedAgentModelOverrides),
|
|
1774
1866
|
);
|
|
1867
|
+
const activatedThinkingLevel =
|
|
1868
|
+
prepared.defaultThinkingLevel !== undefined && prepared.defaultThinkingLevel !== ThinkingLevel.Inherit
|
|
1869
|
+
? prepared.defaultThinkingLevel
|
|
1870
|
+
: prepared.previousPersistedDefaultThinkingLevel;
|
|
1871
|
+
if (
|
|
1872
|
+
!selectionSuperseded ||
|
|
1873
|
+
sameSerializedValue(prepared.settings.getGlobal("defaultThinkingLevel"), activatedThinkingLevel)
|
|
1874
|
+
) {
|
|
1875
|
+
restore("restore thinking level setting", () =>
|
|
1876
|
+
prepared.previousPersistedDefaultThinkingLevel === undefined
|
|
1877
|
+
? prepared.settings.unset("defaultThinkingLevel")
|
|
1878
|
+
: prepared.settings.set("defaultThinkingLevel", prepared.previousPersistedDefaultThinkingLevel),
|
|
1879
|
+
);
|
|
1880
|
+
}
|
|
1775
1881
|
}
|
|
1776
|
-
if (
|
|
1882
|
+
if (
|
|
1883
|
+
modelRolesChanged &&
|
|
1884
|
+
(!selectionSuperseded ||
|
|
1885
|
+
sameSerializedValue(prepared.settings.getOverride("modelRoles"), activatedModelRolesOverride))
|
|
1886
|
+
) {
|
|
1777
1887
|
restore("restore model role overrides", () =>
|
|
1778
1888
|
prepared.previousModelRolesOverride === undefined
|
|
1779
1889
|
? prepared.settings.clearOverride("modelRoles")
|
|
1780
1890
|
: prepared.settings.override("modelRoles", prepared.previousModelRolesOverride),
|
|
1781
1891
|
);
|
|
1782
1892
|
}
|
|
1783
|
-
if (
|
|
1893
|
+
if (
|
|
1894
|
+
overridesChanged &&
|
|
1895
|
+
(!selectionSuperseded ||
|
|
1896
|
+
sameSerializedValue(
|
|
1897
|
+
prepared.settings.getOverride("task.agentModelOverrides"),
|
|
1898
|
+
activatedAgentModelOverridesOverride,
|
|
1899
|
+
))
|
|
1900
|
+
) {
|
|
1784
1901
|
restore("restore agent role overrides", () =>
|
|
1785
1902
|
prepared.previousAgentModelOverridesOverride === undefined
|
|
1786
1903
|
? prepared.settings.clearOverride("task.agentModelOverrides")
|
|
1787
1904
|
: prepared.settings.override("task.agentModelOverrides", prepared.previousAgentModelOverridesOverride),
|
|
1788
1905
|
);
|
|
1789
1906
|
}
|
|
1790
|
-
if (modelMutationStarted) {
|
|
1907
|
+
if (modelMutationStarted && !selectionSuperseded) {
|
|
1791
1908
|
try {
|
|
1792
1909
|
if (prepared.session.restoreModelSelectionForRollback) {
|
|
1793
1910
|
await prepared.session.restoreModelSelectionForRollback(
|
|
@@ -1810,7 +1927,11 @@ export async function applyPreparedModelProfileActivation(
|
|
|
1810
1927
|
prepared.session.recordResumeDefaultModel?.(prepared.previousSessionDefaultModel),
|
|
1811
1928
|
);
|
|
1812
1929
|
}
|
|
1813
|
-
if (
|
|
1930
|
+
if (
|
|
1931
|
+
defaultChainChanged &&
|
|
1932
|
+
(!selectionSuperseded ||
|
|
1933
|
+
sameSerializedValue(prepared.session.getConfiguredModelChainState?.("default"), activatedDefaultChainState))
|
|
1934
|
+
) {
|
|
1814
1935
|
const previousChain = prepared.previousDefaultChainState;
|
|
1815
1936
|
restore("restore default chain", () =>
|
|
1816
1937
|
prepared.session.setConfiguredModelChain(
|
|
@@ -1824,16 +1945,27 @@ export async function applyPreparedModelProfileActivation(
|
|
|
1824
1945
|
),
|
|
1825
1946
|
);
|
|
1826
1947
|
}
|
|
1827
|
-
if (
|
|
1948
|
+
if (
|
|
1949
|
+
prepared.previousDefaultFallbackRuntimeState &&
|
|
1950
|
+
(!selectionSuperseded ||
|
|
1951
|
+
sameSerializedValue(prepared.session.getDefaultFallbackRuntimeState?.(), activatedFallbackRuntimeState))
|
|
1952
|
+
) {
|
|
1828
1953
|
restore("restore fallback runtime", () =>
|
|
1829
1954
|
prepared.session.restoreDefaultFallbackRuntimeState?.(prepared.previousDefaultFallbackRuntimeState!),
|
|
1830
1955
|
);
|
|
1831
1956
|
}
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1957
|
+
if (!selectionSuperseded) {
|
|
1958
|
+
restore("restore active profile", () =>
|
|
1959
|
+
prepared.session.setActiveModelProfile?.(prepared.previousActiveModelProfile),
|
|
1960
|
+
);
|
|
1961
|
+
}
|
|
1835
1962
|
restore("restore canonical model variant", () =>
|
|
1836
|
-
|
|
1963
|
+
restoreCanonicalVariantAfterPreparation(
|
|
1964
|
+
prepared.modelRegistry,
|
|
1965
|
+
prepared.session,
|
|
1966
|
+
prepared.previousCanonicalVariant,
|
|
1967
|
+
prepared.previousUserCanonicalVariantSelection,
|
|
1968
|
+
),
|
|
1837
1969
|
);
|
|
1838
1970
|
if (persistentMutationStarted) {
|
|
1839
1971
|
try {
|
|
@@ -1845,6 +1977,7 @@ export async function applyPreparedModelProfileActivation(
|
|
|
1845
1977
|
if (rollbackErrors.length > 0) {
|
|
1846
1978
|
throw incompleteModelProfileRollbackError("activation", activationStage, error, rollbackErrors);
|
|
1847
1979
|
}
|
|
1980
|
+
if (activationWasCancelled) return;
|
|
1848
1981
|
throw error;
|
|
1849
1982
|
}
|
|
1850
1983
|
// The installed role layer decides whether this profile is vendor-separated,
|
|
@@ -2112,28 +2245,46 @@ export async function activateModelProfile(
|
|
|
2112
2245
|
options: PrepareModelProfileActivationOptions,
|
|
2113
2246
|
applyOptions: ApplyModelProfileActivationOptions = {},
|
|
2114
2247
|
): Promise<void> {
|
|
2248
|
+
if (applyOptions.isCurrent && !applyOptions.isCurrent()) return;
|
|
2115
2249
|
const prepared = await prepareModelProfileActivation(options);
|
|
2250
|
+
if (applyOptions.isCurrent && !applyOptions.isCurrent()) {
|
|
2251
|
+
restoreCanonicalVariantAfterPreparation(
|
|
2252
|
+
prepared.modelRegistry,
|
|
2253
|
+
prepared.session,
|
|
2254
|
+
prepared.previousCanonicalVariant,
|
|
2255
|
+
prepared.previousUserCanonicalVariantSelection,
|
|
2256
|
+
);
|
|
2257
|
+
return;
|
|
2258
|
+
}
|
|
2116
2259
|
await applyPreparedModelProfileActivation(prepared, applyOptions);
|
|
2117
2260
|
}
|
|
2118
2261
|
|
|
2119
2262
|
/** Install only a profile's runtime role layer, preserving session model and configured-chain intent. */
|
|
2120
|
-
|
|
2263
|
+
|
|
2264
|
+
export async function applyModelProfileRuntimeBindings(
|
|
2265
|
+
options: PrepareModelProfileActivationOptions,
|
|
2266
|
+
isCurrent?: () => boolean,
|
|
2267
|
+
): Promise<void> {
|
|
2268
|
+
if (isCurrent && !isCurrent()) return;
|
|
2121
2269
|
const prepared = await prepareModelProfileActivation(options);
|
|
2270
|
+
const previousModelRolesOverride = prepared.settings.getOverride("modelRoles");
|
|
2271
|
+
const previousAgentModelOverridesOverride = prepared.settings.getOverride("task.agentModelOverrides");
|
|
2272
|
+
const previousActiveModelProfile = prepared.session.getActiveModelProfile?.();
|
|
2273
|
+
let activatedModelRolesOverride: Readonly<Record<string, ModelSelectorValue>> | undefined;
|
|
2274
|
+
let activatedAgentModelOverridesOverride: Readonly<Record<string, ModelSelectorValue>> | undefined;
|
|
2122
2275
|
try {
|
|
2276
|
+
if (isCurrent && !isCurrent()) return;
|
|
2123
2277
|
prepared.settings.override("modelRoles", {
|
|
2124
2278
|
...prepared.baseModelRoles,
|
|
2125
2279
|
...prepared.modelRoles,
|
|
2126
2280
|
});
|
|
2281
|
+
activatedModelRolesOverride = prepared.settings.getOverride("modelRoles");
|
|
2127
2282
|
prepared.settings.override("task.agentModelOverrides", {
|
|
2128
2283
|
...prepared.baseAgentModelOverrides,
|
|
2129
2284
|
...prepared.agentModelOverrides,
|
|
2130
2285
|
});
|
|
2286
|
+
activatedAgentModelOverridesOverride = prepared.settings.getOverride("task.agentModelOverrides");
|
|
2131
2287
|
prepared.session.setActiveModelProfile?.(prepared.profileName);
|
|
2132
|
-
prepared.session.noteProfileInstalledOverrides?.(
|
|
2133
|
-
Object.keys(prepared.modelRoles),
|
|
2134
|
-
Object.keys(prepared.agentModelOverrides),
|
|
2135
|
-
prepared.previousModel,
|
|
2136
|
-
);
|
|
2137
2288
|
try {
|
|
2138
2289
|
await prepared.session.syncEagerDelegation?.();
|
|
2139
2290
|
} catch (error) {
|
|
@@ -2142,7 +2293,50 @@ export async function applyModelProfileRuntimeBindings(options: PrepareModelProf
|
|
|
2142
2293
|
error: error instanceof Error ? error.message : String(error),
|
|
2143
2294
|
});
|
|
2144
2295
|
}
|
|
2296
|
+
if (isCurrent && !isCurrent()) {
|
|
2297
|
+
const restoredModelRolesOverride = restoreConcurrentProfileOverrides(
|
|
2298
|
+
previousModelRolesOverride,
|
|
2299
|
+
activatedModelRolesOverride,
|
|
2300
|
+
prepared.settings.getOverride("modelRoles"),
|
|
2301
|
+
);
|
|
2302
|
+
if (restoredModelRolesOverride === undefined) prepared.settings.clearOverride("modelRoles");
|
|
2303
|
+
else prepared.settings.override("modelRoles", restoredModelRolesOverride);
|
|
2304
|
+
const restoredAgentModelOverridesOverride = restoreConcurrentProfileOverrides(
|
|
2305
|
+
previousAgentModelOverridesOverride,
|
|
2306
|
+
activatedAgentModelOverridesOverride,
|
|
2307
|
+
prepared.settings.getOverride("task.agentModelOverrides"),
|
|
2308
|
+
);
|
|
2309
|
+
if (restoredAgentModelOverridesOverride === undefined)
|
|
2310
|
+
prepared.settings.clearOverride("task.agentModelOverrides");
|
|
2311
|
+
else prepared.settings.override("task.agentModelOverrides", restoredAgentModelOverridesOverride);
|
|
2312
|
+
if (prepared.session.getActiveModelProfile?.() === prepared.profileName) {
|
|
2313
|
+
prepared.session.setActiveModelProfile?.(previousActiveModelProfile);
|
|
2314
|
+
}
|
|
2315
|
+
try {
|
|
2316
|
+
await prepared.session.syncEagerDelegation?.();
|
|
2317
|
+
} catch (error) {
|
|
2318
|
+
logger.warn("Failed to sync eager delegation after canceled recovered profile runtime bindings", {
|
|
2319
|
+
profile: prepared.profileName,
|
|
2320
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2321
|
+
});
|
|
2322
|
+
}
|
|
2323
|
+
return;
|
|
2324
|
+
}
|
|
2325
|
+
prepared.session.noteProfileInstalledOverrides?.(
|
|
2326
|
+
Object.keys(prepared.modelRoles),
|
|
2327
|
+
Object.keys(prepared.agentModelOverrides),
|
|
2328
|
+
prepared.previousModel,
|
|
2329
|
+
);
|
|
2145
2330
|
} finally {
|
|
2146
|
-
|
|
2331
|
+
if (isCurrent && !isCurrent()) {
|
|
2332
|
+
restoreCanonicalVariantAfterPreparation(
|
|
2333
|
+
prepared.modelRegistry,
|
|
2334
|
+
prepared.session,
|
|
2335
|
+
prepared.previousCanonicalVariant,
|
|
2336
|
+
prepared.previousUserCanonicalVariantSelection,
|
|
2337
|
+
);
|
|
2338
|
+
} else {
|
|
2339
|
+
restoreCanonicalVariant(prepared.modelRegistry, prepared.session.sessionId, prepared.previousCanonicalVariant);
|
|
2340
|
+
}
|
|
2147
2341
|
}
|
|
2148
2342
|
}
|