@gajae-code/coding-agent 0.12.21 → 0.13.0
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 +67 -2
- package/dist/types/cli/args.d.ts +5 -2
- package/dist/types/cli/root-flags.d.ts +246 -0
- package/dist/types/cli.d.ts +11 -19
- package/dist/types/commands/daemon.d.ts +0 -30
- package/dist/types/commands/launch.d.ts +11 -19
- package/dist/types/commands/quick-lane.d.ts +32 -0
- package/dist/types/commands/sdk.d.ts +21 -15
- package/dist/types/config/file-lock-gc.d.ts +2 -0
- package/dist/types/config/model-equivalence.d.ts +20 -0
- package/dist/types/config/model-profile-activation.d.ts +62 -17
- package/dist/types/config/model-profiles.d.ts +10 -0
- package/dist/types/config/model-registry.d.ts +68 -1
- package/dist/types/config/model-resolver.d.ts +15 -4
- package/dist/types/config/models-config-schema.d.ts +7 -2
- package/dist/types/config/provider-selection-policy.d.ts +62 -0
- package/dist/types/config/settings-schema.d.ts +36 -78
- package/dist/types/config/settings.d.ts +2 -0
- package/dist/types/edit/renderer.d.ts +5 -2
- package/dist/types/edit/streaming.d.ts +13 -0
- package/dist/types/extensibility/custom-tools/types.d.ts +2 -0
- package/dist/types/extensibility/extensions/compact-handler.d.ts +2 -1
- package/dist/types/extensibility/extensions/types.d.ts +3 -0
- package/dist/types/gjc-runtime/gc-runtime.d.ts +19 -5
- package/dist/types/internal-urls/local-protocol.d.ts +1 -0
- package/dist/types/modes/components/model-selector.d.ts +0 -2
- package/dist/types/modes/components/provider-order-context.d.ts +45 -0
- package/dist/types/modes/components/provider-order-editor.d.ts +24 -0
- package/dist/types/modes/components/settings-defs.d.ts +5 -1
- package/dist/types/modes/components/settings-selector.d.ts +2 -0
- package/dist/types/quick-lane/classify.d.ts +40 -0
- package/dist/types/runtime/stt-settings-setup.d.ts +18 -0
- package/dist/types/sdk/broker/broker.d.ts +56 -2
- package/dist/types/sdk/broker/operation-receipt-ledger.d.ts +25 -0
- package/dist/types/sdk/broker/session-index.d.ts +83 -2
- package/dist/types/sdk/broker/state-version.d.ts +1 -1
- package/dist/types/sdk/bus/notification-service.d.ts +6 -0
- package/dist/types/sdk/bus/prompt-reconciliation.d.ts +8 -1
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +4 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +26 -0
- package/dist/types/sdk/cli/rows.d.ts +98 -0
- package/dist/types/sdk/cli/session-cli.d.ts +35 -3
- package/dist/types/sdk/elevation/allowlist.d.ts +20 -0
- package/dist/types/sdk/elevation/audit.d.ts +93 -0
- package/dist/types/sdk/elevation/capability.d.ts +3 -0
- package/dist/types/sdk/elevation/digest.d.ts +72 -0
- package/dist/types/sdk/elevation/dispatch-receipt.d.ts +85 -0
- package/dist/types/sdk/elevation/grant-ledger.d.ts +163 -0
- package/dist/types/sdk/elevation/owner.d.ts +48 -0
- package/dist/types/sdk/guides/cache.d.ts +98 -0
- package/dist/types/sdk/guides/catalog.d.ts +156 -0
- package/dist/types/sdk/guides/cli.d.ts +39 -0
- package/dist/types/sdk/guides/manifest.d.ts +66 -0
- package/dist/types/sdk/guides/verify.d.ts +66 -0
- package/dist/types/sdk/host/control/dispatch.d.ts +8 -0
- package/dist/types/sdk/host/control/index.d.ts +1 -1
- package/dist/types/sdk/host/control/operations.d.ts +3 -2
- package/dist/types/sdk/host/query/cursor.d.ts +10 -0
- package/dist/types/sdk/host/query/handlers.d.ts +21 -0
- package/dist/types/sdk/host/session-runtime.d.ts +9 -0
- package/dist/types/sdk/mcp/server.d.ts +2 -2
- package/dist/types/sdk/prompt-status.d.ts +11 -0
- package/dist/types/sdk/session.d.ts +4 -0
- package/dist/types/sdk/transport/index.d.ts +1 -0
- package/dist/types/sdk/transport/relay.d.ts +1 -0
- package/dist/types/sdk/transport/serve-cli.d.ts +20 -1
- package/dist/types/session/agent-session.d.ts +32 -18
- package/dist/types/session/blob-store.d.ts +13 -7
- package/dist/types/session/fallback-chain-controller.d.ts +15 -0
- package/dist/types/session/internal/managed-session-storage.d.ts +25 -1
- package/dist/types/session/internal/session-memory-sidecar.d.ts +5 -5
- package/dist/types/session/session-manager.d.ts +139 -10
- package/dist/types/session/session-storage.d.ts +48 -0
- package/dist/types/setup/provider-onboarding.d.ts +7 -1
- package/dist/types/slash-commands/builtin-registry.d.ts +14 -0
- package/dist/types/stt/setup.d.ts +2 -0
- package/dist/types/task/executor.d.ts +10 -2
- package/dist/types/tools/browser/runtime-diagnostics.d.ts +65 -0
- package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
- package/dist/types/tools/browser/tab-supervisor.d.ts +2 -0
- package/dist/types/tools/browser/tab-worker.d.ts +2 -0
- package/dist/types/tools/browser.d.ts +2 -0
- package/dist/types/tools/image-gen.d.ts +14 -18
- package/dist/types/tools/index.d.ts +2 -0
- package/dist/types/tools/resource-gc.d.ts +2 -0
- package/dist/types/utils/pasted-image-path.d.ts +6 -0
- package/package.json +9 -9
- package/scripts/generate-sdk-operation-inventory.ts +8 -0
- package/scripts/run-test-manifest.ts +61 -21
- package/scripts/verify-gjc-sdk-canonicalization.ts +9 -4
- package/src/cli/args.ts +62 -9
- package/src/cli/completion-cli.ts +1 -0
- package/src/cli/fast-help.ts +1 -0
- package/src/cli/root-flags.ts +100 -0
- package/src/cli/setup-cli.ts +6 -2
- package/src/cli.ts +42 -65
- package/src/commands/acp.ts +1 -1
- package/src/commands/daemon.ts +2 -31
- package/src/commands/gc.ts +1 -1
- package/src/commands/launch.ts +8 -129
- package/src/commands/quick-lane.ts +51 -0
- package/src/commands/sdk.ts +200 -26
- package/src/commands/setup.ts +4 -2
- package/src/config/file-lock-gc.ts +4 -1
- package/src/config/model-equivalence.ts +76 -7
- package/src/config/model-profile-activation.ts +1115 -265
- package/src/config/model-profiles.ts +134 -2
- package/src/config/model-registry.ts +352 -50
- package/src/config/model-resolver.ts +289 -38
- package/src/config/models-config-schema.ts +11 -4
- package/src/config/provider-selection-policy.ts +146 -0
- package/src/config/settings-schema.ts +50 -77
- package/src/config/settings.ts +40 -0
- package/src/coordinator-mcp/server.ts +32 -2
- package/src/edit/renderer.ts +175 -223
- package/src/edit/streaming.ts +108 -1
- package/src/export/html/index.ts +57 -7
- package/src/extensibility/custom-tools/types.ts +2 -0
- package/src/extensibility/extensions/compact-handler.ts +3 -2
- package/src/extensibility/extensions/runner.ts +6 -0
- package/src/extensibility/extensions/types.ts +3 -0
- package/src/gjc-runtime/gc-runtime.ts +379 -20
- package/src/gjc-runtime/launch-worktree.ts +5 -1
- package/src/gjc-runtime/team-runtime.ts +59 -2
- package/src/gjc-runtime/tmux-owner-isolation.ts +19 -0
- package/src/gjc-runtime/ultragoal-receipt-freshness.ts +16 -1
- package/src/internal-urls/docs-index.generated.ts +17 -13
- package/src/internal-urls/local-protocol.ts +1 -0
- package/src/main.ts +40 -3
- package/src/memories/index.ts +4 -2
- package/src/modes/acp/acp-agent.ts +235 -91
- package/src/modes/components/model-selector.ts +206 -42
- package/src/modes/components/provider-order-context.ts +197 -0
- package/src/modes/components/provider-order-editor.ts +441 -0
- package/src/modes/components/settings-defs.ts +21 -1
- package/src/modes/components/settings-selector.ts +45 -2
- package/src/modes/components/tool-execution.ts +47 -15
- package/src/modes/controllers/command-controller.ts +6 -3
- package/src/modes/controllers/extension-ui-controller.ts +2 -0
- package/src/modes/controllers/input-controller.ts +73 -2
- package/src/modes/controllers/selector-controller.ts +260 -153
- package/src/modes/prompt-suggestion-controller.ts +1 -1
- package/src/modes/runtime-init.ts +1 -0
- package/src/modes/utils/ui-helpers.ts +18 -0
- package/src/prompts/tools/browser.md +1 -0
- package/src/quick-lane/classify.ts +257 -0
- package/src/rlm/index.ts +1 -1
- package/src/runtime/stt-settings-setup.ts +57 -0
- package/src/sdk/acp/adapter.ts +2 -1
- package/src/sdk/broker/broker.ts +780 -12
- package/src/sdk/broker/lifecycle.ts +70 -29
- package/src/sdk/broker/operation-receipt-ledger.ts +144 -0
- package/src/sdk/broker/session-index.ts +463 -48
- package/src/sdk/broker/state-version.ts +13 -9
- package/src/sdk/broker/transport.ts +14 -1
- package/src/sdk/bus/index.ts +34 -13
- package/src/sdk/bus/kind-aware-reconciliation.ts +21 -2
- package/src/sdk/bus/notification-service.ts +47 -1
- package/src/sdk/bus/prompt-reconciliation.ts +22 -3
- package/src/sdk/bus/telegram-daemon-contract.ts +4 -1
- package/src/sdk/bus/telegram-daemon.ts +54 -3
- package/src/sdk/cli/rows.ts +247 -0
- package/src/sdk/cli/session-cli.ts +930 -79
- package/src/sdk/elevation/allowlist.ts +54 -0
- package/src/sdk/elevation/audit.ts +208 -0
- package/src/sdk/elevation/capability.ts +41 -0
- package/src/sdk/elevation/digest.ts +129 -0
- package/src/sdk/elevation/dispatch-receipt.ts +184 -0
- package/src/sdk/elevation/grant-ledger.ts +1142 -0
- package/src/sdk/elevation/owner.ts +109 -0
- package/src/sdk/guides/cache.ts +363 -0
- package/src/sdk/guides/catalog.ts +554 -0
- package/src/sdk/guides/cli.ts +235 -0
- package/src/sdk/guides/manifest.ts +152 -0
- package/src/sdk/guides/verify.ts +178 -0
- package/src/sdk/host/control/dispatch.ts +49 -1
- package/src/sdk/host/control/index.ts +1 -0
- package/src/sdk/host/control/operations.ts +8 -1
- package/src/sdk/host/query/cursor.ts +47 -3
- package/src/sdk/host/query/handlers.ts +155 -2
- package/src/sdk/host/sdk-surface-parity.test.ts +1 -0
- package/src/sdk/host/session-runtime.test.ts +391 -1
- package/src/sdk/host/session-runtime.ts +308 -73
- package/src/sdk/host/surface-policy.ts +3 -0
- package/src/sdk/host/websocket-transport.ts +7 -1
- package/src/sdk/mcp/server.ts +88 -15
- package/src/sdk/prompt-status.ts +8 -0
- package/src/sdk/protocol/operation-inventory.generated.json +62 -0
- package/src/sdk/protocol/operation-registry.ts +3 -2
- package/src/sdk/session.ts +87 -39
- package/src/sdk/transport/index.ts +1 -0
- package/src/sdk/transport/relay.ts +3 -0
- package/src/sdk/transport/serve-cli.ts +111 -24
- package/src/secrets/obfuscator.ts +92 -12
- package/src/session/agent-session.ts +322 -93
- package/src/session/blob-store.ts +60 -8
- package/src/session/fallback-chain-controller.ts +35 -0
- package/src/session/internal/managed-session-scope.ts +25 -3
- package/src/session/internal/managed-session-storage.ts +574 -73
- package/src/session/internal/session-memory-sidecar.ts +19 -29
- package/src/session/session-manager.ts +2166 -743
- package/src/session/session-storage.ts +715 -48
- package/src/setup/provider-onboarding.ts +19 -3
- package/src/setup/provider-presets.json +3 -1
- package/src/slash-commands/builtin-registry.ts +85 -3
- package/src/stt/downloader.ts +2 -3
- package/src/stt/setup.ts +29 -4
- package/src/task/executor.ts +22 -18
- package/src/task/index.ts +24 -1
- package/src/tools/archive-reader.ts +11 -2
- package/src/tools/browser/runtime-diagnostics.ts +249 -0
- package/src/tools/browser/tab-protocol.ts +4 -0
- package/src/tools/browser/tab-supervisor.ts +5 -0
- package/src/tools/browser/tab-worker.ts +36 -1
- package/src/tools/browser.ts +7 -0
- package/src/tools/image-gen.ts +110 -166
- package/src/tools/index.ts +2 -0
- package/src/tools/read.ts +1 -1
- package/src/tools/resource-gc.ts +6 -1
- package/src/tools/tool-catalog.generated.ts +5 -1
- package/src/utils/pasted-image-path.ts +93 -0
- package/src/web/search/index.ts +3 -3
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
2
|
import { ThinkingLevel } from "@gajae-code/agent-core";
|
|
3
|
+
import type { Api, Model } from "@gajae-code/ai/core";
|
|
3
4
|
import { getOAuthProviders } from "@gajae-code/ai/utils/oauth";
|
|
4
5
|
import type { OAuthProvider } from "@gajae-code/ai/utils/oauth/types";
|
|
5
6
|
import type { Component, OverlayHandle, SlashCommand } from "@gajae-code/tui";
|
|
@@ -20,6 +21,7 @@ import { formatModelSelectorValue } from "../../config/model-resolver";
|
|
|
20
21
|
import { selectorHead } from "../../config/model-selector-value";
|
|
21
22
|
import type { ModelProfileConfig } from "../../config/models-config-schema";
|
|
22
23
|
import { type Settings, type SettingsAtomicReceipt, settings } from "../../config/settings";
|
|
24
|
+
import type { SettingValue } from "../../config/settings-schema";
|
|
23
25
|
import { DebugSelectorComponent } from "../../debug";
|
|
24
26
|
import { disableProvider, enableProvider } from "../../discovery";
|
|
25
27
|
import { clearPluginRootsAndCaches, resolveActiveProjectRegistryPath } from "../../discovery/helpers";
|
|
@@ -50,6 +52,7 @@ import {
|
|
|
50
52
|
stopInteractiveActivityIndicator,
|
|
51
53
|
suspendInteractiveActivityIndicator,
|
|
52
54
|
} from "../../modes/types";
|
|
55
|
+
import { configureSttFromSettings } from "../../runtime/stt-settings-setup";
|
|
53
56
|
import { ChatDaemonController } from "../../sdk/bus/chat-daemon-control";
|
|
54
57
|
import {
|
|
55
58
|
getCurrentTelegramActivationMarker,
|
|
@@ -91,6 +94,7 @@ import {
|
|
|
91
94
|
} from "../../sdk/bus/telegram-daemon";
|
|
92
95
|
import { TelegramDaemonController } from "../../sdk/bus/telegram-daemon-control";
|
|
93
96
|
import { runTelegramSetup, type TelegramSetupPreflight } from "../../sdk/bus/telegram-setup";
|
|
97
|
+
import type { DefaultFallbackRuntimeState } from "../../session/agent-session";
|
|
94
98
|
import { type SessionInfo, SessionManager } from "../../session/session-manager";
|
|
95
99
|
import { getTreeForInternalRead } from "../../session/session-manager-internal";
|
|
96
100
|
|
|
@@ -123,11 +127,8 @@ import {
|
|
|
123
127
|
} from "../../setup/model-onboarding-guidance";
|
|
124
128
|
import { addApiCompatibleProvider, formatProviderSetupResult } from "../../setup/provider-onboarding";
|
|
125
129
|
import {
|
|
126
|
-
IMAGE_PROVIDER_DEFAULTS,
|
|
127
130
|
isConfigurableSearchProviderId,
|
|
128
131
|
isSearchProviderPreference,
|
|
129
|
-
setConfiguredImageModel,
|
|
130
|
-
setPreferredImageProvider,
|
|
131
132
|
setPreferredSearchProvider,
|
|
132
133
|
setSearchFallbackProviders,
|
|
133
134
|
setSearchHardTimeoutMs,
|
|
@@ -171,6 +172,8 @@ import {
|
|
|
171
172
|
type ProviderOnboardingAction,
|
|
172
173
|
ProviderOnboardingSelectorComponent,
|
|
173
174
|
} from "../components/provider-onboarding-selector";
|
|
175
|
+
import { ProviderOrderContext } from "../components/provider-order-context";
|
|
176
|
+
import { ProviderOrderEditorComponent } from "../components/provider-order-editor";
|
|
174
177
|
import { SessionObserverOverlayComponent } from "../components/session-observer-overlay";
|
|
175
178
|
import { SessionSelectorComponent } from "../components/session-selector";
|
|
176
179
|
import { dashboardSessions, SessionsDashboardComponent } from "../components/sessions-dashboard";
|
|
@@ -1195,6 +1198,21 @@ export function createNotificationsEditorOperations(
|
|
|
1195
1198
|
};
|
|
1196
1199
|
}
|
|
1197
1200
|
|
|
1201
|
+
interface DefaultAssignmentRollbackSnapshot {
|
|
1202
|
+
model: Model<Api> | undefined;
|
|
1203
|
+
thinkingLevel: ThinkingLevel | undefined;
|
|
1204
|
+
persistedModelRoles: SettingValue<"modelRoles"> | undefined;
|
|
1205
|
+
persistedAgentOverrides: SettingValue<"task.agentModelOverrides"> | undefined;
|
|
1206
|
+
persistedProfile: SettingValue<"modelProfile.default"> | undefined;
|
|
1207
|
+
modelRolesOverride: SettingValue<"modelRoles"> | undefined;
|
|
1208
|
+
agentOverridesOverride: SettingValue<"task.agentModelOverrides"> | undefined;
|
|
1209
|
+
profileOverride: SettingValue<"modelProfile.default"> | undefined;
|
|
1210
|
+
chain: { entries: readonly string[]; origin: string; identity?: string; explicitHead?: boolean } | undefined;
|
|
1211
|
+
activeProfile: string | undefined;
|
|
1212
|
+
canonicalVariant: string | undefined;
|
|
1213
|
+
resumeDefaultSelector: string | undefined;
|
|
1214
|
+
fallbackRuntimeState: DefaultFallbackRuntimeState;
|
|
1215
|
+
}
|
|
1198
1216
|
export class SelectorController {
|
|
1199
1217
|
#transcriptViewerOpen = false;
|
|
1200
1218
|
#transcriptViewer?: TranscriptViewerOverlay;
|
|
@@ -1213,6 +1231,113 @@ export class SelectorController {
|
|
|
1213
1231
|
this.#credentialAutoImportStateStore = credentialAutoImportStateStore;
|
|
1214
1232
|
}
|
|
1215
1233
|
|
|
1234
|
+
#captureDefaultAssignmentRollback(): DefaultAssignmentRollbackSnapshot {
|
|
1235
|
+
return {
|
|
1236
|
+
model: this.ctx.session.model,
|
|
1237
|
+
thinkingLevel: this.ctx.session.thinkingLevel,
|
|
1238
|
+
persistedModelRoles: this.ctx.settings.getGlobal("modelRoles"),
|
|
1239
|
+
persistedAgentOverrides: this.ctx.settings.getGlobal("task.agentModelOverrides"),
|
|
1240
|
+
persistedProfile: this.ctx.settings.getGlobal("modelProfile.default"),
|
|
1241
|
+
modelRolesOverride: this.ctx.settings.getOverride("modelRoles"),
|
|
1242
|
+
agentOverridesOverride: this.ctx.settings.getOverride("task.agentModelOverrides"),
|
|
1243
|
+
profileOverride: this.ctx.settings.getOverride("modelProfile.default"),
|
|
1244
|
+
chain: this.ctx.session.getConfiguredModelChainState("default"),
|
|
1245
|
+
activeProfile: this.ctx.session.getActiveModelProfile?.(),
|
|
1246
|
+
canonicalVariant: this.ctx.session.modelRegistry.getSessionCanonicalVariant?.(this.ctx.session.sessionId),
|
|
1247
|
+
resumeDefaultSelector: this.ctx.session.sessionManager.buildSessionContext().models.default,
|
|
1248
|
+
fallbackRuntimeState: this.ctx.session.getDefaultFallbackRuntimeState(),
|
|
1249
|
+
};
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
async #restoreDefaultAssignmentRollback(
|
|
1253
|
+
snapshot: DefaultAssignmentRollbackSnapshot,
|
|
1254
|
+
error: unknown,
|
|
1255
|
+
restoreLiveModel: boolean = true,
|
|
1256
|
+
restoreProfileState: boolean = true,
|
|
1257
|
+
): Promise<never> {
|
|
1258
|
+
if (!restoreLiveModel && !restoreProfileState) throw error;
|
|
1259
|
+
const rollbackErrors: unknown[] = [];
|
|
1260
|
+
const restore = (action: () => void): void => {
|
|
1261
|
+
try {
|
|
1262
|
+
action();
|
|
1263
|
+
} catch (rollbackError) {
|
|
1264
|
+
rollbackErrors.push(rollbackError);
|
|
1265
|
+
}
|
|
1266
|
+
};
|
|
1267
|
+
restore(() =>
|
|
1268
|
+
snapshot.persistedModelRoles === undefined
|
|
1269
|
+
? this.ctx.settings.unset("modelRoles")
|
|
1270
|
+
: this.ctx.settings.set("modelRoles", snapshot.persistedModelRoles),
|
|
1271
|
+
);
|
|
1272
|
+
restore(() =>
|
|
1273
|
+
snapshot.persistedAgentOverrides === undefined
|
|
1274
|
+
? this.ctx.settings.unset("task.agentModelOverrides")
|
|
1275
|
+
: this.ctx.settings.set("task.agentModelOverrides", snapshot.persistedAgentOverrides),
|
|
1276
|
+
);
|
|
1277
|
+
restore(() =>
|
|
1278
|
+
snapshot.persistedProfile === undefined
|
|
1279
|
+
? this.ctx.settings.unset("modelProfile.default")
|
|
1280
|
+
: this.ctx.settings.set("modelProfile.default", snapshot.persistedProfile),
|
|
1281
|
+
);
|
|
1282
|
+
restore(() =>
|
|
1283
|
+
snapshot.modelRolesOverride === undefined
|
|
1284
|
+
? this.ctx.settings.clearOverride("modelRoles")
|
|
1285
|
+
: this.ctx.settings.override("modelRoles", snapshot.modelRolesOverride),
|
|
1286
|
+
);
|
|
1287
|
+
restore(() =>
|
|
1288
|
+
snapshot.agentOverridesOverride === undefined
|
|
1289
|
+
? this.ctx.settings.clearOverride("task.agentModelOverrides")
|
|
1290
|
+
: this.ctx.settings.override("task.agentModelOverrides", snapshot.agentOverridesOverride),
|
|
1291
|
+
);
|
|
1292
|
+
restore(() =>
|
|
1293
|
+
snapshot.profileOverride === undefined
|
|
1294
|
+
? this.ctx.settings.clearOverride("modelProfile.default")
|
|
1295
|
+
: this.ctx.settings.override("modelProfile.default", snapshot.profileOverride),
|
|
1296
|
+
);
|
|
1297
|
+
if (restoreProfileState) {
|
|
1298
|
+
restore(() =>
|
|
1299
|
+
this.ctx.session.setConfiguredModelChain(
|
|
1300
|
+
"default",
|
|
1301
|
+
snapshot.chain?.entries ?? [],
|
|
1302
|
+
snapshot.chain?.origin ?? "rollback",
|
|
1303
|
+
snapshot.chain?.identity,
|
|
1304
|
+
snapshot.chain?.explicitHead ?? true,
|
|
1305
|
+
),
|
|
1306
|
+
);
|
|
1307
|
+
restore(() => this.ctx.session.restoreDefaultFallbackRuntimeState(snapshot.fallbackRuntimeState));
|
|
1308
|
+
restore(() => {
|
|
1309
|
+
if (snapshot.canonicalVariant) {
|
|
1310
|
+
this.ctx.session.modelRegistry.restoreSessionCanonicalVariant?.(
|
|
1311
|
+
this.ctx.session.sessionId,
|
|
1312
|
+
snapshot.canonicalVariant,
|
|
1313
|
+
);
|
|
1314
|
+
} else {
|
|
1315
|
+
this.ctx.session.modelRegistry.clearCanonicalVariant?.(this.ctx.session.sessionId);
|
|
1316
|
+
}
|
|
1317
|
+
});
|
|
1318
|
+
}
|
|
1319
|
+
if (restoreLiveModel) {
|
|
1320
|
+
restore(() => this.ctx.session.recordResumeDefaultModel(snapshot.resumeDefaultSelector));
|
|
1321
|
+
}
|
|
1322
|
+
restore(() => this.ctx.session.setActiveModelProfile?.(snapshot.activeProfile));
|
|
1323
|
+
try {
|
|
1324
|
+
await this.ctx.settings.flushOrThrow();
|
|
1325
|
+
} catch (rollbackError) {
|
|
1326
|
+
rollbackErrors.push(rollbackError);
|
|
1327
|
+
}
|
|
1328
|
+
if (restoreLiveModel) {
|
|
1329
|
+
try {
|
|
1330
|
+
await this.ctx.session.restoreModelSelectionForRollback(snapshot.model, snapshot.thinkingLevel);
|
|
1331
|
+
} catch (rollbackError) {
|
|
1332
|
+
rollbackErrors.push(rollbackError);
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
if (rollbackErrors.length > 0) {
|
|
1336
|
+
throw new AggregateError([error, ...rollbackErrors], "Model assignment failed and rollback was incomplete");
|
|
1337
|
+
}
|
|
1338
|
+
throw error;
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1216
1341
|
isTranscriptViewerOpen(): boolean {
|
|
1217
1342
|
return this.#transcriptViewerOpen;
|
|
1218
1343
|
}
|
|
@@ -1226,7 +1351,7 @@ export class SelectorController {
|
|
|
1226
1351
|
await Promise.all(
|
|
1227
1352
|
oauthProviders.map(provider =>
|
|
1228
1353
|
this.ctx.session.modelRegistry
|
|
1229
|
-
.getApiKeyForProvider(provider.id, this.ctx.session.
|
|
1354
|
+
.getApiKeyForProvider(provider.id, this.ctx.session.credentialSessionId)
|
|
1230
1355
|
.catch(() => undefined),
|
|
1231
1356
|
),
|
|
1232
1357
|
);
|
|
@@ -1535,81 +1660,6 @@ export class SelectorController {
|
|
|
1535
1660
|
}
|
|
1536
1661
|
}
|
|
1537
1662
|
|
|
1538
|
-
async #handleImageGenerationConfig(): Promise<void> {
|
|
1539
|
-
const provider = await this.ctx.showHookInput(
|
|
1540
|
-
"Image Generation provider (auto, openai, gemini, openrouter, antigravity, alibaba, custom)",
|
|
1541
|
-
"auto",
|
|
1542
|
-
);
|
|
1543
|
-
if (provider === undefined) return;
|
|
1544
|
-
const normalized = provider.trim().toLowerCase();
|
|
1545
|
-
const validProviders = ["auto", "openai", "gemini", "openrouter", "antigravity", "alibaba", "custom"];
|
|
1546
|
-
if (!validProviders.includes(normalized)) {
|
|
1547
|
-
this.ctx.showStatus(`Invalid image provider: ${normalized}. Valid: ${validProviders.join(", ")}`);
|
|
1548
|
-
return;
|
|
1549
|
-
}
|
|
1550
|
-
let model: string | undefined;
|
|
1551
|
-
if (normalized !== "auto" && normalized !== "custom") {
|
|
1552
|
-
const defaultModel = IMAGE_PROVIDER_DEFAULTS[normalized];
|
|
1553
|
-
model = await this.ctx.showHookInput(`Image model for ${normalized} (default: ${defaultModel})`, defaultModel);
|
|
1554
|
-
if (model === undefined) return;
|
|
1555
|
-
model = model.trim() || defaultModel;
|
|
1556
|
-
}
|
|
1557
|
-
let customUrl: string | undefined;
|
|
1558
|
-
let customKey: string | undefined;
|
|
1559
|
-
if (normalized === "custom") {
|
|
1560
|
-
customUrl = await this.ctx.showHookInput("Custom image endpoint base URL");
|
|
1561
|
-
if (!customUrl?.trim()) {
|
|
1562
|
-
this.ctx.showStatus("Custom image endpoint requires a base URL");
|
|
1563
|
-
return;
|
|
1564
|
-
}
|
|
1565
|
-
model = await this.ctx.showHookInput("Custom image model", IMAGE_PROVIDER_DEFAULTS.openai);
|
|
1566
|
-
if (model === undefined) return;
|
|
1567
|
-
model = model.trim() || IMAGE_PROVIDER_DEFAULTS.openai;
|
|
1568
|
-
customKey = await this.ctx.showHookInput("Custom image endpoint API key");
|
|
1569
|
-
}
|
|
1570
|
-
const scope = await this.ctx.showHookInput(
|
|
1571
|
-
"Scope: 'session' (this session only) or 'default' (persist)",
|
|
1572
|
-
"session",
|
|
1573
|
-
);
|
|
1574
|
-
if (scope === undefined) return;
|
|
1575
|
-
const persistDefault = scope.trim().toLowerCase() === "default";
|
|
1576
|
-
if (persistDefault && !this.ctx.settings.canWriteDurableConfig()) {
|
|
1577
|
-
this.ctx.showError(
|
|
1578
|
-
"Cannot change settings while config.yml has invalid YAML syntax. Repair config.yml and reload settings.",
|
|
1579
|
-
);
|
|
1580
|
-
return;
|
|
1581
|
-
}
|
|
1582
|
-
|
|
1583
|
-
const imageProvider = normalized as
|
|
1584
|
-
| "auto"
|
|
1585
|
-
| "openai"
|
|
1586
|
-
| "gemini"
|
|
1587
|
-
| "openrouter"
|
|
1588
|
-
| "antigravity"
|
|
1589
|
-
| "alibaba"
|
|
1590
|
-
| "custom";
|
|
1591
|
-
setPreferredImageProvider(imageProvider === "custom" ? "auto" : imageProvider);
|
|
1592
|
-
setConfiguredImageModel({
|
|
1593
|
-
provider: imageProvider,
|
|
1594
|
-
model: model ?? null,
|
|
1595
|
-
customUrl: customUrl?.trim(),
|
|
1596
|
-
customKey: customKey?.trim(),
|
|
1597
|
-
});
|
|
1598
|
-
|
|
1599
|
-
if (persistDefault) {
|
|
1600
|
-
this.ctx.settings.set("providers.image", imageProvider);
|
|
1601
|
-
if (model) this.ctx.settings.set("providers.imageModel", model);
|
|
1602
|
-
if (customUrl?.trim()) this.ctx.settings.set("providers.imageCustomUrl", customUrl.trim());
|
|
1603
|
-
if (customKey?.trim()) this.ctx.settings.set("providers.imageCustomKey", customKey.trim());
|
|
1604
|
-
}
|
|
1605
|
-
|
|
1606
|
-
const displayModel =
|
|
1607
|
-
model ?? (normalized !== "auto" && normalized !== "custom" ? IMAGE_PROVIDER_DEFAULTS[normalized] : undefined);
|
|
1608
|
-
const label = normalized === "auto" ? "Auto" : `${normalized}${displayModel ? ` (${displayModel})` : ""}`;
|
|
1609
|
-
this.ctx.showStatus(`Image Generation: ${label}${persistDefault ? " (default)" : " (session)"}`);
|
|
1610
|
-
this.ctx.ui.requestRender();
|
|
1611
|
-
}
|
|
1612
|
-
|
|
1613
1663
|
showCustomProviderWizard(): void {
|
|
1614
1664
|
this.showSelector(done => {
|
|
1615
1665
|
let wizard: CustomProviderWizardComponent;
|
|
@@ -1745,6 +1795,40 @@ export class SelectorController {
|
|
|
1745
1795
|
this.ctx.ui.requestRender();
|
|
1746
1796
|
},
|
|
1747
1797
|
onRenderRequested: () => this.ctx.ui.requestRender(),
|
|
1798
|
+
createProviderOrderEditor: closeEditor => {
|
|
1799
|
+
// The editor owns the context lifecycle: dispose() on
|
|
1800
|
+
// close or external teardown releases the subscriptions,
|
|
1801
|
+
// so the controller only wires change repaints here.
|
|
1802
|
+
let editor: ProviderOrderEditorComponent | undefined;
|
|
1803
|
+
const context = new ProviderOrderContext(
|
|
1804
|
+
this.ctx.session.modelRegistry,
|
|
1805
|
+
this.ctx.settings,
|
|
1806
|
+
() => {
|
|
1807
|
+
editor?.refresh();
|
|
1808
|
+
this.ctx.ui.requestRender();
|
|
1809
|
+
},
|
|
1810
|
+
this.ctx.session.credentialSessionId,
|
|
1811
|
+
);
|
|
1812
|
+
try {
|
|
1813
|
+
editor = new ProviderOrderEditorComponent(
|
|
1814
|
+
context,
|
|
1815
|
+
() => {
|
|
1816
|
+
closeEditor();
|
|
1817
|
+
this.ctx.ui.requestRender();
|
|
1818
|
+
},
|
|
1819
|
+
message => this.ctx.showError(message),
|
|
1820
|
+
);
|
|
1821
|
+
} catch (error) {
|
|
1822
|
+
// The context subscribed to settings/auth in its constructor.
|
|
1823
|
+
// If editor construction fails the editor disposes it before
|
|
1824
|
+
// rethrowing (initial rebuild failure); dispose again here so
|
|
1825
|
+
// failures before that point (e.g. UI setup) can't leak the
|
|
1826
|
+
// subscriptions this closure created.
|
|
1827
|
+
context.dispose();
|
|
1828
|
+
throw error;
|
|
1829
|
+
}
|
|
1830
|
+
return editor;
|
|
1831
|
+
},
|
|
1748
1832
|
onCancel: () => {
|
|
1749
1833
|
done();
|
|
1750
1834
|
// Restore status line to saved settings
|
|
@@ -1965,6 +2049,18 @@ export class SelectorController {
|
|
|
1965
2049
|
this.ctx.editor.setAutocompleteMaxVisible(typeof value === "number" ? value : Number(value));
|
|
1966
2050
|
break;
|
|
1967
2051
|
|
|
2052
|
+
case "stt.enabled":
|
|
2053
|
+
if (value === true) {
|
|
2054
|
+
void configureSttFromSettings({
|
|
2055
|
+
modelName: settings.get("stt.modelName"),
|
|
2056
|
+
setEnabled: enabled => settings.set("stt.enabled", enabled),
|
|
2057
|
+
flush: () => settings.flushOrThrow(),
|
|
2058
|
+
showStatus: message => this.ctx.showStatus(message),
|
|
2059
|
+
showError: message => this.ctx.showError(message),
|
|
2060
|
+
});
|
|
2061
|
+
}
|
|
2062
|
+
break;
|
|
2063
|
+
|
|
1968
2064
|
// Settings with UI side effects
|
|
1969
2065
|
case "showImages":
|
|
1970
2066
|
for (const child of this.ctx.chatContainer.children) {
|
|
@@ -2101,37 +2197,6 @@ export class SelectorController {
|
|
|
2101
2197
|
setSearchHardTimeoutMs(value * 1000);
|
|
2102
2198
|
}
|
|
2103
2199
|
break;
|
|
2104
|
-
case "providers.image":
|
|
2105
|
-
case "providers.imageModel":
|
|
2106
|
-
case "providers.imageCustomUrl":
|
|
2107
|
-
case "providers.imageCustomKey":
|
|
2108
|
-
case "providers.imageCustomKeyEnv": {
|
|
2109
|
-
const imgProvider = this.ctx.settings.get("providers.image");
|
|
2110
|
-
const imgModel = this.ctx.settings.get("providers.imageModel");
|
|
2111
|
-
const imgCustomUrl = this.ctx.settings.get("providers.imageCustomUrl");
|
|
2112
|
-
const imgCustomKey = this.ctx.settings.get("providers.imageCustomKey");
|
|
2113
|
-
const imgCustomKeyEnv = this.ctx.settings.get("providers.imageCustomKeyEnv");
|
|
2114
|
-
if (
|
|
2115
|
-
imgProvider === "auto" ||
|
|
2116
|
-
imgProvider === "openai" ||
|
|
2117
|
-
imgProvider === "gemini" ||
|
|
2118
|
-
imgProvider === "openrouter" ||
|
|
2119
|
-
imgProvider === "antigravity" ||
|
|
2120
|
-
imgProvider === "alibaba" ||
|
|
2121
|
-
imgProvider === "custom"
|
|
2122
|
-
) {
|
|
2123
|
-
setPreferredImageProvider(imgProvider === "custom" ? "auto" : imgProvider);
|
|
2124
|
-
setConfiguredImageModel({
|
|
2125
|
-
provider: imgProvider,
|
|
2126
|
-
model: imgModel ?? null,
|
|
2127
|
-
customUrl: imgCustomUrl,
|
|
2128
|
-
customKey: imgCustomKey,
|
|
2129
|
-
customKeyEnv: imgCustomKeyEnv,
|
|
2130
|
-
});
|
|
2131
|
-
}
|
|
2132
|
-
break;
|
|
2133
|
-
}
|
|
2134
|
-
|
|
2135
2200
|
// MCP update injection - live subscribe/unsubscribe
|
|
2136
2201
|
case "mcp.notifications":
|
|
2137
2202
|
this.ctx.mcpManager?.setNotificationsEnabled(value as boolean);
|
|
@@ -2199,11 +2264,6 @@ export class SelectorController {
|
|
|
2199
2264
|
await this.#deleteCustomModelPreset(selection.profileName, modelSelector);
|
|
2200
2265
|
return;
|
|
2201
2266
|
}
|
|
2202
|
-
if (selection.kind === "imageGeneration") {
|
|
2203
|
-
done();
|
|
2204
|
-
await this.#handleImageGenerationConfig();
|
|
2205
|
-
return;
|
|
2206
|
-
}
|
|
2207
2267
|
if (selection.kind === "profile") {
|
|
2208
2268
|
await this.#applyModelProfile(selection.profileName, selection.setDefault);
|
|
2209
2269
|
done();
|
|
@@ -2232,12 +2292,19 @@ export class SelectorController {
|
|
|
2232
2292
|
if (includesRoleAgent) {
|
|
2233
2293
|
const apiKey = await this.ctx.session.modelRegistry.getApiKey(
|
|
2234
2294
|
model,
|
|
2235
|
-
this.ctx.session.
|
|
2295
|
+
this.ctx.session.credentialSessionId,
|
|
2236
2296
|
);
|
|
2237
2297
|
if (!apiKey) {
|
|
2238
2298
|
throw new Error(`No API key for ${model.provider}/${model.id}`);
|
|
2239
2299
|
}
|
|
2240
2300
|
}
|
|
2301
|
+
if (includesDefault && !includesRoleAgent) {
|
|
2302
|
+
const apiKey = await this.ctx.session.modelRegistry.getApiKey(
|
|
2303
|
+
model,
|
|
2304
|
+
this.ctx.session.credentialSessionId,
|
|
2305
|
+
);
|
|
2306
|
+
if (!apiKey) throw new Error(`No API key for ${model.provider}/${model.id}`);
|
|
2307
|
+
}
|
|
2241
2308
|
const value =
|
|
2242
2309
|
selectedSelector ?? formatModelSelectorValue(`${model.provider}/${model.id}`, thinkingLevel);
|
|
2243
2310
|
const assignments = new Map<GjcModelAssignmentTargetId, string>();
|
|
@@ -2247,30 +2314,47 @@ export class SelectorController {
|
|
|
2247
2314
|
? selectedSelector.slice(0, -thinkingLevel.length - 1)
|
|
2248
2315
|
: selectedSelector;
|
|
2249
2316
|
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2317
|
+
const rollbackSnapshot = this.#captureDefaultAssignmentRollback();
|
|
2318
|
+
let defaultMutationStarted = false;
|
|
2319
|
+
let assignmentMutationStarted = false;
|
|
2320
|
+
let materializedProfile = false;
|
|
2321
|
+
try {
|
|
2322
|
+
if (includesDefault) {
|
|
2323
|
+
await this.ctx.session.setModel(model, "default", {
|
|
2324
|
+
selector: defaultSelector,
|
|
2325
|
+
thinkingLevel,
|
|
2326
|
+
cause: "user-selection",
|
|
2327
|
+
onMutationStarted: () => {
|
|
2328
|
+
defaultMutationStarted = true;
|
|
2329
|
+
},
|
|
2330
|
+
});
|
|
2331
|
+
if (thinkingLevel && thinkingLevel !== ThinkingLevel.Inherit) {
|
|
2332
|
+
this.ctx.session.setThinkingLevel(thinkingLevel);
|
|
2333
|
+
}
|
|
2258
2334
|
}
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2335
|
+
assignmentMutationStarted = true;
|
|
2336
|
+
materializedProfile = materializeActiveModelProfileAssignments({
|
|
2337
|
+
session: this.ctx.session,
|
|
2338
|
+
settings: this.ctx.settings,
|
|
2339
|
+
assignments,
|
|
2340
|
+
});
|
|
2341
|
+
if (!materializedProfile) {
|
|
2342
|
+
for (const targetRole of targetRoles) {
|
|
2343
|
+
const target = GJC_MODEL_ASSIGNMENT_TARGETS[targetRole];
|
|
2344
|
+
if (target.settingsPath === "modelRoles") {
|
|
2345
|
+
this.ctx.settings.setModelRole(targetRole, value);
|
|
2346
|
+
} else {
|
|
2347
|
+
this.ctx.settings.setAgentModelOverride(targetRole, value);
|
|
2348
|
+
}
|
|
2272
2349
|
}
|
|
2273
2350
|
}
|
|
2351
|
+
} catch (error) {
|
|
2352
|
+
await this.#restoreDefaultAssignmentRollback(
|
|
2353
|
+
rollbackSnapshot,
|
|
2354
|
+
error,
|
|
2355
|
+
defaultMutationStarted,
|
|
2356
|
+
defaultMutationStarted || assignmentMutationStarted,
|
|
2357
|
+
);
|
|
2274
2358
|
}
|
|
2275
2359
|
modelSelector.refreshRoleAssignments({
|
|
2276
2360
|
currentModel: this.ctx.session.model,
|
|
@@ -2294,27 +2378,47 @@ export class SelectorController {
|
|
|
2294
2378
|
this.ctx.ui.requestRender();
|
|
2295
2379
|
} else if (role === "default") {
|
|
2296
2380
|
// Default: update agent state and persist as the active default model.
|
|
2297
|
-
await this.ctx.session.
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
});
|
|
2381
|
+
const apiKey = await this.ctx.session.modelRegistry.getApiKey(
|
|
2382
|
+
model,
|
|
2383
|
+
this.ctx.session.credentialSessionId,
|
|
2384
|
+
);
|
|
2385
|
+
if (!apiKey) throw new Error(`No API key for ${model.provider}/${model.id}`);
|
|
2386
|
+
const rollbackSnapshot = this.#captureDefaultAssignmentRollback();
|
|
2387
|
+
let defaultMutationStarted = false;
|
|
2388
|
+
let assignmentMutationStarted = false;
|
|
2302
2389
|
const value = formatModelSelectorValue(
|
|
2303
2390
|
selectedSelector ?? `${model.provider}/${model.id}`,
|
|
2304
2391
|
thinkingLevel,
|
|
2305
2392
|
);
|
|
2306
|
-
|
|
2307
|
-
|
|
2393
|
+
try {
|
|
2394
|
+
await this.ctx.session.setModel(model, role, {
|
|
2395
|
+
selector: selectedSelector,
|
|
2396
|
+
thinkingLevel,
|
|
2397
|
+
cause: "user-selection",
|
|
2398
|
+
onMutationStarted: () => {
|
|
2399
|
+
defaultMutationStarted = true;
|
|
2400
|
+
},
|
|
2401
|
+
});
|
|
2402
|
+
assignmentMutationStarted = true;
|
|
2403
|
+
const materializedProfile = materializeActiveModelProfileAssignment({
|
|
2308
2404
|
session: this.ctx.session,
|
|
2309
2405
|
settings: this.ctx.settings,
|
|
2310
2406
|
role,
|
|
2311
2407
|
selector: value,
|
|
2312
|
-
})
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2408
|
+
});
|
|
2409
|
+
if (!materializedProfile) {
|
|
2410
|
+
this.ctx.settings.setModelRole(role, value);
|
|
2411
|
+
}
|
|
2412
|
+
if (thinkingLevel && thinkingLevel !== ThinkingLevel.Inherit) {
|
|
2413
|
+
this.ctx.session.setThinkingLevel(thinkingLevel);
|
|
2414
|
+
}
|
|
2415
|
+
} catch (error) {
|
|
2416
|
+
await this.#restoreDefaultAssignmentRollback(
|
|
2417
|
+
rollbackSnapshot,
|
|
2418
|
+
error,
|
|
2419
|
+
defaultMutationStarted,
|
|
2420
|
+
defaultMutationStarted || assignmentMutationStarted,
|
|
2421
|
+
);
|
|
2318
2422
|
}
|
|
2319
2423
|
refreshRoleAssignments();
|
|
2320
2424
|
this.ctx.statusLine.invalidate();
|
|
@@ -2322,7 +2426,10 @@ export class SelectorController {
|
|
|
2322
2426
|
this.ctx.showStatus(`Default model: ${selectedSelector ?? model.id}`);
|
|
2323
2427
|
this.ctx.ui.requestRender();
|
|
2324
2428
|
} else {
|
|
2325
|
-
const apiKey = await this.ctx.session.modelRegistry.getApiKey(
|
|
2429
|
+
const apiKey = await this.ctx.session.modelRegistry.getApiKey(
|
|
2430
|
+
model,
|
|
2431
|
+
this.ctx.session.credentialSessionId,
|
|
2432
|
+
);
|
|
2326
2433
|
if (!apiKey) {
|
|
2327
2434
|
throw new Error(`No API key for ${model.provider}/${model.id}`);
|
|
2328
2435
|
}
|
|
@@ -2365,7 +2472,7 @@ export class SelectorController {
|
|
|
2365
2472
|
},
|
|
2366
2473
|
{
|
|
2367
2474
|
...options,
|
|
2368
|
-
sessionId: this.ctx.session.
|
|
2475
|
+
sessionId: this.ctx.session.credentialSessionId,
|
|
2369
2476
|
currentThinkingLevel: this.ctx.session.thinkingLevel,
|
|
2370
2477
|
activeModelProfile:
|
|
2371
2478
|
this.ctx.session.getActiveModelProfile?.() ?? this.ctx.settings.get("modelProfile.default"),
|
|
@@ -3234,7 +3341,7 @@ export class SelectorController {
|
|
|
3234
3341
|
validateAuth: async (selectedProviderId: string) => {
|
|
3235
3342
|
const apiKey = await this.ctx.session.modelRegistry.getApiKeyForProvider(
|
|
3236
3343
|
selectedProviderId,
|
|
3237
|
-
this.ctx.session.
|
|
3344
|
+
this.ctx.session.credentialSessionId,
|
|
3238
3345
|
);
|
|
3239
3346
|
return !!apiKey;
|
|
3240
3347
|
},
|
|
@@ -62,7 +62,7 @@ export class PromptSuggestionController {
|
|
|
62
62
|
this.#ctx.session.messages,
|
|
63
63
|
this.#ctx.session.modelRegistry,
|
|
64
64
|
this.#ctx.settings,
|
|
65
|
-
this.#ctx.session.
|
|
65
|
+
this.#ctx.session.credentialSessionId,
|
|
66
66
|
this.#ctx.session.model,
|
|
67
67
|
provider => this.#ctx.session.agent.metadataForProvider(provider),
|
|
68
68
|
)
|
|
@@ -99,6 +99,7 @@ export async function initializeExtensions(session: AgentSession, options: Initi
|
|
|
99
99
|
// ExtensionContextActions
|
|
100
100
|
{
|
|
101
101
|
getModel: () => session.model,
|
|
102
|
+
getCredentialSessionId: () => session.credentialSessionId,
|
|
102
103
|
isIdle: () => !session.isStreaming,
|
|
103
104
|
getActivePromptHandle: () => session.activePromptHandle,
|
|
104
105
|
abort: () => session.abort(),
|
|
@@ -368,6 +368,7 @@ export function trimChatChildren(ctx: InteractiveModeContext): void {
|
|
|
368
368
|
}
|
|
369
369
|
|
|
370
370
|
export class UiHelpers {
|
|
371
|
+
#compactionFlushRetryScheduled = false;
|
|
371
372
|
#renderedIrcInlineComponents = new Map<string, readonly Component[]>();
|
|
372
373
|
#viewportAnchorOccurrences = new WeakMap<object, { base: string; epoch: number; id: string }>();
|
|
373
374
|
#nextViewportAnchorOccurrence = new Map<string, number>();
|
|
@@ -1217,6 +1218,23 @@ export class UiHelpers {
|
|
|
1217
1218
|
}
|
|
1218
1219
|
|
|
1219
1220
|
async flushCompactionQueue(options?: { willRetry?: boolean }): Promise<void> {
|
|
1221
|
+
if (this.ctx.session.isCompacting || this.ctx.session.isBashRunning || this.ctx.session.isEvalRunning) {
|
|
1222
|
+
if (!this.#compactionFlushRetryScheduled) {
|
|
1223
|
+
this.#compactionFlushRetryScheduled = true;
|
|
1224
|
+
void (async () => {
|
|
1225
|
+
while (
|
|
1226
|
+
this.ctx.session.isCompacting ||
|
|
1227
|
+
this.ctx.session.isBashRunning ||
|
|
1228
|
+
this.ctx.session.isEvalRunning
|
|
1229
|
+
) {
|
|
1230
|
+
await Bun.sleep(50);
|
|
1231
|
+
}
|
|
1232
|
+
this.#compactionFlushRetryScheduled = false;
|
|
1233
|
+
await this.flushCompactionQueue(options);
|
|
1234
|
+
})();
|
|
1235
|
+
}
|
|
1236
|
+
return;
|
|
1237
|
+
}
|
|
1220
1238
|
if (this.ctx.compactionQueuedMessages.length === 0) {
|
|
1221
1239
|
return;
|
|
1222
1240
|
}
|
|
@@ -11,6 +11,7 @@ Drives a real Chromium tab with full puppeteer access via JS execution.
|
|
|
11
11
|
- Browser kinds: no `app` launches headless Chromium; `app.path` reuses CDP or kills stale same-path processes before spawning — NEVER use it for a daily Chrome profile; use explicit `app.browser: "chrome"` profile mode instead. Saved-profile/CDP automation has access to that profile's cookies and authenticated accounts. Profile mode refuses a matching non-CDP Chrome instead of killing/relaunching it, and `kill: true` can terminate only a Chrome process GJC launched; `app.cdp_url` is externally owned and disconnect-only. CDP must stay on `127.0.0.1`: it grants full browser-account access.
|
|
12
12
|
- Inside `run`, `tab` exposes high-level helpers (`goto`, `observe`, `id`, `click`, `type`, `fill`, `press`, `waitFor`, `screenshot`, `extract`, …); reach for `page` (raw puppeteer Page) when they don't cover it.
|
|
13
13
|
- Selectors accept CSS as well as puppeteer query handlers: `aria/Sign in`, `text/Continue`, `xpath/…`, `pierce/…`.
|
|
14
|
+
- Runtime diagnostics are opt-in: pass `diagnostics: true` to `open` to subscribe the tab to page `Runtime.exceptionThrown` and `console.error` events. The next successful `act`/`run` response then includes at most 20 `runtimeDiagnostics` entries plus `runtimeDiagnosticsDropped`, then drains them. Entries contain only kind, time, origin-only URL, line/column, and a built-in error class from a fixed allowlist — never path segments, query strings, messages, console arguments, values, or stacks. Output is byte-bounded and marks truncation explicitly.
|
|
14
15
|
- Full reference — helpers, browser kinds, CDP/security details, and more examples — read `gjc://tools/browser.md`.
|
|
15
16
|
</instruction>
|
|
16
17
|
|