mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-15 08:31:14 -07:00
continuous session
This commit is contained in:
@@ -777,6 +777,7 @@ export async function loadCliConfig(
|
||||
skillsSupport: settings.skills?.enabled ?? true,
|
||||
disabledSkills: settings.skills?.disabled,
|
||||
experimentalJitContext: settings.experimental?.jitContext,
|
||||
continuousSession: settings.experimental?.continuousSession,
|
||||
modelSteering: settings.experimental?.modelSteering,
|
||||
toolOutputMasking: settings.experimental?.toolOutputMasking,
|
||||
noBrowser: !!process.env['NO_BROWSER'],
|
||||
|
||||
@@ -1846,6 +1846,15 @@ const SETTINGS_SCHEMA = {
|
||||
'Enable model steering (user hints) to guide the model during tool execution.',
|
||||
showInDialog: true,
|
||||
},
|
||||
continuousSession: {
|
||||
type: 'boolean',
|
||||
label: 'Continuous Session',
|
||||
category: 'Experimental',
|
||||
requiresRestart: false,
|
||||
default: false,
|
||||
description: 'Enables tool and prompts for a continuous session effect.',
|
||||
showInDialog: true,
|
||||
},
|
||||
directWebFetch: {
|
||||
type: 'boolean',
|
||||
label: 'Direct Web Fetch',
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, afterEach } from 'vitest';
|
||||
import { AppRig } from '../test-utils/AppRig.js';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { PolicyDecision } from '@google/gemini-cli-core';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
describe('Continuous Session Integration', () => {
|
||||
let rig: AppRig | undefined;
|
||||
|
||||
afterEach(async () => {
|
||||
await rig?.unmount();
|
||||
});
|
||||
|
||||
it('should handle checkpoint_state and manual compress tools correctly', async () => {
|
||||
const fakeResponsesPath = path.join(
|
||||
__dirname,
|
||||
'../test-utils/fixtures/continuous_session.responses',
|
||||
);
|
||||
rig = new AppRig({
|
||||
fakeResponsesPath,
|
||||
});
|
||||
await rig.initialize();
|
||||
rig.render();
|
||||
await rig.waitForIdle();
|
||||
|
||||
// Set policies to AUTO so it proceeds without asking user
|
||||
rig.setToolPolicy('checkpoint_state', PolicyDecision.ALLOW);
|
||||
rig.setToolPolicy('compress', PolicyDecision.ALLOW);
|
||||
|
||||
// Start the quest
|
||||
await rig.type('Start the mission');
|
||||
await rig.pressEnter();
|
||||
|
||||
// 1. Wait for CheckpointState tool call
|
||||
await rig.waitForOutput('CheckpointState');
|
||||
|
||||
// 2. Wait for Compress tool call
|
||||
await rig.waitForOutput('Compress');
|
||||
|
||||
// 3. Wait for final model response after compression
|
||||
await rig.waitForOutput('Compression successful.');
|
||||
});
|
||||
});
|
||||
@@ -680,9 +680,10 @@ export class AppRig {
|
||||
await this.waitUntil(
|
||||
() => {
|
||||
const frame = this.lastFrame;
|
||||
return typeof pattern === 'string'
|
||||
const matched = typeof pattern === 'string'
|
||||
? frame.includes(pattern)
|
||||
: pattern.test(frame);
|
||||
return matched;
|
||||
},
|
||||
{
|
||||
timeout,
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"role":"model","parts":[{"text":"I will now checkpoint our progress."},{"functionCall":{"name":"checkpoint_state","args":{"summary":"GOAL: Implementation of session continuity.\nPROGRESS: Tools implemented.\nCONSTRAINT: Use high-fidelity summary."}}}]},"finishReason":"STOP"}]}]}
|
||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"role":"model","parts":[{"text":"Checkpoint created. Now I will trigger compression to clear the context."},{"functionCall":{"name":"compress","args":{"force":true}}}]},"finishReason":"STOP"}]}]}
|
||||
{"method":"generateContent","response":{"candidates":[{"content":{"role":"model","parts":[{"text":"<state_snapshot>\n<overall_goal>Implement session continuity</overall_goal>\n<active_constraints>Use high-fidelity summary</active_constraints>\n<key_knowledge>Tools implemented: checkpoint_state, compress</key_knowledge>\n<task_state>1. [DONE] Implement tools\n2. [IN PROGRESS] Verify continuity\n</task_state>\n</state_snapshot>"}]}}],"finishReason":"STOP"}}
|
||||
{"method":"generateContent","response":{"candidates":[{"content":{"role":"model","parts":[{"text":"The <state_snapshot> is accurate and preserves all critical details."}]},"finishReason":"STOP"}]}}
|
||||
{"method":"generateContentStream","response":[{"candidates":[{"content":{"role":"model","parts":[{"text":"Compression successful. I have clear context and I remember our mission."}]},"finishReason":"STOP"}]}]}
|
||||
@@ -1278,10 +1278,22 @@ export const useGeminiStream = (
|
||||
case ServerGeminiEventType.ChatCompressed:
|
||||
handleChatCompressionEvent(event.value, userMessageTimestamp);
|
||||
break;
|
||||
case ServerGeminiEventType.ToolCallConfirmation:
|
||||
case ServerGeminiEventType.ToolCallResponse:
|
||||
// do nothing
|
||||
case ServerGeminiEventType.ToolCallResponse: {
|
||||
const response = event.value;
|
||||
if (response.resultDisplay) {
|
||||
addItem(
|
||||
{
|
||||
type: MessageType.INFO,
|
||||
text: typeof response.resultDisplay === 'string'
|
||||
? response.resultDisplay
|
||||
: 'Tool execution completed.',
|
||||
},
|
||||
userMessageTimestamp,
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerGeminiEventType.ToolCallConfirmation:
|
||||
case ServerGeminiEventType.MaxSessionTurns:
|
||||
handleMaxSessionTurnsEvent();
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user