mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-07-14 20:10:36 -07:00
feat(acp): extract and stream plan events from agent thoughts
- Updated default model configurations (Gemini 3/3.1) to enforce `includeThoughts: true` and `ThinkingLevel.HIGH` and updated schema, doc and tests to reflect this. - Extended the code assist converters to safely extract and format the `thought` field, preventing type errors during `CountToken` API calls. - Implemented real-time `extractPlanEntries` parsing using regex that gracefully extracts markdown task lists (e.g., `[TODO]`, `[x]`, `[]`) while safely ignoring content inside code blocks. - Added logic in the ACP client that incrementally reads the agent's thought buffer and emits `sessionUpdate: 'plan'` events directly to the IDE whenever the tracked tasks change. - Formatted `agent_thought_chunk` outputs to replace escaped literal newlines (`\n`) with actual native newlines, ensuring the IDE chat displays main thought sections cleanly without visual artifacts. - Added comprehensive unit tests for the plan parser and ACP integration.
This commit is contained in:
@@ -221,6 +221,15 @@ describe('converter', () => {
|
||||
frequencyPenalty: 0.8,
|
||||
seed: 9,
|
||||
responseMimeType: 'application/json',
|
||||
responseSchema: undefined,
|
||||
responseJsonSchema: undefined,
|
||||
routingConfig: undefined,
|
||||
modelSelectionConfig: undefined,
|
||||
responseModalities: undefined,
|
||||
mediaResolution: undefined,
|
||||
speechConfig: undefined,
|
||||
audioTimestamp: undefined,
|
||||
thinkingConfig: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -164,6 +164,7 @@ function toVertexGenerateContentRequest(
|
||||
req: GenerateContentParameters,
|
||||
sessionId?: string,
|
||||
): VertexGenerateContentRequest {
|
||||
const generationConfig = toVertexGenerationConfig(req.config);
|
||||
return {
|
||||
contents: toContents(req.contents),
|
||||
systemInstruction: maybeToContent(req.config?.systemInstruction),
|
||||
@@ -172,7 +173,7 @@ function toVertexGenerateContentRequest(
|
||||
toolConfig: req.config?.toolConfig,
|
||||
labels: req.config?.labels,
|
||||
safetySettings: req.config?.safetySettings,
|
||||
generationConfig: toVertexGenerationConfig(req.config),
|
||||
generationConfig,
|
||||
session_id: sessionId,
|
||||
};
|
||||
}
|
||||
@@ -247,8 +248,9 @@ function toPart(part: PartUnion): Part {
|
||||
// Handle thought parts for CountToken API compatibility
|
||||
// The CountToken API expects parts to have certain required "oneof" fields initialized,
|
||||
// but thought parts don't conform to this schema and cause API failures
|
||||
if ('thought' in part && part.thought) {
|
||||
const thoughtText = `[Thought: ${part.thought}]`;
|
||||
const thoughtValue = (part as { thought?: unknown }).thought;
|
||||
if ('thought' in part && thoughtValue) {
|
||||
const thoughtText = `[Thought: ${String(thoughtValue)}]`;
|
||||
|
||||
const newPart = { ...part };
|
||||
delete (newPart as Record<string, unknown>)['thought'];
|
||||
@@ -287,6 +289,7 @@ function toVertexGenerationConfig(
|
||||
if (!config) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
temperature: config.temperature,
|
||||
topP: config.topP,
|
||||
|
||||
@@ -25,9 +25,6 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = {
|
||||
extends: 'base',
|
||||
modelConfig: {
|
||||
generateContentConfig: {
|
||||
thinkingConfig: {
|
||||
includeThoughts: true,
|
||||
},
|
||||
temperature: 1,
|
||||
topP: 0.95,
|
||||
topK: 64,
|
||||
@@ -39,6 +36,7 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = {
|
||||
modelConfig: {
|
||||
generateContentConfig: {
|
||||
thinkingConfig: {
|
||||
includeThoughts: true,
|
||||
thinkingBudget: DEFAULT_THINKING_MODE,
|
||||
},
|
||||
},
|
||||
@@ -49,6 +47,7 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = {
|
||||
modelConfig: {
|
||||
generateContentConfig: {
|
||||
thinkingConfig: {
|
||||
includeThoughts: true,
|
||||
thinkingLevel: ThinkingLevel.HIGH,
|
||||
},
|
||||
},
|
||||
@@ -59,16 +58,64 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = {
|
||||
// ensure these model configs can be used interactively.
|
||||
// TODO(joshualitt): Introduce internal base configs for the various models,
|
||||
// note: we will have to think carefully about names.
|
||||
'gemini-3.1-pro-preview': {
|
||||
extends: 'chat-base-3',
|
||||
modelConfig: {
|
||||
model: 'gemini-3.1-pro-preview',
|
||||
generateContentConfig: {
|
||||
thinkingConfig: {
|
||||
includeThoughts: true,
|
||||
thinkingLevel: ThinkingLevel.HIGH,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'gemini-3.1-pro-preview-customtools': {
|
||||
extends: 'chat-base-3',
|
||||
modelConfig: {
|
||||
model: 'gemini-3.1-pro-preview-customtools',
|
||||
generateContentConfig: {
|
||||
thinkingConfig: {
|
||||
includeThoughts: true,
|
||||
thinkingLevel: ThinkingLevel.HIGH,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'gemini-3-pro-preview': {
|
||||
extends: 'chat-base-3',
|
||||
modelConfig: {
|
||||
model: 'gemini-3-pro-preview',
|
||||
generateContentConfig: {
|
||||
thinkingConfig: {
|
||||
includeThoughts: true,
|
||||
thinkingLevel: ThinkingLevel.HIGH,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'gemini-3-flash-preview': {
|
||||
extends: 'chat-base-3',
|
||||
modelConfig: {
|
||||
model: 'gemini-3-flash-preview',
|
||||
generateContentConfig: {
|
||||
thinkingConfig: {
|
||||
includeThoughts: true,
|
||||
thinkingLevel: ThinkingLevel.HIGH,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'gemini-3.1-flash-lite-preview': {
|
||||
extends: 'chat-base-3',
|
||||
modelConfig: {
|
||||
model: 'gemini-3.1-flash-lite-preview',
|
||||
generateContentConfig: {
|
||||
thinkingConfig: {
|
||||
includeThoughts: true,
|
||||
thinkingLevel: ThinkingLevel.HIGH,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'gemini-2.5-pro': {
|
||||
@@ -100,6 +147,12 @@ export const DEFAULT_MODEL_CONFIGS: ModelConfigServiceConfig = {
|
||||
extends: 'base',
|
||||
modelConfig: {
|
||||
model: 'gemini-3-flash-preview',
|
||||
generateContentConfig: {
|
||||
thinkingConfig: {
|
||||
includeThoughts: true,
|
||||
thinkingLevel: ThinkingLevel.HIGH,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
classifier: {
|
||||
|
||||
@@ -1039,9 +1039,13 @@ export class GeminiChat {
|
||||
}
|
||||
|
||||
const thoughtPart = content.parts[0];
|
||||
if (thoughtPart.text) {
|
||||
const rawText =
|
||||
typeof thoughtPart.thought === 'string'
|
||||
? thoughtPart.thought
|
||||
: thoughtPart.text;
|
||||
|
||||
if (rawText) {
|
||||
// Extract subject and description using the same logic as turn.ts
|
||||
const rawText = thoughtPart.text;
|
||||
const subjectStringMatches = rawText.match(/\*\*(.*?)\*\*/s);
|
||||
const subject = subjectStringMatches
|
||||
? subjectStringMatches[1].trim()
|
||||
|
||||
@@ -9,9 +9,6 @@
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true
|
||||
},
|
||||
"topK": 64
|
||||
}
|
||||
},
|
||||
@@ -19,22 +16,46 @@
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingBudget": 8192
|
||||
},
|
||||
"topK": 64
|
||||
}
|
||||
}
|
||||
},
|
||||
"chat-base-3": {
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
},
|
||||
"topK": 64
|
||||
}
|
||||
}
|
||||
},
|
||||
"gemini-3.1-pro-preview": {
|
||||
"model": "gemini-3.1-pro-preview",
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gemini-3.1-pro-preview-customtools": {
|
||||
"model": "gemini-3.1-pro-preview-customtools",
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gemini-3-pro-preview": {
|
||||
@@ -42,11 +63,11 @@
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
},
|
||||
"topK": 64
|
||||
}
|
||||
}
|
||||
},
|
||||
"gemini-3-flash-preview": {
|
||||
@@ -54,11 +75,23 @@
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
},
|
||||
"topK": 64
|
||||
}
|
||||
}
|
||||
},
|
||||
"gemini-3.1-flash-lite-preview": {
|
||||
"model": "gemini-3.1-flash-lite-preview",
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gemini-2.5-pro": {
|
||||
@@ -66,11 +99,11 @@
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingBudget": 8192
|
||||
},
|
||||
"topK": 64
|
||||
}
|
||||
}
|
||||
},
|
||||
"gemini-2.5-flash": {
|
||||
@@ -78,11 +111,11 @@
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingBudget": 8192
|
||||
},
|
||||
"topK": 64
|
||||
}
|
||||
}
|
||||
},
|
||||
"gemini-2.5-flash-lite": {
|
||||
@@ -90,11 +123,11 @@
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingBudget": 8192
|
||||
},
|
||||
"topK": 64
|
||||
}
|
||||
}
|
||||
},
|
||||
"gemini-2.5-flash-base": {
|
||||
@@ -108,7 +141,11 @@
|
||||
"model": "gemini-3-flash-preview",
|
||||
"generateContentConfig": {
|
||||
"temperature": 0,
|
||||
"topP": 1
|
||||
"topP": 1,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"classifier": {
|
||||
@@ -175,6 +212,10 @@
|
||||
"generateContentConfig": {
|
||||
"temperature": 0,
|
||||
"topP": 1,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
},
|
||||
"tools": [
|
||||
{
|
||||
"googleSearch": {}
|
||||
@@ -187,6 +228,10 @@
|
||||
"generateContentConfig": {
|
||||
"temperature": 0,
|
||||
"topP": 1,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
},
|
||||
"tools": [
|
||||
{
|
||||
"urlContext": {}
|
||||
@@ -198,14 +243,22 @@
|
||||
"model": "gemini-3-flash-preview",
|
||||
"generateContentConfig": {
|
||||
"temperature": 0,
|
||||
"topP": 1
|
||||
"topP": 1,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"loop-detection": {
|
||||
"model": "gemini-3-flash-preview",
|
||||
"generateContentConfig": {
|
||||
"temperature": 0,
|
||||
"topP": 1
|
||||
"topP": 1,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"loop-detection-double-check": {
|
||||
@@ -219,14 +272,22 @@
|
||||
"model": "gemini-3-flash-preview",
|
||||
"generateContentConfig": {
|
||||
"temperature": 0,
|
||||
"topP": 1
|
||||
"topP": 1,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"next-speaker-checker": {
|
||||
"model": "gemini-3-flash-preview",
|
||||
"generateContentConfig": {
|
||||
"temperature": 0,
|
||||
"topP": 1
|
||||
"topP": 1,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"chat-compression-3-pro": {
|
||||
|
||||
@@ -9,9 +9,6 @@
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true
|
||||
},
|
||||
"topK": 64
|
||||
}
|
||||
},
|
||||
@@ -19,22 +16,46 @@
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingBudget": 8192
|
||||
},
|
||||
"topK": 64
|
||||
}
|
||||
}
|
||||
},
|
||||
"chat-base-3": {
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
},
|
||||
"topK": 64
|
||||
}
|
||||
}
|
||||
},
|
||||
"gemini-3.1-pro-preview": {
|
||||
"model": "gemini-3.1-pro-preview",
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gemini-3.1-pro-preview-customtools": {
|
||||
"model": "gemini-3.1-pro-preview-customtools",
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gemini-3-pro-preview": {
|
||||
@@ -42,11 +63,11 @@
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
},
|
||||
"topK": 64
|
||||
}
|
||||
}
|
||||
},
|
||||
"gemini-3-flash-preview": {
|
||||
@@ -54,11 +75,23 @@
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
},
|
||||
"topK": 64
|
||||
}
|
||||
}
|
||||
},
|
||||
"gemini-3.1-flash-lite-preview": {
|
||||
"model": "gemini-3.1-flash-lite-preview",
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gemini-2.5-pro": {
|
||||
@@ -66,11 +99,11 @@
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingBudget": 8192
|
||||
},
|
||||
"topK": 64
|
||||
}
|
||||
}
|
||||
},
|
||||
"gemini-2.5-flash": {
|
||||
@@ -78,11 +111,11 @@
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingBudget": 8192
|
||||
},
|
||||
"topK": 64
|
||||
}
|
||||
}
|
||||
},
|
||||
"gemini-2.5-flash-lite": {
|
||||
@@ -90,11 +123,11 @@
|
||||
"generateContentConfig": {
|
||||
"temperature": 1,
|
||||
"topP": 0.95,
|
||||
"topK": 64,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingBudget": 8192
|
||||
},
|
||||
"topK": 64
|
||||
}
|
||||
}
|
||||
},
|
||||
"gemini-2.5-flash-base": {
|
||||
@@ -108,7 +141,11 @@
|
||||
"model": "gemini-3-flash-preview",
|
||||
"generateContentConfig": {
|
||||
"temperature": 0,
|
||||
"topP": 1
|
||||
"topP": 1,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"classifier": {
|
||||
@@ -175,6 +212,10 @@
|
||||
"generateContentConfig": {
|
||||
"temperature": 0,
|
||||
"topP": 1,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
},
|
||||
"tools": [
|
||||
{
|
||||
"googleSearch": {}
|
||||
@@ -187,6 +228,10 @@
|
||||
"generateContentConfig": {
|
||||
"temperature": 0,
|
||||
"topP": 1,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
},
|
||||
"tools": [
|
||||
{
|
||||
"urlContext": {}
|
||||
@@ -198,14 +243,22 @@
|
||||
"model": "gemini-3-flash-preview",
|
||||
"generateContentConfig": {
|
||||
"temperature": 0,
|
||||
"topP": 1
|
||||
"topP": 1,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"loop-detection": {
|
||||
"model": "gemini-3-flash-preview",
|
||||
"generateContentConfig": {
|
||||
"temperature": 0,
|
||||
"topP": 1
|
||||
"topP": 1,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"loop-detection-double-check": {
|
||||
@@ -219,14 +272,22 @@
|
||||
"model": "gemini-3-flash-preview",
|
||||
"generateContentConfig": {
|
||||
"temperature": 0,
|
||||
"topP": 1
|
||||
"topP": 1,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"next-speaker-checker": {
|
||||
"model": "gemini-3-flash-preview",
|
||||
"generateContentConfig": {
|
||||
"temperature": 0,
|
||||
"topP": 1
|
||||
"topP": 1,
|
||||
"thinkingConfig": {
|
||||
"includeThoughts": true,
|
||||
"thinkingLevel": "HIGH"
|
||||
}
|
||||
}
|
||||
},
|
||||
"chat-compression-3-pro": {
|
||||
|
||||
Reference in New Issue
Block a user