feat(plan): support automatic model switching for Plan Mode (#20240)

This commit is contained in:
Jerop Kipruto
2026-02-24 19:15:14 -05:00
committed by GitHub
parent 1f9da6723f
commit bf278ef2b0
19 changed files with 422 additions and 31 deletions
@@ -37,6 +37,7 @@ import {
} from '../types.js';
import { HookType } from '../../hooks/types.js';
import { AgentTerminateMode } from '../../agents/types.js';
import { ApprovalMode } from '../../policy/types.js';
import { GIT_COMMIT_INFO, CLI_VERSION } from '../../generated/git-commit.js';
import { UserAccountManager } from '../../utils/userAccountManager.js';
import { InstallationManager } from '../../utils/installationManager.js';
@@ -905,6 +906,7 @@ describe('ClearcutLogger', () => {
'some reasoning',
false,
undefined,
ApprovalMode.DEFAULT,
);
logger?.logModelRoutingEvent(event);
@@ -939,6 +941,7 @@ describe('ClearcutLogger', () => {
'some reasoning',
true,
'Something went wrong',
ApprovalMode.DEFAULT,
);
logger?.logModelRoutingEvent(event);
@@ -977,6 +980,7 @@ describe('ClearcutLogger', () => {
'[Score: 90 / Threshold: 80] reasoning',
false,
undefined,
ApprovalMode.DEFAULT,
true,
'80',
);
@@ -24,6 +24,7 @@ import {
import { OutputFormat } from '../output/types.js';
import { logs } from '@opentelemetry/api-logs';
import type { Config, GeminiCLIExtension } from '../config/config.js';
import { ApprovalMode } from '../policy/types.js';
import {
logApiError,
logApiRequest,
@@ -1856,6 +1857,7 @@ describe('loggers', () => {
'test-reason',
false,
undefined,
ApprovalMode.DEFAULT,
);
logModelRouting(mockConfig, event);
@@ -1890,6 +1892,7 @@ describe('loggers', () => {
'[Score: 90 / Threshold: 80] reasoning',
false,
undefined,
ApprovalMode.DEFAULT,
true,
'80',
);
@@ -1923,6 +1926,7 @@ describe('loggers', () => {
'test-reason',
false,
undefined,
ApprovalMode.DEFAULT,
);
logModelRouting(mockConfig, event);
@@ -27,6 +27,7 @@ import {
TokenStorageInitializationEvent,
} from './types.js';
import { AgentTerminateMode } from '../agents/types.js';
import { ApprovalMode } from '../policy/types.js';
const mockCounterAddFn: Mock<
(value: number, attributes?: Attributes, context?: Context) => void
@@ -490,6 +491,7 @@ describe('Telemetry Metrics', () => {
'test-reason',
false,
undefined,
ApprovalMode.DEFAULT,
);
recordModelRoutingMetricsModule(mockConfig, event);
expect(mockHistogramRecordFn).not.toHaveBeenCalled();
@@ -505,6 +507,7 @@ describe('Telemetry Metrics', () => {
'test-reason',
false,
undefined,
ApprovalMode.DEFAULT,
);
recordModelRoutingMetricsModule(mockConfig, event);
@@ -516,6 +519,7 @@ describe('Telemetry Metrics', () => {
'routing.decision_source': 'default',
'routing.failed': false,
'routing.reasoning': 'test-reason',
'routing.approval_mode': ApprovalMode.DEFAULT,
});
// The session counter is called once on init
expect(mockCounterAddFn).toHaveBeenCalledTimes(1);
@@ -530,6 +534,7 @@ describe('Telemetry Metrics', () => {
'test-reason',
true,
'test-error',
ApprovalMode.DEFAULT,
);
recordModelRoutingMetricsModule(mockConfig, event);
@@ -541,6 +546,7 @@ describe('Telemetry Metrics', () => {
'routing.decision_source': 'Classifier',
'routing.failed': true,
'routing.reasoning': 'test-reason',
'routing.approval_mode': ApprovalMode.DEFAULT,
});
expect(mockCounterAddFn).toHaveBeenCalledTimes(2);
@@ -552,6 +558,7 @@ describe('Telemetry Metrics', () => {
'routing.decision_source': 'Classifier',
'routing.failed': true,
'routing.reasoning': 'test-reason',
'routing.approval_mode': ApprovalMode.DEFAULT,
'routing.error_message': 'test-error',
});
});
+1
View File
@@ -863,6 +863,7 @@ export function recordModelRoutingMetrics(
'routing.decision_model': event.decision_model,
'routing.decision_source': event.decision_source,
'routing.failed': event.failed,
'routing.approval_mode': event.approval_mode,
};
if (event.reasoning) {
+4
View File
@@ -1370,6 +1370,7 @@ export class ModelRoutingEvent implements BaseTelemetryEvent {
error_message?: string;
enable_numerical_routing?: boolean;
classifier_threshold?: string;
approval_mode: ApprovalMode;
constructor(
decision_model: string,
@@ -1378,6 +1379,7 @@ export class ModelRoutingEvent implements BaseTelemetryEvent {
reasoning: string | undefined,
failed: boolean,
error_message: string | undefined,
approval_mode: ApprovalMode,
enable_numerical_routing?: boolean,
classifier_threshold?: string,
) {
@@ -1389,6 +1391,7 @@ export class ModelRoutingEvent implements BaseTelemetryEvent {
this.reasoning = reasoning;
this.failed = failed;
this.error_message = error_message;
this.approval_mode = approval_mode;
this.enable_numerical_routing = enable_numerical_routing;
this.classifier_threshold = classifier_threshold;
}
@@ -1402,6 +1405,7 @@ export class ModelRoutingEvent implements BaseTelemetryEvent {
decision_source: this.decision_source,
routing_latency_ms: this.routing_latency_ms,
failed: this.failed,
approval_mode: this.approval_mode,
};
if (this.reasoning) {