feat(vscode-ide-companion): support context left

This commit is contained in:
yiliang114 2025-12-24 01:09:21 +08:00
parent 642dda0315
commit 8e64c5acaf
16 changed files with 507 additions and 6 deletions

View file

@ -19,6 +19,7 @@ import {
type Config,
type ConversationRecord,
type DeviceAuthorizationData,
tokenLimit,
} from '@qwen-code/qwen-code-core';
import type { ApprovalModeValue } from './schema.js';
import * as acp from './acp.js';
@ -100,6 +101,14 @@ class GeminiAgent {
}));
const version = process.env['CLI_VERSION'] || process.version;
const modelName = this.config.getModel();
const modelInfo =
modelName && modelName.length > 0
? {
name: modelName,
contextLimit: tokenLimit(modelName),
}
: undefined;
return {
protocolVersion: acp.PROTOCOL_VERSION,
@ -113,6 +122,7 @@ class GeminiAgent {
currentModeId: currentApprovalMode as ApprovalModeValue,
availableModes,
},
modelInfo,
agentCapabilities: {
loadSession: true,
promptCapabilities: {
@ -347,6 +357,8 @@ class GeminiAgent {
await session.sendAvailableCommandsUpdate();
}, 0);
await session.announceCurrentModel(true);
if (conversation && conversation.messages) {
await session.replayHistory(conversation.messages);
}

View file

@ -93,6 +93,7 @@ export type ModeInfo = z.infer<typeof modeInfoSchema>;
export type ModesData = z.infer<typeof modesDataSchema>;
export type AgentInfo = z.infer<typeof agentInfoSchema>;
export type ModelInfo = z.infer<typeof modelInfoSchema>;
export type PromptCapabilities = z.infer<typeof promptCapabilitiesSchema>;
@ -417,11 +418,17 @@ export const agentInfoSchema = z.object({
version: z.string(),
});
export const modelInfoSchema = z.object({
name: z.string(),
contextLimit: z.number().optional().nullable(),
});
export const initializeResponseSchema = z.object({
agentCapabilities: agentCapabilitiesSchema,
agentInfo: agentInfoSchema,
authMethods: z.array(authMethodSchema),
modes: modesDataSchema,
modelInfo: modelInfoSchema.optional(),
protocolVersion: z.number(),
});
@ -514,6 +521,13 @@ export const currentModeUpdateSchema = z.object({
export type CurrentModeUpdate = z.infer<typeof currentModeUpdateSchema>;
export const currentModelUpdateSchema = z.object({
sessionUpdate: z.literal('current_model_update'),
model: modelInfoSchema,
});
export type CurrentModelUpdate = z.infer<typeof currentModelUpdateSchema>;
export const sessionUpdateSchema = z.union([
z.object({
content: contentBlockSchema,
@ -555,6 +569,7 @@ export const sessionUpdateSchema = z.union([
sessionUpdate: z.literal('plan'),
}),
currentModeUpdateSchema,
currentModelUpdateSchema,
availableCommandsUpdateSchema,
]);

View file

@ -33,6 +33,7 @@ import {
UserPromptEvent,
TodoWriteTool,
ExitPlanModeTool,
tokenLimit,
} from '@qwen-code/qwen-code-core';
import * as acp from '../acp.js';
@ -52,6 +53,7 @@ import type {
SetModeResponse,
ApprovalModeValue,
CurrentModeUpdate,
CurrentModelUpdate,
} from '../schema.js';
import { isSlashCommand } from '../../ui/utils/commandUtils.js';
@ -86,6 +88,10 @@ export class Session implements SessionContext {
private readonly toolCallEmitter: ToolCallEmitter;
private readonly planEmitter: PlanEmitter;
private readonly messageEmitter: MessageEmitter;
private lastAnnouncedModel: {
name: string;
contextLimit?: number | null;
} | null = null;
// Implement SessionContext interface
readonly sessionId: string;
@ -191,6 +197,8 @@ export class Session implements SessionContext {
parts = await this.#resolvePrompt(params.prompt, pendingSend.signal);
}
await this.sendCurrentModelUpdate();
let nextMessage: Content | null = { role: 'user', parts };
while (nextMessage !== null) {
@ -379,6 +387,40 @@ export class Session implements SessionContext {
await this.sendUpdate(update);
}
async announceCurrentModel(force: boolean = false): Promise<void> {
await this.sendCurrentModelUpdate(force);
}
private async sendCurrentModelUpdate(force: boolean = false): Promise<void> {
const modelName = this.config.getModel();
if (!modelName) {
return;
}
const contextLimit = tokenLimit(modelName);
if (
!force &&
this.lastAnnouncedModel &&
this.lastAnnouncedModel.name === modelName &&
this.lastAnnouncedModel.contextLimit === contextLimit
) {
return;
}
this.lastAnnouncedModel = { name: modelName, contextLimit };
const update: CurrentModelUpdate = {
sessionUpdate: 'current_model_update',
model: {
name: modelName,
contextLimit,
},
};
await this.sendUpdate(update);
}
private async runTool(
abortSignal: AbortSignal,
promptId: string,